From 30e086ad6b9073ceb61bac47c6e448ee991b143a Mon Sep 17 00:00:00 2001 From: Jef Roosens Date: Wed, 18 Jan 2023 13:53:50 +0100 Subject: [PATCH] test: started porting cron tests --- .gitignore | 1 + Makefile | 4 +- include/vieter_cron.h | 41 ++++++++++--------- src/cron/expression.c | 29 ++++++++------ src/cron/parse.c | 50 ++++++++++++----------- test/cron/test_parse.c | 91 ++++++++++++++---------------------------- 6 files changed, 97 insertions(+), 119 deletions(-) diff --git a/.gitignore b/.gitignore index 6654b8d..2fe0b45 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ build/ compile_commands.json +.cache/ diff --git a/Makefile b/Makefile index bb1d972..313735c 100644 --- a/Makefile +++ b/Makefile @@ -60,11 +60,11 @@ $(BUILD_DIR)/$(TEST_DIR)/%.c.o: $(TEST_DIR)/%.c # =====MAINTENANCE===== .PHONY: lint lint: - clang-format -n --Werror $(SRCS) $(SRCS_H) $(SRCS_TEST) + clang-format -n --Werror $(SRCS) $(SRCS_H) .PHONY: fmt fmt: - clang-format -i $(SRCS) $(SRCS_H) $(SRCS_TEST) + clang-format -i $(SRCS) $(SRCS_H) .PHONY: clean clean: diff --git a/include/vieter_cron.h b/include/vieter_cron.h index 25db1fd..a6019a9 100644 --- a/include/vieter_cron.h +++ b/include/vieter_cron.h @@ -7,16 +7,16 @@ #include #include -typedef enum cron_parse_error { - cron_parse_ok = 0, - cron_parse_invalid_expression = 1, - cron_parse_invalid_number = 2, - cron_parse_out_of_range = 3, - cron_parse_too_many_parts = 4, - cron_parse_not_enough_parts = 5 -} cron_parse_error; +typedef enum vieter_cron_parse_error { + vieter_cron_parse_ok = 0, + vieter_cron_parse_invalid_expression = 1, + vieter_cron_parse_invalid_number = 2, + vieter_cron_parse_out_of_range = 3, + vieter_cron_parse_too_many_parts = 4, + vieter_cron_parse_not_enough_parts = 5 +} vieter_cron_parse_error; -typedef struct cron_expression { +typedef struct vieter_cron_expression { uint8_t *minutes; uint8_t *hours; uint8_t *days; @@ -25,26 +25,29 @@ typedef struct cron_expression { uint8_t hour_count; uint8_t day_count; uint8_t month_count; -} cron_expression; +} vieter_cron_expression; -typedef struct cron_simple_time { +typedef struct vieter_cron_simple_time { int year; int month; int day; int hour; int minute; -} cron_simple_time; +} vieter_cron_simple_time; -cron_expression *ce_init(); +vieter_cron_expression *ce_init(); -void cron_ce_free(cron_expression *ce); +void vieter_cron_ce_free(vieter_cron_expression *ce); -void cron_ce_next(cron_simple_time *out, cron_expression *ce, - cron_simple_time *ref); +void vieter_cron_ce_next(vieter_cron_simple_time *out, + vieter_cron_expression *ce, + vieter_cron_simple_time *ref); -void cron_ce_next_from_now(cron_simple_time *out, cron_expression *ce); +void vieter_cron_ce_next_from_now(vieter_cron_simple_time *out, + vieter_cron_expression *ce); -enum cron_parse_error cron_ce_parse_expression(cron_expression *out, - const char *expression); +enum vieter_cron_parse_error +vieter_cron_parse_expression(vieter_cron_expression *out, + const char *expression); #endif diff --git a/src/cron/expression.c b/src/cron/expression.c index 4261366..f876bbc 100644 --- a/src/cron/expression.c +++ b/src/cron/expression.c @@ -3,9 +3,11 @@ const uint8_t month_days[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; -cron_expression *ce_init() { return malloc(sizeof(cron_expression)); } +vieter_cron_expression *vieter_cron_expression_init() { + return malloc(sizeof(vieter_cron_expression)); +} -void ce_free(cron_expression *ce) { +void ce_free(vieter_cron_expression *ce) { free(ce->months); free(ce->days); free(ce->hours); @@ -13,8 +15,8 @@ void ce_free(cron_expression *ce) { free(ce); } -void ce_next(cron_simple_time *out, cron_expression *ce, - cron_simple_time *ref) { +void vieter_cron_next(vieter_cron_simple_time *out, vieter_cron_expression *ce, + vieter_cron_simple_time *ref) { // For all of these values, the rule is the following: if their value is // the length of their respective array in the CronExpression object, that // means we've looped back around. This means that the "bigger" value has @@ -98,18 +100,19 @@ void ce_next(cron_simple_time *out, cron_expression *ce, } } -void ce_next_from_now(cron_simple_time *out, cron_expression *ce) { +void vieter_cron_next_from_now(vieter_cron_simple_time *out, + vieter_cron_expression *ce) { time_t t = time(NULL); struct tm gm; gmtime_r(&t, &gm); - cron_simple_time ref = {// tm_year contains years since 1900 - .year = 1900 + gm.tm_year, - // tm_mon goes from 0 to 11 - .month = gm.tm_mon + 1, - .day = gm.tm_mday, - .hour = gm.tm_hour, - .minute = gm.tm_min}; + vieter_cron_simple_time ref = {// tm_year contains years since 1900 + .year = 1900 + gm.tm_year, + // tm_mon goes from 0 to 11 + .month = gm.tm_mon + 1, + .day = gm.tm_mday, + .hour = gm.tm_hour, + .minute = gm.tm_min}; - ce_next(out, ce, &ref); + vieter_cron_next(out, ce, &ref); } diff --git a/src/cron/parse.c b/src/cron/parse.c index 74f0bb7..247e052 100644 --- a/src/cron/parse.c +++ b/src/cron/parse.c @@ -16,10 +16,10 @@ const uint8_t max_parts = 4; #define SAFE_ATOI(v, s, min, max) \ int _##v = atoi(s); \ if ((_##v) == 0 && strcmp((s), "0") != 0) { \ - return cron_parse_invalid_number; \ + return vieter_cron_parse_invalid_number; \ } \ if (((_##v) < (min)) || ((_##v) > (max))) { \ - return cron_parse_out_of_range; \ + return vieter_cron_parse_out_of_range; \ } \ v = (uint8_t)(_##v); @@ -41,8 +41,9 @@ const uint8_t max_parts = 4; * - a/c * - a-b/c */ -cron_parse_error ce_parse_range(uint64_t *out, char *s, uint8_t min, - uint8_t max) { +vieter_cron_parse_error vieter_cron_expression_parse_range(uint64_t *out, + char *s, uint8_t min, + uint8_t max) { size_t slash_index = 0, dash_index = 0; size_t s_index = 0; char cur_char; @@ -54,12 +55,12 @@ cron_parse_error ce_parse_range(uint64_t *out, char *s, uint8_t min, (cur_char >= '0' && cur_char <= '9'); if (!is_valid_character) { - return cron_parse_invalid_expression; + return vieter_cron_parse_invalid_expression; } if (cur_char == '/') { if (s_index == 0 || slash_index != 0) { - return cron_parse_invalid_expression; + return vieter_cron_parse_invalid_expression; } slash_index = s_index; @@ -68,7 +69,7 @@ cron_parse_error ce_parse_range(uint64_t *out, char *s, uint8_t min, } else if (cur_char == '-') { // At most one dash is allowed, and it must be before the slash if (s_index == 0 || dash_index != 0 || slash_index != 0) { - return cron_parse_invalid_expression; + return vieter_cron_parse_invalid_expression; } dash_index = s_index; @@ -85,7 +86,7 @@ cron_parse_error ce_parse_range(uint64_t *out, char *s, uint8_t min, if (s[0] == '*') { if (s[1] != '\0' || dash_index != 0) { - return cron_parse_invalid_expression; + return vieter_cron_parse_invalid_expression; } start = min; @@ -112,7 +113,7 @@ cron_parse_error ce_parse_range(uint64_t *out, char *s, uint8_t min, } } - return cron_parse_ok; + return vieter_cron_parse_ok; } /* @@ -120,19 +121,19 @@ cron_parse_error ce_parse_range(uint64_t *out, char *s, uint8_t min, * min-max range the part represents. A part consists of one or more range * expressions, separated by commas. */ -cron_parse_error ce_parse_part(uint64_t *out, char *s, uint8_t min, - uint8_t max) { +vieter_cron_parse_error ce_parse_part(uint64_t *out, char *s, uint8_t min, + uint8_t max) { *out = 0; char *next; - cron_parse_error res; + vieter_cron_parse_error res; while ((next = strchr(s, ',')) != NULL) { next[0] = '\0'; - res = ce_parse_range(out, s, min, max); + res = vieter_cron_expression_parse_range(out, s, min, max); - if (res != cron_parse_ok) { + if (res != vieter_cron_parse_ok) { return res; } @@ -140,7 +141,7 @@ cron_parse_error ce_parse_part(uint64_t *out, char *s, uint8_t min, } // Make sure to parse the final range as well - return ce_parse_range(out, s, min, max); + return vieter_cron_expression_parse_range(out, s, min, max); } /* @@ -196,13 +197,14 @@ uint8_t bf_to_nums(uint8_t **out, uint64_t bf, uint8_t min, uint8_t max) { /* * Parse a cron expression string into a cron_expression struct. */ -cron_parse_error ce_parse_expression(cron_expression *out, - const char *expression) { +vieter_cron_parse_error +vieter_cron_parse_expression(vieter_cron_expression *out, + const char *expression) { // The parsing functions modify the input string in-place char *s = strdup(expression); char *orig_s = s; - cron_parse_error res = cron_parse_ok; + vieter_cron_parse_error res = vieter_cron_parse_ok; // First we divide the input string into its parts, divided by spaces. // Each part is delimited by a NULL byte. @@ -237,7 +239,7 @@ cron_parse_error ce_parse_expression(cron_expression *out, // s[0] isn't '\0', there's still another part before the end of the string. if (s[0] != '\0') { if (part_count == max_parts) { - res = cron_parse_too_many_parts; + res = vieter_cron_parse_too_many_parts; goto end; } @@ -246,7 +248,7 @@ cron_parse_error ce_parse_expression(cron_expression *out, } if (part_count < min_parts) { - res = cron_parse_not_enough_parts; + res = vieter_cron_parse_not_enough_parts; goto end; } @@ -259,7 +261,7 @@ cron_parse_error ce_parse_expression(cron_expression *out, if (part_count >= 4) { res = ce_parse_part(&bit_field, parts[3], min[3], max[3]); - if (res != cron_parse_ok) { + if (res != vieter_cron_parse_ok) { goto end; } @@ -283,7 +285,7 @@ cron_parse_error ce_parse_expression(cron_expression *out, res = ce_parse_part(&bit_field, parts[2], min[2], max_day_value); - if (res != cron_parse_ok) { + if (res != vieter_cron_parse_ok) { free(out->months); goto end; @@ -301,7 +303,7 @@ cron_parse_error ce_parse_expression(cron_expression *out, res = ce_parse_part(&bit_field, parts[1], min[1], max[1]); - if (res != cron_parse_ok) { + if (res != vieter_cron_parse_ok) { free(out->months); free(out->days); @@ -315,7 +317,7 @@ cron_parse_error ce_parse_expression(cron_expression *out, res = ce_parse_part(&bit_field, parts[0], min[0], max[0]); - if (res != cron_parse_ok) { + if (res != vieter_cron_parse_ok) { free(out->months); free(out->days); free(out->hours); diff --git a/test/cron/test_parse.c b/test/cron/test_parse.c index dfd7f8e..ee67027 100644 --- a/test/cron/test_parse.c +++ b/test/cron/test_parse.c @@ -1,69 +1,38 @@ #include "acutest.h" #include "vieter_cron.h" -void test_tutorial(void) { - void *mem; +void test_not_allowed() { + char *expressions[] = { + "4 *-7", + "4 *-7/4", + "4 7/*", + "0 0 30 2", + "0 /5", + "0 ", + "0", + " 0", + " 0 ", + "1 2 3 4~9", + "1 1-3-5", + "0 5/2-5", + "", + "1 1/2/3", + "*5 8", + "x 8", + NULL + }; - mem = malloc(10); - TEST_CHECK(mem != NULL); + int i = 0; - mem = realloc(mem, 20); - TEST_CHECK(mem != NULL); + while (expressions[i] != NULL) { + vieter_cron_expression out; + TEST_CHECK_(vieter_cron_parse_expression(&out, expressions[i]) != vieter_cron_parse_ok, "%s should error", expressions[i]); - free(mem); + i++; + } } -void test_fail(void) { - int a, b; - - /* This condition is designed to fail so you can see what the failed test - * output looks like. */ - a = 1; - b = 2; - TEST_CHECK(a + b == 5); - - /* Here is TEST_CHECK_ in action. */ - TEST_CHECK_(a + b == 5, "%d + %d == 5", a, b); - - /* We may also show more information about the failure. */ - if (!TEST_CHECK(a + b == 5)) { - TEST_MSG("a: %d", a); - TEST_MSG("b: %d", b); - } - - /* The macro TEST_MSG() only outputs something when the preceding - * condition fails, so we can avoid the 'if' statement. */ - TEST_CHECK(a + b == 3); - TEST_MSG("a: %d", a); - TEST_MSG("b: %d", b); -} - -static void helper(void) { - /* Kill the current test with a condition which is never true. */ - TEST_ASSERT(1 == 2); - - /* This never happens because the test is aborted above. */ - TEST_CHECK(1 + 2 == 2 + 1); -} - -void test_abort(void) { - helper(); - - /* This test never happens because the test is aborted inside the helper() - * function. */ - TEST_CHECK(1 * 2 == 2 * 1); -} - -void test_crash(void) { - int *invalid = ((int *)NULL) + 0xdeadbeef; - - *invalid = 42; - TEST_CHECK_(1 == 1, "This should never execute, due to a write into " - "an invalid address."); -} - -TEST_LIST = {{"tutorial", test_tutorial}, - {"fail", test_fail}, - {"abort", test_abort}, - {"crash", test_crash}, - {NULL, NULL}}; +TEST_LIST = { + {"not_allowed", test_not_allowed}, + {NULL, NULL} +};