#include #include #include "raid/core/types.hpp" #include "raid/core/error.hpp" #include "raid/core/hash.hpp" #include "raid/core/rng.hpp" #include "raid/core/log.hpp" #include "raid/core/thread_pool.hpp" #include using namespace raid; TEST_CASE("Date round trips and weekdays", "[core]") { Date d = Date::from_ymd(2024, 3, 11); auto y = d.ymd(); CHECK(y.year == 2024); CHECK(y.month == 3); CHECK(y.day == 11); CHECK(d.weekday() == 1); // Monday CHECK(Date::from_ymd(1970, 1, 1).days == 0); CHECK(Date::from_ymd(1970, 1, 1).weekday() == 4); CHECK(date_from_iso("2000-02-29").iso() == "2000-02-29"); CHECK(Date::from_ymd(2026, 11, 2).weekday() == 1); } TEST_CASE("Timestamp ISO parsing", "[core]") { CHECK(timestamp_from_iso("2024-03-08T09:00:00Z").us == 1709888400000000LL); CHECK(timestamp_from_iso("2024-03-08T04:00:00-05:00").us == 1709888400000000LL); CHECK(timestamp_from_iso("2024-03-08T09:00:00.250000+00:00").us == 1709888400250000LL); CHECK(timestamp_iso(Timestamp(1709888400000000LL)) == "2024-03-08T09:00:00.000000Z"); CHECK_THROWS_AS(timestamp_from_iso("2024-13-01"), RaidError); } TEST_CASE("SHA-256 known answers", "[core]") { CHECK(Sha256::of("") == "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"); CHECK(Sha256::of("abc") == "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"); std::string big(1000, 'a'); Sha256 h; for (int i = 0; i < 1000; ++i) h.update(big); CHECK(h.hex() == "cdc76e5c9914fb9281a1c7e284d73e67f1809a48a497200e046d39ccc7112cd0"); } TEST_CASE("RNG determinism and moments", "[core]") { Rng a(42, 1), b(42, 1), c(42, 2); CHECK(a.next_u64() == b.next_u64()); CHECK(a.next_u64() != c.next_u64()); Rng r(7, 0); double s = 0, s2 = 0; const int n = 200000; for (int i = 0; i < n; ++i) { double z = r.normal(); s += z; s2 += z * z; } CHECK_THAT(s / n, Catch::Matchers::WithinAbs(0.0, 0.01)); CHECK_THAT(s2 / n, Catch::Matchers::WithinAbs(1.0, 0.02)); double st = 0; for (int i = 0; i < n; ++i) { double z = r.student_t(5.0); st += z * z; } CHECK_THAT(st / n, Catch::Matchers::WithinAbs(5.0 / 3.0, 0.05)); } TEST_CASE("Log redaction hides keys", "[core]") { CHECK(log::redact("Authorization: Bearer fd_abc123.SECRET") == "Authorization: Bearer "); CHECK(log::redact("url?userid=XYZ&x=1") == "url?userid=&x=1"); CHECK(log::redact("key fd_abc.def inside") == "key inside"); } TEST_CASE("Thread pool parallel_for covers the range once and propagates exceptions", "[core]") { ThreadPool p(4); std::atomic acc{0}; p.parallel_for(100000, [&](usize b, usize e) { long s = 0; for (usize i = b; i < e; ++i) s += static_cast(i); acc += s; }); CHECK(acc.load() == 4999950000L); CHECK_THROWS_AS(p.parallel_for(10, [](usize, usize) { throw RaidError(ErrorCode::numerical, "boom"); }), RaidError); }