diff options
-rw-r--r-- | tests.c | 45 | ||||
-rw-r--r-- | version_compare.c | 48 | ||||
-rw-r--r-- | version_compare.h | 1 |
3 files changed, 85 insertions, 9 deletions
@@ -77,6 +77,13 @@ static struct TestCase_version_compare test_cases_version_compare[] = { {"1.0a", ">=", "1.0.0", 1}, {"1.0a", "!=", "1.0.0", 1}, + {"1.0.3", "=", "2.0.0", 0}, + {"1.0.3", "<", "2.0.0", 1}, + {"1.0.3", "<=", "2.0.0", 1}, + {"1.0.3", ">", "2.0.0", 0}, + {"1.0.3", ">=", "2.0.0", 0}, + {"1.0.3", "!=", "2.0.0", 1}, + {"2022.1", "=", "2022.4", 0}, {"2022.1", "<", "2022.4", 1}, {"2022.1", "<=", "2022.4", 1}, @@ -84,6 +91,34 @@ static struct TestCase_version_compare test_cases_version_compare[] = { {"2022.1", ">=", "2022.4", 0}, {"2022.1", "!=", "2022.4", 1}, + {"1:2022.1", "=", "2022.4", 0}, + {"1:2022.1", "<", "2022.4", 1}, + {"1:2022.1", "<=", "2022.4", 1}, + {"1:2022.1", ">", "2022.4", 0}, + {"1:2022.1", ">=", "2022.4", 0}, + {"1:2022.1", "!=", "2022.4", 1}, + + {"1:2022.1", "=", "2:2022.4", 0}, + {"1:2022.1", "<", "2:2022.4", 1}, + {"1:2022.1", "<=", "2:2022.4", 1}, + {"1:2022.1", ">", "2:2022.4", 0}, + {"1:2022.1", ">=", "2:2022.4", 0}, + {"1:2022.1", "!=", "2:2022.4", 1}, + + {"2:2022.4", "=", "1:2022.1", 0}, + {"2:2022.4", "<", "1:2022.1", 0}, + {"2:2022.4", "<=", "1:2022.1", 0}, + {"2:2022.4", ">", "1:2022.1", 1}, + {"2:2022.4", ">=", "1:2022.1", 1}, + {"2:2022.4", "!=", "1:2022.1", 1}, + + {"2022.1", "=", "2:2022.1", 0}, + {"2022.1", "<", "2:2022.1", 1}, + {"2022.1", "<=", "2:2022.1", 1}, + {"2022.1", ">", "2:2022.1", 0}, + {"2022.1", ">=", "2:2022.1", 0}, + {"2022.1", "!=", "2:2022.1", 1}, + {"2022.4", "=", "2022.1", 0}, {"2022.4", "<", "2022.1", 0}, {"2022.4", "<=", "2022.1", 0}, @@ -109,7 +144,7 @@ static int run_cases_version_compare(struct TestCase_version_compare tests[], si int op = version_parse_operator(test->op); result = version_compare(op, test->a, test->b); - printf("%s %s %s is %s", test->a, test->op, test->b, result ? "TRUE" : "FALSE" ); + printf("%s %s %s is %s (%d)", test->a, test->op, test->b, result ? "TRUE" : "FALSE" , result); if (test->result != result) { printf(" [FAILED: got %d, expected %d]\n", result, test->result); failed++; @@ -132,7 +167,7 @@ static int run_cases_string(struct TestCase_strings tests[], size_t size, strfn fn(&s); result = strcmp(test->result, s); - printf("'%s' is %s", s, !result ? "CORRECT" : "INCORRECT" ); + printf("'%s' is %s (%d)", s, !result ? "CORRECT" : "INCORRECT", !result ); if (result) { printf(" [FAILED: got '%s', expected '%s']\n", s, test->result); failed++; @@ -144,7 +179,6 @@ static int run_cases_string(struct TestCase_strings tests[], size_t size, strfn return failed; } - char **make_argv(int *argc, char *argv[]) { char **args; *argc = 0; @@ -153,7 +187,6 @@ char **make_argv(int *argc, char *argv[]) { *argc = *argc + 1; } - //char **args = calloc(*argc + 1, sizeof(*argv)); args = calloc(*argc + 1, sizeof(*argv)); if (!args) { perror("unable to allocate args array"); @@ -279,7 +312,7 @@ static int run_cases_program_split(struct TestCase_version_compare tests[], size struct TestCase_version_compare *test = &tests[i]; result = run_program((char *[]){test->a, test->op, test->b, NULL}); - printf("%s %s %s is %s", test->a, test->op, test->b, result ? "TRUE" : "FALSE" ); + printf("%s %s %s is %s (%d)", test->a, test->op, test->b, result ? "TRUE" : "FALSE", result); if (test->result != result) { printf(" [FAILED: got %d, expected %d]\n", result, test->result); failed++; @@ -300,7 +333,7 @@ static int run_cases_program_standalone(struct TestCase_version_compare tests[], snprintf(data, sizeof(data) - 1, "%s %s %s", test->a, test->op, test->b); result = run_program((char *[]){data, NULL}); - printf("%s %s %s is %s", test->a, test->op, test->b, result ? "TRUE" : "FALSE" ); + printf("%s %s %s is %s (%d)", test->a, test->op, test->b, result ? "TRUE" : "FALSE", result); if (test->result != result) { printf(" [FAILED: got %d, expected %d]\n", result, test->result); failed++; diff --git a/version_compare.c b/version_compare.c index c6aaca7..7e63024 100644 --- a/version_compare.c +++ b/version_compare.c @@ -128,7 +128,7 @@ char *collapse_whitespace(char **s) { * @return -1 on error */ int version_sum(const char *str) { - int result; + int i, result, epoch; char *s, *ptr, *end; if (!str || isempty(str)) { @@ -136,6 +136,7 @@ int version_sum(const char *str) { } result = 0; + epoch = 0; s = strdup(str); if (!s) { return -1; @@ -146,17 +147,44 @@ int version_sum(const char *str) { // Parsing stops at the first non-alpha, non-'.' character // Digits are processed until the first invalid character // I'm torn whether this should be considered an error + i = 0; while (end != NULL) { - result += (int) strtoul(ptr, &end, 10); + int tmp_result = 0; + + tmp_result = (int) strtoul(ptr, &end, 10); + + // Circumvent a bug which allows a smaller version to be greater + // than a larger version + // Bug: + // 1.0.3 == 1 + 0 + 3 = 4 + // 2.0.0 == 2 + 0 + 0 = 2 + // Correction: + // ((1 * EPOCH_MOD) + 1).0.3 = 104 + // ((2 * EPOCH_MOD) + 2).0.0 = 202 + if (!i && tmp_result && *end != ':') { + result += tmp_result * EPOCH_MOD; + i++; + } + ptr = end; - if (*ptr == '.') + if (*ptr == '.' || *ptr == '-') { ptr++; + } + else if (!epoch && *ptr == ':') { + epoch = 1; + result += EPOCH_MOD; + ptr++; + } else if (isalpha(*ptr)) { result += *ptr - ('a' - 1); ptr++; } else end = NULL; + + if (tmp_result) { + result += tmp_result; + } } free(s); @@ -204,6 +232,12 @@ int version_parse_operator(char *str) { return result; } +int version_has_epoch(const char *str) { + char *result; + result = strchr(str, ':'); + return result ? 1 : 0; +} + /** * Compare version strings based on flag(s) * @param flags verison operators @@ -227,6 +261,14 @@ int version_compare(int flags, const char *aa, const char *bb) { if (result_b < 0) return -1; + + if ((version_has_epoch(aa) && !version_has_epoch(bb))) { + result_a -= EPOCH_MOD; + } + if (!version_has_epoch(aa) && version_has_epoch(bb)) { + result_b -= EPOCH_MOD; + } + result = 0; if (flags & GT && flags & EQ) result |= result_a >= result_b; diff --git a/version_compare.h b/version_compare.h index a951e53..cf873ad 100644 --- a/version_compare.h +++ b/version_compare.h @@ -5,6 +5,7 @@ #define LT 1 << 2 #define EQ 1 << 3 #define NOT 1 << 4 +#define EPOCH_MOD 100 int isempty(char *str); char *lstrip(char **s); |