GROUND WORK PHASE 3
This commit is contained in:
143
tests/RuntimeLiveStateTests.cpp
Normal file
143
tests/RuntimeLiveStateTests.cpp
Normal file
@@ -0,0 +1,143 @@
|
||||
#include "RenderStateComposer.h"
|
||||
#include "RuntimeLiveState.h"
|
||||
|
||||
#include <chrono>
|
||||
#include <cmath>
|
||||
#include <iostream>
|
||||
|
||||
namespace
|
||||
{
|
||||
int gFailures = 0;
|
||||
|
||||
void Expect(bool condition, const char* message)
|
||||
{
|
||||
if (condition)
|
||||
return;
|
||||
|
||||
std::cerr << "FAIL: " << message << "\n";
|
||||
++gFailures;
|
||||
}
|
||||
|
||||
ShaderParameterDefinition FloatDefinition(const std::string& id, const std::string& label)
|
||||
{
|
||||
ShaderParameterDefinition definition;
|
||||
definition.id = id;
|
||||
definition.label = label;
|
||||
definition.type = ShaderParameterType::Float;
|
||||
definition.defaultNumbers = { 0.0 };
|
||||
definition.minNumbers = { 0.0 };
|
||||
definition.maxNumbers = { 1.0 };
|
||||
return definition;
|
||||
}
|
||||
|
||||
RuntimeRenderState MakeLayerState()
|
||||
{
|
||||
RuntimeRenderState state;
|
||||
state.layerId = "layer-one";
|
||||
state.shaderId = "test-shader";
|
||||
state.shaderName = "Test Shader";
|
||||
state.parameterDefinitions.push_back(FloatDefinition("amount", "Amount"));
|
||||
ShaderParameterValue amount;
|
||||
amount.numberValues = { 0.25 };
|
||||
state.parameterValues["amount"] = amount;
|
||||
return state;
|
||||
}
|
||||
|
||||
void TestRuntimeLiveStateAppliesLatestOscOverlay()
|
||||
{
|
||||
RuntimeLiveState liveState;
|
||||
|
||||
RuntimeLiveOscUpdate first;
|
||||
first.routeKey = "layer-one\namount";
|
||||
first.layerKey = "layer-one";
|
||||
first.parameterKey = "amount";
|
||||
first.targetValue = JsonValue(0.5);
|
||||
|
||||
RuntimeLiveOscUpdate second = first;
|
||||
second.targetValue = JsonValue(0.75);
|
||||
|
||||
liveState.ApplyOscUpdates({ first, second });
|
||||
Expect(liveState.OverlayCount() == 1, "live state keeps one overlay per route");
|
||||
|
||||
std::vector<RuntimeRenderState> states = { MakeLayerState() };
|
||||
RuntimeLiveStateApplyOptions options;
|
||||
options.allowCommit = false;
|
||||
options.smoothing = 0.0;
|
||||
liveState.ApplyToLayerStates(states, options, nullptr);
|
||||
|
||||
const auto valueIt = states[0].parameterValues.find("amount");
|
||||
Expect(valueIt != states[0].parameterValues.end(), "overlay writes the target parameter");
|
||||
Expect(!valueIt->second.numberValues.empty() && std::fabs(valueIt->second.numberValues[0] - 0.75) < 0.0001,
|
||||
"overlay applies the latest target value");
|
||||
}
|
||||
|
||||
void TestRuntimeLiveStateQueuesAndCompletesCommit()
|
||||
{
|
||||
RuntimeLiveState liveState;
|
||||
|
||||
RuntimeLiveOscUpdate update;
|
||||
update.routeKey = "layer-one\namount";
|
||||
update.layerKey = "layer-one";
|
||||
update.parameterKey = "amount";
|
||||
update.targetValue = JsonValue(0.9);
|
||||
liveState.ApplyOscUpdates({ update });
|
||||
|
||||
std::vector<RuntimeRenderState> states = { MakeLayerState() };
|
||||
std::vector<RuntimeLiveOscCommitRequest> commitRequests;
|
||||
RuntimeLiveStateApplyOptions options;
|
||||
options.allowCommit = true;
|
||||
options.smoothing = 0.0;
|
||||
options.commitDelay = std::chrono::milliseconds(0);
|
||||
options.now = std::chrono::steady_clock::now() + std::chrono::milliseconds(1);
|
||||
liveState.ApplyToLayerStates(states, options, &commitRequests);
|
||||
|
||||
Expect(commitRequests.size() == 1, "live state queues a commit request once the overlay can settle");
|
||||
Expect(commitRequests[0].routeKey == "layer-one\namount", "commit request preserves route");
|
||||
Expect(commitRequests[0].generation == 1, "commit request carries overlay generation");
|
||||
|
||||
liveState.ApplyOscCommitCompletions({ { commitRequests[0].routeKey, commitRequests[0].generation } });
|
||||
Expect(liveState.OverlayCount() == 0, "matching commit completion removes settled overlay");
|
||||
}
|
||||
|
||||
void TestRenderStateComposerBuildsFrameState()
|
||||
{
|
||||
RuntimeLiveState liveState;
|
||||
RuntimeLiveOscUpdate update;
|
||||
update.routeKey = "layer-one\namount";
|
||||
update.layerKey = "Test Shader";
|
||||
update.parameterKey = "Amount";
|
||||
update.targetValue = JsonValue(0.6);
|
||||
liveState.ApplyOscUpdates({ update });
|
||||
|
||||
RenderStateCompositionInput input;
|
||||
input.baseLayerStates = { MakeLayerState() };
|
||||
input.liveState = &liveState;
|
||||
input.liveStateOptions.allowCommit = false;
|
||||
input.liveStateOptions.smoothing = 0.0;
|
||||
|
||||
RenderStateComposer composer;
|
||||
RenderStateCompositionResult result = composer.BuildFrameState(input);
|
||||
|
||||
Expect(result.layerStates.size() == 1, "composer returns composed layer state");
|
||||
const auto valueIt = result.layerStates[0].parameterValues.find("amount");
|
||||
Expect(valueIt != result.layerStates[0].parameterValues.end(), "composer applies live overlay through live state");
|
||||
Expect(!valueIt->second.numberValues.empty() && std::fabs(valueIt->second.numberValues[0] - 0.6) < 0.0001,
|
||||
"composer uses OSC key matching against shader names and labels");
|
||||
}
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
TestRuntimeLiveStateAppliesLatestOscOverlay();
|
||||
TestRuntimeLiveStateQueuesAndCompletesCommit();
|
||||
TestRenderStateComposerBuildsFrameState();
|
||||
|
||||
if (gFailures != 0)
|
||||
{
|
||||
std::cerr << gFailures << " RuntimeLiveState test failure(s).\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
std::cout << "RuntimeLiveState tests passed.\n";
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user