#include "ShaderPackageRegistry.h" #include #include #include #include #include #include #include namespace { int gFailures = 0; void Expect(bool condition, const char* message) { if (condition) return; std::cerr << "FAIL: " << message << "\n"; ++gFailures; } std::filesystem::path MakeTestRoot() { const auto stamp = std::chrono::steady_clock::now().time_since_epoch().count(); std::filesystem::path root = std::filesystem::temp_directory_path() / ("video-shader-registry-tests-" + std::to_string(stamp)); std::filesystem::create_directories(root); return root; } void WriteFile(const std::filesystem::path& path, const std::string& contents) { std::filesystem::create_directories(path.parent_path()); std::ofstream output(path, std::ios::binary); output << contents; } void WriteShaderPackage(const std::filesystem::path& root, const std::string& directoryName, const std::string& manifest) { const std::filesystem::path packageRoot = root / directoryName; WriteFile(packageRoot / "shader.json", manifest); WriteFile(packageRoot / "shader.slang", "float4 shadeVideo(float2 uv) { return float4(uv, 0.0, 1.0); }\n"); } void TestValidManifest() { const std::filesystem::path root = MakeTestRoot(); WriteFile(root / "look" / "mask.png", "not a real png, but enough for existence checks"); WriteShaderPackage(root, "look", R"({ "id": "look-01", "name": "Look 01", "description": "Test package", "category": "Tests", "entryPoint": "shadeVideo", "textures": [{ "id": "maskTex", "path": "mask.png" }], "temporal": { "enabled": true, "historySource": "source", "historyLength": 8 }, "parameters": [ { "id": "gain", "label": "Gain", "type": "float", "default": 0.5, "min": 0, "max": 1 }, { "id": "mode", "label": "Mode", "type": "enum", "default": "soft", "options": [ { "value": "soft", "label": "Soft" }, { "value": "hard", "label": "Hard" } ] } ] })"); ShaderPackageRegistry registry(4); ShaderPackage package; std::string error; Expect(registry.ParseManifest(root / "look" / "shader.json", package, error), "valid manifest parses"); Expect(package.id == "look-01", "manifest id is preserved"); Expect(package.textureAssets.size() == 1 && package.textureAssets[0].id == "maskTex", "texture assets parse"); Expect(package.temporal.enabled && package.temporal.effectiveHistoryLength == 4, "temporal history is capped"); Expect(package.parameters.size() == 2, "parameters parse"); std::filesystem::remove_all(root); } void TestInvalidManifest() { const std::filesystem::path root = MakeTestRoot(); WriteShaderPackage(root, "bad", R"({ "id": "bad", "name": "Bad", "entryPoint": "not-valid!", "parameters": [] })"); ShaderPackageRegistry registry(4); ShaderPackage package; std::string error; Expect(!registry.ParseManifest(root / "bad" / "shader.json", package, error), "invalid shader identifier is rejected"); Expect(error.find("entryPoint") != std::string::npos, "invalid manifest error names the bad field"); std::filesystem::remove_all(root); } void TestDuplicateScan() { const std::filesystem::path root = MakeTestRoot(); WriteShaderPackage(root, "a", R"({ "id": "dupe", "name": "A", "parameters": [] })"); WriteShaderPackage(root, "b", R"({ "id": "dupe", "name": "B", "parameters": [] })"); ShaderPackageRegistry registry(4); std::map packages; std::vector order; std::string error; Expect(!registry.Scan(root, packages, order, error), "duplicate package ids are rejected"); Expect(error.find("Duplicate shader id") != std::string::npos, "duplicate scan error is clear"); std::filesystem::remove_all(root); } } int main() { TestValidManifest(); TestInvalidManifest(); TestDuplicateScan(); if (gFailures != 0) { std::cerr << gFailures << " ShaderPackageRegistry test failure(s).\n"; return 1; } std::cout << "ShaderPackageRegistry tests passed.\n"; return 0; }