#include #include "clock_model.h" using namespace roro; void setUp() {} void tearDown() {} static const char* kBrussels = "CET-1CEST,M3.5.0,M10.5.0/3"; static const int64_t k2026_07_01_1200Z = 1782907200; static const int64_t k2026_01_15_1200Z = 1768478400; void test_clock_is_unset_until_a_source_sets_it() { ClockModel c; TEST_ASSERT_FALSE(c.isSet()); TEST_ASSERT_EQUAL(static_cast(TimeSource::None), static_cast(c.source())); } void test_time_advances_with_uptime_after_being_set() { ClockModel c; TEST_ASSERT_TRUE(c.set(k2026_07_01_1200Z, TimeSource::Ntp, 5000)); TEST_ASSERT_TRUE(c.isSet()); TEST_ASSERT_EQUAL_INT64(k2026_07_01_1200Z + 10, c.utcNow(15000)); } void test_lower_priority_source_does_not_override() { ClockModel c; c.set(k2026_07_01_1200Z, TimeSource::Ntp, 0); TEST_ASSERT_FALSE(c.set(k2026_07_01_1200Z + 500, TimeSource::Mesh, 0)); TEST_ASSERT_EQUAL_INT64(k2026_07_01_1200Z, c.utcNow(0)); } void test_equal_or_higher_priority_source_overrides() { ClockModel c; c.set(k2026_07_01_1200Z, TimeSource::Mesh, 0); TEST_ASSERT_TRUE(c.set(k2026_07_01_1200Z + 1, TimeSource::Mesh, 0)); TEST_ASSERT_TRUE(c.set(k2026_07_01_1200Z + 2, TimeSource::Gnss, 0)); TEST_ASSERT_EQUAL(static_cast(TimeSource::Gnss), static_cast(c.source())); } void test_utc_now_survives_millis_wraparound() { ClockModel c; c.set(k2026_07_01_1200Z, TimeSource::Ntp, 0xFFFFFFFFu - 999); TEST_ASSERT_EQUAL_INT64(k2026_07_01_1200Z + 2, c.utcNow(1000)); } void test_relative_age_formatting() { TEST_ASSERT_EQUAL_STRING("now", ClockModel::formatAge(0).c_str()); TEST_ASSERT_EQUAL_STRING("now", ClockModel::formatAge(59).c_str()); TEST_ASSERT_EQUAL_STRING("1 min ago", ClockModel::formatAge(60).c_str()); TEST_ASSERT_EQUAL_STRING("59 min ago", ClockModel::formatAge(3599).c_str()); TEST_ASSERT_EQUAL_STRING("1 h ago", ClockModel::formatAge(3600).c_str()); TEST_ASSERT_EQUAL_STRING("23 h ago", ClockModel::formatAge(86399).c_str()); TEST_ASSERT_EQUAL_STRING("2 d ago", ClockModel::formatAge(2 * 86400).c_str()); } void test_local_time_in_brussels_summer_and_winter() { ClockModel::applyTimezone(kBrussels); TEST_ASSERT_EQUAL_STRING("14:00", ClockModel::formatLocalTime(k2026_07_01_1200Z).c_str()); TEST_ASSERT_EQUAL_STRING("13:00", ClockModel::formatLocalTime(k2026_01_15_1200Z).c_str()); } int main() { UNITY_BEGIN(); RUN_TEST(test_clock_is_unset_until_a_source_sets_it); RUN_TEST(test_time_advances_with_uptime_after_being_set); RUN_TEST(test_lower_priority_source_does_not_override); RUN_TEST(test_equal_or_higher_priority_source_overrides); RUN_TEST(test_utc_now_survives_millis_wraparound); RUN_TEST(test_relative_age_formatting); RUN_TEST(test_local_time_in_brussels_summer_and_winter); return UNITY_END(); }