#include "app_core/app_startup.h" #include "test_harness.h" #include #include namespace { class FakeAppStartupServices final : public pp::app::AppStartupServices { public: void store_run_counter(int value) override { stored_run_counter = value; call_order += "store-counter;"; } void save_preferences() override { save_calls += 1; call_order += "save;"; } void start_timelapse_recording() override { timelapse_starts += 1; call_order += "timelapse;"; } void apply_vr_controllers_enabled(bool enabled) override { vr_controllers_enabled = enabled; call_order += "vr-controllers;"; } void show_license_warning() override { license_warnings += 1; call_order += "license;"; } int stored_run_counter = 0; int save_calls = 0; int timelapse_starts = 0; bool vr_controllers_enabled = false; int license_warnings = 0; std::string call_order; }; void startup_plan_increments_counter_and_enables_requested_side_effects(pp::tests::Harness& harness) { const auto plan = pp::app::plan_app_startup(7, true, false, false); PP_EXPECT(harness, plan); PP_EXPECT(harness, plan.value().previous_run_counter == 7); PP_EXPECT(harness, plan.value().next_run_counter == 8); PP_EXPECT(harness, plan.value().save_preferences); PP_EXPECT(harness, plan.value().start_timelapse); PP_EXPECT(harness, !plan.value().vr_controllers_enabled); PP_EXPECT(harness, plan.value().show_license_warning); } void startup_plan_preserves_disabled_optional_work(pp::tests::Harness& harness) { const auto plan = pp::app::plan_app_startup(0, false, true, true); PP_EXPECT(harness, plan); PP_EXPECT(harness, plan.value().next_run_counter == 1); PP_EXPECT(harness, !plan.value().start_timelapse); PP_EXPECT(harness, plan.value().vr_controllers_enabled); PP_EXPECT(harness, !plan.value().show_license_warning); } void startup_plan_rejects_invalid_counters(pp::tests::Harness& harness) { const auto negative = pp::app::plan_app_startup(-1, true, true, true); const auto overflow = pp::app::plan_app_startup(std::numeric_limits::max(), true, true, true); PP_EXPECT(harness, !negative); PP_EXPECT(harness, negative.status().code == pp::foundation::StatusCode::invalid_argument); PP_EXPECT(harness, !overflow); PP_EXPECT(harness, overflow.status().code == pp::foundation::StatusCode::out_of_range); } void startup_executor_dispatches_in_stable_order(pp::tests::Harness& harness) { FakeAppStartupServices services; const auto plan = pp::app::plan_app_startup(2, true, true, false); PP_EXPECT(harness, plan); PP_EXPECT(harness, pp::app::execute_app_startup_plan(plan.value(), services).ok()); PP_EXPECT(harness, services.stored_run_counter == 3); PP_EXPECT(harness, services.save_calls == 1); PP_EXPECT(harness, services.timelapse_starts == 1); PP_EXPECT(harness, services.vr_controllers_enabled); PP_EXPECT(harness, services.license_warnings == 1); PP_EXPECT(harness, services.call_order == "store-counter;save;timelapse;vr-controllers;license;"); } void startup_executor_preserves_no_op_side_effects(pp::tests::Harness& harness) { FakeAppStartupServices services; auto plan = pp::app::plan_app_startup(4, false, false, true).value(); PP_EXPECT(harness, pp::app::execute_app_startup_plan(plan, services).ok()); PP_EXPECT(harness, services.stored_run_counter == 5); PP_EXPECT(harness, services.save_calls == 1); PP_EXPECT(harness, services.timelapse_starts == 0); PP_EXPECT(harness, !services.vr_controllers_enabled); PP_EXPECT(harness, services.license_warnings == 0); PP_EXPECT(harness, services.call_order == "store-counter;save;vr-controllers;"); } void startup_split_executors_keep_persistence_and_runtime_separate(pp::tests::Harness& harness) { FakeAppStartupServices persistence_services; FakeAppStartupServices runtime_services; const auto plan = pp::app::plan_app_startup(5, true, false, false); PP_EXPECT(harness, plan); PP_EXPECT(harness, pp::app::execute_app_startup_persistence_plan(plan.value(), persistence_services).ok()); PP_EXPECT(harness, persistence_services.stored_run_counter == 6); PP_EXPECT(harness, persistence_services.save_calls == 1); PP_EXPECT(harness, persistence_services.timelapse_starts == 0); PP_EXPECT(harness, persistence_services.license_warnings == 0); PP_EXPECT(harness, persistence_services.call_order == "store-counter;save;"); PP_EXPECT(harness, pp::app::execute_app_startup_runtime_plan(plan.value(), runtime_services).ok()); PP_EXPECT(harness, runtime_services.stored_run_counter == 0); PP_EXPECT(harness, runtime_services.save_calls == 0); PP_EXPECT(harness, runtime_services.timelapse_starts == 1); PP_EXPECT(harness, !runtime_services.vr_controllers_enabled); PP_EXPECT(harness, runtime_services.license_warnings == 1); PP_EXPECT(harness, runtime_services.call_order == "timelapse;vr-controllers;license;"); } void startup_executor_rejects_malformed_counter_state(pp::tests::Harness& harness) { FakeAppStartupServices services; pp::app::AppStartupPlan plan; plan.previous_run_counter = 3; plan.next_run_counter = 3; PP_EXPECT(harness, !pp::app::execute_app_startup_plan(plan, services).ok()); PP_EXPECT(harness, services.call_order.empty()); } } int main() { pp::tests::Harness harness; harness.run( "startup plan increments counter and enables requested side effects", startup_plan_increments_counter_and_enables_requested_side_effects); harness.run("startup plan preserves disabled optional work", startup_plan_preserves_disabled_optional_work); harness.run("startup plan rejects invalid counters", startup_plan_rejects_invalid_counters); harness.run("startup executor dispatches in stable order", startup_executor_dispatches_in_stable_order); harness.run("startup executor preserves no-op side effects", startup_executor_preserves_no_op_side_effects); harness.run( "startup split executors keep persistence and runtime separate", startup_split_executors_keep_persistence_and_runtime_separate); harness.run("startup executor rejects malformed counter state", startup_executor_rejects_malformed_counter_state); return harness.finish(); }