110 lines
4.0 KiB
C++
Executable File
110 lines
4.0 KiB
C++
Executable File
#include <unity.h>
|
|
|
|
#include "CivilTime.h"
|
|
#include "SessionClock.h"
|
|
#include "FakeMonotonicClock.h"
|
|
|
|
using namespace timbre_core;
|
|
|
|
void setUp(void) {}
|
|
void tearDown(void) {}
|
|
|
|
static void test_fixed_utc_minus_six_conversion(void) {
|
|
// 2024-01-01 00:00 UTC is 2023-12-31 18:00 in the fixed local zone.
|
|
const CivilDateTime local = CivilTime::fromUnixSeconds(1704067200LL);
|
|
TEST_ASSERT_EQUAL_INT(2023, local.year);
|
|
TEST_ASSERT_EQUAL_INT(12, local.month);
|
|
TEST_ASSERT_EQUAL_INT(31, local.day);
|
|
TEST_ASSERT_EQUAL_INT(18, local.hour);
|
|
TEST_ASSERT_EQUAL_INT(0, local.minute);
|
|
TEST_ASSERT_EQUAL_INT(0, local.second);
|
|
TEST_ASSERT_EQUAL_INT(0, local.weekday); // Sunday
|
|
}
|
|
|
|
static void test_leap_day_and_round_trip(void) {
|
|
CivilDateTime leap;
|
|
leap.year = 2024;
|
|
leap.month = 2;
|
|
leap.day = 29;
|
|
leap.hour = 12;
|
|
leap.minute = 34;
|
|
leap.second = 56;
|
|
leap.weekday = CivilTime::weekdayForDate(leap.year, leap.month, leap.day);
|
|
|
|
TEST_ASSERT_TRUE(leap.valid());
|
|
std::int64_t epoch = 0;
|
|
TEST_ASSERT_TRUE(CivilTime::toUnixSeconds(leap, epoch));
|
|
const CivilDateTime roundTrip = CivilTime::fromUnixSeconds(epoch);
|
|
TEST_ASSERT_TRUE(roundTrip == leap);
|
|
|
|
TEST_ASSERT_TRUE(CivilTime::isLeapYear(2024));
|
|
TEST_ASSERT_FALSE(CivilTime::isLeapYear(1900));
|
|
TEST_ASSERT_TRUE(CivilTime::isLeapYear(2000));
|
|
TEST_ASSERT_EQUAL_INT(29, CivilTime::daysInMonth(2024, 2));
|
|
TEST_ASSERT_EQUAL_INT(28, CivilTime::daysInMonth(1900, 2));
|
|
}
|
|
|
|
static void test_pre_epoch_values_use_floor_seconds(void) {
|
|
const CivilDateTime local = CivilTime::fromUnixSeconds(-1);
|
|
TEST_ASSERT_EQUAL_INT(1969, local.year);
|
|
TEST_ASSERT_EQUAL_INT(12, local.month);
|
|
TEST_ASSERT_EQUAL_INT(31, local.day);
|
|
// UTC-1 is 17:59:59 in the fixed UTC-06:00 local zone.
|
|
TEST_ASSERT_EQUAL_INT(17, local.hour);
|
|
TEST_ASSERT_EQUAL_INT(59, local.minute);
|
|
TEST_ASSERT_EQUAL_INT(59, local.second);
|
|
|
|
const CivilDateTime invalid{CivilDateTime{2023, 2, 29, 0, 0, 0, 0}};
|
|
TEST_ASSERT_FALSE(invalid.valid());
|
|
}
|
|
|
|
static void test_date_and_minute_keys_are_stable(void) {
|
|
CivilDateTime value{2024, 1, 1, 8, 5, 0, 0};
|
|
const LocalMinuteKey first = LocalMinuteKey::from(value);
|
|
TEST_ASSERT_EQUAL_INT64(20240101LL, first.date);
|
|
TEST_ASSERT_EQUAL_INT(485, first.minuteOfDay);
|
|
|
|
// Keep the same local time so the serial difference is exactly one day.
|
|
CivilDateTime nextDay{2024, 1, 2, 8, 5, 0, 0};
|
|
const LocalMinuteKey second = LocalMinuteKey::from(nextDay);
|
|
TEST_ASSERT_TRUE(first < second);
|
|
TEST_ASSERT_TRUE(first != second);
|
|
TEST_ASSERT_EQUAL_INT64(1LL * 1440LL, second.serial() - first.serial());
|
|
}
|
|
|
|
static void test_session_clock_anchors_first_observation_without_catchup(void) {
|
|
FakeMonotonicClock source(100);
|
|
SessionClock clock(source);
|
|
|
|
const SessionClock::Observation first = clock.observe(1704067200LL);
|
|
TEST_ASSERT_TRUE(first.valid);
|
|
TEST_ASSERT_TRUE(first.firstObservation);
|
|
TEST_ASSERT_EQUAL_UINT64(100, first.monotonicMs);
|
|
|
|
source.advance(5000);
|
|
const SessionClock::Observation later = clock.observe(1704067205LL);
|
|
TEST_ASSERT_TRUE(later.valid);
|
|
TEST_ASSERT_FALSE(later.firstObservation);
|
|
TEST_ASSERT_FALSE(later.monotonicRegression);
|
|
TEST_ASSERT_EQUAL_INT(2023, later.local.year);
|
|
TEST_ASSERT_EQUAL_INT(18, later.local.hour);
|
|
TEST_ASSERT_EQUAL_INT(0, later.local.minute);
|
|
TEST_ASSERT_EQUAL_INT(5, later.local.second);
|
|
|
|
source.advance(1000);
|
|
const SessionClock::Observation tick = clock.tick();
|
|
TEST_ASSERT_TRUE(tick.valid);
|
|
TEST_ASSERT_EQUAL_INT(6, tick.local.second);
|
|
TEST_ASSERT_EQUAL_UINT64(6000, clock.sessionElapsedMs());
|
|
}
|
|
|
|
int main(int, char**) {
|
|
UNITY_BEGIN();
|
|
RUN_TEST(test_fixed_utc_minus_six_conversion);
|
|
RUN_TEST(test_leap_day_and_round_trip);
|
|
RUN_TEST(test_pre_epoch_values_use_floor_seconds);
|
|
RUN_TEST(test_date_and_minute_keys_are_stable);
|
|
RUN_TEST(test_session_clock_anchors_first_observation_without_catchup);
|
|
return UNITY_END();
|
|
}
|