Files
Toolbox/tests/toolRegistrySettingsTests.cpp
Yadciel c611b008af Fügt CLI-Toolverwaltung und erweiterte UI-Funktionen hinzu
Ermöglicht die Verwaltung (Erstellen, Auflisten, Ausführen) von Tools über eine Befehlszeilenschnittstelle für Automatisierung und Integration. Die Benutzeroberfläche wurde mit dedizierten Ansichten für Toolerstellung und -bearbeitung, In-App-Lua-Hilfe sowie kontextsensitiven Menüs erweitert. Neue Abhängigkeiten (CLI11, rang) wurden integriert und eine umfassende Testsuite hinzugefügt. Die Lizenzierung wurde auf AGPL-3.0 umgestellt und ein Kontributionsleitfaden bereitgestellt.
2026-07-17 17:22:15 +02:00

155 lines
6.9 KiB
C++

#include "toolRegistry.h"
#include <cassert>
#include <chrono>
#include <filesystem>
#include <fstream>
#include <string>
namespace {
std::string readText(const std::filesystem::path& path) {
std::ifstream input(path, std::ios::binary);
return {std::istreambuf_iterator<char>(input), std::istreambuf_iterator<char>()};
}
} // namespace
int main() {
const auto suffix = std::to_string(std::chrono::steady_clock::now().time_since_epoch().count());
const std::filesystem::path home = std::filesystem::temp_directory_path() /
("toolbox-settings-contract-" + suffix);
std::filesystem::create_directories(home);
ToolDraft created{
.name = "Acme",
.description = "Startet Acme.",
.luaScript = "error('must be replaced')",
.iconBase64 = {},
.timeoutSeconds = 30,
.templateType = "program",
.templateTarget = R"(C:\Program Files\Acme\Acme.exe)",
};
const auto creation = ToolRegistry::createTool(home, created);
assert(creation.success);
const auto oldPath = ToolRegistry::toolboxDirectory(home) / "Acme";
const auto toolboxRoot = ToolRegistry::toolboxDirectory(home);
const auto preparedStage = toolboxRoot / ".toolbox-update-101";
const auto preparedJournal = toolboxRoot / ".toolbox-transaction-101.json";
std::filesystem::copy(oldPath, preparedStage, std::filesystem::copy_options::recursive);
std::ofstream(preparedJournal) <<
R"({"version":1,"id":"101","originalName":"Acme","targetName":"Acme Website"})";
ToolRegistry::loadTools(home);
assert(std::filesystem::exists(oldPath));
assert(!std::filesystem::exists(preparedStage));
assert(!std::filesystem::exists(preparedJournal));
const auto movedStage = toolboxRoot / ".toolbox-update-102";
const auto movedBackup = toolboxRoot / ".toolbox-backup-102";
const auto movedJournal = toolboxRoot / ".toolbox-transaction-102.json";
std::filesystem::copy(oldPath, movedStage, std::filesystem::copy_options::recursive);
std::ofstream(movedJournal) <<
R"({"version":1,"id":"102","originalName":"Acme","targetName":"Acme Website"})";
std::filesystem::rename(oldPath, movedBackup);
ToolRegistry::loadTools(home);
assert(std::filesystem::exists(oldPath));
assert(!std::filesystem::exists(movedStage));
assert(!std::filesystem::exists(movedBackup));
assert(!std::filesystem::exists(movedJournal));
const auto mismatchedBackup = toolboxRoot / ".toolbox-backup-104";
const auto mismatchedJournal = toolboxRoot / ".toolbox-transaction-wrong.json";
std::filesystem::copy(oldPath, mismatchedBackup, std::filesystem::copy_options::recursive);
std::ofstream(mismatchedJournal) <<
R"({"version":1,"id":"104","originalName":"Acme","targetName":"Acme Website"})";
ToolRegistry::loadTools(home);
assert(std::filesystem::exists(mismatchedBackup));
assert(std::filesystem::exists(mismatchedJournal));
const auto outsideTool = home / "outside-tool";
std::filesystem::create_directory(outsideTool);
std::ofstream(outsideTool / "start.lua") << "print('outside')";
assert(!ToolRegistry::getToolDetails(home, outsideTool).success);
const auto orphanPath = ToolRegistry::toolboxDirectory(home) / ".toolbox-update-orphan";
std::filesystem::create_directory(orphanPath);
std::ofstream(orphanPath / "start.lua") << "print('orphan')";
const auto visibleTools = ToolRegistry::loadTools(home);
assert(visibleTools.size() == 1);
assert(visibleTools.front().name == "Acme");
std::ofstream(oldPath / "asset.txt") << "preserve me";
const auto loaded = ToolRegistry::getToolDetails(home, oldPath);
assert(loaded.success);
assert(loaded.details.name == "Acme");
assert(loaded.details.description == "Startet Acme.");
assert(loaded.details.timeoutSeconds == 30);
assert(loaded.details.templateType == "program");
assert(loaded.details.templateTarget == R"(C:\Program Files\Acme\Acme.exe)");
assert(loaded.details.luaScript.find("start") != std::string::npos);
assert(loaded.details.luaScript.find("must be replaced") == std::string::npos);
ToolUpdateDraft update{
.name = "Acme Website",
.description = "Öffnet die Acme-Website.",
.luaScript = "error('must also be replaced')",
.timeoutSeconds = 45,
.templateType = "website",
.templateTarget = "https://www.example.com/docs",
};
const auto updated = ToolRegistry::updateTool(home, oldPath, update);
assert(updated.success);
const auto newPath = ToolRegistry::toolboxDirectory(home) / "Acme Website";
assert(updated.toolPath == newPath);
assert(!std::filesystem::exists(oldPath));
assert(readText(newPath / "asset.txt") == "preserve me");
const auto committedBackup = toolboxRoot / ".toolbox-backup-103";
const auto committedJournal = toolboxRoot / ".toolbox-transaction-103.json";
std::filesystem::copy(newPath, committedBackup, std::filesystem::copy_options::recursive);
std::ofstream(committedJournal) <<
R"({"version":1,"id":"103","originalName":"Acme","targetName":"Acme Website"})";
ToolRegistry::loadTools(home);
assert(std::filesystem::exists(newPath));
assert(!std::filesystem::exists(committedBackup));
assert(!std::filesystem::exists(committedJournal));
const auto reloaded = ToolRegistry::getToolDetails(home, newPath);
assert(reloaded.success);
assert(reloaded.details.name == "Acme Website");
assert(reloaded.details.description == "Öffnet die Acme-Website.");
assert(reloaded.details.timeoutSeconds == 45);
assert(reloaded.details.templateType == "website");
assert(reloaded.details.templateTarget == "https://www.example.com/docs");
assert(reloaded.details.luaScript.find("https://www.example.com/docs") != std::string::npos);
assert(reloaded.details.luaScript.find("must also be replaced") == std::string::npos);
std::ofstream(newPath / "tool.json") << R"({"version":1,"type":"bogus","target":"ignored"})";
const auto invalidMetadata = ToolRegistry::getToolDetails(home, newPath);
assert(invalidMetadata.success);
assert(invalidMetadata.details.templateType == "lua");
assert(invalidMetadata.details.templateTarget.empty());
std::filesystem::remove(newPath / "tool.json");
const auto legacy = ToolRegistry::getToolDetails(home, newPath);
assert(legacy.success);
assert(legacy.details.templateType == "lua");
assert(legacy.details.templateTarget.empty());
const auto invalid = ToolRegistry::updateTool(home, newPath, ToolUpdateDraft{
.name = "../escape",
.description = "invalid",
.luaScript = "print('invalid')",
.timeoutSeconds = 30,
.templateType = "lua",
});
assert(!invalid.success);
assert(std::filesystem::exists(newPath));
assert(readText(newPath / "description.txt") == "Öffnet die Acme-Website.");
std::filesystem::remove_all(home);
return 0;
}