mirror of
https://github.com/PerMalmberg/libcron.git
synced 2025-02-17 17:59:55 +08:00
215 lines
8.8 KiB
C++
215 lines
8.8 KiB
C++
#include <catch.hpp>
|
|
#include <chrono>
|
|
#include <date/date.h>
|
|
#include <libcron/include/libcron/Cron.h>
|
|
#include <iostream>
|
|
|
|
using namespace libcron;
|
|
using namespace date;
|
|
using namespace std::chrono;
|
|
|
|
system_clock::time_point DT(year_month_day ymd, hours h = hours{0}, minutes m = minutes{0}, seconds s = seconds{0})
|
|
{
|
|
sys_days t = ymd;
|
|
auto sum = t + h + m + s;
|
|
return sum;
|
|
}
|
|
|
|
bool test(const std::string& schedule, system_clock::time_point from,
|
|
const std::vector<system_clock::time_point>& expected_next)
|
|
{
|
|
auto c = CronData::create(schedule);
|
|
bool res = c.is_valid();
|
|
if (res)
|
|
{
|
|
CronSchedule sched(c);
|
|
|
|
auto curr_from = from;
|
|
|
|
for (size_t i = 0; res && i < expected_next.size(); ++i)
|
|
{
|
|
auto result = sched.calculate_from(curr_from);
|
|
auto calculated = std::get<1>(result);
|
|
|
|
res = std::get<0>(result) && calculated == expected_next[i];
|
|
|
|
if (res)
|
|
{
|
|
// Add a second to the time so that we move on to the next expected time
|
|
// and don't get locked on the current one.
|
|
curr_from = expected_next[i] + seconds{1};
|
|
}
|
|
else
|
|
{
|
|
std::cout
|
|
<< "From: " << curr_from << "\n"
|
|
<< "Expected: " << expected_next[i] << "\n"
|
|
<< "Calculated: " << calculated;
|
|
}
|
|
}
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
bool test(const std::string& schedule, system_clock::time_point from, system_clock::time_point expected_next)
|
|
{
|
|
auto c = CronData::create(schedule);
|
|
bool res = c.is_valid();
|
|
if (res)
|
|
{
|
|
CronSchedule sched(c);
|
|
auto result = sched.calculate_from(from);
|
|
auto run_time = std::get<1>(result);
|
|
res &= std::get<0>(result) && expected_next == run_time;
|
|
|
|
if (!res)
|
|
{
|
|
std::cout
|
|
<< "From: " << from << "\n"
|
|
<< "Expected: " << expected_next << "\n"
|
|
<< "Calculated: " << run_time;
|
|
}
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
SCENARIO("Calculating next runtime")
|
|
{
|
|
REQUIRE(test("0 0 * * * ?", DT(2010_y / 1 / 1), DT(2010_y / 1 / 1, hours{0})));
|
|
REQUIRE(test("0 0 * * * ?", DT(2010_y / 1 / 1, hours{0}, minutes{0}, seconds{1}), DT(2010_y / 1 / 1, hours{1})));
|
|
REQUIRE(test("0 0 * * * ?", DT(2010_y / 1 / 1, hours{5}), DT(2010_y / 1 / 1, hours{5})));
|
|
REQUIRE(test("0 0 * * * ?", DT(2010_y / 1 / 1, hours{5}, minutes{1}), DT(2010_y / 1 / 1, hours{6})));
|
|
REQUIRE(test("0 0 * * * ?", DT(2017_y / 12 / 31, hours{23}, minutes{59}, seconds{58}),
|
|
DT(2018_y / 1 / 1, hours{0})));
|
|
REQUIRE(test("0 0 10 * * ?", DT(2017_y / 12 / 31, hours{9}, minutes{59}, seconds{58}),
|
|
DT(2017_y / 12 / 31, hours{10})));
|
|
REQUIRE(test("0 0 10 * * ?", DT(2017_y / 12 / 31, hours{23}, minutes{59}, seconds{58}),
|
|
DT(2018_y / 1 / 1, hours{10})));
|
|
REQUIRE(test("0 0 10 ? FEB *", DT(2017_y / 12 / 31, hours{23}, minutes{59}, seconds{58}),
|
|
DT(2018_y / 2 / 1, hours{10})));
|
|
REQUIRE(test("0 0 10 25 FEB ?", DT(2017_y / 12 / 31, hours{23}, minutes{59}, seconds{58}),
|
|
DT(2018_y / 2 / 25, hours{10})));
|
|
REQUIRE(test("0 0 10 ? FEB 1", DT(2017_y / 12 / 31, hours{23}, minutes{59}, seconds{58}),
|
|
DT(year_month_day{2018_y / 2 / mon[1]}, hours{10})));
|
|
REQUIRE(test("0 0 10 ? FEB 6", DT(2017_y / 12 / 31, hours{23}, minutes{59}, seconds{58}),
|
|
DT(year_month_day{2018_y / 2 / sat[1]}, hours{10})));
|
|
REQUIRE(test("* * ? 10-12 NOV ?", DT(2018_y / 11 / 11, hours{10}, minutes{11}, seconds{12}),
|
|
DT(year_month_day{2018_y / 11 / 11}, hours{10}, minutes{11}, seconds{12})));
|
|
REQUIRE(test("0 0 * 31 APR,MAY ?", DT(2017_y / 6 / 1), DT(2018_y / may / 31)));
|
|
}
|
|
|
|
SCENARIO("Leap year")
|
|
{
|
|
REQUIRE(test("0 0 * 29 FEB *", DT(2015_y / 1 / 1), DT(2016_y / 2 / 29)));
|
|
REQUIRE(test("0 0 * 29 FEB ?", DT(2018_y / 1 / 1), DT(2020_y / 2 / 29)));
|
|
REQUIRE(test("0 0 * 29 FEB ?", DT(2020_y / 2 / 29, hours{15}, minutes{13}, seconds{13}),
|
|
DT(2020_y / 2 / 29, hours{16})));
|
|
}
|
|
|
|
SCENARIO("Multiple calculations")
|
|
{
|
|
WHEN("Every 15 minutes, every 2nd hour")
|
|
{
|
|
REQUIRE(test("0 0/15 0/2 * * ?", DT(2018_y / 1 / 1, hours{13}, minutes{14}, seconds{59}),
|
|
{DT(2018_y / 1 / 1, hours{14}, minutes{00}),
|
|
DT(2018_y / 1 / 1, hours{14}, minutes{15}),
|
|
DT(2018_y / 1 / 1, hours{14}, minutes{30}),
|
|
DT(2018_y / 1 / 1, hours{14}, minutes{45}),
|
|
DT(2018_y / 1 / 1, hours{16}, minutes{00}),
|
|
DT(2018_y / 1 / 1, hours{16}, minutes{15})}));
|
|
}
|
|
|
|
WHEN("Every top of the hour, every 12th hour, during 12 and 13:th July")
|
|
{
|
|
REQUIRE(test("0 0 0/12 12-13 JUL ?", DT(2018_y / 1 / 1),
|
|
{DT(2018_y / 7 / 12, hours{0}),
|
|
DT(2018_y / 7 / 12, hours{12}),
|
|
DT(2018_y / 7 / 13, hours{0}),
|
|
DT(2018_y / 7 / 13, hours{12}),
|
|
DT(2019_y / 7 / 12, hours{0}),
|
|
DT(2019_y / 7 / 12, hours{12})}));
|
|
}
|
|
|
|
WHEN("Every first of the month, 15h, every second month, 22m")
|
|
{
|
|
REQUIRE(test("0 22 15 1 * ?", DT(2018_y / 1 / 1),
|
|
{DT(2018_y / 1 / 1, hours{15}, minutes{22}),
|
|
DT(2018_y / 2 / 1, hours{15}, minutes{22}),
|
|
DT(2018_y / 3 / 1, hours{15}, minutes{22}),
|
|
DT(2018_y / 4 / 1, hours{15}, minutes{22}),
|
|
DT(2018_y / 5 / 1, hours{15}, minutes{22}),
|
|
DT(2018_y / 6 / 1, hours{15}, minutes{22}),
|
|
DT(2018_y / 7 / 1, hours{15}, minutes{22}),
|
|
DT(2018_y / 8 / 1, hours{15}, minutes{22}),
|
|
DT(2018_y / 9 / 1, hours{15}, minutes{22}),
|
|
DT(2018_y / 10 / 1, hours{15}, minutes{22}),
|
|
DT(2018_y / 11 / 1, hours{15}, minutes{22}),
|
|
DT(2018_y / 12 / 1, hours{15}, minutes{22}),
|
|
DT(2019_y / 1 / 1, hours{15}, minutes{22})}));
|
|
}
|
|
|
|
WHEN("“At minute 0 past hour 0 and 12 on day-of-month 1 in every 2nd month")
|
|
{
|
|
REQUIRE(test("0 0 0,12 1 */2 ?", DT(2018_y / 3 / 10, hours{16}, minutes{51}), DT(2018_y / 5 / 1)));
|
|
}
|
|
|
|
WHEN("“At 00:05 in August")
|
|
{
|
|
REQUIRE(test("0 5 0 * 8 ?", DT(2018_y / 3 / 10, hours{16}, minutes{51}),
|
|
{DT(2018_y / 8 / 1, hours{0}, minutes{5}),
|
|
DT(2018_y / 8 / 2, hours{0}, minutes{5})}));
|
|
}
|
|
|
|
WHEN("At 22:00 on every day-of-week from Monday through Friday")
|
|
{
|
|
REQUIRE(test("0 0 22 ? * 1-5", DT(2021_y / 12 / 15, hours{16}, minutes{51}),
|
|
{DT(2021_y / 12 / 15, hours{22}),
|
|
DT(2021_y / 12 / 16, hours{22}),
|
|
DT(2021_y / 12 / 17, hours{22}),
|
|
// 18-19 are weekend
|
|
DT(2021_y / 12 / 20, hours{22}),
|
|
DT(2021_y / 12 / 21, hours{22})}));
|
|
}
|
|
}
|
|
|
|
SCENARIO("Examples from README.md")
|
|
{
|
|
REQUIRE(test("* * * * * ?", DT(2018_y / 03 / 1, hours{12}, minutes{13}, seconds{45}),
|
|
{
|
|
DT(2018_y / 03 / 1, hours{12}, minutes{13}, seconds{45}),
|
|
DT(2018_y / 03 / 1, hours{12}, minutes{13}, seconds{46}),
|
|
DT(2018_y / 03 / 1, hours{12}, minutes{13}, seconds{47}),
|
|
DT(2018_y / 03 / 1, hours{12}, minutes{13}, seconds{48})
|
|
}));
|
|
|
|
REQUIRE(test("0 0 12 * * MON-FRI", DT(2018_y / 03 / 10, hours{12}, minutes{13}, seconds{45}),
|
|
{
|
|
DT(2018_y / 03 / 12, hours{12}),
|
|
DT(2018_y / 03 / 13, hours{12}),
|
|
DT(2018_y / 03 / 14, hours{12}),
|
|
DT(2018_y / 03 / 15, hours{12}),
|
|
DT(2018_y / 03 / 16, hours{12}),
|
|
DT(2018_y / 03 / 19, hours{12})
|
|
}));
|
|
|
|
REQUIRE(test("0 0 12 1/2 * ?", DT(2018_y / 01 / 2, hours{12}, minutes{13}, seconds{45}),
|
|
{
|
|
DT(2018_y / 1 / 3, hours{12}),
|
|
DT(2018_y / 1 / 5, hours{12}),
|
|
DT(2018_y / 1 / 7, hours{12})
|
|
}));
|
|
|
|
REQUIRE(test("0 0 */12 ? * *", DT(2018_y / 8 / 15, hours{13}, minutes{13}, seconds{45}),
|
|
{
|
|
DT(2018_y / 8 / 16, hours{0}),
|
|
DT(2018_y / 8 / 16, hours{12}),
|
|
DT(2018_y / 8 / 17, hours{0})
|
|
}));
|
|
}
|
|
|
|
SCENARIO("Unable to calculate time point")
|
|
{
|
|
REQUIRE_FALSE(test( "0 0 * 31 FEB *", DT(2021_y / 1 / 1), DT(2022_y / 1 / 1)));
|
|
} |