mirror of
https://github.com/PerMalmberg/libcron.git
synced 2025-04-22 00:13:01 -05:00
Validation of days vs. months with more tests.
This commit is contained in:
parent
f7442f6972
commit
cb6a7958e8
@ -1,5 +1,8 @@
|
||||
#include <date.h>
|
||||
#include "CronData.h"
|
||||
|
||||
using namespace date;
|
||||
|
||||
namespace libcron
|
||||
{
|
||||
|
||||
@ -33,6 +36,7 @@ namespace libcron
|
||||
valid &= validate_numeric<DayOfMonth>(match[4], day_of_month);
|
||||
valid &= validate_literal<Months>(match[5], months, month_names);
|
||||
valid &= validate_literal<DayOfWeek>(match[6], day_of_week, day_names);
|
||||
valid &= validate_date_vs_months();
|
||||
}
|
||||
}
|
||||
|
||||
@ -59,11 +63,52 @@ namespace libcron
|
||||
return !s.empty()
|
||||
&& std::find_if(s.begin(), s.end(),
|
||||
[](char c)
|
||||
{ return !std::isdigit(c); }) == s.end();
|
||||
{
|
||||
return !std::isdigit(c);
|
||||
}) == s.end();
|
||||
}
|
||||
|
||||
bool CronData::is_between(int32_t value, int32_t low_limit, int32_t high_limt)
|
||||
{
|
||||
return value >= low_limit && value <= high_limt;
|
||||
}
|
||||
|
||||
bool CronData::validate_date_vs_months() const
|
||||
{
|
||||
bool res = true;
|
||||
|
||||
// Verify that the available dates are possible based on the given months
|
||||
if (months.find(static_cast<Months>(2)) != months.end())
|
||||
{
|
||||
// February allowed, make sure that the allowed date(s) includes 29 and below.
|
||||
res = has_any_in_range(day_of_month, 1, 29);
|
||||
}
|
||||
|
||||
if(res)
|
||||
{
|
||||
// Make sure that if the days contains only 31, at least one month allows that date.
|
||||
if(day_of_month.size() == 1 && day_of_month.find(DayOfMonth::Last) != day_of_month.end())
|
||||
{
|
||||
std::vector<int32_t> months_with_31;
|
||||
for (int32_t i = 1; i <= 12; ++i)
|
||||
{
|
||||
auto ymd = 2018_y / i / date::last;
|
||||
if (unsigned(ymd.day()) == 31)
|
||||
{
|
||||
months_with_31.push_back(i);
|
||||
}
|
||||
}
|
||||
|
||||
res = false;
|
||||
for(size_t i = 0; !res && i < months_with_31.size(); ++i)
|
||||
{
|
||||
auto month = months_with_31[i];
|
||||
res = months.find(static_cast<Months>(month)) != months.end();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return res;
|
||||
}
|
||||
}
|
@ -101,6 +101,18 @@ namespace libcron
|
||||
return static_cast<uint8_t>(t);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static bool has_any_in_range(const std::set<T>& set, uint8_t low, uint8_t high)
|
||||
{
|
||||
bool found = false;
|
||||
for (auto i = low; !found && i <= high; ++i)
|
||||
{
|
||||
found |= set.find(static_cast<T>(i)) != set.end();
|
||||
}
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
void parse(const std::string& cron_expression);
|
||||
@ -134,6 +146,8 @@ namespace libcron
|
||||
|
||||
bool is_between(int32_t value, int32_t low_limit, int32_t high_limit);
|
||||
|
||||
bool validate_date_vs_months() const;
|
||||
|
||||
std::set<Seconds> seconds{};
|
||||
std::set<Minutes> minutes{};
|
||||
std::set<Hours> hours{};
|
||||
|
@ -53,14 +53,10 @@ SCENARIO("Calculating next runtime")
|
||||
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(2018_y / 1 / 1), DT(2020_y / 2 / 29)));
|
||||
}
|
||||
|
||||
SCENARIO("Date that does not exist")
|
||||
{
|
||||
//REQUIRE_FALSE(test("0 0 * 30 FEB *", DT(2018_y / 1 / 1), DT(2020_y / 2 / 29)));
|
||||
}
|
@ -21,17 +21,7 @@ bool has_value_range(const std::set<T>& set, uint8_t low, uint8_t high)
|
||||
return found;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool has_any_in_range(const std::set<T>& set, uint8_t low, uint8_t high)
|
||||
{
|
||||
bool found = false;
|
||||
for (auto i = low; !found && i <= high; ++i)
|
||||
{
|
||||
found |= set.find(static_cast<T>(i)) != set.end();
|
||||
}
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
SCENARIO("Numerical inputs")
|
||||
{
|
||||
@ -159,7 +149,7 @@ SCENARIO("Literal input")
|
||||
auto c = CronData::create("* * * * JAN-MAR,DEC *");
|
||||
REQUIRE(c.is_valid());
|
||||
REQUIRE(has_value_range(c.get_months(), 1, 3));
|
||||
REQUIRE_FALSE(has_any_in_range(c.get_months(), 4, 11));
|
||||
REQUIRE_FALSE(CronData::has_any_in_range(c.get_months(), 4, 11));
|
||||
REQUIRE(has_value_range(c.get_months(), 12, 12));
|
||||
}
|
||||
AND_THEN("Range is valid")
|
||||
@ -167,14 +157,14 @@ SCENARIO("Literal input")
|
||||
auto c = CronData::create("* * * * JAN-MAR,DEC FRI,MON,THU");
|
||||
REQUIRE(c.is_valid());
|
||||
REQUIRE(has_value_range(c.get_months(), 1, 3));
|
||||
REQUIRE_FALSE(has_any_in_range(c.get_months(), 4, 11));
|
||||
REQUIRE_FALSE(CronData::has_any_in_range(c.get_months(), 4, 11));
|
||||
REQUIRE(has_value_range(c.get_months(), 12, 12));
|
||||
REQUIRE(has_value_range(c.get_day_of_week(), 5, 5));
|
||||
REQUIRE(has_value_range(c.get_day_of_week(), 1, 1));
|
||||
REQUIRE(has_value_range(c.get_day_of_week(), 4, 4));
|
||||
REQUIRE_FALSE(has_any_in_range(c.get_day_of_week(), 0, 0));
|
||||
REQUIRE_FALSE(has_any_in_range(c.get_day_of_week(), 2, 3));
|
||||
REQUIRE_FALSE(has_any_in_range(c.get_day_of_week(), 6, 6));
|
||||
REQUIRE_FALSE(CronData::has_any_in_range(c.get_day_of_week(), 0, 0));
|
||||
REQUIRE_FALSE(CronData::has_any_in_range(c.get_day_of_week(), 2, 3));
|
||||
REQUIRE_FALSE(CronData::has_any_in_range(c.get_day_of_week(), 6, 6));
|
||||
}
|
||||
}
|
||||
AND_WHEN("Using backward range")
|
||||
@ -185,7 +175,7 @@ SCENARIO("Literal input")
|
||||
REQUIRE(c.is_valid());
|
||||
REQUIRE(has_value_range(c.get_months(), 4, 12));
|
||||
REQUIRE(has_value_range(c.get_months(), 1, 1));
|
||||
REQUIRE_FALSE(has_any_in_range(c.get_months(), 2, 3));
|
||||
REQUIRE_FALSE(CronData::has_any_in_range(c.get_months(), 2, 3));
|
||||
}
|
||||
AND_THEN("Range is valid")
|
||||
{
|
||||
@ -193,7 +183,7 @@ SCENARIO("Literal input")
|
||||
REQUIRE(c.is_valid());
|
||||
REQUIRE(has_value_range(c.get_day_of_week(), 6, 6)); // Has saturday
|
||||
REQUIRE(has_value_range(c.get_day_of_week(), 0, 3)); // Has sun, mon, tue, wed
|
||||
REQUIRE_FALSE(has_any_in_range(c.get_day_of_week(), 4, 5)); // Does not have thu or fri.
|
||||
REQUIRE_FALSE(CronData::has_any_in_range(c.get_day_of_week(), 4, 5)); // Does not have thu or fri.
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -215,15 +205,25 @@ SCENARIO("Using step syntax")
|
||||
REQUIRE(has_value_range(c.get_months(), 7, 7));
|
||||
REQUIRE(has_value_range(c.get_months(), 9, 9));
|
||||
REQUIRE(has_value_range(c.get_months(), 11, 11));
|
||||
REQUIRE_FALSE(has_any_in_range(c.get_months(), 2, 2));
|
||||
REQUIRE_FALSE(has_any_in_range(c.get_months(), 4, 4));
|
||||
REQUIRE_FALSE(has_any_in_range(c.get_months(), 6, 6));
|
||||
REQUIRE_FALSE(has_any_in_range(c.get_months(), 8, 8));
|
||||
REQUIRE_FALSE(has_any_in_range(c.get_months(), 10, 10));
|
||||
REQUIRE_FALSE(has_any_in_range(c.get_months(), 12, 12));
|
||||
REQUIRE_FALSE(CronData::has_any_in_range(c.get_months(), 2, 2));
|
||||
REQUIRE_FALSE(CronData::has_any_in_range(c.get_months(), 4, 4));
|
||||
REQUIRE_FALSE(CronData::has_any_in_range(c.get_months(), 6, 6));
|
||||
REQUIRE_FALSE(CronData::has_any_in_range(c.get_months(), 8, 8));
|
||||
REQUIRE_FALSE(CronData::has_any_in_range(c.get_months(), 10, 10));
|
||||
REQUIRE_FALSE(CronData::has_any_in_range(c.get_months(), 12, 12));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SCENARIO("Dates that does not exist")
|
||||
{
|
||||
REQUIRE_FALSE(CronData::create("0 0 * 30 FEB *").is_valid());
|
||||
REQUIRE_FALSE(CronData::create("0 0 * 31 APR *").is_valid());
|
||||
}
|
||||
|
||||
SCENARIO("Date that exist in one of the months")
|
||||
{
|
||||
REQUIRE(CronData::create("0 0 * 31 APR,MAY *").is_valid());
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user