diff --git a/score/launch_manager/src/daemon/src/configuration/details/flatbuffer_config_loader_UT.cpp b/score/launch_manager/src/daemon/src/configuration/details/flatbuffer_config_loader_UT.cpp index db0269bfd4..884924a1c8 100644 --- a/score/launch_manager/src/daemon/src/configuration/details/flatbuffer_config_loader_UT.cpp +++ b/score/launch_manager/src/daemon/src/configuration/details/flatbuffer_config_loader_UT.cpp @@ -84,8 +84,8 @@ ::flatbuffers::Offset buildDefaultDeploymentConfig(::flatb auto sandbox = buildDefaultSandbox(fbb); return fb::CreateDeploymentConfig( fbb, - 1.0 /*ready_timeout*/, - 1.0 /*shutdown_timeout*/, + 1000 /*ready_timeout_ms*/, + 1000 /*shutdown_timeout_ms*/, 0 /*environmental_variables*/, bin_dir, work_dir, @@ -116,8 +116,9 @@ std::vector buildConfigWithComponents( ::flatbuffers::FlatBufferBuilder& fbb, ::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset>> comps) { - auto fallback = fb::CreateFallbackRunTarget(fbb, 0 /*description*/, 0 /*depends_on*/, 1.0 /*transition_timeout*/); - auto alive_sup = fb::CreateAliveSupervision(fbb, 1.0 /*evaluation_cycle*/); + auto fallback = + fb::CreateFallbackRunTarget(fbb, 0 /*description*/, 0 /*depends_on*/, 1000 /*transition_timeout_ms*/); + auto alive_sup = fb::CreateAliveSupervision(fbb, 1000 /*evaluation_cycle_ms*/); auto rts = fbb.CreateVector(std::vector<::flatbuffers::Offset>{}); auto irt = fbb.CreateString("Startup"); auto config = fb::CreateLaunchManagerConfig( @@ -129,8 +130,9 @@ std::vector buildConfigWithRunTargets( ::flatbuffers::FlatBufferBuilder& fbb, ::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset>> rts) { - auto fallback = fb::CreateFallbackRunTarget(fbb, 0 /*description*/, 0 /*depends_on*/, 1.0 /*transition_timeout*/); - auto alive_sup = fb::CreateAliveSupervision(fbb, 1.0 /*evaluation_cycle*/); + auto fallback = + fb::CreateFallbackRunTarget(fbb, 0 /*description*/, 0 /*depends_on*/, 1000 /*transition_timeout_ms*/); + auto alive_sup = fb::CreateAliveSupervision(fbb, 1000 /*evaluation_cycle_ms*/); auto comps = fbb.CreateVector(std::vector<::flatbuffers::Offset>{}); auto irt = fbb.CreateString("Startup"); auto config = fb::CreateLaunchManagerConfig( @@ -168,8 +170,8 @@ class FlatbufferConfigLoaderTest : public ::testing::Test ::flatbuffers::FlatBufferBuilder fbb; auto irt = fbb.CreateString(initial_run_target); auto fallback = - fb::CreateFallbackRunTarget(fbb, 0 /*description*/, 0 /*depends_on*/, 1.0 /*transition_timeout*/); - auto alive_sup = fb::CreateAliveSupervision(fbb, 1.0 /*evaluation_cycle*/); + fb::CreateFallbackRunTarget(fbb, 0 /*description*/, 0 /*depends_on*/, 1000 /*transition_timeout_ms*/); + auto alive_sup = fb::CreateAliveSupervision(fbb, 1000 /*evaluation_cycle_ms*/); auto comps = fbb.CreateVector(std::vector<::flatbuffers::Offset>{}); auto rts = fbb.CreateVector(std::vector<::flatbuffers::Offset>{}); auto config = fb::CreateLaunchManagerConfig(fbb, schema_version, comps, rts, irt, fallback, alive_sup); @@ -209,7 +211,7 @@ TEST_F(FlatbufferConfigLoaderTest, LoadSingleComponent) ::flatbuffers::FlatBufferBuilder fbb; auto alive_sup = fb::CreateComponentAliveSupervision( - fbb, 0.5 /*reporting_cycle*/, 2 /*failed_cycles_tolerance*/, 1 /*min_indications*/, 3 /*max_indications*/); + fbb, 500 /*reporting_cycle_ms*/, 2 /*failed_cycles_tolerance*/, 1 /*min_indications*/, 3 /*max_indications*/); auto app_profile = fb::CreateApplicationProfile( fbb, fb::ApplicationType::Reporting_And_Supervised, true /*is_self_terminating*/, alive_sup); auto bin_name = fbb.CreateString("my_binary"); @@ -225,8 +227,8 @@ TEST_F(FlatbufferConfigLoaderTest, LoadSingleComponent) auto sandbox = buildDefaultSandbox(fbb); auto deploy = fb::CreateDeploymentConfig( fbb, - 1.5 /*ready_timeout*/, - 2.5 /*shutdown_timeout*/, + 1500 /*ready_timeout_ms*/, + 2500 /*shutdown_timeout_ms*/, 0 /*environmental_variables*/, bin_dir, work_dir, @@ -278,7 +280,7 @@ TEST_F(FlatbufferConfigLoaderTest, LoadSingleComponentWithFileState) auto app_profile = fb::CreateApplicationProfile(fbb, fb::ApplicationType::Native, false /*is_self_terminating*/); auto bin_name = fbb.CreateString("my_binary"); auto file_state = - fb::CreateFileStateDirect(fbb, "/tmp/ready", fb::FileExistenceState::Exists, 0.01 /*polling_interval*/); + fb::CreateFileStateDirect(fbb, "/tmp/ready", fb::FileExistenceState::Exists, 10 /*polling_interval_ms*/); auto ready_cond = fb::CreateReadyCondition(fbb, std::nullopt, file_state); auto comp_props = fb::CreateComponentProperties( fbb, bin_name, app_profile, 0 /*depends_on*/, 0 /*process_arguments*/, ready_cond); @@ -288,8 +290,8 @@ TEST_F(FlatbufferConfigLoaderTest, LoadSingleComponentWithFileState) auto sandbox = buildDefaultSandbox(fbb); auto deploy = fb::CreateDeploymentConfig( fbb, - 1.5 /*ready_timeout*/, - 2.5 /*shutdown_timeout*/, + 1500 /*ready_timeout_ms*/, + 2500 /*shutdown_timeout_ms*/, 0 /*environmental_variables*/, bin_dir, work_dir, @@ -326,7 +328,7 @@ TEST_F(FlatbufferConfigLoaderTest, LoadRunTargets) auto rt_desc = fbb.CreateString("Initial state"); auto rt_dep = fbb.CreateString("component_a"); auto rt_deps = fbb.CreateVector(std::vector<::flatbuffers::Offset<::flatbuffers::String>>{rt_dep}); - auto rt = fb::CreateRunTarget(fbb, rt_name, rt_desc, rt_deps, 5.0 /*transition_timeout*/, switch_action); + auto rt = fb::CreateRunTarget(fbb, rt_name, rt_desc, rt_deps, 5000 /*transition_timeout_ms*/, switch_action); auto rts = fbb.CreateVector(std::vector<::flatbuffers::Offset>{rt}); auto result = loadBuffer(buildConfigWithRunTargets(fbb, rts)); @@ -353,7 +355,8 @@ TEST_F(FlatbufferConfigLoaderTest, ConfiguredOffRunTargetIsLoadedVerbatim) auto switch_action = fb::CreateSwitchRunTargetAction(fbb, switch_target); auto rt_name = fbb.CreateString(kOffRunTargetName); auto rt_desc = fbb.CreateString("Configured off state"); - auto rt = fb::CreateRunTarget(fbb, rt_name, rt_desc, 0 /*depends_on*/, 2.0 /*transition_timeout*/, switch_action); + auto rt = + fb::CreateRunTarget(fbb, rt_name, rt_desc, 0 /*depends_on*/, 2000 /*transition_timeout_ms*/, switch_action); auto rts = fbb.CreateVector(std::vector<::flatbuffers::Offset>{rt}); auto result = loadBuffer(buildConfigWithRunTargets(fbb, rts)); @@ -374,9 +377,9 @@ TEST_F(FlatbufferConfigLoaderTest, LoadFallbackRunTarget) auto fb_desc = fbb.CreateString("Fallback state"); auto fb_dep = fbb.CreateString("critical_comp"); auto fb_deps = fbb.CreateVector(std::vector<::flatbuffers::Offset<::flatbuffers::String>>{fb_dep}); - auto fallback = fb::CreateFallbackRunTarget(fbb, fb_desc, fb_deps, 10.0 /*transition_timeout*/); + auto fallback = fb::CreateFallbackRunTarget(fbb, fb_desc, fb_deps, 10000 /*transition_timeout_ms*/); - auto alive_sup = fb::CreateAliveSupervision(fbb, 1.0 /*evaluation_cycle*/); + auto alive_sup = fb::CreateAliveSupervision(fbb, 1000 /*evaluation_cycle_ms*/); auto comps = fbb.CreateVector(std::vector<::flatbuffers::Offset>{}); auto rts = fbb.CreateVector(std::vector<::flatbuffers::Offset>{}); auto irt = fbb.CreateString("Startup"); @@ -399,8 +402,9 @@ TEST_F(FlatbufferConfigLoaderTest, LoadAliveSupervision) ::flatbuffers::FlatBufferBuilder fbb; - auto alive_sup = fb::CreateAliveSupervision(fbb, 0.25 /*evaluation_cycle*/); - auto fallback = fb::CreateFallbackRunTarget(fbb, 0 /*description*/, 0 /*depends_on*/, 1.0 /*transition_timeout*/); + auto alive_sup = fb::CreateAliveSupervision(fbb, 250 /*evaluation_cycle_ms*/); + auto fallback = + fb::CreateFallbackRunTarget(fbb, 0 /*description*/, 0 /*depends_on*/, 1000 /*transition_timeout_ms*/); auto comps = fbb.CreateVector(std::vector<::flatbuffers::Offset>{}); auto rts = fbb.CreateVector(std::vector<::flatbuffers::Offset>{}); auto irt = fbb.CreateString("Startup"); @@ -421,10 +425,11 @@ TEST_F(FlatbufferConfigLoaderTest, LoadWatchdog) auto dev_path = fbb.CreateString("/dev/watchdog0"); auto watchdog = fb::CreateWatchdog( - fbb, dev_path, 30.0 /*max_timeout*/, true /*deactivate_on_shutdown*/, false /*require_magic_close*/); + fbb, dev_path, 30000 /*max_timeout_ms*/, true /*deactivate_on_shutdown*/, false /*require_magic_close*/); - auto fallback = fb::CreateFallbackRunTarget(fbb, 0 /*description*/, 0 /*depends_on*/, 1.0 /*transition_timeout*/); - auto alive_sup = fb::CreateAliveSupervision(fbb, 1.0 /*evaluation_cycle*/); + auto fallback = + fb::CreateFallbackRunTarget(fbb, 0 /*description*/, 0 /*depends_on*/, 1000 /*transition_timeout_ms*/); + auto alive_sup = fb::CreateAliveSupervision(fbb, 1000 /*evaluation_cycle_ms*/); auto comps = fbb.CreateVector(std::vector<::flatbuffers::Offset>{}); auto rts = fbb.CreateVector(std::vector<::flatbuffers::Offset>{}); auto irt = fbb.CreateString("Startup"); @@ -449,14 +454,14 @@ TEST_F(FlatbufferConfigLoaderTest, LoadRestartRecoveryAction) ::flatbuffers::FlatBufferBuilder fbb; - auto restart = fb::CreateRestartAction(fbb, 3 /*number_of_attempts*/, 1.5 /*delay_before_restart*/); + auto restart = fb::CreateRestartAction(fbb, 3 /*number_of_attempts*/, 1500 /*delay_before_restart_ms*/); auto bin_dir = fbb.CreateString("/opt"); auto work_dir = fbb.CreateString("/tmp"); auto sandbox = buildDefaultSandbox(fbb); auto deploy = fb::CreateDeploymentConfig( fbb, - 1.0 /*ready_timeout*/, - 1.0 /*shutdown_timeout*/, + 1000 /*ready_timeout_ms*/, + 1000 /*shutdown_timeout_ms*/, 0 /*environmental_variables*/, bin_dir, work_dir, @@ -488,7 +493,7 @@ TEST_F(FlatbufferConfigLoaderTest, LoadSwitchRunTargetAction) auto switch_action = fb::CreateSwitchRunTargetAction(fbb, target_name); auto rt_name = fbb.CreateString("Startup"); auto rt = fb::CreateRunTarget( - fbb, rt_name, 0 /*description*/, 0 /*depends_on*/, 1.0 /*transition_timeout*/, switch_action); + fbb, rt_name, 0 /*description*/, 0 /*depends_on*/, 1000 /*transition_timeout_ms*/, switch_action); auto rts = fbb.CreateVector(std::vector<::flatbuffers::Offset>{rt}); auto result = loadBuffer(buildConfigWithRunTargets(fbb, rts)); @@ -520,8 +525,8 @@ TEST_F(FlatbufferConfigLoaderTest, LoadSandbox) auto work_dir = fbb.CreateString("/tmp"); auto deploy = fb::CreateDeploymentConfig( fbb, - 0.5 /*ready_timeout*/, - 0.5 /*shutdown_timeout*/, + 500 /*ready_timeout_ms*/, + 500 /*shutdown_timeout_ms*/, 0 /*environmental_variables*/, bin_dir, work_dir, @@ -558,7 +563,7 @@ TEST_F(FlatbufferConfigLoaderTest, LoadComponentAliveSupervision) ::flatbuffers::FlatBufferBuilder fbb; auto comp_alive_sup = fb::CreateComponentAliveSupervision( - fbb, 1.0 /*reporting_cycle*/, 3 /*failed_cycles_tolerance*/, 2 /*min_indications*/, 5 /*max_indications*/); + fbb, 1000 /*reporting_cycle_ms*/, 3 /*failed_cycles_tolerance*/, 2 /*min_indications*/, 5 /*max_indications*/); auto app_profile = fb::CreateApplicationProfile( fbb, fb::ApplicationType::Reporting_And_Supervised, false /*is_self_terminating*/, comp_alive_sup); auto bin_name = fbb.CreateString("supervised_bin"); @@ -601,8 +606,8 @@ TEST_F(FlatbufferConfigLoaderTest, LoadEnvironmentalVariables) auto sandbox = buildDefaultSandbox(fbb); auto deploy = fb::CreateDeploymentConfig( fbb, - 0.5 /*ready_timeout*/, - 0.5 /*shutdown_timeout*/, + 500 /*ready_timeout_ms*/, + 500 /*shutdown_timeout_ms*/, env_vars, bin_dir, work_dir, @@ -756,8 +761,8 @@ TEST_F(FlatbufferConfigLoaderTest, MissingSchemaVersionReturnsInvalidFormat) ::flatbuffers::FlatBufferBuilder fbb; auto irt = fbb.CreateString("Startup"); - auto fallback = fb::CreateFallbackRunTarget(fbb, 0, 0, 1.0); - auto alive_sup = fb::CreateAliveSupervision(fbb, 1.0); + auto fallback = fb::CreateFallbackRunTarget(fbb, 0, 0, 1000); + auto alive_sup = fb::CreateAliveSupervision(fbb, 1000); auto comps = fbb.CreateVector(std::vector<::flatbuffers::Offset>{}); auto rts = fbb.CreateVector(std::vector<::flatbuffers::Offset>{}); auto config = fb::CreateLaunchManagerConfig(fbb, std::nullopt, comps, rts, irt, fallback, alive_sup); diff --git a/score/launch_manager/src/daemon/src/configuration/details/flatbuffer_type_converters.cpp b/score/launch_manager/src/daemon/src/configuration/details/flatbuffer_type_converters.cpp index 1f5724bbd3..56e8a9501d 100644 --- a/score/launch_manager/src/daemon/src/configuration/details/flatbuffer_type_converters.cpp +++ b/score/launch_manager/src/daemon/src/configuration/details/flatbuffer_type_converters.cpp @@ -21,7 +21,6 @@ #include #include #include -#include #include #include @@ -52,29 +51,6 @@ std::optional optionalScalarValue(const ::flatbuffers::Optional& field) } // anonymous namespace -constexpr double kSecondsToMilliseconds = 1000.0; - -score::cpp::expected secondsToMs(double seconds) -{ - if (seconds < 0.0) - { - LM_LOG_ERROR() << "Negative time value " << seconds << " seconds is not supported"; - return score::cpp::make_unexpected(IConfigLoader::Error::InvalidFormat); - } - if (seconds * kSecondsToMilliseconds > static_cast(std::numeric_limits::max())) - { - LM_LOG_ERROR() << "Time value " << seconds << " seconds exceeds maximum representable milliseconds"; - return score::cpp::make_unexpected(IConfigLoader::Error::InvalidFormat); - } - const auto result = static_cast(seconds * kSecondsToMilliseconds); - if (seconds > 0.0 && result == 0U) - { - LM_LOG_ERROR() << "Sub-millisecond time value " << seconds << " seconds rounds to 0ms"; - return score::cpp::make_unexpected(IConfigLoader::Error::InvalidFormat); - } - return result; -} - ApplicationType convertApplicationType(fb::ApplicationType fb_type) { switch (fb_type) @@ -205,18 +181,13 @@ score::cpp::expected, IConfigLoader::Error> convert { return score::cpp::make_unexpected(number_of_attempts.error()); } - auto delay_before_restart = requireScalarValue(ra->delay_before_restart(), "RestartAction::delay_before_restart"); + auto delay_before_restart = + requireScalarValue(ra->delay_before_restart_ms(), "RestartAction::delay_before_restart_ms"); if (!delay_before_restart.has_value()) { return score::cpp::make_unexpected(delay_before_restart.error()); } - auto delay_ms = secondsToMs(*delay_before_restart); - if (!delay_ms.has_value()) - { - LM_LOG_ERROR() << "Invalid value for RestartAction::delay_before_restart"; - return score::cpp::make_unexpected(delay_ms.error()); - } - return std::optional{RestartAction{*number_of_attempts, *delay_ms}}; + return std::optional{RestartAction{*number_of_attempts, *delay_before_restart}}; } std::optional convertSwitchRunTargetAction(const fb::SwitchRunTargetAction* sa) @@ -244,7 +215,7 @@ score::cpp::expected convertCom if (fb_cas != nullptr) { auto reporting_cycle = - requireScalarValue(fb_cas->reporting_cycle(), "ComponentAliveSupervision::reporting_cycle"); + requireScalarValue(fb_cas->reporting_cycle_ms(), "ComponentAliveSupervision::reporting_cycle_ms"); if (!reporting_cycle.has_value()) { return score::cpp::make_unexpected(reporting_cycle.error()); @@ -255,13 +226,7 @@ score::cpp::expected convertCom { return score::cpp::make_unexpected(failed_cycles_tolerance.error()); } - auto reporting_cycle_ms = secondsToMs(*reporting_cycle); - if (!reporting_cycle_ms.has_value()) - { - LM_LOG_ERROR() << "Invalid value for ComponentAliveSupervision::reporting_cycle"; - return score::cpp::make_unexpected(reporting_cycle_ms.error()); - } - result.reporting_cycle_ms = *reporting_cycle_ms; + result.reporting_cycle_ms = *reporting_cycle; result.failed_cycles_tolerance = *failed_cycles_tolerance; result.min_indications = optionalScalarValue(fb_cas->min_indications()); result.max_indications = optionalScalarValue(fb_cas->max_indications()); @@ -312,14 +277,10 @@ score::cpp::expected convertFileState(const fb: { SCORE_LANGUAGE_FUTURECPP_ASSERT_PRD_MESSAGE( fb_fs.file_path(), "FileState::file_path must never be nullptr as it is required in the schema"); - SCORE_LANGUAGE_FUTURECPP_ASSERT_PRD_MESSAGE( - fb_fs.polling_interval() != 0.0, - "No FileState::polling_interval is configured, this should have been defaulted with the script."); - auto polling_interval_ms = secondsToMs(fb_fs.polling_interval()); + auto polling_interval_ms = requireScalarValue(fb_fs.polling_interval_ms(), "FileState::polling_interval_ms"); if (!polling_interval_ms.has_value()) { - LM_LOG_ERROR() << "Invalid value for FileState::polling_interval"; return score::cpp::make_unexpected(polling_interval_ms.error()); } return FileState{ @@ -466,30 +427,19 @@ score::cpp::expected convertDeploymentCo "DeploymentConfig::working_dir must never be nullptr as it is required in the schema"); SCORE_LANGUAGE_FUTURECPP_ASSERT_PRD_MESSAGE( fb_dc->sandbox(), "DeploymentConfig::sandbox must never be nullptr as it is required in the schema"); - auto ready_timeout = requireScalarValue(fb_dc->ready_timeout(), "DeploymentConfig::ready_timeout"); + auto ready_timeout = requireScalarValue(fb_dc->ready_timeout_ms(), "DeploymentConfig::ready_timeout_ms"); if (!ready_timeout.has_value()) { return score::cpp::make_unexpected(ready_timeout.error()); } - auto shutdown_timeout = requireScalarValue(fb_dc->shutdown_timeout(), "DeploymentConfig::shutdown_timeout"); + auto shutdown_timeout = + requireScalarValue(fb_dc->shutdown_timeout_ms(), "DeploymentConfig::shutdown_timeout_ms"); if (!shutdown_timeout.has_value()) { return score::cpp::make_unexpected(shutdown_timeout.error()); } - auto ready_timeout_ms = secondsToMs(*ready_timeout); - if (!ready_timeout_ms.has_value()) - { - LM_LOG_ERROR() << "Invalid value for DeploymentConfig::ready_timeout"; - return score::cpp::make_unexpected(ready_timeout_ms.error()); - } - auto shutdown_timeout_ms = secondsToMs(*shutdown_timeout); - if (!shutdown_timeout_ms.has_value()) - { - LM_LOG_ERROR() << "Invalid value for DeploymentConfig::shutdown_timeout"; - return score::cpp::make_unexpected(shutdown_timeout_ms.error()); - } - result.ready_timeout_ms = *ready_timeout_ms; - result.shutdown_timeout_ms = *shutdown_timeout_ms; + result.ready_timeout_ms = *ready_timeout; + result.shutdown_timeout_ms = *shutdown_timeout; result.environmental_variables = convertEnvironmentalVariables(fb_dc->environmental_variables()); result.bin_dir = fb_dc->bin_dir()->str(); result.working_dir = fb_dc->working_dir()->str(); @@ -553,7 +503,8 @@ score::cpp::expected convertRunTarget(con SCORE_LANGUAGE_FUTURECPP_ASSERT_PRD_MESSAGE( fb_rt->recovery_action(), "RunTarget::recovery_action must never be nullptr as it is required in the schema"); - auto transition_timeout = requireScalarValue(fb_rt->transition_timeout(), "RunTarget::transition_timeout"); + auto transition_timeout = + requireScalarValue(fb_rt->transition_timeout_ms(), "RunTarget::transition_timeout_ms"); if (!transition_timeout.has_value()) { return score::cpp::make_unexpected(transition_timeout.error()); @@ -561,13 +512,7 @@ score::cpp::expected convertRunTarget(con result.name = fb_rt->name()->str(); result.description = safeString(fb_rt->description()); result.depends_on = convertStringVector(fb_rt->depends_on()); - auto transition_timeout_ms = secondsToMs(*transition_timeout); - if (!transition_timeout_ms.has_value()) - { - LM_LOG_ERROR() << "Invalid value for RunTarget::transition_timeout"; - return score::cpp::make_unexpected(transition_timeout_ms.error()); - } - result.transition_timeout_ms = *transition_timeout_ms; + result.transition_timeout_ms = *transition_timeout; result.recovery_action = convertRequiredSwitchRunTargetAction(fb_rt->recovery_action()); } return result; @@ -580,20 +525,14 @@ score::cpp::expected convertFallb if (fb_frt != nullptr) { auto transition_timeout = - requireScalarValue(fb_frt->transition_timeout(), "FallbackRunTarget::transition_timeout"); + requireScalarValue(fb_frt->transition_timeout_ms(), "FallbackRunTarget::transition_timeout_ms"); if (!transition_timeout.has_value()) { return score::cpp::make_unexpected(transition_timeout.error()); } result.description = safeString(fb_frt->description()); result.depends_on = convertStringVector(fb_frt->depends_on()); - auto transition_timeout_ms = secondsToMs(*transition_timeout); - if (!transition_timeout_ms.has_value()) - { - LM_LOG_ERROR() << "Invalid value for FallbackRunTarget::transition_timeout"; - return score::cpp::make_unexpected(transition_timeout_ms.error()); - } - result.transition_timeout_ms = *transition_timeout_ms; + result.transition_timeout_ms = *transition_timeout; } return result; } @@ -605,18 +544,12 @@ score::cpp::expected convertAliveS { return AliveSupervisionConfig{}; } - auto evaluation_cycle = requireScalarValue(fb_as->evaluation_cycle(), "AliveSupervision::evaluation_cycle"); + auto evaluation_cycle = requireScalarValue(fb_as->evaluation_cycle_ms(), "AliveSupervision::evaluation_cycle_ms"); if (!evaluation_cycle.has_value()) { return score::cpp::make_unexpected(evaluation_cycle.error()); } - auto evaluation_cycle_ms = secondsToMs(*evaluation_cycle); - if (!evaluation_cycle_ms.has_value()) - { - LM_LOG_ERROR() << "Invalid value for AliveSupervision::evaluation_cycle"; - return score::cpp::make_unexpected(evaluation_cycle_ms.error()); - } - return AliveSupervisionConfig{*evaluation_cycle_ms}; + return AliveSupervisionConfig{*evaluation_cycle}; } score::cpp::expected, IConfigLoader::Error> convertWatchdog(const fb::Watchdog* fb_wd) @@ -627,7 +560,7 @@ score::cpp::expected, IConfigLoader::Error> conver } SCORE_LANGUAGE_FUTURECPP_ASSERT_PRD_MESSAGE( fb_wd->device_file_path(), "Watchdog::device_file_path must never be nullptr as it is required in the schema"); - auto max_timeout = requireScalarValue(fb_wd->max_timeout(), "Watchdog::max_timeout"); + auto max_timeout = requireScalarValue(fb_wd->max_timeout_ms(), "Watchdog::max_timeout_ms"); if (!max_timeout.has_value()) { return score::cpp::make_unexpected(max_timeout.error()); @@ -645,13 +578,7 @@ score::cpp::expected, IConfigLoader::Error> conver } WatchdogConfig result{}; result.device_file_path = fb_wd->device_file_path()->str(); - auto max_timeout_ms = secondsToMs(*max_timeout); - if (!max_timeout_ms.has_value()) - { - LM_LOG_ERROR() << "Invalid value for Watchdog::max_timeout"; - return score::cpp::make_unexpected(max_timeout_ms.error()); - } - result.max_timeout_ms = *max_timeout_ms; + result.max_timeout_ms = *max_timeout; result.deactivate_on_shutdown = *deactivate_on_shutdown; result.require_magic_close = *require_magic_close; return std::optional{std::move(result)}; diff --git a/score/launch_manager/src/daemon/src/configuration/details/flatbuffer_type_converters.hpp b/score/launch_manager/src/daemon/src/configuration/details/flatbuffer_type_converters.hpp index 259344d163..00ed02406f 100644 --- a/score/launch_manager/src/daemon/src/configuration/details/flatbuffer_type_converters.hpp +++ b/score/launch_manager/src/daemon/src/configuration/details/flatbuffer_type_converters.hpp @@ -60,8 +60,6 @@ score::cpp::expected validateRange(int64_t value, // --- Scalar and enum helpers --- -/// @brief Converts a time value from seconds to milliseconds. -[[nodiscard]] score::cpp::expected secondsToMs(double seconds); /// @brief Converts a FlatBuffer ApplicationType enum to the config ApplicationType. [[nodiscard]] ApplicationType convertApplicationType(fb::ApplicationType fb_type); /// @brief Converts a FlatBuffer ProcessState enum to the config ProcessState. diff --git a/score/launch_manager/src/daemon/src/configuration/details/flatbuffer_type_converters_UT.cpp b/score/launch_manager/src/daemon/src/configuration/details/flatbuffer_type_converters_UT.cpp index 3591f82cbe..f5148a08cb 100644 --- a/score/launch_manager/src/daemon/src/configuration/details/flatbuffer_type_converters_UT.cpp +++ b/score/launch_manager/src/daemon/src/configuration/details/flatbuffer_type_converters_UT.cpp @@ -63,64 +63,6 @@ class TypeConverterTestBase : public ::testing::Test } }; -// ============================================================================ -// secondsToMs tests -// ============================================================================ - -class SecondsToMsTest : public TypeConverterTestBase -{ -}; - -TEST_F(SecondsToMsTest, ConvertsPositiveValue) -{ - RecordProperty("Description", "A positive seconds value converts to milliseconds."); - - auto result = secondsToMs(1.5); - - ASSERT_THAT(result.has_value(), IsTrue()); - EXPECT_THAT(*result, Eq(1500U)); -} - -TEST_F(SecondsToMsTest, ConvertsZero) -{ - RecordProperty("Description", "Zero seconds converts to zero milliseconds."); - - auto result = secondsToMs(0.0); - - ASSERT_THAT(result.has_value(), IsTrue()); - EXPECT_THAT(*result, Eq(0U)); -} - -TEST_F(SecondsToMsTest, RejectsNegativeValue) -{ - RecordProperty("Description", "A negative seconds value returns InvalidFormat."); - - auto result = secondsToMs(-1.0); - - ASSERT_THAT(result.has_value(), IsFalse()); - EXPECT_THAT(result.error(), Eq(IConfigLoader::Error::InvalidFormat)); -} - -TEST_F(SecondsToMsTest, RejectsOverflow) -{ - RecordProperty("Description", "A value exceeding uint32_t max milliseconds returns InvalidFormat."); - - auto result = secondsToMs(5000000.0); - - ASSERT_THAT(result.has_value(), IsFalse()); - EXPECT_THAT(result.error(), Eq(IConfigLoader::Error::InvalidFormat)); -} - -TEST_F(SecondsToMsTest, RejectsSubMillisecond) -{ - RecordProperty("Description", "A positive value that rounds to 0ms returns InvalidFormat."); - - auto result = secondsToMs(0.0001); - - ASSERT_THAT(result.has_value(), IsFalse()); - EXPECT_THAT(result.error(), Eq(IConfigLoader::Error::InvalidFormat)); -} - // ============================================================================ // Enum conversion tests // ============================================================================ @@ -367,7 +309,7 @@ TEST_F(ConverterTest, ConvertRestartActionValid) { RecordProperty("Description", "convertRestartAction with valid fields returns correct values."); ::flatbuffers::FlatBufferBuilder fbb; - auto ra = fb::CreateRestartAction(fbb, 3 /*number_of_attempts*/, 1.5 /*delay_before_restart*/); + auto ra = fb::CreateRestartAction(fbb, 3 /*number_of_attempts*/, 1500 /*delay_before_restart_ms*/); fbb.Finish(ra); const auto* ptr = ::flatbuffers::GetRoot(fbb.GetBufferPointer()); @@ -426,7 +368,7 @@ TEST_F(ConverterTest, ConvertComponentAliveSupervisionValid) RecordProperty("Description", "convertComponentAliveSupervision maps all fields correctly."); ::flatbuffers::FlatBufferBuilder fbb; auto cas = fb::CreateComponentAliveSupervision( - fbb, 0.5 /*reporting_cycle*/, 2 /*failed_cycles_tolerance*/, 1 /*min_indications*/, 3 /*max_indications*/); + fbb, 500 /*reporting_cycle_ms*/, 2 /*failed_cycles_tolerance*/, 1 /*min_indications*/, 3 /*max_indications*/); fbb.Finish(cas); const auto* ptr = ::flatbuffers::GetRoot(fbb.GetBufferPointer()); @@ -442,10 +384,10 @@ TEST_F(ConverterTest, ConvertComponentAliveSupervisionValid) TEST_F(ConverterTest, ConvertComponentAliveSupervisionMissingReportingCycleReturnsError) { - RecordProperty("Description", "Missing reporting_cycle returns InvalidFormat."); + RecordProperty("Description", "Missing reporting_cycle_ms returns InvalidFormat."); ::flatbuffers::FlatBufferBuilder fbb; auto cas = fb::CreateComponentAliveSupervision( - fbb, ::flatbuffers::nullopt /*reporting_cycle*/, 3 /*failed_cycles_tolerance*/); + fbb, ::flatbuffers::nullopt /*reporting_cycle_ms*/, 3 /*failed_cycles_tolerance*/); fbb.Finish(cas); const auto* ptr = ::flatbuffers::GetRoot(fbb.GetBufferPointer()); @@ -459,7 +401,7 @@ TEST_F(ConverterTest, ConvertComponentAliveSupervisionMissingToleranceReturnsErr RecordProperty("Description", "Missing failed_cycles_tolerance returns InvalidFormat."); ::flatbuffers::FlatBufferBuilder fbb; auto cas = fb::CreateComponentAliveSupervision( - fbb, 1.0 /*reporting_cycle*/, ::flatbuffers::nullopt /*failed_cycles_tolerance*/); + fbb, 1000 /*reporting_cycle_ms*/, ::flatbuffers::nullopt /*failed_cycles_tolerance*/); fbb.Finish(cas); const auto* ptr = ::flatbuffers::GetRoot(fbb.GetBufferPointer()); @@ -472,7 +414,7 @@ TEST_F(ConverterTest, ConvertComponentAliveSupervisionBothIndicationsAbsentRetur { RecordProperty("Description", "Both min/max_indications absent returns InvalidFormat."); ::flatbuffers::FlatBufferBuilder fbb; - auto cas = fb::CreateComponentAliveSupervision(fbb, 1.0 /*reporting_cycle*/, 3 /*failed_cycles_tolerance*/); + auto cas = fb::CreateComponentAliveSupervision(fbb, 1000 /*reporting_cycle_ms*/, 3 /*failed_cycles_tolerance*/); fbb.Finish(cas); const auto* ptr = ::flatbuffers::GetRoot(fbb.GetBufferPointer()); @@ -486,7 +428,7 @@ TEST_F(ConverterTest, ConvertComponentAliveSupervisionOnlyMinIndicationsPresent) RecordProperty("Description", "Only min_indications set is accepted, max_indications remains nullopt."); ::flatbuffers::FlatBufferBuilder fbb; auto cas = fb::CreateComponentAliveSupervision( - fbb, 1.0 /*reporting_cycle*/, 3 /*failed_cycles_tolerance*/, 2 /*min_indications*/); + fbb, 1000 /*reporting_cycle_ms*/, 3 /*failed_cycles_tolerance*/, 2 /*min_indications*/); fbb.Finish(cas); const auto* ptr = ::flatbuffers::GetRoot(fbb.GetBufferPointer()); @@ -503,7 +445,7 @@ TEST_F(ConverterTest, ConvertComponentAliveSupervisionOnlyMaxIndicationsPresent) ::flatbuffers::FlatBufferBuilder fbb; auto cas = fb::CreateComponentAliveSupervision( fbb, - 1.0 /*reporting_cycle*/, + 1000 /*reporting_cycle_ms*/, 3 /*failed_cycles_tolerance*/, ::flatbuffers::nullopt /*min_indications*/, 5 /*max_indications*/); @@ -583,7 +525,7 @@ TEST_F(ConverterTest, ConvertReadyConditionWithFileState) { RecordProperty("Description", "convertReadyCondition maps file_state correctly."); ::flatbuffers::FlatBufferBuilder fbb; - auto fs = fb::CreateFileStateDirect(fbb, "/tmp/ready", fb::FileExistenceState::Exists, 0.01 /*polling_interval*/); + auto fs = fb::CreateFileStateDirect(fbb, "/tmp/ready", fb::FileExistenceState::Exists, 10 /*polling_interval_ms*/); auto rc = fb::CreateReadyCondition(fbb, ::flatbuffers::nullopt /*process_state*/, fs); fbb.Finish(rc); const auto* ptr = ::flatbuffers::GetRoot(fbb.GetBufferPointer()); @@ -622,11 +564,12 @@ TEST_F(ConverterTest, ConvertReadyConditionWithNeitherStateDeath) EXPECT_DEATH(static_cast(convertReadyCondition(ptr)), ".*"); } -TEST_F(ConverterTest, ConvertReadyConditionWithInvalidPollingIntervalReturnsError) +TEST_F(ConverterTest, ConvertReadyConditionWithMissingPollingIntervalReturnsError) { - RecordProperty("Description", "convertReadyCondition propagates an invalid FileState::polling_interval."); + RecordProperty( + "Description", "convertReadyCondition propagates a missing FileState::polling_interval_ms as InvalidFormat."); ::flatbuffers::FlatBufferBuilder fbb; - auto fs = fb::CreateFileStateDirect(fbb, "/tmp/ready", fb::FileExistenceState::Exists, -1.0 /*polling_interval*/); + auto fs = fb::CreateFileStateDirect(fbb, "/tmp/ready", fb::FileExistenceState::Exists); auto rc = fb::CreateReadyCondition(fbb, ::flatbuffers::nullopt /*process_state*/, fs); fbb.Finish(rc); const auto* ptr = ::flatbuffers::GetRoot(fbb.GetBufferPointer()); @@ -654,10 +597,11 @@ TEST_F(ConverterTest, ConvertFileExistenceStateMapsBothValues) TEST_F(ConverterTest, ConvertFileStateValid) { - RecordProperty("Description", "convertFileState maps file_path, an explicit state and polling_interval correctly."); + RecordProperty( + "Description", "convertFileState maps file_path, an explicit state and polling_interval_ms correctly."); ::flatbuffers::FlatBufferBuilder fbb; auto fs = - fb::CreateFileStateDirect(fbb, "/tmp/ready", fb::FileExistenceState::NotExisting, 0.3 /*polling_interval*/); + fb::CreateFileStateDirect(fbb, "/tmp/ready", fb::FileExistenceState::NotExisting, 300 /*polling_interval_ms*/); fbb.Finish(fs); const auto* ptr = ::flatbuffers::GetRoot(fbb.GetBufferPointer()); @@ -673,7 +617,7 @@ TEST_F(ConverterTest, ConvertFileStateDefaultsToExists) RecordProperty("Description", "convertFileState defaults state to Exists if it is not set."); ::flatbuffers::FlatBufferBuilder fbb; // state is omitted from the buffer since it matches the schema default - auto fs = fb::CreateFileStateDirect(fbb, "/tmp/ready", fb::FileExistenceState::Exists, 0.01 /*polling_interval*/); + auto fs = fb::CreateFileStateDirect(fbb, "/tmp/ready", fb::FileExistenceState::Exists, 10 /*polling_interval_ms*/); fbb.Finish(fs); const auto* ptr = ::flatbuffers::GetRoot(fbb.GetBufferPointer()); @@ -683,41 +627,17 @@ TEST_F(ConverterTest, ConvertFileStateDefaultsToExists) EXPECT_THAT(result->polling_interval, Eq(std::chrono::milliseconds{10})); } -TEST_F(ConverterTest, ConvertFileStateWithoutPollingIntervalDeath) +TEST_F(ConverterTest, ConvertFileStateWithoutPollingIntervalReturnsError) { RecordProperty( "Description", - "convertFileState fires an assertion if polling_interval is not configured, as the configuration script " - "always defaults it."); + "convertFileState returns InvalidFormat if polling_interval_ms is not configured, as the configuration " + "script always defaults it."); ::flatbuffers::FlatBufferBuilder fbb; auto fs = fb::CreateFileStateDirect(fbb, "/tmp/ready"); fbb.Finish(fs); const auto* ptr = ::flatbuffers::GetRoot(fbb.GetBufferPointer()); - EXPECT_DEATH(static_cast(convertFileState(*ptr)), ".*"); -} - -TEST_F(ConverterTest, ConvertFileStateNegativePollingIntervalReturnsError) -{ - RecordProperty("Description", "convertFileState returns InvalidFormat for a negative polling_interval."); - ::flatbuffers::FlatBufferBuilder fbb; - auto fs = fb::CreateFileStateDirect(fbb, "/tmp/ready", fb::FileExistenceState::Exists, -0.5 /*polling_interval*/); - fbb.Finish(fs); - const auto* ptr = ::flatbuffers::GetRoot(fbb.GetBufferPointer()); - - auto result = convertFileState(*ptr); - ASSERT_THAT(result.has_value(), IsFalse()); - EXPECT_THAT(result.error(), Eq(IConfigLoader::Error::InvalidFormat)); -} - -TEST_F(ConverterTest, ConvertFileStateSubMillisecondPollingIntervalReturnsError) -{ - RecordProperty("Description", "convertFileState returns InvalidFormat for a sub-millisecond polling_interval."); - ::flatbuffers::FlatBufferBuilder fbb; - auto fs = fb::CreateFileStateDirect(fbb, "/tmp/ready", fb::FileExistenceState::Exists, 0.0001 /*polling_interval*/); - fbb.Finish(fs); - const auto* ptr = ::flatbuffers::GetRoot(fbb.GetBufferPointer()); - auto result = convertFileState(*ptr); ASSERT_THAT(result.has_value(), IsFalse()); EXPECT_THAT(result.error(), Eq(IConfigLoader::Error::InvalidFormat)); @@ -889,8 +809,8 @@ TEST_F(ConverterTest, ConvertDeploymentConfigValid) auto sandbox = buildDefaultSandbox(fbb); auto deploy = fb::CreateDeploymentConfig( fbb, - 1.5 /*ready_timeout*/, - 2.5 /*shutdown_timeout*/, + 1500 /*ready_timeout_ms*/, + 2500 /*shutdown_timeout_ms*/, 0 /*environmental_variables*/, bin_dir, work_dir, @@ -912,15 +832,15 @@ TEST_F(ConverterTest, ConvertDeploymentConfigValid) TEST_F(ConverterTest, ConvertDeploymentConfigMissingReadyTimeoutReturnsError) { - RecordProperty("Description", "Missing ready_timeout returns InvalidFormat."); + RecordProperty("Description", "Missing ready_timeout_ms returns InvalidFormat."); ::flatbuffers::FlatBufferBuilder fbb; auto bin_dir = fbb.CreateString("/opt"); auto work_dir = fbb.CreateString("/tmp"); auto sandbox = buildDefaultSandbox(fbb); auto deploy = fb::CreateDeploymentConfig( fbb, - ::flatbuffers::nullopt /*ready_timeout*/, - 1.0 /*shutdown_timeout*/, + ::flatbuffers::nullopt /*ready_timeout_ms*/, + 1000 /*shutdown_timeout_ms*/, 0 /*environmental_variables*/, bin_dir, work_dir, @@ -937,15 +857,15 @@ TEST_F(ConverterTest, ConvertDeploymentConfigMissingReadyTimeoutReturnsError) TEST_F(ConverterTest, ConvertDeploymentConfigMissingShutdownTimeoutReturnsError) { - RecordProperty("Description", "Missing shutdown_timeout returns InvalidFormat."); + RecordProperty("Description", "Missing shutdown_timeout_ms returns InvalidFormat."); ::flatbuffers::FlatBufferBuilder fbb; auto bin_dir = fbb.CreateString("/opt"); auto work_dir = fbb.CreateString("/tmp"); auto sandbox = buildDefaultSandbox(fbb); auto deploy = fb::CreateDeploymentConfig( fbb, - 1.0 /*ready_timeout*/, - ::flatbuffers::nullopt /*shutdown_timeout*/, + 1000 /*ready_timeout_ms*/, + ::flatbuffers::nullopt /*shutdown_timeout_ms*/, 0 /*environmental_variables*/, bin_dir, work_dir, @@ -976,8 +896,8 @@ TEST_F(ConverterTest, ConvertComponentValid) auto sandbox = buildDefaultSandbox(fbb); auto deploy = fb::CreateDeploymentConfig( fbb, - 1.0 /*ready_timeout*/, - 1.0 /*shutdown_timeout*/, + 1000 /*ready_timeout_ms*/, + 1000 /*shutdown_timeout_ms*/, 0 /*environmental_variables*/, bin_dir, work_dir, @@ -1016,8 +936,8 @@ TEST_F(ConverterTest, ConvertComponentsValid) auto sandbox = buildDefaultSandbox(fbb); auto deploy = fb::CreateDeploymentConfig( fbb, - 1.0 /*ready_timeout*/, - 1.0 /*shutdown_timeout*/, + 1000 /*ready_timeout_ms*/, + 1000 /*shutdown_timeout_ms*/, 0 /*environmental_variables*/, bin_dir, work_dir, @@ -1060,8 +980,8 @@ TEST_F(ConverterTest, ConvertComponentsWithInvalidComponentReturnsError) auto sandbox = buildDefaultSandbox(fbb); auto deploy = fb::CreateDeploymentConfig( fbb, - 1.0 /*ready_timeout*/, - 1.0 /*shutdown_timeout*/, + 1000 /*ready_timeout_ms*/, + 1000 /*shutdown_timeout_ms*/, 0 /*environmental_variables*/, bin_dir, work_dir, @@ -1090,7 +1010,7 @@ TEST_F(ConverterTest, ConvertRunTargetsValid) auto switch_action = fb::CreateSwitchRunTargetAction(fbb, switch_target); auto rt_name = fbb.CreateString(name); return fb::CreateRunTarget( - fbb, rt_name, 0 /*description*/, 0 /*depends_on*/, 1.0 /*transition_timeout*/, switch_action); + fbb, rt_name, 0 /*description*/, 0 /*depends_on*/, 1000 /*transition_timeout_ms*/, switch_action); }; auto rt_a = build_rt("Startup", "SafeState"); @@ -1122,7 +1042,7 @@ TEST_F(ConverterTest, ConvertRunTargetsWithInvalidRunTargetReturnsError) rt_name, 0 /*description*/, 0 /*depends_on*/, - ::flatbuffers::nullopt /*transition_timeout*/, + ::flatbuffers::nullopt /*transition_timeout_ms*/, switch_action); auto rts = fbb.CreateVector(std::vector<::flatbuffers::Offset>{rt}); fbb.Finish(rts); @@ -1145,7 +1065,7 @@ TEST_F(ConverterTest, ConvertRunTargetValid) auto rt_desc = fbb.CreateString("Initial state"); auto rt_dep = fbb.CreateString("component_a"); auto rt_deps = fbb.CreateVector(std::vector<::flatbuffers::Offset<::flatbuffers::String>>{rt_dep}); - auto rt = fb::CreateRunTarget(fbb, rt_name, rt_desc, rt_deps, 5.0 /*transition_timeout*/, switch_action); + auto rt = fb::CreateRunTarget(fbb, rt_name, rt_desc, rt_deps, 5000 /*transition_timeout_ms*/, switch_action); fbb.Finish(rt); const auto* ptr = ::flatbuffers::GetRoot(fbb.GetBufferPointer()); @@ -1161,7 +1081,7 @@ TEST_F(ConverterTest, ConvertRunTargetValid) TEST_F(ConverterTest, ConvertRunTargetMissingTransitionTimeoutReturnsError) { - RecordProperty("Description", "Missing transition_timeout returns InvalidFormat."); + RecordProperty("Description", "Missing transition_timeout_ms returns InvalidFormat."); ::flatbuffers::FlatBufferBuilder fbb; auto switch_target = fbb.CreateString("SafeState"); auto switch_action = fb::CreateSwitchRunTargetAction(fbb, switch_target); @@ -1171,7 +1091,7 @@ TEST_F(ConverterTest, ConvertRunTargetMissingTransitionTimeoutReturnsError) rt_name, 0 /*description*/, 0 /*depends_on*/, - ::flatbuffers::nullopt /*transition_timeout*/, + ::flatbuffers::nullopt /*transition_timeout_ms*/, switch_action); fbb.Finish(rt); const auto* ptr = ::flatbuffers::GetRoot(fbb.GetBufferPointer()); @@ -1188,7 +1108,7 @@ TEST_F(ConverterTest, ConvertFallbackRunTargetValid) auto desc = fbb.CreateString("Fallback state"); auto dep = fbb.CreateString("critical_comp"); auto deps = fbb.CreateVector(std::vector<::flatbuffers::Offset<::flatbuffers::String>>{dep}); - auto frt = fb::CreateFallbackRunTarget(fbb, desc, deps, 10.0 /*transition_timeout*/); + auto frt = fb::CreateFallbackRunTarget(fbb, desc, deps, 10000 /*transition_timeout_ms*/); fbb.Finish(frt); const auto* ptr = ::flatbuffers::GetRoot(fbb.GetBufferPointer()); @@ -1202,7 +1122,7 @@ TEST_F(ConverterTest, ConvertFallbackRunTargetValid) TEST_F(ConverterTest, ConvertFallbackRunTargetMissingTimeoutReturnsError) { - RecordProperty("Description", "Missing transition_timeout returns InvalidFormat."); + RecordProperty("Description", "Missing transition_timeout_ms returns InvalidFormat."); ::flatbuffers::FlatBufferBuilder fbb; auto frt = fb::CreateFallbackRunTarget(fbb); fbb.Finish(frt); @@ -1223,9 +1143,9 @@ TEST_F(ConverterTest, ConvertAliveSupervisionNullReturnsDefault) TEST_F(ConverterTest, ConvertAliveSupervisionValid) { - RecordProperty("Description", "convertAliveSupervision maps evaluation_cycle correctly."); + RecordProperty("Description", "convertAliveSupervision maps evaluation_cycle_ms correctly."); ::flatbuffers::FlatBufferBuilder fbb; - auto as = fb::CreateAliveSupervision(fbb, 0.25 /*evaluation_cycle*/); + auto as = fb::CreateAliveSupervision(fbb, 250 /*evaluation_cycle_ms*/); fbb.Finish(as); const auto* ptr = ::flatbuffers::GetRoot(fbb.GetBufferPointer()); @@ -1236,7 +1156,7 @@ TEST_F(ConverterTest, ConvertAliveSupervisionValid) TEST_F(ConverterTest, ConvertAliveSupervisionMissingCycleReturnsError) { - RecordProperty("Description", "Missing evaluation_cycle returns InvalidFormat."); + RecordProperty("Description", "Missing evaluation_cycle_ms returns InvalidFormat."); ::flatbuffers::FlatBufferBuilder fbb; auto as = fb::CreateAliveSupervision(fbb); fbb.Finish(as); @@ -1260,7 +1180,7 @@ TEST_F(ConverterTest, ConvertWatchdogValid) RecordProperty("Description", "convertWatchdog maps all fields correctly."); ::flatbuffers::FlatBufferBuilder fbb; auto dev_path = fbb.CreateString("/dev/watchdog0"); - auto wd = fb::CreateWatchdog(fbb, dev_path, 30.0 /*max_timeout*/, true /*deactivate*/, false /*magic_close*/); + auto wd = fb::CreateWatchdog(fbb, dev_path, 30000 /*max_timeout_ms*/, true /*deactivate*/, false /*magic_close*/); fbb.Finish(wd); const auto* ptr = ::flatbuffers::GetRoot(fbb.GetBufferPointer()); @@ -1275,13 +1195,13 @@ TEST_F(ConverterTest, ConvertWatchdogValid) TEST_F(ConverterTest, ConvertWatchdogMissingMaxTimeoutReturnsError) { - RecordProperty("Description", "Missing max_timeout returns InvalidFormat."); + RecordProperty("Description", "Missing max_timeout_ms returns InvalidFormat."); ::flatbuffers::FlatBufferBuilder fbb; auto dev_path = fbb.CreateString("/dev/watchdog0"); auto wd = fb::CreateWatchdog( fbb, dev_path, - ::flatbuffers::nullopt /*max_timeout*/, + ::flatbuffers::nullopt /*max_timeout_ms*/, true /*deactivate_on_shutdown*/, false /*require_magic_close*/); fbb.Finish(wd); @@ -1300,7 +1220,7 @@ TEST_F(ConverterTest, ConvertWatchdogMissingDeactivateReturnsError) auto wd = fb::CreateWatchdog( fbb, dev_path, - 30.0 /*max_timeout*/, + 30000 /*max_timeout_ms*/, ::flatbuffers::nullopt /*deactivate_on_shutdown*/, false /*require_magic_close*/); fbb.Finish(wd); @@ -1319,7 +1239,7 @@ TEST_F(ConverterTest, ConvertWatchdogMissingMagicCloseReturnsError) auto wd = fb::CreateWatchdog( fbb, dev_path, - 30.0 /*max_timeout*/, + 30000 /*max_timeout_ms*/, true /*deactivate_on_shutdown*/, ::flatbuffers::nullopt /*require_magic_close*/); fbb.Finish(wd); diff --git a/score/launch_manager/src/daemon/src/configuration/details/lm_flatcfg.fbs b/score/launch_manager/src/daemon/src/configuration/details/lm_flatcfg.fbs index 23d352c1a1..a9cfbc3ab3 100644 --- a/score/launch_manager/src/daemon/src/configuration/details/lm_flatcfg.fbs +++ b/score/launch_manager/src/daemon/src/configuration/details/lm_flatcfg.fbs @@ -41,8 +41,8 @@ enum SchedulingPolicy : byte { // Defines the configuration parameters used for alive monitoring of a component. table ComponentAliveSupervision { - // Duration in seconds of the time interval used to verify alive notifications. - reporting_cycle:double = null; // required + // Duration in milliseconds of the time interval used to verify alive notifications. + reporting_cycle_ms:uint32 = null; // required // Maximum number of consecutive reporting cycle failures before recovery is triggered. failed_cycles_tolerance:uint32 = null; // required // Minimum number of checkpoints that must be reported within each reporting_cycle. @@ -65,8 +65,8 @@ table FileState { file_path:string (required); // required // Existence state of the file. Defaults to Exists if not specified. state:FileExistenceState = Exists; // optional, defaults to Exists - // Time in seconds to wait between each poll if the file is present. - polling_interval: double; // required + // Time in milliseconds to wait between each poll if the file is present. + polling_interval_ms:uint32 = null; // required } // Defines the conditions that determine when the component enters the ready state. @@ -94,8 +94,8 @@ table ComponentProperties { table RestartAction { // Maximum number of restart attempts before recovery is considered failed. number_of_attempts:uint32 = null; // required - // Delay in seconds before initiating a restart attempt. - delay_before_restart:double = null; // required + // Delay in milliseconds before initiating a restart attempt. + delay_before_restart_ms:uint32 = null; // required } // Recovery action that switches to a specified Run Target. @@ -132,10 +132,10 @@ table Sandbox { // Deployment configuration for a component. table DeploymentConfig { - // Maximum time in seconds for the component to reach its ready state. - ready_timeout:double = null; // required - // Maximum time in seconds for the component to terminate after SIGTERM. - shutdown_timeout:double = null; // required + // Maximum time in milliseconds for the component to reach its ready state. + ready_timeout_ms:uint32 = null; // required + // Maximum time in milliseconds for the component to terminate after SIGTERM. + shutdown_timeout_ms:uint32 = null; // required // Environment variables passed to the component at startup. environmental_variables:[EnvironmentalVariable]; // optional // Absolute path to the directory where the component is installed. @@ -158,8 +158,8 @@ table RunTarget { description:string; // optional // Names of components and Run Targets that must be activated with this Run Target. depends_on:[string]; // optional - // Time limit in seconds for the Run Target transition. - transition_timeout:double = null; // required + // Time limit in milliseconds for the Run Target transition. + transition_timeout_ms:uint32 = null; // required // Recovery action when a component in this Run Target fails. recovery_action:SwitchRunTargetAction (required); } @@ -176,16 +176,16 @@ table Component { // Global alive supervision configuration. table AliveSupervision { - // Length in seconds of the time window used to assess alive supervision reports. - evaluation_cycle:double = null; // required + // Length in milliseconds of the time window used to assess alive supervision reports. + evaluation_cycle_ms:uint32 = null; // required } // External watchdog device configuration. table Watchdog { // Path to the external watchdog device file (e.g., /dev/watchdog). device_file_path:string (required); // required - // Maximum timeout in seconds configured on the external watchdog. - max_timeout:double = null; // required + // Maximum timeout in milliseconds configured on the external watchdog. + max_timeout_ms:uint32 = null; // required // Whether the watchdog is deactivated during shutdown. deactivate_on_shutdown:bool = null; // required // Whether the magic close sequence is performed on intentional shutdown. @@ -199,8 +199,8 @@ table FallbackRunTarget { description:string; // optional // Names of components and Run Targets that must be activated. depends_on:[string]; // optional - // Time limit in seconds for the Run Target transition. - transition_timeout:double = null; // required + // Time limit in milliseconds for the Run Target transition. + transition_timeout_ms:uint32 = null; // required } // Root configuration table for the S-CORE Launch Manager. diff --git a/scripts/config_mapping/lifecycle_config.py b/scripts/config_mapping/lifecycle_config.py index 1ee449102a..eaa39177e0 100644 --- a/scripts/config_mapping/lifecycle_config.py +++ b/scripts/config_mapping/lifecycle_config.py @@ -130,6 +130,28 @@ def apply_file_state_defaults(ready_condition): ready_condition["file_state"] = {**merged} +UINT32_MAX = 0xFFFFFFFF + + +def sec_to_ms(sec: float) -> int: + """Convert a duration in seconds (float) to integer milliseconds. + + Raises ValueError if the value is negative, overflows a uint32, or is a + sub-millisecond value that would silently round down to 0ms. + """ + if sec < 0: + raise ValueError(f"Negative time value {sec} seconds is not supported") + ms = sec * 1000 + if ms > UINT32_MAX: + raise ValueError( + f"Time value {sec} seconds exceeds maximum representable milliseconds" + ) + result = int(ms) + if sec > 0 and result == 0: + raise ValueError(f"Sub-millisecond time value {sec} seconds rounds to 0ms") + return result + + def preprocess_defaults(global_defaults, config): """ This function takes the input configuration and fills in any missing fields with default values. @@ -302,20 +324,32 @@ def gen_config(output_dir, config, input_filename): if is_supervised(comp_props["application_profile"]["application_type"]): alive_sup = comp_props["application_profile"].get("alive_supervision", {}) app_profile["alive_supervision"] = { - "reporting_cycle": alive_sup["reporting_cycle"], + "reporting_cycle_ms": sec_to_ms(alive_sup["reporting_cycle"]), "failed_cycles_tolerance": alive_sup["failed_cycles_tolerance"], "min_indications": alive_sup["min_indications"], "max_indications": alive_sup["max_indications"], } + ready_condition = comp_props.get( + "ready_condition", {"process_state": "Running"} + ) + if "file_state" in ready_condition: + file_state = ready_condition["file_state"] + ready_condition = { + **ready_condition, + "file_state": { + "file_path": file_state["file_path"], + "state": file_state["state"], + "polling_interval_ms": sec_to_ms(file_state["polling_interval"]), + }, + } + props = { "binary_name": comp_props.get("binary_name", ""), "application_profile": app_profile, "depends_on": comp_props.get("depends_on", []), "process_arguments": comp_props.get("process_arguments", []), - "ready_condition": comp_props.get( - "ready_condition", {"process_state": "Running"} - ), + "ready_condition": ready_condition, } component["component_properties"] = props @@ -338,8 +372,8 @@ def gen_config(output_dir, config, input_filename): sandbox_out["max_cpu_usage"] = sandbox["max_cpu_usage"] deployment = { - "ready_timeout": depl_cfg["ready_timeout"], - "shutdown_timeout": depl_cfg["shutdown_timeout"], + "ready_timeout_ms": sec_to_ms(depl_cfg["ready_timeout"]), + "shutdown_timeout_ms": sec_to_ms(depl_cfg["shutdown_timeout"]), "bin_dir": depl_cfg["bin_dir"], # Default the working directory to bin_dir (the directory the # executable lives in) when not set explicitly. @@ -358,7 +392,9 @@ def gen_config(output_dir, config, input_filename): restart = rra.get("restart", rra) deployment["ready_recovery_action"] = { "number_of_attempts": restart.get("number_of_attempts", 0), - "delay_before_restart": restart.get("delay_before_restart", 0), + "delay_before_restart_ms": sec_to_ms( + restart.get("delay_before_restart", 0) + ), } if "recovery_action" in depl_cfg: @@ -377,7 +413,7 @@ def gen_config(output_dir, config, input_filename): for rt_name, rt_config in config["run_targets"].items(): rt = { "name": rt_name, - "transition_timeout": rt_config.get("transition_timeout", 3), + "transition_timeout_ms": sec_to_ms(rt_config.get("transition_timeout", 3)), "recovery_action": { "run_target": rt_config.get("recovery_action", {}) .get("switch_run_target", {}) @@ -393,15 +429,18 @@ def gen_config(output_dir, config, input_filename): out["initial_run_target"] = config["initial_run_target"] fallback = config.get("fallback_run_target", {}) - out["fallback_run_target"] = { - key: fallback[key] - for key in ("transition_timeout", "description", "depends_on") - if key in fallback - } + fb_out = {} + if "transition_timeout" in fallback: + fb_out["transition_timeout_ms"] = sec_to_ms(fallback["transition_timeout"]) + if fallback.get("description"): + fb_out["description"] = fallback["description"] + if "depends_on" in fallback and fallback["depends_on"]: + fb_out["depends_on"] = fallback["depends_on"] + out["fallback_run_target"] = fb_out out["alive_supervision"] = { - "evaluation_cycle": config.get("alive_supervision", {}).get( - "evaluation_cycle", 0.5 + "evaluation_cycle_ms": sec_to_ms( + config.get("alive_supervision", {}).get("evaluation_cycle", 0.5) ), } @@ -415,7 +454,7 @@ def gen_config(output_dir, config, input_filename): if watchdog_config and required_watchdog_fields.issubset(watchdog_config.keys()): out["watchdog"] = { "device_file_path": watchdog_config["device_file_path"], - "max_timeout": watchdog_config["max_timeout"], + "max_timeout_ms": sec_to_ms(watchdog_config["max_timeout"]), "deactivate_on_shutdown": watchdog_config["deactivate_on_shutdown"], "require_magic_close": watchdog_config["require_magic_close"], } diff --git a/scripts/config_mapping/tests/full_config_test/expected_output/lm_config_gen.json b/scripts/config_mapping/tests/full_config_test/expected_output/lm_config_gen.json index 16a8645ac0..112e6c5f3b 100644 --- a/scripts/config_mapping/tests/full_config_test/expected_output/lm_config_gen.json +++ b/scripts/config_mapping/tests/full_config_test/expected_output/lm_config_gen.json @@ -10,7 +10,7 @@ "application_type": "Reporting_And_Supervised", "is_self_terminating": false, "alive_supervision": { - "reporting_cycle": 0.5, + "reporting_cycle_ms": 500, "failed_cycles_tolerance": 2, "min_indications": 1, "max_indications": 3 @@ -27,8 +27,8 @@ } }, "deployment_config": { - "ready_timeout": 2.0, - "shutdown_timeout": 3.0, + "ready_timeout_ms": 2000, + "shutdown_timeout_ms": 3000, "bin_dir": "/opt/apps/a", "working_dir": "/var/run/a", "sandbox": { @@ -64,7 +64,7 @@ ], "ready_recovery_action": { "number_of_attempts": 5, - "delay_before_restart": 0.5 + "delay_before_restart_ms": 500 }, "recovery_action": { "run_target": "fallback_run_target" @@ -87,15 +87,15 @@ ], "ready_condition": { "file_state": { + "file_path": "/var/run/b/ready", "state": "Exists", - "polling_interval": 0.01, - "file_path": "/var/run/b/ready" + "polling_interval_ms": 10 } } }, "deployment_config": { - "ready_timeout": 1.0, - "shutdown_timeout": 2.0, + "ready_timeout_ms": 1000, + "shutdown_timeout_ms": 2000, "bin_dir": "/opt/apps/b", "working_dir": "/var/run/apps", "sandbox": { @@ -126,7 +126,7 @@ ], "ready_recovery_action": { "number_of_attempts": 3, - "delay_before_restart": 1.0 + "delay_before_restart_ms": 1000 }, "recovery_action": { "run_target": "fallback_run_target" @@ -148,15 +148,15 @@ "process_arguments": [], "ready_condition": { "file_state": { + "file_path": "/var/run/c/startup.lock", "state": "NotExisting", - "polling_interval": 0.5, - "file_path": "/var/run/c/startup.lock" + "polling_interval_ms": 500 } } }, "deployment_config": { - "ready_timeout": 1.0, - "shutdown_timeout": 2.0, + "ready_timeout_ms": 1000, + "shutdown_timeout_ms": 2000, "bin_dir": "/opt/apps/c", "working_dir": "/var/run/apps", "sandbox": { @@ -189,7 +189,7 @@ ], "ready_recovery_action": { "number_of_attempts": 3, - "delay_before_restart": 1.0 + "delay_before_restart_ms": 1000 }, "recovery_action": { "run_target": "fallback_run_target" @@ -205,7 +205,7 @@ "application_type": "State_Manager", "is_self_terminating": false, "alive_supervision": { - "reporting_cycle": 0.1, + "reporting_cycle_ms": 100, "failed_cycles_tolerance": 0, "min_indications": 0, "max_indications": 10 @@ -218,8 +218,8 @@ } }, "deployment_config": { - "ready_timeout": 1.0, - "shutdown_timeout": 2.0, + "ready_timeout_ms": 1000, + "shutdown_timeout_ms": 2000, "bin_dir": "/opt/apps/sm", "working_dir": "/var/run/apps", "sandbox": { @@ -252,7 +252,7 @@ ], "ready_recovery_action": { "number_of_attempts": 3, - "delay_before_restart": 1.0 + "delay_before_restart_ms": 1000 }, "recovery_action": { "run_target": "fallback_run_target" @@ -263,7 +263,7 @@ "run_targets": [ { "name": "Startup", - "transition_timeout": 3.0, + "transition_timeout_ms": 3000, "recovery_action": { "run_target": "fallback_run_target" }, @@ -274,7 +274,7 @@ }, { "name": "Full", - "transition_timeout": 10.0, + "transition_timeout_ms": 10000, "recovery_action": { "run_target": "fallback_run_target" }, @@ -288,7 +288,7 @@ }, { "name": "Diagnostic", - "transition_timeout": 7.5, + "transition_timeout_ms": 7500, "recovery_action": { "run_target": "fallback_run_target" }, @@ -301,18 +301,18 @@ ], "initial_run_target": "Startup", "fallback_run_target": { - "transition_timeout": 1.5, + "transition_timeout_ms": 1500, "description": "Fallback mode - all non-essential services stopped", "depends_on": [ "state_manager" ] }, "alive_supervision": { - "evaluation_cycle": 0.25 + "evaluation_cycle_ms": 250 }, "watchdog": { "device_file_path": "/dev/watchdog", - "max_timeout": 2, + "max_timeout_ms": 2000, "deactivate_on_shutdown": true, "require_magic_close": false } diff --git a/scripts/config_mapping/tests/minimal_config_test/expected_output/lm_config_gen.json b/scripts/config_mapping/tests/minimal_config_test/expected_output/lm_config_gen.json index 3b5d06403f..172194e30b 100644 --- a/scripts/config_mapping/tests/minimal_config_test/expected_output/lm_config_gen.json +++ b/scripts/config_mapping/tests/minimal_config_test/expected_output/lm_config_gen.json @@ -4,7 +4,7 @@ "run_targets": [ { "name": "Startup", - "transition_timeout": 3, + "transition_timeout_ms": 3000, "recovery_action": { "run_target": "fallback_run_target" } @@ -12,11 +12,9 @@ ], "initial_run_target": "Startup", "fallback_run_target": { - "transition_timeout": 3, - "description": "", - "depends_on": [] + "transition_timeout_ms": 3000 }, "alive_supervision": { - "evaluation_cycle": 0.5 + "evaluation_cycle_ms": 500 } } diff --git a/scripts/config_mapping/tests/smoke_test/expected_output/lm_config_gen.json b/scripts/config_mapping/tests/smoke_test/expected_output/lm_config_gen.json index 70a4325aa6..fb4bf4a1c8 100644 --- a/scripts/config_mapping/tests/smoke_test/expected_output/lm_config_gen.json +++ b/scripts/config_mapping/tests/smoke_test/expected_output/lm_config_gen.json @@ -20,8 +20,8 @@ } }, "deployment_config": { - "ready_timeout": 0.5, - "shutdown_timeout": 0.5, + "ready_timeout_ms": 500, + "shutdown_timeout_ms": 500, "bin_dir": "/opt/scripts", "working_dir": "/opt/scripts", "sandbox": { @@ -54,7 +54,7 @@ ], "ready_recovery_action": { "number_of_attempts": 1, - "delay_before_restart": 0.5 + "delay_before_restart_ms": 500 }, "recovery_action": { "run_target": "Off" @@ -83,8 +83,8 @@ } }, "deployment_config": { - "ready_timeout": 0.5, - "shutdown_timeout": 0.5, + "ready_timeout_ms": 500, + "shutdown_timeout_ms": 500, "bin_dir": "/opt/apps/dlt-daemon", "working_dir": "/opt/apps/dlt-daemon", "sandbox": { @@ -117,7 +117,7 @@ ], "ready_recovery_action": { "number_of_attempts": 1, - "delay_before_restart": 0.5 + "delay_before_restart_ms": 500 }, "recovery_action": { "run_target": "Off" @@ -133,7 +133,7 @@ "application_type": "Reporting_And_Supervised", "is_self_terminating": false, "alive_supervision": { - "reporting_cycle": 0.5, + "reporting_cycle_ms": 500, "failed_cycles_tolerance": 2, "min_indications": 1, "max_indications": 3 @@ -150,8 +150,8 @@ } }, "deployment_config": { - "ready_timeout": 0.5, - "shutdown_timeout": 0.5, + "ready_timeout_ms": 500, + "shutdown_timeout_ms": 500, "bin_dir": "/opt/apps/someip", "working_dir": "/opt/apps/someip", "sandbox": { @@ -184,7 +184,7 @@ ], "ready_recovery_action": { "number_of_attempts": 1, - "delay_before_restart": 0.5 + "delay_before_restart_ms": 500 }, "recovery_action": { "run_target": "Off" @@ -200,7 +200,7 @@ "application_type": "Reporting_And_Supervised", "is_self_terminating": false, "alive_supervision": { - "reporting_cycle": 0.5, + "reporting_cycle_ms": 500, "failed_cycles_tolerance": 2, "min_indications": 1, "max_indications": 3 @@ -220,8 +220,8 @@ } }, "deployment_config": { - "ready_timeout": 0.5, - "shutdown_timeout": 0.5, + "ready_timeout_ms": 500, + "shutdown_timeout_ms": 500, "bin_dir": "/opt/apps/test_app1", "working_dir": "/opt/apps/test_app1", "sandbox": { @@ -254,7 +254,7 @@ ], "ready_recovery_action": { "number_of_attempts": 1, - "delay_before_restart": 0.5 + "delay_before_restart_ms": 500 }, "recovery_action": { "run_target": "Off" @@ -270,7 +270,7 @@ "application_type": "State_Manager", "is_self_terminating": false, "alive_supervision": { - "reporting_cycle": 0.5, + "reporting_cycle_ms": 500, "failed_cycles_tolerance": 2, "min_indications": 1, "max_indications": 3 @@ -289,8 +289,8 @@ } }, "deployment_config": { - "ready_timeout": 0.5, - "shutdown_timeout": 0.5, + "ready_timeout_ms": 500, + "shutdown_timeout_ms": 500, "bin_dir": "/opt/apps/state_manager", "working_dir": "/opt/apps/state_manager", "sandbox": { @@ -323,7 +323,7 @@ ], "ready_recovery_action": { "number_of_attempts": 1, - "delay_before_restart": 0.5 + "delay_before_restart_ms": 500 }, "recovery_action": { "run_target": "Off" @@ -334,7 +334,7 @@ "run_targets": [ { "name": "Startup", - "transition_timeout": 5, + "transition_timeout_ms": 5000, "recovery_action": { "run_target": "fallback_run_target" }, @@ -345,7 +345,7 @@ }, { "name": "Full", - "transition_timeout": 5, + "transition_timeout_ms": 5000, "recovery_action": { "run_target": "fallback_run_target" }, @@ -358,16 +358,15 @@ ], "initial_run_target": "Startup", "fallback_run_target": { - "transition_timeout": 1.5, - "description": "Switching off everything", - "depends_on": [] + "transition_timeout_ms": 1500, + "description": "Switching off everything" }, "alive_supervision": { - "evaluation_cycle": 0.5 + "evaluation_cycle_ms": 500 }, "watchdog": { "device_file_path": "/dev/watchdog", - "max_timeout": 2, + "max_timeout_ms": 2000, "deactivate_on_shutdown": true, "require_magic_close": false } diff --git a/scripts/config_mapping/unit_tests.py b/scripts/config_mapping/unit_tests.py index b8eb8cce71..224e2aff77 100644 --- a/scripts/config_mapping/unit_tests.py +++ b/scripts/config_mapping/unit_tests.py @@ -34,9 +34,37 @@ preprocess_defaults, schema_validation, score_defaults, + sec_to_ms, SCHED_POLICY_MAP, ) +# --------------------------------------------------------------------------- +# sec_to_ms +# --------------------------------------------------------------------------- + + +def test_sec_to_ms_converts_positive_value(): + assert sec_to_ms(1.5) == 1500 + + +def test_sec_to_ms_converts_zero(): + assert sec_to_ms(0.0) == 0 + + +def test_sec_to_ms_rejects_negative_value(): + with pytest.raises(ValueError, match="Negative time value"): + sec_to_ms(-1.0) + + +def test_sec_to_ms_rejects_overflow(): + with pytest.raises(ValueError, match="exceeds maximum representable milliseconds"): + sec_to_ms(5000000.0) + + +def test_sec_to_ms_rejects_sub_millisecond(): + with pytest.raises(ValueError, match="rounds to 0ms"): + sec_to_ms(0.0001) + # --------------------------------------------------------------------------- # preprocess_defaults @@ -849,7 +877,7 @@ def test_gen_config_with_alive_supervision(tmp_path): app_profile = output["components"][0]["component_properties"]["application_profile"] assert "alive_supervision" in app_profile - assert app_profile["alive_supervision"]["reporting_cycle"] == 1.0 + assert app_profile["alive_supervision"]["reporting_cycle_ms"] == 1000 assert app_profile["alive_supervision"]["failed_cycles_tolerance"] == 3 assert app_profile["alive_supervision"]["min_indications"] == 1 assert app_profile["alive_supervision"]["max_indications"] == 5 @@ -915,7 +943,7 @@ def test_gen_config_with_watchdog(tmp_path): assert output["schema_version"] == 1 assert output["watchdog"]["device_file_path"] == "/dev/watchdog0" - assert output["watchdog"]["max_timeout"] == 5 + assert output["watchdog"]["max_timeout_ms"] == 5000 assert output["watchdog"]["deactivate_on_shutdown"] is True assert output["watchdog"]["require_magic_close"] is True @@ -1190,7 +1218,7 @@ def test_gen_config_ready_recovery_action(tmp_path): rra = output["components"][0]["deployment_config"]["ready_recovery_action"] assert rra["number_of_attempts"] == 3 - assert rra["delay_before_restart"] == 5 + assert rra["delay_before_restart_ms"] == 5000 ## TODO