summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMitya Selivanov <automainint@guattari.tech>2023-09-08 21:34:37 +0200
committerMitya Selivanov <automainint@guattari.tech>2023-09-08 21:34:37 +0200
commit0a112c3f0964e4be0bab7148538656173768c3b7 (patch)
tree66ab90aaf5b6b4bf19c03f7fbf0ceca25102983b
parent24be37e59ba144a507bb53f07ca2673e0ed444b4 (diff)
downloadkit-0a112c3f0964e4be0bab7148538656173768c3b7.zip
Refactor kit_test to header-only library
-rw-r--r--build_and_test.sh16
-rw-r--r--source/kit/kit_test.h1119
-rw-r--r--source/kit_test/_static.c3
-rw-r--r--source/kit_test/bench.c398
-rw-r--r--source/kit_test/bench.h132
-rw-r--r--source/kit_test/shared.inl.h80
-rw-r--r--source/kit_test/test.c359
-rw-r--r--source/kit_test/test.h118
-rw-r--r--source/tests/_static.c41
-rw-r--r--source/tests/array_ref.test.c12
-rw-r--r--source/tests/async_function.test.c2
-rw-r--r--source/tests/atomic.test.c2
-rw-r--r--source/tests/bench.test.c3
-rw-r--r--source/tests/bigint.test.c2
-rw-r--r--source/tests/condition_variable.test.c2
-rw-r--r--source/tests/duration.test.c2
-rw-r--r--source/tests/dynamic_array.test.c2
-rw-r--r--source/tests/file.test.c2
-rw-r--r--source/tests/input_buffer.test.c2
-rw-r--r--source/tests/input_stream.test.c2
-rw-r--r--source/tests/lower_bound.test.c2
-rw-r--r--source/tests/main.test.c7
-rw-r--r--source/tests/mersenne_twister_64.test.c2
-rw-r--r--source/tests/move_back.test.c2
-rw-r--r--source/tests/mutex.test.c2
-rw-r--r--source/tests/secure_random.test.c2
-rw-r--r--source/tests/sha256.test.c2
-rw-r--r--source/tests/string_ref.test.c2
-rw-r--r--source/tests/test_cpp.cpp3
-rw-r--r--source/tests/test_signals.cpp3
-rw-r--r--source/tests/test_too_many_assertions.c4
-rw-r--r--source/tests/test_too_many_tests.c4
-rw-r--r--source/tests/thread.test.c2
33 files changed, 1175 insertions, 1161 deletions
diff --git a/build_and_test.sh b/build_and_test.sh
index 6e5b5fc..63bc27c 100644
--- a/build_and_test.sh
+++ b/build_and_test.sh
@@ -118,6 +118,7 @@ fi
echo ""
+echo "Build kit"
$COMPILE ${FLAGS} \
${FLAG_OBJ}"build/kit${OBJ_POSTFIX}" \
"source/kit/_static.c"
@@ -125,17 +126,10 @@ if [ $? -ne 0 ]; then
exit 1
fi
-$COMPILE ${FLAGS} \
- ${FLAG_OBJ}"build/kit_test${OBJ_POSTFIX}" \
- "source/kit_test/_static.c"
-if [ $? -ne 0 ]; then
- exit 1
-fi
-
+echo "Build kit_test_suite"
$COMPILE ${FLAGS} \
${FLAG_EXE}"build/kit_test_suite${EXE_POSTFIX}" \
"build/kit${OBJ_POSTFIX}" \
- "build/kit_test${OBJ_POSTFIX}" \
"source/tests/_static.c" \
${LINK_FLAGS}
if [ $? -ne 0 ]; then
@@ -145,7 +139,6 @@ fi
$COMPILE ${FLAGS} \
${FLAG_EXE}"build/test_too_many_assertions${EXE_POSTFIX}" \
"build/kit${OBJ_POSTFIX}" \
- "build/kit_test${OBJ_POSTFIX}" \
"source/tests/test_too_many_assertions.c" \
${LINK_FLAGS}
if [ $? -ne 0 ]; then
@@ -155,7 +148,6 @@ fi
$COMPILE ${FLAGS} \
${FLAG_EXE}"build/test_too_many_tests${EXE_POSTFIX}" \
"build/kit${OBJ_POSTFIX}" \
- "build/kit_test${OBJ_POSTFIX}" \
"source/tests/test_too_many_tests.c" \
${LINK_FLAGS}
if [ $? -ne 0 ]; then
@@ -165,7 +157,6 @@ fi
$COMPILEPP ${FLAGS} \
${FLAG_EXE}"build/test_cpp${EXE_POSTFIX}" \
"build/kit${OBJ_POSTFIX}" \
- "build/kit_test${OBJ_POSTFIX}" \
"source/tests/test_cpp.cpp" \
${LINK_FLAGS}
if [ $? -ne 0 ]; then
@@ -175,7 +166,6 @@ fi
$COMPILEPP ${FLAGS} \
${FLAG_EXE}"build/test_signals${EXE_POSTFIX}" \
"build/kit${OBJ_POSTFIX}" \
- "build/kit_test${OBJ_POSTFIX}" \
"source/tests/test_signals.cpp" \
${LINK_FLAGS}
if [ $? -ne 0 ]; then
@@ -216,7 +206,7 @@ else
STATUS=1
fi
-./build/test_signals --quiet
+./build/test_signals
if [ $? -eq 0 ]; then
echo "signals - OK"
else
diff --git a/source/kit/kit_test.h b/source/kit/kit_test.h
new file mode 100644
index 0000000..f935cf9
--- /dev/null
+++ b/source/kit/kit_test.h
@@ -0,0 +1,1119 @@
+// ================================================================
+//
+// kit_test.h
+//
+// Header-only unit-testing and microbenchmarks framework for C.
+//
+// - Define a unique KIT_TEST_FILE for each file to avoid name
+// collisions.
+//
+// - Define KIT_TEST_IMPLEMENTATION to include the implementation.
+//
+// Optional settings
+//
+// - KIT_TESTS_SIZE_LIMIT
+// - KIT_TEST_ASSERTIONS_LIMIT
+// - KIT_BENCHS_SIZE_LIMIT
+// - KIT_BENCH_MAX_REPEATS
+// - KIT_BENCH_MAX_CYCLES
+// - KIT_BENCH_REPEATS_DEFAULT_1
+// - KIT_BENCH_REPEATS_DEFAULT_2
+//
+// ================================================================
+//
+// The MIT License
+//
+// Copyright (c) 2022-2023 Mitya Selivanov
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use, copy,
+// modify, merge, publish, distribute, sublicense, and/or sell copies
+// of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+//
+// ================================================================
+
+#ifndef KIT_TEST_H
+#define KIT_TEST_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _GNU_SOURCE
+# define _GNU_SOURCE
+#endif
+
+#include <stddef.h>
+#include <stdint.h>
+
+#ifndef KIT_TEST_FILE
+# define KIT_TEST_FILE kit_test
+#endif
+
+#ifndef KIT_TESTS_SIZE_LIMIT
+# define KIT_TESTS_SIZE_LIMIT 0x1000
+#endif
+
+#ifndef KIT_TEST_ASSERTIONS_LIMIT
+# define KIT_TEST_ASSERTIONS_LIMIT 0x50
+#endif
+
+#ifndef KIT_BENCHS_SIZE_LIMIT
+# define KIT_BENCHS_SIZE_LIMIT 200
+#endif
+
+#ifndef KIT_BENCH_MAX_REPEATS
+# define KIT_BENCH_MAX_REPEATS 4000
+#endif
+
+#ifndef KIT_BENCH_MAX_CYCLES
+# define KIT_BENCH_MAX_CYCLES 40
+#endif
+
+#ifndef KIT_BENCH_REPEATS_DEFAULT_1
+# define KIT_BENCH_REPEATS_DEFAULT_1 40
+#endif
+
+#ifndef KIT_BENCH_REPEATS_DEFAULT_2
+# define KIT_BENCH_REPEATS_DEFAULT_2 400
+#endif
+
+typedef void (*kit_test_report_fn)(int test_index, int line,
+ int64_t value, int64_t expected);
+typedef void (*kit_test_run_fn)(
+ int kit_test_index_, kit_test_report_fn kit_test_report_fn_);
+
+typedef struct {
+ char const *test_name;
+ char const *test_file;
+ kit_test_run_fn test_fn;
+ int assertions;
+ int line[KIT_TEST_ASSERTIONS_LIMIT];
+ int status[KIT_TEST_ASSERTIONS_LIMIT];
+ int64_t value[KIT_TEST_ASSERTIONS_LIMIT];
+ int64_t expected[KIT_TEST_ASSERTIONS_LIMIT];
+ int signal;
+} kit_test_case_t;
+
+typedef struct {
+ int size;
+ kit_test_case_t v[KIT_TESTS_SIZE_LIMIT];
+} kit_tests_list_t;
+
+extern kit_tests_list_t kit_tests_list;
+
+#define KIT_TEST_CONCAT4_(a, b, c, d) a##b##c##d
+#define KIT_TEST_CONCAT3_(a, b, c) KIT_TEST_CONCAT4_(a, b, _, c)
+
+#ifdef __cplusplus
+# define KIT_TEST_ON_START_(f) \
+ static void f(void); \
+ static int KIT_TEST_CONCAT3_(_kit_test_init_, __LINE__, \
+ f) = (f(), 0); \
+ static void f(void)
+#else
+# ifdef _MSC_VER
+# pragma section(".CRT$XCU", read)
+# define KIT_TEST_ON_START_2_(f, p) \
+ static void f(void); \
+ __declspec(allocate(".CRT$XCU")) void (*f##_)(void) = f; \
+ __pragma(comment(linker, "/include:" p #f "_")) static void f( \
+ void)
+# ifdef _WIN64
+# define KIT_TEST_ON_START_(f) KIT_TEST_ON_START_2_(f, "")
+# else
+# define KIT_TEST_ON_START_(f) KIT_TEST_ON_START_2_(f, "_")
+# endif
+# else
+# define KIT_TEST_ON_START_(f) \
+ static void f(void) __attribute__((constructor)); \
+ static void f(void)
+# endif
+#endif
+
+void kit_test_register(char const *name, char const *file,
+ kit_test_run_fn fn);
+
+#define KIT_TEST(name) \
+ static void KIT_TEST_CONCAT3_(kit_test_run_, __LINE__, \
+ KIT_TEST_FILE)(int, \
+ kit_test_report_fn); \
+ KIT_TEST_ON_START_( \
+ KIT_TEST_CONCAT3_(kit_test_case_, __LINE__, KIT_TEST_FILE)) { \
+ kit_test_register( \
+ name, __FILE__, \
+ KIT_TEST_CONCAT3_(kit_test_run_, __LINE__, KIT_TEST_FILE)); \
+ } \
+ static void KIT_TEST_CONCAT3_(kit_test_run_, __LINE__, \
+ KIT_TEST_FILE)( \
+ int kit_test_index_, kit_test_report_fn kit_test_report_fn_)
+
+#define KIT_REQUIRE(...) \
+ kit_test_report_fn_(kit_test_index_, __LINE__, (__VA_ARGS__), 1)
+
+#define KIT_REQUIRE_EQ(...) \
+ kit_test_report_fn_(kit_test_index_, __LINE__, __VA_ARGS__)
+
+int kit_run_tests(int argc, char **argv);
+
+typedef void (*kit_bench_set_repeats_limit_fn)(int bench_index,
+ int repeats_limit);
+typedef int (*kit_bench_loop_fn)(int bench_index);
+typedef void (*kit_bench_begin_fn)(int bench_index);
+typedef void (*kit_bench_end_fn)(int bench_index);
+
+typedef void (*kit_bench_run_fn)(
+ int kit_bench_index_,
+ kit_bench_set_repeats_limit_fn kit_bench_set_repeats_limit_,
+ kit_bench_loop_fn kit_bench_loop_,
+ kit_bench_begin_fn kit_bench_begin_,
+ kit_bench_end_fn kit_bench_end_);
+
+typedef struct {
+ char const *bench_name;
+ char const *bench_file;
+ kit_bench_run_fn bench_fn;
+ int64_t sec[KIT_BENCH_MAX_REPEATS];
+ int32_t nsec[KIT_BENCH_MAX_REPEATS];
+ int64_t duration_nsec[KIT_BENCH_MAX_REPEATS];
+ int64_t duration_sorted_nsec[KIT_BENCH_MAX_REPEATS];
+ int repeats;
+ int cycles_size;
+ int cycles[KIT_BENCH_MAX_CYCLES];
+ int cycle;
+ int signal;
+ int ready;
+} kit_benchmark_t;
+
+typedef struct {
+ int size;
+ kit_benchmark_t v[KIT_BENCHS_SIZE_LIMIT];
+} kit_benchs_list_t;
+
+extern kit_benchs_list_t kit_benchs_list;
+
+void kit_bench_register(char const *name, char const *file,
+ kit_bench_run_fn fn);
+
+#define KIT_BENCHMARK(name) \
+ static void KIT_TEST_CONCAT3_(kit_bench_run_, __LINE__, \
+ KIT_TEST_FILE)( \
+ int, kit_bench_set_repeats_limit_fn, kit_bench_loop_fn, \
+ kit_bench_begin_fn, kit_bench_end_fn); \
+ KIT_TEST_ON_START_( \
+ KIT_TEST_CONCAT3_(kit_benchmark_, __LINE__, KIT_TEST_FILE)) { \
+ kit_bench_register( \
+ name, __FILE__, \
+ KIT_TEST_CONCAT3_(kit_bench_run_, __LINE__, KIT_TEST_FILE)); \
+ } \
+ static void KIT_TEST_CONCAT3_(kit_bench_run_, __LINE__, \
+ KIT_TEST_FILE)( \
+ int kit_bench_index_, \
+ kit_bench_set_repeats_limit_fn kit_bench_set_repeats_limit_, \
+ kit_bench_loop_fn kit_bench_loop_, \
+ kit_bench_begin_fn kit_bench_begin_, \
+ kit_bench_end_fn kit_bench_end_)
+
+#define KIT_BENCHMARK_REPEAT(repeats_limit_) \
+ kit_bench_set_repeats_limit_(kit_bench_index_, repeats_limit_)
+
+#define KIT_BENCHMARK_BEGIN \
+ while (kit_bench_loop_(kit_bench_index_)) { \
+ kit_bench_begin_(kit_bench_index_); \
+ {
+
+#define KIT_BENCHMARK_END \
+ } \
+ kit_bench_end_(kit_bench_index_); \
+ }
+
+/* FIXME
+ */
+#define KIT_DO_NOT_OPTIMIZE(x) \
+ do { \
+ volatile void *bench_ptr_ = &(x); \
+ (void) bench_ptr_; \
+ } while (0)
+
+int kit_run_benchmarks(int argc, char **argv);
+
+#ifndef KIT_DISABLE_SHORT_NAMES
+# define TEST KIT_TEST
+# define REQUIRE KIT_REQUIRE
+# define REQUIRE_EQ KIT_REQUIRE_EQ
+# define BENCHMARK KIT_BENCHMARK
+# define BENCHMARK_REPEAT KIT_BENCHMARK_REPEAT
+# define BENCHMARK_BEGIN KIT_BENCHMARK_BEGIN
+# define BENCHMARK_END KIT_BENCHMARK_END
+# define DO_NOT_OPTIMIZE KIT_DO_NOT_OPTIMIZE
+
+# define test_register kit_test_register
+# define run_tests kit_run_tests
+# define bench_register kit_bench_register
+# define run_benchmarks kit_run_benchmarks
+#endif
+
+#ifdef KIT_TEST_IMPLEMENTATION
+
+# ifndef KIT_TIME_H
+# define KIT_TIME_H
+
+# ifndef _GNU_SOURCE
+# define _GNU_SOURCE
+# endif
+
+# include <time.h>
+
+# ifndef TIME_UTC
+# define TIME_UTC 1
+# endif
+
+# ifdef __MINGW32__
+# ifndef WIN32_LEAN_AND_MEAN
+# define WIN32_LEAN_AND_MEAN 1
+# endif
+# include <Windows.h>
+
+# define KIT_TIMESPEC_IMPL_UNIX_EPOCH_IN_TICKS \
+ 116444736000000000ull
+# define KIT_TIMESPEC_IMPL_TICKS_PER_SECONDS 10000000ull
+
+static int timespec_get(struct timespec *ts, int base) {
+ if (ts == NULL || base != TIME_UTC)
+ return 0;
+
+ FILETIME ft;
+ ULARGE_INTEGER date;
+ LONGLONG ticks;
+
+ GetSystemTimeAsFileTime(&ft);
+ date.HighPart = ft.dwHighDateTime;
+ date.LowPart = ft.dwLowDateTime;
+ ticks = (LONGLONG) (date.QuadPart -
+ KIT_TIMESPEC_IMPL_UNIX_EPOCH_IN_TICKS);
+ ts->tv_sec = ticks / KIT_TIMESPEC_IMPL_TICKS_PER_SECONDS;
+ ts->tv_nsec = (ticks % KIT_TIMESPEC_IMPL_TICKS_PER_SECONDS) * 100;
+
+ return base;
+}
+# endif
+
+# endif
+
+# include <setjmp.h>
+# include <signal.h>
+# include <stdio.h>
+# include <stdlib.h>
+# include <string.h>
+
+enum {
+ kit_white_,
+ kit_blue_,
+ kit_light_,
+ kit_yellow_,
+ kit_red_,
+ kit_green_
+};
+
+static char const *kit_color_codes_[] = {
+ [kit_white_] = "\x1b[38m", [kit_blue_] = "\x1b[34m",
+ [kit_light_] = "\x1b[37m", [kit_yellow_] = "\x1b[33m",
+ [kit_red_] = "\x1b[31m", [kit_green_] = "\x1b[32m"
+};
+
+static int kit_print_color_(int c) {
+ return printf("%s", kit_color_codes_[c]);
+}
+
+static int kit_signums_[] = { SIGINT, SIGILL, SIGABRT,
+ SIGFPE, SIGSEGV, SIGTERM };
+
+static char const *kit_signames_[64];
+
+static void kit_signames_init_(void) {
+ memset(kit_signames_, 0, sizeof kit_signames_);
+ kit_signames_[SIGINT] = "Interactive attention signal";
+ kit_signames_[SIGILL] = "Illegal instruction";
+ kit_signames_[SIGABRT] = "Abnormal termination";
+ kit_signames_[SIGFPE] = "Erroneous arithmetic operation";
+ kit_signames_[SIGSEGV] = "Invalid access to storage";
+ kit_signames_[SIGTERM] = "Termination request";
+}
+
+kit_tests_list_t kit_tests_list = { 0 };
+
+static void kit_report_(int i, int line, int64_t value,
+ int64_t expected) {
+ int n = kit_tests_list.v[i].assertions++;
+
+ if (n >= KIT_TEST_ASSERTIONS_LIMIT)
+ return;
+
+ kit_tests_list.v[i].line[n] = line;
+ kit_tests_list.v[i].status[n] = value == expected;
+ kit_tests_list.v[i].value[n] = value;
+ kit_tests_list.v[i].expected[n] = expected;
+}
+
+static int64_t ns_to_ms(int64_t ns) {
+ return (ns + 500000) / 1000000;
+}
+
+static int64_t sec_to_ms(int64_t sec) {
+ return 1000 * sec;
+}
+
+void kit_test_register(char const *name, char const *file,
+ kit_test_run_fn fn) {
+ int n = kit_tests_list.size++;
+ if (n < KIT_TESTS_SIZE_LIMIT) {
+ kit_tests_list.v[n].test_fn = fn;
+ kit_tests_list.v[n].test_name = name;
+ kit_tests_list.v[n].test_file = file;
+ kit_tests_list.v[n].assertions = 0;
+ }
+}
+
+static jmp_buf kit_test_restore_execution;
+
+static void kit_test_handle_signal(int signum) {
+ longjmp(kit_test_restore_execution, signum);
+}
+
+static void kit_test_setup_signals() {
+ int i;
+
+ for (i = 0; i < sizeof kit_signums_ / sizeof *kit_signums_; i++) {
+# if (defined(_WIN32) && !defined(__CYGWIN__)) || \
+ !defined(_POSIX_C_SOURCE)
+ signal(kit_signums_[i], kit_test_handle_signal);
+# else
+ struct sigaction action;
+ memset(&action, 0, sizeof action);
+ action.sa_handler = kit_test_handle_signal;
+
+ sigaction(kit_signums_[i], &action, NULL);
+# endif
+ }
+}
+
+static int kit_run_test_(volatile int i) {
+ int signum = setjmp(kit_test_restore_execution);
+
+ if (signum != 0) {
+ kit_tests_list.v[i].signal = signum;
+ return 0;
+ }
+
+ kit_tests_list.v[i].test_fn(i, kit_report_);
+ return 1;
+}
+
+int kit_run_tests(int argc, char **argv) {
+ kit_signames_init_();
+
+ int success_count = 0;
+ int fail_assertion_count = 0;
+ int total_assertion_count = 0;
+ int status = 0;
+ int quiet = 0;
+ int no_color = 0;
+ int line_width = 20;
+ int carriage_return = 1;
+
+ int i, j;
+
+ char const *specific_test = NULL;
+
+ kit_test_setup_signals();
+
+ for (i = 0; i < argc; i++)
+ if (strcmp("--no-term-color", argv[i]) == 0)
+ no_color = 1;
+ else if (strcmp("--no-carriage-return", argv[i]) == 0)
+ carriage_return = 0;
+ else if (strcmp("--quiet", argv[i]) == 0)
+ quiet = 1;
+ else if (strcmp("--match", argv[i]) == 0)
+ specific_test = argv[++i];
+
+ quiet && (no_color = 1);
+
+ if (specific_test != NULL) {
+ no_color || kit_print_color_(kit_light_);
+ quiet || printf("Run tests matching ");
+ no_color || kit_print_color_(kit_white_);
+ quiet || printf("*%s*", specific_test);
+ no_color || kit_print_color_(kit_light_);
+ quiet || printf("\n\n");
+ }
+
+ char const *file = NULL;
+ ptrdiff_t file_root = -1;
+ int tests_total = 0;
+
+ for (i = 0; i < kit_tests_list.size && i < KIT_TESTS_SIZE_LIMIT;
+ i++) {
+ if (specific_test != NULL &&
+ strstr(kit_tests_list.v[i].test_name, specific_test) == NULL)
+ continue;
+ tests_total++;
+ int l = 2 + (int) strlen(kit_tests_list.v[i].test_name);
+ if (line_width < l)
+ line_width = l;
+ }
+
+ if (tests_total > 0) {
+ char const *s = kit_tests_list.v[0].test_file;
+
+ for (j = 1; j < kit_tests_list.size && j < KIT_TESTS_SIZE_LIMIT;
+ j++) {
+ if (specific_test != NULL &&
+ strstr(kit_tests_list.v[j].test_name, specific_test) ==
+ NULL)
+ continue;
+ if (strcmp(s, kit_tests_list.v[j].test_file) == 0)
+ continue;
+ int k = 0;
+ for (;
+ s[k] != '\0' && kit_tests_list.v[j].test_file[k] != '\0' &&
+ s[k] == kit_tests_list.v[j].test_file[k];
+ k++) { }
+ if (file_root == -1 || file_root > k)
+ file_root = k;
+ }
+
+ if (file_root == -1) {
+ for (i = 0; s[i] != '\0'; i++)
+ if (s[i] == '/' || s[i] == '\\')
+ file_root = i + 1;
+ }
+ }
+
+ for (i = 0; i < kit_tests_list.size && i < KIT_TESTS_SIZE_LIMIT;
+ i++) {
+ if (specific_test != NULL &&
+ strstr(kit_tests_list.v[i].test_name, specific_test) == NULL)
+ continue;
+ if (file == NULL ||
+ strcmp(file, kit_tests_list.v[i].test_file) != 0) {
+ if (file != NULL)
+ quiet || printf("\n");
+ file = kit_tests_list.v[i].test_file;
+ no_color || kit_print_color_(kit_blue_);
+ quiet || printf("* ");
+ no_color || kit_print_color_(kit_white_);
+ quiet || printf("%s\n", file + file_root);
+ }
+
+ !carriage_return || no_color || kit_print_color_(kit_yellow_);
+ carriage_return || no_color || kit_print_color_(kit_light_);
+ quiet || printf("` %s ", kit_tests_list.v[i].test_name);
+ !carriage_return || quiet || printf("\r");
+ quiet || fflush(stdout);
+
+ struct timespec begin, end;
+ timespec_get(&begin, TIME_UTC);
+
+ int test_status = kit_run_test_(i);
+
+ timespec_get(&end, TIME_UTC);
+ int duration = (int) (ns_to_ms(end.tv_nsec - begin.tv_nsec) +
+ sec_to_ms(end.tv_sec - begin.tv_sec));
+
+ for (j = 0; j < kit_tests_list.v[i].assertions &&
+ j < KIT_TEST_ASSERTIONS_LIMIT;
+ j++)
+ if (kit_tests_list.v[i].status[j] == 0) {
+ fail_assertion_count++;
+ test_status = 0;
+ }
+
+ if (kit_tests_list.v[i].assertions > KIT_TEST_ASSERTIONS_LIMIT)
+ test_status = 0;
+
+ total_assertion_count += kit_tests_list.v[i].assertions;
+
+ !carriage_return || no_color || kit_print_color_(kit_light_);
+ !carriage_return || quiet ||
+ printf("` %s ", kit_tests_list.v[i].test_name);
+
+ int l = (int) strlen(kit_tests_list.v[i].test_name);
+ quiet || printf("%*c", line_width - l, ' ');
+
+ if (test_status == 0) {
+ no_color || kit_print_color_(kit_red_);
+ quiet || printf("FAIL");
+ no_color || kit_print_color_(kit_light_);
+ duration == 0 || quiet || printf(" %d ms", duration);
+ quiet || printf("\n");
+ status = 1;
+ } else {
+ no_color || kit_print_color_(kit_green_);
+ quiet || printf("OK");
+ no_color || kit_print_color_(kit_light_);
+ duration == 0 || quiet || printf(" %d ms", duration);
+ quiet || printf("\n");
+ success_count++;
+ }
+
+ quiet || fflush(stdout);
+ }
+
+ no_color || kit_print_color_(kit_white_);
+ quiet || printf("\n%d of %d tests passed.\n", success_count,
+ tests_total);
+ quiet || printf("%d of %d assertions passed.\n\n",
+ total_assertion_count - fail_assertion_count,
+ total_assertion_count);
+
+ no_color || kit_print_color_(kit_light_);
+
+ if (!quiet && status != 0) {
+ int have_kit_report_s = 0;
+
+ for (i = 0; i < kit_tests_list.size && i < KIT_TESTS_SIZE_LIMIT;
+ i++) {
+ if (specific_test != NULL &&
+ strstr(kit_tests_list.v[i].test_name, specific_test) ==
+ NULL)
+ continue;
+ if (kit_tests_list.v[i].signal != 0) {
+ int signum = kit_tests_list.v[i].signal;
+ if (signum >= 0 &&
+ signum < sizeof kit_signames_ / sizeof *kit_signames_ &&
+ kit_signames_[signum] != NULL) {
+ no_color || kit_print_color_(kit_light_);
+ printf("Signal \"%s\" (%d) for \"", kit_signames_[signum],
+ signum);
+ no_color || kit_print_color_(kit_white_);
+ printf("%s", kit_tests_list.v[i].test_name);
+ no_color || kit_print_color_(kit_light_);
+ printf("\" in \"");
+ no_color || kit_print_color_(kit_white_);
+
+ printf("%s", kit_tests_list.v[i].test_file + file_root);
+ no_color || kit_print_color_(kit_light_);
+ printf("\"!.\n");
+ } else {
+ no_color || kit_print_color_(kit_light_);
+ printf("Unknown signal (%d) for \"", signum);
+ no_color || kit_print_color_(kit_white_);
+ printf("%s", kit_tests_list.v[i].test_name);
+ no_color || kit_print_color_(kit_light_);
+ printf("\" in \"");
+ no_color || kit_print_color_(kit_white_);
+
+ printf("%s", kit_tests_list.v[i].test_file + file_root);
+ no_color || kit_print_color_(kit_light_);
+ printf("\"!.\n");
+ }
+ have_kit_report_s = 1;
+ }
+ if (kit_tests_list.v[i].assertions >
+ KIT_TEST_ASSERTIONS_LIMIT) {
+ no_color || kit_print_color_(kit_light_);
+ printf("Too many assertions for \"");
+ no_color || kit_print_color_(kit_white_);
+ printf("%s", kit_tests_list.v[i].test_name);
+ no_color || kit_print_color_(kit_light_);
+ printf("\" in \"");
+ no_color || kit_print_color_(kit_white_);
+
+ printf("%s", kit_tests_list.v[i].test_file + file_root);
+ no_color || kit_print_color_(kit_light_);
+ printf("\"!.\n");
+ have_kit_report_s = 1;
+ }
+ }
+
+ have_kit_report_s &&printf("\n");
+ }
+
+ if (!quiet && status != 0) {
+ for (i = 0; i < kit_tests_list.size && i < KIT_TESTS_SIZE_LIMIT;
+ i++) {
+ if (specific_test != NULL &&
+ strstr(kit_tests_list.v[i].test_name, specific_test) ==
+ NULL)
+ continue;
+
+ if (kit_tests_list.v[i].assertions <= KIT_TEST_ASSERTIONS_LIMIT)
+ for (j = 0; j < kit_tests_list.v[i].assertions; j++)
+ if (!kit_tests_list.v[i].status[j]) {
+ no_color || kit_print_color_(kit_light_);
+ printf("Assertion on line ");
+ no_color || kit_print_color_(kit_white_);
+ printf("%d", kit_tests_list.v[i].line[j]);
+ no_color || kit_print_color_(kit_light_);
+ printf(" in \"");
+ no_color || kit_print_color_(kit_white_);
+ printf("%s", kit_tests_list.v[i].test_file + file_root);
+ no_color || kit_print_color_(kit_light_);
+ printf("\" failed.\n");
+ no_color || kit_print_color_(kit_red_);
+ printf(" -> ");
+ no_color || kit_print_color_(kit_light_);
+ printf("Got wrong value");
+ no_color || kit_print_color_(kit_white_);
+ printf("%10lld",
+ (long long) kit_tests_list.v[i].value[j]);
+ no_color || kit_print_color_(kit_light_);
+ printf(" (");
+ no_color || kit_print_color_(kit_white_);
+ printf("0x%08llx",
+ (unsigned long long) kit_tests_list.v[i].value[j]);
+ no_color || kit_print_color_(kit_light_);
+ printf(")\n");
+ no_color || kit_print_color_(kit_green_);
+ printf(" -> ");
+ no_color || kit_print_color_(kit_light_);
+ printf("Expected value ");
+ no_color || kit_print_color_(kit_white_);
+ printf("%10lld",
+ (long long) kit_tests_list.v[i].expected[j]);
+ no_color || kit_print_color_(kit_light_);
+ printf(" (");
+ no_color || kit_print_color_(kit_white_);
+ printf(
+ "0x%08llx",
+ (unsigned long long) kit_tests_list.v[i].expected[j]);
+ no_color || kit_print_color_(kit_light_);
+ printf(")\n\n");
+ }
+ }
+ }
+
+ if (kit_tests_list.size > KIT_TESTS_SIZE_LIMIT) {
+ no_color || kit_print_color_(kit_light_);
+ quiet || printf("Too many tests!\n\n");
+ status = 1;
+ }
+
+ if (status == 0) {
+ no_color || kit_print_color_(kit_green_);
+ quiet || printf("OK\n");
+ } else {
+ no_color || kit_print_color_(kit_red_);
+ quiet || printf("FAILED\n");
+ }
+
+ no_color || kit_print_color_(kit_white_);
+ quiet || printf("\n");
+ return status;
+}
+
+kit_benchs_list_t kit_benchs_list = { 0 };
+
+static void bench_set_repeats_limit(int i, int repeats_limit) {
+ if (kit_benchs_list.v[i].ready)
+ return;
+ if (kit_benchs_list.v[i].cycles_size >= KIT_BENCH_MAX_CYCLES)
+ return;
+ kit_benchs_list.v[i].cycles[kit_benchs_list.v[i].cycles_size] =
+ repeats_limit;
+ kit_benchs_list.v[i].cycles_size++;
+}
+
+static int bench_loop(int i) {
+ if (!kit_benchs_list.v[i].ready)
+ return 0;
+ return kit_benchs_list.v[i].repeats <
+ kit_benchs_list.v[i].cycles[kit_benchs_list.v[i].cycle];
+}
+
+static void bench_begin(int i) {
+ int n = kit_benchs_list.v[i].repeats++;
+
+ if (n >= KIT_BENCH_MAX_REPEATS)
+ return;
+
+ struct timespec tv;
+ timespec_get(&tv, TIME_UTC);
+
+ kit_benchs_list.v[i].sec[n] = (int64_t) tv.tv_sec;
+ kit_benchs_list.v[i].nsec[n] = (int64_t) tv.tv_nsec;
+}
+
+static void bench_end(int i) {
+ int n = kit_benchs_list.v[i].repeats - 1;
+
+ if (n < 0 || n >= KIT_BENCH_MAX_REPEATS)
+ return;
+
+ struct timespec tv;
+ timespec_get(&tv, TIME_UTC);
+
+ int64_t sec = ((int64_t) tv.tv_sec) - kit_benchs_list.v[i].sec[n];
+ int64_t nsec = ((int64_t) tv.tv_nsec) -
+ kit_benchs_list.v[i].nsec[n];
+
+ kit_benchs_list.v[i].duration_nsec[n] = sec * 1000000000 + nsec;
+}
+
+void kit_bench_register(char const *name, char const *file,
+ kit_bench_run_fn fn) {
+ int n = kit_benchs_list.size++;
+ if (n < KIT_BENCHS_SIZE_LIMIT) {
+ kit_benchmark_t *bench = kit_benchs_list.v + n;
+
+ bench->bench_fn = fn;
+ bench->bench_name = name;
+ bench->bench_file = file;
+ bench->cycles_size = 0;
+ bench->ready = 0;
+ }
+}
+
+static jmp_buf kit_bench_restore_execution;
+
+static void kit_bench_handle_signal(int signum) {
+ longjmp(kit_bench_restore_execution, signum);
+}
+
+static void kit_bench_setup_signals() {
+ int i;
+
+ for (i = 0; i < sizeof kit_signums_ / sizeof *kit_signums_; i++) {
+# if (defined(_WIN32) && !defined(__CYGWIN__)) || \
+ !defined(_POSIX_C_SOURCE)
+ signal(kit_signums_[i], kit_bench_handle_signal);
+# else
+ struct sigaction action;
+ memset(&action, 0, sizeof action);
+ action.sa_handler = kit_bench_handle_signal;
+
+ sigaction(kit_signums_[i], &action, NULL);
+# endif
+ }
+}
+
+static int kit_run_bench_(volatile int i) {
+ int signum = setjmp(kit_bench_restore_execution);
+
+ if (signum != 0) {
+ kit_benchs_list.v[i].signal = signum;
+ return 0;
+ }
+
+ kit_benchs_list.v[i].bench_fn(i, bench_set_repeats_limit,
+ bench_loop, bench_begin, bench_end);
+ return 1;
+}
+
+static int kit_compare_64_(void const *x_, void const *y_) {
+ int64_t const *x = (int64_t const *) x_;
+ int64_t const *y = (int64_t const *) y_;
+ return *x - *y;
+}
+
+static int kit_compare_32_(void const *x_, void const *y_) {
+ int const *x = (int const *) x_;
+ int const *y = (int const *) y_;
+ return *x - *y;
+}
+
+int kit_run_benchmarks(int argc, char **argv) {
+ int success_count = 0;
+ int status = 0;
+ int no_color = 0;
+ int line_width = 20;
+ int carriage_return = 1;
+
+ char const *specific_bench = NULL;
+
+ kit_bench_setup_signals();
+
+ for (int i = 0; i < argc; i++)
+ if (strcmp("--no-term-color", argv[i]) == 0)
+ no_color = 1;
+ else if (strcmp("--no-carriage-return", argv[i]) == 0)
+ carriage_return = 0;
+ else if (strcmp("--match", argv[i]) == 0)
+ specific_bench = argv[++i];
+
+ if (specific_bench != NULL) {
+ no_color || kit_print_color_(kit_light_);
+ printf("Run benchmarks matching ");
+ no_color || kit_print_color_(kit_white_);
+ printf("*%s*", specific_bench);
+ no_color || kit_print_color_(kit_light_);
+ printf("\n\n");
+ }
+
+ char const *file = NULL;
+ ptrdiff_t file_root = -1;
+ int benchs_total = 0;
+
+ for (int i = 0;
+ i < kit_benchs_list.size && i < KIT_BENCHS_SIZE_LIMIT; i++) {
+ if (specific_bench != NULL &&
+ strstr(kit_benchs_list.v[i].bench_name, specific_bench) ==
+ NULL)
+ continue;
+ benchs_total++;
+ int l = 2 + (int) strlen(kit_benchs_list.v[i].bench_name);
+ if (line_width < l)
+ line_width = l;
+ }
+
+ if (benchs_total > 0) {
+ char const *s = kit_benchs_list.v[0].bench_file;
+
+ for (int j = 1;
+ j < kit_benchs_list.size && j < KIT_BENCHS_SIZE_LIMIT; j++) {
+ kit_benchmark_t *bench = kit_benchs_list.v + j;
+
+ if (specific_bench != NULL &&
+ strstr(bench->bench_name, specific_bench) == NULL)
+ continue;
+ if (strcmp(s, bench->bench_file) == 0)
+ continue;
+ int k = 0;
+ for (; s[k] != '\0' && bench->bench_file[k] != '\0' &&
+ s[k] == bench->bench_file[k];
+ k++) { }
+ if (file_root == -1 || file_root > k)
+ file_root = k;
+ }
+
+ if (file_root == -1) {
+ for (int i = 0; s[i] != '\0'; i++)
+ if (s[i] == '/' || s[i] == '\\')
+ file_root = i + 1;
+ }
+ }
+
+ no_color || kit_print_color_(kit_blue_);
+ printf("# ");
+ no_color || kit_print_color_(kit_light_);
+ printf("BENCHMARK");
+ printf("%*c", line_width - 9, ' ');
+ no_color || kit_print_color_(kit_green_);
+ printf(" LOW ");
+ no_color || kit_print_color_(kit_light_);
+ printf("|");
+ no_color || kit_print_color_(kit_blue_);
+ printf(" MEDIAN ");
+ no_color || kit_print_color_(kit_light_);
+ printf("|");
+ no_color || kit_print_color_(kit_yellow_);
+ printf(" HIGH\n");
+ no_color || kit_print_color_(kit_light_);
+ printf(" (in microseconds)\n\n");
+
+ /* Prepare cycles.
+ */
+
+ for (int i = 0;
+ i < kit_benchs_list.size && i < KIT_BENCHS_SIZE_LIMIT; i++) {
+ kit_benchmark_t *bench = kit_benchs_list.v + i;
+
+ if (specific_bench != NULL &&
+ strstr(bench->bench_name, specific_bench) == NULL)
+ continue;
+
+ kit_run_bench_(i);
+
+ if (bench->cycles_size == 0) {
+ bench->cycles_size = 2;
+ bench->cycles[0] = KIT_BENCH_REPEATS_DEFAULT_1;
+ bench->cycles[1] = KIT_BENCH_REPEATS_DEFAULT_2;
+ }
+
+ qsort(bench->cycles, bench->cycles_size, sizeof *bench->cycles,
+ kit_compare_32_);
+
+ kit_benchs_list.v[i].ready = 1;
+ }
+
+ /* Run cycles.
+ */
+
+ for (int cycle = 0; cycle < KIT_BENCH_MAX_CYCLES; cycle++) {
+ /* Prepare cycle.
+ */
+
+ int cycles_done = 1;
+
+ for (int i = 0;
+ i < kit_benchs_list.size && i < KIT_BENCHS_SIZE_LIMIT; i++) {
+ kit_benchmark_t *bench = kit_benchs_list.v + i;
+
+ if (specific_bench != NULL &&
+ strstr(bench->bench_name, specific_bench) == NULL)
+ continue;
+ if (cycle >= bench->cycles_size)
+ continue;
+
+ bench->repeats = 0;
+ bench->cycle = cycle;
+ cycles_done = 0;
+ }
+
+ if (cycles_done)
+ break;
+
+ /* Run benchmarks.
+ */
+
+ for (int i = 0;
+ i < kit_benchs_list.size && i < KIT_BENCHS_SIZE_LIMIT; i++) {
+ kit_benchmark_t *bench = kit_benchs_list.v + i;
+
+ if (specific_bench != NULL &&
+ strstr(bench->bench_name, specific_bench) == NULL)
+ continue;
+ if (cycle >= bench->cycles_size)
+ continue;
+
+ if (file == NULL || strcmp(file, bench->bench_file) != 0) {
+ if (file != NULL)
+ printf("\n");
+ file = bench->bench_file;
+ no_color || kit_print_color_(kit_blue_);
+ printf("* ");
+ no_color || kit_print_color_(kit_white_);
+ printf("%s\n", file + file_root);
+ }
+
+ !carriage_return || no_color || kit_print_color_(kit_yellow_);
+ carriage_return || no_color || kit_print_color_(kit_light_);
+ printf("` %s ", bench->bench_name);
+ !carriage_return || printf("\r");
+ fflush(stdout);
+
+ int bench_status = kit_run_bench_(i);
+
+ if (bench->repeats > KIT_BENCH_MAX_REPEATS)
+ bench_status = 0;
+
+ !carriage_return || no_color || kit_print_color_(kit_light_);
+ !carriage_return || printf("` %s ", bench->bench_name);
+
+ int l = (int) strlen(bench->bench_name);
+ printf("%*c", line_width - l, ' ');
+
+ if (bench->repeats <= 0) {
+ no_color || kit_print_color_(kit_yellow_);
+ printf(" 0 runs\n");
+ success_count++;
+ } else if (bench_status == 0) {
+ no_color || kit_print_color_(kit_red_);
+ printf(" FAIL\n");
+ status = 1;
+ } else {
+ int repeats = bench->repeats;
+
+ memcpy(bench->duration_sorted_nsec, bench->duration_nsec,
+ repeats * sizeof *bench->duration_sorted_nsec);
+ qsort(bench->duration_sorted_nsec, repeats,
+ sizeof *bench->duration_sorted_nsec, kit_compare_64_);
+
+ int64_t average = bench->duration_sorted_nsec[repeats / 2];
+ int64_t floor = bench->duration_sorted_nsec[repeats / 20];
+ int64_t roof =
+ bench->duration_sorted_nsec[repeats - repeats / 20 - 1];
+
+ no_color || kit_print_color_(kit_white_);
+ printf("%-9g", (double) floor * 0.001);
+ no_color || kit_print_color_(kit_light_);
+ printf("| ");
+ no_color || kit_print_color_(kit_white_);
+ printf("%-9g", (double) average * 0.001);
+ no_color || kit_print_color_(kit_light_);
+ printf("| ");
+ no_color || kit_print_color_(kit_white_);
+ printf("%-9g", (double) roof * 0.001);
+ no_color || kit_print_color_(kit_light_);
+ printf(" %d runs\n", repeats);
+ success_count++;
+ }
+ }
+ }
+
+ printf("\n");
+
+ if (status != 0) {
+ for (int i = 0;
+ i < kit_benchs_list.size && i < KIT_BENCHS_SIZE_LIMIT; i++) {
+ kit_benchmark_t *bench = kit_benchs_list.v + i;
+
+ if (specific_bench != NULL &&
+ strstr(bench->bench_name, specific_bench) == NULL)
+ continue;
+ if (bench->signal != 0) {
+ int signum = bench->signal;
+ if (signum >= 0 &&
+ signum < sizeof kit_signames_ / sizeof *kit_signames_ &&
+ kit_signames_[signum] != NULL) {
+ no_color || kit_print_color_(kit_light_);
+ printf("Signal \"%s\" (%d) for \"", kit_signames_[signum],
+ signum);
+ no_color || kit_print_color_(kit_white_);
+ printf("%s", bench->bench_name);
+ no_color || kit_print_color_(kit_light_);
+ printf("\" in \"");
+ no_color || kit_print_color_(kit_white_);
+ printf("%s", bench->bench_file + file_root);
+ no_color || kit_print_color_(kit_light_);
+ printf("\"!.\n");
+ } else {
+ no_color || kit_print_color_(kit_light_);
+ printf("Unknown signal (%d) for \"", signum);
+ no_color || kit_print_color_(kit_white_);
+ printf("%s", bench->bench_name);
+ no_color || kit_print_color_(kit_light_);
+ printf("\" in \"");
+ no_color || kit_print_color_(kit_white_);
+ printf("%s", bench->bench_file + file_root);
+ no_color || kit_print_color_(kit_light_);
+ printf("\"!.\n");
+ }
+ }
+ }
+
+ printf("\n");
+ }
+
+ if (kit_benchs_list.size > KIT_BENCHS_SIZE_LIMIT) {
+ no_color || kit_print_color_(kit_light_);
+ printf("Too many benchmarks!\n\n");
+ status = 1;
+ }
+
+ if (status == 0) {
+ no_color || kit_print_color_(kit_green_);
+ printf("DONE\n");
+ } else {
+ no_color || kit_print_color_(kit_red_);
+ printf("DONE WITH ERRORS\n");
+ }
+
+ no_color || kit_print_color_(kit_white_);
+ printf("\n");
+ return status;
+}
+
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/source/kit_test/_static.c b/source/kit_test/_static.c
deleted file mode 100644
index 036b397..0000000
--- a/source/kit_test/_static.c
+++ /dev/null
@@ -1,3 +0,0 @@
-#include "test.c"
-
-#include "bench.c"
diff --git a/source/kit_test/bench.c b/source/kit_test/bench.c
deleted file mode 100644
index 9386bfe..0000000
--- a/source/kit_test/bench.c
+++ /dev/null
@@ -1,398 +0,0 @@
-#include "bench.h"
-
-#include "shared.inl.h"
-
-kit_benchs_list_t kit_benchs_list = { 0 };
-
-static void bench_set_repeats_limit(int i, int repeats_limit) {
- if (kit_benchs_list.v[i].ready)
- return;
- if (kit_benchs_list.v[i].cycles_size >= KIT_BENCH_MAX_CYCLES)
- return;
- kit_benchs_list.v[i].cycles[kit_benchs_list.v[i].cycles_size] =
- repeats_limit;
- kit_benchs_list.v[i].cycles_size++;
-}
-
-static int bench_loop(int i) {
- if (!kit_benchs_list.v[i].ready)
- return 0;
- return kit_benchs_list.v[i].repeats <
- kit_benchs_list.v[i].cycles[kit_benchs_list.v[i].cycle];
-}
-
-static void bench_begin(int i) {
- int const n = kit_benchs_list.v[i].repeats++;
-
- if (n >= KIT_BENCH_MAX_REPEATS)
- return;
-
- struct timespec tv;
- timespec_get(&tv, TIME_UTC);
-
- kit_benchs_list.v[i].sec[n] = (int64_t) tv.tv_sec;
- kit_benchs_list.v[i].nsec[n] = (int64_t) tv.tv_nsec;
-}
-
-static void bench_end(int i) {
- int const n = kit_benchs_list.v[i].repeats - 1;
-
- if (n < 0 || n >= KIT_BENCH_MAX_REPEATS)
- return;
-
- struct timespec tv;
- timespec_get(&tv, TIME_UTC);
-
- int64_t const sec = ((int64_t) tv.tv_sec) -
- kit_benchs_list.v[i].sec[n];
- int64_t const nsec = ((int64_t) tv.tv_nsec) -
- kit_benchs_list.v[i].nsec[n];
-
- kit_benchs_list.v[i].duration_nsec[n] = sec * 1000000000 + nsec;
-}
-
-void kit_bench_register(char const *name, char const *file,
- kit_bench_run_fn fn) {
- int n = kit_benchs_list.size++;
- if (n < KIT_BENCHS_SIZE_LIMIT) {
- kit_benchmark_t *const bench = kit_benchs_list.v + n;
-
- bench->bench_fn = fn;
- bench->bench_name = name;
- bench->bench_file = file;
- bench->cycles_size = 0;
- bench->ready = 0;
- }
-}
-
-static jmp_buf kit_bench_restore_execution;
-
-static void kit_bench_handle_signal(int signum) {
- longjmp(kit_bench_restore_execution, signum);
-}
-
-static void kit_bench_setup_signals() {
- int i;
-
- for (i = 0; i < sizeof signums / sizeof *signums; i++) {
-#if (defined(_WIN32) && !defined(__CYGWIN__)) || \
- !defined(_POSIX_C_SOURCE)
- signal(signums[i], kit_bench_handle_signal);
-#else
- struct sigaction action;
- memset(&action, 0, sizeof action);
- action.sa_handler = kit_bench_handle_signal;
-
- sigaction(signums[i], &action, NULL);
-#endif
- }
-}
-
-static int run_bench(volatile int i) {
- int signum = setjmp(kit_bench_restore_execution);
-
- if (signum != 0) {
- kit_benchs_list.v[i].signal = signum;
- return 0;
- }
-
- kit_benchs_list.v[i].bench_fn(i, bench_set_repeats_limit,
- bench_loop, bench_begin, bench_end);
- return 1;
-}
-
-int compare_64_(void const *x_, void const *y_) {
- int64_t const *x = (int64_t const *) x_;
- int64_t const *y = (int64_t const *) y_;
- return *x - *y;
-}
-
-int compare_32_(void const *x_, void const *y_) {
- int const *x = (int const *) x_;
- int const *y = (int const *) y_;
- return *x - *y;
-}
-
-int kit_run_benchmarks(int argc, char **argv) {
- int success_count = 0;
- int status = 0;
- int no_color = 0;
- int line_width = 20;
- int carriage_return = 1;
-
- char const *specific_bench = NULL;
-
- kit_bench_setup_signals();
-
- for (int i = 0; i < argc; i++)
- if (strcmp("--no-term-color", argv[i]) == 0)
- no_color = 1;
- else if (strcmp("--no-carriage-return", argv[i]) == 0)
- carriage_return = 0;
- else if (strcmp("--match", argv[i]) == 0)
- specific_bench = argv[++i];
-
- if (specific_bench != NULL) {
- no_color || print_color(light);
- printf("Run benchmarks matching ");
- no_color || print_color(white);
- printf("*%s*", specific_bench);
- no_color || print_color(light);
- printf("\n\n");
- }
-
- char const *file = NULL;
- ptrdiff_t file_root = -1;
- int benchs_total = 0;
-
- for (int i = 0;
- i < kit_benchs_list.size && i < KIT_BENCHS_SIZE_LIMIT; i++) {
- if (specific_bench != NULL &&
- strstr(kit_benchs_list.v[i].bench_name, specific_bench) ==
- NULL)
- continue;
- benchs_total++;
- int const l = 2 + (int) strlen(kit_benchs_list.v[i].bench_name);
- if (line_width < l)
- line_width = l;
- }
-
- if (benchs_total > 0) {
- char const *const s = kit_benchs_list.v[0].bench_file;
-
- for (int j = 1;
- j < kit_benchs_list.size && j < KIT_BENCHS_SIZE_LIMIT; j++) {
- kit_benchmark_t *const bench = kit_benchs_list.v + j;
-
- if (specific_bench != NULL &&
- strstr(bench->bench_name, specific_bench) == NULL)
- continue;
- if (strcmp(s, bench->bench_file) == 0)
- continue;
- int k = 0;
- for (; s[k] != '\0' && bench->bench_file[k] != '\0' &&
- s[k] == bench->bench_file[k];
- k++) { }
- if (file_root == -1 || file_root > k)
- file_root = k;
- }
-
- if (file_root == -1) {
- for (int i = 0; s[i] != '\0'; i++)
- if (s[i] == '/' || s[i] == '\\')
- file_root = i + 1;
- }
- }
-
- no_color || print_color(blue);
- printf("# ");
- no_color || print_color(light);
- printf("BENCHMARK");
- printf("%*c", line_width - 9, ' ');
- no_color || print_color(green);
- printf(" LOW ");
- no_color || print_color(light);
- printf("|");
- no_color || print_color(blue);
- printf(" MEDIAN ");
- no_color || print_color(light);
- printf("|");
- no_color || print_color(yellow);
- printf(" HIGH\n");
- no_color || print_color(light);
- printf(" (in microseconds)\n\n");
-
- /* Prepare cycles.
- */
-
- for (int i = 0;
- i < kit_benchs_list.size && i < KIT_BENCHS_SIZE_LIMIT; i++) {
- kit_benchmark_t *const bench = kit_benchs_list.v + i;
-
- if (specific_bench != NULL &&
- strstr(bench->bench_name, specific_bench) == NULL)
- continue;
-
- run_bench(i);
-
- if (bench->cycles_size == 0) {
- bench->cycles_size = 2;
- bench->cycles[0] = KIT_BENCH_REPEATS_DEFAULT_1;
- bench->cycles[1] = KIT_BENCH_REPEATS_DEFAULT_2;
- }
-
- qsort(bench->cycles, bench->cycles_size, sizeof *bench->cycles,
- compare_32_);
-
- kit_benchs_list.v[i].ready = 1;
- }
-
- /* Run cycles.
- */
-
- for (int cycle = 0; cycle < KIT_BENCH_MAX_CYCLES; cycle++) {
- /* Prepare cycle.
- */
-
- int cycles_done = 1;
-
- for (int i = 0;
- i < kit_benchs_list.size && i < KIT_BENCHS_SIZE_LIMIT; i++) {
- kit_benchmark_t *const bench = kit_benchs_list.v + i;
-
- if (specific_bench != NULL &&
- strstr(bench->bench_name, specific_bench) == NULL)
- continue;
- if (cycle >= bench->cycles_size)
- continue;
-
- bench->repeats = 0;
- bench->cycle = cycle;
- cycles_done = 0;
- }
-
- if (cycles_done)
- break;
-
- /* Run benchmarks.
- */
-
- for (int i = 0;
- i < kit_benchs_list.size && i < KIT_BENCHS_SIZE_LIMIT; i++) {
- kit_benchmark_t *const bench = kit_benchs_list.v + i;
-
- if (specific_bench != NULL &&
- strstr(bench->bench_name, specific_bench) == NULL)
- continue;
- if (cycle >= bench->cycles_size)
- continue;
-
- if (file == NULL || strcmp(file, bench->bench_file) != 0) {
- if (file != NULL)
- printf("\n");
- file = bench->bench_file;
- no_color || print_color(blue);
- printf("* ");
- no_color || print_color(white);
- printf("%s\n", file + file_root);
- }
-
- !carriage_return || no_color || print_color(yellow);
- carriage_return || no_color || print_color(light);
- printf("` %s ", bench->bench_name);
- !carriage_return || printf("\r");
- fflush(stdout);
-
- int bench_status = run_bench(i);
-
- if (bench->repeats > KIT_BENCH_MAX_REPEATS)
- bench_status = 0;
-
- !carriage_return || no_color || print_color(light);
- !carriage_return || printf("` %s ", bench->bench_name);
-
- int const l = (int) strlen(bench->bench_name);
- printf("%*c", line_width - l, ' ');
-
- if (bench->repeats <= 0) {
- no_color || print_color(yellow);
- printf(" 0 runs\n");
- success_count++;
- } else if (bench_status == 0) {
- no_color || print_color(red);
- printf(" FAIL\n");
- status = 1;
- } else {
- int const repeats = bench->repeats;
-
- memcpy(bench->duration_sorted_nsec, bench->duration_nsec,
- repeats * sizeof *bench->duration_sorted_nsec);
- qsort(bench->duration_sorted_nsec, repeats,
- sizeof *bench->duration_sorted_nsec, compare_64_);
-
- int64_t const average =
- bench->duration_sorted_nsec[repeats / 2];
- int64_t const floor =
- bench->duration_sorted_nsec[repeats / 20];
- int64_t const roof =
- bench->duration_sorted_nsec[repeats - repeats / 20 - 1];
-
- no_color || print_color(white);
- printf("%-9g", (double) floor * 0.001);
- no_color || print_color(light);
- printf("| ");
- no_color || print_color(white);
- printf("%-9g", (double) average * 0.001);
- no_color || print_color(light);
- printf("| ");
- no_color || print_color(white);
- printf("%-9g", (double) roof * 0.001);
- no_color || print_color(light);
- printf(" %d runs\n", repeats);
- success_count++;
- }
- }
- }
-
- printf("\n");
-
- if (status != 0) {
- for (int i = 0;
- i < kit_benchs_list.size && i < KIT_BENCHS_SIZE_LIMIT; i++) {
- kit_benchmark_t *const bench = kit_benchs_list.v + i;
-
- if (specific_bench != NULL &&
- strstr(bench->bench_name, specific_bench) == NULL)
- continue;
- if (bench->signal != 0) {
- int signum = bench->signal;
- if (signum >= 0 &&
- signum < sizeof signames / sizeof *signames &&
- signames[signum] != NULL) {
- no_color || print_color(light);
- printf("Signal \"%s\" (%d) for \"", signames[signum],
- signum);
- no_color || print_color(white);
- printf("%s", bench->bench_name);
- no_color || print_color(light);
- printf("\" in \"");
- no_color || print_color(white);
- printf("%s", bench->bench_file + file_root);
- no_color || print_color(light);
- printf("\"!.\n");
- } else {
- no_color || print_color(light);
- printf("Unknown signal (%d) for \"", signum);
- no_color || print_color(white);
- printf("%s", bench->bench_name);
- no_color || print_color(light);
- printf("\" in \"");
- no_color || print_color(white);
- printf("%s", bench->bench_file + file_root);
- no_color || print_color(light);
- printf("\"!.\n");
- }
- }
- }
-
- printf("\n");
- }
-
- if (kit_benchs_list.size > KIT_BENCHS_SIZE_LIMIT) {
- no_color || print_color(light);
- printf("Too many benchmarks!\n\n");
- status = 1;
- }
-
- if (status == 0) {
- no_color || print_color(green);
- printf("DONE\n");
- } else {
- no_color || print_color(red);
- printf("DONE WITH ERRORS\n");
- }
-
- no_color || print_color(white);
- printf("\n");
- return status;
-}
diff --git a/source/kit_test/bench.h b/source/kit_test/bench.h
deleted file mode 100644
index dd86c17..0000000
--- a/source/kit_test/bench.h
+++ /dev/null
@@ -1,132 +0,0 @@
-#ifndef KIT_BENCH_BENCH_H
-#define KIT_BENCH_BENCH_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include "test.h"
-
-#include <stdint.h>
-
-#ifndef KIT_TEST_FILE
-# define KIT_TEST_FILE kit_bench
-#endif
-
-#ifndef KIT_BENCHS_SIZE_LIMIT
-# define KIT_BENCHS_SIZE_LIMIT 200
-#endif
-
-#ifndef KIT_BENCH_MAX_REPEATS
-# define KIT_BENCH_MAX_REPEATS 4000
-#endif
-
-#ifndef KIT_BENCH_MAX_CYCLES
-# define KIT_BENCH_MAX_CYCLES 40
-#endif
-
-#ifndef KIT_BENCH_REPEATS_DEFAULT_1
-# define KIT_BENCH_REPEATS_DEFAULT_1 40
-#endif
-
-#ifndef KIT_BENCH_REPEATS_DEFAULT_2
-# define KIT_BENCH_REPEATS_DEFAULT_2 400
-#endif
-
-typedef void (*kit_bench_set_repeats_limit_fn)(int bench_index,
- int repeats_limit);
-typedef int (*kit_bench_loop_fn)(int bench_index);
-typedef void (*kit_bench_begin_fn)(int bench_index);
-typedef void (*kit_bench_end_fn)(int bench_index);
-
-typedef void (*kit_bench_run_fn)(
- int kit_bench_index_,
- kit_bench_set_repeats_limit_fn kit_bench_set_repeats_limit_,
- kit_bench_loop_fn kit_bench_loop_,
- kit_bench_begin_fn kit_bench_begin_,
- kit_bench_end_fn kit_bench_end_);
-
-typedef struct {
- char const *bench_name;
- char const *bench_file;
- kit_bench_run_fn bench_fn;
- int64_t sec[KIT_BENCH_MAX_REPEATS];
- int32_t nsec[KIT_BENCH_MAX_REPEATS];
- int64_t duration_nsec[KIT_BENCH_MAX_REPEATS];
- int64_t duration_sorted_nsec[KIT_BENCH_MAX_REPEATS];
- int repeats;
- int cycles_size;
- int cycles[KIT_BENCH_MAX_CYCLES];
- int cycle;
- int signal;
- int ready;
-} kit_benchmark_t;
-
-typedef struct {
- int size;
- kit_benchmark_t v[KIT_BENCHS_SIZE_LIMIT];
-} kit_benchs_list_t;
-
-extern kit_benchs_list_t kit_benchs_list;
-
-void kit_bench_register(char const *name, char const *file,
- kit_bench_run_fn fn);
-
-#define KIT_BENCHMARK(name) \
- static void KIT_TEST_CONCAT3_(kit_bench_run_, __LINE__, \
- KIT_TEST_FILE)( \
- int, kit_bench_set_repeats_limit_fn, kit_bench_loop_fn, \
- kit_bench_begin_fn, kit_bench_end_fn); \
- KIT_TEST_ON_START_( \
- KIT_TEST_CONCAT3_(kit_benchmark_, __LINE__, KIT_TEST_FILE)) { \
- kit_bench_register( \
- name, __FILE__, \
- KIT_TEST_CONCAT3_(kit_bench_run_, __LINE__, KIT_TEST_FILE)); \
- } \
- static void KIT_TEST_CONCAT3_(kit_bench_run_, __LINE__, \
- KIT_TEST_FILE)( \
- int kit_bench_index_, \
- kit_bench_set_repeats_limit_fn kit_bench_set_repeats_limit_, \
- kit_bench_loop_fn kit_bench_loop_, \
- kit_bench_begin_fn kit_bench_begin_, \
- kit_bench_end_fn kit_bench_end_)
-
-#define KIT_BENCHMARK_REPEAT(repeats_limit_) \
- kit_bench_set_repeats_limit_(kit_bench_index_, repeats_limit_)
-
-#define KIT_BENCHMARK_BEGIN \
- while (kit_bench_loop_(kit_bench_index_)) { \
- kit_bench_begin_(kit_bench_index_); \
- {
-
-#define KIT_BENCHMARK_END \
- } \
- kit_bench_end_(kit_bench_index_); \
- }
-
-/* FIXME
- */
-#define KIT_DO_NOT_OPTIMIZE(x) \
- do { \
- volatile void *bench_ptr_ = &(x); \
- (void) bench_ptr_; \
- } while (0)
-
-int kit_run_benchmarks(int argc, char **argv);
-
-#ifndef KIT_DISABLE_SHORT_NAMES
-# define BENCHMARK KIT_BENCHMARK
-# define BENCHMARK_REPEAT KIT_BENCHMARK_REPEAT
-# define BENCHMARK_BEGIN KIT_BENCHMARK_BEGIN
-# define BENCHMARK_END KIT_BENCHMARK_END
-# define DO_NOT_OPTIMIZE KIT_DO_NOT_OPTIMIZE
-
-# define bench_register kit_bench_register
-# define run_benchmarks kit_run_benchmarks
-#endif
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/source/kit_test/shared.inl.h b/source/kit_test/shared.inl.h
deleted file mode 100644
index 11b42bb..0000000
--- a/source/kit_test/shared.inl.h
+++ /dev/null
@@ -1,80 +0,0 @@
-#ifndef KIT_TEST_SHARED_INL_H
-#define KIT_TEST_SHARED_INL_H
-
-// kit/time.h
-//
-#ifndef KIT_TIME_H
-# define KIT_TIME_H
-
-# ifndef _GNU_SOURCE
-# define _GNU_SOURCE
-# endif
-
-# include <time.h>
-
-# ifndef TIME_UTC
-# define TIME_UTC 1
-# endif
-
-# ifdef __MINGW32__
-# ifndef WIN32_LEAN_AND_MEAN
-# define WIN32_LEAN_AND_MEAN 1
-# endif
-# include <Windows.h>
-
-# define KIT_TIMESPEC_IMPL_UNIX_EPOCH_IN_TICKS \
- 116444736000000000ull
-# define KIT_TIMESPEC_IMPL_TICKS_PER_SECONDS 10000000ull
-
-static int timespec_get(struct timespec *ts, int base) {
- if (ts == NULL || base != TIME_UTC)
- return 0;
-
- FILETIME ft;
- ULARGE_INTEGER date;
- LONGLONG ticks;
-
- GetSystemTimeAsFileTime(&ft);
- date.HighPart = ft.dwHighDateTime;
- date.LowPart = ft.dwLowDateTime;
- ticks = (LONGLONG) (date.QuadPart -
- KIT_TIMESPEC_IMPL_UNIX_EPOCH_IN_TICKS);
- ts->tv_sec = ticks / KIT_TIMESPEC_IMPL_TICKS_PER_SECONDS;
- ts->tv_nsec = (ticks % KIT_TIMESPEC_IMPL_TICKS_PER_SECONDS) * 100;
-
- return base;
-}
-# endif
-
-#endif // kit/time.h
-
-#include <setjmp.h>
-#include <signal.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-enum { white, blue, light, yellow, red, green };
-
-static char const *const color_codes[] = {
- [white] = "\x1b[38m", [blue] = "\x1b[34m", [light] = "\x1b[37m",
- [yellow] = "\x1b[33m", [red] = "\x1b[31m", [green] = "\x1b[32m"
-};
-
-static int print_color(int c) {
- return printf("%s", color_codes[c]);
-}
-
-static int const signums[] = { SIGINT, SIGILL, SIGABRT,
- SIGFPE, SIGSEGV, SIGTERM };
-
-static char const *const signames[] = {
- [SIGINT] = "Interactive attention signal",
- [SIGILL] = "Illegal instruction",
- [SIGABRT] = "Abnormal termination",
- [SIGFPE] = "Erroneous arithmetic operation",
- [SIGSEGV] = "Invalid access to storage",
- [SIGTERM] = "Termination request"
-};
-
-#endif
diff --git a/source/kit_test/test.c b/source/kit_test/test.c
deleted file mode 100644
index 86ababa..0000000
--- a/source/kit_test/test.c
+++ /dev/null
@@ -1,359 +0,0 @@
-#include "test.h"
-
-#include "shared.inl.h"
-
-kit_tests_list_t kit_tests_list = { 0 };
-
-static void report(int i, int line, long long value,
- long long expected) {
- int const n = kit_tests_list.v[i].assertions++;
-
- if (n >= KIT_TEST_ASSERTIONS_LIMIT)
- return;
-
- kit_tests_list.v[i].line[n] = line;
- kit_tests_list.v[i].status[n] = value == expected;
- kit_tests_list.v[i].value[n] = value;
- kit_tests_list.v[i].expected[n] = expected;
-}
-
-static long long ns_to_ms(long long ns) {
- return (ns + 500000) / 1000000;
-}
-
-static long long sec_to_ms(long long sec) {
- return 1000 * sec;
-}
-
-void kit_test_register(char const *name, char const *file,
- kit_test_run_fn fn) {
- int n = kit_tests_list.size++;
- if (n < KIT_TESTS_SIZE_LIMIT) {
- kit_tests_list.v[n].test_fn = fn;
- kit_tests_list.v[n].test_name = name;
- kit_tests_list.v[n].test_file = file;
- kit_tests_list.v[n].assertions = 0;
- }
-}
-
-static jmp_buf kit_test_restore_execution;
-
-static void kit_test_handle_signal(int signum) {
- longjmp(kit_test_restore_execution, signum);
-}
-
-static void kit_test_setup_signals() {
- int i;
-
- for (i = 0; i < sizeof signums / sizeof *signums; i++) {
-#if (defined(_WIN32) && !defined(__CYGWIN__)) || \
- !defined(_POSIX_C_SOURCE)
- signal(signums[i], kit_test_handle_signal);
-#else
- struct sigaction action;
- memset(&action, 0, sizeof action);
- action.sa_handler = kit_test_handle_signal;
-
- sigaction(signums[i], &action, NULL);
-#endif
- }
-}
-
-static int run_test(volatile int i) {
- int signum = setjmp(kit_test_restore_execution);
-
- if (signum != 0) {
- kit_tests_list.v[i].signal = signum;
- return 0;
- }
-
- kit_tests_list.v[i].test_fn(i, report);
- return 1;
-}
-
-int kit_run_tests(int argc, char **argv) {
- int success_count = 0;
- int fail_assertion_count = 0;
- int total_assertion_count = 0;
- int status = 0;
- int quiet = 0;
- int no_color = 0;
- int line_width = 20;
- int carriage_return = 1;
-
- int i, j;
-
- char const *specific_test = NULL;
-
- kit_test_setup_signals();
-
- for (i = 0; i < argc; i++)
- if (strcmp("--no-term-color", argv[i]) == 0)
- no_color = 1;
- else if (strcmp("--no-carriage-return", argv[i]) == 0)
- carriage_return = 0;
- else if (strcmp("--quiet", argv[i]) == 0)
- quiet = 1;
- else if (strcmp("--match", argv[i]) == 0)
- specific_test = argv[++i];
-
- quiet && (no_color = 1);
-
- if (specific_test != NULL) {
- no_color || print_color(light);
- quiet || printf("Run tests matching ");
- no_color || print_color(white);
- quiet || printf("*%s*", specific_test);
- no_color || print_color(light);
- quiet || printf("\n\n");
- }
-
- char const *file = NULL;
- ptrdiff_t file_root = -1;
- int tests_total = 0;
-
- for (i = 0; i < kit_tests_list.size && i < KIT_TESTS_SIZE_LIMIT;
- i++) {
- if (specific_test != NULL &&
- strstr(kit_tests_list.v[i].test_name, specific_test) == NULL)
- continue;
- tests_total++;
- int const l = 2 + (int) strlen(kit_tests_list.v[i].test_name);
- if (line_width < l)
- line_width = l;
- }
-
- if (tests_total > 0) {
- char const *const s = kit_tests_list.v[0].test_file;
-
- for (j = 1; j < kit_tests_list.size && j < KIT_TESTS_SIZE_LIMIT;
- j++) {
- if (specific_test != NULL &&
- strstr(kit_tests_list.v[j].test_name, specific_test) ==
- NULL)
- continue;
- if (strcmp(s, kit_tests_list.v[j].test_file) == 0)
- continue;
- int k = 0;
- for (;
- s[k] != '\0' && kit_tests_list.v[j].test_file[k] != '\0' &&
- s[k] == kit_tests_list.v[j].test_file[k];
- k++) { }
- if (file_root == -1 || file_root > k)
- file_root = k;
- }
-
- if (file_root == -1) {
- for (i = 0; s[i] != '\0'; i++)
- if (s[i] == '/' || s[i] == '\\')
- file_root = i + 1;
- }
- }
-
- for (i = 0; i < kit_tests_list.size && i < KIT_TESTS_SIZE_LIMIT;
- i++) {
- if (specific_test != NULL &&
- strstr(kit_tests_list.v[i].test_name, specific_test) == NULL)
- continue;
- if (file == NULL ||
- strcmp(file, kit_tests_list.v[i].test_file) != 0) {
- if (file != NULL)
- quiet || printf("\n");
- file = kit_tests_list.v[i].test_file;
- no_color || print_color(blue);
- quiet || printf("* ");
- no_color || print_color(white);
- quiet || printf("%s\n", file + file_root);
- }
-
- !carriage_return || no_color || print_color(yellow);
- carriage_return || no_color || print_color(light);
- quiet || printf("` %s ", kit_tests_list.v[i].test_name);
- !carriage_return || quiet || printf("\r");
- quiet || fflush(stdout);
-
- struct timespec begin, end;
- timespec_get(&begin, TIME_UTC);
-
- int test_status = run_test(i);
-
- timespec_get(&end, TIME_UTC);
- int duration = (int) (ns_to_ms(end.tv_nsec - begin.tv_nsec) +
- sec_to_ms(end.tv_sec - begin.tv_sec));
-
- for (j = 0; j < kit_tests_list.v[i].assertions &&
- j < KIT_TEST_ASSERTIONS_LIMIT;
- j++)
- if (kit_tests_list.v[i].status[j] == 0) {
- fail_assertion_count++;
- test_status = 0;
- }
-
- if (kit_tests_list.v[i].assertions > KIT_TEST_ASSERTIONS_LIMIT)
- test_status = 0;
-
- total_assertion_count += kit_tests_list.v[i].assertions;
-
- !carriage_return || no_color || print_color(light);
- !carriage_return || quiet ||
- printf("` %s ", kit_tests_list.v[i].test_name);
-
- int const l = (int) strlen(kit_tests_list.v[i].test_name);
- quiet || printf("%*c", line_width - l, ' ');
-
- if (test_status == 0) {
- no_color || print_color(red);
- quiet || printf("FAIL");
- no_color || print_color(light);
- duration == 0 || quiet || printf(" %d ms", duration);
- quiet || printf("\n");
- status = 1;
- } else {
- no_color || print_color(green);
- quiet || printf("OK");
- no_color || print_color(light);
- duration == 0 || quiet || printf(" %d ms", duration);
- quiet || printf("\n");
- success_count++;
- }
-
- quiet || fflush(stdout);
- }
-
- no_color || print_color(white);
- quiet || printf("\n%d of %d tests passed.\n", success_count,
- tests_total);
- quiet || printf("%d of %d assertions passed.\n\n",
- total_assertion_count - fail_assertion_count,
- total_assertion_count);
-
- no_color || print_color(light);
-
- if (!quiet && status != 0) {
- int have_reports = 0;
-
- for (i = 0; i < kit_tests_list.size && i < KIT_TESTS_SIZE_LIMIT;
- i++) {
- if (specific_test != NULL &&
- strstr(kit_tests_list.v[i].test_name, specific_test) ==
- NULL)
- continue;
- if (kit_tests_list.v[i].signal != 0) {
- int signum = kit_tests_list.v[i].signal;
- if (signum >= 0 &&
- signum < sizeof signames / sizeof *signames &&
- signames[signum] != NULL) {
- no_color || print_color(light);
- printf("Signal \"%s\" (%d) for \"", signames[signum],
- signum);
- no_color || print_color(white);
- printf("%s", kit_tests_list.v[i].test_name);
- no_color || print_color(light);
- printf("\" in \"");
- no_color || print_color(white);
-
- printf("%s", kit_tests_list.v[i].test_file + file_root);
- no_color || print_color(light);
- printf("\"!.\n");
- } else {
- no_color || print_color(light);
- printf("Unknown signal (%d) for \"", signum);
- no_color || print_color(white);
- printf("%s", kit_tests_list.v[i].test_name);
- no_color || print_color(light);
- printf("\" in \"");
- no_color || print_color(white);
-
- printf("%s", kit_tests_list.v[i].test_file + file_root);
- no_color || print_color(light);
- printf("\"!.\n");
- }
- have_reports = 1;
- }
- if (kit_tests_list.v[i].assertions >
- KIT_TEST_ASSERTIONS_LIMIT) {
- no_color || print_color(light);
- printf("Too many assertions for \"");
- no_color || print_color(white);
- printf("%s", kit_tests_list.v[i].test_name);
- no_color || print_color(light);
- printf("\" in \"");
- no_color || print_color(white);
-
- printf("%s", kit_tests_list.v[i].test_file + file_root);
- no_color || print_color(light);
- printf("\"!.\n");
- have_reports = 1;
- }
- }
-
- have_reports &&printf("\n");
- }
-
- if (!quiet && status != 0) {
- for (i = 0; i < kit_tests_list.size && i < KIT_TESTS_SIZE_LIMIT;
- i++) {
- if (specific_test != NULL &&
- strstr(kit_tests_list.v[i].test_name, specific_test) ==
- NULL)
- continue;
-
- if (kit_tests_list.v[i].assertions <= KIT_TEST_ASSERTIONS_LIMIT)
- for (j = 0; j < kit_tests_list.v[i].assertions; j++)
- if (!kit_tests_list.v[i].status[j]) {
- no_color || print_color(light);
- printf("Assertion on line ");
- no_color || print_color(white);
- printf("%d", kit_tests_list.v[i].line[j]);
- no_color || print_color(light);
- printf(" in \"");
- no_color || print_color(white);
- printf("%s", kit_tests_list.v[i].test_file + file_root);
- no_color || print_color(light);
- printf("\" failed.\n");
- no_color || print_color(red);
- printf(" -> ");
- no_color || print_color(light);
- printf("Got wrong value");
- no_color || print_color(white);
- printf("%10lld", kit_tests_list.v[i].value[j]);
- no_color || print_color(light);
- printf(" (");
- no_color || print_color(white);
- printf("0x%08llx", kit_tests_list.v[i].value[j]);
- no_color || print_color(light);
- printf(")\n");
- no_color || print_color(green);
- printf(" -> ");
- no_color || print_color(light);
- printf("Expected value ");
- no_color || print_color(white);
- printf("%10lld", kit_tests_list.v[i].expected[j]);
- no_color || print_color(light);
- printf(" (");
- no_color || print_color(white);
- printf("0x%08llx", kit_tests_list.v[i].expected[j]);
- no_color || print_color(light);
- printf(")\n\n");
- }
- }
- }
-
- if (kit_tests_list.size > KIT_TESTS_SIZE_LIMIT) {
- no_color || print_color(light);
- quiet || printf("Too many tests!\n\n");
- status = 1;
- }
-
- if (status == 0) {
- no_color || print_color(green);
- quiet || printf("OK\n");
- } else {
- no_color || print_color(red);
- quiet || printf("FAILED\n");
- }
-
- no_color || print_color(white);
- quiet || printf("\n");
- return status;
-}
diff --git a/source/kit_test/test.h b/source/kit_test/test.h
deleted file mode 100644
index 6584cbe..0000000
--- a/source/kit_test/test.h
+++ /dev/null
@@ -1,118 +0,0 @@
-#ifndef KIT_TEST_TEST_H
-#define KIT_TEST_TEST_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#ifndef _GNU_SOURCE
-# define _GNU_SOURCE
-#endif
-
-#include <stddef.h>
-
-#ifndef KIT_TEST_FILE
-# define KIT_TEST_FILE kit_test
-#endif
-
-#ifndef KIT_TESTS_SIZE_LIMIT
-# define KIT_TESTS_SIZE_LIMIT 0x1000
-#endif
-
-#ifndef KIT_TEST_ASSERTIONS_LIMIT
-# define KIT_TEST_ASSERTIONS_LIMIT 0x50
-#endif
-
-typedef void (*kit_test_report_fn)(int test_index, int line,
- long long value,
- long long expected);
-typedef void (*kit_test_run_fn)(
- int kit_test_index_, kit_test_report_fn kit_test_report_fn_);
-
-typedef struct {
- char const *test_name;
- char const *test_file;
- kit_test_run_fn test_fn;
- int assertions;
- int line[KIT_TEST_ASSERTIONS_LIMIT];
- int status[KIT_TEST_ASSERTIONS_LIMIT];
- long long value[KIT_TEST_ASSERTIONS_LIMIT];
- long long expected[KIT_TEST_ASSERTIONS_LIMIT];
- int signal;
-} kit_test_case_t;
-
-typedef struct {
- int size;
- kit_test_case_t v[KIT_TESTS_SIZE_LIMIT];
-} kit_tests_list_t;
-
-extern kit_tests_list_t kit_tests_list;
-
-#define KIT_TEST_CONCAT4_(a, b, c, d) a##b##c##d
-#define KIT_TEST_CONCAT3_(a, b, c) KIT_TEST_CONCAT4_(a, b, _, c)
-
-#ifdef __cplusplus
-# define KIT_TEST_ON_START_(f) \
- static void f(void); \
- static int KIT_TEST_CONCAT3_(_kit_test_init_, __LINE__, \
- f) = (f(), 0); \
- static void f(void)
-#else
-# ifdef _MSC_VER
-# pragma section(".CRT$XCU", read)
-# define KIT_TEST_ON_START_2_(f, p) \
- static void f(void); \
- __declspec(allocate(".CRT$XCU")) void (*f##_)(void) = f; \
- __pragma(comment(linker, "/include:" p #f "_")) static void f( \
- void)
-# ifdef _WIN64
-# define KIT_TEST_ON_START_(f) KIT_TEST_ON_START_2_(f, "")
-# else
-# define KIT_TEST_ON_START_(f) KIT_TEST_ON_START_2_(f, "_")
-# endif
-# else
-# define KIT_TEST_ON_START_(f) \
- static void f(void) __attribute__((constructor)); \
- static void f(void)
-# endif
-#endif
-
-void kit_test_register(char const *name, char const *file,
- kit_test_run_fn fn);
-
-#define KIT_TEST(name) \
- static void KIT_TEST_CONCAT3_(kit_test_run_, __LINE__, \
- KIT_TEST_FILE)(int, \
- kit_test_report_fn); \
- KIT_TEST_ON_START_( \
- KIT_TEST_CONCAT3_(kit_test_case_, __LINE__, KIT_TEST_FILE)) { \
- kit_test_register( \
- name, __FILE__, \
- KIT_TEST_CONCAT3_(kit_test_run_, __LINE__, KIT_TEST_FILE)); \
- } \
- static void KIT_TEST_CONCAT3_(kit_test_run_, __LINE__, \
- KIT_TEST_FILE)( \
- int kit_test_index_, kit_test_report_fn kit_test_report_fn_)
-
-#define KIT_REQUIRE(...) \
- kit_test_report_fn_(kit_test_index_, __LINE__, (__VA_ARGS__), 1)
-
-#define KIT_REQUIRE_EQ(...) \
- kit_test_report_fn_(kit_test_index_, __LINE__, __VA_ARGS__)
-
-int kit_run_tests(int argc, char **argv);
-
-#ifndef KIT_DISABLE_SHORT_NAMES
-# define TEST KIT_TEST
-# define REQUIRE KIT_REQUIRE
-# define REQUIRE_EQ KIT_REQUIRE_EQ
-
-# define test_register kit_test_register
-# define run_tests kit_run_tests
-#endif
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/source/tests/_static.c b/source/tests/_static.c
index 54587d3..9975a53 100644
--- a/source/tests/_static.c
+++ b/source/tests/_static.c
@@ -1,55 +1,56 @@
-#include "array_ref.test.c"
-#undef KIT_TEST_FILE
+#define KIT_TEST_IMPLEMENTATION
+#include "main.test.c"
-#include "async_function.test.c"
#undef KIT_TEST_FILE
+#include "array_ref.test.c"
-#include "bigint.test.c"
#undef KIT_TEST_FILE
+#include "async_function.test.c"
-#include "condition_variable.test.c"
#undef KIT_TEST_FILE
+#include "bigint.test.c"
-#include "dynamic_array.test.c"
#undef KIT_TEST_FILE
+#include "condition_variable.test.c"
-#include "file.test.c"
#undef KIT_TEST_FILE
+#include "dynamic_array.test.c"
-#include "input_buffer.test.c"
#undef KIT_TEST_FILE
+#include "file.test.c"
-#include "input_stream.test.c"
#undef KIT_TEST_FILE
+#include "input_buffer.test.c"
-#include "lower_bound.test.c"
#undef KIT_TEST_FILE
+#include "input_stream.test.c"
-#include "mersenne_twister_64.test.c"
#undef KIT_TEST_FILE
+#include "lower_bound.test.c"
-#include "move_back.test.c"
#undef KIT_TEST_FILE
+#include "mersenne_twister_64.test.c"
-#include "mutex.test.c"
#undef KIT_TEST_FILE
+#include "move_back.test.c"
-#include "secure_random.test.c"
#undef KIT_TEST_FILE
+#include "mutex.test.c"
-#include "sha256.test.c"
#undef KIT_TEST_FILE
+#include "secure_random.test.c"
-#include "string_ref.test.c"
#undef KIT_TEST_FILE
+#include "sha256.test.c"
-#include "duration.test.c"
#undef KIT_TEST_FILE
+#include "string_ref.test.c"
-#include "thread.test.c"
#undef KIT_TEST_FILE
+#include "duration.test.c"
-#include "bench.test.c"
#undef KIT_TEST_FILE
+#include "thread.test.c"
-#include "main.test.c"
+#undef KIT_TEST_FILE
+#include "bench.test.c"
diff --git a/source/tests/array_ref.test.c b/source/tests/array_ref.test.c
index cb19850..06e098c 100644
--- a/source/tests/array_ref.test.c
+++ b/source/tests/array_ref.test.c
@@ -1,17 +1,7 @@
#include "../kit/array_ref.h"
#define KIT_TEST_FILE array_ref
-#include "../kit_test/test.h"
-
-TEST("array ref wrap") {
- int foo[] = { 1, 2, 3 };
- AR_WRAP(ref, int, foo);
-
- REQUIRE(ref.size == 3);
- REQUIRE(ref.values[0] == 1);
- REQUIRE(ref.values[1] == 2);
- REQUIRE(ref.values[2] == 3);
-}
+#include "../kit/kit_test.h"
TEST("array ref wrap") {
int foo[] = { 1, 2, 3 };
diff --git a/source/tests/async_function.test.c b/source/tests/async_function.test.c
index 35ce0ce..2e62f64 100644
--- a/source/tests/async_function.test.c
+++ b/source/tests/async_function.test.c
@@ -1,7 +1,7 @@
#include "../kit/async_function.h"
#define KIT_TEST_FILE async_function
-#include "../kit_test/test.h"
+#include "../kit/kit_test.h"
AF_STATE(int, test_foo, );
static AF_DECL(test_foo);
diff --git a/source/tests/atomic.test.c b/source/tests/atomic.test.c
index c1831a3..8bf2c95 100644
--- a/source/tests/atomic.test.c
+++ b/source/tests/atomic.test.c
@@ -2,7 +2,7 @@
#include "../kit/thread.h"
#define KIT_TEST_FILE atomic
-#include "../kit_test/test.h"
+#include "../kit/kit_test.h"
TEST("atomic store and load") {
ATOMIC(int) value;
diff --git a/source/tests/bench.test.c b/source/tests/bench.test.c
index 92e216d..a5536f4 100644
--- a/source/tests/bench.test.c
+++ b/source/tests/bench.test.c
@@ -1,12 +1,11 @@
#define KIT_TEST_FILE bench
-#include "../kit_test/bench.h"
+#include "../kit/kit_test.h"
struct test_foo_ {
double f;
};
BENCHMARK("foo") {
-
/* Benchmark setup.
*/
diff --git a/source/tests/bigint.test.c b/source/tests/bigint.test.c
index c8ac44f..ad0d076 100644
--- a/source/tests/bigint.test.c
+++ b/source/tests/bigint.test.c
@@ -2,7 +2,7 @@
#include "../kit/bigint.h"
#define KIT_TEST_FILE bigint
-#include "../kit_test/test.h"
+#include "../kit/kit_test.h"
#if __STDC_VERSION__ >= 199901L
static_assert(sizeof(bigint_t) == 256, "KIT_BIGINT_SIZE check");
diff --git a/source/tests/condition_variable.test.c b/source/tests/condition_variable.test.c
index dfbe4a6..59882bf 100644
--- a/source/tests/condition_variable.test.c
+++ b/source/tests/condition_variable.test.c
@@ -2,7 +2,7 @@
#include "../kit/thread.h"
#define KIT_TEST_FILE condition_variable
-#include "../kit_test/test.h"
+#include "../kit/kit_test.h"
typedef struct {
mtx_t m;
diff --git a/source/tests/duration.test.c b/source/tests/duration.test.c
index 56919e4..9613583 100644
--- a/source/tests/duration.test.c
+++ b/source/tests/duration.test.c
@@ -1,5 +1,5 @@
#define KIT_TEST_FILE duration
-#include "../kit_test/test.h"
+#include "../kit/kit_test.h"
#if defined(_WIN32) && !defined(__CYGWIN__)
__declspec(dllimport) void __stdcall Sleep(unsigned long timeout);
diff --git a/source/tests/dynamic_array.test.c b/source/tests/dynamic_array.test.c
index 8701e6c..8aa7f42 100644
--- a/source/tests/dynamic_array.test.c
+++ b/source/tests/dynamic_array.test.c
@@ -1,7 +1,7 @@
#include "../kit/dynamic_array.h"
#define KIT_TEST_FILE dynamic_array
-#include "../kit_test/test.h"
+#include "../kit/kit_test.h"
TEST("dynamic array empty") {
DA_CREATE(v, char, 0);
diff --git a/source/tests/file.test.c b/source/tests/file.test.c
index 859de86..94e8ed3 100644
--- a/source/tests/file.test.c
+++ b/source/tests/file.test.c
@@ -3,7 +3,7 @@
#include <string.h>
#define KIT_TEST_FILE file
-#include "../kit_test/test.h"
+#include "../kit/kit_test.h"
TEST("file path cache") {
string_t user = path_user(NULL);
diff --git a/source/tests/input_buffer.test.c b/source/tests/input_buffer.test.c
index 3cd84b6..bfbcaef 100644
--- a/source/tests/input_buffer.test.c
+++ b/source/tests/input_buffer.test.c
@@ -1,7 +1,7 @@
#include "../kit/input_buffer.h"
#define KIT_TEST_FILE input_buffer
-#include "../kit_test/test.h"
+#include "../kit/kit_test.h"
TEST("input buffer read once") {
str_t text = { .size = 3, .values = "foo" };
diff --git a/source/tests/input_stream.test.c b/source/tests/input_stream.test.c
index 467c227..4b609b9 100644
--- a/source/tests/input_stream.test.c
+++ b/source/tests/input_stream.test.c
@@ -2,7 +2,7 @@
#include "../kit/file.h"
#define KIT_TEST_FILE input_stream
-#include "../kit_test/test.h"
+#include "../kit/kit_test.h"
TEST("input stream wrap string") {
char foo[] = "test";
diff --git a/source/tests/lower_bound.test.c b/source/tests/lower_bound.test.c
index 56ec816..ea6e72d 100644
--- a/source/tests/lower_bound.test.c
+++ b/source/tests/lower_bound.test.c
@@ -2,7 +2,7 @@
#include "../kit/array_ref.h"
#define KIT_TEST_FILE lower_bound
-#include "../kit_test/test.h"
+#include "../kit/kit_test.h"
static int kit_less_int(int left, int right) {
return left < right;
diff --git a/source/tests/main.test.c b/source/tests/main.test.c
index 790c8c2..d81a8cb 100644
--- a/source/tests/main.test.c
+++ b/source/tests/main.test.c
@@ -1,10 +1,9 @@
-#include "../kit/status.h"
-#include "../kit_test/bench.h"
-#include "../kit_test/test.h"
+#define KIT_TEST_IMPLEMENTATION
+#include "../kit/kit_test.h"
int main(int argc, char **argv) {
int status = run_tests(argc, argv);
- if (status == KIT_OK)
+ if (status == 0)
status = run_benchmarks(argc, argv);
return status;
}
diff --git a/source/tests/mersenne_twister_64.test.c b/source/tests/mersenne_twister_64.test.c
index f9b0278..a138a41 100644
--- a/source/tests/mersenne_twister_64.test.c
+++ b/source/tests/mersenne_twister_64.test.c
@@ -2,7 +2,7 @@
#include "../kit/secure_random.h"
#define KIT_TEST_FILE mersenne_twister_64
-#include "../kit_test/test.h"
+#include "../kit/kit_test.h"
enum { MT64_TEST_SIZE = 1000 };
diff --git a/source/tests/move_back.test.c b/source/tests/move_back.test.c
index f3f6dc4..18171b5 100644
--- a/source/tests/move_back.test.c
+++ b/source/tests/move_back.test.c
@@ -1,7 +1,7 @@
#include "../kit/move_back.h"
#define KIT_TEST_FILE move_back
-#include "../kit_test/test.h"
+#include "../kit/kit_test.h"
static int is_equal(int x, int y) {
return x == y;
diff --git a/source/tests/mutex.test.c b/source/tests/mutex.test.c
index ce26991..c2e5d85 100644
--- a/source/tests/mutex.test.c
+++ b/source/tests/mutex.test.c
@@ -2,7 +2,7 @@
#include "../kit/thread.h"
#define KIT_TEST_FILE mutex
-#include "../kit_test/test.h"
+#include "../kit/kit_test.h"
enum { SLEEP = 400000000, TICK_COUNT = 200, THREAD_COUNT = 100 };
diff --git a/source/tests/secure_random.test.c b/source/tests/secure_random.test.c
index 0f25b47..e54edee 100644
--- a/source/tests/secure_random.test.c
+++ b/source/tests/secure_random.test.c
@@ -2,7 +2,7 @@
#include <string.h>
#define KIT_TEST_FILE secure_random
-#include "../kit_test/test.h"
+#include "../kit/kit_test.h"
TEST("secure random") {
int v[20];
diff --git a/source/tests/sha256.test.c b/source/tests/sha256.test.c
index 0f751df..215a73b 100644
--- a/source/tests/sha256.test.c
+++ b/source/tests/sha256.test.c
@@ -2,7 +2,7 @@
#include "../kit/array_ref.h"
#define KIT_TEST_FILE sha256_64
-#include "../kit_test/test.h"
+#include "../kit/kit_test.h"
#include <string.h>
diff --git a/source/tests/string_ref.test.c b/source/tests/string_ref.test.c
index 2891f16..a75abc5 100644
--- a/source/tests/string_ref.test.c
+++ b/source/tests/string_ref.test.c
@@ -1,7 +1,7 @@
#include "../kit/string_ref.h"
#define KIT_TEST_FILE string_ref
-#include "../kit_test/test.h"
+#include "../kit/kit_test.h"
TEST("static string wrap") {
str_t ref = SZ("foo bar");
diff --git a/source/tests/test_cpp.cpp b/source/tests/test_cpp.cpp
index 8b762e4..919ebb9 100644
--- a/source/tests/test_cpp.cpp
+++ b/source/tests/test_cpp.cpp
@@ -1,4 +1,5 @@
-#include "../kit_test/test.h"
+#define KIT_TEST_IMPLEMENTATION
+#include "../kit/kit_test.h"
TEST("foo") {
REQUIRE(20 + 22 == 42);
diff --git a/source/tests/test_signals.cpp b/source/tests/test_signals.cpp
index 1b4acc7..0ffd5eb 100644
--- a/source/tests/test_signals.cpp
+++ b/source/tests/test_signals.cpp
@@ -1,4 +1,5 @@
-#include "../kit_test/test.h"
+#define KIT_TEST_IMPLEMENTATION
+#include "../kit/kit_test.h"
#include <cstdlib>
#include <stdexcept>
diff --git a/source/tests/test_too_many_assertions.c b/source/tests/test_too_many_assertions.c
index 662207d..a1ce710 100644
--- a/source/tests/test_too_many_assertions.c
+++ b/source/tests/test_too_many_assertions.c
@@ -1,4 +1,6 @@
-#include "../kit_test/test.h"
+#define KIT_TEST_IMPLEMENTATION
+#define KIT_TEST_ASSERTIONS_LIMIT 10
+#include "../kit/kit_test.h"
TEST("foo") {
int i;
diff --git a/source/tests/test_too_many_tests.c b/source/tests/test_too_many_tests.c
index d4842e4..9691e2c 100644
--- a/source/tests/test_too_many_tests.c
+++ b/source/tests/test_too_many_tests.c
@@ -1,4 +1,6 @@
-#include "../kit_test/test.h"
+#define KIT_TEST_IMPLEMENTATION
+#define KIT_TESTS_SIZE_LIMIT 40
+#include "../kit/kit_test.h"
void bar(int index, kit_test_report_fn report) { }
diff --git a/source/tests/thread.test.c b/source/tests/thread.test.c
index 50f7c04..b8069da 100644
--- a/source/tests/thread.test.c
+++ b/source/tests/thread.test.c
@@ -1,7 +1,7 @@
#include "../kit/thread.h"
#define KIT_TEST_FILE thread
-#include "../kit_test/test.h"
+#include "../kit/kit_test.h"
static int test_nothing(void *_) {
return 0;