Files
video-shader-toys/tests/RenderCadenceCompositorRuntimeStateJsonTests.cpp
Aiden 56883439a6
All checks were successful
CI / React UI Build (push) Successful in 12s
CI / Native Windows Build And Tests (push) Successful in 2m14s
CI / Windows Release Package (push) Has been skipped
clean split
2026-05-30 21:22:03 +10:00

155 lines
6.7 KiB
C++

#include "RuntimeStateJson.h"
#include <chrono>
#include <filesystem>
#include <fstream>
#include <iostream>
#include <string>
namespace
{
int gFailures = 0;
void ExpectContains(const std::string& text, const std::string& fragment, const std::string& message)
{
if (text.find(fragment) != std::string::npos)
return;
++gFailures;
std::cerr << "FAIL: " << message << "\n";
}
std::filesystem::path MakeTestRoot()
{
const auto stamp = std::chrono::steady_clock::now().time_since_epoch().count();
const std::filesystem::path root = std::filesystem::temp_directory_path() / ("render-cadence-state-json-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;
}
}
int main()
{
RenderCadenceCompositor::AppConfig config = RenderCadenceCompositor::DefaultAppConfig();
config.output.resolution = "1080p";
config.output.frameRate = "59.94";
RenderCadenceCompositor::CadenceTelemetrySnapshot telemetry;
telemetry.renderFps = 59.94;
telemetry.renderFrameMilliseconds = 2.5;
telemetry.renderFrameBudgetUsedPercent = 15.0;
telemetry.renderFrameMaxMilliseconds = 4.0;
telemetry.readbackQueueMilliseconds = 0.6;
telemetry.completedReadbackCopyMilliseconds = 1.2;
telemetry.completedDrops = 3;
telemetry.acquireMisses = 4;
telemetry.scheduleFailures = 2;
telemetry.completions = 12;
telemetry.displayedLate = 1;
telemetry.shaderBuildsCommitted = 1;
telemetry.deckLinkBufferedAvailable = true;
telemetry.deckLinkBuffered = 4;
telemetry.deckLinkScheduleCallMilliseconds = 1.25;
telemetry.deckLinkScheduleLeadAvailable = true;
telemetry.deckLinkScheduleLeadFrames = 4;
telemetry.deckLinkPlaybackFrameIndex = 10;
telemetry.deckLinkNextScheduleFrameIndex = 14;
telemetry.deckLinkPlaybackStreamTime = 10010;
telemetry.deckLinkScheduleRealignments = 1;
const std::filesystem::path root = MakeTestRoot();
WriteFile(root / "solid-color" / "shader.slang", "float4 shadeVideo(float2 uv) { return float4(uv, 0.0, 1.0); }\n");
WriteFile(root / "solid-color" / "shader.json", R"({
"id": "solid-color",
"name": "Solid Color",
"description": "A single color shader.",
"category": "Generator",
"entryPoint": "shadeVideo",
"parameters": [
{
"id": "color",
"label": "Color",
"description": "Output color.",
"type": "color",
"default": [1.0, 0.25, 0.5, 1.0],
"min": [0.0, 0.0, 0.0, 0.0],
"max": [1.0, 1.0, 1.0, 1.0],
"step": [0.01, 0.01, 0.01, 0.01]
}
]
})");
RenderCadenceCompositor::SupportedShaderCatalog shaderCatalog;
std::string error;
ExpectContains(shaderCatalog.Load(root, 4, error) ? "loaded" : error, "loaded", "test shader catalog should load");
RenderCadenceCompositor::RuntimeLayerModel layerModel;
layerModel.InitializeSingleLayer(shaderCatalog, "solid-color", error);
RuntimeShaderArtifact artifact;
artifact.shaderId = "solid-color";
artifact.displayName = "Solid Color";
artifact.fragmentShaderSource = "void main(){}";
artifact.message = "Runtime shader committed.";
layerModel.MarkBuildReady(artifact, error);
const RenderCadenceCompositor::RuntimeLayerModelSnapshot layerSnapshot = layerModel.Snapshot();
RenderCadenceCompositor::RuntimeStateJsonInput stateInput{
config,
telemetry,
8080,
true,
"DeckLink scheduled output running.",
nullptr
};
stateInput.writeRuntimeJson = [&layerSnapshot](RenderCadenceCompositor::JsonWriter& writer) {
RenderCadenceCompositor::WriteShaderRuntimeJson(writer, layerSnapshot);
};
stateInput.writeCatalogJson = [&shaderCatalog](RenderCadenceCompositor::JsonWriter& writer) {
RenderCadenceCompositor::WriteShaderCatalogJson(writer, shaderCatalog);
};
stateInput.writeLayersJson = [&shaderCatalog, &layerSnapshot](RenderCadenceCompositor::JsonWriter& writer) {
RenderCadenceCompositor::WriteRuntimeShaderLayersJson(writer, shaderCatalog, layerSnapshot);
};
const std::string json = RenderCadenceCompositor::RuntimeStateToJson(stateInput);
ExpectContains(json, "\"shaders\":[{\"id\":\"solid-color\"", "state JSON should include supported shaders");
ExpectContains(json, "\"layerCount\":1", "state JSON should expose the display layer count");
ExpectContains(json, "\"layers\":[{\"id\":\"runtime-layer-1\"", "state JSON should expose the active display layer");
ExpectContains(json, "\"parameters\":[{\"id\":\"color\"", "state JSON should expose active shader parameters");
ExpectContains(json, "\"type\":\"color\"", "state JSON should serialize parameter types for the UI");
ExpectContains(json, "\"width\":1920", "state JSON should expose output width");
ExpectContains(json, "\"height\":1080", "state JSON should expose output height");
ExpectContains(json, "\"input\":{\"backend\":\"decklink\",\"device\":\"default\",\"resolution\":\"1080p\",\"frameRate\":\"59.94\"}", "state JSON should expose nested input config");
ExpectContains(json, "\"output\":{\"backend\":\"decklink\",\"device\":\"default\",\"resolution\":\"1080p\",\"frameRate\":\"59.94\",\"pixelFormat\":\"auto\",\"systemFramePixelFormat\":\"8-bit BGRA\",\"keying\"", "state JSON should expose nested output config");
ExpectContains(json, "\"osc\":{\"configured\":true,\"listening\":false", "state JSON should expose OSC stub status");
ExpectContains(json, "\"videoOutput\":{\"enabled\":true,\"backend\":\"decklink\"", "state JSON should expose neutral video output status");
ExpectContains(json, "\"scheduleFailures\":2", "state JSON should expose neutral video output schedule failures");
ExpectContains(json, "\"backendMetrics\":{\"bufferedAvailable\":true,\"buffered\":4", "state JSON should expose backend-specific video output metrics");
ExpectContains(json, "\"scheduleLeadFrames\":4", "state JSON should expose backend-specific schedule lead");
ExpectContains(json, "\"renderMs\":2.5", "state JSON should expose top-level render timing");
ExpectContains(json, "\"budgetUsedPercent\":15", "state JSON should expose top-level render budget percentage");
ExpectContains(json, "\"renderFrameMs\":2.5", "state JSON should expose cadence render timing");
ExpectContains(json, "\"readbackQueueMs\":0.6", "state JSON should expose readback queue timing");
ExpectContains(json, "\"completedReadbackCopyMs\":1.2", "state JSON should expose completed readback copy timing");
ExpectContains(json, "\"completedDrops\":3", "state JSON should expose completed drop count");
ExpectContains(json, "\"acquireMisses\":4", "state JSON should expose acquire miss count");
std::filesystem::remove_all(root);
if (gFailures != 0)
{
std::cerr << gFailures << " RenderCadenceCompositorRuntimeStateJson test failure(s).\n";
return 1;
}
std::cout << "RenderCadenceCompositorRuntimeStateJson tests passed.\n";
return 0;
}