Skip to content

Commit

Permalink
add: convenience functions, tests; fix: np checks
Browse files Browse the repository at this point in the history
  • Loading branch information
aschmidt75 committed Apr 10, 2023
1 parent 90bd06f commit 6dc0f03
Show file tree
Hide file tree
Showing 5 changed files with 199 additions and 18 deletions.
9 changes: 6 additions & 3 deletions include/semverreq.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,10 @@ extern "C" {
* Both input strings must be valid semver version and requirements strings.
* @param[in] version_str e.g.: "3.24.2"
* @param[in] versionreq_str, e.g. ">=3.20.0 <4.0.0"
* @return 0 if version matches requirements, != 0 otherwise; > 0 indicates an error in input parameters
* @param[out] res: 1 if version matches requirements, 0 otherwise;
* @return err: 0 = successful operation, != 0 indicates an error in input parameters
*/
int semver_matches(const char *version_str, const char *versionreq_str);
int semver_matches(const char *version_str, const char *versionreq_str, int *res);

/**
* semver_version_req
Expand Down Expand Up @@ -125,7 +126,9 @@ int semver_version_req_snprint(semver_version_req self, char *buf, size_t sz);
int semver_version_req_sprint(semver_version_req self, char *buf);

/**
* semver_version_req_matches checks, if `v` is within the bounds of `self`
* semver_version_req_matches checks, if `v` is within the bounds of `self`.
* self and v must be correctly set up, otherwise the result may be wrong.
* @returns 1 if it matches, 0 otherwise
*/
int semver_version_req_matches(semver_version_req self, semver_version v);

Expand Down
16 changes: 13 additions & 3 deletions src/semver.c
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ int semver_cmp(const char *_a, const char *_b, int *res) {
return 2;
}
if(!b) {
semver_version_delete(a);
return 3;
}

Expand Down Expand Up @@ -134,21 +135,30 @@ semver_version semver_version_from(unsigned long major, unsigned long minor,

semver_version semver_version_from_string(const char *s) {
int k;
semver_version_impl *res = (semver_version_impl *)semver_version_new();
semver_version_impl *res = 0;
if (!s) {
return 0;
}
res = (semver_version_impl *)semver_version_new();
k = semver_version_from_string_impl(res, s);
if (k != SEMVER_OK) {
semver_version_delete(res);
return NULL;
return 0;
}
return (semver_version )res;
}

semver_version_wrapped semver_version_from_string_wrapped(const char *s) {
int k;
semver_version_wrapped res;
semver_version_impl *impl = (semver_version_impl *)semver_version_new();
semver_version_impl *impl = 0;
res.err = 0;
res.unwrap.result = 0;
if (!s) {
res.err = 1;
return res;
}
impl = (semver_version_impl *)semver_version_new();
k = semver_version_from_string_impl(impl, s);
if (k != SEMVER_OK) {
res.err = 1;
Expand Down
52 changes: 52 additions & 0 deletions src/semverreq.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,37 @@
#include "semver.h"
#include "semverreq.h"

int semver_matches(const char *version_str, const char *versionreq_str, int *res) {
semver_version_req r = 0;
semver_version v = 0;
int err = 1;

if (!res || !version_str || !versionreq_str ) {
goto end_delete;
}

v = semver_version_from_string(version_str);
if (!v) {
goto end_delete;
}

r = semver_version_req_from_string(versionreq_str);
if (!r) {
goto end_delete;
}

*res = semver_version_req_matches(r, v);
err = 0;

end_delete:
if(v) {
semver_version_delete(v);
}
if(r) {
semver_version_req_delete(r);
}
return err;
}

#define SEMVERREQ_NEW(obj, type) \
do { \
Expand Down Expand Up @@ -523,3 +554,24 @@ int semver_version_req_sprint(semver_version_req _self, char *buf) {

return sprintf(buf, "%s%s %s%s", lower_cmp, buf1, upper_cmp, buf2);
}

int semver_version_req_matches(semver_version_req _self, semver_version v) {
int cl, cu;

semver_version_req_impl self = (semver_version_req_impl)_self;

cl = semver_version_cmp(v, self->lower);
if (cl < 0 || (cl == 0 && !self->lower_including)) {
return 0;
/* v is not compatible with lower bound */
}

cu = semver_version_cmp(v, self->upper);
if (cu > 0 || (cu == 0 && !self->upper_including)) {
return 0;
/* v is not compatible with upper bound */
}

/* v is compatible with both lower and upper bound */
return 1;
}
54 changes: 42 additions & 12 deletions test/semver-test.c
Original file line number Diff line number Diff line change
Expand Up @@ -316,20 +316,25 @@ void test_semver_copy() {

void test_semver_cmp3() {

/*
* https://semver.org/spec/v2.0.0.html 11.4.4
* 1.0.0-alpha < 1.0.0-alpha.1 < 1.0.0-alpha.beta < 1.0.0-beta < 1.0.0-beta.2
* < 1.0.0-beta.11 < 1.0.0-rc.1 < 1.0.0.
*/
const char *arr[] = {
"1.0.0-alpha", "1.0.0-alpha.1", "1.0.0-alpha.beta",
"1.0.0-beta", "1.0.0-beta.2", "1.0.0-beta.11",
"1.0.0-rc.1", "1.0.0"
};

size_t i;
"0.0.0",
"0.0.1", "0.0.2",
"0.1.0", "0.1.1-alpha", "0.1.1",
"0.9.0", "0.9.9-beta", "0.9.9",
"1.0.0-alpha", "1.0.0-alpha.1", "1.0.0-alpha.beta",
"1.0.0-beta", "1.0.0-beta.2", "1.0.0-beta.11",
"1.0.0-rc.1", "1.0.0",
"1.0.1-alpha", "1.0.1", "1.0.2",
"1.1.0", "1.1.1",
"1.9.0",
"2.0.0",
"99.99.99"
};

size_t i, j;
int comp_res, r;
for (i = 1; i < sizeof(arr) / sizeof(const char *); i++) {
size_t n = sizeof(arr) / sizeof(const char *);
for (i = 1; i < n; i++) {
comp_res = 99;

r = semver_cmp(arr[i - 1], arr[i], &comp_res);
Expand All @@ -345,8 +350,32 @@ void test_semver_cmp3() {
TEST_ASSERT_EQUAL(0, comp_res);

}
for (i = 0, j=n-1; i < n/2; i++, j--) {
comp_res = 99;

r = semver_cmp(arr[i], arr[j], &comp_res);
TEST_ASSERT_EQUAL(0, r);
TEST_ASSERT_LESS_THAN(0, comp_res);

r = semver_cmp(arr[j], arr[i], &comp_res);
TEST_ASSERT_EQUAL(0, r);
TEST_ASSERT_GREATER_THAN(0, comp_res);

}
}

void test_semver_cmp3_invalid() {
int comp_res, r;

r = semver_cmp(0, 0, 0);
TEST_ASSERT_NOT_EQUAL(0, r);

r = semver_cmp("not-valid", 0, &comp_res);
TEST_ASSERT_NOT_EQUAL(0, r);

r = semver_cmp("1.2.3", "in-valid", &comp_res);
TEST_ASSERT_NOT_EQUAL(0, r);
}

void run_semver_tests() {
int i;
Expand All @@ -360,5 +389,6 @@ void run_semver_tests() {
RUN_TEST(test_semver_prerelease_cmp);
RUN_TEST(test_semver_copy);
RUN_TEST(test_semver_cmp3);
RUN_TEST(test_semver_cmp3_invalid);
}
}
86 changes: 86 additions & 0 deletions test/semverreq-test.c
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,87 @@ void test_wb_parse_version_req_2nd(void) {
}
}

typedef struct {
const char *v;
const char *r;
const int res;
} exp5_t;

void test_semverreq_match_exact() {
const exp5_t tests[] = {
{ "0.0.1", 0, 1 },
{ "1.45.3-alpha", 0, 1 },
{ "1.45.3-beta+some", 0, 1 },
{ "1.45.3", 0, 1 },
};
const size_t n = sizeof(tests)/sizeof(exp5_t);
int res, err;
size_t i;
char buf[255];

for (i = 0; i < n; i++) {
res = 99;

memset(buf, 0, sizeof(buf));
buf[0] = '=';
strcpy(&buf[1], tests[i].v);
err = semver_matches(tests[i].v, buf, &res);

TEST_ASSERT_EQUAL(0, err);
TEST_ASSERT_NOT_EQUAL(99, res);
TEST_ASSERT_GREATER_THAN(0, res);
}
}

void test_semverreq_match_range() {
const exp5_t tests[] = {
{ "0.0.0", ">=0.0.1 <1.0.0", 0 },
{ "0.0.1-alpha", ">=0.0.1 <1.0.0", 0 },
{ "0.0.1", ">=0.0.1 <1.0.0", 1 },
{ "0.0.1", ">0.0.1 <1.0.0", 0 },
{ "0.0.2", ">0.0.1 <1.0.0", 1 },
{ "0.1.0", ">0.0.1 <1.0.0", 1 },
{ "0.9.9-alpha", ">0.0.1 <1.0.0", 1 },
{ "1.0.0", ">0.0.1 <1.0.0", 0 },
{ "1.0.0", ">0.0.1 <=1.0.0", 1 },
{ "1.3.0", ">=1.3.0 <2.0.0", 1 },
{ "1.45.3", ">=1.3.0 <2.0.0", 1 },
{ "2.0.0", ">=1.3.0 <2.0.0", 0 }
};
const size_t n = sizeof(tests)/sizeof(exp5_t);
int res, err;
size_t i;

for (i = 0; i < n; i++) {
res = 99;
err = semver_matches(tests[i].v, tests[i].r, &res);

TEST_ASSERT_EQUAL(0, err);
TEST_ASSERT_NOT_EQUAL(99, res);
TEST_ASSERT_EQUAL(tests[i].res, res);
}
}

void test_semverreq_match_range_ops() {
const exp5_t tests[] = {
{ "0.1.3", "~0.1.0", 1 },
{ "0.1.3", "~0.1.1", 1 },
{ "0.1.3", "~0.0.1", 0 },
};
const size_t n = sizeof(tests)/sizeof(exp5_t);
int res, err;
size_t i;

for (i = 0; i < n; i++) {
res = 99;
err = semver_matches(tests[i].v, tests[i].r, &res);

TEST_ASSERT_EQUAL(0, err);
TEST_ASSERT_NOT_EQUAL(99, res);
TEST_ASSERT_EQUAL(tests[i].res, res);
}
}

void run_semverreq_tests(void) {
/* explicitly constructed semverreqs should print correctly */
RUN_TEST(test_semverreq_print);
Expand All @@ -247,4 +328,9 @@ void run_semverreq_tests(void) {

/* paring should work correctly */
RUN_TEST(test_semverreq_parse);

/* high level function should work correctly */
RUN_TEST(test_semverreq_match_exact);
RUN_TEST(test_semverreq_match_range);
RUN_TEST(test_semverreq_match_range_ops);
}

0 comments on commit 6dc0f03

Please sign in to comment.