diff --git a/ccronexpr.c b/ccronexpr.c index 149bff0..ecb6944 100644 --- a/ccronexpr.c +++ b/ccronexpr.c @@ -72,9 +72,10 @@ typedef enum { #define CRON_INVALID_INSTANT ((time_t) -1) -static const char* DAYS_ARR[] = { "SUN", "MON", "TUE", "WED", "THU", "FRI", "SAT" }; +static const char *DAYS_ARR[] = {"SUN", "MON", "TUE", "WED", "THU", "FRI", "SAT"}; #define CRON_DAYS_ARR_LEN 7 -static const char* MONTHS_ARR[] = { "FOO", "JAN", "FEB", "MAR", "APR", "MAY", "JUN", "JUL", "AUG", "SEP", "OCT", "NOV", "DEC" }; +static const char *MONTHS_ARR[] = {"FOO", "JAN", "FEB", "MAR", "APR", "MAY", "JUN", "JUL", "AUG", "SEP", "OCT", "NOV", + "DEC"}; #define CRON_MONTHS_ARR_LEN 13 #define CRON_MAX_STR_LEN_TO_SPLIT 256 @@ -91,8 +92,11 @@ static const char* MONTHS_ARR[] = { "FOO", "JAN", "FEB", "MAR", "APR", "MAY", "J (abs(num) < 1000000000 ? 9 : 10))))))))) #ifndef _WIN32 + struct tm *gmtime_r(const time_t *timep, struct tm *result); + struct tm *localtime_r(const time_t *timep, struct tm *result); + #endif /* Defining 'cron_mktime' to use use UTC (default) or local time */ @@ -105,10 +109,13 @@ time_t cron_mktime(struct tm* tm) { } #else /* _WIN32 */ #ifndef ANDROID + /* can be hidden in time.h */ -time_t timegm(struct tm* __tp); +time_t timegm(struct tm *__tp); + #endif /* ANDROID */ -time_t cron_mktime(struct tm* tm) { + +time_t cron_mktime(struct tm *tm) { #ifndef ANDROID return timegm(tm); #else /* ANDROID */ @@ -120,6 +127,7 @@ time_t cron_mktime(struct tm* tm) { return result; #endif /* ANDROID */ } + #endif /* _WIN32 */ @@ -127,11 +135,14 @@ time_t cron_mktime(struct tm* tm) { #define cronFree(x) free(x) #define cronMalloc(x) malloc(x) #else -void* cronMalloc(size_t n); -void cronFree(void* p); + +void *cronMalloc(size_t n); + +void cronFree(void *p); + #endif -struct tm* cron_time(time_t* date, struct tm* out) { +struct tm *cron_time(time_t *date, struct tm *out) { #ifdef __MINGW32__ (void)(out); /* To avoid unused warning */ return gmtime(date); @@ -161,7 +172,7 @@ struct tm* cron_time(time_t* date, struct tm* out) { #endif /* CRON_USE_LOCAL_TIME */ -static void free_splitted(char** splitted, size_t len) { +static void free_splitted(char **splitted, size_t len) { size_t i; if (!splitted) return; for (i = 0; i < len; i++) { @@ -172,9 +183,9 @@ static void free_splitted(char** splitted, size_t len) { cronFree(splitted); } -static char* strdupl(const char* str, size_t len) { +static char *strdupl(const char *str, size_t len) { if (!str) return NULL; - char* res = (char*) cronMalloc(len + 1); + char *res = (char *) cronMalloc(len + 1); if (!res) return NULL; memset(res, 0, len + 1); memcpy(res, str, len); @@ -184,7 +195,7 @@ static char* strdupl(const char* str, size_t len) { /** Return next set bit position of bits starting at from_index as integer, set notfound to 1 if none was found. * Interval: [from_index:max[ */ -static unsigned int next_set_bit(const uint8_t* bits, unsigned int max, unsigned int from_index, int* notfound) { +static unsigned int next_set_bit(const uint8_t *bits, unsigned int max, unsigned int from_index, int *notfound) { unsigned int i; if (!bits) { *notfound = 1; @@ -200,7 +211,7 @@ static unsigned int next_set_bit(const uint8_t* bits, unsigned int max, unsigned /// Clear bit in reset byte at position *fi* (*arr* is usually initialized with -1) /// Example: push_to_fields_arr(array, CRON_CF_MINUTE) /// - if used on a completely "new" array, would clear bit 2 (CRON_CF_MINUTE) and return -static void push_to_fields_arr(uint8_t* arr, cron_cf fi) { +static void push_to_fields_arr(uint8_t *arr, cron_cf fi) { if (!arr) { return; } @@ -210,7 +221,7 @@ static void push_to_fields_arr(uint8_t* arr, cron_cf fi) { *arr &= ~(1 << fi); // Unset bit at position fi } -static int add_to_field(struct tm* calendar, cron_cf field, int val) { +static int add_to_field(struct tm *calendar, cron_cf field, int val) { if (!calendar) { return 1; } @@ -247,7 +258,7 @@ static int add_to_field(struct tm* calendar, cron_cf field, int val) { /** * Reset the calendar field (at position field) to 0/1. */ -static int reset(struct tm* calendar, cron_cf field) { +static int reset(struct tm *calendar, cron_cf field) { if (!calendar) { return 1; } @@ -290,14 +301,14 @@ static int reset(struct tm* calendar, cron_cf field) { * @param reset_fields BitArray/BitFlags of CRON_CF_ARR_LEN; each bit is either 1 (no reset) or 0, so it will reset its corresponding field in calendar. * @return 1 if a reset fails, 0 if successful. */ -static int reset_all(struct tm* calendar, uint8_t *reset_fields) { +static int reset_all(struct tm *calendar, uint8_t *reset_fields) { int i; int res = 0; if (!calendar || !reset_fields) { return 1; } for (i = 0; i < CRON_CF_ARR_LEN; i++) { - if ( !(*reset_fields & (1 << i)) ) { // reset when value was already considered "right", so bit was cleared + if (!(*reset_fields & (1 << i))) { // reset when value was already considered "right", so bit was cleared res = reset(calendar, i); if (0 != res) return res; *reset_fields |= 1 << i; // reset field bit here, so it will not be reset on next iteration if necessary @@ -306,7 +317,7 @@ static int reset_all(struct tm* calendar, uint8_t *reset_fields) { return 0; } -static int set_field(struct tm* calendar, cron_cf field, unsigned int val) { +static int set_field(struct tm *calendar, cron_cf field, unsigned int val) { if (!calendar) { return 1; } @@ -356,7 +367,9 @@ static int set_field(struct tm* calendar, cron_cf field, unsigned int val) { * @param res_out Pointer to error code output. (Will be checked by do_next().) * @return Either next trigger value for or 0 if field could not be set in calendar or lower calendar fields could not be reset. (If failing, *res_out will be set to 1 as well.) */ -static unsigned int find_next(const uint8_t* bits, unsigned int max, unsigned int value, struct tm* calendar, cron_cf field, cron_cf nextField, uint8_t* reset_fields, int* res_out) { +static unsigned int +find_next(const uint8_t *bits, unsigned int max, unsigned int value, struct tm *calendar, cron_cf field, + cron_cf nextField, uint8_t *reset_fields, int *res_out) { int notfound = 0; int err = 0; unsigned int next_value = next_set_bit(bits, max, value, ¬found); @@ -394,8 +407,9 @@ static unsigned int find_next(const uint8_t* bits, unsigned int max, unsigned in * @param res_out Integer pointer for passing out error values * @return 0 if an error happened (res_out is also set to 1), next day of month as an unsigned int when successful. */ -static unsigned int handle_w_dom(struct tm* calendar, const uint8_t* days_of_month, unsigned int day_of_month, const uint8_t* w_flags, uint8_t* reset_fields, int* res_out) -{ +static unsigned int +handle_w_dom(struct tm *calendar, const uint8_t *days_of_month, unsigned int day_of_month, const uint8_t *w_flags, + uint8_t *reset_fields, int *res_out) { int err; unsigned int count = 0; unsigned int desired_day, loopday; @@ -411,7 +425,7 @@ static unsigned int handle_w_dom(struct tm* calendar, const uint8_t* days_of_mon loopday = calendar->tm_mday; loopmonth = calendar->tm_mon; // First: Check for w_flags up to 2 days earlier, but at most the 1st (bit 0 (LW) is checked separately) - desired_day = next_set_bit(w_flags, day_of_month, (day_of_month-2 > 0 ? day_of_month-2 : 1), ¬found); + desired_day = next_set_bit(w_flags, day_of_month, (day_of_month - 2 > 0 ? day_of_month - 2 : 1), ¬found); if (!notfound) { // Check first which day is the "desired" day (xxW): // - Is current day a Monday? @@ -432,7 +446,7 @@ static unsigned int handle_w_dom(struct tm* calendar, const uint8_t* days_of_mon *res_out = 1; return 0; } - if ( calendar->tm_wday == 6) { + if (calendar->tm_wday == 6) { // Go 2 days forward for SAT (6); SUN is handled by the 1st case err = add_to_field(calendar, CRON_CF_DAY_OF_MONTH, 2); if (err) { @@ -455,7 +469,7 @@ static unsigned int handle_w_dom(struct tm* calendar, const uint8_t* days_of_mon return 0; } // check if month rolled over - if( loopmonth < calendar->tm_mon ) { + if (loopmonth < calendar->tm_mon) { // check if LW flag is set, if yes, go back to last day of "current month" if (cron_getBit(w_flags, 0)) { err = add_to_field(calendar, CRON_CF_DAY_OF_MONTH, -1); @@ -474,7 +488,8 @@ static unsigned int handle_w_dom(struct tm* calendar, const uint8_t* days_of_mon day_of_month = calendar->tm_mday; } - if ( (cron_getBit(w_flags, day_of_month) && !cron_getBit(days_of_month, day_of_month)) || check_weekday) { // weekday checking required? + if ((cron_getBit(w_flags, day_of_month) && !cron_getBit(days_of_month, day_of_month)) || + check_weekday) { // weekday checking required? // Is it a weekday? If so, great! It can be returned directly, and the following condition will be irrelevant. // Otherwise... if (calendar->tm_wday == 6 || !calendar->tm_wday) { // SAT or SUN @@ -536,8 +551,9 @@ static unsigned int handle_w_dom(struct tm* calendar, const uint8_t* days_of_mon * @param res_out Integer pointer for passing out error values * @return 0 if an error happened (res_out is also set to 1), next day of month as an unsigned int when successful. */ -static unsigned int handle_l_flag(struct tm* calendar, const uint8_t* days_of_month, unsigned int day_of_month, const uint8_t* days_of_week, uint8_t lw_flags, uint8_t* reset_fields, int* res_out) -{ +static unsigned int +handle_l_flag(struct tm *calendar, const uint8_t *days_of_month, unsigned int day_of_month, const uint8_t *days_of_week, + uint8_t lw_flags, uint8_t *reset_fields, int *res_out) { int err; unsigned int count = 0; const unsigned int max = 366; @@ -559,7 +575,7 @@ static unsigned int handle_l_flag(struct tm* calendar, const uint8_t* days_of_mo *res_out = 1; return 0; } - err = set_field(calendar, CRON_CF_MONTH, calendar->tm_mon +1); + err = set_field(calendar, CRON_CF_MONTH, calendar->tm_mon + 1); if (err) { *res_out = 1; return 0; @@ -584,7 +600,7 @@ static unsigned int handle_l_flag(struct tm* calendar, const uint8_t* days_of_mo } // Verify assumed trigger day is not behind startday - if ( (startmonth == (unsigned int) calendar->tm_mon) && (startday > day_of_month) ) { + if ((startmonth == (unsigned int) calendar->tm_mon) && (startday > day_of_month)) { // Startmonth hasn't changed, but trigger day is before initial day reset_all(calendar, reset_fields); while (calendar->tm_mon - startmonth == 0) { @@ -606,18 +622,17 @@ static unsigned int handle_l_flag(struct tm* calendar, const uint8_t* days_of_mo uint8_t offset_mask[4]; for (int i = 0; i < 4; i++) { - memset(&(offset_mask[i]), ~(*(days_of_month+i)), 1); + memset(&(offset_mask[i]), ~(*(days_of_month + i)), 1); } - for (unsigned int loop = 0; loop < max; loop++) - { + for (unsigned int loop = 0; loop < max; loop++) { // Goto first day of following month err = set_field(calendar, CRON_CF_DAY_OF_MONTH, 1); if (err) { *res_out = 1; return 0; } - err = set_field(calendar, CRON_CF_MONTH, calendar->tm_mon +1); + err = set_field(calendar, CRON_CF_MONTH, calendar->tm_mon + 1); if (err) { *res_out = 1; return 0; @@ -633,7 +648,7 @@ static unsigned int handle_l_flag(struct tm* calendar, const uint8_t* days_of_mo // If offset is set, go back offset days from end of month if ((offset = next_set_bit(offset_mask, CRON_MAX_DAYS_OF_MONTH, 1, &err))) { - err = add_to_field(calendar, CRON_CF_DAY_OF_MONTH, - (int) offset); + err = add_to_field(calendar, CRON_CF_DAY_OF_MONTH, -(int) offset); if (err) { *res_out = 1; return 0; @@ -685,13 +700,15 @@ static unsigned int handle_l_flag(struct tm* calendar, const uint8_t* days_of_mo break; } // Finally, check if the planned date has moved in comparison to the start. If so, reset appropriate calendar fields for recalculation - if ( (startday != day_of_month) || (startmonth != (unsigned int) calendar->tm_mon) ) { + if ((startday != day_of_month) || (startmonth != (unsigned int) calendar->tm_mon)) { reset_all(calendar, reset_fields); } return day_of_month; } -static unsigned int find_next_day(struct tm* calendar, const uint8_t* days_of_month, unsigned int day_of_month, const uint8_t* days_of_week, unsigned int day_of_week, uint8_t l_flags, const uint8_t* w_flags, uint8_t* reset_fields, int* res_out) { +static unsigned int +find_next_day(struct tm *calendar, const uint8_t *days_of_month, unsigned int day_of_month, const uint8_t *days_of_week, + unsigned int day_of_week, uint8_t l_flags, const uint8_t *w_flags, uint8_t *reset_fields, int *res_out) { int err; unsigned int count = 0; int notfound = 0; @@ -700,9 +717,8 @@ static unsigned int find_next_day(struct tm* calendar, const uint8_t* days_of_mo day_of_month = handle_l_flag(calendar, days_of_month, day_of_month, days_of_week, l_flags, reset_fields, res_out); if (*res_out) goto return_error; - } - else { - next_set_bit(w_flags, CRON_MAX_DAYS_OF_MONTH , 0, ¬found); // check for W day presence + } else { + next_set_bit(w_flags, CRON_MAX_DAYS_OF_MONTH, 0, ¬found); // check for W day presence if (notfound) { while ((!cron_getBit(days_of_month, day_of_month) || !cron_getBit(days_of_week, day_of_week)) && count++ < max) { @@ -738,7 +754,7 @@ static unsigned int find_next_day(struct tm* calendar, const uint8_t* days_of_mo * @param dot Year of the original time. If no trigger is found even 4 years in the future, an error code (-1) is returned. * @return Error code: 0 on success, other values (e. g. -1) mean failure. */ -static int do_next(const cron_expr* expr, struct tm* calendar, unsigned int dot) { +static int do_next(const cron_expr *expr, struct tm *calendar, unsigned int dot) { int res = 0; uint8_t reset_fields = 0xFE; // First bit (seconds) should always be unset, because if minutes roll over (and seconds didn't), seconds need to be reset as well uint8_t second_reset_fields = 0xFF; // Only used for seconds; they shouldn't reset themselves after finding a match @@ -811,7 +827,8 @@ static int do_next(const cron_expr* expr, struct tm* calendar, unsigned int dot) } month = calendar->tm_mon; /*day already adds one if no day in same month is found*/ - update_month = find_next(expr->months, CRON_MAX_MONTHS-1, month, calendar, CRON_CF_MONTH, CRON_CF_YEAR, &reset_fields, + update_month = find_next(expr->months, CRON_MAX_MONTHS - 1, month, calendar, CRON_CF_MONTH, CRON_CF_YEAR, + &reset_fields, &res); // max-1 because month bits are only set from 0 to 11 if (0 != res) goto return_result; if (month != update_month) { @@ -824,7 +841,7 @@ static int do_next(const cron_expr* expr, struct tm* calendar, unsigned int dot) return res; } -static int to_upper(char* str) { +static int to_upper(char *str) { if (!str) return 1; int i; for (i = 0; '\0' != str[i]; i++) { @@ -833,16 +850,16 @@ static int to_upper(char* str) { return 0; } -static char* to_string(int num) { +static char *to_string(int num) { if (abs(num) >= CRON_MAX_NUM_TO_SRING) return NULL; - char* str = (char*) cronMalloc(CRON_NUM_OF_DIGITS(num) + 1); + char *str = (char *) cronMalloc(CRON_NUM_OF_DIGITS(num) + 1); if (!str) return NULL; int res = sprintf(str, "%d", num); if (res < 0) return NULL; return str; } -static char* str_replace(char *orig, const char *rep, const char *with) { +static char *str_replace(char *orig, const char *rep, const char *with) { char *result; /* the return string */ char *ins; /* the next insert point */ char *tmp; /* varies */ @@ -867,7 +884,7 @@ static char* str_replace(char *orig, const char *rep, const char *with) { ins points to the next occurrence of rep in orig orig points to the remainder of orig after "end of rep" */ - tmp = result = (char*) cronMalloc(strlen(orig) + (len_with - len_rep) * count + 1); + tmp = result = (char *) cronMalloc(strlen(orig) + (len_with - len_rep) * count + 1); if (!result) return NULL; while (count--) { @@ -881,8 +898,8 @@ static char* str_replace(char *orig, const char *rep, const char *with) { return result; } -static unsigned int parse_uint(const char* str, int* errcode) { - char* endptr; +static unsigned int parse_uint(const char *str, int *errcode) { + char *endptr; errno = 0; long int l = strtol(str, &endptr, 10); if (errno == ERANGE || *endptr != '\0' || l < 0 || l > INT_MAX) { @@ -894,16 +911,16 @@ static unsigned int parse_uint(const char* str, int* errcode) { } } -static char** split_str(const char* str, char del, size_t* len_out) { +static char **split_str(const char *str, char del, size_t *len_out) { size_t i; size_t stlen = 0; size_t len = 0; int accum = 0; - char* buf = NULL; - char** res = NULL; + char *buf = NULL; + char **res = NULL; size_t bi = 0; size_t ri = 0; - char* tmp; + char *tmp; if (!str) goto return_error; for (i = 0; '\0' != str[i]; i++) { @@ -927,10 +944,10 @@ static char** split_str(const char* str, char del, size_t* len_out) { } if (0 == len) return NULL; - buf = (char*) cronMalloc(stlen + 1); + buf = (char *) cronMalloc(stlen + 1); if (!buf) goto return_error; memset(buf, 0, stlen + 1); - res = (char**) cronMalloc(len * sizeof(char*)); + res = (char **) cronMalloc(len * sizeof(char *)); if (!res) goto return_error; for (i = 0; i < stlen; i++) { @@ -965,13 +982,13 @@ static char** split_str(const char* str, char del, size_t* len_out) { return NULL; } -static char* replace_ordinals(char* value, const char** arr, size_t arr_len) { +static char *replace_ordinals(char *value, const char **arr, size_t arr_len) { size_t i; - char* cur = value; - char* res = NULL; + char *cur = value; + char *res = NULL; int first = 1; for (i = 0; i < arr_len; i++) { - char* strnum = to_string((int) i); + char *strnum = to_string((int) i); if (!strnum) { if (!first) { cronFree(cur); @@ -994,7 +1011,7 @@ static char* replace_ordinals(char* value, const char** arr, size_t arr_len) { return res; } -static int has_char(char* str, char ch) { +static int has_char(char *str, char ch) { size_t i; size_t len = 0; if (!str) return 0; @@ -1008,12 +1025,11 @@ static int has_char(char* str, char ch) { static int hash_seed = 0; static cron_custom_hash_fn fn = NULL; -void cron_init_hash(int seed) -{ +void cron_init_hash(int seed) { hash_seed = seed; } -void cron_init_custom_hash_fn(cron_custom_hash_fn func) -{ + +void cron_init_custom_hash_fn(cron_custom_hash_fn func) { fn = func; } @@ -1029,8 +1045,8 @@ void cron_init_custom_hash_fn(cron_custom_hash_fn func) * @param error Error string in which error descriptions will be stored, if they happen. Just needs to be a const char** pointer. (See usage of get_range) * @return New char* with replaced H, to be used instead of field. */ -static char* replace_hashed(char* field, unsigned int n, unsigned int min, unsigned int max, cron_custom_hash_fn hashFn, const char** error) -{ +static char *replace_hashed(char *field, unsigned int n, unsigned int min, unsigned int max, cron_custom_hash_fn hashFn, + const char **error) { unsigned int i = 0; unsigned int value; char *newField = NULL; @@ -1047,8 +1063,7 @@ static char* replace_hashed(char* field, unsigned int n, unsigned int min, unsig // Generate random value if (hashFn) { value = hashFn(hash_seed, n); - } - else { + } else { int newSeed = rand(); srand(hash_seed); while (n >= i++) { @@ -1057,12 +1072,12 @@ static char* replace_hashed(char* field, unsigned int n, unsigned int min, unsig srand(newSeed); } // ensure value is below max... - value %= max-min; + value %= max - min; // and above min value += min; // Check if a custom range is present, and get rid of it - if ( has_char(field, '(') ) { + if (has_char(field, '(')) { sscanf(field, "H(%5[-0123456789])", innerString); sprintf(customRemover, "(%s)", innerString); field = str_replace(field, customRemover, NULL); @@ -1083,10 +1098,10 @@ static char* replace_hashed(char* field, unsigned int n, unsigned int min, unsig return newField; } -static unsigned int* get_range(char* field, unsigned int min, unsigned int max, const char** error) { - char** parts = NULL; +static unsigned int *get_range(char *field, unsigned int min, unsigned int max, const char **error) { + char **parts = NULL; size_t len = 0; - unsigned int* res = (unsigned int*) cronMalloc(2 * sizeof(unsigned int)); + unsigned int *res = (unsigned int *) cronMalloc(2 * sizeof(unsigned int)); if (!res) goto return_error; res[0] = 0; @@ -1144,21 +1159,21 @@ static unsigned int* get_range(char* field, unsigned int min, unsigned int max, return NULL; } -void cron_setBit(uint8_t* rbyte, unsigned int idx) { +void cron_setBit(uint8_t *rbyte, unsigned int idx) { uint8_t j = idx / 8; uint8_t k = idx % 8; rbyte[j] |= (1 << k); } -void cron_delBit(uint8_t* rbyte, unsigned int idx) { +void cron_delBit(uint8_t *rbyte, unsigned int idx) { uint8_t j = idx / 8; uint8_t k = idx % 8; rbyte[j] &= ~(1 << k); } -uint8_t cron_getBit(const uint8_t* rbyte, unsigned int idx) { +uint8_t cron_getBit(const uint8_t *rbyte, unsigned int idx) { uint8_t j = idx / 8; uint8_t k = idx % 8; @@ -1178,12 +1193,12 @@ uint8_t cron_getBit(const uint8_t* rbyte, unsigned int idx) { * @param max Max possible value for current field, not included in interval * @param error String output of error, if one occurred */ -void set_number_hits(const char* value, uint8_t* target, unsigned int min, unsigned int max, const char** error) { +void set_number_hits(const char *value, uint8_t *target, unsigned int min, unsigned int max, const char **error) { size_t i; unsigned int i1; size_t len = 0; - char** fields = split_str(value, ',', &len); + char **fields = split_str(value, ',', &len); if (!fields) { *error = "Comma split error"; goto return_result; @@ -1193,7 +1208,7 @@ void set_number_hits(const char* value, uint8_t* target, unsigned int min, unsig if (!has_char(fields[i], '/')) { /* Not an incrementer so it must be a range (possibly empty) */ - unsigned int* range = get_range(fields[i], min, max, error); + unsigned int *range = get_range(fields[i], min, max, error); if (*error) { if (range) { @@ -1211,13 +1226,13 @@ void set_number_hits(const char* value, uint8_t* target, unsigned int min, unsig } else { size_t len2 = 0; - char** split = split_str(fields[i], '/', &len2); + char **split = split_str(fields[i], '/', &len2); if (len2 != 2) { *error = "Incrementer doesn't have two fields"; free_splitted(split, len2); goto return_result; } - unsigned int* range = get_range(split[0], min, max, error); + unsigned int *range = get_range(split[0], min, max, error); if (*error) { if (range) { cronFree(range); @@ -1258,7 +1273,7 @@ void set_number_hits(const char* value, uint8_t* target, unsigned int min, unsig } static char *replace_h_entry(char *field, unsigned int pos, unsigned int min, const char **error) { - char* has_h = strchr(field, 'H'); + char *has_h = strchr(field, 'H'); if (has_h == NULL) { return field; } @@ -1267,31 +1282,32 @@ static char *replace_h_entry(char *field, unsigned int pos, unsigned int min, co // minBuf is 0xFF to see if it has been altered/read successfully, since 0 is a valid value for it unsigned int minBuf = 0xFF, maxBuf = 0; - if(*(has_h + 1) == '/') { /* H before an iterator */ - sscanf(has_h, "H/%2u", &customMax); // get value of iterator, so it will be used as maximum instead of standard maximum for field + if (*(has_h + 1) == '/') { /* H before an iterator */ + sscanf(has_h, "H/%2u", + &customMax); // get value of iterator, so it will be used as maximum instead of standard maximum for field if (!customMax) { /* iterator might have been specified as an ordinal instead... */ *error = "Hashed: Iterator error"; return field; } } - if ((has_h != field) && (*(has_h - 1) == '/') ) { /* H not allowed as iterator */ + if ((has_h != field) && (*(has_h - 1) == '/')) { /* H not allowed as iterator */ *error = "Hashed: 'H' not allowed as iterator"; return field; } if (*(has_h + 1) == '-' || \ - (has_h != field && *(has_h - 1) == '-') ) { // 'H' not starting field, so may be the end of a range + (has_h != field && *(has_h - 1) == '-')) { // 'H' not starting field, so may be the end of a range *error = "'H' is not allowed for use in ranges"; return field; } // Test if custom Range is specified - if (*(has_h + 1) == '(' ) { + if (*(has_h + 1) == '(') { sscanf(has_h, "H(%2u-%2u)", &minBuf, &maxBuf); - if ( !maxBuf || \ + if (!maxBuf || \ (minBuf == 0xFF) || \ (minBuf > maxBuf) || \ (minBuf < min) || \ // if a customMax is present: Is read maximum bigger than it? (which it shouldn't be) - (customMax ? maxBuf > customMax : 0) + (customMax ? maxBuf > customMax : 0) ) { *error = "'H' custom range error"; return field; @@ -1335,11 +1351,10 @@ static char *replace_h_entry(char *field, unsigned int pos, unsigned int min, co return field; } -static char* check_and_replace_h(char* field, unsigned int pos, unsigned int min, const char** error) -{ - char* has_h = strchr(field, 'H'); +static char *check_and_replace_h(char *field, unsigned int pos, unsigned int min, const char **error) { + char *has_h = strchr(field, 'H'); if (has_h) { - char *accum_field = NULL; + char *accum_field = NULL; char **subfields = NULL; size_t subfields_len = 0; // Check if Field contains ',', if so, split into multiple subfields, and replace in each (with same position no) @@ -1365,7 +1380,7 @@ static char* check_and_replace_h(char* field, unsigned int pos, unsigned int min res_len += res_lens[i]; } // Allocate space for the full string: Result lengths + (result count - 1) for the commas + 1 for '\0' - accum_field = (char *) cronMalloc(res_len + subfields_len ); + accum_field = (char *) cronMalloc(res_len + subfields_len); if (accum_field == NULL) { *error = "Failed to merge 'H' in list"; goto return_error; @@ -1381,8 +1396,9 @@ static char* check_and_replace_h(char* field, unsigned int pos, unsigned int min strncpy(tracking, subfields[i], res_lens[i]); tracking += res_lens[i]; // Don't append comma to last list entry - if (i < subfields_len-1) { - strncpy(tracking, ",", 2); // using 2 to ensure the string ends in '\0', tracking will be set to that char + if (i < subfields_len - 1) { + strncpy(tracking, ",", + 2); // using 2 to ensure the string ends in '\0', tracking will be set to that char tracking += 1; } } @@ -1402,11 +1418,11 @@ static char* check_and_replace_h(char* field, unsigned int pos, unsigned int min return field; } -static void set_months(char* value, uint8_t* targ, const char** error) { +static void set_months(char *value, uint8_t *targ, const char **error) { int err; unsigned int i; - char* replaced = NULL; + char *replaced = NULL; err = to_upper(value); if (err) return; @@ -1430,14 +1446,14 @@ static void set_months(char* value, uint8_t* targ, const char** error) { } } -static void set_days(char* field, uint8_t* targ, int max, const char** error) { +static void set_days(char *field, uint8_t *targ, int max, const char **error) { if (1 == strlen(field) && '?' == field[0]) { field[0] = '*'; } set_number_hits(field, targ, 0, max, error); } -static void set_days_of_month(char* field, uint8_t* targ, const char** error) { +static void set_days_of_month(char *field, uint8_t *targ, const char **error) { /* Days of month start with 1 (in Cron and Calendar) so add one */ set_days(field, targ, CRON_MAX_DAYS_OF_MONTH, error); /* ... and remove it from the front */ @@ -1447,9 +1463,8 @@ static void set_days_of_month(char* field, uint8_t* targ, const char** error) { } -static void l_check(char* field, unsigned int pos, unsigned int* offset, cron_expr* target, const char** error) -{ - char* has_l = strchr(field, 'L'); +static void l_check(char *field, unsigned int pos, unsigned int *offset, cron_expr *target, const char **error) { + char *has_l = strchr(field, 'L'); int err; if (has_l) { @@ -1461,22 +1476,22 @@ static void l_check(char* field, unsigned int pos, unsigned int* offset, cron_ex return; } // Ensure no specific days are set in day of week - if ( (target->days_of_week[0] ^ 0x7f) != 0 ) { + if ((target->days_of_week[0] ^ 0x7f) != 0) { *error = "Cannot set specific days of week if using 'L' in days of month."; return; } // Ensure only 1 day is specified, and W day is not the last in a range or list or iterator of days // Also, char following 'L' has to be either '-', 'W' or '\0' - if ( (has_char(field, ',') || has_char(field, '/')) || \ - !( (*(field+1) == '-') || (*(field+1) == 'W') || (*(field+1) == '\0') ) ) { + if ((has_char(field, ',') || has_char(field, '/')) || \ + !((*(field + 1) == '-') || (*(field + 1) == 'W') || (*(field + 1) == '\0'))) { *error = "L only allowed in combination before an offset or before W in 'day of month' field"; return; } cron_setBit(target->months, CRON_L_DOM_BIT); if (has_char(field, '-')) { - if ( *(has_l+1) == '-' && has_l == field) { + if (*(has_l + 1) == '-' && has_l == field) { // offset is specified, L is starting dom - if(offset) { + if (offset) { *offset = parse_uint(has_l + 2, &err); } else { *error = "Offset found in 'day of month', but no valid pointer given"; @@ -1504,11 +1519,11 @@ static void l_check(char* field, unsigned int pos, unsigned int* offset, cron_ex } break; case CRON_FIELD_DAY_OF_WEEK: { - if ( has_char(field, ',') || has_char(field, '/') || has_char(field, '-')) { + if (has_char(field, ',') || has_char(field, '/') || has_char(field, '-')) { *error = "L only allowed in combination with one day in 'day of week' field"; return; } - if ( (has_l == field) && (strlen(field) == 1) ) { + if ((has_l == field) && (strlen(field) == 1)) { *has_l = '0'; // Only L, so replace with sunday } else { cron_setBit(target->months, CRON_L_DOW_BIT); @@ -1523,11 +1538,10 @@ static void l_check(char* field, unsigned int pos, unsigned int* offset, cron_ex } } -static char* w_check(char* field, cron_expr* target, const char** error) -{ - char* has_w = strchr(field, 'W'); - char* newField = NULL; - char** splitField = NULL; +static char *w_check(char *field, cron_expr *target, const char **error) { + char *has_w = strchr(field, 'W'); + char *newField = NULL; + char **splitField = NULL; size_t len_out = 0; unsigned int w_day = 0; @@ -1535,7 +1549,7 @@ static char* w_check(char* field, cron_expr* target, const char** error) // Only available for dom, so no pos checking needed if (has_w) { - newField = (char *)cronMalloc(sizeof(char) * strlen(field) ); + newField = (char *) cronMalloc(sizeof(char) * strlen(field)); if (!newField) { *error = "w_check: newField malloc error"; goto return_error; @@ -1543,12 +1557,12 @@ static char* w_check(char* field, cron_expr* target, const char** error) memset(newField, 0, sizeof(char) * strlen(field)); char *tracking = newField; // Ensure only 1 day is specified, and W day is not the last in a range or list or iterator of days - if ( has_char(field, '/') || has_char(field, '-')) { + if (has_char(field, '/') || has_char(field, '-')) { *error = "W not allowed in iterators or ranges in 'day of month' field"; goto return_error; } // Ensure no specific days are set in day of week - if ( (target->days_of_week[0] ^ 0x7f) != 0 ) { + if ((target->days_of_week[0] ^ 0x7f) != 0) { *error = "Cannot set specific days of week when using 'W' in days of month."; goto return_error; } @@ -1558,13 +1572,13 @@ static char* w_check(char* field, cron_expr* target, const char** error) goto return_error; } for (size_t i = 0; i < len_out; i++) { - if ( (has_w = strchr(splitField[i], 'W')) ) { + if ((has_w = strchr(splitField[i], 'W'))) { // Ensure nothing follows 'W' if (*(has_w + 1) != '\0') { *error = "If W is used, 'day of month' element needs to end with it"; goto return_error; } - if ( !(strcmp(splitField[i], "LW"))) { + if (!(strcmp(splitField[i], "LW"))) { cron_setBit(target->w_flags, 0); } else { *has_w = '\0'; @@ -1596,12 +1610,11 @@ static char* w_check(char* field, cron_expr* target, const char** error) return field; } -void cron_parse_expr(const char* expression, cron_expr* target, const char** error) -{ - const char* err_local; +void cron_parse_expr(const char *expression, cron_expr *target, const char **error) { + const char *err_local; size_t len = 0; - char** fields = NULL; - char* days_replaced = NULL; + char **fields = NULL; + char *days_replaced = NULL; unsigned int offset = 0; int notfound = 0; if (!error) { @@ -1658,7 +1671,7 @@ void cron_parse_expr(const char* expression, cron_expr* target, const char** err } // Days of month: Ensure L-flag for dow is unset, unless the field is '*' - if ( (strcmp(fields[3], "*") != 0) && (strcmp(fields[3], "?") != 0)) { + if ((strcmp(fields[3], "*") != 0) && (strcmp(fields[3], "?") != 0)) { if (cron_getBit(target->months, CRON_L_DOW_BIT)) { *error = "Cannot specify specific days of month when using 'L' in days of week."; goto return_res; @@ -1675,7 +1688,7 @@ void cron_parse_expr(const char* expression, cron_expr* target, const char** err // If w flags are set, days of month can be empty (e.g. "LW" or "9W") // So parsing has to happen if the field str len > 0, but can be skipped if a W flag was found next_set_bit(target->w_flags, CRON_MAX_DAYS_OF_MONTH, 0, ¬found); - if ( strlen(fields[3]) || notfound ) set_days_of_month(fields[3], target->days_of_month, error); + if (strlen(fields[3]) || notfound) set_days_of_month(fields[3], target->days_of_month, error); if (*error) goto return_res; if (offset) cron_delBit(target->days_of_month, offset); @@ -1688,7 +1701,7 @@ void cron_parse_expr(const char* expression, cron_expr* target, const char** err free_splitted(fields, len); } -time_t cron_next(const cron_expr* expr, time_t date) { +time_t cron_next(const cron_expr *expr, time_t date) { /* The plan: @@ -1710,7 +1723,7 @@ time_t cron_next(const cron_expr* expr, time_t date) { if (!expr) return CRON_INVALID_INSTANT; struct tm calval; memset(&calval, 0, sizeof(struct tm)); - struct tm* calendar = cron_time(&date, &calval); + struct tm *calendar = cron_time(&date, &calval); if (!calendar) return CRON_INVALID_INSTANT; time_t original = cron_mktime(calendar); if (CRON_INVALID_INSTANT == original) return CRON_INVALID_INSTANT; diff --git a/ccronexpr.h b/ccronexpr.h index 2350fdc..c127c7f 100644 --- a/ccronexpr.h +++ b/ccronexpr.h @@ -22,14 +22,16 @@ */ #ifndef CCRONEXPR_H -#define CCRONEXPR_H +#define CCRONEXPR_H #if defined(__cplusplus) && !defined(CRON_COMPILE_AS_CXX) extern "C" { #endif #ifndef ANDROID + #include + #else /* ANDROID */ #include #endif /* ANDROID */ @@ -70,7 +72,7 @@ typedef struct { * must be freed by client using 'cron_expr_free' function. * NULL is returned on error. */ -void cron_parse_expr(const char* expression, cron_expr* target, const char** error); +void cron_parse_expr(const char *expression, cron_expr *target, const char **error); /** * Uses the specified expression to calculate the next 'fire' date after @@ -82,14 +84,16 @@ void cron_parse_expr(const char* expression, cron_expr* target, const char** err * @param date start date to start calculation from * @return next 'fire' date in case of success, '((time_t) -1)' in case of error. */ -time_t cron_next(const cron_expr* expr, time_t date); +time_t cron_next(const cron_expr *expr, time_t date); /** * uint8_t* replace char* for storing hit dates, set_bit and get_bit are used as handlers */ -uint8_t cron_getBit(const uint8_t* rbyte, unsigned int idx); -void cron_setBit(uint8_t* rbyte, unsigned int idx); -void cron_delBit(uint8_t* rbyte, unsigned int idx); +uint8_t cron_getBit(const uint8_t *rbyte, unsigned int idx); + +void cron_setBit(uint8_t *rbyte, unsigned int idx); + +void cron_delBit(uint8_t *rbyte, unsigned int idx); /** * Function for deterministic replacing of 'H' in expression (similar to Jenkins feature) @@ -99,6 +103,7 @@ void cron_delBit(uint8_t* rbyte, unsigned int idx); * returns a hash that is always the same for the same seed and idx */ typedef int (*cron_custom_hash_fn)(int seed, uint8_t idx); + /** * Set seed for 'H' replacement number generation, to keep it deterministic. * With default hash func, it will only be set when a number is generated and reset to a (previously generated) random number after; @@ -106,6 +111,7 @@ typedef int (*cron_custom_hash_fn)(int seed, uint8_t idx); * @param seed The seed to be used */ void cron_init_hash(int seed); + /** * Set a custom hash function to be used for 'H' replacement number generation * @param func A function which can generate pseudo-random numbers based on a seed. @@ -120,11 +126,11 @@ void cron_init_custom_hash_fn(cron_custom_hash_fn func); * * @param expr parsed cron expression to free */ -void cron_expr_free(cron_expr* expr); +void cron_expr_free(cron_expr *expr); #if defined(__cplusplus) && !defined(CRON_COMPILE_AS_CXX) } /* extern "C"*/ #endif -#endif /* CCRONEXPR_H */ +#endif /* CCRONEXPR_H */ diff --git a/ccronexpr_test.c b/ccronexpr_test.c index 54b9f1e..207c1aa 100644 --- a/ccronexpr_test.c +++ b/ccronexpr_test.c @@ -44,7 +44,8 @@ static int cronAllocations = 0; static int cronTotalAllocations = 0; static int maxAlloc = 0; -void* cronMalloc(size_t n) { + +void *cronMalloc(size_t n) { cronAllocations++; cronTotalAllocations++; if (cronAllocations > maxAlloc) { @@ -53,15 +54,18 @@ void* cronMalloc(size_t n) { return malloc(n); } -void cronFree(void* p) { +void cronFree(void *p) { cronAllocations--; free(p); } + #endif #ifndef ANDROID #ifndef _WIN32 -time_t timegm(struct tm* __tp); + +time_t timegm(struct tm *__tp); + #else /* _WIN32 */ static time_t timegm(struct tm* tm) { return _mkgmtime(tm); @@ -79,7 +83,7 @@ static time_t timegm(struct tm * const t) { } #endif -static int crons_equal(cron_expr* cr1, cron_expr* cr2) { +static int crons_equal(cron_expr *cr1, cron_expr *cr2) { unsigned int i; for (i = 0; i < ARRAY_LEN(cr1->seconds); i++) { if (cr1->seconds[i] != cr2->seconds[i]) { @@ -122,40 +126,40 @@ static int crons_equal(cron_expr* cr1, cron_expr* cr2) { int one_dec_num(const char ch) { switch (ch) { - case '0': - return 0; - case '1': - return 1; - case '2': - return 2; - case '3': - return 3; - case '4': - return 4; - case '5': - return 5; - case '6': - return 6; - case '7': - return 7; - case '8': - return 8; - case '9': - return 9; - default: - return -1; + case '0': + return 0; + case '1': + return 1; + case '2': + return 2; + case '3': + return 3; + case '4': + return 4; + case '5': + return 5; + case '6': + return 6; + case '7': + return 7; + case '8': + return 8; + case '9': + return 9; + default: + return -1; } } -int two_dec_num(const char* first) { +int two_dec_num(const char *first) { return one_dec_num(first[0]) * 10 + one_dec_num(first[1]); } /* strptime is not available in msvc */ /* 2012-07-01_09:53:50 */ /* 0123456789012345678 */ -struct tm* poors_mans_strptime(const char* str) { - struct tm* cal = (struct tm*) malloc(sizeof(struct tm)); +struct tm *poors_mans_strptime(const char *str) { + struct tm *cal = (struct tm *) malloc(sizeof(struct tm)); int year; sscanf(str, "%4d", &year); cal->tm_year = year - 1900; @@ -169,8 +173,8 @@ struct tm* poors_mans_strptime(const char* str) { return cal; } -bool check_next(const char* pattern, const char* initial, const char* expected) { - const char* err = NULL; +bool check_next(const char *pattern, const char *initial, const char *expected) { + const char *err = NULL; cron_expr parsed; cron_parse_expr(pattern, &parsed, &err); if (err) { @@ -178,13 +182,13 @@ bool check_next(const char* pattern, const char* initial, const char* expected) return false; } - struct tm* calinit = poors_mans_strptime(initial); + struct tm *calinit = poors_mans_strptime(initial); time_t dateinit = timegm(calinit); - if(-1 == dateinit) return false; + if (-1 == dateinit) return false; time_t datenext = cron_next(&parsed, dateinit); - struct tm* calnext = gmtime(&datenext); + struct tm *calnext = gmtime(&datenext); if (calnext == NULL) return false; - char* buffer = (char*) malloc(21); + char *buffer = (char *) malloc(21); memset(buffer, 0, 21); strftime(buffer, 20, DATE_FORMAT, calnext); if (0 != strcmp(expected, buffer)) { @@ -199,7 +203,7 @@ bool check_next(const char* pattern, const char* initial, const char* expected) return true; } -bool check_same(const char* expr1, const char* expr2) { +bool check_same(const char *expr1, const char *expr2) { cron_expr parsed1; cron_parse_expr(expr1, &parsed1, NULL); cron_expr parsed2; @@ -216,7 +220,7 @@ bool check_same(const char* expr1, const char* expr2) { bool check_calc_invalid() { cron_expr parsed; cron_parse_expr("0 0 0 31 6 *", &parsed, NULL); - struct tm * calinit = poors_mans_strptime("2012-07-01_09:53:50"); + struct tm *calinit = poors_mans_strptime("2012-07-01_09:53:50"); time_t dateinit = timegm(calinit); time_t res = cron_next(&parsed, dateinit); free(calinit); @@ -224,8 +228,8 @@ bool check_calc_invalid() { return true; } -bool check_expr_invalid(const char* expr) { - const char* err = NULL; +bool check_expr_invalid(const char *expr) { + const char *err = NULL; cron_expr test; cron_parse_expr(expr, &test, &err); if (!err) { @@ -235,8 +239,8 @@ bool check_expr_invalid(const char* expr) { return true; } -bool check_expr_valid(const char* expr) { - const char* err = NULL; +bool check_expr_valid(const char *expr) { + const char *err = NULL; cron_expr test; cron_parse_expr(expr, &test, &err); if (err) { @@ -250,241 +254,240 @@ int testing_hash_function(int seed, uint8_t idx) { return seed * idx; } -int fake_custom_hash_function(int seed, uint8_t idx) -{ +int fake_custom_hash_function(int seed, uint8_t idx) { return seed * (idx + 1); } void test_expr() { - assert(check_next("*/15 * 1-4 * * *", "2012-07-01_09:53:50", "2012-07-02_01:00:00")); - assert(check_next("*/15 * 1-4 * * *", "2012-07-01_09:53:00", "2012-07-02_01:00:00")); - assert(check_next("0 */2 1-4 * * *", "2012-07-01_09:00:00", "2012-07-02_01:00:00")); - assert(check_next("* * * * * *", "2012-07-01_09:00:00", "2012-07-01_09:00:01")); - assert(check_next("* * * * * *", "2012-12-01_09:00:58", "2012-12-01_09:00:59")); - assert(check_next("10 * * * * *", "2012-12-01_09:42:09", "2012-12-01_09:42:10")); - assert(check_next("11 * * * * *", "2012-12-01_09:42:10", "2012-12-01_09:42:11")); - assert(check_next("10 * * * * *", "2012-12-01_09:42:10", "2012-12-01_09:43:10")); - assert(check_next("10-15 * * * * *", "2012-12-01_09:42:09", "2012-12-01_09:42:10")); - assert(check_next("10-15 * * * * *", "2012-12-01_21:42:14", "2012-12-01_21:42:15")); - assert(check_next("0 * * * * *", "2012-12-01_21:10:42", "2012-12-01_21:11:00")); - assert(check_next("0 * * * * *", "2012-12-01_21:11:00", "2012-12-01_21:12:00")); - assert(check_next("0 11 * * * *", "2012-12-01_21:10:42", "2012-12-01_21:11:00")); - assert(check_next("0 10 * * * *", "2012-12-01_21:11:00", "2012-12-01_22:10:00")); - assert(check_next("0 0 * * * *", "2012-09-30_11:01:00", "2012-09-30_12:00:00")); - assert(check_next("0 0 * * * *", "2012-09-30_12:00:00", "2012-09-30_13:00:00")); - assert(check_next("0 0 * * * *", "2012-09-10_23:01:00", "2012-09-11_00:00:00")); - assert(check_next("0 0 * * * *", "2012-09-11_00:00:00", "2012-09-11_01:00:00")); - assert(check_next("0 0 0 * * *", "2012-09-01_14:42:43", "2012-09-02_00:00:00")); - assert(check_next("0 0 0 * * *", "2012-09-02_00:00:00", "2012-09-03_00:00:00")); - assert(check_next("* * * 10 * *", "2012-10-09_15:12:42", "2012-10-10_00:00:00")); - assert(check_next("* * * 10 * *", "2012-10-11_15:12:42", "2012-11-10_00:00:00")); - assert(check_next("0 0 0 * * *", "2012-09-30_15:12:42", "2012-10-01_00:00:00")); - assert(check_next("0 0 0 * * *", "2012-10-01_00:00:00", "2012-10-02_00:00:00")); - assert(check_next("0 0 0 * * *", "2012-08-30_15:12:42", "2012-08-31_00:00:00")); - assert(check_next("0 0 0 * * *", "2012-08-31_00:00:00", "2012-09-01_00:00:00")); - assert(check_next("0 0 0 * * *", "2012-10-30_15:12:42", "2012-10-31_00:00:00")); - assert(check_next("0 0 0 * * *", "2012-10-31_00:00:00", "2012-11-01_00:00:00")); - assert(check_next("0 0 0 1 * *", "2012-10-30_15:12:42", "2012-11-01_00:00:00")); - assert(check_next("0 0 0 1 * *", "2012-11-01_00:00:00", "2012-12-01_00:00:00")); - assert(check_next("0 0 0 1 * *", "2010-12-31_15:12:42", "2011-01-01_00:00:00")); - assert(check_next("0 0 0 1 * *", "2011-01-01_00:00:00", "2011-02-01_00:00:00")); - assert(check_next("0 0 0 31 * *", "2011-10-30_15:12:42", "2011-10-31_00:00:00")); - assert(check_next("0 0 0 1 * *", "2011-10-30_15:12:42", "2011-11-01_00:00:00")); - assert(check_next("* * * * * 2", "2010-10-25_15:12:42", "2010-10-26_00:00:00")); - assert(check_next("* * * * * 2", "2010-10-20_15:12:42", "2010-10-26_00:00:00")); - assert(check_next("* * * * * 2", "2010-10-27_15:12:42", "2010-11-02_00:00:00")); - assert(check_next("55 5 * * * *", "2010-10-27_15:04:54", "2010-10-27_15:05:55")); - assert(check_next("55 5 * * * *", "2010-10-27_15:05:55", "2010-10-27_16:05:55")); - assert(check_next("20,40 5 * * * *", "2010-10-27_15:06:30", "2010-10-27_16:05:20")); - assert(check_next("20 6 * * * *", "2010-10-27_15:06:30", "2010-10-27_16:06:20")); - assert(check_next("20 5,7 16 * * *", "2010-10-27_15:06:30", "2010-10-27_16:05:20")); - assert(check_next("20,40 5 16 * * *", "2010-10-27_15:06:30", "2010-10-27_16:05:20")); - assert(check_next("20 5 15,17 28 * *", "2010-10-27_15:06:30", "2010-10-28_15:05:20")); - assert(check_next("20,40 5 15,17 28 * *","2010-10-27_15:06:30", "2010-10-28_15:05:20")); - assert(check_next("55 * 10 * * *", "2010-10-27_09:04:54", "2010-10-27_10:00:55")); - assert(check_next("55 * 10 * * *", "2010-10-27_10:00:55", "2010-10-27_10:01:55")); - assert(check_next("* 5 10 * * *", "2010-10-27_09:04:55", "2010-10-27_10:05:00")); - assert(check_next("* 5 10 * * *", "2010-10-27_10:05:00", "2010-10-27_10:05:01")); - assert(check_next("55 * * 3 * *", "2010-10-02_10:05:54", "2010-10-03_00:00:55")); - assert(check_next("55 * * 3 * *", "2010-10-03_00:00:55", "2010-10-03_00:01:55")); - assert(check_next("* * * 3 11 *", "2010-10-02_14:42:55", "2010-11-03_00:00:00")); - assert(check_next("* * * 3 11 *", "2010-11-03_00:00:00", "2010-11-03_00:00:01")); - assert(check_next("0 0 0 29 2 *", "2007-02-10_14:42:55", "2008-02-29_00:00:00")); - assert(check_next("0 0 0 29 2 *", "2008-02-29_00:00:00", "2012-02-29_00:00:00")); - assert(check_next("0 0 7 ? * MON-FRI", "2009-09-26_00:42:55", "2009-09-28_07:00:00")); - assert(check_next("0 0 7 ? * MON-FRI", "2009-09-28_07:00:00", "2009-09-29_07:00:00")); - assert(check_next("0 30 23 30 1/3 ?", "2010-12-30_00:00:00", "2011-01-30_23:30:00")); - assert(check_next("0 30 23 30 1/3 ?", "2011-01-30_23:30:00", "2011-04-30_23:30:00")); - assert(check_next("0 30 23 30 1/3 ?", "2011-04-30_23:30:00", "2011-07-30_23:30:00")); - assert(check_next("0 0 1 28 * ?", "2022-02-28_02:00:00", "2022-03-28_01:00:00")); - assert(check_next("0 0 0 * 12 ?", "2022-01-01_00:00:00", "2022-12-01_00:00:00")); + assert(check_next("*/15 * 1-4 * * *", "2012-07-01_09:53:50", "2012-07-02_01:00:00")); + assert(check_next("*/15 * 1-4 * * *", "2012-07-01_09:53:00", "2012-07-02_01:00:00")); + assert(check_next("0 */2 1-4 * * *", "2012-07-01_09:00:00", "2012-07-02_01:00:00")); + assert(check_next("* * * * * *", "2012-07-01_09:00:00", "2012-07-01_09:00:01")); + assert(check_next("* * * * * *", "2012-12-01_09:00:58", "2012-12-01_09:00:59")); + assert(check_next("10 * * * * *", "2012-12-01_09:42:09", "2012-12-01_09:42:10")); + assert(check_next("11 * * * * *", "2012-12-01_09:42:10", "2012-12-01_09:42:11")); + assert(check_next("10 * * * * *", "2012-12-01_09:42:10", "2012-12-01_09:43:10")); + assert(check_next("10-15 * * * * *", "2012-12-01_09:42:09", "2012-12-01_09:42:10")); + assert(check_next("10-15 * * * * *", "2012-12-01_21:42:14", "2012-12-01_21:42:15")); + assert(check_next("0 * * * * *", "2012-12-01_21:10:42", "2012-12-01_21:11:00")); + assert(check_next("0 * * * * *", "2012-12-01_21:11:00", "2012-12-01_21:12:00")); + assert(check_next("0 11 * * * *", "2012-12-01_21:10:42", "2012-12-01_21:11:00")); + assert(check_next("0 10 * * * *", "2012-12-01_21:11:00", "2012-12-01_22:10:00")); + assert(check_next("0 0 * * * *", "2012-09-30_11:01:00", "2012-09-30_12:00:00")); + assert(check_next("0 0 * * * *", "2012-09-30_12:00:00", "2012-09-30_13:00:00")); + assert(check_next("0 0 * * * *", "2012-09-10_23:01:00", "2012-09-11_00:00:00")); + assert(check_next("0 0 * * * *", "2012-09-11_00:00:00", "2012-09-11_01:00:00")); + assert(check_next("0 0 0 * * *", "2012-09-01_14:42:43", "2012-09-02_00:00:00")); + assert(check_next("0 0 0 * * *", "2012-09-02_00:00:00", "2012-09-03_00:00:00")); + assert(check_next("* * * 10 * *", "2012-10-09_15:12:42", "2012-10-10_00:00:00")); + assert(check_next("* * * 10 * *", "2012-10-11_15:12:42", "2012-11-10_00:00:00")); + assert(check_next("0 0 0 * * *", "2012-09-30_15:12:42", "2012-10-01_00:00:00")); + assert(check_next("0 0 0 * * *", "2012-10-01_00:00:00", "2012-10-02_00:00:00")); + assert(check_next("0 0 0 * * *", "2012-08-30_15:12:42", "2012-08-31_00:00:00")); + assert(check_next("0 0 0 * * *", "2012-08-31_00:00:00", "2012-09-01_00:00:00")); + assert(check_next("0 0 0 * * *", "2012-10-30_15:12:42", "2012-10-31_00:00:00")); + assert(check_next("0 0 0 * * *", "2012-10-31_00:00:00", "2012-11-01_00:00:00")); + assert(check_next("0 0 0 1 * *", "2012-10-30_15:12:42", "2012-11-01_00:00:00")); + assert(check_next("0 0 0 1 * *", "2012-11-01_00:00:00", "2012-12-01_00:00:00")); + assert(check_next("0 0 0 1 * *", "2010-12-31_15:12:42", "2011-01-01_00:00:00")); + assert(check_next("0 0 0 1 * *", "2011-01-01_00:00:00", "2011-02-01_00:00:00")); + assert(check_next("0 0 0 31 * *", "2011-10-30_15:12:42", "2011-10-31_00:00:00")); + assert(check_next("0 0 0 1 * *", "2011-10-30_15:12:42", "2011-11-01_00:00:00")); + assert(check_next("* * * * * 2", "2010-10-25_15:12:42", "2010-10-26_00:00:00")); + assert(check_next("* * * * * 2", "2010-10-20_15:12:42", "2010-10-26_00:00:00")); + assert(check_next("* * * * * 2", "2010-10-27_15:12:42", "2010-11-02_00:00:00")); + assert(check_next("55 5 * * * *", "2010-10-27_15:04:54", "2010-10-27_15:05:55")); + assert(check_next("55 5 * * * *", "2010-10-27_15:05:55", "2010-10-27_16:05:55")); + assert(check_next("20,40 5 * * * *", "2010-10-27_15:06:30", "2010-10-27_16:05:20")); + assert(check_next("20 6 * * * *", "2010-10-27_15:06:30", "2010-10-27_16:06:20")); + assert(check_next("20 5,7 16 * * *", "2010-10-27_15:06:30", "2010-10-27_16:05:20")); + assert(check_next("20,40 5 16 * * *", "2010-10-27_15:06:30", "2010-10-27_16:05:20")); + assert(check_next("20 5 15,17 28 * *", "2010-10-27_15:06:30", "2010-10-28_15:05:20")); + assert(check_next("20,40 5 15,17 28 * *", "2010-10-27_15:06:30", "2010-10-28_15:05:20")); + assert(check_next("55 * 10 * * *", "2010-10-27_09:04:54", "2010-10-27_10:00:55")); + assert(check_next("55 * 10 * * *", "2010-10-27_10:00:55", "2010-10-27_10:01:55")); + assert(check_next("* 5 10 * * *", "2010-10-27_09:04:55", "2010-10-27_10:05:00")); + assert(check_next("* 5 10 * * *", "2010-10-27_10:05:00", "2010-10-27_10:05:01")); + assert(check_next("55 * * 3 * *", "2010-10-02_10:05:54", "2010-10-03_00:00:55")); + assert(check_next("55 * * 3 * *", "2010-10-03_00:00:55", "2010-10-03_00:01:55")); + assert(check_next("* * * 3 11 *", "2010-10-02_14:42:55", "2010-11-03_00:00:00")); + assert(check_next("* * * 3 11 *", "2010-11-03_00:00:00", "2010-11-03_00:00:01")); + assert(check_next("0 0 0 29 2 *", "2007-02-10_14:42:55", "2008-02-29_00:00:00")); + assert(check_next("0 0 0 29 2 *", "2008-02-29_00:00:00", "2012-02-29_00:00:00")); + assert(check_next("0 0 7 ? * MON-FRI", "2009-09-26_00:42:55", "2009-09-28_07:00:00")); + assert(check_next("0 0 7 ? * MON-FRI", "2009-09-28_07:00:00", "2009-09-29_07:00:00")); + assert(check_next("0 30 23 30 1/3 ?", "2010-12-30_00:00:00", "2011-01-30_23:30:00")); + assert(check_next("0 30 23 30 1/3 ?", "2011-01-30_23:30:00", "2011-04-30_23:30:00")); + assert(check_next("0 30 23 30 1/3 ?", "2011-04-30_23:30:00", "2011-07-30_23:30:00")); + assert(check_next("0 0 1 28 * ?", "2022-02-28_02:00:00", "2022-03-28_01:00:00")); + assert(check_next("0 0 0 * 12 ?", "2022-01-01_00:00:00", "2022-12-01_00:00:00")); // H Tests cron_init_custom_hash_fn(testing_hash_function); cron_init_hash(7); - assert(check_next("H H H H H ?", "2022-05-12_00:00:00", "2022-05-22_14:07:00")); // 0 7 14 22 5 (1) - assert(check_next("H H H H H ?", "2022-06-12_00:00:00", "2023-05-22_14:07:00")); - assert(check_next("H H H ? H H", "2022-05-12_00:00:00", "2022-05-16_14:07:00")); - assert(check_next("H 0 1 * * ?", "2022-05-12_00:00:00", "2022-05-12_01:00:00")); - assert(check_next("H 0,12 1 * * ?", "2022-05-12_01:01:00", "2022-05-12_01:12:00")); - assert(check_next("H 0,H 1 * * ?", "2022-05-12_01:01:00", "2022-05-12_01:07:00")); - assert(check_next("H 0 1/4 * * ?", "2022-05-12_01:01:00", "2022-05-12_05:00:00")); - assert(check_next("H H 1 * * ?", "2022-05-12_00:00:00", "2022-05-12_01:07:00")); + assert(check_next("H H H H H ?", "2022-05-12_00:00:00", "2022-05-22_14:07:00")); // 0 7 14 22 5 (1) + assert(check_next("H H H H H ?", "2022-06-12_00:00:00", "2023-05-22_14:07:00")); + assert(check_next("H H H ? H H", "2022-05-12_00:00:00", "2022-05-16_14:07:00")); + assert(check_next("H 0 1 * * ?", "2022-05-12_00:00:00", "2022-05-12_01:00:00")); + assert(check_next("H 0,12 1 * * ?", "2022-05-12_01:01:00", "2022-05-12_01:12:00")); + assert(check_next("H 0,H 1 * * ?", "2022-05-12_01:01:00", "2022-05-12_01:07:00")); + assert(check_next("H 0 1/4 * * ?", "2022-05-12_01:01:00", "2022-05-12_05:00:00")); + assert(check_next("H H 1 * * ?", "2022-05-12_00:00:00", "2022-05-12_01:07:00")); // H,H is same as H - assert(check_next("H H,H 1 * * ?", "2022-05-12_00:00:00", "2022-05-12_01:07:00")); - assert(check_next("0 H/5 1 * * ?", "2022-05-12_00:00:00", "2022-05-12_01:02:00")); - assert(check_next("0 0 1 1 H/MAY ?", "2022-05-12_00:00:00", "2022-06-01_01:00:00")); - assert(check_next("0 0 1 1 H/MAY ?", "2022-06-12_00:00:00", "2022-11-01_01:00:00")); + assert(check_next("H H,H 1 * * ?", "2022-05-12_00:00:00", "2022-05-12_01:07:00")); + assert(check_next("0 H/5 1 * * ?", "2022-05-12_00:00:00", "2022-05-12_01:02:00")); + assert(check_next("0 0 1 1 H/MAY ?", "2022-05-12_00:00:00", "2022-06-01_01:00:00")); + assert(check_next("0 0 1 1 H/MAY ?", "2022-06-12_00:00:00", "2022-11-01_01:00:00")); // Tests for H in custom range - assert(check_next("0 H(0-5) 1 1 * ?", "2022-06-12_00:00:00", "2022-07-01_01:01:00")); // 0 1 1 1 * * - assert(check_next("0 H,H(0-5) 1 1 * ?", "2022-06-12_00:00:00", "2022-07-01_01:01:00")); // 0 1,1 1 1 * * - assert(check_next("0 H(0-5),H(2-9) 1 1 * ?", "2022-06-12_02:00:00", "2022-07-01_01:01:00")); // 0 1,9 1 1 * * - assert(check_next("0 H(0-5),H(2-9) 1 1 * ?", "2022-07-01_01:01:01", "2022-07-01_01:09:00")); // 0 1,9 1 1 * * - assert(check_next("0 H(0-5),H(2-7) 1 1 * ?", "2022-06-12_02:00:00", "2022-07-01_01:01:00")); // 0 1,3 1 1 * * - assert(check_next("0 H(0-5),H(2-7) 1 1 * ?", "2022-07-01_01:01:01", "2022-07-01_01:03:00")); // 0 1,3 1 1 * * - assert(check_next("0 0 0 H(1-5),H(1-2) * ?", "2022-07-01_01:01:01", "2022-07-02_00:00:00")); // 0 0 0 2,3 * * - assert(check_next("0 0 0 H(1-5),H(1-2) * ?", "2022-07-02_01:01:01", "2022-08-02_00:00:00")); // 0 0 0 2,3 * * - assert(check_next("0 0 1 H(1-9)W * ?","2022-06-12_00:00:00", "2022-07-04_01:00:00")); // Day is 4 - assert(check_next("0 0 1 H(1-9)W * ?","2022-06-01_00:00:00", "2022-06-03_01:00:00")); - assert(check_next("0 0 1 ? * HL", "2022-06-12_00:00:00", "2022-06-27_01:00:00")); - assert(check_next("0 0 1 ? * H(1-6)L", "2022-06-12_00:00:00", "2022-06-25_01:00:00")); + assert(check_next("0 H(0-5) 1 1 * ?", "2022-06-12_00:00:00", "2022-07-01_01:01:00")); // 0 1 1 1 * * + assert(check_next("0 H,H(0-5) 1 1 * ?", "2022-06-12_00:00:00", "2022-07-01_01:01:00")); // 0 1,1 1 1 * * + assert(check_next("0 H(0-5),H(2-9) 1 1 * ?","2022-06-12_02:00:00", "2022-07-01_01:01:00")); // 0 1,9 1 1 * * + assert(check_next("0 H(0-5),H(2-9) 1 1 * ?","2022-07-01_01:01:01", "2022-07-01_01:09:00")); // 0 1,9 1 1 * * + assert(check_next("0 H(0-5),H(2-7) 1 1 * ?","2022-06-12_02:00:00", "2022-07-01_01:01:00")); // 0 1,3 1 1 * * + assert(check_next("0 H(0-5),H(2-7) 1 1 * ?","2022-07-01_01:01:01", "2022-07-01_01:03:00")); // 0 1,3 1 1 * * + assert(check_next("0 0 0 H(1-5),H(1-2) * ?","2022-07-01_01:01:01", "2022-07-02_00:00:00")); // 0 0 0 2,3 * * + assert(check_next("0 0 0 H(1-5),H(1-2) * ?","2022-07-02_01:01:01", "2022-08-02_00:00:00")); // 0 0 0 2,3 * * + assert(check_next("0 0 1 H(1-9)W * ?", "2022-06-12_00:00:00", "2022-07-04_01:00:00")); // Day is 4 + assert(check_next("0 0 1 H(1-9)W * ?", "2022-06-01_00:00:00", "2022-06-03_01:00:00")); + assert(check_next("0 0 1 ? * HL", "2022-06-12_00:00:00", "2022-06-27_01:00:00")); + assert(check_next("0 0 1 ? * H(1-6)L", "2022-06-12_00:00:00", "2022-06-25_01:00:00")); cron_init_hash(42); - assert(check_next("H H H H H ?", "2022-05-12_00:00:00", "2023-01-19_12:42:00")); // 0 42 12(84) 19(126) 1(168) 1(210) - assert(check_next("H H H ? H H", "2022-05-12_00:00:00", "2023-01-02_12:42:00")); - assert(check_next("H 0 1 * * ?", "2022-05-12_00:00:00", "2022-05-12_01:00:00")); - assert(check_next("0 H/10 1 * * ?", "2022-05-12_00:00:00", "2022-05-12_01:02:00")); - assert(check_next("0 0 1 1 H/MAY ?", "2022-05-12_00:00:00", "2022-06-01_01:00:00")); + assert(check_next("H H H H H ?", "2022-05-12_00:00:00", "2023-01-19_12:42:00")); // 0 42 12(84) 19(126) 1(168) 1(210) + assert(check_next("H H H ? H H", "2022-05-12_00:00:00", "2023-01-02_12:42:00")); + assert(check_next("H 0 1 * * ?", "2022-05-12_00:00:00", "2022-05-12_01:00:00")); + assert(check_next("0 H/10 1 * * ?", "2022-05-12_00:00:00", "2022-05-12_01:02:00")); + assert(check_next("0 0 1 1 H/MAY ?", "2022-05-12_00:00:00", "2022-06-01_01:00:00")); cron_init_hash(12); - assert(check_next("H H H H H ?", "2022-05-12_00:00:00", "2023-01-10_00:12:00")); // 0 12 0 10 1 5 - assert(check_next("H H H ? H H", "2022-05-12_00:00:00", "2023-01-06_00:12:00")); + assert(check_next("H H H H H ?", "2022-05-12_00:00:00", "2023-01-10_00:12:00")); // 0 12 0 10 1 5 + assert(check_next("H H H ? H H", "2022-05-12_00:00:00", "2023-01-06_00:12:00")); // Tests for a custom hash function cron_custom_hash_fn custom_fn = fake_custom_hash_function; cron_init_custom_hash_fn(custom_fn); - assert(check_next("H H H H H ?", "2022-05-12_00:00:00", "2023-01-22_12:24:12")); // 12 24 12 22 1 3 - assert(check_next("H H H ? H H", "2022-05-12_00:00:00", "2023-01-04_12:24:12")); // 12 24 12 22 1 3 - assert(check_next("0 0 1 ? * H/TUE", "2022-05-12_00:00:00", "2022-05-13_01:00:00")); // 1/TUE + assert(check_next("H H H H H ?", "2022-05-12_00:00:00", "2023-01-22_12:24:12")); // 12 24 12 22 1 3 + assert(check_next("H H H ? H H", "2022-05-12_00:00:00", "2023-01-04_12:24:12")); // 12 24 12 22 1 3 + assert(check_next("0 0 1 ? * H/TUE", "2022-05-12_00:00:00", "2022-05-13_01:00:00")); // 1/TUE cron_init_custom_hash_fn(testing_hash_function); // W Tests - assert(check_next("0 0 1 4W * ?", "2022-04-12_00:00:00", "2022-05-04_01:00:00")); - assert(check_next("0 0 1 4W * ?", "2022-05-12_00:00:00", "2022-06-03_01:00:00")); - assert(check_next("0 0 1 1W * ?", "2022-10-01_00:00:00", "2022-10-03_01:00:00")); - assert(check_next("0 0 1 1W * ?", "2022-10-03_00:00:00", "2022-10-03_01:00:00")); - assert(check_next("0 0 1 16W * ?", "2022-07-16_00:00:00", "2022-08-16_01:00:00")); - assert(check_next("0 0 1 20W * ?", "2022-08-20_00:00:00", "2022-09-20_01:00:00")); - assert(check_next("0 0 1 1W * ?", "2022-10-03_02:00:00", "2022-11-01_01:00:00")); - assert(check_next("0 0 1 1W * ?", "2022-05-01_02:00:00", "2022-05-02_01:00:00")); - assert(check_next("0 0 1 1W * ?", "2022-09-01_00:00:00", "2022-09-01_01:00:00")); - assert(check_next("0 0 1 1,3W * ?", "2022-09-01_00:00:00", "2022-09-01_01:00:00")); - assert(check_next("0 0 1 1,3W * ?", "2022-09-02_00:00:00", "2022-09-02_01:00:00")); - assert(check_next("0 0 1 1,3W * ?", "2022-09-03_00:00:00", "2022-10-01_01:00:00")); - assert(check_next("0 0 1 1,3W * ?", "2022-10-02_00:00:00", "2022-10-03_01:00:00")); + assert(check_next("0 0 1 4W * ?", "2022-04-12_00:00:00", "2022-05-04_01:00:00")); + assert(check_next("0 0 1 4W * ?", "2022-05-12_00:00:00", "2022-06-03_01:00:00")); + assert(check_next("0 0 1 1W * ?", "2022-10-01_00:00:00", "2022-10-03_01:00:00")); + assert(check_next("0 0 1 1W * ?", "2022-10-03_00:00:00", "2022-10-03_01:00:00")); + assert(check_next("0 0 1 16W * ?", "2022-07-16_00:00:00", "2022-08-16_01:00:00")); + assert(check_next("0 0 1 20W * ?", "2022-08-20_00:00:00", "2022-09-20_01:00:00")); + assert(check_next("0 0 1 1W * ?", "2022-10-03_02:00:00", "2022-11-01_01:00:00")); + assert(check_next("0 0 1 1W * ?", "2022-05-01_02:00:00", "2022-05-02_01:00:00")); + assert(check_next("0 0 1 1W * ?", "2022-09-01_00:00:00", "2022-09-01_01:00:00")); + assert(check_next("0 0 1 1,3W * ?", "2022-09-01_00:00:00", "2022-09-01_01:00:00")); + assert(check_next("0 0 1 1,3W * ?", "2022-09-02_00:00:00", "2022-09-02_01:00:00")); + assert(check_next("0 0 1 1,3W * ?", "2022-09-03_00:00:00", "2022-10-01_01:00:00")); + assert(check_next("0 0 1 1,3W * ?", "2022-10-02_00:00:00", "2022-10-03_01:00:00")); // Check behaviour with more days mixed with W fields - assert(check_next("0 0 1 1,3W,15 * ?", "2022-09-01_00:00:00", "2022-09-01_01:00:00")); - assert(check_next("0 0 1 1,3W,15 * ?", "2022-09-02_00:00:00", "2022-09-02_01:00:00")); - assert(check_next("0 0 1 1,3W,15 * ?", "2022-09-03_00:00:00", "2022-09-15_01:00:00")); - assert(check_next("0 0 1 1,3W,15 * ?", "2022-09-16_00:00:00", "2022-10-01_01:00:00")); - assert(check_next("0 0 1 1,3W,15 * ?", "2022-10-02_00:00:00", "2022-10-03_01:00:00")); - assert(check_next("0 0 1 1,3W,15,16W * ?", "2022-09-01_00:00:00", "2022-09-01_01:00:00")); - assert(check_next("0 0 1 1,3W,15,16W * ?", "2022-09-02_00:00:00", "2022-09-02_01:00:00")); - assert(check_next("0 0 1 1,3W,15,16W * ?", "2022-09-03_00:00:00", "2022-09-15_01:00:00")); - assert(check_next("0 0 1 1,3W,15,16W * ?", "2022-09-16_00:00:00", "2022-09-16_01:00:00")); - assert(check_next("0 0 1 1,3W,15,16W * ?", "2022-09-17_00:00:00", "2022-10-01_01:00:00")); - assert(check_next("0 0 1 1,3W,15,16W * ?", "2022-10-02_00:00:00", "2022-10-03_01:00:00")); - assert(check_next("0 0 1 1,3W,15,16W * ?", "2025-02-16_00:00:00", "2025-02-17_01:00:00")); - assert(check_next("0 0 1 1W,4W * ?", "2022-09-01_00:00:00", "2022-09-01_01:00:00")); - assert(check_next("0 0 1 1W,4W * ?", "2022-09-02_00:00:00", "2022-09-05_01:00:00")); - assert(check_next("0 0 1 1W,4W * ?", "2022-06-03_00:00:00", "2022-06-03_01:00:00")); - assert(check_next("0 0 1 1W,4W * ?", "2022-09-03_00:00:00", "2022-09-05_01:00:00")); - assert(check_next("0 0 1 1W,4W * ?", "2022-10-01_00:00:00", "2022-10-03_01:00:00")); - assert(check_next("0 0 1 1W,15W * ?", "2022-09-01_00:00:00", "2022-09-01_01:00:00")); - assert(check_next("0 0 1 1W,15W * ?", "2022-10-01_00:00:00", "2022-10-03_01:00:00")); - assert(check_next("0 0 1 1W,15W * ?", "2022-09-02_00:00:00", "2022-09-15_01:00:00")); - assert(check_next("0 0 1 1W,15W * ?", "2022-01-01_00:00:00", "2022-01-03_01:00:00")); - assert(check_next("0 0 1 1W,15W * ?", "2022-01-04_00:00:00", "2022-01-14_01:00:00")); - assert(check_next("0 0 1 1W,15W * ?", "2022-01-15_00:00:00", "2022-02-01_01:00:00")); - assert(check_next("0 0 1 8W,26W * ?", "2022-01-06_00:00:00", "2022-01-07_01:00:00")); - assert(check_next("0 0 1 8W,26W * ?", "2022-01-26_00:00:00", "2022-01-26_01:00:00")); - assert(check_next("0 0 1 8W,26W * ?", "2022-02-26_00:00:00", "2022-03-08_01:00:00")); - assert(check_next("0 0 1 8W,26W * ?", "2022-03-09_00:00:00", "2022-03-25_01:00:00")); - assert(check_next("0 0 1 29W * ?", "2022-02-28_00:00:00", "2022-03-29_01:00:00")); - assert(check_next("0 0 1 29W * ?", "2024-02-28_00:00:00", "2024-02-29_01:00:00")); - assert(check_next("0 0 1 31W * ?", "2022-02-28_00:00:00", "2022-03-31_01:00:00")); - assert(check_next("0 0 1 31W * ?", "2022-06-17_00:00:00", "2022-07-29_01:00:00")); - assert(check_next("0 0 1 31W * ?", "2022-07-30_00:00:00", "2022-08-31_01:00:00")); - assert(check_next("0 0 1 26W * ?", "2022-06-27_00:00:00", "2022-06-27_01:00:00")); - assert(check_next("H 0 1 26W * ?", "2022-06-27_00:00:00", "2022-06-27_01:00:00")); - assert(check_next("H 0 1 26W * ?", "2022-06-27_02:00:00", "2022-07-26_01:00:00")); - assert(check_next("H 0 1 HW * ?", "2022-06-27_02:00:00", "2022-07-11_01:00:00")); // 10W - assert(check_next("H 0 1 HW * ?", "2022-05-27_02:00:00", "2022-06-10_01:00:00")); // 10W + assert(check_next("0 0 1 1,3W,15 * ?", "2022-09-01_00:00:00", "2022-09-01_01:00:00")); + assert(check_next("0 0 1 1,3W,15 * ?", "2022-09-02_00:00:00", "2022-09-02_01:00:00")); + assert(check_next("0 0 1 1,3W,15 * ?", "2022-09-03_00:00:00", "2022-09-15_01:00:00")); + assert(check_next("0 0 1 1,3W,15 * ?", "2022-09-16_00:00:00", "2022-10-01_01:00:00")); + assert(check_next("0 0 1 1,3W,15 * ?", "2022-10-02_00:00:00", "2022-10-03_01:00:00")); + assert(check_next("0 0 1 1,3W,15,16W * ?", "2022-09-01_00:00:00", "2022-09-01_01:00:00")); + assert(check_next("0 0 1 1,3W,15,16W * ?", "2022-09-02_00:00:00", "2022-09-02_01:00:00")); + assert(check_next("0 0 1 1,3W,15,16W * ?", "2022-09-03_00:00:00", "2022-09-15_01:00:00")); + assert(check_next("0 0 1 1,3W,15,16W * ?", "2022-09-16_00:00:00", "2022-09-16_01:00:00")); + assert(check_next("0 0 1 1,3W,15,16W * ?", "2022-09-17_00:00:00", "2022-10-01_01:00:00")); + assert(check_next("0 0 1 1,3W,15,16W * ?", "2022-10-02_00:00:00", "2022-10-03_01:00:00")); + assert(check_next("0 0 1 1,3W,15,16W * ?", "2025-02-16_00:00:00", "2025-02-17_01:00:00")); + assert(check_next("0 0 1 1W,4W * ?", "2022-09-01_00:00:00", "2022-09-01_01:00:00")); + assert(check_next("0 0 1 1W,4W * ?", "2022-09-02_00:00:00", "2022-09-05_01:00:00")); + assert(check_next("0 0 1 1W,4W * ?", "2022-06-03_00:00:00", "2022-06-03_01:00:00")); + assert(check_next("0 0 1 1W,4W * ?", "2022-09-03_00:00:00", "2022-09-05_01:00:00")); + assert(check_next("0 0 1 1W,4W * ?", "2022-10-01_00:00:00", "2022-10-03_01:00:00")); + assert(check_next("0 0 1 1W,15W * ?", "2022-09-01_00:00:00", "2022-09-01_01:00:00")); + assert(check_next("0 0 1 1W,15W * ?", "2022-10-01_00:00:00", "2022-10-03_01:00:00")); + assert(check_next("0 0 1 1W,15W * ?", "2022-09-02_00:00:00", "2022-09-15_01:00:00")); + assert(check_next("0 0 1 1W,15W * ?", "2022-01-01_00:00:00", "2022-01-03_01:00:00")); + assert(check_next("0 0 1 1W,15W * ?", "2022-01-04_00:00:00", "2022-01-14_01:00:00")); + assert(check_next("0 0 1 1W,15W * ?", "2022-01-15_00:00:00", "2022-02-01_01:00:00")); + assert(check_next("0 0 1 8W,26W * ?", "2022-01-06_00:00:00", "2022-01-07_01:00:00")); + assert(check_next("0 0 1 8W,26W * ?", "2022-01-26_00:00:00", "2022-01-26_01:00:00")); + assert(check_next("0 0 1 8W,26W * ?", "2022-02-26_00:00:00", "2022-03-08_01:00:00")); + assert(check_next("0 0 1 8W,26W * ?", "2022-03-09_00:00:00", "2022-03-25_01:00:00")); + assert(check_next("0 0 1 29W * ?", "2022-02-28_00:00:00", "2022-03-29_01:00:00")); + assert(check_next("0 0 1 29W * ?", "2024-02-28_00:00:00", "2024-02-29_01:00:00")); + assert(check_next("0 0 1 31W * ?", "2022-02-28_00:00:00", "2022-03-31_01:00:00")); + assert(check_next("0 0 1 31W * ?", "2022-06-17_00:00:00", "2022-07-29_01:00:00")); + assert(check_next("0 0 1 31W * ?", "2022-07-30_00:00:00", "2022-08-31_01:00:00")); + assert(check_next("0 0 1 26W * ?", "2022-06-27_00:00:00", "2022-06-27_01:00:00")); + assert(check_next("H 0 1 26W * ?", "2022-06-27_00:00:00", "2022-06-27_01:00:00")); + assert(check_next("H 0 1 26W * ?", "2022-06-27_02:00:00", "2022-07-26_01:00:00")); + assert(check_next("H 0 1 HW * ?", "2022-06-27_02:00:00", "2022-07-11_01:00:00")); // 10W + assert(check_next("H 0 1 HW * ?", "2022-05-27_02:00:00", "2022-06-10_01:00:00")); // 10W // L Tests - assert(check_next("0 0 1 LW * ?", "2022-06-22_00:00:00", "2022-06-30_01:00:00")); - assert(check_next("0 0 1 LW * ?", "2022-07-01_00:00:00", "2022-07-29_01:00:00")); - assert(check_next("0 0 1 LW * ?", "2022-07-29_02:00:00", "2022-08-31_01:00:00")); - assert(check_next("0 0 1 LW * ?", "2022-10-01_00:00:00", "2022-10-31_01:00:00")); - assert(check_next("0 0 1 LW * ?", "2022-07-31_00:00:00", "2022-08-31_01:00:00")); - assert(check_next("0 0 1 LW * ?", "2022-07-30_00:00:00", "2022-08-31_01:00:00")); + assert(check_next("0 0 1 LW * ?", "2022-06-22_00:00:00", "2022-06-30_01:00:00")); + assert(check_next("0 0 1 LW * ?", "2022-07-01_00:00:00", "2022-07-29_01:00:00")); + assert(check_next("0 0 1 LW * ?", "2022-07-29_02:00:00", "2022-08-31_01:00:00")); + assert(check_next("0 0 1 LW * ?", "2022-10-01_00:00:00", "2022-10-31_01:00:00")); + assert(check_next("0 0 1 LW * ?", "2022-07-31_00:00:00", "2022-08-31_01:00:00")); + assert(check_next("0 0 1 LW * ?", "2022-07-30_00:00:00", "2022-08-31_01:00:00")); cron_init_hash(7); - assert(check_next("H 0 H LW * ?", "2022-10-01_00:00:00", "2022-10-31_14:00:00")); - assert(check_next("0 0 1 L * ?", "2022-05-12_00:00:00", "2022-05-31_01:00:00")); - assert(check_next("0 0 1 L * ?", "2022-02-12_00:00:00", "2022-02-28_01:00:00")); - assert(check_next("0 0 1 L * ?", "2020-02-12_00:00:00", "2020-02-29_01:00:00")); - assert(check_next("0 0 1 L * ?", "2021-02-12_00:00:00", "2021-02-28_01:00:00")); - assert(check_next("0 0 1 ? * L", "2022-05-12_00:00:00", "2022-05-15_01:00:00")); - assert(check_next("0 0 1 ? * 4L", "2022-05-12_00:00:00", "2022-05-26_01:00:00")); - assert(check_next("0 0 1 ? * 1L", "2022-03-29_00:00:00", "2022-04-25_01:00:00")); - assert(check_next("0 0 1 ? * 5L", "2022-06-25_00:00:00", "2022-07-29_01:00:00")); - assert(check_next("0 0 1 L-2 * ?", "2022-05-12_00:00:00", "2022-05-29_01:00:00")); - assert(check_next("0 0 1 L-3 * ?", "2020-02-12_00:00:00", "2020-02-26_01:00:00")); - assert(check_next("0 0 1 L-30 * ?", "2022-03-01_00:00:00", "2022-03-01_01:00:00")); - assert(check_next("0 0 1 L-30 * ?", "2022-01-02_00:00:00", "2022-02-01_01:00:00")); - assert(check_next("0 0 1 L-31 * ?", "2022-05-12_00:00:00", "2022-06-01_01:00:00")); - assert(check_next("0 0 1 L-32 * ?", "2022-05-12_00:00:00", "2022-06-01_01:00:00")); - assert(check_next("0 0 1 L-31 2 ?", "2022-01-01_00:00:00", "2022-02-01_01:00:00")); + assert(check_next("H 0 H LW * ?", "2022-10-01_00:00:00", "2022-10-31_14:00:00")); + assert(check_next("0 0 1 L * ?", "2022-05-12_00:00:00", "2022-05-31_01:00:00")); + assert(check_next("0 0 1 L * ?", "2022-02-12_00:00:00", "2022-02-28_01:00:00")); + assert(check_next("0 0 1 L * ?", "2020-02-12_00:00:00", "2020-02-29_01:00:00")); + assert(check_next("0 0 1 L * ?", "2021-02-12_00:00:00", "2021-02-28_01:00:00")); + assert(check_next("0 0 1 ? * L", "2022-05-12_00:00:00", "2022-05-15_01:00:00")); + assert(check_next("0 0 1 ? * 4L", "2022-05-12_00:00:00", "2022-05-26_01:00:00")); + assert(check_next("0 0 1 ? * 1L", "2022-03-29_00:00:00", "2022-04-25_01:00:00")); + assert(check_next("0 0 1 ? * 5L", "2022-06-25_00:00:00", "2022-07-29_01:00:00")); + assert(check_next("0 0 1 L-2 * ?", "2022-05-12_00:00:00", "2022-05-29_01:00:00")); + assert(check_next("0 0 1 L-3 * ?", "2020-02-12_00:00:00", "2020-02-26_01:00:00")); + assert(check_next("0 0 1 L-30 * ?", "2022-03-01_00:00:00", "2022-03-01_01:00:00")); + assert(check_next("0 0 1 L-30 * ?", "2022-01-02_00:00:00", "2022-02-01_01:00:00")); + assert(check_next("0 0 1 L-31 * ?", "2022-05-12_00:00:00", "2022-06-01_01:00:00")); + assert(check_next("0 0 1 L-32 * ?", "2022-05-12_00:00:00", "2022-06-01_01:00:00")); + assert(check_next("0 0 1 L-31 2 ?", "2022-01-01_00:00:00", "2022-02-01_01:00:00")); // Tests for unintended month rollovers when going from 31st, see https://github.com/staticlibs/ccronexpr/issues/35 - assert(check_next("0 0 0 ? 11-12 *", "2022-05-31_00:00:00", "2022-11-01_00:00:00")); - assert(check_next("0 0 0 ? 11-12 *", "2022-07-31_00:00:00", "2022-11-01_00:00:00")); - assert(check_next("0 0 0 ? 11-12 *", "2022-08-31_00:00:00", "2022-11-01_00:00:00")); - assert(check_next("0 0 0 ? 11-12 *", "2022-10-31_00:00:00", "2022-11-01_00:00:00")); - assert(check_next("0 0 0 ? 6-7 *", "2022-05-31_00:00:00", "2022-06-01_00:00:00")); - assert(check_next("0 0 0 ? 8-9 *", "2022-07-31_00:00:00", "2022-08-01_00:00:00")); - assert(check_next("0 0 0 ? 9-10 *", "2022-08-31_00:00:00", "2022-09-01_00:00:00")); - - assert(check_next("0 0 0 ? 2-3 *", "2022-01-31_00:00:00", "2022-02-01_00:00:00")); - assert(check_next("0 0 0 ? 4-5 *", "2022-03-31_00:00:00", "2022-04-01_00:00:00")); + assert(check_next("0 0 0 ? 11-12 *", "2022-05-31_00:00:00", "2022-11-01_00:00:00")); + assert(check_next("0 0 0 ? 11-12 *", "2022-07-31_00:00:00", "2022-11-01_00:00:00")); + assert(check_next("0 0 0 ? 11-12 *", "2022-08-31_00:00:00", "2022-11-01_00:00:00")); + assert(check_next("0 0 0 ? 11-12 *", "2022-10-31_00:00:00", "2022-11-01_00:00:00")); + assert(check_next("0 0 0 ? 6-7 *", "2022-05-31_00:00:00", "2022-06-01_00:00:00")); + assert(check_next("0 0 0 ? 8-9 *", "2022-07-31_00:00:00", "2022-08-01_00:00:00")); + assert(check_next("0 0 0 ? 9-10 *", "2022-08-31_00:00:00", "2022-09-01_00:00:00")); + + assert(check_next("0 0 0 ? 2-3 *", "2022-01-31_00:00:00", "2022-02-01_00:00:00")); + assert(check_next("0 0 0 ? 4-5 *", "2022-03-31_00:00:00", "2022-04-01_00:00:00")); // Multiple consecutive days with 'W' flag - assert(check_next("0 0 0 24W * *", "2022-09-22_01:02:03", "2022-09-23_00:00:00")); - assert(check_next("0 0 0 25W * *", "2022-09-24_01:02:03", "2022-09-26_00:00:00")); - assert(check_next("0 0 0 30W * *", "2023-04-24_01:02:03", "2023-04-28_00:00:00")); - assert(check_next("0 0 0 24W,25W * *", "2022-09-22_01:02:03", "2022-09-23_00:00:00")); - assert(check_next("0 0 0 24W,25W * *", "2022-09-24_01:02:03", "2022-09-26_00:00:00")); - assert(check_next("0 0 0 29W,30W * *", "2022-10-24_01:02:03", "2022-10-28_00:00:00")); - assert(check_next("0 0 0 29W,30W * *", "2022-10-28_01:02:03", "2022-10-31_00:00:00")); - assert(check_next("0 0 0 29W,30W * *", "2022-10-29_01:02:03", "2022-10-31_00:00:00")); - assert(check_next("0 0 0 29W,30W * *", "2023-04-27_01:02:03", "2023-04-28_00:00:00")); - assert(check_next("0 0 0 29W,30W * *", "2023-04-29_01:02:03", "2023-05-29_00:00:00")); - assert(check_next("0 0 0 1W,2W * *", "2023-04-01_01:02:03", "2023-04-03_00:00:00")); - assert(check_next("0 0 0 1W,2W * *", "2023-04-02_01:02:03", "2023-04-03_00:00:00")); - assert(check_next("0 0 0 1W,2W * *", "2023-04-03_01:02:03", "2023-05-01_00:00:00")); - assert(check_next("0 0 0 1W,15W,30W * *","2023-04-01_01:02:03", "2023-04-03_00:00:00")); - assert(check_next("0 0 0 1W,15W,30W * *","2023-04-03_01:02:03", "2023-04-14_00:00:00")); - assert(check_next("0 0 0 1W,15,30W * *","2023-04-03_01:02:03", "2023-04-15_00:00:00")); - assert(check_next("0 0 0 1W,15W,30W * *","2023-04-14_01:02:03", "2023-04-28_00:00:00")); - assert(check_next("0 0 0 1W,15,30W * *","2023-04-14_01:02:03", "2023-04-15_00:00:00")); - assert(check_next("0 0 0 1W,15,30W * *","2023-04-15_01:02:03", "2023-04-28_00:00:00")); - assert(check_next("0 0 0 1W,15W,30W * *","2023-04-28_01:02:03", "2023-05-01_00:00:00")); + assert(check_next("0 0 0 24W * *", "2022-09-22_01:02:03", "2022-09-23_00:00:00")); + assert(check_next("0 0 0 25W * *", "2022-09-24_01:02:03", "2022-09-26_00:00:00")); + assert(check_next("0 0 0 30W * *", "2023-04-24_01:02:03", "2023-04-28_00:00:00")); + assert(check_next("0 0 0 24W,25W * *", "2022-09-22_01:02:03", "2022-09-23_00:00:00")); + assert(check_next("0 0 0 24W,25W * *", "2022-09-24_01:02:03", "2022-09-26_00:00:00")); + assert(check_next("0 0 0 29W,30W * *", "2022-10-24_01:02:03", "2022-10-28_00:00:00")); + assert(check_next("0 0 0 29W,30W * *", "2022-10-28_01:02:03", "2022-10-31_00:00:00")); + assert(check_next("0 0 0 29W,30W * *", "2022-10-29_01:02:03", "2022-10-31_00:00:00")); + assert(check_next("0 0 0 29W,30W * *", "2023-04-27_01:02:03", "2023-04-28_00:00:00")); + assert(check_next("0 0 0 29W,30W * *", "2023-04-29_01:02:03", "2023-05-29_00:00:00")); + assert(check_next("0 0 0 1W,2W * *", "2023-04-01_01:02:03", "2023-04-03_00:00:00")); + assert(check_next("0 0 0 1W,2W * *", "2023-04-02_01:02:03", "2023-04-03_00:00:00")); + assert(check_next("0 0 0 1W,2W * *", "2023-04-03_01:02:03", "2023-05-01_00:00:00")); + assert(check_next("0 0 0 1W,15W,30W * *", "2023-04-01_01:02:03", "2023-04-03_00:00:00")); + assert(check_next("0 0 0 1W,15W,30W * *", "2023-04-03_01:02:03", "2023-04-14_00:00:00")); + assert(check_next("0 0 0 1W,15,30W * *", "2023-04-03_01:02:03", "2023-04-15_00:00:00")); + assert(check_next("0 0 0 1W,15W,30W * *", "2023-04-14_01:02:03", "2023-04-28_00:00:00")); + assert(check_next("0 0 0 1W,15,30W * *", "2023-04-14_01:02:03", "2023-04-15_00:00:00")); + assert(check_next("0 0 0 1W,15,30W * *", "2023-04-15_01:02:03", "2023-04-28_00:00:00")); + assert(check_next("0 0 0 1W,15W,30W * *", "2023-04-28_01:02:03", "2023-05-01_00:00:00")); assert(check_next("0 0 0 1W,8W,15W,30W * *","2023-04-01_01:02:03", "2023-04-03_00:00:00")); assert(check_next("0 0 0 1W,8W,15W,30W * *","2023-04-03_01:02:03", "2023-04-07_00:00:00")); assert(check_next("0 0 0 1W,8W,15W,30W * *","2023-04-07_01:02:03", "2023-04-14_00:00:00")); assert(check_next("0 0 0 1W,8W,15W,30W * *","2023-04-14_01:02:03", "2023-04-28_00:00:00")); assert(check_next("0 0 0 1W,8W,15W,30W * *","2023-04-28_01:02:03", "2023-05-01_00:00:00")); - assert(check_next("0 0 0 1W,15W,LW * *","2023-04-01_01:02:03", "2023-04-03_00:00:00")); - assert(check_next("0 0 0 1W,15W,LW * *","2023-04-03_01:02:03", "2023-04-14_00:00:00")); - assert(check_next("0 0 0 1W,15W,LW * *","2023-04-14_01:02:03", "2023-04-28_00:00:00")); - assert(check_next("0 0 0 1W,15W,LW * *","2023-04-28_01:02:03", "2023-05-01_00:00:00")); - assert(check_next("0 0 0 1W,15W,LW * *","2023-06-15_01:02:03", "2023-06-30_00:00:00")); - assert(check_next("0 0 0 1W,15W,LW * *","2023-09-15_01:02:03", "2023-09-29_00:00:00")); - assert(check_next("0 0 0 1,1W,15W * *","2021-12-31_01:02:03", "2022-01-01_00:00:00")); - assert(check_next("0 0 0 1,1W,15W * *","2022-01-01_01:02:03", "2022-01-03_00:00:00")); - assert(check_next("0 0 0 1,1W,15W * *","2022-01-03_01:02:03", "2022-01-14_00:00:00")); + assert(check_next("0 0 0 1W,15W,LW * *", "2023-04-01_01:02:03", "2023-04-03_00:00:00")); + assert(check_next("0 0 0 1W,15W,LW * *", "2023-04-03_01:02:03", "2023-04-14_00:00:00")); + assert(check_next("0 0 0 1W,15W,LW * *", "2023-04-14_01:02:03", "2023-04-28_00:00:00")); + assert(check_next("0 0 0 1W,15W,LW * *", "2023-04-28_01:02:03", "2023-05-01_00:00:00")); + assert(check_next("0 0 0 1W,15W,LW * *", "2023-06-15_01:02:03", "2023-06-30_00:00:00")); + assert(check_next("0 0 0 1W,15W,LW * *", "2023-09-15_01:02:03", "2023-09-29_00:00:00")); + assert(check_next("0 0 0 1,1W,15W * *", "2021-12-31_01:02:03", "2022-01-01_00:00:00")); + assert(check_next("0 0 0 1,1W,15W * *", "2022-01-01_01:02:03", "2022-01-03_00:00:00")); + assert(check_next("0 0 0 1,1W,15W * *", "2022-01-03_01:02:03", "2022-01-14_00:00:00")); } void test_parse() { @@ -500,7 +503,8 @@ void test_parse() { assert(check_same("* * * * 2 *", "* * * * Feb *")); assert(check_same("* * * * 1 *", "* * * * 1 *")); assert(check_same("* * * * 1 L", "* * * * 1 SUN")); - assert(check_same("* * * * * *", "0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19-59,H 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18-59,H 0,1,2,3,4,5,6,7,8,9,10,11-23,H 1,2,3,4,5,6,7,8,9,10,11,12,13,14-31,H jan,feb,mar,apr,may,jun,jul,aug,sep,oct,nov,dec,H mon,tue,wed,thu,fri,sat,sun,H")); + assert(check_same("* * * * * *", + "0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19-59,H 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18-59,H 0,1,2,3,4,5,6,7,8,9,10,11-23,H 1,2,3,4,5,6,7,8,9,10,11,12,13,14-31,H jan,feb,mar,apr,may,jun,jul,aug,sep,oct,nov,dec,H mon,tue,wed,thu,fri,sat,sun,H")); //assert(check_same("0 0 15 1,16,L * *", "0 0 15 1,L,16 * *")); //assert(check_expr_valid("0 0 15 1,16,L * *")); //assert(check_expr_valid("0 0 15 1,L,16 * *")); @@ -567,7 +571,7 @@ void test_parse() { assert(check_expr_invalid("0 0 1 L12- * ?")); assert(check_expr_invalid("0 0 1 L1-4 * ?")); // H can not be used in ranges - assert(check_expr_invalid("H H-H 1 * * ?" )); // H-H Must be error, H can not be used in ranges + assert(check_expr_invalid("H H-H 1 * * ?")); // H-H Must be error, H can not be used in ranges assert(check_expr_invalid("H H-H 1 * * ?")); // H-60 Must be error, H can not be used in ranges assert(check_expr_invalid("H H-60 1 * * ?")); // H-60 Must be error, H can not be used in ranges assert(check_expr_invalid("H 1-H 1 * * ?")); // H can not be used in ranges @@ -642,8 +646,7 @@ void test_bits() { } /// Test if non-empty cron_expr will still result in the desired cron_expr -void test_invalid_bits(void) -{ +void test_invalid_bits(void) { cron_expr expr; const char *err = NULL; time_t res; @@ -729,9 +732,10 @@ void test_invalid_bits(void) /* For this test to work you need to set "-DCRON_TEST_MALLOC=1"*/ #ifdef CRON_TEST_MALLOC + void test_memory() { cron_expr cron; - const char* err; + const char *err; cron_parse_expr("* * * * * *", &cron, &err); if (cronAllocations != 0) { @@ -740,6 +744,7 @@ void test_memory() { } printf("Allocations: total: %d, max: %d\n", cronTotalAllocations, maxAlloc); } + #endif int main() { @@ -750,9 +755,9 @@ int main() { test_parse(); check_calc_invalid(); test_invalid_bits(); - #ifdef CRON_TEST_MALLOC +#ifdef CRON_TEST_MALLOC test_memory(); /* For this test to work you need to set "-DCRON_TEST_MALLOC=1"*/ - #endif +#endif printf("\nAll OK!\n"); return 0; }