]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
test-string-util: include a copy of rpm's version comparison tests
authorZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Tue, 17 May 2022 12:33:08 +0000 (14:33 +0200)
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Tue, 17 May 2022 15:15:16 +0000 (17:15 +0200)
We said that strverscmp_improved() is similar to rpm, so it's nice to include
their tests too so we can pin down the differences.

Our test is changed to print older<newer instead of newer>older.
(I know the computer doesn't care, but I find it much harder to think about
when newer is on the left…)

The rpm test strings are copied from
https://github.com/rpm-software-management/rpm/blob/master/tests/rpmvercmp.at.
rpmio is licensed GPL OR LGPL, so we can do that without any issue.
(I think it could be argued as "fair use" anyway, but that's not necessary
in this case.)
I kept the original form as much as possible so it'll be easy to copy things
back and forth in the future.

src/test/test-string-util.c

index 00163d501ecfc3d8a9b85fa97af6c9836ef4e41a..d0a4eca3906e56b87d82bd634f2f5fd03b27b74b 100644 (file)
@@ -828,13 +828,24 @@ TEST(string_contains_word) {
         assert_se(!string_contains_word("a:b:cc", ":#", ":cc"));
 }
 
-static void test_strverscmp_improved_one(const char *newer, const char *older) {
-        log_info("/* %s(%s, %s) */", __func__, strnull(newer), strnull(older));
+static void test_strverscmp_improved_one(const char* a, const char *b, int expected) {
+        int r = strverscmp_improved(a, b);
+
+        log_info("'%s' %s '%s'%s",
+                 strnull(a),
+                 r > 0 ? ">" : r < 0 ? "<" : "==",
+                 strnull(b),
+                 r == expected ? "" : " !!!!!!!!!!!!!");
+        assert_se(r == expected);
+}
+
+static void test_strverscmp_improved_newer(const char *older, const char *newer) {
+        test_strverscmp_improved_one(older, newer, -1);
 
-        assert_se(strverscmp_improved(newer, newer) == 0);
-        assert_se(strverscmp_improved(newer, older) >  0);
-        assert_se(strverscmp_improved(older, newer) <  0);
         assert_se(strverscmp_improved(older, older) == 0);
+        assert_se(strverscmp_improved(older, newer) < 0);
+        assert_se(strverscmp_improved(newer, older) > 0);
+        assert_se(strverscmp_improved(newer, newer) == 0);
 }
 
 TEST(strverscmp_improved) {
@@ -868,43 +879,189 @@ TEST(strverscmp_improved) {
 
         STRV_FOREACH(p, versions)
                 STRV_FOREACH(q, p + 1)
-                        test_strverscmp_improved_one(*q, *p);
-
-        test_strverscmp_improved_one("123.45-67.89", "123.45-67.88");
-        test_strverscmp_improved_one("123.45-67.89a", "123.45-67.89");
-        test_strverscmp_improved_one("123.45-67.89", "123.45-67.ab");
-        test_strverscmp_improved_one("123.45-67.89", "123.45-67.9");
-        test_strverscmp_improved_one("123.45-67.89", "123.45-67");
-        test_strverscmp_improved_one("123.45-67.89", "123.45-66.89");
-        test_strverscmp_improved_one("123.45-67.89", "123.45-9.99");
-        test_strverscmp_improved_one("123.45-67.89", "123.42-99.99");
-        test_strverscmp_improved_one("123.45-67.89", "123-99.99");
+                        test_strverscmp_improved_newer(*p, *q);
+
+        test_strverscmp_improved_newer("123.45-67.88", "123.45-67.89");
+        test_strverscmp_improved_newer("123.45-67.89", "123.45-67.89a");
+        test_strverscmp_improved_newer("123.45-67.ab", "123.45-67.89");
+        test_strverscmp_improved_newer("123.45-67.9", "123.45-67.89");
+        test_strverscmp_improved_newer("123.45-67", "123.45-67.89");
+        test_strverscmp_improved_newer("123.45-66.89", "123.45-67.89");
+        test_strverscmp_improved_newer("123.45-9.99", "123.45-67.89");
+        test_strverscmp_improved_newer("123.42-99.99", "123.45-67.89");
+        test_strverscmp_improved_newer("123-99.99", "123.45-67.89");
 
         /* '~' : pre-releases */
-        test_strverscmp_improved_one("123.45-67.89", "123~rc1-99.99");
-        test_strverscmp_improved_one("123-45.67.89", "123~rc1-99.99");
-        test_strverscmp_improved_one("123~rc2-67.89", "123~rc1-99.99");
-        test_strverscmp_improved_one("123^aa2-67.89", "123~rc1-99.99");
-        test_strverscmp_improved_one("123aa2-67.89", "123~rc1-99.99");
+        test_strverscmp_improved_newer("123~rc1-99.99", "123.45-67.89");
+        test_strverscmp_improved_newer("123~rc1-99.99", "123-45.67.89");
+        test_strverscmp_improved_newer("123~rc1-99.99", "123~rc2-67.89");
+        test_strverscmp_improved_newer("123~rc1-99.99", "123^aa2-67.89");
+        test_strverscmp_improved_newer("123~rc1-99.99", "123aa2-67.89");
 
         /* '-' : separator between version and release. */
-        test_strverscmp_improved_one("123.45-67.89", "123-99.99");
-        test_strverscmp_improved_one("123^aa2-67.89", "123-99.99");
-        test_strverscmp_improved_one("123aa2-67.89", "123-99.99");
+        test_strverscmp_improved_newer("123-99.99", "123.45-67.89");
+        test_strverscmp_improved_newer("123-99.99", "123^aa2-67.89");
+        test_strverscmp_improved_newer("123-99.99", "123aa2-67.89");
 
         /* '^' : patch releases */
-        test_strverscmp_improved_one("123.45-67.89", "123^45-67.89");
-        test_strverscmp_improved_one("123^aa2-67.89", "123^aa1-99.99");
-        test_strverscmp_improved_one("123aa2-67.89", "123^aa2-67.89");
+        test_strverscmp_improved_newer("123^45-67.89", "123.45-67.89");
+        test_strverscmp_improved_newer("123^aa1-99.99", "123^aa2-67.89");
+        test_strverscmp_improved_newer("123^aa2-67.89", "123aa2-67.89");
 
         /* '.' : point release */
-        test_strverscmp_improved_one("123aa2-67.89", "123.aa2-67.89");
-        test_strverscmp_improved_one("123.ab2-67.89", "123.aa2-67.89");
+        test_strverscmp_improved_newer("123.aa2-67.89", "123aa2-67.89");
+        test_strverscmp_improved_newer("123.aa2-67.89", "123.ab2-67.89");
 
         /* invalid characters */
         assert_se(strverscmp_improved("123_aa2-67.89", "123aa+2-67.89") == 0);
 }
 
+#define RPMVERCMP(a, b, c) \
+        test_strverscmp_improved_one(STRINGIFY(a), STRINGIFY(b), (c))
+
+TEST(strverscmp_improved_rpm) {
+        /* Tests copied from rmp's rpmio test suite, under the LGPL license:
+         * https://github.com/rpm-software-management/rpm/blob/master/tests/rpmvercmp.at.
+         * The original form is retained for easy comparisons and updates.
+         */
+
+        RPMVERCMP(1.0, 1.0, 0);
+        RPMVERCMP(1.0, 2.0, -1);
+        RPMVERCMP(2.0, 1.0, 1);
+
+        RPMVERCMP(2.0.1, 2.0.1, 0);
+        RPMVERCMP(2.0, 2.0.1, -1);
+        RPMVERCMP(2.0.1, 2.0, 1);
+
+        RPMVERCMP(2.0.1a, 2.0.1a, 0);
+        RPMVERCMP(2.0.1a, 2.0.1, 1);
+        RPMVERCMP(2.0.1, 2.0.1a, -1);
+
+        RPMVERCMP(5.5p1, 5.5p1, 0);
+        RPMVERCMP(5.5p1, 5.5p2, -1);
+        RPMVERCMP(5.5p2, 5.5p1, 1);
+
+        RPMVERCMP(5.5p10, 5.5p10, 0);
+        RPMVERCMP(5.5p1, 5.5p10, -1);
+        RPMVERCMP(5.5p10, 5.5p1, 1);
+
+        RPMVERCMP(10xyz, 10.1xyz, 1);    /* Note: this is reversed from rpm's vercmp */
+        RPMVERCMP(10.1xyz, 10xyz, -1);   /* Note: this is reversed from rpm's vercmp */
+
+        RPMVERCMP(xyz10, xyz10, 0);
+        RPMVERCMP(xyz10, xyz10.1, -1);
+        RPMVERCMP(xyz10.1, xyz10, 1);
+
+        RPMVERCMP(xyz.4, xyz.4, 0);
+        RPMVERCMP(xyz.4, 8, -1);
+        RPMVERCMP(8, xyz.4, 1);
+        RPMVERCMP(xyz.4, 2, -1);
+        RPMVERCMP(2, xyz.4, 1);
+
+        RPMVERCMP(5.5p2, 5.6p1, -1);
+        RPMVERCMP(5.6p1, 5.5p2, 1);
+
+        RPMVERCMP(5.6p1, 6.5p1, -1);
+        RPMVERCMP(6.5p1, 5.6p1, 1);
+
+        RPMVERCMP(6.0.rc1, 6.0, 1);
+        RPMVERCMP(6.0, 6.0.rc1, -1);
+
+        RPMVERCMP(10b2, 10a1, 1);
+        RPMVERCMP(10a2, 10b2, -1);
+
+        RPMVERCMP(1.0aa, 1.0aa, 0);
+        RPMVERCMP(1.0a, 1.0aa, -1);
+        RPMVERCMP(1.0aa, 1.0a, 1);
+
+        RPMVERCMP(10.0001, 10.0001, 0);
+        RPMVERCMP(10.0001, 10.1, 0);
+        RPMVERCMP(10.1, 10.0001, 0);
+        RPMVERCMP(10.0001, 10.0039, -1);
+        RPMVERCMP(10.0039, 10.0001, 1);
+
+        RPMVERCMP(4.999.9, 5.0, -1);
+        RPMVERCMP(5.0, 4.999.9, 1);
+
+        RPMVERCMP(20101121, 20101121, 0);
+        RPMVERCMP(20101121, 20101122, -1);
+        RPMVERCMP(20101122, 20101121, 1);
+
+        RPMVERCMP(2_0, 2_0, 0);
+        RPMVERCMP(2.0, 2_0, -1);   /* Note: in rpm those compare equal */
+        RPMVERCMP(2_0, 2.0, 1);    /* Note: in rpm those compare equal */
+
+        /* RhBug:178798 case */
+        RPMVERCMP(a, a, 0);
+        RPMVERCMP(a+, a+, 0);
+        RPMVERCMP(a+, a_, 0);
+        RPMVERCMP(a_, a+, 0);
+        RPMVERCMP(+a, +a, 0);
+        RPMVERCMP(+a, _a, 0);
+        RPMVERCMP(_a, +a, 0);
+        RPMVERCMP(+_, +_, 0);
+        RPMVERCMP(_+, +_, 0);
+        RPMVERCMP(_+, _+, 0);
+        RPMVERCMP(+, _, 0);
+        RPMVERCMP(_, +, 0);
+
+        /* Basic testcases for tilde sorting */
+        RPMVERCMP(1.0~rc1, 1.0~rc1, 0);
+        RPMVERCMP(1.0~rc1, 1.0, -1);
+        RPMVERCMP(1.0, 1.0~rc1, 1);
+        RPMVERCMP(1.0~rc1, 1.0~rc2, -1);
+        RPMVERCMP(1.0~rc2, 1.0~rc1, 1);
+        RPMVERCMP(1.0~rc1~git123, 1.0~rc1~git123, 0);
+        RPMVERCMP(1.0~rc1~git123, 1.0~rc1, -1);
+        RPMVERCMP(1.0~rc1, 1.0~rc1~git123, 1);
+
+        /* Basic testcases for caret sorting */
+        RPMVERCMP(1.0^, 1.0^, 0);
+        RPMVERCMP(1.0^, 1.0, 1);
+        RPMVERCMP(1.0, 1.0^, -1);
+        RPMVERCMP(1.0^git1, 1.0^git1, 0);
+        RPMVERCMP(1.0^git1, 1.0, 1);
+        RPMVERCMP(1.0, 1.0^git1, -1);
+        RPMVERCMP(1.0^git1, 1.0^git2, -1);
+        RPMVERCMP(1.0^git2, 1.0^git1, 1);
+        RPMVERCMP(1.0^git1, 1.01, -1);
+        RPMVERCMP(1.01, 1.0^git1, 1);
+        RPMVERCMP(1.0^20160101, 1.0^20160101, 0);
+        RPMVERCMP(1.0^20160101, 1.0.1, -1);
+        RPMVERCMP(1.0.1, 1.0^20160101, 1);
+        RPMVERCMP(1.0^20160101^git1, 1.0^20160101^git1, 0);
+        RPMVERCMP(1.0^20160102, 1.0^20160101^git1, 1);
+        RPMVERCMP(1.0^20160101^git1, 1.0^20160102, -1);
+
+        /* Basic testcases for tilde and caret sorting */
+        RPMVERCMP(1.0~rc1^git1, 1.0~rc1^git1, 0);
+        RPMVERCMP(1.0~rc1^git1, 1.0~rc1, 1);
+        RPMVERCMP(1.0~rc1, 1.0~rc1^git1, -1);
+        RPMVERCMP(1.0^git1~pre, 1.0^git1~pre, 0);
+        RPMVERCMP(1.0^git1, 1.0^git1~pre, 1);
+        RPMVERCMP(1.0^git1~pre, 1.0^git1, -1);
+
+        /* These are included here to document current, arguably buggy behaviors
+         * for reference purposes and for easy checking against unintended
+         * behavior changes. */
+        log_info("/* RPM version comparison oddities */");
+        /* RhBug:811992 case */
+        RPMVERCMP(1b.fc17, 1b.fc17, 0);
+        RPMVERCMP(1b.fc17, 1.fc17, 1); /* Note: this is reversed from rpm's vercmp, WAT! */
+        RPMVERCMP(1.fc17, 1b.fc17, -1);
+        RPMVERCMP(1g.fc17, 1g.fc17, 0);
+        RPMVERCMP(1g.fc17, 1.fc17, 1);
+        RPMVERCMP(1.fc17, 1g.fc17, -1);
+
+        /* Non-ascii characters are considered equal so these are all the same, eh… */
+        RPMVERCMP(1.1.α, 1.1.α, 0);
+        RPMVERCMP(1.1.α, 1.1.β, 0);
+        RPMVERCMP(1.1.β, 1.1.α, 0);
+        RPMVERCMP(1.1.αα, 1.1.α, 0);
+        RPMVERCMP(1.1.α, 1.1.ββ, 0);
+        RPMVERCMP(1.1.ββ, 1.1.αα, 0);
+}
+
 TEST(strextendf) {
         _cleanup_free_ char *p = NULL;