]> git.ipfire.org Git - thirdparty/git.git/commitdiff
t/unit-tests: update to 10e96bc
authorPatrick Steinhardt <ps@pks.im>
Mon, 22 Sep 2025 13:16:11 +0000 (15:16 +0200)
committerJunio C Hamano <gitster@pobox.com>
Mon, 22 Sep 2025 17:09:03 +0000 (10:09 -0700)
Update to 10e96bc (Merge pull request #127 from
pks-gitlab/pks-ci-improvements, 2025-09-22). This commit includes a
couple of changes:

  - The GitHub CI has been updated to include a 32 bit CI job.
    Furthermore, the jobs now compile with "-Werror" and more warnings
    enabled.

  - An issue was addressed where `uintptr_t` is not available on
    NonStop [1].

  - The clar selftests have been restructured so that it is now possible
    to add small test suites more readily. This was done to add tests
    for the above addressed issue, where we now use "%p" to print
    pointers in a platform dependent way.

  - An issue was addressed where the test output had a trailing
    whitespace with certain output formats, which caused whitespace
    issues in the test expectation files.

[1]: <01c101dc2842$38903640$a9b0a2c0$@nexbridge.com>

Reported-by: Randall S. Becker <rsbecker@nexbridge.com>
Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
24 files changed:
t/unit-tests/clar/.github/workflows/ci.yml
t/unit-tests/clar/clar.c
t/unit-tests/clar/clar/print.h
t/unit-tests/clar/generate.py
t/unit-tests/clar/test/CMakeLists.txt
t/unit-tests/clar/test/expected/help
t/unit-tests/clar/test/expected/quiet
t/unit-tests/clar/test/expected/specific_test
t/unit-tests/clar/test/expected/stop_on_failure
t/unit-tests/clar/test/expected/suite_names
t/unit-tests/clar/test/expected/summary.xml
t/unit-tests/clar/test/expected/summary_with_filename
t/unit-tests/clar/test/expected/summary_without_filename
t/unit-tests/clar/test/expected/tap
t/unit-tests/clar/test/expected/without_arguments
t/unit-tests/clar/test/main.c
t/unit-tests/clar/test/selftest.c
t/unit-tests/clar/test/selftest.h
t/unit-tests/clar/test/selftest_suite/CMakeLists.txt [deleted file]
t/unit-tests/clar/test/suites/CMakeLists.txt [new file with mode: 0644]
t/unit-tests/clar/test/suites/combined.c [moved from t/unit-tests/clar/test/selftest_suite/selftest_suite.c with 72% similarity]
t/unit-tests/clar/test/suites/main.c [moved from t/unit-tests/clar/test/selftest_suite/main.c with 100% similarity]
t/unit-tests/clar/test/suites/pointer.c [new file with mode: 0644]
t/unit-tests/clar/test/suites/resources/test/file [moved from t/unit-tests/clar/test/selftest_suite/resources/test/file with 100% similarity]

index c41f55f6ff5befbf7b0e6c6d175bcfa4fdffe760..4d4724222c3e89f7ec3a3355e56ea0a79becb5d4 100644 (file)
@@ -13,30 +13,47 @@ jobs:
         platform:
           - os: ubuntu-latest
             generator: Unix Makefiles
+            env:
+              CFLAGS: "-Werror -Wall -Wextra"
           - os: ubuntu-latest
             generator: Unix Makefiles
             env:
               CC: "clang"
-              CFLAGS: "-fsanitize=leak"
+              CFLAGS: "-Werror -Wall -Wextra -fsanitize=leak"
+          - os: ubuntu-latest
+            generator: Unix Makefiles
+            image: i386/debian:latest
+            env:
+              CFLAGS: "-Werror -Wall -Wextra"
           - os: macos-latest
             generator: Unix Makefiles
+            env:
+              CFLAGS: "-Werror -Wall -Wextra"
           - os: windows-latest
             generator: Visual Studio 17 2022
           - os: windows-latest
             generator: MSYS Makefiles
+            env:
+              CFLAGS: "-Werror -Wall -Wextra"
           - os: windows-latest
             generator: MinGW Makefiles
+            env:
+              CFLAGS: "-Werror -Wall -Wextra"
       fail-fast: false
 
     runs-on: ${{ matrix.platform.os }}
+    container: ${{matrix.platform.image}}
 
     env:
       CC: ${{matrix.platform.env.CC}}
       CFLAGS: ${{matrix.platform.env.CFLAGS}}
 
     steps:
+    - name: Prepare 32 bit container image
+      if: matrix.platform.image == 'i386/debian:latest'
+      run: apt -q update && apt -q -y install cmake gcc libc6-amd64 lib64stdc++6 make python3
     - name: Check out
-      uses: actions/checkout@v2
+      uses: actions/checkout@v4
     - name: Build
       shell: bash
       run: |
index 80c5359425213adae40b54bc429ea054397628dd..d6176e50b2214b2b90cf110ba1cdf4aa953bbfd9 100644 (file)
@@ -195,7 +195,7 @@ struct clar_suite {
 };
 
 /* From clar_print_*.c */
-static void clar_print_init(int test_count, int suite_count, const char *suite_names);
+static void clar_print_init(int test_count, int suite_count);
 static void clar_print_shutdown(int test_count, int suite_count, int error_count);
 static void clar_print_error(int num, const struct clar_report *report, const struct clar_error *error);
 static void clar_print_ontest(const char *suite_name, const char *test_name, int test_number, enum cl_test_status failed);
@@ -592,11 +592,7 @@ clar_test_init(int argc, char **argv)
        if (argc > 1)
                clar_parse_args(argc, argv);
 
-       clar_print_init(
-               (int)_clar_callback_count,
-               (int)_clar_suite_count,
-               ""
-       );
+       clar_print_init((int)_clar_callback_count, (int)_clar_suite_count);
 
        if (!_clar.summary_filename &&
            (summary_env = getenv("CLAR_SUMMARY")) != NULL) {
@@ -875,8 +871,7 @@ void clar__assert_equal(
                void *p1 = va_arg(args, void *), *p2 = va_arg(args, void *);
                is_equal = (p1 == p2);
                if (!is_equal)
-                       p_snprintf(buf, sizeof(buf), "0x%"PRIxPTR" != 0x%"PRIxPTR,
-                                  (uintptr_t)p1, (uintptr_t)p2);
+                       p_snprintf(buf, sizeof(buf), "%p != %p", p1, p2);
        }
        else {
                int i1 = va_arg(args, int), i2 = va_arg(args, int);
index 0282aaa13810d8acc121d566fd0285a2893a2089..89b66591d7556d997a97c5f6917aaa9e2d7d70fd 100644 (file)
@@ -1,13 +1,13 @@
 /* clap: clar protocol, the traditional clar output format */
 
-static void clar_print_clap_init(int test_count, int suite_count, const char *suite_names)
+static void clar_print_clap_init(int test_count, int suite_count)
 {
        (void)test_count;
 
        if (_clar.verbosity < 0)
                return;
 
-       printf("Loaded %d suites: %s\n", (int)suite_count, suite_names);
+       printf("Loaded %d suites:\n", (int)suite_count);
        printf("Started (test status codes: OK='.' FAILURE='F' SKIPPED='S')\n");
 }
 
@@ -103,11 +103,10 @@ static void clar_print_clap_onabort(const char *fmt, va_list arg)
 
 /* tap: test anywhere protocol format */
 
-static void clar_print_tap_init(int test_count, int suite_count, const char *suite_names)
+static void clar_print_tap_init(int test_count, int suite_count)
 {
        (void)test_count;
        (void)suite_count;
-       (void)suite_names;
        printf("TAP version 13\n");
 }
 
@@ -207,9 +206,9 @@ static void clar_print_tap_onabort(const char *fmt, va_list arg)
                } \
        } while (0)
 
-static void clar_print_init(int test_count, int suite_count, const char *suite_names)
+static void clar_print_init(int test_count, int suite_count)
 {
-       PRINT(init, test_count, suite_count, suite_names);
+       PRINT(init, test_count, suite_count);
 }
 
 static void clar_print_shutdown(int test_count, int suite_count, int error_count)
index 80996ac3e718960f7fa1c3fd3a0aee6863654dbd..fd2f0ee83b55c50ae6a302a7e2afe4e60b6f6318 100755 (executable)
@@ -158,17 +158,24 @@ class TestSuite(object):
 
     def find_modules(self):
         modules = []
-        for root, _, files in os.walk(self.path):
-            module_root = root[len(self.path):]
-            module_root = [c for c in module_root.split(os.sep) if c]
 
-            tests_in_module = fnmatch.filter(files, "*.c")
+        if os.path.isfile(self.path):
+            full_path = os.path.abspath(self.path)
+            module_name = os.path.basename(self.path)
+            module_name = os.path.splitext(module_name)[0]
+            modules.append((full_path, module_name))
+        else:
+            for root, _, files in os.walk(self.path):
+                module_root = root[len(self.path):]
+                module_root = [c for c in module_root.split(os.sep) if c]
 
-            for test_file in tests_in_module:
-                full_path = os.path.join(root, test_file)
-                module_name = "_".join(module_root + [test_file[:-2]]).replace("-", "_")
+                tests_in_module = fnmatch.filter(files, "*.c")
 
-                modules.append((full_path, module_name))
+                for test_file in tests_in_module:
+                    full_path = os.path.join(root, test_file)
+                    module_name = "_".join(module_root + [test_file[:-2]]).replace("-", "_")
+
+                    modules.append((full_path, module_name))
 
         return modules
 
@@ -217,6 +224,7 @@ class TestSuite(object):
 
     def write(self):
         output = os.path.join(self.output, 'clar.suite')
+        os.makedirs(self.output, exist_ok=True)
 
         if not self.should_generate(output):
             return False
@@ -258,7 +266,11 @@ if __name__ == '__main__':
         sys.exit(1)
 
     path = args.pop() if args else '.'
+    if os.path.isfile(path) and not options.output:
+        print("Must provide --output when specifying a file")
+        sys.exit(1)
     output = options.output or path
+
     suite = TestSuite(path, output)
     suite.load(options.force)
     suite.disable(options.excluded)
index 96abd6ed93177f8d6f59dedd108b25035fc11380..f24016643973d27b115467b9510fd140723d7239 100644 (file)
@@ -1,5 +1,3 @@
-add_subdirectory(selftest_suite)
-
 find_package(Python COMPONENTS Interpreter REQUIRED)
 
 add_custom_command(OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/clar.suite"
@@ -40,15 +38,12 @@ target_include_directories(selftest PRIVATE
 )
 target_link_libraries(selftest clar)
 
-add_test(NAME build_selftest_suite
-       COMMAND "${CMAKE_COMMAND}" --build "${CMAKE_BINARY_DIR}" --config "$<CONFIG>" --target selftest_suite
-)
-set_tests_properties(build_selftest_suite PROPERTIES FIXTURES_SETUP clar_test_fixture)
-
 add_test(NAME build_selftest
        COMMAND "${CMAKE_COMMAND}" --build "${CMAKE_BINARY_DIR}" --config "$<CONFIG>" --target selftest
 )
 set_tests_properties(build_selftest PROPERTIES FIXTURES_SETUP clar_test_fixture)
 
-add_test(NAME selftest COMMAND "${CMAKE_CURRENT_BINARY_DIR}/selftest" "$<TARGET_FILE:selftest_suite>")
+add_subdirectory(suites)
+
+add_test(NAME selftest COMMAND "${CMAKE_CURRENT_BINARY_DIR}/selftest" $<TARGET_FILE_DIR:combined_suite>)
 set_tests_properties(selftest PROPERTIES FIXTURES_REQUIRED clar_test_fixture)
index 4b2be69f9731b32fb3f008e818c50456d9228377..9428def2d719a2da20aca2e45794f97d92df5400 100644 (file)
@@ -1,4 +1,4 @@
-Usage: selftest [options]
+Usage: combined [options]
 
 Options:
   -sname        Run only the suite with `name` (can go to individual test name)
index 975164147ff9463866365e0f7b083c446a448c02..280c99d8ad5eba1d6f998621854ca65feadcd782 100644 (file)
@@ -1,49 +1,44 @@
   1) Failure:
-selftest::suite::1 [file:42]
+combined::1 [file:42]
   Function call failed: -1
 
   2) Failure:
-selftest::suite::2 [file:42]
+combined::2 [file:42]
   Expression is not true: 100 == 101
 
   3) Failure:
-selftest::suite::strings [file:42]
+combined::strings [file:42]
   String mismatch: "mismatched" != actual ("this one fails")
   'mismatched' != 'expected' (at byte 0)
 
   4) Failure:
-selftest::suite::strings_with_length [file:42]
+combined::strings_with_length [file:42]
   String mismatch: "exactly" != actual ("this one fails")
   'exa' != 'exp' (at byte 2)
 
   5) Failure:
-selftest::suite::int [file:42]
+combined::int [file:42]
   101 != value ("extra note on failing test")
   101 != 100
 
   6) Failure:
-selftest::suite::int_fmt [file:42]
+combined::int_fmt [file:42]
   022 != value
   0022 != 0144
 
   7) Failure:
-selftest::suite::bool [file:42]
+combined::bool [file:42]
   0 != value
   0 != 1
 
   8) Failure:
-selftest::suite::ptr [file:42]
-  Pointer mismatch: p1 != p2
-  0x1 != 0x2
-
-  9) Failure:
-selftest::suite::multiline_description [file:42]
+combined::multiline_description [file:42]
   Function call failed: -1
   description line 1
   description line 2
 
-  10) Failure:
-selftest::suite::null_string [file:42]
+  9) Failure:
+combined::null_string [file:42]
   String mismatch: "expected" != actual ("this one fails")
   'expected' != NULL
 
index afa2150980442bf7ce0d7d39d53dcf50843ab328..6c22e9f507d4e5263b5a9eb9dab9f321865856ad 100644 (file)
@@ -1,9 +1,9 @@
-Loaded 1 suites: 
+Loaded 1 suites:
 Started (test status codes: OK='.' FAILURE='F' SKIPPED='S')
 F
 
   1) Failure:
-selftest::suite::bool [file:42]
+combined::bool [file:42]
   0 != value
   0 != 1
 
index 1156ade0f92b6fe6d8db6276996d1cbe1d25bb61..c23610754f839bd480b6b137d662829205c5f7f4 100644 (file)
@@ -1,8 +1,8 @@
-Loaded 1 suites: 
+Loaded 1 suites:
 Started (test status codes: OK='.' FAILURE='F' SKIPPED='S')
 F
 
   1) Failure:
-selftest::suite::1 [file:42]
+combined::1 [file:42]
   Function call failed: -1
 
index 1b0f6397eb315b30b25e5d6b92d0e4a84bec01cf..10d1538427ecb7ba11e8c65063e97da27856e20b 100644 (file)
@@ -1,2 +1,2 @@
 Test suites (use -s<name> to run just one):
-   0: selftest::suite
+   0: combined
index 9034a03d1fa4f2aa779c779e2160a1bc00529912..9a89d43a593152f8dda5a758a92521ec52250428 100644 (file)
                <testcase name="bool" classname="selftest" time="0.00">
                        <failure type="assert"><![CDATA[0 != value
 0 != 1]]></failure>
-               </testcase>
-               <testcase name="ptr" classname="selftest" time="0.00">
-                       <failure type="assert"><![CDATA[Pointer mismatch: p1 != p2
-0x1 != 0x2]]></failure>
                </testcase>
                <testcase name="multiline_description" classname="selftest" time="0.00">
                        <failure type="assert"><![CDATA[Function call failed: âˆ’1
index a5f4d4053708969f5cc9cc06eb5223548155c90a..460160791d14c005730167dc8bce5f088dd93f17 100644 (file)
@@ -1,53 +1,48 @@
-Loaded 1 suites: 
+Loaded 1 suites:
 Started (test status codes: OK='.' FAILURE='F' SKIPPED='S')
-FFFFFFFFFF
+FFFFFFFFF
 
   1) Failure:
-selftest::suite::1 [file:42]
+combined::1 [file:42]
   Function call failed: -1
 
   2) Failure:
-selftest::suite::2 [file:42]
+combined::2 [file:42]
   Expression is not true: 100 == 101
 
   3) Failure:
-selftest::suite::strings [file:42]
+combined::strings [file:42]
   String mismatch: "mismatched" != actual ("this one fails")
   'mismatched' != 'expected' (at byte 0)
 
   4) Failure:
-selftest::suite::strings_with_length [file:42]
+combined::strings_with_length [file:42]
   String mismatch: "exactly" != actual ("this one fails")
   'exa' != 'exp' (at byte 2)
 
   5) Failure:
-selftest::suite::int [file:42]
+combined::int [file:42]
   101 != value ("extra note on failing test")
   101 != 100
 
   6) Failure:
-selftest::suite::int_fmt [file:42]
+combined::int_fmt [file:42]
   022 != value
   0022 != 0144
 
   7) Failure:
-selftest::suite::bool [file:42]
+combined::bool [file:42]
   0 != value
   0 != 1
 
   8) Failure:
-selftest::suite::ptr [file:42]
-  Pointer mismatch: p1 != p2
-  0x1 != 0x2
-
-  9) Failure:
-selftest::suite::multiline_description [file:42]
+combined::multiline_description [file:42]
   Function call failed: -1
   description line 1
   description line 2
 
-  10) Failure:
-selftest::suite::null_string [file:42]
+  9) Failure:
+combined::null_string [file:42]
   String mismatch: "expected" != actual ("this one fails")
   'expected' != NULL
 
index 5984502773e7a802cd1915164ae6d896d8460a6b..7874c1d98bc01b303c9690352e47bfcfab375b9e 100644 (file)
@@ -1,53 +1,48 @@
-Loaded 1 suites: 
+Loaded 1 suites:
 Started (test status codes: OK='.' FAILURE='F' SKIPPED='S')
-FFFFFFFFFF
+FFFFFFFFF
 
   1) Failure:
-selftest::suite::1 [file:42]
+combined::1 [file:42]
   Function call failed: -1
 
   2) Failure:
-selftest::suite::2 [file:42]
+combined::2 [file:42]
   Expression is not true: 100 == 101
 
   3) Failure:
-selftest::suite::strings [file:42]
+combined::strings [file:42]
   String mismatch: "mismatched" != actual ("this one fails")
   'mismatched' != 'expected' (at byte 0)
 
   4) Failure:
-selftest::suite::strings_with_length [file:42]
+combined::strings_with_length [file:42]
   String mismatch: "exactly" != actual ("this one fails")
   'exa' != 'exp' (at byte 2)
 
   5) Failure:
-selftest::suite::int [file:42]
+combined::int [file:42]
   101 != value ("extra note on failing test")
   101 != 100
 
   6) Failure:
-selftest::suite::int_fmt [file:42]
+combined::int_fmt [file:42]
   022 != value
   0022 != 0144
 
   7) Failure:
-selftest::suite::bool [file:42]
+combined::bool [file:42]
   0 != value
   0 != 1
 
   8) Failure:
-selftest::suite::ptr [file:42]
-  Pointer mismatch: p1 != p2
-  0x1 != 0x2
-
-  9) Failure:
-selftest::suite::multiline_description [file:42]
+combined::multiline_description [file:42]
   Function call failed: -1
   description line 1
   description line 2
 
-  10) Failure:
-selftest::suite::null_string [file:42]
+  9) Failure:
+combined::null_string [file:42]
   String mismatch: "expected" != actual ("this one fails")
   'expected' != NULL
 
index 3dc4973dfa10a84e7dc24c687781629551e3eecc..bddbd5dfe98b61d2bb083e302b5cf34b7c9d542d 100644 (file)
@@ -1,6 +1,6 @@
 TAP version 13
-# start of suite 1: selftest::suite
-not ok 1 - selftest::suite::1
+# start of suite 1: combined
+not ok 1 - combined::1
     ---
     reason: |
       Function call failed: -1
@@ -9,7 +9,7 @@ not ok 1 - selftest::suite::1
       line: 42
       function: 'func'
     ---
-not ok 2 - selftest::suite::2
+not ok 2 - combined::2
     ---
     reason: |
       Expression is not true: 100 == 101
@@ -18,7 +18,7 @@ not ok 2 - selftest::suite::2
       line: 42
       function: 'func'
     ---
-not ok 3 - selftest::suite::strings
+not ok 3 - combined::strings
     ---
     reason: |
       String mismatch: "mismatched" != actual ("this one fails")
@@ -28,7 +28,7 @@ not ok 3 - selftest::suite::strings
       line: 42
       function: 'func'
     ---
-not ok 4 - selftest::suite::strings_with_length
+not ok 4 - combined::strings_with_length
     ---
     reason: |
       String mismatch: "exactly" != actual ("this one fails")
@@ -38,7 +38,7 @@ not ok 4 - selftest::suite::strings_with_length
       line: 42
       function: 'func'
     ---
-not ok 5 - selftest::suite::int
+not ok 5 - combined::int
     ---
     reason: |
       101 != value ("extra note on failing test")
@@ -48,7 +48,7 @@ not ok 5 - selftest::suite::int
       line: 42
       function: 'func'
     ---
-not ok 6 - selftest::suite::int_fmt
+not ok 6 - combined::int_fmt
     ---
     reason: |
       022 != value
@@ -58,7 +58,7 @@ not ok 6 - selftest::suite::int_fmt
       line: 42
       function: 'func'
     ---
-not ok 7 - selftest::suite::bool
+not ok 7 - combined::bool
     ---
     reason: |
       0 != value
@@ -68,17 +68,7 @@ not ok 7 - selftest::suite::bool
       line: 42
       function: 'func'
     ---
-not ok 8 - selftest::suite::ptr
-    ---
-    reason: |
-      Pointer mismatch: p1 != p2
-      0x1 != 0x2
-    at:
-      file: 'file'
-      line: 42
-      function: 'func'
-    ---
-not ok 9 - selftest::suite::multiline_description
+not ok 8 - combined::multiline_description
     ---
     reason: |
       Function call failed: -1
@@ -89,7 +79,7 @@ not ok 9 - selftest::suite::multiline_description
       line: 42
       function: 'func'
     ---
-not ok 10 - selftest::suite::null_string
+not ok 9 - combined::null_string
     ---
     reason: |
       String mismatch: "expected" != actual ("this one fails")
@@ -99,4 +89,4 @@ not ok 10 - selftest::suite::null_string
       line: 42
       function: 'func'
     ---
-1..10
+1..9
index 08b67b874cb1c1698b2c2f73e83f8e9641f3f900..1111d418a060f7307f9ef3b15fe6374a53dbffc7 100644 (file)
@@ -1,53 +1,48 @@
-Loaded 1 suites: 
+Loaded 1 suites:
 Started (test status codes: OK='.' FAILURE='F' SKIPPED='S')
-FFFFFFFFFF
+FFFFFFFFF
 
   1) Failure:
-selftest::suite::1 [file:42]
+combined::1 [file:42]
   Function call failed: -1
 
   2) Failure:
-selftest::suite::2 [file:42]
+combined::2 [file:42]
   Expression is not true: 100 == 101
 
   3) Failure:
-selftest::suite::strings [file:42]
+combined::strings [file:42]
   String mismatch: "mismatched" != actual ("this one fails")
   'mismatched' != 'expected' (at byte 0)
 
   4) Failure:
-selftest::suite::strings_with_length [file:42]
+combined::strings_with_length [file:42]
   String mismatch: "exactly" != actual ("this one fails")
   'exa' != 'exp' (at byte 2)
 
   5) Failure:
-selftest::suite::int [file:42]
+combined::int [file:42]
   101 != value ("extra note on failing test")
   101 != 100
 
   6) Failure:
-selftest::suite::int_fmt [file:42]
+combined::int_fmt [file:42]
   022 != value
   0022 != 0144
 
   7) Failure:
-selftest::suite::bool [file:42]
+combined::bool [file:42]
   0 != value
   0 != 1
 
   8) Failure:
-selftest::suite::ptr [file:42]
-  Pointer mismatch: p1 != p2
-  0x1 != 0x2
-
-  9) Failure:
-selftest::suite::multiline_description [file:42]
+combined::multiline_description [file:42]
   Function call failed: -1
   description line 1
   description line 2
 
-  10) Failure:
-selftest::suite::null_string [file:42]
+  9) Failure:
+combined::null_string [file:42]
   String mismatch: "expected" != actual ("this one fails")
   'expected' != NULL
 
index b1ba2996f1365914de5bd9cf5566f05ff244bacb..94af4406437224a7394d004b18d81099451e80e1 100644 (file)
@@ -3,7 +3,7 @@
 
 #include "selftest.h"
 
-const char *selftest_binary_path;
+const char *selftest_suite_directory;
 
 #ifdef _WIN32
 int __cdecl main(int argc, char *argv[])
@@ -12,12 +12,12 @@ int main(int argc, char *argv[])
 #endif
 {
        if (argc < 2) {
-               fprintf(stderr, "usage: %s <selftest-suite-executable> <options>\n",
+               fprintf(stderr, "usage: %s <selftest-suite-directory> <options>\n",
                        argv[0]);
                exit(1);
        }
 
-       selftest_binary_path = argv[1];
+       selftest_suite_directory = argv[1];
        memmove(argv + 1, argv + 2, argc - 1);
        argc -= 1;
 
index abd585f4e4abb4c4f4f96bd86086a60fba6656ef..eed83e4512006d7675705f1d8cadceae11e76eb2 100644 (file)
@@ -59,38 +59,34 @@ static char *read_file(const char *path)
        return content;
 }
 
-static void run(const char *expected_output_file, int expected_error_code, ...)
+static char *execute(const char *suite, int expected_error_code, const char **args, size_t nargs)
 {
        SECURITY_ATTRIBUTES security_attributes = { 0 };
        PROCESS_INFORMATION process_info = { 0 };
        STARTUPINFO startup_info = { 0 };
+       char binary_path[4096] = { 0 };
        char cmdline[4096] = { 0 };
-       char *expected_output = NULL;
        char *output = NULL;
        HANDLE stdout_write;
        HANDLE stdout_read;
        DWORD exit_code;
-       va_list ap;
+       size_t i;
+
+       snprintf(binary_path, sizeof(binary_path), "%s/%s_suite.exe",
+                selftest_suite_directory, suite);
 
        /*
         * Assemble command line arguments. In theory we'd have to properly
         * quote them. In practice none of our tests actually care.
         */
-       va_start(ap, expected_error_code);
-       snprintf(cmdline, sizeof(cmdline), "selftest");
-       while (1) {
+       snprintf(cmdline, sizeof(cmdline), suite);
+       for (i = 0; i < nargs; i++) {
                size_t cmdline_len = strlen(cmdline);
-               const char *arg;
-
-               arg = va_arg(ap, const char *);
-               if (!arg)
-                       break;
-
+               const char *arg = args[i];
                cl_assert(cmdline_len + strlen(arg) < sizeof(cmdline));
                snprintf(cmdline + cmdline_len, sizeof(cmdline) - cmdline_len,
                         " %s", arg);
        }
-       va_end(ap);
 
        /*
         * Create a pipe that we will use to read data from the child process.
@@ -110,17 +106,39 @@ static void run(const char *expected_output_file, int expected_error_code, ...)
        startup_info.hStdError = stdout_write;
        startup_info.hStdOutput = stdout_write;
        startup_info.dwFlags |= STARTF_USESTDHANDLES;
-       cl_assert_equal_b(1, CreateProcess(selftest_binary_path, cmdline, NULL, NULL, TRUE,
+       cl_assert_equal_b(1, CreateProcess(binary_path, cmdline, NULL, NULL, TRUE,
                                           0, NULL, NULL, &startup_info, &process_info));
        cl_assert_equal_b(1, CloseHandle(stdout_write));
 
        output = read_full(stdout_read, 1);
        cl_assert_equal_b(1, CloseHandle(stdout_read));
        cl_assert_equal_b(1, GetExitCodeProcess(process_info.hProcess, &exit_code));
+       cl_assert_equal_i(exit_code, expected_error_code);
+
+       return output;
+}
+
+static void assert_output(const char *suite, const char *expected_output_file, int expected_error_code, ...)
+{
+       char *expected_output = NULL;
+       char *output = NULL;
+       const char *args[16];
+       va_list ap;
+       size_t i;
+
+       va_start(ap, expected_error_code);
+       for (i = 0; ; i++) {
+               const char *arg = va_arg(ap, const char *);
+               if (!arg)
+                       break;
+               cl_assert(i < sizeof(args) / sizeof(*args));
+               args[i] = arg;
+       }
+       va_end(ap);
 
+       output = execute(suite, expected_error_code, args, i);
        expected_output = read_file(cl_fixture(expected_output_file));
        cl_assert_equal_s(output, expected_output);
-       cl_assert_equal_i(exit_code, expected_error_code);
 
        free(expected_output);
        free(output);
@@ -180,29 +198,25 @@ static char *read_file(const char *path)
        return data;
 }
 
-static void run(const char *expected_output_file, int expected_error_code, ...)
+static char *execute(const char *suite, int expected_error_code, const char **args, size_t nargs)
 {
-       const char *argv[16];
        int pipe_fds[2];
-       va_list ap;
        pid_t pid;
-       int i;
-
-       va_start(ap, expected_error_code);
-       argv[0] = "selftest";
-       for (i = 1; ; i++) {
-               cl_assert(i < sizeof(argv) / sizeof(*argv));
-
-               argv[i] = va_arg(ap, const char *);
-               if (!argv[i])
-                       break;
-       }
-       va_end(ap);
 
        cl_must_pass(pipe(pipe_fds));
 
        pid = fork();
        if (!pid) {
+               const char *final_args[17] = { NULL };
+               char binary_path[4096];
+               size_t len = 0;
+               size_t i;
+
+               cl_assert(nargs < sizeof(final_args) / sizeof(*final_args));
+               final_args[0] = suite;
+               for (i = 0; i < nargs; i++)
+                       final_args[i + 1] = args[i];
+
                if (dup2(pipe_fds[1], STDOUT_FILENO) < 0 ||
                    dup2(pipe_fds[1], STDERR_FILENO) < 0 ||
                    close(0) < 0 ||
@@ -210,11 +224,29 @@ static void run(const char *expected_output_file, int expected_error_code, ...)
                    close(pipe_fds[1]) < 0)
                        exit(1);
 
-               execv(selftest_binary_path, (char **) argv);
+               cl_assert(len + strlen(selftest_suite_directory) < sizeof(binary_path));
+               strcpy(binary_path, selftest_suite_directory);
+               len += strlen(selftest_suite_directory);
+
+               cl_assert(len + 1 < sizeof(binary_path));
+               binary_path[len] = '/';
+               len += 1;
+
+               cl_assert(len + strlen(suite) < sizeof(binary_path));
+               strcpy(binary_path + len, suite);
+               len += strlen(suite);
+
+               cl_assert(len + strlen("_suite") < sizeof(binary_path));
+               strcpy(binary_path + len, "_suite");
+               len += strlen("_suite");
+
+               binary_path[len] = '\0';
+
+               execv(binary_path, (char **) final_args);
                exit(1);
        } else if (pid > 0) {
                pid_t waited_pid;
-               char *expected_output, *output;
+               char *output;
                int stat;
 
                cl_must_pass(close(pipe_fds[1]));
@@ -226,56 +258,78 @@ static void run(const char *expected_output_file, int expected_error_code, ...)
                cl_assert(WIFEXITED(stat));
                cl_assert_equal_i(WEXITSTATUS(stat), expected_error_code);
 
-               expected_output = read_file(cl_fixture(expected_output_file));
-               cl_assert_equal_s(output, expected_output);
-
-               free(expected_output);
-               free(output);
+               return output;
        } else {
                cl_fail("Fork failed.");
        }
+
+       return NULL;
+}
+
+static void assert_output(const char *suite, const char *expected_output_file, int expected_error_code, ...)
+{
+       char *expected_output, *output;
+       const char *args[16];
+       va_list ap;
+       size_t i;
+
+       va_start(ap, expected_error_code);
+       for (i = 0; ; i++) {
+               cl_assert(i < sizeof(args) / sizeof(*args));
+               args[i] = va_arg(ap, const char *);
+               if (!args[i])
+                       break;
+       }
+       va_end(ap);
+
+       output = execute(suite, expected_error_code, args, i);
+       expected_output = read_file(cl_fixture(expected_output_file));
+       cl_assert_equal_s(output, expected_output);
+
+       free(expected_output);
+       free(output);
 }
 #endif
 
 void test_selftest__help(void)
 {
-       cl_invoke(run("help", 1, "-h", NULL));
+       cl_invoke(assert_output("combined", "help", 1, "-h", NULL));
 }
 
 void test_selftest__without_arguments(void)
 {
-       cl_invoke(run("without_arguments", 10, NULL));
+       cl_invoke(assert_output("combined", "without_arguments", 9, NULL));
 }
 
 void test_selftest__specific_test(void)
 {
-       cl_invoke(run("specific_test", 1, "-sselftest::suite::bool", NULL));
+       cl_invoke(assert_output("combined", "specific_test", 1, "-scombined::bool", NULL));
 }
 
 void test_selftest__stop_on_failure(void)
 {
-       cl_invoke(run("stop_on_failure", 1, "-Q", NULL));
+       cl_invoke(assert_output("combined", "stop_on_failure", 1, "-Q", NULL));
 }
 
 void test_selftest__quiet(void)
 {
-       cl_invoke(run("quiet", 10, "-q", NULL));
+       cl_invoke(assert_output("combined", "quiet", 9, "-q", NULL));
 }
 
 void test_selftest__tap(void)
 {
-       cl_invoke(run("tap", 10, "-t", NULL));
+       cl_invoke(assert_output("combined", "tap", 9, "-t", NULL));
 }
 
 void test_selftest__suite_names(void)
 {
-       cl_invoke(run("suite_names", 0, "-l", NULL));
+       cl_invoke(assert_output("combined", "suite_names", 0, "-l", NULL));
 }
 
 void test_selftest__summary_without_filename(void)
 {
        struct stat st;
-       cl_invoke(run("summary_without_filename", 10, "-r", NULL));
+       cl_invoke(assert_output("combined", "summary_without_filename", 9, "-r", NULL));
        /* The summary contains timestamps, so we cannot verify its contents. */
        cl_must_pass(stat("summary.xml", &st));
 }
@@ -283,7 +337,34 @@ void test_selftest__summary_without_filename(void)
 void test_selftest__summary_with_filename(void)
 {
        struct stat st;
-       cl_invoke(run("summary_with_filename", 10, "-rdifferent.xml", NULL));
+       cl_invoke(assert_output("combined", "summary_with_filename", 9, "-rdifferent.xml", NULL));
        /* The summary contains timestamps, so we cannot verify its contents. */
        cl_must_pass(stat("different.xml", &st));
 }
+
+void test_selftest__pointer_equal(void)
+{
+       const char *args[] = {
+               "-spointer::equal",
+               "-t"
+       };
+       char *output = execute("pointer", 0, args, 2);
+       cl_assert_equal_s(output,
+                  "TAP version 13\n"
+                  "# start of suite 1: pointer\n"
+                  "ok 1 - pointer::equal\n"
+                  "1..1\n"
+       );
+       free(output);
+}
+
+void test_selftest__pointer_unequal(void)
+{
+       const char *args[] = {
+               "-spointer::unequal",
+       };
+       char *output = execute("pointer", 1, args, 1);
+       cl_assert(output);
+       cl_assert(strstr(output, "Pointer mismatch: "));
+       free(output);
+}
index 220a350c50487b6d1bb871b29aaa082a5d6a4905..c24e0c5af41790872b026a7dcbb3780806093f96 100644 (file)
@@ -1,3 +1,3 @@
 #include "clar.h"
 
-extern const char *selftest_binary_path;
+extern const char *selftest_suite_directory;
diff --git a/t/unit-tests/clar/test/selftest_suite/CMakeLists.txt b/t/unit-tests/clar/test/selftest_suite/CMakeLists.txt
deleted file mode 100644 (file)
index 9597d67..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-find_package(Python COMPONENTS Interpreter REQUIRED)
-
-add_custom_command(OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/clar.suite"
-       COMMAND "${Python_EXECUTABLE}" "${CMAKE_SOURCE_DIR}/generate.py" --output "${CMAKE_CURRENT_BINARY_DIR}"
-       DEPENDS main.c selftest_suite.c
-       WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
-)
-
-add_executable(selftest_suite)
-set_target_properties(selftest_suite PROPERTIES
-       C_STANDARD 90
-       C_STANDARD_REQUIRED ON
-       C_EXTENSIONS OFF
-)
-
-# MSVC generates all kinds of warnings. We may want to fix these in the future
-# and then unconditionally treat warnings as errors.
-if(NOT MSVC)
-       set_target_properties(selftest_suite PROPERTIES
-               COMPILE_WARNING_AS_ERROR ON
-       )
-endif()
-
-target_sources(selftest_suite PRIVATE
-       main.c
-       selftest_suite.c
-       "${CMAKE_CURRENT_BINARY_DIR}/clar.suite"
-)
-target_compile_definitions(selftest_suite PRIVATE
-       CLAR_FIXTURE_PATH="${CMAKE_CURRENT_SOURCE_DIR}/resources/"
-       CLAR_SELFTEST
-)
-target_compile_options(selftest_suite PRIVATE
-       $<IF:$<CXX_COMPILER_ID:MSVC>,/W4,-Wall>
-)
-target_include_directories(selftest_suite PRIVATE
-       "${CMAKE_SOURCE_DIR}"
-       "${CMAKE_CURRENT_BINARY_DIR}"
-)
-target_link_libraries(selftest_suite clar)
diff --git a/t/unit-tests/clar/test/suites/CMakeLists.txt b/t/unit-tests/clar/test/suites/CMakeLists.txt
new file mode 100644 (file)
index 0000000..fa8ab94
--- /dev/null
@@ -0,0 +1,53 @@
+list(APPEND suites
+       "combined"
+       "pointer"
+)
+
+foreach(suite IN LISTS suites)
+       add_custom_command(OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/${suite}/clar.suite"
+               COMMAND "${Python_EXECUTABLE}"
+                       "${CMAKE_SOURCE_DIR}/generate.py"
+                       "${CMAKE_CURRENT_SOURCE_DIR}/${suite}.c"
+                       --output "${CMAKE_CURRENT_BINARY_DIR}/${suite}"
+               DEPENDS ${suite}.c
+               WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
+       )
+
+       add_executable(${suite}_suite)
+       set_target_properties(${suite}_suite PROPERTIES
+               C_STANDARD 90
+               C_STANDARD_REQUIRED ON
+               C_EXTENSIONS OFF
+       )
+
+       # MSVC generates all kinds of warnings. We may want to fix these in the future
+       # and then unconditionally treat warnings as errors.
+       if(NOT MSVC)
+               set_target_properties(${suite}_suite PROPERTIES
+                       COMPILE_WARNING_AS_ERROR ON
+               )
+       endif()
+
+       target_sources(${suite}_suite PRIVATE
+               main.c
+               ${suite}.c
+               "${CMAKE_CURRENT_BINARY_DIR}/${suite}/clar.suite"
+       )
+       target_compile_definitions(${suite}_suite PRIVATE
+               CLAR_FIXTURE_PATH="${CMAKE_CURRENT_SOURCE_DIR}/resources/"
+               CLAR_SELFTEST
+       )
+       target_compile_options(${suite}_suite PRIVATE
+               $<IF:$<CXX_COMPILER_ID:MSVC>,/W4,-Wall>
+       )
+       target_include_directories(${suite}_suite PRIVATE
+               "${CMAKE_SOURCE_DIR}"
+               "${CMAKE_CURRENT_BINARY_DIR}/${suite}"
+       )
+       target_link_libraries(${suite}_suite clar)
+
+       add_test(NAME build_${suite}_suite
+               COMMAND "${CMAKE_COMMAND}" --build "${CMAKE_BINARY_DIR}" --config "$<CONFIG>" --target selftest
+       )
+       set_tests_properties(build_${suite}_suite PROPERTIES FIXTURES_SETUP clar_test_fixture)
+endforeach()
similarity index 72%
rename from t/unit-tests/clar/test/selftest_suite/selftest_suite.c
rename to t/unit-tests/clar/test/suites/combined.c
index 77f872128c709dd082d9e15577a5ef841761e0be..e8b41c98c37fa209de090ccc58a931324afe5c67 100644 (file)
@@ -11,14 +11,14 @@ static int file_size(const char *filename)
        return -1;
 }
 
-void test_selftest_suite__cleanup(void)
+void test_combined__cleanup(void)
 {
        cl_fixture_cleanup("test");
 
        cl_assert(file_size("test/file") == -1);
 }
 
-void test_selftest_suite__1(void)
+void test_combined__1(void)
 {
        cl_assert(1);
        cl_must_pass(0);  /* 0 == success */
@@ -26,7 +26,7 @@ void test_selftest_suite__1(void)
        cl_must_pass(-1); /* demonstrate a failing call */
 }
 
-void test_selftest_suite__2(void)
+void test_combined__2(void)
 {
        cl_fixture_sandbox("test");
 
@@ -35,7 +35,7 @@ void test_selftest_suite__2(void)
        cl_assert(100 == 101);
 }
 
-void test_selftest_suite__strings(void)
+void test_combined__strings(void)
 {
        const char *actual = "expected";
        cl_assert_equal_s("expected", actual);
@@ -43,7 +43,7 @@ void test_selftest_suite__strings(void)
        cl_assert_equal_s_("mismatched", actual, "this one fails");
 }
 
-void test_selftest_suite__strings_with_length(void)
+void test_combined__strings_with_length(void)
 {
        const char *actual = "expected";
        cl_assert_equal_strn("expected_", actual, 8);
@@ -52,39 +52,32 @@ void test_selftest_suite__strings_with_length(void)
        cl_assert_equal_strn_("exactly", actual, 3, "this one fails");
 }
 
-void test_selftest_suite__int(void)
+void test_combined__int(void)
 {
        int value = 100;
        cl_assert_equal_i(100, value);
        cl_assert_equal_i_(101, value, "extra note on failing test");
 }
 
-void test_selftest_suite__int_fmt(void)
+void test_combined__int_fmt(void)
 {
        int value = 100;
        cl_assert_equal_i_fmt(022, value, "%04o");
 }
 
-void test_selftest_suite__bool(void)
+void test_combined__bool(void)
 {
        int value = 100;
        cl_assert_equal_b(1, value);       /* test equality as booleans */
        cl_assert_equal_b(0, value);
 }
 
-void test_selftest_suite__ptr(void)
-{
-       void *p1 = (void *)0x1, *p2 = (void *)0x2;
-       cl_assert_equal_p(p1, p1); /* pointers to same object */
-       cl_assert_equal_p(p1, p2);
-}
-
-void test_selftest_suite__multiline_description(void)
+void test_combined__multiline_description(void)
 {
        cl_must_pass_(-1, "description line 1\ndescription line 2");
 }
 
-void test_selftest_suite__null_string(void)
+void test_combined__null_string(void)
 {
        const char *actual = NULL;
        cl_assert_equal_s(actual, actual);
diff --git a/t/unit-tests/clar/test/suites/pointer.c b/t/unit-tests/clar/test/suites/pointer.c
new file mode 100644 (file)
index 0000000..20535b1
--- /dev/null
@@ -0,0 +1,13 @@
+#include "clar.h"
+
+void test_pointer__equal(void)
+{
+       void *p1 = (void *)0x1;
+       cl_assert_equal_p(p1, p1);
+}
+
+void test_pointer__unequal(void)
+{
+       void *p1 = (void *)0x1, *p2 = (void *)0x2;
+       cl_assert_equal_p(p1, p2);
+}