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: |
};
/* 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);
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) {
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);
/* 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");
}
/* 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");
}
} \
} 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)
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
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
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)
-add_subdirectory(selftest_suite)
-
find_package(Python COMPONENTS Interpreter REQUIRED)
add_custom_command(OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/clar.suite"
)
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)
-Usage: selftest [options]
+Usage: combined [options]
Options:
-sname Run only the suite with `name` (can go to individual test name)
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
-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
-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
Test suites (use -s<name> to run just one):
- 0: selftest::suite
+ 0: combined
<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
-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
-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
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
line: 42
function: 'func'
---
-not ok 2 - selftest::suite::2
+not ok 2 - combined::2
---
reason: |
Expression is not true: 100 == 101
line: 42
function: 'func'
---
-not ok 3 - selftest::suite::strings
+not ok 3 - combined::strings
---
reason: |
String mismatch: "mismatched" != actual ("this one fails")
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")
line: 42
function: 'func'
---
-not ok 5 - selftest::suite::int
+not ok 5 - combined::int
---
reason: |
101 != value ("extra note on failing test")
line: 42
function: 'func'
---
-not ok 6 - selftest::suite::int_fmt
+not ok 6 - combined::int_fmt
---
reason: |
022 != value
line: 42
function: 'func'
---
-not ok 7 - selftest::suite::bool
+not ok 7 - combined::bool
---
reason: |
0 != value
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
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")
line: 42
function: 'func'
---
-1..10
+1..9
-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
#include "selftest.h"
-const char *selftest_binary_path;
+const char *selftest_suite_directory;
#ifdef _WIN32
int __cdecl 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;
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.
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);
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 ||
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]));
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));
}
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);
+}
#include "clar.h"
-extern const char *selftest_binary_path;
+extern const char *selftest_suite_directory;
+++ /dev/null
-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)
--- /dev/null
+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()
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 */
cl_must_pass(-1); /* demonstrate a failing call */
}
-void test_selftest_suite__2(void)
+void test_combined__2(void)
{
cl_fixture_sandbox("test");
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);
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);
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);
--- /dev/null
+#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);
+}