#include "RuntimeEvent.h" #include "RuntimeEventCoalescingQueue.h" #include "RuntimeEventDispatcher.h" #include "RuntimeEventQueue.h" #include "RuntimeEventType.h" #include "RuntimeEventPayloads.h" #include "RuntimeEventTestHarness.h" #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; } void TestRuntimeEventTypeNames() { Expect(RuntimeEventTypeName(RuntimeEventType::Unknown) == "Unknown", "unknown event type has a stable name"); Expect(RuntimeEventTypeName(RuntimeEventType::OscCommitRequested) == "OscCommitRequested", "control event name is stable"); Expect(RuntimeEventTypeName(RuntimeEventType::RuntimeMutationAccepted) == "RuntimeMutationAccepted", "runtime event name is stable"); Expect(RuntimeEventTypeName(RuntimeEventType::ShaderBuildPrepared) == "ShaderBuildPrepared", "shader build event name is stable"); Expect(RuntimeEventTypeName(RuntimeEventType::RenderSnapshotPublished) == "RenderSnapshotPublished", "render event name is stable"); Expect(RuntimeEventTypeName(RuntimeEventType::BackendStateChanged) == "BackendStateChanged", "backend event name is stable"); Expect(RuntimeEventTypeName(RuntimeEventType::QueueDepthChanged) == "QueueDepthChanged", "telemetry event name is stable"); } void TestRuntimeEventPayloadTypes() { OscCommitRequestedEvent oscCommit; oscCommit.routeKey = "layer-1\namount"; oscCommit.layerKey = "layer-1"; oscCommit.parameterKey = "amount"; oscCommit.generation = 42; Expect(RuntimeEventPayloadType(oscCommit) == RuntimeEventType::OscCommitRequested, "OSC commit payload maps to OSC commit event type"); Expect(oscCommit.generation == 42, "OSC commit payload keeps generation"); RuntimeMutationEvent acceptedMutation; acceptedMutation.action = "SetLayerShader"; acceptedMutation.accepted = true; acceptedMutation.shaderBuildRequested = true; acceptedMutation.persistenceRequested = true; Expect(RuntimeEventPayloadType(acceptedMutation) == RuntimeEventType::RuntimeMutationAccepted, "accepted mutation payload maps to accepted event type"); Expect(acceptedMutation.shaderBuildRequested, "mutation payload carries shader build follow-up"); Expect(acceptedMutation.persistenceRequested, "mutation payload carries persistence follow-up"); RuntimeMutationEvent rejectedMutation; rejectedMutation.accepted = false; rejectedMutation.errorMessage = "Unknown layer."; Expect(RuntimeEventPayloadType(rejectedMutation) == RuntimeEventType::RuntimeMutationRejected, "rejected mutation payload maps to rejected event type"); Expect(rejectedMutation.errorMessage == "Unknown layer.", "mutation payload carries rejection error"); RuntimePersistenceRequestedEvent persistence; persistence.reason = "UpdateLayerParameter"; persistence.debounceAllowed = true; Expect(RuntimeEventPayloadType(persistence) == RuntimeEventType::RuntimePersistenceRequested, "runtime persistence payload maps to persistence event type"); Expect(persistence.debounceAllowed, "runtime persistence payload carries debounce policy"); ShaderBuildEvent preparedBuild; preparedBuild.phase = RuntimeEventShaderBuildPhase::Prepared; preparedBuild.inputWidth = 1920; preparedBuild.inputHeight = 1080; Expect(RuntimeEventPayloadType(preparedBuild) == RuntimeEventType::ShaderBuildPrepared, "shader build payload maps by phase"); Expect(preparedBuild.inputWidth == 1920 && preparedBuild.inputHeight == 1080, "shader build payload carries input dimensions"); RenderResetEvent appliedReset; appliedReset.scope = RuntimeEventRenderResetScope::TemporalHistoryAndFeedback; appliedReset.applied = true; Expect(RuntimeEventPayloadType(appliedReset) == RuntimeEventType::RenderResetApplied, "render reset payload maps applied state"); Expect(appliedReset.scope == RuntimeEventRenderResetScope::TemporalHistoryAndFeedback, "render reset payload carries reset scope"); RenderSnapshotPublishRequestedEvent snapshotRequest; snapshotRequest.outputWidth = 1920; snapshotRequest.outputHeight = 1080; snapshotRequest.reason = "test"; Expect(RuntimeEventPayloadType(snapshotRequest) == RuntimeEventType::RenderSnapshotPublishRequested, "render snapshot request payload maps to request event"); RenderSnapshotPublishedEvent snapshotPublished; snapshotPublished.snapshotVersion = 3; snapshotPublished.parameterVersion = 4; snapshotPublished.layerCount = 2; Expect(RuntimeEventPayloadType(snapshotPublished) == RuntimeEventType::RenderSnapshotPublished, "render snapshot published payload maps to published event"); Expect(snapshotPublished.layerCount == 2, "render snapshot published payload carries layer count"); OutputFrameCompletedEvent completedFrame; completedFrame.result = "Completed"; Expect(RuntimeEventPayloadType(completedFrame) == RuntimeEventType::OutputFrameCompleted, "completed output frame payload maps to completed event"); completedFrame.result = "DisplayedLate"; Expect(RuntimeEventPayloadType(completedFrame) == RuntimeEventType::OutputLateFrameDetected, "late output frame payload maps to late event"); completedFrame.result = "Dropped"; Expect(RuntimeEventPayloadType(completedFrame) == RuntimeEventType::OutputDroppedFrameDetected, "dropped output frame payload maps to dropped event"); TimingSampleRecordedEvent timingSample; timingSample.subsystem = "RuntimeEventDispatcher"; timingSample.metric = "dispatchDuration"; timingSample.value = 0.5; timingSample.unit = "ms"; Expect(RuntimeEventPayloadType(timingSample) == RuntimeEventType::TimingSampleRecorded, "timing sample payload maps to timing event"); QueueDepthChangedEvent queueDepth; queueDepth.queueName = "runtime-events"; queueDepth.depth = 1; queueDepth.capacity = 16; Expect(RuntimeEventPayloadType(queueDepth) == RuntimeEventType::QueueDepthChanged, "queue depth payload maps to queue depth event"); SubsystemWarningEvent warning; warning.subsystem = "VideoBackend"; warning.warningKey = "late-frame"; Expect(RuntimeEventPayloadType(warning) == RuntimeEventType::SubsystemWarningRaised, "warning payload maps to raised event by default"); warning.cleared = true; Expect(RuntimeEventPayloadType(warning) == RuntimeEventType::SubsystemWarningCleared, "warning payload maps to cleared event when marked cleared"); } void TestRuntimeEventEnvelope() { const auto createdAt = std::chrono::steady_clock::now(); OscCommitRequestedEvent oscCommit; oscCommit.routeKey = "layer-1\namount"; oscCommit.layerKey = "layer-1"; oscCommit.parameterKey = "amount"; oscCommit.generation = 7; RuntimeEvent event = MakeRuntimeEvent(oscCommit, "ControlServices", 12, createdAt); Expect(event.type == RuntimeEventType::OscCommitRequested, "runtime event infers type from payload"); Expect(event.sequence == 12, "runtime event stores sequence"); Expect(event.source == "ControlServices", "runtime event stores source"); Expect(event.createdAt == createdAt, "runtime event stores creation time"); Expect(event.HasPayload(), "runtime event reports payload presence"); Expect(event.PayloadMatchesType(), "runtime event payload matches inferred type"); const auto* payload = std::get_if(&event.payload); Expect(payload && payload->generation == 7, "runtime event stores typed payload in variant"); event.type = RuntimeEventType::RuntimeMutationAccepted; Expect(!event.PayloadMatchesType(), "runtime event detects mismatched payload and type"); RuntimeEvent empty; Expect(!empty.HasPayload(), "default runtime event has no payload"); Expect(empty.PayloadMatchesType(), "default runtime event unknown type matches empty payload"); RuntimeMutationEvent acceptedMutation; acceptedMutation.accepted = true; acceptedMutation.action = "SetLayerBypass"; RuntimeEvent acceptedEvent = MakeRuntimeEvent(acceptedMutation, "RuntimeCoordinator", 13, createdAt); Expect(acceptedEvent.type == RuntimeEventType::RuntimeMutationAccepted, "runtime event handles payloads with dynamic accepted mapping"); RuntimeMutationEvent rejectedMutation; rejectedMutation.accepted = false; rejectedMutation.action = "SetLayerBypass"; RuntimeEvent rejectedEvent = MakeRuntimeEvent(rejectedMutation, "RuntimeCoordinator", 14, createdAt); Expect(rejectedEvent.type == RuntimeEventType::RuntimeMutationRejected, "runtime event handles payloads with dynamic rejected mapping"); } void TestRuntimeEventQueue() { RuntimeEventQueue queue(2); const auto createdAt = std::chrono::steady_clock::now() - std::chrono::milliseconds(5); RuntimeStateBroadcastRequestedEvent firstPayload; firstPayload.reason = "first"; RuntimeStateBroadcastRequestedEvent secondPayload; secondPayload.reason = "second"; RuntimeStateBroadcastRequestedEvent thirdPayload; thirdPayload.reason = "third"; Expect(queue.Push(MakeRuntimeEvent(firstPayload, "test", 1, createdAt)), "queue accepts first event"); Expect(queue.Push(MakeRuntimeEvent(secondPayload, "test", 2, createdAt)), "queue accepts second event"); Expect(!queue.Push(MakeRuntimeEvent(thirdPayload, "test", 3, createdAt)), "queue rejects event when capacity is full"); RuntimeEventQueueMetrics fullMetrics = queue.GetMetrics(std::chrono::steady_clock::now()); Expect(fullMetrics.depth == 2, "queue metrics report depth"); Expect(fullMetrics.capacity == 2, "queue metrics report capacity"); Expect(fullMetrics.droppedCount == 1, "queue metrics report dropped count"); Expect(fullMetrics.oldestEventAgeMilliseconds >= 0.0, "queue metrics report oldest event age"); RuntimeEvent event; Expect(queue.TryPop(event), "queue pops first event"); Expect(event.sequence == 1, "queue preserves FIFO order"); std::vector drained = queue.Drain(); Expect(drained.size() == 1, "queue drains remaining event"); Expect(drained[0].sequence == 2, "drained event preserves FIFO order"); Expect(queue.Depth() == 0, "queue is empty after drain"); } void TestRuntimeEventDispatcher() { RuntimeEventDispatcher dispatcher(4); int allHandlerCount = 0; int broadcastHandlerCount = 0; int failureHandlerCount = 0; dispatcher.SubscribeAll([&](const RuntimeEvent& event) { Expect(event.sequence != 0, "dispatcher assigns sequence before all-handler dispatch"); ++allHandlerCount; }); dispatcher.Subscribe(RuntimeEventType::RuntimeStateBroadcastRequested, [&](const RuntimeEvent& event) { Expect(event.type == RuntimeEventType::RuntimeStateBroadcastRequested, "dispatcher invokes type-specific handler for matching event"); ++broadcastHandlerCount; }); dispatcher.Subscribe(RuntimeEventType::RuntimeStateBroadcastRequested, [&](const RuntimeEvent&) { ++failureHandlerCount; throw std::runtime_error("test handler failure"); }); RuntimeStateBroadcastRequestedEvent broadcast; broadcast.reason = "test"; Expect(dispatcher.PublishPayload(broadcast, "test"), "dispatcher publishes payload"); Expect(dispatcher.QueueDepth() == 1, "dispatcher reports queued depth"); RuntimeEventDispatchResult result = dispatcher.DispatchPending(); Expect(result.dispatchedEvents == 1, "dispatcher reports dispatched event count"); Expect(result.handlerInvocations == 3, "dispatcher reports handler invocation count"); Expect(result.handlerFailures == 1, "dispatcher catches and reports handler failures"); Expect(allHandlerCount == 1, "dispatcher invoked all-handler"); Expect(broadcastHandlerCount == 1, "dispatcher invoked type-specific handler"); Expect(failureHandlerCount == 1, "dispatcher invoked failing handler"); Expect(dispatcher.QueueDepth() == 0, "dispatcher queue is empty after dispatch"); RuntimeEvent mismatched = MakeRuntimeEvent(broadcast, "test"); mismatched.type = RuntimeEventType::ShaderBuildRequested; Expect(!dispatcher.Publish(mismatched), "dispatcher rejects mismatched event type and payload"); RuntimeEventDispatcher tinyDispatcher(1); Expect(tinyDispatcher.PublishPayload(broadcast, "test"), "tiny dispatcher accepts first event"); Expect(!tinyDispatcher.PublishPayload(broadcast, "test"), "tiny dispatcher rejects event when queue is full"); RuntimeEventQueueMetrics metrics = tinyDispatcher.GetQueueMetrics(); Expect(metrics.droppedCount == 1, "dispatcher exposes queue drop metrics"); } void TestRuntimeEventCoalescingQueue() { RuntimeEventCoalescingQueue queue(2); const auto createdAt = std::chrono::steady_clock::now() - std::chrono::milliseconds(5); OscValueReceivedEvent first; first.routeKey = "layer-1\namount"; first.layerKey = "layer-1"; first.parameterKey = "amount"; first.valueJson = "0.1"; first.generation = 1; OscValueReceivedEvent replacement = first; replacement.valueJson = "0.9"; replacement.generation = 2; OscValueReceivedEvent otherRoute; otherRoute.routeKey = "layer-2\namount"; otherRoute.layerKey = "layer-2"; otherRoute.parameterKey = "amount"; otherRoute.valueJson = "0.3"; otherRoute.generation = 3; OscValueReceivedEvent overflow; overflow.routeKey = "layer-3\namount"; overflow.layerKey = "layer-3"; overflow.parameterKey = "amount"; overflow.valueJson = "0.4"; overflow.generation = 4; Expect(queue.Push(MakeRuntimeEvent(first, "ControlServices", 1, createdAt)), "coalescing queue accepts first keyed event"); Expect(queue.Push(MakeRuntimeEvent(replacement, "ControlServices", 2, std::chrono::steady_clock::now())), "coalescing queue replaces matching keyed event"); Expect(queue.Push(MakeRuntimeEvent(otherRoute, "ControlServices", 3, createdAt)), "coalescing queue accepts second keyed event"); Expect(!queue.Push(MakeRuntimeEvent(overflow, "ControlServices", 4, createdAt)), "coalescing queue rejects new key when full"); RuntimeEventCoalescingQueueMetrics metrics = queue.GetMetrics(std::chrono::steady_clock::now()); Expect(metrics.depth == 2, "coalescing queue metrics report unique-key depth"); Expect(metrics.capacity == 2, "coalescing queue metrics report capacity"); Expect(metrics.coalescedCount == 1, "coalescing queue metrics report coalesced count"); Expect(metrics.droppedCount == 1, "coalescing queue metrics report dropped count"); Expect(metrics.oldestEventAgeMilliseconds >= 0.0, "coalescing queue metrics report oldest event age"); std::vector drained = queue.Drain(); Expect(drained.size() == 2, "coalescing queue drains unique events"); Expect(drained[0].sequence == 2, "coalescing queue keeps latest replacement event"); Expect(drained[1].sequence == 3, "coalescing queue preserves first-seen key order"); const auto* latestPayload = std::get_if(&drained[0].payload); Expect(latestPayload && latestPayload->valueJson == "0.9", "coalescing queue keeps latest payload value"); Expect(queue.Depth() == 0, "coalescing queue is empty after drain"); } void TestRuntimeEventCoalescingCustomKey() { RuntimeEventCoalescingQueue queue(4, [](const RuntimeEvent& event) { return std::string(RuntimeEventTypeName(event.type)); }); RuntimeStateBroadcastRequestedEvent first; first.reason = "parameter"; RuntimeStateBroadcastRequestedEvent second; second.reason = "reload"; Expect(queue.Push(MakeRuntimeEvent(first, "RuntimeCoordinator", 10)), "custom-key coalescing queue accepts first event"); Expect(queue.Push(MakeRuntimeEvent(second, "RuntimeCoordinator", 11)), "custom-key coalescing queue coalesces second event by type"); std::vector drained = queue.Drain(); Expect(drained.size() == 1, "custom-key coalescing queue drains one coalesced event"); Expect(drained[0].sequence == 11, "custom-key coalescing queue keeps latest event"); const auto* payload = std::get_if(&drained[0].payload); Expect(payload && payload->reason == "reload", "custom-key coalescing queue keeps latest typed payload"); } void TestRuntimeEventTestHarness() { RuntimeEventTestHarness harness; RuntimeStateBroadcastRequestedEvent broadcast; broadcast.reason = "parameter"; RuntimeEventDispatchResult firstDispatch = harness.PublishAndDispatch(broadcast, "RuntimeCoordinator"); Expect(firstDispatch.dispatchedEvents == 1, "test harness publishes and dispatches payloads"); Expect(harness.SeenCount() == 1, "test harness records dispatched events"); Expect(harness.SeenCount(RuntimeEventType::RuntimeStateBroadcastRequested) == 1, "test harness counts seen events by type"); const RuntimeEvent* seenBroadcast = harness.LastSeen(RuntimeEventType::RuntimeStateBroadcastRequested); Expect(seenBroadcast && seenBroadcast->source == "RuntimeCoordinator", "test harness returns last seen event by type"); harness.ClearSeen(); Expect(harness.SeenCount() == 0, "test harness clears seen events"); OscValueReceivedEvent first; first.routeKey = "layer-1\namount"; first.layerKey = "layer-1"; first.parameterKey = "amount"; first.valueJson = "0.1"; first.generation = 1; OscValueReceivedEvent replacement = first; replacement.valueJson = "0.8"; replacement.generation = 2; Expect(harness.PublishCoalesced(first, "ControlServices", 20), "test harness accepts first coalesced payload"); Expect(harness.PublishCoalesced(replacement, "ControlServices", 21), "test harness accepts replacement coalesced payload"); RuntimeEventDispatchResult coalescedDispatch = harness.FlushCoalescedAndDispatch(); Expect(coalescedDispatch.dispatchedEvents == 1, "test harness dispatches one coalesced event"); Expect(harness.SeenCount(RuntimeEventType::OscValueReceived) == 1, "test harness records coalesced event"); const RuntimeEvent* seenOsc = harness.LastSeen(RuntimeEventType::OscValueReceived); const auto* seenPayload = seenOsc ? std::get_if(&seenOsc->payload) : nullptr; Expect(seenPayload && seenPayload->valueJson == "0.8", "test harness keeps latest coalesced payload"); } void TestAcceptedMutationFollowUps() { RuntimeEventTestHarness harness; RuntimeMutationEvent mutation; mutation.action = "SetLayerShader"; mutation.accepted = true; mutation.runtimeStateChanged = true; mutation.runtimeStateBroadcastRequired = true; mutation.shaderBuildRequested = true; mutation.persistenceRequested = true; RuntimeStateChangedEvent stateChanged; stateChanged.reason = mutation.action; stateChanged.persistenceRequested = true; RuntimePersistenceRequestedEvent persistence; persistence.reason = mutation.action; persistence.debounceAllowed = true; RuntimeReloadRequestedEvent reload; reload.reason = mutation.action; reload.preserveFeedbackState = false; ShaderBuildEvent build; build.phase = RuntimeEventShaderBuildPhase::Requested; build.succeeded = true; build.message = "Shader rebuild queued."; Expect(harness.Publish(mutation, "RuntimeCoordinator"), "accepted mutation event publishes"); Expect(harness.Publish(stateChanged, "RuntimeCoordinator"), "state changed follow-up publishes"); Expect(harness.Publish(persistence, "RuntimeCoordinator"), "persistence follow-up publishes"); Expect(harness.Publish(reload, "RuntimeCoordinator"), "reload follow-up publishes"); Expect(harness.Publish(build, "RuntimeCoordinator"), "shader build follow-up publishes"); RuntimeEventDispatchResult result = harness.DispatchPending(); Expect(result.dispatchedEvents == 5, "accepted mutation dispatches every expected follow-up"); Expect(harness.SeenCount(RuntimeEventType::RuntimeMutationAccepted) == 1, "accepted mutation fact is observed"); Expect(harness.SeenCount(RuntimeEventType::RuntimeStateChanged) == 1, "accepted mutation publishes state changed follow-up"); Expect(harness.SeenCount(RuntimeEventType::RuntimePersistenceRequested) == 1, "accepted mutation publishes persistence follow-up"); Expect(harness.SeenCount(RuntimeEventType::RuntimeReloadRequested) == 1, "accepted mutation publishes reload follow-up"); Expect(harness.SeenCount(RuntimeEventType::ShaderBuildRequested) == 1, "accepted mutation publishes shader build follow-up"); const RuntimeEvent* persistenceEvent = harness.LastSeen(RuntimeEventType::RuntimePersistenceRequested); const auto* persistencePayload = persistenceEvent ? std::get_if(&persistenceEvent->payload) : nullptr; Expect(persistencePayload && persistencePayload->reason == "SetLayerShader", "persistence follow-up preserves mutation action reason"); } void TestRejectedMutationHasNoDownstreamFollowUps() { RuntimeEventTestHarness harness; RuntimeMutationEvent mutation; mutation.action = "SetLayerShader"; mutation.accepted = false; mutation.errorMessage = "Unknown shader id: missing"; Expect(harness.Publish(mutation, "RuntimeCoordinator"), "rejected mutation event publishes"); RuntimeEventDispatchResult result = harness.DispatchPending(); Expect(result.dispatchedEvents == 1, "rejected mutation dispatches only the rejection fact"); Expect(harness.SeenCount(RuntimeEventType::RuntimeMutationRejected) == 1, "rejected mutation fact is observed"); Expect(harness.SeenCount(RuntimeEventType::RuntimeStateChanged) == 0, "rejected mutation has no state follow-up"); Expect(harness.SeenCount(RuntimeEventType::RuntimePersistenceRequested) == 0, "rejected mutation has no persistence follow-up"); Expect(harness.SeenCount(RuntimeEventType::RuntimeReloadRequested) == 0, "rejected mutation has no reload follow-up"); Expect(harness.SeenCount(RuntimeEventType::ShaderBuildRequested) == 0, "rejected mutation has no shader build follow-up"); const RuntimeEvent* rejectedEvent = harness.LastSeen(RuntimeEventType::RuntimeMutationRejected); const auto* rejectedPayload = rejectedEvent ? std::get_if(&rejectedEvent->payload) : nullptr; Expect(rejectedPayload && rejectedPayload->errorMessage == "Unknown shader id: missing", "rejected mutation preserves error message"); } void TestShaderBuildGenerationEventMatching() { RuntimeEventTestHarness harness; std::size_t handledBuilds = 0; uint64_t handledGeneration = 0; harness.Dispatcher().Subscribe(RuntimeEventType::ShaderBuildPrepared, [&](const RuntimeEvent& event) { const auto* payload = std::get_if(&event.payload); if (!payload || payload->generation != 7) return; ++handledBuilds; handledGeneration = payload->generation; }); ShaderBuildEvent stale; stale.phase = RuntimeEventShaderBuildPhase::Prepared; stale.generation = 6; stale.succeeded = true; ShaderBuildEvent current = stale; current.generation = 7; Expect(harness.Publish(stale, "ShaderBuildQueue"), "stale shader build event publishes"); Expect(harness.Publish(current, "ShaderBuildQueue"), "current shader build event publishes"); RuntimeEventDispatchResult result = harness.DispatchPending(); Expect(result.dispatchedEvents == 2, "shader build readiness events dispatch in order"); Expect(harness.SeenCount(RuntimeEventType::ShaderBuildPrepared) == 2, "both shader build readiness facts are observable"); Expect(handledBuilds == 1, "generation-aware handler applies only the expected build once"); Expect(handledGeneration == 7, "generation-aware handler records the expected generation"); } void TestHandlerFailureCanBecomeTelemetryEvent() { RuntimeEventTestHarness harness; harness.Dispatcher().Subscribe(RuntimeEventType::RuntimeStateBroadcastRequested, [](const RuntimeEvent&) { throw std::runtime_error("handler failed"); }); RuntimeStateBroadcastRequestedEvent broadcast; broadcast.reason = "test"; Expect(harness.Publish(broadcast, "test"), "broadcast event publishes before failing handler"); RuntimeEventDispatchResult result = harness.DispatchPending(); Expect(result.handlerFailures == 1, "dispatcher reports handler failure for telemetry"); TimingSampleRecordedEvent timing; timing.subsystem = "RuntimeEventDispatcher"; timing.metric = "handlerFailures"; timing.value = static_cast(result.handlerFailures); timing.unit = "count"; Expect(harness.Publish(timing, "HealthTelemetry"), "handler failure timing sample publishes"); harness.DispatchPending(); Expect(harness.SeenCount(RuntimeEventType::TimingSampleRecorded) == 1, "handler failure can be observed as telemetry event"); } } int main() { TestRuntimeEventTypeNames(); TestRuntimeEventPayloadTypes(); TestRuntimeEventEnvelope(); TestRuntimeEventQueue(); TestRuntimeEventDispatcher(); TestRuntimeEventCoalescingQueue(); TestRuntimeEventCoalescingCustomKey(); TestRuntimeEventTestHarness(); TestAcceptedMutationFollowUps(); TestRejectedMutationHasNoDownstreamFollowUps(); TestShaderBuildGenerationEventMatching(); TestHandlerFailureCanBecomeTelemetryEvent(); if (gFailures != 0) { std::cerr << gFailures << " RuntimeEventType test failure(s).\n"; return 1; } std::cout << "RuntimeEventType tests passed.\n"; return 0; }