456 lines
14 KiB
C
456 lines
14 KiB
C
#include "malunal/microtest.h"
|
|
#include "malunal/version.h"
|
|
|
|
/* -------------------------------------------------------------------------
|
|
* parse_version(): successful parses
|
|
* ---------------------------------------------------------------------- */
|
|
|
|
MICROTEST(parse_version, basic_triple_succeeds) {
|
|
strview_t view = strview_from_cstr("1.2.3");
|
|
version_t ver;
|
|
error_t err = parse_version(&view, &ver);
|
|
|
|
MICROTEST_EXPECT_NULL(err.domain);
|
|
MICROTEST_EXPECT_EQ(ver.major, (malunal_size_t)1);
|
|
MICROTEST_EXPECT_EQ(ver.minor, (malunal_size_t)2);
|
|
MICROTEST_EXPECT_EQ(ver.patch, (malunal_size_t)3);
|
|
MICROTEST_EXPECT_EQ(strview_length(&ver.preview), (malunal_size_t)0);
|
|
MICROTEST_EXPECT_EQ(strview_length(&ver.build), (malunal_size_t)0);
|
|
}
|
|
|
|
MICROTEST(parse_version, all_zero_succeeds) {
|
|
strview_t view = strview_from_cstr("0.0.0");
|
|
version_t ver;
|
|
error_t err = parse_version(&view, &ver);
|
|
|
|
MICROTEST_EXPECT_NULL(err.domain);
|
|
MICROTEST_EXPECT_EQ(ver.major, (malunal_size_t)0);
|
|
MICROTEST_EXPECT_EQ(ver.minor, (malunal_size_t)0);
|
|
MICROTEST_EXPECT_EQ(ver.patch, (malunal_size_t)0);
|
|
}
|
|
|
|
MICROTEST(parse_version, multi_digit_components_succeed) {
|
|
strview_t view = strview_from_cstr("123.456.789");
|
|
version_t ver;
|
|
error_t err = parse_version(&view, &ver);
|
|
|
|
MICROTEST_EXPECT_NULL(err.domain);
|
|
MICROTEST_EXPECT_EQ(ver.major, (malunal_size_t)123);
|
|
MICROTEST_EXPECT_EQ(ver.minor, (malunal_size_t)456);
|
|
MICROTEST_EXPECT_EQ(ver.patch, (malunal_size_t)789);
|
|
}
|
|
|
|
MICROTEST(parse_version, preview_only_succeeds) {
|
|
strview_t view = strview_from_cstr("1.2.3-alpha");
|
|
version_t ver;
|
|
error_t err = parse_version(&view, &ver);
|
|
|
|
MICROTEST_EXPECT_NULL(err.domain);
|
|
MICROTEST_EXPECT_EQ(strview_length(&ver.preview), (malunal_size_t)5);
|
|
MICROTEST_EXPECT_TRUE(memcmp(ver.preview.beg, "alpha", 5) == 0);
|
|
MICROTEST_EXPECT_EQ(strview_length(&ver.build), (malunal_size_t)0);
|
|
}
|
|
|
|
MICROTEST(parse_version, dotted_preview_succeeds) {
|
|
strview_t view = strview_from_cstr("1.2.3-alpha.1");
|
|
version_t ver;
|
|
error_t err = parse_version(&view, &ver);
|
|
|
|
MICROTEST_EXPECT_NULL(err.domain);
|
|
MICROTEST_EXPECT_EQ(strview_length(&ver.preview), (malunal_size_t)7);
|
|
MICROTEST_EXPECT_TRUE(memcmp(ver.preview.beg, "alpha.1", 7) == 0);
|
|
}
|
|
|
|
MICROTEST(parse_version, build_only_succeeds) {
|
|
strview_t view = strview_from_cstr("1.2.3+build.5");
|
|
version_t ver;
|
|
error_t err = parse_version(&view, &ver);
|
|
|
|
MICROTEST_EXPECT_NULL(err.domain);
|
|
MICROTEST_EXPECT_EQ(strview_length(&ver.preview), (malunal_size_t)0);
|
|
MICROTEST_EXPECT_EQ(strview_length(&ver.build), (malunal_size_t)7);
|
|
MICROTEST_EXPECT_TRUE(memcmp(ver.build.beg, "build.5", 7) == 0);
|
|
}
|
|
|
|
MICROTEST(parse_version, preview_and_build_succeed) {
|
|
strview_t view = strview_from_cstr("1.2.3-alpha.1+build.5");
|
|
version_t ver;
|
|
error_t err = parse_version(&view, &ver);
|
|
|
|
MICROTEST_EXPECT_NULL(err.domain);
|
|
MICROTEST_EXPECT_EQ(ver.major, (malunal_size_t)1);
|
|
MICROTEST_EXPECT_EQ(ver.minor, (malunal_size_t)2);
|
|
MICROTEST_EXPECT_EQ(ver.patch, (malunal_size_t)3);
|
|
MICROTEST_EXPECT_TRUE(memcmp(ver.preview.beg, "alpha.1", 7) == 0);
|
|
MICROTEST_EXPECT_TRUE(memcmp(ver.build.beg, "build.5", 7) == 0);
|
|
}
|
|
|
|
MICROTEST(parse_version, single_digit_zero_component_is_not_leading_zero) {
|
|
/* A lone "0" is a valid component; the leading-zero rule only forbids
|
|
* *multiple* digits starting with zero (e.g. "01"). */
|
|
strview_t view = strview_from_cstr("0.2.3");
|
|
version_t ver;
|
|
error_t err = parse_version(&view, &ver);
|
|
|
|
MICROTEST_EXPECT_NULL(err.domain);
|
|
MICROTEST_EXPECT_EQ(ver.major, (malunal_size_t)0);
|
|
}
|
|
|
|
/* -------------------------------------------------------------------------
|
|
* parse_version(): error cases
|
|
* ---------------------------------------------------------------------- */
|
|
|
|
MICROTEST(parse_version, null_verstr_reports_null_input) {
|
|
version_t ver;
|
|
error_t err = parse_version(null, &ver);
|
|
|
|
MICROTEST_EXPECT_NOT_NULL(err.domain);
|
|
MICROTEST_EXPECT_EQ(err.code, (malunal_int32_t)VERSION_ERROR_NULL_INPUT);
|
|
}
|
|
|
|
MICROTEST(parse_version, null_out_reports_null_input) {
|
|
strview_t view = strview_from_cstr("1.2.3");
|
|
error_t err = parse_version(&view, null);
|
|
|
|
MICROTEST_EXPECT_NOT_NULL(err.domain);
|
|
MICROTEST_EXPECT_EQ(err.code, (malunal_int32_t)VERSION_ERROR_NULL_INPUT);
|
|
}
|
|
|
|
MICROTEST(parse_version, null_backing_data_succeeds_as_zero_version) {
|
|
strview_t view = { null, null };
|
|
version_t ver;
|
|
error_t err = parse_version(&view, &ver);
|
|
|
|
MICROTEST_EXPECT_NULL(err.domain);
|
|
MICROTEST_EXPECT_EQ(ver.major, (malunal_size_t)0);
|
|
MICROTEST_EXPECT_EQ(ver.minor, (malunal_size_t)0);
|
|
MICROTEST_EXPECT_EQ(ver.patch, (malunal_size_t)0);
|
|
}
|
|
|
|
MICROTEST(parse_version, leading_zero_in_major_fails) {
|
|
strview_t view = strview_from_cstr("01.2.3");
|
|
version_t ver;
|
|
error_t err = parse_version(&view, &ver);
|
|
|
|
MICROTEST_EXPECT_NOT_NULL(err.domain);
|
|
MICROTEST_EXPECT_EQ(err.code, (malunal_int32_t)VERSION_ERROR_LEADING_ZERO);
|
|
}
|
|
|
|
MICROTEST(parse_version, leading_zero_in_minor_fails) {
|
|
strview_t view = strview_from_cstr("1.02.3");
|
|
version_t ver;
|
|
error_t err = parse_version(&view, &ver);
|
|
|
|
MICROTEST_EXPECT_NOT_NULL(err.domain);
|
|
MICROTEST_EXPECT_EQ(err.code, (malunal_int32_t)VERSION_ERROR_LEADING_ZERO);
|
|
}
|
|
|
|
MICROTEST(parse_version, leading_zero_in_patch_fails) {
|
|
strview_t view = strview_from_cstr("1.2.03");
|
|
version_t ver;
|
|
error_t err = parse_version(&view, &ver);
|
|
|
|
MICROTEST_EXPECT_NOT_NULL(err.domain);
|
|
MICROTEST_EXPECT_EQ(err.code, (malunal_int32_t)VERSION_ERROR_LEADING_ZERO);
|
|
}
|
|
|
|
MICROTEST(parse_version, missing_minor_and_patch_fails) {
|
|
strview_t view = strview_from_cstr("1.2");
|
|
version_t ver;
|
|
error_t err = parse_version(&view, &ver);
|
|
|
|
MICROTEST_EXPECT_NOT_NULL(err.domain);
|
|
MICROTEST_EXPECT_EQ(err.code, (malunal_int32_t)VERSION_ERROR_MISSING_PART);
|
|
}
|
|
|
|
MICROTEST(parse_version, missing_patch_digits_fails) {
|
|
strview_t view = strview_from_cstr("1.2.");
|
|
version_t ver;
|
|
error_t err = parse_version(&view, &ver);
|
|
|
|
MICROTEST_EXPECT_NOT_NULL(err.domain);
|
|
MICROTEST_EXPECT_EQ(err.code, (malunal_int32_t)VERSION_ERROR_INVALID_NUMBER);
|
|
}
|
|
|
|
MICROTEST(parse_version, fourth_numeric_component_fails) {
|
|
strview_t view = strview_from_cstr("1.2.3.4");
|
|
version_t ver;
|
|
error_t err = parse_version(&view, &ver);
|
|
|
|
MICROTEST_EXPECT_NOT_NULL(err.domain);
|
|
MICROTEST_EXPECT_EQ(err.code, (malunal_int32_t)VERSION_ERROR_UNEXPECTED_CHAR);
|
|
}
|
|
|
|
MICROTEST(parse_version, empty_preview_fails) {
|
|
strview_t view = strview_from_cstr("1.2.3-");
|
|
version_t ver;
|
|
error_t err = parse_version(&view, &ver);
|
|
|
|
MICROTEST_EXPECT_NOT_NULL(err.domain);
|
|
MICROTEST_EXPECT_EQ(err.code, (malunal_int32_t)VERSION_ERROR_MISSING_PART);
|
|
}
|
|
|
|
MICROTEST(parse_version, empty_build_fails) {
|
|
strview_t view = strview_from_cstr("1.2.3+");
|
|
version_t ver;
|
|
error_t err = parse_version(&view, &ver);
|
|
|
|
MICROTEST_EXPECT_NOT_NULL(err.domain);
|
|
MICROTEST_EXPECT_EQ(err.code, (malunal_int32_t)VERSION_ERROR_MISSING_PART);
|
|
}
|
|
|
|
MICROTEST(parse_version, negative_major_fails) {
|
|
strview_t view = strview_from_cstr("-1.2.3");
|
|
version_t ver;
|
|
error_t err = parse_version(&view, &ver);
|
|
|
|
MICROTEST_EXPECT_NOT_NULL(err.domain);
|
|
MICROTEST_EXPECT_EQ(err.code, (malunal_int32_t)VERSION_ERROR_INVALID_NUMBER);
|
|
}
|
|
|
|
MICROTEST(parse_version, non_numeric_components_fail) {
|
|
strview_t view = strview_from_cstr("a.b.c");
|
|
version_t ver;
|
|
error_t err = parse_version(&view, &ver);
|
|
|
|
MICROTEST_EXPECT_NOT_NULL(err.domain);
|
|
MICROTEST_EXPECT_EQ(err.code, (malunal_int32_t)VERSION_ERROR_INVALID_NUMBER);
|
|
}
|
|
|
|
MICROTEST(parse_version, overflowing_major_fails) {
|
|
strview_t view = strview_from_cstr("99999999999999999999.2.3");
|
|
version_t ver;
|
|
error_t err = parse_version(&view, &ver);
|
|
|
|
MICROTEST_EXPECT_NOT_NULL(err.domain);
|
|
MICROTEST_EXPECT_EQ(err.code, (malunal_int32_t)VERSION_ERROR_VALUE_OVERFLOW);
|
|
}
|
|
|
|
MICROTEST(parse_version, overflowing_patch_fails) {
|
|
strview_t view = strview_from_cstr("1.2.99999999999999999999");
|
|
version_t ver;
|
|
error_t err = parse_version(&view, &ver);
|
|
|
|
MICROTEST_EXPECT_NOT_NULL(err.domain);
|
|
MICROTEST_EXPECT_EQ(err.code, (malunal_int32_t)VERSION_ERROR_VALUE_OVERFLOW);
|
|
}
|
|
|
|
/* -------------------------------------------------------------------------
|
|
* version_compare(): core number precedence
|
|
* ---------------------------------------------------------------------- */
|
|
|
|
static
|
|
version_t
|
|
must_parse(malunal_cstr_t s) {
|
|
strview_t view = strview_from_cstr(s);
|
|
version_t ver;
|
|
parse_version(&view, &ver);
|
|
return ver;
|
|
}
|
|
|
|
MICROTEST(version_compare, identical_versions_are_equal) {
|
|
version_t a = must_parse("1.2.3");
|
|
version_t b = must_parse("1.2.3");
|
|
|
|
MICROTEST_EXPECT_EQ(version_compare(&a, &b), 0);
|
|
}
|
|
|
|
MICROTEST(version_compare, is_reflexive) {
|
|
version_t a = must_parse("1.2.3");
|
|
|
|
MICROTEST_EXPECT_EQ(version_compare(&a, &a), 0);
|
|
}
|
|
|
|
MICROTEST(version_compare, greater_major_wins) {
|
|
version_t a = must_parse("2.0.0");
|
|
version_t b = must_parse("1.9.9");
|
|
|
|
MICROTEST_EXPECT_GT(version_compare(&a, &b), 0);
|
|
MICROTEST_EXPECT_LT(version_compare(&b, &a), 0);
|
|
}
|
|
|
|
MICROTEST(version_compare, greater_minor_wins_when_major_equal) {
|
|
version_t a = must_parse("1.3.0");
|
|
version_t b = must_parse("1.2.9");
|
|
|
|
MICROTEST_EXPECT_GT(version_compare(&a, &b), 0);
|
|
}
|
|
|
|
MICROTEST(version_compare, greater_patch_wins_when_major_minor_equal) {
|
|
version_t a = must_parse("1.2.4");
|
|
version_t b = must_parse("1.2.3");
|
|
|
|
MICROTEST_EXPECT_GT(version_compare(&a, &b), 0);
|
|
}
|
|
|
|
MICROTEST(version_compare, numeric_comparison_not_lexical) {
|
|
/* 1.2.10 > 1.2.9 numerically, even though "10" < "9" lexically. */
|
|
version_t a = must_parse("1.2.10");
|
|
version_t b = must_parse("1.2.9");
|
|
|
|
MICROTEST_EXPECT_GT(version_compare(&a, &b), 0);
|
|
}
|
|
|
|
/* -------------------------------------------------------------------------
|
|
* version_compare(): pre-release precedence
|
|
* ---------------------------------------------------------------------- */
|
|
|
|
MICROTEST(version_compare, preview_has_lower_precedence_than_release) {
|
|
version_t preview = must_parse("1.0.0-alpha");
|
|
version_t release = must_parse("1.0.0");
|
|
|
|
MICROTEST_EXPECT_LT(version_compare(&preview, &release), 0);
|
|
MICROTEST_EXPECT_GT(version_compare(&release, &preview), 0);
|
|
}
|
|
|
|
MICROTEST(version_compare, more_preview_identifiers_has_higher_precedence) {
|
|
version_t shorter = must_parse("1.0.0-alpha");
|
|
version_t longer = must_parse("1.0.0-alpha.1");
|
|
|
|
MICROTEST_EXPECT_LT(version_compare(&shorter, &longer), 0);
|
|
}
|
|
|
|
MICROTEST(version_compare, numeric_identifier_has_lower_precedence_than_alphanumeric) {
|
|
version_t numeric = must_parse("1.0.0-alpha.1");
|
|
version_t alpha = must_parse("1.0.0-alpha.beta");
|
|
|
|
MICROTEST_EXPECT_LT(version_compare(&numeric, &alpha), 0);
|
|
}
|
|
|
|
MICROTEST(version_compare, numeric_preview_identifiers_compare_numerically) {
|
|
/* "10" > "2" numerically, even though "10" < "2" lexically. */
|
|
version_t ten = must_parse("1.0.0-rc.10");
|
|
version_t two = must_parse("1.0.0-rc.2");
|
|
|
|
MICROTEST_EXPECT_GT(version_compare(&ten, &two), 0);
|
|
}
|
|
|
|
MICROTEST(version_compare, alphanumeric_preview_identifiers_compare_lexically) {
|
|
version_t a = must_parse("1.0.0-alpha");
|
|
version_t b = must_parse("1.0.0-beta");
|
|
|
|
MICROTEST_EXPECT_LT(version_compare(&a, &b), 0);
|
|
}
|
|
|
|
MICROTEST(version_compare, identical_previews_are_equal) {
|
|
version_t a = must_parse("1.0.0-alpha.1");
|
|
version_t b = must_parse("1.0.0-alpha.1");
|
|
|
|
MICROTEST_EXPECT_EQ(version_compare(&a, &b), 0);
|
|
}
|
|
|
|
/* -------------------------------------------------------------------------
|
|
* version_compare(): build metadata is ignored
|
|
* ---------------------------------------------------------------------- */
|
|
|
|
MICROTEST(version_compare, differing_build_metadata_is_ignored) {
|
|
version_t a = must_parse("1.0.0+build.1");
|
|
version_t b = must_parse("1.0.0+build.2");
|
|
|
|
MICROTEST_EXPECT_EQ(version_compare(&a, &b), 0);
|
|
}
|
|
|
|
MICROTEST(version_compare, build_metadata_ignored_with_preview_present) {
|
|
version_t a = must_parse("1.0.0-alpha+build.1");
|
|
version_t b = must_parse("1.0.0-alpha+build.2");
|
|
|
|
MICROTEST_EXPECT_EQ(version_compare(&a, &b), 0);
|
|
}
|
|
|
|
/* -------------------------------------------------------------------------
|
|
* version_string()
|
|
* ---------------------------------------------------------------------- */
|
|
|
|
MICROTEST(version_string, basic_triple_round_trips) {
|
|
version_t ver = must_parse("1.2.3");
|
|
|
|
malunal_char_t buffer[32];
|
|
malunal_int32_t n = version_string(&ver, buffer, sizeof(buffer));
|
|
|
|
MICROTEST_EXPECT_GT(n, 0);
|
|
MICROTEST_EXPECT_TRUE(strcmp(buffer, "1.2.3") == 0);
|
|
}
|
|
|
|
MICROTEST(version_string, includes_preview) {
|
|
version_t ver = must_parse("1.2.3-alpha.1");
|
|
|
|
malunal_char_t buffer[32];
|
|
malunal_int32_t n = version_string(&ver, buffer, sizeof(buffer));
|
|
|
|
MICROTEST_EXPECT_GT(n, 0);
|
|
MICROTEST_EXPECT_TRUE(strcmp(buffer, "1.2.3-alpha.1") == 0);
|
|
}
|
|
|
|
MICROTEST(version_string, includes_build) {
|
|
version_t ver = must_parse("1.2.3+build.5");
|
|
|
|
malunal_char_t buffer[32];
|
|
malunal_int32_t n = version_string(&ver, buffer, sizeof(buffer));
|
|
|
|
MICROTEST_EXPECT_GT(n, 0);
|
|
MICROTEST_EXPECT_TRUE(strcmp(buffer, "1.2.3+build.5") == 0);
|
|
}
|
|
|
|
MICROTEST(version_string, includes_preview_and_build) {
|
|
version_t ver = must_parse("1.2.3-alpha.1+build.5");
|
|
|
|
malunal_char_t buffer[32];
|
|
malunal_int32_t n = version_string(&ver, buffer, sizeof(buffer));
|
|
|
|
MICROTEST_EXPECT_GT(n, 0);
|
|
MICROTEST_EXPECT_TRUE(strcmp(buffer, "1.2.3-alpha.1+build.5") == 0);
|
|
}
|
|
|
|
MICROTEST(version_string, too_small_buffer_fails) {
|
|
version_t ver = must_parse("1.2.3-alpha.1+build.5");
|
|
|
|
malunal_char_t buffer[5];
|
|
malunal_int32_t n = version_string(&ver, buffer, sizeof(buffer));
|
|
|
|
MICROTEST_EXPECT_EQ(n, -1);
|
|
}
|
|
|
|
MICROTEST(version_string, exact_size_buffer_succeeds) {
|
|
/* "1.2.3" is 5 characters plus a null terminator. */
|
|
version_t ver = must_parse("1.2.3");
|
|
|
|
malunal_char_t buffer[6];
|
|
malunal_int32_t n = version_string(&ver, buffer, sizeof(buffer));
|
|
|
|
MICROTEST_EXPECT_EQ(n, 5);
|
|
MICROTEST_EXPECT_TRUE(strcmp(buffer, "1.2.3") == 0);
|
|
}
|
|
|
|
MICROTEST(version_string, one_byte_too_small_fails) {
|
|
version_t ver = must_parse("1.2.3");
|
|
|
|
malunal_char_t buffer[5];
|
|
malunal_int32_t n = version_string(&ver, buffer, sizeof(buffer));
|
|
|
|
MICROTEST_EXPECT_EQ(n, -1);
|
|
}
|
|
|
|
MICROTEST(version_string, null_self_fails) {
|
|
malunal_char_t buffer[32];
|
|
malunal_int32_t n = version_string(null, buffer, sizeof(buffer));
|
|
|
|
MICROTEST_EXPECT_EQ(n, -1);
|
|
}
|
|
|
|
MICROTEST(version_string, null_buffer_fails) {
|
|
version_t ver = must_parse("1.2.3");
|
|
malunal_int32_t n = version_string(&ver, null, 32);
|
|
|
|
MICROTEST_EXPECT_EQ(n, -1);
|
|
}
|
|
|
|
MICROTEST(version_string, zero_length_fails) {
|
|
version_t ver = must_parse("1.2.3");
|
|
malunal_char_t buffer[32];
|
|
malunal_int32_t n = version_string(&ver, buffer, 0);
|
|
|
|
MICROTEST_EXPECT_EQ(n, -1);
|
|
}
|
|
|
|
MICROTEST_MAIN()
|