#include "sched/schedule_window.hpp" #include #include #include "check.hpp" namespace proto = velox::proto; using velox::daemon::sched::window_open; namespace { // A std::tm for a given weekday (0=Sun) and HH:MM on 2026-09-14 (a Monday) + offset days. std::tm at(int wday, int hh, int mm, const char* date = "2026-09-14") { std::tm t{}; t.tm_year = 126; // 2026 // parse "YYYY-MM-DD" int y = 0, mo = 0, d = 0; std::sscanf(date, "%d-%d-%d", &y, &mo, &d); t.tm_year = y - 1900; t.tm_mon = mo - 1; t.tm_mday = d; t.tm_wday = wday; t.tm_hour = hh; t.tm_min = mm; return t; } proto::Schedule periodic(const char* start, const char* stop, std::vector days) { proto::Schedule s; s.enabled = true; s.mode = proto::ScheduleMode::Periodic; if (start) s.startTime = start; if (stop) s.stopTime = stop; if (!days.empty()) s.daysOfWeek = std::move(days); return s; } } // namespace void run() { // --- disabled schedule: always open -------------------------------------------- { proto::Schedule s; s.enabled = false; s.mode = proto::ScheduleMode::Periodic; CHECK(window_open(s, at(3, 3, 0))); std::optional none; CHECK(window_open(none, at(3, 3, 0))); } // --- periodic, weekdays 01:00-06:00 ------------------------------------------- { const auto s = periodic("01:00", "06:00", {1, 2, 3, 4, 5}); // Mon-Fri CHECK(window_open(s, at(1, 2, 30))); // Monday 02:30 -> open CHECK(!window_open(s, at(1, 6, 0))); // 06:00 is the exclusive end CHECK(!window_open(s, at(1, 0, 59))); // before start CHECK(!window_open(s, at(0, 2, 30))); // Sunday -> wrong day CHECK(!window_open(s, at(6, 2, 30))); // Saturday -> wrong day } // --- periodic, no daysOfWeek -> every day ------------------------------------ { const auto s = periodic("09:00", "17:00", {}); CHECK(window_open(s, at(0, 12, 0))); // Sunday still fine CHECK(window_open(s, at(3, 9, 0))); // inclusive start CHECK(!window_open(s, at(3, 17, 0))); } // --- overnight window 22:00-06:00 ------------------------------------------ { const auto s = periodic("22:00", "06:00", {}); CHECK(window_open(s, at(3, 23, 0))); // late evening CHECK(window_open(s, at(3, 2, 0))); // early morning CHECK(!window_open(s, at(3, 12, 0))); // midday -> closed CHECK(window_open(s, at(3, 22, 0))); // inclusive start CHECK(!window_open(s, at(3, 6, 0))); // exclusive end } // --- null stopTime -> until end of day ---------------------------------- { auto s = periodic("20:00", nullptr, {}); CHECK(!window_open(s, at(3, 19, 59))); CHECK(window_open(s, at(3, 20, 0))); CHECK(window_open(s, at(3, 23, 59))); } // --- null startTime -> from midnight ----------------------------------- { auto s = periodic(nullptr, "08:00", {}); CHECK(window_open(s, at(3, 0, 0))); CHECK(window_open(s, at(3, 7, 59))); CHECK(!window_open(s, at(3, 8, 0))); } // --- mode "once": only on the named date ------------------------------ { proto::Schedule s; s.enabled = true; s.mode = proto::ScheduleMode::Once; s.startTime = "10:00"; s.stopTime = "12:00"; s.onceDate = "2026-09-14"; CHECK(window_open(s, at(1, 11, 0, "2026-09-14"))); // right date + time CHECK(!window_open(s, at(1, 9, 0, "2026-09-14"))); // right date, before window CHECK(!window_open(s, at(2, 11, 0, "2026-09-15"))); // wrong date s.daysOfWeek = {2}; // ignored for "once" CHECK(window_open(s, at(1, 11, 0, "2026-09-14"))); } // --- "once" with no onceDate never runs ------------------------------ { proto::Schedule s; s.enabled = true; s.mode = proto::ScheduleMode::Once; CHECK(!window_open(s, at(1, 11, 0))); } } TEST_MAIN()