#include "VideoBackendLifecycle.h" #include #include namespace { int gFailures = 0; void Expect(bool condition, const char* message) { if (condition) return; std::cerr << "FAIL: " << message << "\n"; ++gFailures; } void TestAllowedLifecycleTransitions() { VideoBackendLifecycle lifecycle; Expect(lifecycle.State() == VideoBackendLifecycleState::Uninitialized, "lifecycle starts uninitialized"); Expect(lifecycle.TransitionTo(VideoBackendLifecycleState::Discovering, "discover").accepted, "uninitialized can transition to discovering"); Expect(lifecycle.TransitionTo(VideoBackendLifecycleState::Discovered, "discovered").accepted, "discovering can transition to discovered"); Expect(lifecycle.TransitionTo(VideoBackendLifecycleState::Configuring, "configuring").accepted, "discovered can transition to configuring"); Expect(lifecycle.TransitionTo(VideoBackendLifecycleState::Configured, "configured").accepted, "configuring can transition to configured"); Expect(lifecycle.TransitionTo(VideoBackendLifecycleState::Prerolling, "preroll").accepted, "configured can transition to prerolling"); Expect(lifecycle.TransitionTo(VideoBackendLifecycleState::Running, "running").accepted, "prerolling can transition to running"); Expect(lifecycle.TransitionTo(VideoBackendLifecycleState::Degraded, "degraded").accepted, "running can transition to degraded"); Expect(lifecycle.TransitionTo(VideoBackendLifecycleState::Running, "recovered").accepted, "degraded can transition back to running"); Expect(lifecycle.TransitionTo(VideoBackendLifecycleState::Stopping, "stopping").accepted, "running can transition to stopping"); Expect(lifecycle.TransitionTo(VideoBackendLifecycleState::Stopped, "stopped").accepted, "stopping can transition to stopped"); } void TestInvalidLifecycleTransitionIsRejected() { VideoBackendLifecycle lifecycle; const VideoBackendLifecycleTransition transition = lifecycle.TransitionTo(VideoBackendLifecycleState::Running, "skip setup"); Expect(!transition.accepted, "uninitialized cannot transition directly to running"); Expect(lifecycle.State() == VideoBackendLifecycleState::Uninitialized, "invalid transition leaves state unchanged"); Expect(transition.errorMessage.find("Invalid video backend lifecycle transition") != std::string::npos, "invalid transition reports an error"); } void TestFailureStateRecordsReasonAndCanRecover() { VideoBackendLifecycle lifecycle; Expect(lifecycle.TransitionTo(VideoBackendLifecycleState::Discovering, "discover").accepted, "lifecycle can start discovery"); Expect(lifecycle.Fail("no device").accepted, "discovering can transition to failed"); Expect(lifecycle.State() == VideoBackendLifecycleState::Failed, "failure transition sets failed state"); Expect(lifecycle.FailureReason() == "no device", "failure reason is retained"); Expect(lifecycle.TransitionTo(VideoBackendLifecycleState::Discovering, "retry").accepted, "failed lifecycle can retry discovery"); Expect(lifecycle.FailureReason().empty(), "successful non-failed transition clears failure reason"); } void TestStateNamesAreStable() { Expect(std::string(VideoBackendLifecycle::StateName(VideoBackendLifecycleState::Uninitialized)) == "uninitialized", "uninitialized state name is stable"); Expect(std::string(VideoBackendLifecycle::StateName(VideoBackendLifecycleState::Running)) == "running", "running state name is stable"); Expect(std::string(VideoBackendLifecycle::StateName(VideoBackendLifecycleState::Failed)) == "failed", "failed state name is stable"); } } int main() { TestAllowedLifecycleTransitions(); TestInvalidLifecycleTransitionIsRejected(); TestFailureStateRecordsReasonAndCanRecover(); TestStateNamesAreStable(); if (gFailures != 0) { std::cerr << gFailures << " video backend lifecycle test failure(s).\n"; return 1; } std::cout << "VideoBackendLifecycle tests passed.\n"; return 0; }