mirror of
https://github.com/PerMalmberg/libcron.git
synced 2025-07-24 19:23:18 -05:00
Work on DST handling.
This commit is contained in:
@@ -15,4 +15,9 @@ add_executable(
|
||||
CronDataTest.cpp
|
||||
CronScheduleTest.cpp CronTest.cpp)
|
||||
|
||||
target_link_libraries(${PROJECT_NAME} libcron)
|
||||
target_link_libraries(${PROJECT_NAME} libcron)
|
||||
|
||||
set_target_properties(${PROJECT_NAME} PROPERTIES
|
||||
ARCHIVE_OUTPUT_DIRECTORY "${OUTPUT_LOCATION}"
|
||||
LIBRARY_OUTPUT_DIRECTORY "${OUTPUT_LOCATION}"
|
||||
RUNTIME_OUTPUT_DIRECTORY "${OUTPUT_LOCATION}")
|
@@ -19,190 +19,260 @@ std::string create_schedule_expiring_in(std::chrono::system_clock::time_point no
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
SCENARIO("Adding a task")
|
||||
{
|
||||
GIVEN("A Cron instance with no task")
|
||||
{
|
||||
Cron c;
|
||||
auto expired = false;
|
||||
|
||||
THEN("Starts with no task")
|
||||
{
|
||||
REQUIRE(c.count() == 0);
|
||||
}
|
||||
|
||||
WHEN("Adding a task that runs every second")
|
||||
{
|
||||
REQUIRE(c.add_schedule("A task", "* * * * * ?",
|
||||
[&expired]()
|
||||
{
|
||||
expired = true;
|
||||
})
|
||||
);
|
||||
|
||||
THEN("Count is 1 and task was not expired two seconds ago")
|
||||
{
|
||||
REQUIRE(c.count() == 1);
|
||||
c.execute_expired_tasks(c.get_clock()->now() - 2s);
|
||||
REQUIRE_FALSE(expired);
|
||||
}
|
||||
AND_THEN("Task is expired when calculating based on current time")
|
||||
{
|
||||
c.execute_expired_tasks();
|
||||
THEN("Task is expired")
|
||||
{
|
||||
REQUIRE(expired);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SCENARIO("Adding a task that expires in the future")
|
||||
{
|
||||
GIVEN("A Cron instance with task expiring in 3 seconds")
|
||||
{
|
||||
auto expired = false;
|
||||
|
||||
Cron c;
|
||||
REQUIRE(c.add_schedule("A task", create_schedule_expiring_in(c.get_clock()->now(), hours{0}, minutes{0}, seconds{3}),
|
||||
[&expired]()
|
||||
{
|
||||
expired = true;
|
||||
})
|
||||
);
|
||||
|
||||
THEN("Not yet expired")
|
||||
{
|
||||
REQUIRE_FALSE(expired);
|
||||
}
|
||||
AND_WHEN("When waiting one second")
|
||||
{
|
||||
std::this_thread::sleep_for(1s);
|
||||
c.execute_expired_tasks();
|
||||
THEN("Task has not yet expired")
|
||||
{
|
||||
REQUIRE_FALSE(expired);
|
||||
}
|
||||
}
|
||||
AND_WHEN("When waiting three seconds")
|
||||
{
|
||||
std::this_thread::sleep_for(3s);
|
||||
c.execute_expired_tasks();
|
||||
THEN("Task has expired")
|
||||
{
|
||||
REQUIRE(expired);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SCENARIO("Task priority")
|
||||
{
|
||||
GIVEN("A Cron instance with two tasks expiring in 3 and 5 seconds, added in 'reverse' order")
|
||||
{
|
||||
auto _3_second_expired = 0;
|
||||
auto _5_second_expired = 0;
|
||||
|
||||
|
||||
Cron c;
|
||||
REQUIRE(c.add_schedule("Five", create_schedule_expiring_in(c.get_clock()->now(), hours{0}, minutes{0}, seconds{5}),
|
||||
[&_5_second_expired]()
|
||||
{
|
||||
_5_second_expired++;
|
||||
})
|
||||
);
|
||||
|
||||
REQUIRE(c.add_schedule("Three", create_schedule_expiring_in(c.get_clock()->now(), hours{0}, minutes{0}, seconds{3}),
|
||||
[&_3_second_expired]()
|
||||
{
|
||||
_3_second_expired++;
|
||||
})
|
||||
);
|
||||
|
||||
THEN("Not yet expired")
|
||||
{
|
||||
REQUIRE_FALSE(_3_second_expired);
|
||||
REQUIRE_FALSE(_5_second_expired);
|
||||
}
|
||||
|
||||
WHEN("Waiting 1 seconds")
|
||||
{
|
||||
std::this_thread::sleep_for(1s);
|
||||
c.execute_expired_tasks();
|
||||
|
||||
THEN("Task has not yet expired")
|
||||
{
|
||||
REQUIRE(_3_second_expired == 0);
|
||||
REQUIRE(_5_second_expired == 0);
|
||||
}
|
||||
}
|
||||
AND_WHEN("Waiting 3 seconds")
|
||||
{
|
||||
std::this_thread::sleep_for(3s);
|
||||
c.execute_expired_tasks();
|
||||
|
||||
THEN("3 second task has expired")
|
||||
{
|
||||
REQUIRE(_3_second_expired == 1);
|
||||
REQUIRE(_5_second_expired == 0);
|
||||
}
|
||||
}
|
||||
AND_WHEN("Waiting 5 seconds")
|
||||
{
|
||||
std::this_thread::sleep_for(5s);
|
||||
c.execute_expired_tasks();
|
||||
|
||||
THEN("3 and 5 second task has expired")
|
||||
{
|
||||
REQUIRE(_3_second_expired == 1);
|
||||
REQUIRE(_5_second_expired == 1);
|
||||
}
|
||||
}
|
||||
AND_WHEN("Waiting based on the time given by the Cron instance")
|
||||
{
|
||||
std::this_thread::sleep_for(c.time_until_next());
|
||||
c.execute_expired_tasks();
|
||||
|
||||
THEN("3 second task has expired")
|
||||
{
|
||||
REQUIRE(_3_second_expired == 1);
|
||||
REQUIRE(_5_second_expired == 0);
|
||||
}
|
||||
}
|
||||
AND_WHEN("Waiting based on the time given by the Cron instance")
|
||||
{
|
||||
std::this_thread::sleep_for(c.time_until_next());
|
||||
REQUIRE(c.execute_expired_tasks() == 1);
|
||||
|
||||
std::this_thread::sleep_for(c.time_until_next());
|
||||
REQUIRE(c.execute_expired_tasks() == 1);
|
||||
|
||||
THEN("3 and 5 second task has each expired once")
|
||||
{
|
||||
REQUIRE(_3_second_expired == 1);
|
||||
REQUIRE(_5_second_expired == 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//SCENARIO("Clock changes")
|
||||
//SCENARIO("Adding a task")
|
||||
//{
|
||||
// GIVEN("A Cron instance with a single task expiring in 4h")
|
||||
// GIVEN("A Cron instance with no task")
|
||||
// {
|
||||
// Cron c;
|
||||
// auto clock = c.get_clock();
|
||||
// system_clock::time_point time_from_task;
|
||||
// auto now = clock->now();
|
||||
// REQUIRE(c.add_schedule("Task", create_schedule_expiring_in(now, hours{4}, minutes{0}, seconds{0}),
|
||||
// [clock, &time_from_task]()
|
||||
// Cron<> c;
|
||||
// auto expired = false;
|
||||
//
|
||||
// THEN("Starts with no task")
|
||||
// {
|
||||
// REQUIRE(c.count() == 0);
|
||||
// }
|
||||
//
|
||||
// WHEN("Adding a task that runs every second")
|
||||
// {
|
||||
// REQUIRE(c.add_schedule("A task", "* * * * * ?",
|
||||
// [&expired]()
|
||||
// {
|
||||
// expired = true;
|
||||
// })
|
||||
// );
|
||||
//
|
||||
// THEN("Count is 1 and task was not expired two seconds ago")
|
||||
// {
|
||||
// REQUIRE(c.count() == 1);
|
||||
// c.tick(c.get_clock().now() - 2s);
|
||||
// REQUIRE_FALSE(expired);
|
||||
// }
|
||||
// AND_THEN("Task is expired when calculating based on current time")
|
||||
// {
|
||||
// c.tick();
|
||||
// THEN("Task is expired")
|
||||
// {
|
||||
// REQUIRE(expired);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
//
|
||||
//SCENARIO("Adding a task that expires in the future")
|
||||
//{
|
||||
// GIVEN("A Cron instance with task expiring in 3 seconds")
|
||||
// {
|
||||
// auto expired = false;
|
||||
//
|
||||
// Cron<> c;
|
||||
// REQUIRE(c.add_schedule("A task",
|
||||
// create_schedule_expiring_in(c.get_clock().now(), hours{0}, minutes{0}, seconds{3}),
|
||||
// [&expired]()
|
||||
// {
|
||||
// time_from_task = clock->now();
|
||||
// expired = true;
|
||||
// })
|
||||
// );
|
||||
//
|
||||
//
|
||||
// THEN("Not yet expired")
|
||||
// {
|
||||
// REQUIRE_FALSE(expired);
|
||||
// }
|
||||
// AND_WHEN("When waiting one second")
|
||||
// {
|
||||
// std::this_thread::sleep_for(1s);
|
||||
// c.tick();
|
||||
// THEN("Task has not yet expired")
|
||||
// {
|
||||
// REQUIRE_FALSE(expired);
|
||||
// }
|
||||
// }
|
||||
// AND_WHEN("When waiting three seconds")
|
||||
// {
|
||||
// std::this_thread::sleep_for(3s);
|
||||
// c.tick();
|
||||
// THEN("Task has expired")
|
||||
// {
|
||||
// REQUIRE(expired);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
//}
|
||||
//
|
||||
//SCENARIO("Task priority")
|
||||
//{
|
||||
// GIVEN("A Cron instance with two tasks expiring in 3 and 5 seconds, added in 'reverse' order")
|
||||
// {
|
||||
// auto _3_second_expired = 0;
|
||||
// auto _5_second_expired = 0;
|
||||
//
|
||||
//
|
||||
// Cron<> c;
|
||||
// REQUIRE(c.add_schedule("Five",
|
||||
// create_schedule_expiring_in(c.get_clock().now(), hours{0}, minutes{0}, seconds{5}),
|
||||
// [&_5_second_expired]()
|
||||
// {
|
||||
// _5_second_expired++;
|
||||
// })
|
||||
// );
|
||||
//
|
||||
// REQUIRE(c.add_schedule("Three",
|
||||
// create_schedule_expiring_in(c.get_clock().now(), hours{0}, minutes{0}, seconds{3}),
|
||||
// [&_3_second_expired]()
|
||||
// {
|
||||
// _3_second_expired++;
|
||||
// })
|
||||
// );
|
||||
//
|
||||
// THEN("Not yet expired")
|
||||
// {
|
||||
// REQUIRE_FALSE(_3_second_expired);
|
||||
// REQUIRE_FALSE(_5_second_expired);
|
||||
// }
|
||||
//
|
||||
// WHEN("Waiting 1 seconds")
|
||||
// {
|
||||
// std::this_thread::sleep_for(1s);
|
||||
// c.tick();
|
||||
//
|
||||
// THEN("Task has not yet expired")
|
||||
// {
|
||||
// REQUIRE(_3_second_expired == 0);
|
||||
// REQUIRE(_5_second_expired == 0);
|
||||
// }
|
||||
// }
|
||||
// AND_WHEN("Waiting 3 seconds")
|
||||
// {
|
||||
// std::this_thread::sleep_for(3s);
|
||||
// c.tick();
|
||||
//
|
||||
// THEN("3 second task has expired")
|
||||
// {
|
||||
// REQUIRE(_3_second_expired == 1);
|
||||
// REQUIRE(_5_second_expired == 0);
|
||||
// }
|
||||
// }
|
||||
// AND_WHEN("Waiting 5 seconds")
|
||||
// {
|
||||
// std::this_thread::sleep_for(5s);
|
||||
// c.tick();
|
||||
//
|
||||
// THEN("3 and 5 second task has expired")
|
||||
// {
|
||||
// REQUIRE(_3_second_expired == 1);
|
||||
// REQUIRE(_5_second_expired == 1);
|
||||
// }
|
||||
// }
|
||||
// AND_WHEN("Waiting based on the time given by the Cron instance")
|
||||
// {
|
||||
// std::this_thread::sleep_for(c.time_until_next());
|
||||
// c.tick();
|
||||
//
|
||||
// THEN("3 second task has expired")
|
||||
// {
|
||||
// REQUIRE(_3_second_expired == 1);
|
||||
// REQUIRE(_5_second_expired == 0);
|
||||
// }
|
||||
// }
|
||||
// AND_WHEN("Waiting based on the time given by the Cron instance")
|
||||
// {
|
||||
// std::this_thread::sleep_for(c.time_until_next());
|
||||
// REQUIRE(c.tick() == 1);
|
||||
//
|
||||
// std::this_thread::sleep_for(c.time_until_next());
|
||||
// REQUIRE(c.tick() == 1);
|
||||
//
|
||||
// THEN("3 and 5 second task has each expired once")
|
||||
// {
|
||||
// REQUIRE(_3_second_expired == 1);
|
||||
// REQUIRE(_5_second_expired == 1);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
//
|
||||
class TestClock
|
||||
: public ICronClock
|
||||
{
|
||||
public:
|
||||
std::chrono::system_clock::time_point now() const override
|
||||
{
|
||||
return current_time;
|
||||
}
|
||||
|
||||
std::chrono::seconds utc_offset(std::chrono::system_clock::time_point) const override
|
||||
{
|
||||
return 0s;
|
||||
}
|
||||
|
||||
void add(system_clock::duration time)
|
||||
{
|
||||
current_time += time;
|
||||
}
|
||||
|
||||
void set(system_clock::time_point new_time)
|
||||
{
|
||||
current_time = new_time;
|
||||
}
|
||||
|
||||
private:
|
||||
system_clock::time_point current_time = system_clock::now();
|
||||
|
||||
};
|
||||
|
||||
SCENARIO("Clock changes")
|
||||
{
|
||||
GIVEN("A Cron instance with a single task expiring in 4h")
|
||||
{
|
||||
Cron<TestClock> c{};
|
||||
auto& clock = c.get_clock();
|
||||
|
||||
// Midnight
|
||||
clock.set(sys_days{2018_y / 05 / 05});
|
||||
|
||||
// Every hour
|
||||
REQUIRE(c.add_schedule("Clock change task", "0 0 * * * ?", []()
|
||||
{
|
||||
})
|
||||
);
|
||||
|
||||
// https://linux.die.net/man/8/cron
|
||||
|
||||
WHEN("Clock changes <3h forward")
|
||||
{
|
||||
THEN("Task expires accordingly")
|
||||
{
|
||||
REQUIRE(c.tick() == 1);
|
||||
clock.add(minutes{30}); // 00:30
|
||||
REQUIRE(c.tick() == 0);
|
||||
clock.add(minutes{30}); // 01:00
|
||||
REQUIRE(c.tick() == 1);
|
||||
REQUIRE(c.tick() == 0);
|
||||
REQUIRE(c.tick() == 0);
|
||||
clock.add(minutes{30}); // 01:30
|
||||
REQUIRE(c.tick() == 0);
|
||||
clock.add(minutes{15}); // 01:45
|
||||
REQUIRE(c.tick() == 0);
|
||||
clock.add(minutes{15}); // 02:00
|
||||
REQUIRE(c.tick() == 1);
|
||||
}
|
||||
}
|
||||
AND_WHEN("Clock is moved forward >= 3h")
|
||||
{
|
||||
THEN("Task are rescheduled, not run")
|
||||
{
|
||||
REQUIRE(c.tick() == 1);
|
||||
std::cout << c << std::endl;
|
||||
clock.add(hours{3}); // 03:00
|
||||
REQUIRE(c.tick() == 1); // Rescheduled
|
||||
std::cout << c << std::endl;
|
||||
clock.add(minutes{15}); // 03:15
|
||||
REQUIRE(c.tick() == 1);
|
||||
std::cout << c << std::endl;
|
||||
clock.add(minutes{45}); // 04:00
|
||||
REQUIRE(c.tick() == 1);
|
||||
std::cout << c << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user