From 86a1707b75e97ab9c15a5f986b2220a66fd19230 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Mon, 21 Sep 2015 23:26:47 +0200 Subject: [PATCH 001/211] Added cmake option to turn on/off tests (off by default) --- .travis.yml | 1 + CMakeLists.txt | 3 +++ appveyor.yml | 1 + 3 files changed, 5 insertions(+) diff --git a/.travis.yml b/.travis.yml index d9a7c9aa..83c86474 100644 --- a/.travis.yml +++ b/.travis.yml @@ -30,6 +30,7 @@ script: - > cmake -Wno-dev + -DTESTS=ON -DCOVERALLS=${COVERAGE} -DCMAKE_BUILD_TYPE=${CONFIGURATION} -DCMAKE_INSTALL_PREFIX=criterion-${TRAVIS_TAG} diff --git a/CMakeLists.txt b/CMakeLists.txt index 73c04551..3ee09e3e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -50,6 +50,7 @@ endif() # Setup coveralls +option(TESTS "Turn on the samples and test" OFF) option(COVERALLS "Turn on coveralls support" OFF) option(COVERALLS_UPLOAD "Upload the generated coveralls json" ON) @@ -192,6 +193,8 @@ add_custom_target(gcov -P "${CMAKE_MODULE_PATH}/Gcov.cmake" ) +if (TESTS) enable_testing() add_subdirectory(samples) add_subdirectory(test) +endif () diff --git a/appveyor.yml b/appveyor.yml index 46eb294b..869d5cad 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -38,6 +38,7 @@ install: - > cmake -Wno-dev + -DTESTS=ON -DCMAKE_INSTALL_PREFIX="criterion-%RELEASE_NAME%" -DCMAKE_BUILD_TYPE="%CONFIGURATION%" -G "%GENERATOR%" From d05d71bbd5f459f77fb1e1a47482d3fe0b8c2142 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Tue, 22 Sep 2015 00:16:45 +0200 Subject: [PATCH 002/211] Renamed TESTS cmake option to CTESTS --- .travis.yml | 2 +- CMakeLists.txt | 4 ++-- appveyor.yml | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index 83c86474..621b5a15 100644 --- a/.travis.yml +++ b/.travis.yml @@ -30,7 +30,7 @@ script: - > cmake -Wno-dev - -DTESTS=ON + -DCTESTS=ON -DCOVERALLS=${COVERAGE} -DCMAKE_BUILD_TYPE=${CONFIGURATION} -DCMAKE_INSTALL_PREFIX=criterion-${TRAVIS_TAG} diff --git a/CMakeLists.txt b/CMakeLists.txt index 3ee09e3e..9bd4d044 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -50,7 +50,7 @@ endif() # Setup coveralls -option(TESTS "Turn on the samples and test" OFF) +option(CTESTS "Turn on the samples and test" OFF) option(COVERALLS "Turn on coveralls support" OFF) option(COVERALLS_UPLOAD "Upload the generated coveralls json" ON) @@ -193,7 +193,7 @@ add_custom_target(gcov -P "${CMAKE_MODULE_PATH}/Gcov.cmake" ) -if (TESTS) +if (CTESTS) enable_testing() add_subdirectory(samples) add_subdirectory(test) diff --git a/appveyor.yml b/appveyor.yml index 869d5cad..29952bb7 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -38,7 +38,7 @@ install: - > cmake -Wno-dev - -DTESTS=ON + -DCTESTS=ON -DCMAKE_INSTALL_PREFIX="criterion-%RELEASE_NAME%" -DCMAKE_BUILD_TYPE="%CONFIGURATION%" -G "%GENERATOR%" From 984ecc5a74ff6e631105675095e89174b5c254ee Mon Sep 17 00:00:00 2001 From: Snaipe Date: Tue, 22 Sep 2015 01:12:32 +0200 Subject: [PATCH 003/211] Added missing include directory addition for libintl dependency --- CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 9bd4d044..14068747 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -171,6 +171,7 @@ endif() if (LIBINTL_LIB_FOUND) target_link_libraries(criterion ${LIBINTL_LIBRARIES}) + include_directories(${LIBINTL_INCLUDE_DIR}) endif() if (COVERALLS) From 1c42bf8de0df2ff9362b4a58488c540eefcc3b1e Mon Sep 17 00:00:00 2001 From: Snaipe Date: Tue, 22 Sep 2015 01:46:56 +0200 Subject: [PATCH 004/211] Fixed signedness comparison warning on delete_arr --- include/criterion/alloc.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/include/criterion/alloc.h b/include/criterion/alloc.h index 8b80eadb..741b999d 100644 --- a/include/criterion/alloc.h +++ b/include/criterion/alloc.h @@ -88,9 +88,8 @@ namespace criterion { void delete_arr(T* ptr) { size_t len = *(reinterpret_cast(ptr)); T* arr = reinterpret_cast(reinterpret_cast(ptr) + 1); - for (int i = 0; i < len; ++i) { + for (size_t i = 0; i < len; ++i) arr[i].~T(); - } cr_free(ptr); } From 0de2797dee60088f9281fc29b168947d54ec9b80 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Tue, 22 Sep 2015 12:12:54 +0200 Subject: [PATCH 005/211] Renamed assume macros for consistency --- doc/theories.rst | 16 ++++++++-------- include/criterion/theories.h | 30 +++++++++++++++++++++--------- 2 files changed, 29 insertions(+), 17 deletions(-) diff --git a/doc/theories.rst b/doc/theories.rst index f95bae0d..4f07d8aa 100644 --- a/doc/theories.rst +++ b/doc/theories.rst @@ -78,26 +78,26 @@ Macro Description ------------------------------------------------------- ---------------------------------------------------- ``cr_assume_float_neq(Actual, Unexpected, Epsilon)`` Assumes Actual != Expected with an error of Epsilon. ------------------------------------------------------- ---------------------------------------------------- -``cr_assume_strings_eq(Actual, Expected)`` Assumes Actual and Expected are the same string. +``cr_assume_str_eq(Actual, Expected)`` Assumes Actual and Expected are the same string. ------------------------------------------------------- ---------------------------------------------------- -``cr_assume_strings_neq(Actual, Unexpected)`` Assumes Actual and Expected are not the same string. +``cr_assume_str_neq(Actual, Unexpected)`` Assumes Actual and Expected are not the same string. ------------------------------------------------------- ---------------------------------------------------- -``cr_assume_strings_lt(Actual, Expected)`` Assumes Actual is less than Expected +``cr_assume_str_lt(Actual, Expected)`` Assumes Actual is less than Expected lexicographically. ------------------------------------------------------- ---------------------------------------------------- -``cr_assume_strings_leq(Actual, Expected)`` Assumes Actual is less or equal to Expected +``cr_assume_str_leq(Actual, Expected)`` Assumes Actual is less or equal to Expected lexicographically. ------------------------------------------------------- ---------------------------------------------------- -``cr_assume_strings_gt(Actual, Expected)`` Assumes Actual is greater than Expected +``cr_assume_str_gt(Actual, Expected)`` Assumes Actual is greater than Expected lexicographically. ------------------------------------------------------- ---------------------------------------------------- -``cr_assume_strings_geq(Actual, Expected)`` Assumes Actual is greater or equal to Expected +``cr_assume_str_geq(Actual, Expected)`` Assumes Actual is greater or equal to Expected lexicographically. ------------------------------------------------------- ---------------------------------------------------- -``cr_assume_arrays_eq(Actual, Expected, Size)`` Assumes all elements of Actual (from 0 to Size - 1) +``cr_assume_arr_eq(Actual, Expected, Size)`` Assumes all elements of Actual (from 0 to Size - 1) are equals to those of Expected. ------------------------------------------------------- ---------------------------------------------------- -``cr_assume_arrays_neq(Actual, Unexpected, Size)`` Assumes one or more elements of Actual (from 0 to +``cr_assume_arr_neq(Actual, Unexpected, Size)`` Assumes one or more elements of Actual (from 0 to Size - 1) differs from their counterpart in Expected. ======================================================= ==================================================== diff --git a/include/criterion/theories.h b/include/criterion/theories.h index 29055b53..5cdf76af 100644 --- a/include/criterion/theories.h +++ b/include/criterion/theories.h @@ -111,18 +111,18 @@ struct criterion_datapoints { cr_assume((Expected) - (Actual) > (Epsilon) \ || (Actual) - (Expected) > (Epsilon)) -# define cr_assume_strings_op_(Op, Actual, Expected) \ +# define cr_assume_str_op_(Op, Actual, Expected) \ cr_assume(strcmp((Actual), (Expected)) Op 0) -# define cr_assume_strings_eq(Actual, Expected) cr_assume_strings_op_(==, Actual, Expected) -# define cr_assume_strings_neq(Actual, Expected) cr_assume_strings_op_(!=, Actual, Expected) -# define cr_assume_strings_lt(Actual, Expected) cr_assume_strings_op_(<, Actual, Expected) -# define cr_assume_strings_leq(Actual, Expected) cr_assume_strings_op_(<=, Actual, Expected) -# define cr_assume_strings_gt(Actual, Expected) cr_assume_strings_op_(>, Actual, Expected) -# define cr_assume_strings_geq(Actual, Expected) cr_assume_strings_op_(>=, Actual, Expected) +# define cr_assume_str_eq(Actual, Expected) cr_assume_str_op_(==, Actual, Expected) +# define cr_assume_str_neq(Actual, Expected) cr_assume_str_op_(!=, Actual, Expected) +# define cr_assume_str_lt(Actual, Expected) cr_assume_str_op_(<, Actual, Expected) +# define cr_assume_str_leq(Actual, Expected) cr_assume_str_op_(<=, Actual, Expected) +# define cr_assume_str_gt(Actual, Expected) cr_assume_str_op_(>, Actual, Expected) +# define cr_assume_str_geq(Actual, Expected) cr_assume_str_op_(>=, Actual, Expected) -# define cr_assume_arrays_eq(Actual, Expected, Size) cr_assume(!memcmp((A), (B), (Size))) -# define cr_assume_arrays_neq(Actual, Expected, Size) cr_assume(memcmp((A), (B), (Size))) +# define cr_assume_arr_eq(Actual, Expected, Size) cr_assume(!memcmp((A), (B), (Size))) +# define cr_assume_arr_neq(Actual, Expected, Size) cr_assume(memcmp((A), (B), (Size))) CR_API void cr_theory_main(struct criterion_datapoints *dps, size_t datapoints, void (*fnptr)(void)); @@ -142,4 +142,16 @@ CR_API void cr_theory_main(struct criterion_datapoints *dps, size_t datapoints, CR_END_C_API +# ifndef CRITERION_NO_COMPAT +# define cr_assume_strings_eq(...) CRITERION_ASSERT_DEPRECATED_B(cr_assume_strings_eq, cr_assume_str_eq) cr_assume_str_eq(__VA_ARGS__) +# define cr_assume_strings_neq(...) CRITERION_ASSERT_DEPRECATED_B(cr_assume_strings_neq, cr_assume_str_neq) cr_assume_str_neq(__VA_ARGS__) +# define cr_assume_strings_lt(...) CRITERION_ASSERT_DEPRECATED_B(cr_assume_strings_lt, cr_assume_str_lt) cr_assume_str_lt(__VA_ARGS__) +# define cr_assume_strings_leq(...) CRITERION_ASSERT_DEPRECATED_B(cr_assume_strings_leq, cr_assume_str_leq) cr_assume_str_leq(__VA_ARGS__) +# define cr_assume_strings_gt(...) CRITERION_ASSERT_DEPRECATED_B(cr_assume_strings_gt, cr_assume_str_gt) cr_assume_str_gt(__VA_ARGS__) +# define cr_assume_strings_geq(...) CRITERION_ASSERT_DEPRECATED_B(cr_assume_strings_geq, cr_assume_str_geq) cr_assume_str_geq(__VA_ARGS__) + +# define cr_assume_arrays_eq(...) CRITERION_ASSERT_DEPRECATED_B(cr_assume_arrays_eq, cr_assume_arr_eq) cr_assume_arr_eq(__VA_ARGS__) +# define cr_assume_arrays_neq(...) CRITERION_ASSERT_DEPRECATED_B(cr_assume_arrays_neq, cr_assume_arr_neq) cr_assume_arr_neq(__VA_ARGS__) +# endif + #endif /* !CRITERION_THEORIES_H_ */ From ca85603b0d60073bbb96a8a4617e79aac7ec4451 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Tue, 22 Sep 2015 12:14:33 +0200 Subject: [PATCH 006/211] Removed unused include --- src/compat/mockfile.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/compat/mockfile.c b/src/compat/mockfile.c index 4e2716d0..8f662b2e 100644 --- a/src/compat/mockfile.c +++ b/src/compat/mockfile.c @@ -31,7 +31,6 @@ #include "criterion/redirect.h" #ifdef __unix__ -#include # ifdef BSD typedef int cr_count; From 3af74ac9dd8c8c6550c7ea4e8daefff1f441f404 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Tue, 22 Sep 2015 14:06:36 +0200 Subject: [PATCH 007/211] Added package links for brew and AUR --- README.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/README.md b/README.md index 85ec6944..3833265e 100644 --- a/README.md +++ b/README.md @@ -39,6 +39,13 @@ the user would have with other frameworks: ## Downloads +### Packages + +* Mac OS X: `brew install snaipe/soft/criterion` +* [AUR](https://aur.archlinux.org/packages/criterion/): `yaourt -S criterion` + +### Binary archives + * [Linux (x86_64)](https://github.com/Snaipe/Criterion/releases/download/v2.1.0/criterion-v2.1.0-linux-x86_64.tar.bz2) * [OS X (x86_64)](https://github.com/Snaipe/Criterion/releases/download/v2.1.0/criterion-v2.1.0-osx-x86_64.tar.bz2) * [Windows (MSVC - x86_64)](https://github.com/Snaipe/Criterion/releases/download/v2.1.0/criterion-v2.1.0-windows-msvc-x86_64.tar.bz2) From a086aa995cfd3ee0d1555b85b86ca2abca962791 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Tue, 22 Sep 2015 21:43:22 +0200 Subject: [PATCH 008/211] Added parallelisation code & cleaned up runner code --- src/compat/process.c | 30 +++- src/compat/process.h | 3 + src/core/coroutine.h | 181 ++++++++++++++++++++++++ src/core/runner.c | 319 ++++++++++++++++++++++++------------------- src/core/runner.h | 2 - src/core/worker.c | 42 ++++-- src/core/worker.h | 40 ++++-- src/io/event.c | 24 ++-- src/io/event.h | 5 + 9 files changed, 465 insertions(+), 181 deletions(-) create mode 100644 src/core/coroutine.h diff --git a/src/compat/process.c b/src/compat/process.c index 72320d25..b107686b 100644 --- a/src/compat/process.c +++ b/src/compat/process.c @@ -126,9 +126,12 @@ static void handle_sigchld(UNUSED int sig) { (s_proc_handle) { pid }, get_status(status) }; - char buf[sizeof (int) + sizeof (struct worker_status)]; + unsigned long long pid_ull = (unsigned long long) pid; + + char buf[sizeof (int) + sizeof (pid_ull) + sizeof (struct worker_status)]; memcpy(buf, &kind, sizeof (kind)); - memcpy(buf + sizeof (kind), &ws, sizeof (ws)); + memcpy(buf + sizeof (kind), &pid_ull, sizeof (pid_ull)); + memcpy(buf + sizeof (kind) + sizeof (pid_ull), &ws, sizeof (ws)); if (write(fd, &buf, sizeof (buf)) < (ssize_t) sizeof (buf)) abort(); @@ -155,9 +158,12 @@ static void CALLBACK handle_child_terminated(PVOID lpParameter, (s_proc_handle) { wctx->proc_handle }, get_status(status) }; - char buf[sizeof (int) + sizeof (struct worker_status)]; + unsigned long long pid_ull = (unsigned long long) GetProcessId(wctx->proc_handle); + + char buf[sizeof (int) + sizeof (pid_ull) + sizeof (struct worker_status)]; memcpy(buf, &kind, sizeof (kind)); - memcpy(buf + sizeof (kind), &ws, sizeof (ws)); + memcpy(buf + sizeof (kind), &pid_ull, sizeof (pid_ull)); + memcpy(buf + sizeof (kind) + sizeof (pid_ull), &ws, sizeof (ws)); DWORD written; WriteFile(g_worker_pipe->fhs[1], buf, sizeof (buf), &written, NULL); @@ -406,3 +412,19 @@ bool is_current_process(s_proc_handle *proc) { return proc->pid == getpid(); #endif } + +unsigned long long get_process_id(void) { +#ifdef VANILLA_WIN32 + return (unsigned long long) GetCurrentProcessId(); +#else + return (unsigned long long) getpid(); +#endif +} + +unsigned long long get_process_id_of(s_proc_handle *proc) { +#ifdef VANILLA_WIN32 + return (unsigned long long) GetProcessId(proc->handle); +#else + return (unsigned long long) proc->pid; +#endif +} diff --git a/src/compat/process.h b/src/compat/process.h index 0d707708..103d835b 100644 --- a/src/compat/process.h +++ b/src/compat/process.h @@ -55,4 +55,7 @@ void wait_process(s_proc_handle *handle, int *status); s_proc_handle *get_current_process(); bool is_current_process(s_proc_handle *proc); +unsigned long long get_process_id(void); +unsigned long long get_process_id_of(s_proc_handle *proc); + #endif /* !COMPAT_PROCESS_H_ */ diff --git a/src/core/coroutine.h b/src/core/coroutine.h new file mode 100644 index 00000000..a8fad9b8 --- /dev/null +++ b/src/core/coroutine.h @@ -0,0 +1,181 @@ +/* coroutine.h + * + * Coroutine mechanics, implemented on top of standard ANSI C. See + * http://www.chiark.greenend.org.uk/~sgtatham/coroutines.html for + * a full discussion of the theory behind this. + * + * To use these macros to define a coroutine, you need to write a + * function that looks something like this. + * + * [Simple version using static variables (scr macros)] + * int ascending (void) { + * static int i; + * + * scrBegin; + * for (i=0; i<10; i++) { + * scrReturn(i); + * } + * scrFinish(-1); + * } + * + * [Re-entrant version using an explicit context structure (ccr macros)] + * int ascending (ccrContParam) { + * ccrBeginContext; + * int i; + * ccrEndContext(foo); + * + * ccrBegin(foo); + * for (foo->i=0; foo->i<10; foo->i++) { + * ccrReturn(foo->i); + * } + * ccrFinish(-1); + * } + * + * In the static version, you need only surround the function body + * with `scrBegin' and `scrFinish', and then you can do `scrReturn' + * within the function and on the next call control will resume + * just after the scrReturn statement. Any local variables you need + * to be persistent across an `scrReturn' must be declared static. + * + * In the re-entrant version, you need to declare your persistent + * variables between `ccrBeginContext' and `ccrEndContext'. These + * will be members of a structure whose name you specify in the + * parameter to `ccrEndContext'. + * + * The re-entrant macros will malloc() the state structure on first + * call, and free() it when `ccrFinish' is reached. If you want to + * abort in the middle, you can use `ccrStop' to free the state + * structure immediately (equivalent to an explicit return() in a + * caller-type routine). + * + * A coroutine returning void type may call `ccrReturnV', + * `ccrFinishV' and `ccrStopV', or `scrReturnV', to avoid having to + * specify an empty parameter to the ordinary return macros. + * + * Ground rules: + * - never put `ccrReturn' or `scrReturn' within an explicit `switch'. + * - never put two `ccrReturn' or `scrReturn' statements on the same + * source line. + * + * The caller of a static coroutine calls it just as if it were an + * ordinary function: + * + * void main(void) { + * int i; + * do { + * i = ascending(); + * printf("got number %d\n", i); + * } while (i != -1); + * } + * + * The caller of a re-entrant coroutine must provide a context + * variable: + * + * void main(void) { + * ccrContext z = 0; + * do { + * printf("got number %d\n", ascending (&z)); + * } while (z); + * } + * + * Note that the context variable is set back to zero when the + * coroutine terminates (by crStop, or by control reaching + * crFinish). This can make the re-entrant coroutines more useful + * than the static ones, because you can tell when they have + * finished. + * + * If you need to dispose of a crContext when it is non-zero (that + * is, if you want to stop calling a coroutine without suffering a + * memory leak), the caller should call `ccrAbort(ctx)' where `ctx' + * is the context variable. + * + * This mechanism could have been better implemented using GNU C + * and its ability to store pointers to labels, but sadly this is + * not part of the ANSI C standard and so the mechanism is done by + * case statements instead. That's why you can't put a crReturn() + * inside a switch() statement. + */ + +/* + * coroutine.h is copyright 1995,2000 Simon Tatham. + * + * 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 SIMON TATHAM 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. + * + * $Id$ + */ + +#ifndef COROUTINE_H +#define COROUTINE_H + +#include + +/* + * `scr' macros for static coroutines. + */ + +#define scrBegin static int scrLine = 0; switch(scrLine) { case 0:; +#define scrFinish(z) } return (z) +#define scrFinishV } return + +#define scrReturn(z) \ + do {\ + scrLine=__LINE__;\ + return (z); case __LINE__:;\ + } while (0) +#define scrReturnV \ + do {\ + scrLine=__LINE__;\ + return; case __LINE__:;\ + } while (0) + +/* + * `ccr' macros for re-entrant coroutines. + */ + +#define ccrContParam void **ccrParam + +#define ccrBeginContext struct ccrContextTag { int ccrLine +#define ccrEndContext(x) } *x = (struct ccrContextTag *)*ccrParam + +#define ccrBegin(x) if(!x) {x= *ccrParam=malloc(sizeof(*x)); x->ccrLine=0;}\ + if (x) switch(x->ccrLine) { case 0:; +#define ccrFinish(z) } free(*ccrParam); *ccrParam=0; return (z) +#define ccrFinishV } free(*ccrParam); *ccrParam=0; return + +#define ccrReturn(z) \ + do {\ + ((struct ccrContextTag *)*ccrParam)->ccrLine=__LINE__;\ + return (z); case __LINE__:;\ + } while (0) +#define ccrReturnV \ + do {\ + ((struct ccrContextTag *)*ccrParam)->ccrLine=__LINE__;\ + return; case __LINE__:;\ + } while (0) + +#define ccrStop(z) do{ free(*ccrParam); *ccrParam=0; return (z); }while(0) +#define ccrStopV do{ free(*ccrParam); *ccrParam=0; return; }while(0) + +#define ccrContext void * +#define ccrAbort(ctx) do { free (ctx); ctx = 0; } while (0) + +#endif /* COROUTINE_H */ diff --git a/src/core/runner.c b/src/core/runner.c index a998843c..67b5fad5 100644 --- a/src/core/runner.c +++ b/src/core/runner.c @@ -39,6 +39,7 @@ #include "abort.h" #include "config.h" #include "common.h" +#include "coroutine.h" #ifdef HAVE_PCRE #include "string/extmatch.h" @@ -130,45 +131,6 @@ struct criterion_test_set *criterion_init(void) { return set; } -typedef void (*f_test_run)(struct criterion_global_stats *, - struct criterion_suite_stats *, - struct criterion_test *, - struct criterion_suite *); - -static void map_tests(struct criterion_test_set *set, - struct criterion_global_stats *stats, - f_test_run fun) { - - FOREACH_SET(struct criterion_suite_set *s, set->suites) { - if (!s->tests) - continue; - - report(PRE_SUITE, s); - log(pre_suite, s); - - struct criterion_suite_stats *suite_stats = suite_stats_init(&s->suite); - - struct event ev = { .kind = PRE_SUITE }; - stat_push_event(stats, suite_stats, NULL, &ev); - - FOREACH_SET(struct criterion_test *t, s->tests) { - fun(stats, suite_stats, t, &s->suite); - if (criterion_options.fail_fast && stats->tests_failed > 0) - break; - if (!is_runner()) { - sfree(suite_stats); - return; - } - } - - report(POST_SUITE, suite_stats); - log(post_suite, suite_stats); - - sfree(suite_stats); - } - -} - static void run_test_child(struct criterion_test *test, struct criterion_suite *suite) { @@ -224,17 +186,6 @@ static INLINE bool is_disabled(struct criterion_test *t, s_pipe_handle *g_worker_pipe; -struct execution_context { - bool test_started; - bool normal_finish; - bool cleaned_up; - struct criterion_global_stats *stats; - struct criterion_test *test; - struct criterion_test_stats *test_stats; - struct criterion_suite *suite; - struct criterion_suite_stats *suite_stats; -}; - static void handle_worker_terminated(struct event *ev, struct execution_context *ctx) { @@ -301,120 +252,74 @@ static void handle_worker_terminated(struct event *ev, } } -static void run_test(struct criterion_global_stats *stats, +static void handle_event(struct event *ev) { + struct execution_context *ctx = &ev->worker->ctx; + if (ev->kind < WORKER_TERMINATED) + stat_push_event(ctx->stats, ctx->suite_stats, ctx->test_stats, ev); + switch (ev->kind) { + case PRE_INIT: + report(PRE_INIT, ctx->test); + log(pre_init, ctx->test); + break; + case PRE_TEST: + report(PRE_TEST, ctx->test); + log(pre_test, ctx->test); + ctx->test_started = true; + break; + case THEORY_FAIL: { + struct criterion_theory_stats ths = { + .formatted_args = (char*) ev->data, + .stats = ctx->test_stats, + }; + report(THEORY_FAIL, &ths); + log(theory_fail, &ths); + } break; + case ASSERT: + report(ASSERT, ev->data); + log(assert, ev->data); + break; + case POST_TEST: + report(POST_TEST, ctx->test_stats); + log(post_test, ctx->test_stats); + ctx->normal_finish = true; + break; + case POST_FINI: + report(POST_FINI, ctx->test_stats); + log(post_fini, ctx->test_stats); + ctx->cleaned_up = true; + break; + case WORKER_TERMINATED: + handle_worker_terminated(ev, ctx); + break; + } +} + +static struct process *run_test(struct criterion_global_stats *stats, struct criterion_suite_stats *suite_stats, struct criterion_test *test, struct criterion_suite *suite, struct test_single_param *param) { struct criterion_test_stats *test_stats = test_stats_init(test); - struct process *proc = NULL; if (is_disabled(test, suite)) { stat_push_event(stats, suite_stats, test_stats, &(struct event) { .kind = PRE_INIT }); - goto cleanup; + return NULL; } - proc = spawn_test_worker(test, suite, run_test_child, g_worker_pipe, param); - if (proc == NULL && !is_runner()) - goto cleanup; - struct execution_context ctx = { .stats = stats, .test = test, .test_stats = test_stats, .suite = suite, .suite_stats = suite_stats, + .param = param, }; - struct event *ev; - while ((ev = worker_read_event(proc)) != NULL) { - if (ev->kind < WORKER_TERMINATED) - stat_push_event(stats, suite_stats, test_stats, ev); - switch (ev->kind) { - case PRE_INIT: - report(PRE_INIT, test); - log(pre_init, test); - break; - case PRE_TEST: - report(PRE_TEST, test); - log(pre_test, test); - ctx.test_started = true; - break; - case THEORY_FAIL: { - struct criterion_theory_stats ths = { - .formatted_args = (char*) ev->data, - .stats = test_stats, - }; - report(THEORY_FAIL, &ths); - log(theory_fail, &ths); - } break; - case ASSERT: - report(ASSERT, ev->data); - log(assert, ev->data); - break; - case POST_TEST: - report(POST_TEST, test_stats); - log(post_test, test_stats); - ctx.normal_finish = true; - break; - case POST_FINI: - report(POST_FINI, test_stats); - log(post_fini, test_stats); - ctx.cleaned_up = true; - break; - case WORKER_TERMINATED: - handle_worker_terminated(ev, &ctx); - sfree(ev); - goto cleanup; - } - sfree(ev); - } + return spawn_test_worker(&ctx, run_test_child, g_worker_pipe); -cleanup: - sfree(test_stats); - sfree(proc); -} - -static void run_test_param(struct criterion_global_stats *stats, - struct criterion_suite_stats *suite_stats, - struct criterion_test *test, - struct criterion_suite *suite) { - - if (!test->data->param_) - return; - - struct criterion_test_params params = test->data->param_(); - for (size_t i = 0; i < params.length; ++i) { - struct test_single_param param = { params.size, (char *) params.params + i * params.size }; - - run_test(stats, suite_stats, test, suite, ¶m); - if (criterion_options.fail_fast && stats->tests_failed > 0) - break; - if (!is_runner()) - break; - } - - if (params.cleanup) - params.cleanup(¶ms); -} - -static void run_test_switch(struct criterion_global_stats *stats, - struct criterion_suite_stats *suite_stats, - struct criterion_test *test, - struct criterion_suite *suite) { - - switch (test->data->kind_) { - case CR_TEST_NORMAL: - run_test(stats, suite_stats, test, suite, NULL); - break; - case CR_TEST_PARAMETERIZED: - run_test_param(stats, suite_stats, test, suite); - break; - default: break; - } } #ifdef HAVE_PCRE @@ -450,6 +355,134 @@ void criterion_finalize(struct criterion_test_set *set) { sfree(set); } +static struct process *run_next_test(struct criterion_test_set *p_set, + struct criterion_global_stats *p_stats, + ccrContParam) { + ccrBeginContext; + struct criterion_suite_set *suite_set; + struct criterion_test *test; + struct criterion_suite_stats *suite_stats; + struct criterion_test_set *set; + struct criterion_global_stats *stats; + struct criterion_test_params params; + + struct criterion_ordered_set_node *ns; + struct criterion_ordered_set_node *nt; + size_t i; + ccrEndContext(ctx); + + ccrBegin(ctx); + + ctx->set = p_set; + ctx->stats = p_stats; + ccrReturn(NULL); + + for (ctx->ns = ctx->set->suites->first; ctx->ns; ctx->ns = ctx->ns->next) { + ctx->suite_set = (void*) ctx->ns->data; + + if (!ctx->suite_set->tests) + continue; + + report(PRE_SUITE, ctx->suite_set); + log(pre_suite, ctx->suite_set); + + ctx->suite_stats = suite_stats_init(&ctx->suite_set->suite); + + struct event ev = { .kind = PRE_SUITE }; + stat_push_event(ctx->stats, ctx->suite_stats, NULL, &ev); + + for (ctx->nt = ctx->suite_set->tests->first; ctx->nt; ctx->nt = ctx->nt->next) { + ctx->test = (void*) ctx->nt->data; + + if (ctx->test->data->kind_ == CR_TEST_PARAMETERIZED + && ctx->test->data->param_) { + + ctx->params = ctx->test->data->param_(); + for (ctx->i = 0; ctx->i < ctx->params.length; ++ctx->i) { + struct test_single_param param = { + ctx->params.size, + (char *) ctx->params.params + ctx->i * ctx->params.size + }; + + struct process *worker = run_test(ctx->stats, + ctx->suite_stats, + ctx->test, + &ctx->suite_set->suite, + ¶m); + + if (!is_runner()) { + sfree(ctx->suite_stats); + ccrReturn(NULL); + } + + ccrReturn(worker); + } + + if (ctx->params.cleanup) + ctx->params.cleanup(&ctx->params); + } else { + struct process *worker = run_test(ctx->stats, + ctx->suite_stats, + ctx->test, + &ctx->suite_set->suite, + NULL); + + if (!is_runner()) { + sfree(ctx->suite_stats); + ccrReturn(NULL); + } + + ccrReturn(worker); + } + } + + report(POST_SUITE, ctx->suite_stats); + log(post_suite, ctx->suite_stats); + + sfree(ctx->suite_stats); + } + + ccrFinish(NULL); +} + +static void run_tests_async(struct criterion_test_set *set, + struct criterion_global_stats *stats) { + + ccrContext ctx = 0; + + size_t nb_workers = 1; + struct worker_set workers = { + .max_workers = nb_workers, + .workers = malloc(sizeof (struct process*) * nb_workers), + }; + + size_t active_workers = 0; + + // initialization of coroutine + run_next_test(set, stats, &ctx); + + for (size_t i = 0; i < nb_workers; ++i) { + workers.workers[i] = run_next_test(NULL, NULL, &ctx); + ++active_workers; + } + + FILE *event_pipe = pipe_in(g_worker_pipe, PIPE_DUP); + + struct event *ev; + while ((ev = worker_read_event(&workers, event_pipe)) != NULL) { + handle_event(ev); + if (ev->kind == WORKER_TERMINATED) { + workers.workers[ev->worker_index] = run_next_test(NULL, NULL, &ctx); + if (workers.workers[ev->worker_index] == NULL) + --active_workers; + } + sfree(ev); + if (!active_workers) + break; + } + +} + static int criterion_run_all_tests_impl(struct criterion_test_set *set) { report(PRE_ALL, set); log(pre_all, set); @@ -461,7 +494,7 @@ static int criterion_run_all_tests_impl(struct criterion_test_set *set) { abort(); struct criterion_global_stats *stats = stats_init(); - map_tests(set, stats, run_test_switch); + run_tests_async(set, stats); int result = is_runner() ? stats->tests_failed == 0 : -1; diff --git a/src/core/runner.h b/src/core/runner.h index 0b6ad050..9ddb57f4 100644 --- a/src/core/runner.h +++ b/src/core/runner.h @@ -42,6 +42,4 @@ struct criterion_test_set *criterion_init(void); Suite < (struct criterion_suite**) GET_SECTION_END(cr_sts); \ ++Suite) -extern s_pipe_handle *g_worker_pipe; - #endif /* !CRITERION_RUNNER_H_ */ diff --git a/src/core/worker.c b/src/core/worker.c index 85a945a5..1dd6861e 100644 --- a/src/core/worker.c +++ b/src/core/worker.c @@ -32,11 +32,6 @@ #include "compat/posix.h" #include "worker.h" -struct process { - s_proc_handle *proc; - FILE *in; -}; - static s_proc_handle *g_current_proc; void set_runner_process(void) { @@ -57,8 +52,23 @@ static void close_process(void *ptr, UNUSED void *meta) { sfree(proc->proc); } -struct event *worker_read_event(struct process *proc) { - return read_event(proc->in); +struct event *worker_read_event(struct worker_set *workers, FILE *pipe) { + struct event *ev = read_event(pipe); + if (ev) { + ev->worker_index = -1; + for (size_t i = 0; i < workers->max_workers; ++i) { + if (!workers->workers[i]) + continue; + + if (get_process_id_of(workers->workers[i]->proc) == ev->pid) { + ev->worker = workers->workers[i]; + ev->worker_index = i; + return ev; + } + } + abort(); + } + return NULL; } void run_worker(struct worker_context *ctx) { @@ -74,17 +84,15 @@ void run_worker(struct worker_context *ctx) { _Exit(0); } -struct process *spawn_test_worker(struct criterion_test *test, - struct criterion_suite *suite, +struct process *spawn_test_worker(struct execution_context *ctx, f_worker_func func, - s_pipe_handle *pipe, - struct test_single_param *param) { + s_pipe_handle *pipe) { g_worker_context = (struct worker_context) { - .test = test, - .suite = suite, + .test = ctx->test, + .suite = ctx->suite, .func = func, .pipe = pipe, - .param = param, + .param = ctx->param, }; struct process *ptr = NULL; @@ -102,7 +110,11 @@ struct process *spawn_test_worker(struct criterion_test *test, .kind = UNIQUE, .dtor = close_process); - *ptr = (struct process) { .proc = proc, .in = pipe_in(pipe, PIPE_DUP) }; + *ptr = (struct process) { + .proc = proc, + .in = pipe_in(pipe, PIPE_DUP), + .ctx = *ctx, + }; return ptr; } diff --git a/src/core/worker.h b/src/core/worker.h index ab8bff91..e7b2c7a2 100644 --- a/src/core/worker.h +++ b/src/core/worker.h @@ -29,7 +29,29 @@ # include "compat/process.h" # include "compat/pipe.h" -struct process; +struct test_single_param { + size_t size; + void *ptr; +}; + +struct execution_context { + bool test_started; + bool normal_finish; + bool cleaned_up; + struct criterion_global_stats *stats; + struct criterion_test *test; + struct criterion_test_stats *test_stats; + struct criterion_suite *suite; + struct criterion_suite_stats *suite_stats; + struct test_single_param *param; +}; + +struct process { + int active; + s_proc_handle *proc; + FILE *in; + struct execution_context ctx; +}; enum status_kind { EXIT_STATUS, @@ -47,22 +69,22 @@ struct worker_status { struct process_status status; }; -struct test_single_param { - size_t size; - void *ptr; +struct worker_set { + struct process **workers; + size_t max_workers; }; +extern s_pipe_handle *g_worker_pipe; + void run_worker(struct worker_context *ctx); void set_runner_process(void); void unset_runner_process(void); bool is_runner(void); struct process_status wait_proc(struct process *proc); struct process_status get_status(int status); -struct process *spawn_test_worker(struct criterion_test *test, - struct criterion_suite *suite, +struct process *spawn_test_worker(struct execution_context *ctx, f_worker_func func, - s_pipe_handle *pipe, - struct test_single_param *param); -struct event *worker_read_event(struct process *proc); + s_pipe_handle *pipe); +struct event *worker_read_event(struct worker_set *workers, FILE *pipe); #endif /* !PROCESS_H_ */ diff --git a/src/io/event.c b/src/io/event.c index 1ba6a26f..4760020d 100644 --- a/src/io/event.c +++ b/src/io/event.c @@ -49,6 +49,10 @@ struct event *read_event(FILE *f) { if (fread(&kind, sizeof (unsigned), 1, f) == 0) return NULL; + unsigned long long pid; + if (fread(&pid, sizeof (unsigned long long), 1, f) == 0) + return NULL; + switch (kind) { case ASSERT: { const size_t assert_size = sizeof (struct criterion_assert_stats); @@ -73,7 +77,7 @@ struct event *read_event(FILE *f) { .size = sizeof (struct event), .dtor = destroy_assert_event ); - *ev = (struct event) { .kind = kind, .data = buf }; + *ev = (struct event) { .pid = pid, .kind = kind, .data = buf }; return ev; fail_assert: @@ -96,7 +100,7 @@ struct event *read_event(FILE *f) { .size = sizeof (struct event), .dtor = destroy_event ); - *ev = (struct event) { .kind = kind, .data = buf }; + *ev = (struct event) { .pid = pid, .kind = kind, .data = buf }; return ev; } case POST_TEST: { @@ -110,7 +114,7 @@ struct event *read_event(FILE *f) { .size = sizeof (struct event), .dtor = destroy_event ); - *ev = (struct event) { .kind = kind, .data = elapsed_time }; + *ev = (struct event) { .pid = pid, .kind = kind, .data = elapsed_time }; return ev; } case WORKER_TERMINATED: { @@ -124,22 +128,26 @@ struct event *read_event(FILE *f) { .size = sizeof (struct event), .dtor = destroy_event ); - *ev = (struct event) { .kind = kind, .data = status }; + *ev = (struct event) { .pid = pid, .kind = kind, .data = status }; return ev; } default: { struct event *ev = smalloc(sizeof (struct event)); - *ev = (struct event) { .kind = kind, .data = NULL }; + *ev = (struct event) { .pid = pid, .kind = kind, .data = NULL }; return ev; } } } void send_event(int kind, void *data, size_t size) { - unsigned char *buf = malloc(sizeof (int) + size); + unsigned long long pid = get_process_id(); + + unsigned char *buf = malloc(sizeof (int) + sizeof (pid) + size); memcpy(buf, &kind, sizeof (int)); - memcpy(buf + sizeof (int), data, size); - if (fwrite(buf, sizeof (int) + size, 1, g_event_pipe) == 0) + memcpy(buf + sizeof (int), &pid, sizeof (pid)); + memcpy(buf + sizeof (int) + sizeof (pid), data, size); + if (fwrite(buf, sizeof (int) + sizeof (pid) + size, 1, g_event_pipe) == 0) abort(); + free(buf); } diff --git a/src/io/event.h b/src/io/event.h index 64c30acd..faa54d38 100644 --- a/src/io/event.h +++ b/src/io/event.h @@ -25,13 +25,18 @@ # define EVENT_H_ # include "criterion/event.h" +# include "core/worker.h" # include extern FILE *g_event_pipe; struct event { + unsigned long long pid; int kind; void *data; + + struct process *worker; + size_t worker_index; }; enum other_event_kinds { From eac6ee518dd7b42b7d202ee2c7c37e953a44341a Mon Sep 17 00:00:00 2001 From: Snaipe Date: Tue, 22 Sep 2015 22:32:32 +0200 Subject: [PATCH 009/211] Fixed various memory and logic errors --- src/core/runner.c | 86 +++++++++++++++++++++++++++++++++-------------- src/core/stats.c | 1 + src/core/worker.c | 8 ++++- 3 files changed, 68 insertions(+), 27 deletions(-) diff --git a/src/core/runner.c b/src/core/runner.c index 67b5fad5..3817bc69 100644 --- a/src/core/runner.c +++ b/src/core/runner.c @@ -296,26 +296,15 @@ static void handle_event(struct event *ev) { static struct process *run_test(struct criterion_global_stats *stats, struct criterion_suite_stats *suite_stats, - struct criterion_test *test, - struct criterion_suite *suite, + struct criterion_test_stats *test_stats, struct test_single_param *param) { - struct criterion_test_stats *test_stats = test_stats_init(test); - - if (is_disabled(test, suite)) { - stat_push_event(stats, - suite_stats, - test_stats, - &(struct event) { .kind = PRE_INIT }); - return NULL; - } - struct execution_context ctx = { - .stats = stats, - .test = test, - .test_stats = test_stats, - .suite = suite, - .suite_stats = suite_stats, + .stats = sref(stats), + .test = test_stats->test, + .test_stats = sref(test_stats), + .suite = suite_stats->suite, + .suite_stats = sref(suite_stats), .param = param, }; return spawn_test_worker(&ctx, run_test_child, g_worker_pipe); @@ -362,6 +351,7 @@ static struct process *run_next_test(struct criterion_test_set *p_set, struct criterion_suite_set *suite_set; struct criterion_test *test; struct criterion_suite_stats *suite_stats; + struct criterion_test_stats *test_stats; struct criterion_test_set *set; struct criterion_global_stats *stats; struct criterion_test_params params; @@ -397,8 +387,20 @@ static struct process *run_next_test(struct criterion_test_set *p_set, if (ctx->test->data->kind_ == CR_TEST_PARAMETERIZED && ctx->test->data->param_) { + if (is_disabled(ctx->test, ctx->suite_stats->suite)) { + ctx->test_stats = test_stats_init(ctx->test); + stat_push_event(ctx->stats, + ctx->suite_stats, + ctx->test_stats, + &(struct event) { .kind = PRE_INIT }); + sfree(ctx->test_stats); + continue; + } + ctx->params = ctx->test->data->param_(); for (ctx->i = 0; ctx->i < ctx->params.length; ++ctx->i) { + ctx->test_stats = test_stats_init(ctx->test); + struct test_single_param param = { ctx->params.size, (char *) ctx->params.params + ctx->i * ctx->params.size @@ -406,12 +408,12 @@ static struct process *run_next_test(struct criterion_test_set *p_set, struct process *worker = run_test(ctx->stats, ctx->suite_stats, - ctx->test, - &ctx->suite_set->suite, + ctx->test_stats, ¶m); if (!is_runner()) { sfree(ctx->suite_stats); + sfree(ctx->test_stats); ccrReturn(NULL); } @@ -421,12 +423,24 @@ static struct process *run_next_test(struct criterion_test_set *p_set, if (ctx->params.cleanup) ctx->params.cleanup(&ctx->params); } else { + ctx->test_stats = test_stats_init(ctx->test); + + if (is_disabled(ctx->test, ctx->suite_stats->suite)) { + stat_push_event(ctx->stats, + ctx->suite_stats, + ctx->test_stats, + &(struct event) { .kind = PRE_INIT }); + sfree(ctx->test_stats); + continue; + } + struct process *worker = run_test(ctx->stats, ctx->suite_stats, - ctx->test, - &ctx->suite_set->suite, + ctx->test_stats, NULL); + sfree(ctx->test_stats); + if (!is_runner()) { sfree(ctx->suite_stats); ccrReturn(NULL); @@ -453,34 +467,54 @@ static void run_tests_async(struct criterion_test_set *set, size_t nb_workers = 1; struct worker_set workers = { .max_workers = nb_workers, - .workers = malloc(sizeof (struct process*) * nb_workers), + .workers = calloc(nb_workers, sizeof (struct process*)), }; size_t active_workers = 0; + FILE *event_pipe = pipe_in(g_worker_pipe, PIPE_DUP); + struct event *ev = NULL; + // initialization of coroutine run_next_test(set, stats, &ctx); for (size_t i = 0; i < nb_workers; ++i) { workers.workers[i] = run_next_test(NULL, NULL, &ctx); + if (!is_runner()) + goto cleanup; + + if (!ctx) + break; ++active_workers; } - FILE *event_pipe = pipe_in(g_worker_pipe, PIPE_DUP); + if (!active_workers) + goto cleanup; - struct event *ev; while ((ev = worker_read_event(&workers, event_pipe)) != NULL) { handle_event(ev); + size_t wi = ev->worker_index; if (ev->kind == WORKER_TERMINATED) { - workers.workers[ev->worker_index] = run_next_test(NULL, NULL, &ctx); - if (workers.workers[ev->worker_index] == NULL) + sfree(workers.workers[wi]); + workers.workers[wi] = ctx ? run_next_test(NULL, NULL, &ctx) : NULL; + + if (!is_runner()) + goto cleanup; + + if (workers.workers[wi] == NULL) --active_workers; } sfree(ev); if (!active_workers) break; } + ev = NULL; +cleanup: + fclose(event_pipe); + sfree(ev); + free(workers.workers); + ccrAbort(ctx); } static int criterion_run_all_tests_impl(struct criterion_test_set *set) { diff --git a/src/core/stats.c b/src/core/stats.c index a9dbe95c..488aa5c4 100644 --- a/src/core/stats.c +++ b/src/core/stats.c @@ -72,6 +72,7 @@ static void destroy_stats(void *ptr, UNUSED void *meta) { s_glob_stats *stats_init(void) { s_glob_stats *stats = smalloc( .size = sizeof (s_glob_stats), + .kind = SHARED, .dtor = destroy_stats ); *stats = (s_glob_stats) { .suites = NULL }; diff --git a/src/core/worker.c b/src/core/worker.c index 1dd6861e..e956176c 100644 --- a/src/core/worker.c +++ b/src/core/worker.c @@ -49,6 +49,9 @@ bool is_runner(void) { static void close_process(void *ptr, UNUSED void *meta) { struct process *proc = ptr; fclose(proc->in); + sfree(proc->ctx.suite_stats); + sfree(proc->ctx.test_stats); + sfree(proc->ctx.stats); sfree(proc->proc); } @@ -102,12 +105,15 @@ struct process *spawn_test_worker(struct execution_context *ctx, abort(); } else if (proc == NULL) { run_worker(&g_worker_context); + sfree(ctx->test_stats); + sfree(ctx->suite_stats); + sfree(ctx->stats); return NULL; } ptr = smalloc( .size = sizeof (struct process), - .kind = UNIQUE, + .kind = SHARED, .dtor = close_process); *ptr = (struct process) { From 40dbcc34087d11e6840d00b85295c961a62518a4 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Tue, 22 Sep 2015 23:21:51 +0200 Subject: [PATCH 010/211] Added --jobs CLI switch and CRITERION_JOBS environment variable --- CMakeLists.txt | 2 ++ include/criterion/options.h | 1 + samples/CMakeLists.txt | 2 ++ src/compat/internal.h | 5 ++++ src/compat/posix.h | 1 - src/compat/processor.c | 54 +++++++++++++++++++++++++++++++++++++ src/compat/processor.h | 31 +++++++++++++++++++++ src/core/runner.c | 3 ++- src/entry/main.c | 14 +++++++--- 9 files changed, 108 insertions(+), 5 deletions(-) create mode 100644 src/compat/processor.c create mode 100644 src/compat/processor.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 14068747..4a51244a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -104,6 +104,8 @@ set(SOURCE_FILES src/compat/posix.h src/compat/alloc.c src/compat/alloc.h + src/compat/processor.c + src/compat/processor.h src/io/redirect.c src/io/event.c src/io/event.h diff --git a/include/criterion/options.h b/include/criterion/options.h index 0bdcdeef..49c05486 100644 --- a/include/criterion/options.h +++ b/include/criterion/options.h @@ -36,6 +36,7 @@ struct criterion_options { bool fail_fast; const char *pattern; bool short_filename; + size_t jobs; }; CR_BEGIN_C_API diff --git a/samples/CMakeLists.txt b/samples/CMakeLists.txt index a80f1afb..dfba5a01 100644 --- a/samples/CMakeLists.txt +++ b/samples/CMakeLists.txt @@ -65,6 +65,7 @@ macro(add_samples DIR_ SAMPLES_) ENVIRONMENT "CRITERION_ALWAYS_SUCCEED=1" ENVIRONMENT "CRITERION_SHORT_FILENAME=1" ENVIRONMENT "CRITERION_NO_EARLY_EXIT=1" # for coverage + ENVIRONMENT "CRITERION_JOBS=1" # for output ordering ) endif () endforeach() @@ -87,6 +88,7 @@ foreach(script ${SCRIPTS}) ENVIRONMENT "CRITERION_ALWAYS_SUCCEED=1" ENVIRONMENT "CRITERION_SHORT_FILENAME=1" ENVIRONMENT "CRITERION_NO_EARLY_EXIT=1" # for coverage + ENVIRONMENT "CRITERION_JOBS=1" # for output ordering ) endforeach() diff --git a/src/compat/internal.h b/src/compat/internal.h index 29b73ab7..fd5e8af7 100644 --- a/src/compat/internal.h +++ b/src/compat/internal.h @@ -40,6 +40,11 @@ # include # include # include +# include +# ifdef BSD +# include +# include +# endif # endif # include "posix.h" diff --git a/src/compat/posix.h b/src/compat/posix.h index 930225a6..043562db 100644 --- a/src/compat/posix.h +++ b/src/compat/posix.h @@ -55,7 +55,6 @@ # define SIGPROF 27 # define CR_EXCEPTION_TIMEOUT 0xC0001042 # else -# include # include # endif diff --git a/src/compat/processor.c b/src/compat/processor.c new file mode 100644 index 00000000..b0f5244c --- /dev/null +++ b/src/compat/processor.c @@ -0,0 +1,54 @@ +/* + * The MIT License (MIT) + * + * Copyright © 2015 Franklin "Snaipe" Mathieu + * + * 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. + */ + +#include "internal.h" + +size_t get_processor_count(void) { +#ifdef _WIN32 + SYSTEM_INFO sysinfo; + GetSystemInfo(&sysinfo); + + return (size_t) sysinfo.dwNumberOfProcessors; +#elif defined(BSD) + int mib[2] = { CTL_HW, HW_AVAILCPU }; + long long count; + size_t len = sizeof (count); + + /* get the number of CPUs from the system */ + sysctl(mib, 2, &count, &len, NULL, 0); + + if (count < 1) { + mib[1] = HW_NCPU; + sysctl(mib, 2, &count, &len, NULL, 0); + + if (count < 1) + count = 1; + } + return (size_t) count; +#elif defined(__linux__) + return sysconf(_SC_NPROCESSORS_ONLN); +#else +# error System not supported +#endif +} diff --git a/src/compat/processor.h b/src/compat/processor.h new file mode 100644 index 00000000..5e6e35ba --- /dev/null +++ b/src/compat/processor.h @@ -0,0 +1,31 @@ +/* + * The MIT License (MIT) + * + * Copyright © 2015 Franklin "Snaipe" Mathieu + * + * 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 COMPAT_PROCESSOR_H_ +# define COMPAT_PROCESSOR_H_ + +# include + +size_t get_processor_count(void); + +#endif /* !COMPAT_PROCESSOR_H_ */ diff --git a/src/core/runner.c b/src/core/runner.c index 3817bc69..2a29c485 100644 --- a/src/core/runner.c +++ b/src/core/runner.c @@ -30,6 +30,7 @@ #include "criterion/logging.h" #include "compat/time.h" #include "compat/posix.h" +#include "compat/processor.h" #include "string/i18n.h" #include "io/event.h" #include "stats.h" @@ -464,7 +465,7 @@ static void run_tests_async(struct criterion_test_set *set, ccrContext ctx = 0; - size_t nb_workers = 1; + size_t nb_workers = DEF(criterion_options.jobs, get_processor_count()); struct worker_set workers = { .max_workers = nb_workers, .workers = calloc(nb_workers, sizeof (struct process*)), diff --git a/src/entry/main.c b/src/entry/main.c index 5551886b..6fb07879 100644 --- a/src/entry/main.c +++ b/src/entry/main.c @@ -120,6 +120,11 @@ int list_tests(bool unicode) { return 0; } +int atou(const char *str) { + int res = atoi(str); + return res < 0 ? 0 : res; +} + int criterion_handle_args(int argc, char *argv[], bool handle_unknown_arg) { static struct option opts[] = { {"verbose", optional_argument, 0, 'b'}, @@ -128,6 +133,7 @@ int criterion_handle_args(int argc, char *argv[], bool handle_unknown_arg) { {"help", no_argument, 0, 'h'}, {"list", no_argument, 0, 'l'}, {"ascii", no_argument, 0, 'k'}, + {"jobs", required_argument, 0, 'j'}, {"fail-fast", no_argument, 0, 'f'}, {"short-filename", no_argument, 0, 'S'}, #ifdef HAVE_PCRE @@ -151,7 +157,8 @@ int criterion_handle_args(int argc, char *argv[], bool handle_unknown_arg) { opt->no_early_exit = !strcmp("1", DEF(getenv("CRITERION_NO_EARLY_EXIT") , "0")); opt->fail_fast = !strcmp("1", DEF(getenv("CRITERION_FAIL_FAST") , "0")); opt->use_ascii = use_ascii; - opt->logging_threshold = atoi(DEF(getenv("CRITERION_VERBOSITY_LEVEL"), "2")); + opt->jobs = atou(DEF(getenv("CRITERION_JOBS"), "0")); + opt->logging_threshold = atou(DEF(getenv("CRITERION_VERBOSITY_LEVEL"), "2")); opt->short_filename = !strcmp("1", DEF(getenv("CRITERION_SHORT_FILENAME"), "0")); #ifdef HAVE_PCRE opt->pattern = getenv("CRITERION_TEST_PATTERN"); @@ -162,12 +169,13 @@ int criterion_handle_args(int argc, char *argv[], bool handle_unknown_arg) { bool do_list_tests = false; bool do_print_version = false; bool do_print_usage = false; - for (int c; (c = getopt_long(argc, argv, "hvlfS", opts, NULL)) != -1;) { + for (int c; (c = getopt_long(argc, argv, "hvlfj:S", opts, NULL)) != -1;) { switch (c) { - case 'b': criterion_options.logging_threshold = atoi(DEF(optarg, "1")); break; + case 'b': criterion_options.logging_threshold = atou(DEF(optarg, "1")); break; case 'y': criterion_options.always_succeed = true; break; case 'z': criterion_options.no_early_exit = true; break; case 'k': criterion_options.use_ascii = true; break; + case 'j': criterion_options.jobs = atou(optarg); break; case 'f': criterion_options.fail_fast = true; break; case 'S': criterion_options.short_filename = true; break; #ifdef HAVE_PCRE From 2c76e45479aa4f0084200de9104726429006dd39 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Tue, 22 Sep 2015 23:30:53 +0200 Subject: [PATCH 011/211] Fixed missing typedefs on BSD --- src/compat/internal.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/compat/internal.h b/src/compat/internal.h index fd5e8af7..43ff62d8 100644 --- a/src/compat/internal.h +++ b/src/compat/internal.h @@ -43,6 +43,10 @@ # include # ifdef BSD # include +typedef unsigned long u_long; +typedef unsigned int u_int; +typedef unsigned short u_short; +typedef unsigned char u_char; # include # endif # endif From 080c10ebad8c9bee711cdd47112a5028a6ba6d75 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Wed, 23 Sep 2015 00:34:30 +0200 Subject: [PATCH 012/211] Fixed clang warnings over partial initialization in coroutine --- src/core/runner.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/core/runner.c b/src/core/runner.c index 2a29c485..2fef2f76 100644 --- a/src/core/runner.c +++ b/src/core/runner.c @@ -416,9 +416,9 @@ static struct process *run_next_test(struct criterion_test_set *p_set, sfree(ctx->suite_stats); sfree(ctx->test_stats); ccrReturn(NULL); + } else { + ccrReturn(worker); } - - ccrReturn(worker); } if (ctx->params.cleanup) @@ -445,9 +445,9 @@ static struct process *run_next_test(struct criterion_test_set *p_set, if (!is_runner()) { sfree(ctx->suite_stats); ccrReturn(NULL); + } else { + ccrReturn(worker); } - - ccrReturn(worker); } } From ace14dc3bc8c89e16e92c1b7cc750bf242e11dd4 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Wed, 23 Sep 2015 00:42:30 +0200 Subject: [PATCH 013/211] Fixed sysctl errors being ignored when getting the number of processors on BSD --- src/compat/processor.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/compat/processor.c b/src/compat/processor.c index b0f5244c..ba7ab9fb 100644 --- a/src/compat/processor.c +++ b/src/compat/processor.c @@ -32,17 +32,17 @@ size_t get_processor_count(void) { return (size_t) sysinfo.dwNumberOfProcessors; #elif defined(BSD) int mib[2] = { CTL_HW, HW_AVAILCPU }; - long long count; + long long count = 0; size_t len = sizeof (count); /* get the number of CPUs from the system */ - sysctl(mib, 2, &count, &len, NULL, 0); + int res = sysctl(mib, 2, &count, &len, NULL, 0); - if (count < 1) { + if (count < 1 || res == -1) { mib[1] = HW_NCPU; - sysctl(mib, 2, &count, &len, NULL, 0); + res = sysctl(mib, 2, &count, &len, NULL, 0); - if (count < 1) + if (count < 1 || res == -1) count = 1; } return (size_t) count; From f90131d6beef367c1746e45bffb9868dd00c5978 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Wed, 23 Sep 2015 00:59:12 +0200 Subject: [PATCH 014/211] Fixed invalid platform name for x64 in appveyor config --- README.md | 2 ++ appveyor.yml | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 3833265e..85be12f6 100644 --- a/README.md +++ b/README.md @@ -51,6 +51,8 @@ the user would have with other frameworks: * [Windows (MSVC - x86_64)](https://github.com/Snaipe/Criterion/releases/download/v2.1.0/criterion-v2.1.0-windows-msvc-x86_64.tar.bz2) * [Windows (MinGW - x86_64)](https://github.com/Snaipe/Criterion/releases/download/v2.1.0/criterion-v2.1.0-windows-mingw-x86_64.tar.bz2) +[comment]: # (Don't forget to change x86_64 to x64 on windows links on the next release) + If you have a different platform, you can still [build the library from source](http://criterion.readthedocs.org/en/latest/setup.html#installation) ## Developer Resources diff --git a/appveyor.yml b/appveyor.yml index 29952bb7..1f71d410 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -22,7 +22,7 @@ clone_depth: 5 platform: - x86 - - x86_64 + - x64 configuration: - Debug From a6f2bbb4c27cac8a2a6f9c052d8dd118bcd86580 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Wed, 23 Sep 2015 01:48:39 +0200 Subject: [PATCH 015/211] Boyscouting. --- src/compat/pipe.h | 5 +++-- src/compat/process.c | 10 ---------- src/core/runner.c | 10 +++++----- src/core/worker.c | 17 +++++------------ src/core/worker.h | 8 ++++---- src/io/event.h | 2 +- 6 files changed, 18 insertions(+), 34 deletions(-) diff --git a/src/compat/pipe.h b/src/compat/pipe.h index 83aa63db..c2f7d13a 100644 --- a/src/compat/pipe.h +++ b/src/compat/pipe.h @@ -25,6 +25,7 @@ # define PIPE_H_ # include +# include # include "common.h" struct pipe_handle; @@ -53,13 +54,13 @@ FILE *pipe_out(s_pipe_handle *p, enum pipe_opt opts); int stdpipe_options(s_pipe_handle *pipe, int id, int noblock); void pipe_std_redirect(s_pipe_handle *pipe, enum criterion_std_fd fd); -INLINE FILE* get_std_file(int fd_kind) { +INLINE FILE* get_std_file(enum criterion_std_fd fd_kind) { switch (fd_kind) { case CR_STDIN: return stdin; case CR_STDOUT: return stdout; case CR_STDERR: return stderr; } - return NULL; + abort(); } extern s_pipe_handle *stdout_redir; diff --git a/src/compat/process.c b/src/compat/process.c index b107686b..08b66255 100644 --- a/src/compat/process.c +++ b/src/compat/process.c @@ -385,16 +385,6 @@ s_proc_handle *fork_process() { #endif } -void wait_process(s_proc_handle *handle, int *status) { -#ifdef VANILLA_WIN32 - WaitForSingleObject(handle->handle, INFINITE); - *status = get_win_status(handle->handle); - CloseHandle(handle->handle); -#else - waitpid(handle->pid, status, 0); -#endif -} - s_proc_handle *get_current_process() { s_proc_handle *handle = smalloc(sizeof (s_proc_handle)); #ifdef VANILLA_WIN32 diff --git a/src/core/runner.c b/src/core/runner.c index 2fef2f76..abb25c96 100644 --- a/src/core/runner.c +++ b/src/core/runner.c @@ -295,7 +295,7 @@ static void handle_event(struct event *ev) { } } -static struct process *run_test(struct criterion_global_stats *stats, +static struct worker *run_test(struct criterion_global_stats *stats, struct criterion_suite_stats *suite_stats, struct criterion_test_stats *test_stats, struct test_single_param *param) { @@ -345,7 +345,7 @@ void criterion_finalize(struct criterion_test_set *set) { sfree(set); } -static struct process *run_next_test(struct criterion_test_set *p_set, +static struct worker *run_next_test(struct criterion_test_set *p_set, struct criterion_global_stats *p_stats, ccrContParam) { ccrBeginContext; @@ -407,7 +407,7 @@ static struct process *run_next_test(struct criterion_test_set *p_set, (char *) ctx->params.params + ctx->i * ctx->params.size }; - struct process *worker = run_test(ctx->stats, + struct worker *worker = run_test(ctx->stats, ctx->suite_stats, ctx->test_stats, ¶m); @@ -435,7 +435,7 @@ static struct process *run_next_test(struct criterion_test_set *p_set, continue; } - struct process *worker = run_test(ctx->stats, + struct worker *worker = run_test(ctx->stats, ctx->suite_stats, ctx->test_stats, NULL); @@ -468,7 +468,7 @@ static void run_tests_async(struct criterion_test_set *set, size_t nb_workers = DEF(criterion_options.jobs, get_processor_count()); struct worker_set workers = { .max_workers = nb_workers, - .workers = calloc(nb_workers, sizeof (struct process*)), + .workers = calloc(nb_workers, sizeof (struct worker*)), }; size_t active_workers = 0; diff --git a/src/core/worker.c b/src/core/worker.c index e956176c..8912b193 100644 --- a/src/core/worker.c +++ b/src/core/worker.c @@ -47,7 +47,7 @@ bool is_runner(void) { } static void close_process(void *ptr, UNUSED void *meta) { - struct process *proc = ptr; + struct worker *proc = ptr; fclose(proc->in); sfree(proc->ctx.suite_stats); sfree(proc->ctx.test_stats); @@ -87,7 +87,7 @@ void run_worker(struct worker_context *ctx) { _Exit(0); } -struct process *spawn_test_worker(struct execution_context *ctx, +struct worker *spawn_test_worker(struct execution_context *ctx, f_worker_func func, s_pipe_handle *pipe) { g_worker_context = (struct worker_context) { @@ -98,7 +98,7 @@ struct process *spawn_test_worker(struct execution_context *ctx, .param = ctx->param, }; - struct process *ptr = NULL; + struct worker *ptr = NULL; s_proc_handle *proc = fork_process(); if (proc == (void *) -1) { @@ -112,11 +112,11 @@ struct process *spawn_test_worker(struct execution_context *ctx, } ptr = smalloc( - .size = sizeof (struct process), + .size = sizeof (struct worker), .kind = SHARED, .dtor = close_process); - *ptr = (struct process) { + *ptr = (struct worker) { .proc = proc, .in = pipe_in(pipe, PIPE_DUP), .ctx = *ctx, @@ -139,10 +139,3 @@ struct process_status get_status(int status) { return (struct process_status) { .kind = STOPPED }; } - -struct process_status wait_proc(struct process *proc) { - int status; - wait_process(proc->proc, &status); - - return get_status(status); -} diff --git a/src/core/worker.h b/src/core/worker.h index e7b2c7a2..865ab966 100644 --- a/src/core/worker.h +++ b/src/core/worker.h @@ -46,7 +46,7 @@ struct execution_context { struct test_single_param *param; }; -struct process { +struct worker { int active; s_proc_handle *proc; FILE *in; @@ -70,7 +70,7 @@ struct worker_status { }; struct worker_set { - struct process **workers; + struct worker **workers; size_t max_workers; }; @@ -80,9 +80,9 @@ void run_worker(struct worker_context *ctx); void set_runner_process(void); void unset_runner_process(void); bool is_runner(void); -struct process_status wait_proc(struct process *proc); +struct process_status wait_proc(struct worker *proc); struct process_status get_status(int status); -struct process *spawn_test_worker(struct execution_context *ctx, +struct worker *spawn_test_worker(struct execution_context *ctx, f_worker_func func, s_pipe_handle *pipe); struct event *worker_read_event(struct worker_set *workers, FILE *pipe); diff --git a/src/io/event.h b/src/io/event.h index faa54d38..641c9660 100644 --- a/src/io/event.h +++ b/src/io/event.h @@ -35,7 +35,7 @@ struct event { int kind; void *data; - struct process *worker; + struct worker *worker; size_t worker_index; }; From fbd6d3dba053fa69ee04f4b83d586e2f01c1d28e Mon Sep 17 00:00:00 2001 From: Snaipe Date: Wed, 23 Sep 2015 02:11:06 +0200 Subject: [PATCH 016/211] Added documentation for --jobs and CRITERION_JOBS --- doc/env.rst | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/doc/env.rst b/doc/env.rst index 745ff9ba..80a36057 100644 --- a/doc/env.rst +++ b/doc/env.rst @@ -13,6 +13,8 @@ Command line arguments * ``-l or --list``: Print all the tests in a list. * ``-f or --fail-fast``: Exit after the first test failure. * ``--ascii``: Don't use fancy unicode symbols or colors in the output. +* ``-jN or --jobs N``: Use ``N`` parallel jobs to run the tests. ``0`` picks + a number of jobs ideal for your hardware configuration. * ``--pattern [PATTERN]``: Run tests whose string identifier matches the given shell wildcard pattern (see dedicated section below). (\*nix only) * ``--no-early-exit``: The test workers shall not prematurely exit when done and @@ -60,6 +62,8 @@ Environment variables are alternatives to command line switches when set to 1. * ``CRITERION_ENABLE_TAP``: Same as ``--tap``. * ``CRITERION_FAIL_FAST``: Same as ``--fail-fast``. * ``CRITERION_USE_ASCII``: Same as ``--ascii``. +* ``CRITERION_JOBS``: Same as ``jobs``. Sets the number of jobs to + its value. * ``CRITERION_SHORT_FILENAME``: Same as ``--short-filename``. * ``CRITERION_VERBOSITY_LEVEL``: Same as ``--verbose``. Sets the verbosity level to its value. From 7d4896da07bb5fe7c57fc0fd65bb7d8a11eedc19 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Wed, 23 Sep 2015 02:19:11 +0200 Subject: [PATCH 017/211] Updated documentation to mention extglob patterns --- doc/env.rst | 41 ++++++++++++++++++++++++++--------------- 1 file changed, 26 insertions(+), 15 deletions(-) diff --git a/doc/env.rst b/doc/env.rst index 80a36057..97ab252c 100644 --- a/doc/env.rst +++ b/doc/env.rst @@ -29,23 +29,34 @@ Command line arguments Shell Wildcard Pattern ---------------------- -Patterns in criterion are matched against a test's string identifier with -``fnmatch``. This feature is only available on \*nix systems where ``fnmatch`` -is provided. +Extglob patterns in criterion are matched against a test's string identifier. +This feature is only available on \*nix systems where ``PCRE`` is provided. -Special characters used in shell-style wildcard patterns are: +In the table below, a ``pattern-list`` is a list of patterns separated by ``|``. +Any extglob pattern can be constructed by combining any of the following +sub-patterns: -=========== =================================== -Pattern Meaning -=========== =================================== -``*`` matches everything ------------ ----------------------------------- -``?`` matches any character ------------ ----------------------------------- -``[seq]`` matches any character in *seq* ------------ ----------------------------------- -``[!seq]`` matches any character not in *seq* -=========== =================================== +==================== ====================================================== +Pattern Meaning +==================== ====================================================== +``*`` matches everything +-------------------- ------------------------------------------------------ +``?`` matches any character +-------------------- ------------------------------------------------------ +``[seq]`` matches any character in *seq* +-------------------- ------------------------------------------------------ +``[!seq]`` matches any character not in *seq* +-------------------- ------------------------------------------------------ +``?(pattern-list)`` Matches zero or one occurrence of the given patterns +-------------------- ------------------------------------------------------ +``*(pattern-list)`` Matches zero or more occurrences of the given patterns +-------------------- ------------------------------------------------------ +``+(pattern-list)`` Matches one or more occurrences of the given patterns +-------------------- ------------------------------------------------------ +``@(pattern-list)`` Matches one of the given patterns +-------------------- ------------------------------------------------------ +``!(pattern-list)`` Matches anything except one of the given patterns +==================== ====================================================== A test string identifier is of the form ``suite-name/test-name``, so a pattern of ``simple/*`` matches every tests in the ``simple`` suite, ``*/passing`` From 7263020d74bd006e1e066b317fad733d4e4af19c Mon Sep 17 00:00:00 2001 From: Snaipe Date: Wed, 23 Sep 2015 14:09:49 +0200 Subject: [PATCH 018/211] Updated documentation intro [ci skip] --- doc/intro.rst | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/doc/intro.rst b/doc/intro.rst index e2a11250..5d2792e9 100644 --- a/doc/intro.rst +++ b/doc/intro.rst @@ -1,8 +1,7 @@ Introduction ============ -Criterion is a dead-simple, non-intrusive testing framework for the C -programming language. +Criterion is a dead-simple, non-intrusive unit testing framework for C and C++. Philosophy ---------- @@ -20,12 +19,15 @@ the user would have with other frameworks. Features -------- +* C99 and C++11 compatible. * Tests are automatically registered when declared. +* Implements a xUnit framework structure. * A default entry point is provided, no need to declare a main unless you want to do special handling. * Test are isolated in their own process, crashes and signals can be reported and tested. +* Unified interface between C and C++: include the criterion header and it *just* works. +* Supports parameterized tests and theories. * Progress and statistics can be followed in real time with report hooks. * TAP output format can be enabled with an option. -* Runs on Linux, FreeBSD, Mac OS X, and Windows (Compiling with MinGW GCC). -* xUnit framework structure +* Runs on Linux, FreeBSD, Mac OS X, and Windows (Compiling with MinGW GCC and Visual Studio 2015+). From 473d91ea18f0124298cbc517a26a15603a5d41b2 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Wed, 23 Sep 2015 14:10:30 +0200 Subject: [PATCH 019/211] Removed readme FAQ [ci skip] --- README.md | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/README.md b/README.md index 85be12f6..54ebc939 100644 --- a/README.md +++ b/README.md @@ -81,21 +81,6 @@ Gitter.im chat room: [![Join the chat at https://gitter.im/Snaipe/Criterion](htt * [CMake find module for Criterion][find-module] -## F.A.Q. - -**Q. What's wrong with other C test frameworks?** -A. I worked with CUnit and Check, and I must say that they do their job - very well -- the only thing that bugs me is that setting up a test - suite from scratch is a pain, it should really be simpler. Most - (if not all) high-level languages have test frameworks with automatic - test registration, but all the ones for C require you to set up a - main, manually register suites, then tests. Criterion tries to - fix these shortcomings. - -**Q. Where has this been tested?** -A. Currently, on Linux 2.6.32 and Linux 3.15.7, although it should work on - most \*nix systems; Mac OS X Yosemite 10.10, FreeBSD 10.0, Windows 7 and 2K. - ## Credits Logo done by [Greehm](http://www.cargocollective.com/pbouigue) From 350eb235b1ebb6f85d03e86345f1f227354b097e Mon Sep 17 00:00:00 2001 From: Snaipe Date: Wed, 23 Sep 2015 14:11:33 +0200 Subject: [PATCH 020/211] [Issue #53] Removed ext/stdio_sync_filebuf.h --- include/criterion/redirect.h | 156 +++++++++++++++++++++++++++++------ 1 file changed, 130 insertions(+), 26 deletions(-) diff --git a/include/criterion/redirect.h b/include/criterion/redirect.h index 4851b3dc..effb9094 100644 --- a/include/criterion/redirect.h +++ b/include/criterion/redirect.h @@ -31,18 +31,6 @@ # include # include # include - -# ifdef __GNUC__ -# if defined(__MINGW32__) || defined(__MINGW64__) -# define off_t _off_t -# define off64_t _off64_t -# endif -# include -# if defined(__MINGW32__) || defined(__MINGW64__) -# undef off_t -# undef off64_t -# endif -# endif # else # include # endif @@ -143,37 +131,155 @@ CR_END_C_API # ifdef __cplusplus namespace criterion { + template > + class stdio_sync_filebuf : public std::basic_streambuf { + public: + typedef Traits traits; + typedef std::basic_filebuf super; + typedef typename Traits::int_type int_type; + typedef typename Traits::pos_type pos_type; + typedef typename Traits::off_type off_type; + + stdio_sync_filebuf(std::FILE *file) + : file(file) + , lastchar(Traits::eof()) + {} + + stdio_sync_filebuf(stdio_sync_filebuf&& other) = default; + stdio_sync_filebuf& operator=(stdio_sync_filebuf&& other) = default; + + void swap(stdio_sync_filebuf& other) { + super::swap(other); + std::swap(file, other.file); + std::swap(lastchar, other.lastchar); + } + + protected: + int_type syncgetc(); + int_type syncungetc(int_type); + int_type syncputc(int_type); + + virtual std::streampos seekoff(std::streamoff off, + std::ios_base::seekdir dir, + std::ios_base::openmode = std::ios_base::in | std::ios_base::out) { + + int whence; + if (dir == std::ios_base::beg) + whence = SEEK_SET; + else if (dir == std::ios_base::cur) + whence = SEEK_CUR; + else + whence = SEEK_END; + + if (!fseek(file, off, whence)) + return std::streampos(std::ftell(file)); + return std::streamoff(-1); + } + + virtual std::streampos seekpos(std::streampos pos, + std::ios_base::openmode mode = std::ios_base::in | std::ios_base::out) { + return seekoff(std::streamoff(pos), std::ios_base::beg, mode); + } + + virtual std::streamsize xsgetn(CharT* s, std::streamsize n); + virtual std::streamsize xsputn(const CharT* s, std::streamsize n); + + virtual int sync() { + return std::fflush(file); + } + + virtual int_type underflow() { + int_type c = syncgetc(); + return syncungetc(c); + } + + virtual int_type uflow() { + return lastchar = syncgetc(); + } + + static inline bool is_eof(int_type c) { + static const int_type eof = Traits::eof(); + return Traits::eq_int_type(c, eof); + } + + virtual int_type overflow(int_type c = Traits::eof()) { + int_type ret; + if (is_eof(c)) { + if (std::fflush(file)) + ret = Traits::eof(); + else + ret = Traits::not_eof(c); + } else { + ret = syncputc(c); + } + return ret; + } + + virtual int_type pbackfail(int_type c = Traits::eof()) { + int_type ret = syncungetc(is_eof(c) && !is_eof(lastchar) ? lastchar : c); + lastchar = Traits::eof(); + return ret; + } + + private: + std::FILE *file; + bool file_open; + int_type lastchar; + }; + + template <> + inline stdio_sync_filebuf::int_type + stdio_sync_filebuf::syncgetc() { + return std::getc(file); + } + + template <> + inline stdio_sync_filebuf::int_type + stdio_sync_filebuf::syncungetc(stdio_sync_filebuf::int_type c) { + return std::ungetc(c, file); + } + + template <> + inline stdio_sync_filebuf::int_type + stdio_sync_filebuf::syncputc(stdio_sync_filebuf::int_type c) { + return std::putc(c, file); + } + + template <> + inline std::streamsize + stdio_sync_filebuf::xsgetn(char *s, std::streamsize n) { + std::streamsize res = std::fread(s, 1, n, file); + lastchar = res > 0 ? traits::to_int_type(s[res - 1]) : traits::eof(); + return res; + } + + template <> + inline std::streamsize + stdio_sync_filebuf::xsputn(const char *s, std::streamsize n) { + return std::fwrite(s, 1, n, file); + } + template class stream_mixin : public Super { public: stream_mixin(FILE* f) -# ifdef __GNUC__ : Super() - , fbuf(new ::__gnu_cxx::stdio_sync_filebuf(f)) -# else - : Super(f) -# endif + , fbuf(new stdio_sync_filebuf(f)) , file(f) { -# ifdef __GNUC__ std::ios::rdbuf(&*fbuf); -# endif } stream_mixin(const stream_mixin& other) = delete; stream_mixin& operator=(const stream_mixin& other) = delete; stream_mixin(stream_mixin&& other) : -# ifdef __GNUC__ fbuf(std::move(other.fbuf)), -# endif file(std::move(other.file)) {} stream_mixin& operator=(stream_mixin&& other) { -# ifdef __GNUC__ fbuf = std::move(other.fbuf); -# endif file = std::move(other.file); } @@ -184,9 +290,7 @@ namespace criterion { } private: -# ifdef __GNUC__ - std::shared_ptr<::__gnu_cxx::stdio_sync_filebuf> fbuf; -# endif + std::shared_ptr> fbuf; std::FILE* file; }; From 05812ca34ec706f15f830efb208ab473908fbe58 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Wed, 23 Sep 2015 19:21:32 +0200 Subject: [PATCH 021/211] Fixed buggy delete_arr --- include/criterion/alloc.h | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/include/criterion/alloc.h b/include/criterion/alloc.h index 741b999d..4fd6ee02 100644 --- a/include/criterion/alloc.h +++ b/include/criterion/alloc.h @@ -86,11 +86,12 @@ namespace criterion { template void delete_arr(T* ptr) { - size_t len = *(reinterpret_cast(ptr)); - T* arr = reinterpret_cast(reinterpret_cast(ptr) + 1); + size_t *ptr_ = reinterpret_cast(ptr); + size_t len = *(ptr_ - 1); + T* arr = reinterpret_cast(ptr_); for (size_t i = 0; i < len; ++i) arr[i].~T(); - cr_free(ptr); + cr_free(ptr_ - 1); } } From 37a043147f16235ba5ed2dde6a0c3ad7d212caa9 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Wed, 23 Sep 2015 19:22:55 +0200 Subject: [PATCH 022/211] [Issue #54] Added custom allocator for cr_malloc/cr_free --- include/criterion/alloc.h | 50 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 49 insertions(+), 1 deletion(-) diff --git a/include/criterion/alloc.h b/include/criterion/alloc.h index 4fd6ee02..eb687946 100644 --- a/include/criterion/alloc.h +++ b/include/criterion/alloc.h @@ -24,7 +24,13 @@ #ifndef CRITERION_ALLOC_H_ # define CRITERION_ALLOC_H_ -# include +# ifdef __cplusplus +# include +# include +using std::size_t; +# else +# include +# endif # include "common.h" CR_BEGIN_C_API @@ -94,6 +100,48 @@ namespace criterion { cr_free(ptr_ - 1); } + template + struct allocator { + typedef T value_type; + typedef value_type* pointer; + typedef const value_type* const_pointer; + typedef value_type& reference; + typedef const value_type& const_reference; + typedef std::size_t size_type; + typedef std::ptrdiff_t difference_type; + + template + struct rebind { + typedef allocator other; + }; + + inline explicit allocator() {} + inline ~allocator() {} + inline explicit allocator(allocator const&) {} + template + inline explicit allocator(allocator const&) {} + + inline pointer address(reference r) { return &r; } + inline const_pointer address(const_reference r) { return &r; } + + inline pointer allocate(size_type cnt, typename std::allocator::const_pointer = 0) { + return reinterpret_cast(cr_malloc(cnt * sizeof (T))); + } + + inline void deallocate(pointer p, size_type) { cr_free(p); } + + inline size_type max_size() const { + return size_type(-1) / sizeof(T); + } + + inline void construct(pointer p, const T& t) { new(p) T(t); } + inline void construct(pointer p, T&& t) { new (p) T(std::move(t)); } + inline void destroy(pointer p) { p->~T(); } + + inline bool operator==(allocator const&) { return true; } + inline bool operator!=(allocator const& a) { return !operator==(a); } + }; + } # endif From 2b66cda5245d10effb3ddf1b3ed231347bbc966a Mon Sep 17 00:00:00 2001 From: Snaipe Date: Wed, 23 Sep 2015 20:10:00 +0200 Subject: [PATCH 023/211] Added criterion::parameters for simpler C++ parameter generation --- include/criterion/parameterized.h | 11 +++++++++++ include/criterion/types.h | 10 ++++++++++ 2 files changed, 21 insertions(+) diff --git a/include/criterion/parameterized.h b/include/criterion/parameterized.h index 6bfec4ef..d5cde423 100644 --- a/include/criterion/parameterized.h +++ b/include/criterion/parameterized.h @@ -2,6 +2,10 @@ # define CRITERION_PARAMETERIZED_H_ # include "criterion.h" +# include "alloc.h" +# ifdef __cplusplus +# include +# endif # ifdef __cplusplus # define CR_PARAM_TEST_PROTOTYPE_(Param, Category, Name) \ @@ -47,4 +51,11 @@ (struct criterion_test_params) { .size = sizeof (Type), (void*)(Array), __VA_ARGS__ } # endif +# ifdef __cplusplus +namespace criterion { + template + using parameters = std::vector>; +} +# endif + #endif /* !CRITERION_PARAMETERIZED_H_ */ diff --git a/include/criterion/types.h b/include/criterion/types.h index 7e98bc81..d3dada34 100644 --- a/include/criterion/types.h +++ b/include/criterion/types.h @@ -24,8 +24,10 @@ #ifndef CRITERION_TYPES_H_ # define CRITERION_TYPES_H_ +# include "alloc.h" # ifdef __cplusplus # include +# include using std::size_t; # else # include @@ -59,6 +61,14 @@ struct criterion_test_params { , length(length) , cleanup(cleanup) {} + + template + constexpr criterion_test_params(std::vector>& vec) + : size(sizeof (T)) + , params(&vec[0]) + , length(vec.size()) + , cleanup(nullptr) + {} # endif }; From b773bb61c33e14fd64ec640343499a4bea4347d2 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Wed, 23 Sep 2015 20:11:35 +0200 Subject: [PATCH 024/211] Added C++ version of parameterized sample --- samples/CMakeLists.txt | 1 + samples/parameterized.cc | 75 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 76 insertions(+) create mode 100644 samples/parameterized.cc diff --git a/samples/CMakeLists.txt b/samples/CMakeLists.txt index dfba5a01..7bde575c 100644 --- a/samples/CMakeLists.txt +++ b/samples/CMakeLists.txt @@ -29,6 +29,7 @@ set(SAMPLES simple.cc theories.cc redirect.cc + parameterized.cc ) set(SCRIPTS diff --git a/samples/parameterized.cc b/samples/parameterized.cc new file mode 100644 index 00000000..3ae6c57c --- /dev/null +++ b/samples/parameterized.cc @@ -0,0 +1,75 @@ +#include + +// Basic usage + +ParameterizedTestParameters(params, str) { + static const char *strings[] = { + "foo", "bar", "baz" + }; + + return cr_make_param_array(const char *, strings, sizeof (strings) / sizeof (const char *)); +} + +ParameterizedTest(const char **str, params, str) { + cr_assert_fail("Parameter: %s", *str); +} + +// Multiple parameters must be coalesced in a single parameter + +struct parameter_tuple { + int i; + double d; +}; + +ParameterizedTestParameters(params, multiple) { + static struct parameter_tuple params[] = { + {1, 2}, + {3, 4}, + {5, 6}, + }; + + return cr_make_param_array(struct parameter_tuple, params, sizeof (params) / sizeof (struct parameter_tuple)); +} + +ParameterizedTest(struct parameter_tuple *tup, params, multiple) { + cr_assert_fail("Parameters: (%d, %f)", tup->i, tup->d); +} + +// Using dynamically generated parameters + +// you **MUST** use new_obj, new_arr, delete_obj, delete_arr instead of +// the new, new[], delete and delete[] operators (respectively) to allocate and +// deallocate dynamic memory in parameters, otherwise this will crash on +// Windows builds of the test. + +// the criterion::allocator allocator may be used with STL containers to +// allocate objects with the functions described above. + +using criterion::new_obj; +using criterion::new_arr; +using criterion::delete_obj; +using criterion::delete_arr; + +struct parameter_tuple_dyn { + int i; + std::unique_ptr d; + + parameter_tuple_dyn() : i(0), d(nullptr, criterion::free) {} + parameter_tuple_dyn(int i, double *d) : i(i), d(d, criterion::free) {} +}; + +ParameterizedTestParameters(params, cleanup) { + static criterion::parameters params; + + params.push_back(parameter_tuple_dyn(1, new_obj(2))); + params.push_back(parameter_tuple_dyn(3, new_obj(4))); + params.push_back(parameter_tuple_dyn(5, new_obj(6))); + + // A criterion::parameters can be returned in place of a + // criterion_test_params. + return params; +} + +ParameterizedTest(parameter_tuple_dyn *tup, params, cleanup) { + cr_assert_fail("Parameters: (%d, %f)", tup->i, *tup->d); +} From f44eb1760ecf7b0a824af2a8d2f637e77c9ec561 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Wed, 23 Sep 2015 20:37:09 +0200 Subject: [PATCH 025/211] Added optional cleanup parameter to conversion function --- include/criterion/types.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/include/criterion/types.h b/include/criterion/types.h index d3dada34..8265b583 100644 --- a/include/criterion/types.h +++ b/include/criterion/types.h @@ -63,11 +63,12 @@ struct criterion_test_params { {} template - constexpr criterion_test_params(std::vector>& vec) + constexpr criterion_test_params(std::vector>& vec, + void (*cleanup)(criterion_test_params *) = nullptr) : size(sizeof (T)) , params(&vec[0]) , length(vec.size()) - , cleanup(nullptr) + , cleanup(cleanup) {} # endif }; From 0b8680aac785c133000828646889d49be57db0fb Mon Sep 17 00:00:00 2001 From: Snaipe Date: Wed, 23 Sep 2015 21:35:05 +0200 Subject: [PATCH 026/211] Added array-to-criterion_test_param conversion constructor --- include/criterion/types.h | 9 +++++++++ samples/parameterized.cc | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/include/criterion/types.h b/include/criterion/types.h index 8265b583..a28d833f 100644 --- a/include/criterion/types.h +++ b/include/criterion/types.h @@ -70,6 +70,15 @@ struct criterion_test_params { , length(vec.size()) , cleanup(cleanup) {} + + template + constexpr criterion_test_params(T (&arr)[N], + void (*cleanup)(criterion_test_params *) = nullptr) + : size(sizeof (arr[0])) + , params(static_cast(&arr)) + , length(N) + , cleanup(cleanup) + {} # endif }; diff --git a/samples/parameterized.cc b/samples/parameterized.cc index 3ae6c57c..e6aaff95 100644 --- a/samples/parameterized.cc +++ b/samples/parameterized.cc @@ -28,7 +28,7 @@ ParameterizedTestParameters(params, multiple) { {5, 6}, }; - return cr_make_param_array(struct parameter_tuple, params, sizeof (params) / sizeof (struct parameter_tuple)); + return criterion_test_params(params); } ParameterizedTest(struct parameter_tuple *tup, params, multiple) { From 2354ba6c78e02167cd949b6ea122ee64fe9d57ec Mon Sep 17 00:00:00 2001 From: Snaipe Date: Wed, 23 Sep 2015 21:54:42 +0200 Subject: [PATCH 027/211] Fixed and completed documentation on parameterized tests --- doc/parameterized.rst | 67 +++++++++++++++++++++++++++++++------------ 1 file changed, 49 insertions(+), 18 deletions(-) diff --git a/doc/parameterized.rst b/doc/parameterized.rst index 89f251e9..e6b033e0 100644 --- a/doc/parameterized.rst +++ b/doc/parameterized.rst @@ -18,7 +18,7 @@ and the parameter generator function: #include - ParameterizedTestParameter(suite_name, test_name) = { + ParameterizedTestParameters(suite_name, test_name) { void *params; size_t nb_params; @@ -54,17 +54,12 @@ easily use a struct to hold the context as a workaround: ... }; - ParameterizedTestParameter(suite_name, test_name) = { - size_t nb_params = 32; - struct my_params *params = cr_malloc(sizeof (struct my_params) * nb_params); - - // generate parameter set - - params[0] = ... - params[1] = ... - - ... + ParameterizedTestParameters(suite_name, test_name) { + struct my_params params[] = { + // parameter set + }; + size_t nb_params = sizeof (params) / sizeof (struct my_params); return cr_make_param_array(struct my_params, params, nb_params); } @@ -72,8 +67,20 @@ easily use a struct to hold the context as a workaround: // access param.param0, param.param1, ... } -Dynamically allocating fields -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +C++ users can also use a simpler syntax before returning an array of parameters: + +.. code-block:: c++ + + ParameterizedTestParameters(suite_name, test_name) { + struct my_params params[] = { + // parameter set + }; + + return criterion_test_params(params); + } + +Dynamically allocating parameters +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Any dynamic memory allocation done from a ParameterizedTestParameter function **must** be done with ``cr_malloc``, ``cr_calloc``, or ``cr_realloc``. @@ -100,6 +107,9 @@ use: ``criterion::new_arr``. The function possess the exact same semantics as ``delete[] array``. +Furthermore, the ``criterion::allocator`` allocator can be used with STL +containers to allocate memory with the functions above. + Freeing dynamically allocated parameter fields ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -118,15 +128,36 @@ the cleanup function that should be called on the generated parameter context: cr_free(((struct my_params *) ctp->params)->some_int_ptr); } - ParameterizedTestParameter(suite_name, test_name) = { - static my_params param = { + ParameterizedTestParameters(suite_name, test_name) { + static my_params params[] = {{ .some_int_ptr = cr_malloc(sizeof (int)); - }; - *param.some_int_ptr = 42; + }}; + param[0].some_int_ptr = 42; - return cr_make_param_array(struct my_params, ¶m, 1, cleanup_params); + return cr_make_param_array(struct my_params, params, 1, cleanup_params); } +C++ users can use a more convenient approach: + +.. code-block:: c++ + + #include + + struct my_params { + std::unique_ptr some_int_ptr; + + my_params(int *ptr) : some_int_ptr(ptr, criterion::free) {} + }; + + ParameterizedTestParameters(suite_name, test_name) { + static criterion::parameters params; + params.push_back(my_params(criterion::new_obj(42))); + + return params; + } + +``criterion::parameters`` is typedef'd as ``std::vector>``. + Configuring parameterized tests ------------------------------- From 10a3cbb9883483d783401bfceebfdfc935fc8a0c Mon Sep 17 00:00:00 2001 From: Snaipe Date: Wed, 23 Sep 2015 21:57:20 +0200 Subject: [PATCH 028/211] Conditionally disabled asprintf::invalid on some OSes --- test/asprintf.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/test/asprintf.c b/test/asprintf.c index dd191aa0..26405551 100644 --- a/test/asprintf.c +++ b/test/asprintf.c @@ -55,11 +55,16 @@ Theory((struct format_test *fmt), asprintf, valid) { free(actual); } -#if defined(__unix__) && defined(__GNUC__) -# pragma GCC diagnostic ignored "-Wformat" +#if defined(__linux__) || defined(__APPLE__) +# ifdef __GNUC__ +# pragma GCC diagnostic ignored "-Wformat" +# endif +# define ASPRINTF_INVALID_DISABLED 0 +#else +# define ASPRINTF_INVALID_DISABLED 1 +#endif -Test(asprintf, invalid) { +Test(asprintf, invalid, .disabled = ASPRINTF_INVALID_DISABLED) { char *actual; cr_expect_lt(cr_asprintf(&actual, "%"), 0); } -#endif From 665dd400594691f19680ec50910422c45ac18cd3 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Wed, 23 Sep 2015 13:29:31 -0700 Subject: [PATCH 029/211] Fixed BSD & OSX get_processor_count implementation --- src/compat/processor.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/src/compat/processor.c b/src/compat/processor.c index ba7ab9fb..a41fe17c 100644 --- a/src/compat/processor.c +++ b/src/compat/processor.c @@ -31,20 +31,19 @@ size_t get_processor_count(void) { return (size_t) sysinfo.dwNumberOfProcessors; #elif defined(BSD) - int mib[2] = { CTL_HW, HW_AVAILCPU }; + int mib[2] = { CTL_HW, HW_NCPU }; + size_t miblen = 2; +# ifdef __APPLE__ + sysctlnametomib("hw.logicalcpu", mib, &miblen); +# endif + long long count = 0; size_t len = sizeof (count); - /* get the number of CPUs from the system */ int res = sysctl(mib, 2, &count, &len, NULL, 0); - if (count < 1 || res == -1) { - mib[1] = HW_NCPU; - res = sysctl(mib, 2, &count, &len, NULL, 0); - - if (count < 1 || res == -1) - count = 1; - } + if (count < 1 || res == -1) + count = 1; return (size_t) count; #elif defined(__linux__) return sysconf(_SC_NPROCESSORS_ONLN); From 013992d9cdfc03ae52f9843f6cad467e450ca5e9 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Wed, 23 Sep 2015 13:30:08 -0700 Subject: [PATCH 030/211] Removed asprintf::invalid test --- test/asprintf.c | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/test/asprintf.c b/test/asprintf.c index 26405551..0fa34d92 100644 --- a/test/asprintf.c +++ b/test/asprintf.c @@ -54,17 +54,3 @@ Theory((struct format_test *fmt), asprintf, valid) { free(actual); } - -#if defined(__linux__) || defined(__APPLE__) -# ifdef __GNUC__ -# pragma GCC diagnostic ignored "-Wformat" -# endif -# define ASPRINTF_INVALID_DISABLED 0 -#else -# define ASPRINTF_INVALID_DISABLED 1 -#endif - -Test(asprintf, invalid, .disabled = ASPRINTF_INVALID_DISABLED) { - char *actual; - cr_expect_lt(cr_asprintf(&actual, "%"), 0); -} From 13760d0447abdc0fd0aec444ab0aecaf5cea74cd Mon Sep 17 00:00:00 2001 From: Snaipe Date: Wed, 23 Sep 2015 22:34:27 +0200 Subject: [PATCH 031/211] Fixed BSD unused warning --- src/compat/processor.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compat/processor.c b/src/compat/processor.c index a41fe17c..605f57ea 100644 --- a/src/compat/processor.c +++ b/src/compat/processor.c @@ -32,8 +32,8 @@ size_t get_processor_count(void) { return (size_t) sysinfo.dwNumberOfProcessors; #elif defined(BSD) int mib[2] = { CTL_HW, HW_NCPU }; - size_t miblen = 2; # ifdef __APPLE__ + size_t miblen = 2; sysctlnametomib("hw.logicalcpu", mib, &miblen); # endif From 461c56e8e93a86b756b42306f104673ff0ce89a0 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Thu, 24 Sep 2015 00:14:31 +0200 Subject: [PATCH 032/211] Removed deprecated 1.x unprefixed assertion macros --- include/criterion/assert.h | 62 -------------------------------------- 1 file changed, 62 deletions(-) diff --git a/include/criterion/assert.h b/include/criterion/assert.h index f29860ed..c09fa004 100644 --- a/include/criterion/assert.h +++ b/include/criterion/assert.h @@ -596,12 +596,6 @@ CR_END_C_API // It shall be removed in the next major version of Criterion # ifndef CRITERION_NO_COMPAT -# define CRITERION_ASSERT_DEPRECATED_(Name) CRITERION_ASSERT_DEPRECATED__( \ - message \ - ("The `" #Name "` macro is deprecated, " \ - "please use `cr_" #Name "` instead.") \ - ) - # define CRITERION_ASSERT_DEPRECATED_B(Name, Newname) \ CRITERION_ASSERT_DEPRECATED__( \ message \ @@ -617,16 +611,6 @@ CR_END_C_API _Pragma(#Msg) # endif -# ifndef assert -# define assert(...) CRITERION_ASSERT_DEPRECATED_(assert) cr_assert(__VA_ARGS__) - -// this is needed to make the POSIX assert.h redefine assert if -// subsequently included -# ifndef _ASSERT_H -# define _ASSERT_H 1 -# endif /* !_ASSERT_H */ -# endif /* !assert */ - // scheduled for removal after 2.0 # define cr_abort_test(Message) CRITERION_ASSERT_DEPRECATED_B(cr_abort_test, cr_assert_fail) cr_assert_fail(Message) # define cr_assert_strings_eq(...) CRITERION_ASSERT_DEPRECATED_B(cr_assert_strings_eq, cr_assert_str_eq) cr_assert_str_eq(__VA_ARGS__) @@ -642,52 +626,6 @@ CR_END_C_API # define cr_assert_arrays_eq_cmp(...) CRITERION_ASSERT_DEPRECATED_B(cr_assert_arrays_eq_cmp, cr_assert_arr_eq_cmp) cr_assert_arr_eq_cmp(__VA_ARGS__) # define cr_assert_arrays_neq_cmp(...) CRITERION_ASSERT_DEPRECATED_B(cr_assert_arrays_neq_cmp, cr_assert_arr_neq_cmp) cr_assert_arr_neq_cmp(__VA_ARGS__) -// scheduled for removal at 2.0 -# define abort_test(Message) CRITERION_ASSERT_DEPRECATED_(abort_test) cr_abort_test(Message) -# define expect(...) CRITERION_ASSERT_DEPRECATED_(expect) cr_expect(__VA_ARGS__) -# define assert_not(...) CRITERION_ASSERT_DEPRECATED_(assert_not) cr_assert_not(__VA_ARGS__) -# define expect_not(...) CRITERION_ASSERT_DEPRECATED_(expect_not) cr_expect_not(__VA_ARGS__) -# define assert_eq(...) CRITERION_ASSERT_DEPRECATED_(assert_eq) cr_assert_eq(__VA_ARGS__) -# define expect_eq(...) CRITERION_ASSERT_DEPRECATED_(expect_eq) cr_expect_eq(__VA_ARGS__) -# define assert_neq(...) CRITERION_ASSERT_DEPRECATED_(assert_neq) cr_assert_neq(__VA_ARGS__) -# define expect_neq(...) CRITERION_ASSERT_DEPRECATED_(expect_neq) cr_expect_neq(__VA_ARGS__) -# define assert_lt(...) CRITERION_ASSERT_DEPRECATED_(assert_lt) cr_assert_lt(__VA_ARGS__) -# define expect_lt(...) CRITERION_ASSERT_DEPRECATED_(expect_lt) cr_expect_lt(__VA_ARGS__) -# define assert_gt(...) CRITERION_ASSERT_DEPRECATED_(assert_gt) cr_assert_gt(__VA_ARGS__) -# define expect_gt(...) CRITERION_ASSERT_DEPRECATED_(expect_gt) cr_expect_gt(__VA_ARGS__) -# define assert_leq(...) CRITERION_ASSERT_DEPRECATED_(assert_leq) cr_assert_leq(__VA_ARGS__) -# define expect_leq(...) CRITERION_ASSERT_DEPRECATED_(expect_leq) cr_expect_leq(__VA_ARGS__) -# define assert_geq(...) CRITERION_ASSERT_DEPRECATED_(assert_geq) cr_assert_geq(__VA_ARGS__) -# define expect_geq(...) CRITERION_ASSERT_DEPRECATED_(expect_geq) cr_expect_geq(__VA_ARGS__) -# define assert_null(...) CRITERION_ASSERT_DEPRECATED_(assert_null) cr_assert_null(__VA_ARGS__) -# define expect_null(...) CRITERION_ASSERT_DEPRECATED_(expect_null) cr_expect_null(__VA_ARGS__) -# define assert_not_null(...) CRITERION_ASSERT_DEPRECATED_(assert_not_null) cr_assert_not_null(__VA_ARGS__) -# define expect_not_null(...) CRITERION_ASSERT_DEPRECATED_(expect_not_null) cr_expect_not_null(__VA_ARGS__) -# define assert_float_eq(...) CRITERION_ASSERT_DEPRECATED_(assert_float_eq) cr_assert_float_eq(__VA_ARGS__) -# define expect_float_eq(...) CRITERION_ASSERT_DEPRECATED_(expect_float_eq) cr_expect_float_eq(__VA_ARGS__) -# define assert_float_neq(...) CRITERION_ASSERT_DEPRECATED_(assert_float_neq) cr_assert_float_neq(__VA_ARGS__) -# define expect_float_neq(...) CRITERION_ASSERT_DEPRECATED_(expect_float_neq) cr_expect_float_neq(__VA_ARGS__) -# define assert_strings_eq(...) CRITERION_ASSERT_DEPRECATED_(assert_strings_eq) cr_assert_strings_eq(__VA_ARGS__) -# define expect_strings_eq(...) CRITERION_ASSERT_DEPRECATED_(expect_strings_eq) cr_expect_strings_eq(__VA_ARGS__) -# define assert_strings_neq(...) CRITERION_ASSERT_DEPRECATED_(assert_strings_neq) cr_assert_strings_neq(__VA_ARGS__) -# define expect_strings_neq(...) CRITERION_ASSERT_DEPRECATED_(expect_strings_neq) cr_expect_strings_neq(__VA_ARGS__) -# define assert_strings_gt(...) CRITERION_ASSERT_DEPRECATED_(assert_strings_gt) cr_assert_strings_gt(__VA_ARGS__) -# define expect_strings_gt(...) CRITERION_ASSERT_DEPRECATED_(expect_strings_gt) cr_expect_strings_gt(__VA_ARGS__) -# define assert_strings_lt(...) CRITERION_ASSERT_DEPRECATED_(assert_strings_lt) cr_assert_strings_lt(__VA_ARGS__) -# define expect_strings_lt(...) CRITERION_ASSERT_DEPRECATED_(expect_strings_lt) cr_expect_strings_lt(__VA_ARGS__) -# define assert_strings_leq(...) CRITERION_ASSERT_DEPRECATED_(assert_strings_leq) cr_assert_strings_leq(__VA_ARGS__) -# define expect_strings_leq(...) CRITERION_ASSERT_DEPRECATED_(expect_strings_leq) cr_expect_strings_leq(__VA_ARGS__) -# define assert_strings_geq(...) CRITERION_ASSERT_DEPRECATED_(assert_strings_geq) cr_assert_strings_geq(__VA_ARGS__) -# define expect_strings_geq(...) CRITERION_ASSERT_DEPRECATED_(expect_strings_geq) cr_expect_strings_geq(__VA_ARGS__) -# define assert_arrays_eq(...) CRITERION_ASSERT_DEPRECATED_(assert_arrays_eq) cr_assert_arrays_eq(__VA_ARGS__) -# define expect_arrays_eq(...) CRITERION_ASSERT_DEPRECATED_(expect_arrays_eq) cr_expect_arrays_eq(__VA_ARGS__) -# define assert_arrays_neq(...) CRITERION_ASSERT_DEPRECATED_(assert_arrays_neq) cr_assert_arrays_neq(__VA_ARGS__) -# define expect_arrays_neq(...) CRITERION_ASSERT_DEPRECATED_(expect_arrays_neq) cr_expect_arrays_neq(__VA_ARGS__) -# define assert_arrays_eq_cmp(...) CRITERION_ASSERT_DEPRECATED_(assert_arrays_eq_cmp) cr_assert_arrays_eq_cmp(__VA_ARGS__) -# define expect_arrays_eq_cmp(...) CRITERION_ASSERT_DEPRECATED_(expect_arrays_eq_cmp) cr_expect_arrays_eq_cmp(__VA_ARGS__) -# define assert_arrays_neq_cmp(...) CRITERION_ASSERT_DEPRECATED_(assert_arrays_neq_cmp) cr_assert_arrays_neq_cmp(__VA_ARGS__) -# define expect_arrays_neq_cmp(...) CRITERION_ASSERT_DEPRECATED_(expect_arrays_neq_cmp) cr_expect_arrays_neq_cmp(__VA_ARGS__) - # endif #endif /* !CRITERION_ASSERT_H_ */ From 5ec278c7d6ac32b8585bca99ddf69484fa1da2f5 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Thu, 24 Sep 2015 01:14:16 +0200 Subject: [PATCH 033/211] Fixed memory leaks --- src/core/runner.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/core/runner.c b/src/core/runner.c index abb25c96..6ac37114 100644 --- a/src/core/runner.c +++ b/src/core/runner.c @@ -412,9 +412,13 @@ static struct worker *run_next_test(struct criterion_test_set *p_set, ctx->test_stats, ¶m); + sfree(ctx->test_stats); + if (!is_runner()) { sfree(ctx->suite_stats); - sfree(ctx->test_stats); + if (ctx->params.cleanup) + ctx->params.cleanup(&ctx->params); + ccrReturn(NULL); } else { ccrReturn(worker); @@ -514,6 +518,8 @@ static void run_tests_async(struct criterion_test_set *set, cleanup: fclose(event_pipe); sfree(ev); + for (size_t i = 0; i < nb_workers; ++i) + sfree(workers.workers[i]); free(workers.workers); ccrAbort(ctx); } From b347b70bdb004ef4182c021311b97b4199becf63 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Thu, 24 Sep 2015 16:08:58 +0200 Subject: [PATCH 034/211] Refactored runner coroutine into its own file --- CMakeLists.txt | 2 + src/core/coroutine.h | 15 ++- src/core/report.h | 1 + src/core/runner.c | 148 +----------------------------- src/core/runner.h | 1 + src/core/runner_coroutine.c | 178 ++++++++++++++++++++++++++++++++++++ src/core/runner_coroutine.h | 33 +++++++ 7 files changed, 229 insertions(+), 149 deletions(-) create mode 100644 src/core/runner_coroutine.c create mode 100644 src/core/runner_coroutine.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 4a51244a..063037c2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -83,6 +83,8 @@ set(SOURCE_FILES src/core/report.h src/core/runner.c src/core/runner.h + src/core/runner_coroutine.c + src/core/runner_coroutine.h src/core/worker.c src/core/worker.h src/core/stats.c diff --git a/src/core/coroutine.h b/src/core/coroutine.h index a8fad9b8..badea854 100644 --- a/src/core/coroutine.h +++ b/src/core/coroutine.h @@ -153,8 +153,15 @@ #define ccrContParam void **ccrParam -#define ccrBeginContext struct ccrContextTag { int ccrLine -#define ccrEndContext(x) } *x = (struct ccrContextTag *)*ccrParam +#define ccrBeginContext typedef struct { int ccrLine +#define ccrEndContext(x) } ccrContextTag; ccrContextTag *x = (ccrContextTag *)*ccrParam + +#define ccrUseNamedContext(Name, x) \ + typedef struct Name ccrContextTag; \ + ccrContextTag *x = (ccrContextTag *)*ccrParam + +#define ccrBeginDefineContextType(Name) struct Name { int ccrLine +#define ccrEndDefineContextType } #define ccrBegin(x) if(!x) {x= *ccrParam=malloc(sizeof(*x)); x->ccrLine=0;}\ if (x) switch(x->ccrLine) { case 0:; @@ -163,12 +170,12 @@ #define ccrReturn(z) \ do {\ - ((struct ccrContextTag *)*ccrParam)->ccrLine=__LINE__;\ + ((ccrContextTag *)*ccrParam)->ccrLine=__LINE__;\ return (z); case __LINE__:;\ } while (0) #define ccrReturnV \ do {\ - ((struct ccrContextTag *)*ccrParam)->ccrLine=__LINE__;\ + ((ccrContextTag *)*ccrParam)->ccrLine=__LINE__;\ return; case __LINE__:;\ } while (0) diff --git a/src/core/report.h b/src/core/report.h index bc2d166e..bdcffac5 100644 --- a/src/core/report.h +++ b/src/core/report.h @@ -25,6 +25,7 @@ # define REPORT_H_ # include "criterion/hooks.h" +# include "criterion/options.h" # define report(Kind, Data) call_report_hooks_##Kind(Data) diff --git a/src/core/runner.c b/src/core/runner.c index 6ac37114..ea1a7fec 100644 --- a/src/core/runner.c +++ b/src/core/runner.c @@ -33,6 +33,7 @@ #include "compat/processor.h" #include "string/i18n.h" #include "io/event.h" +#include "runner_coroutine.h" #include "stats.h" #include "runner.h" #include "report.h" @@ -40,7 +41,6 @@ #include "abort.h" #include "config.h" #include "common.h" -#include "coroutine.h" #ifdef HAVE_PCRE #include "string/extmatch.h" @@ -132,8 +132,8 @@ struct criterion_test_set *criterion_init(void) { return set; } -static void run_test_child(struct criterion_test *test, - struct criterion_suite *suite) { +void run_test_child(struct criterion_test *test, + struct criterion_suite *suite) { if (suite->data && suite->data->timeout != 0 && test->data->timeout == 0) setup_timeout((uint64_t) (suite->data->timeout * 1e9)); @@ -170,12 +170,6 @@ static void run_test_child(struct criterion_test *test, send_event(POST_FINI, NULL, 0); } -static INLINE bool is_disabled(struct criterion_test *t, - struct criterion_suite *s) { - - return t->data->disabled || (s->data && s->data->disabled); -} - #define push_event(Kind, ...) \ do { \ stat_push_event(ctx->stats, \ @@ -295,23 +289,6 @@ static void handle_event(struct event *ev) { } } -static struct worker *run_test(struct criterion_global_stats *stats, - struct criterion_suite_stats *suite_stats, - struct criterion_test_stats *test_stats, - struct test_single_param *param) { - - struct execution_context ctx = { - .stats = sref(stats), - .test = test_stats->test, - .test_stats = sref(test_stats), - .suite = suite_stats->suite, - .suite_stats = sref(suite_stats), - .param = param, - }; - return spawn_test_worker(&ctx, run_test_child, g_worker_pipe); - -} - #ifdef HAVE_PCRE void disable_unmatching(struct criterion_test_set *set) { FOREACH_SET(struct criterion_suite_set *s, set->suites) { @@ -345,125 +322,6 @@ void criterion_finalize(struct criterion_test_set *set) { sfree(set); } -static struct worker *run_next_test(struct criterion_test_set *p_set, - struct criterion_global_stats *p_stats, - ccrContParam) { - ccrBeginContext; - struct criterion_suite_set *suite_set; - struct criterion_test *test; - struct criterion_suite_stats *suite_stats; - struct criterion_test_stats *test_stats; - struct criterion_test_set *set; - struct criterion_global_stats *stats; - struct criterion_test_params params; - - struct criterion_ordered_set_node *ns; - struct criterion_ordered_set_node *nt; - size_t i; - ccrEndContext(ctx); - - ccrBegin(ctx); - - ctx->set = p_set; - ctx->stats = p_stats; - ccrReturn(NULL); - - for (ctx->ns = ctx->set->suites->first; ctx->ns; ctx->ns = ctx->ns->next) { - ctx->suite_set = (void*) ctx->ns->data; - - if (!ctx->suite_set->tests) - continue; - - report(PRE_SUITE, ctx->suite_set); - log(pre_suite, ctx->suite_set); - - ctx->suite_stats = suite_stats_init(&ctx->suite_set->suite); - - struct event ev = { .kind = PRE_SUITE }; - stat_push_event(ctx->stats, ctx->suite_stats, NULL, &ev); - - for (ctx->nt = ctx->suite_set->tests->first; ctx->nt; ctx->nt = ctx->nt->next) { - ctx->test = (void*) ctx->nt->data; - - if (ctx->test->data->kind_ == CR_TEST_PARAMETERIZED - && ctx->test->data->param_) { - - if (is_disabled(ctx->test, ctx->suite_stats->suite)) { - ctx->test_stats = test_stats_init(ctx->test); - stat_push_event(ctx->stats, - ctx->suite_stats, - ctx->test_stats, - &(struct event) { .kind = PRE_INIT }); - sfree(ctx->test_stats); - continue; - } - - ctx->params = ctx->test->data->param_(); - for (ctx->i = 0; ctx->i < ctx->params.length; ++ctx->i) { - ctx->test_stats = test_stats_init(ctx->test); - - struct test_single_param param = { - ctx->params.size, - (char *) ctx->params.params + ctx->i * ctx->params.size - }; - - struct worker *worker = run_test(ctx->stats, - ctx->suite_stats, - ctx->test_stats, - ¶m); - - sfree(ctx->test_stats); - - if (!is_runner()) { - sfree(ctx->suite_stats); - if (ctx->params.cleanup) - ctx->params.cleanup(&ctx->params); - - ccrReturn(NULL); - } else { - ccrReturn(worker); - } - } - - if (ctx->params.cleanup) - ctx->params.cleanup(&ctx->params); - } else { - ctx->test_stats = test_stats_init(ctx->test); - - if (is_disabled(ctx->test, ctx->suite_stats->suite)) { - stat_push_event(ctx->stats, - ctx->suite_stats, - ctx->test_stats, - &(struct event) { .kind = PRE_INIT }); - sfree(ctx->test_stats); - continue; - } - - struct worker *worker = run_test(ctx->stats, - ctx->suite_stats, - ctx->test_stats, - NULL); - - sfree(ctx->test_stats); - - if (!is_runner()) { - sfree(ctx->suite_stats); - ccrReturn(NULL); - } else { - ccrReturn(worker); - } - } - } - - report(POST_SUITE, ctx->suite_stats); - log(post_suite, ctx->suite_stats); - - sfree(ctx->suite_stats); - } - - ccrFinish(NULL); -} - static void run_tests_async(struct criterion_test_set *set, struct criterion_global_stats *stats) { diff --git a/src/core/runner.h b/src/core/runner.h index 9ddb57f4..9b498393 100644 --- a/src/core/runner.h +++ b/src/core/runner.h @@ -31,6 +31,7 @@ DECL_SECTION_LIMITS(struct criterion_test*, cr_tst); DECL_SECTION_LIMITS(struct criterion_suite*, cr_sts); struct criterion_test_set *criterion_init(void); +void run_test_child(struct criterion_test *test, struct criterion_suite *suite); # define FOREACH_TEST_SEC(Test) \ for (struct criterion_test **Test = GET_SECTION_START(cr_tst); \ diff --git a/src/core/runner_coroutine.c b/src/core/runner_coroutine.c new file mode 100644 index 00000000..31a271c2 --- /dev/null +++ b/src/core/runner_coroutine.c @@ -0,0 +1,178 @@ +/* + * The MIT License (MIT) + * + * Copyright © 2015 Franklin "Snaipe" Mathieu + * + * 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. + */ +#include +#include +#include +#include "criterion/logging.h" +#include "runner_coroutine.h" +#include "worker.h" +#include "stats.h" +#include "runner.h" +#include "report.h" + +static INLINE void nothing(void) {} + +ccrBeginDefineContextType(run_next_context); + + struct criterion_suite_set *suite_set; + struct criterion_test *test; + struct criterion_suite_stats *suite_stats; + struct criterion_test_stats *test_stats; + struct criterion_test_set *set; + struct criterion_global_stats *stats; + struct criterion_test_params params; + + struct criterion_ordered_set_node *ns; + struct criterion_ordered_set_node *nt; + size_t i; + +ccrEndDefineContextType; + +static struct worker *run_test(struct criterion_global_stats *stats, + struct criterion_suite_stats *suite_stats, + struct criterion_test_stats *test_stats, + struct test_single_param *param) { + + struct execution_context ctx = { + .stats = sref(stats), + .test = test_stats->test, + .test_stats = sref(test_stats), + .suite = suite_stats->suite, + .suite_stats = sref(suite_stats), + .param = param, + }; + return spawn_test_worker(&ctx, run_test_child, g_worker_pipe); +} + +static INLINE bool is_disabled(struct criterion_test *t, + struct criterion_suite *s) { + + return t->data->disabled || (s->data && s->data->disabled); +} + + +static struct worker *cleanup_and_return_worker(struct run_next_context *ctx, + struct worker *worker) { + + sfree(ctx->test_stats); + if (!is_runner()) { + worker = NULL; + sfree(ctx->suite_stats); + if (ctx->test->data->kind_ == CR_TEST_PARAMETERIZED + && ctx->params.cleanup) + ctx->params.cleanup(&ctx->params); + } + return worker; +} + +static int skip_disabled(struct run_next_context *ctx) { + if (is_disabled(ctx->test, ctx->suite_stats->suite)) { + ctx->test_stats = test_stats_init(ctx->test); + stat_push_event(ctx->stats, + ctx->suite_stats, + ctx->test_stats, + &(struct event) { .kind = PRE_INIT }); + sfree(ctx->test_stats); + return 1; + } + return 0; +} + +struct worker *run_next_test(struct criterion_test_set *p_set, + struct criterion_global_stats *p_stats, + ccrContParam) { + + ccrUseNamedContext(run_next_context, ctx); + + ccrBegin(ctx); + + ctx->set = p_set; + ctx->stats = p_stats; + ccrReturn(NULL); + + for (ctx->ns = ctx->set->suites->first; ctx->ns; ctx->ns = ctx->ns->next) { + ctx->suite_set = (void*) ctx->ns->data; + + if (!ctx->suite_set->tests) + continue; + + report(PRE_SUITE, ctx->suite_set); + log(pre_suite, ctx->suite_set); + + ctx->suite_stats = suite_stats_init(&ctx->suite_set->suite); + + struct event ev = { .kind = PRE_SUITE }; + stat_push_event(ctx->stats, ctx->suite_stats, NULL, &ev); + + for (ctx->nt = ctx->suite_set->tests->first; ctx->nt; ctx->nt = ctx->nt->next) { + ctx->test = (void*) ctx->nt->data; + + if (ctx->test->data->kind_ == CR_TEST_PARAMETERIZED + && ctx->test->data->param_) { + + if (skip_disabled(ctx)) + continue; + + ctx->params = ctx->test->data->param_(); + for (ctx->i = 0; ctx->i < ctx->params.length; ++ctx->i) { + ctx->test_stats = test_stats_init(ctx->test); + + struct test_single_param param = { + ctx->params.size, + (char *) ctx->params.params + ctx->i * ctx->params.size + }; + + struct worker *worker = run_test(ctx->stats, + ctx->suite_stats, + ctx->test_stats, + ¶m); + + ccrReturn(cleanup_and_return_worker(ctx, worker)); + } + + if (ctx->params.cleanup) + ctx->params.cleanup(&ctx->params); + } else { + ctx->test_stats = test_stats_init(ctx->test); + + if (skip_disabled(ctx)) + continue; + + struct worker *worker = run_test(ctx->stats, + ctx->suite_stats, + ctx->test_stats, + NULL); + + ccrReturn(cleanup_and_return_worker(ctx, worker)); + } + } + + report(POST_SUITE, ctx->suite_stats); + log(post_suite, ctx->suite_stats); + + sfree(ctx->suite_stats); + } + + ccrFinish(NULL); +} diff --git a/src/core/runner_coroutine.h b/src/core/runner_coroutine.h new file mode 100644 index 00000000..0b8773a3 --- /dev/null +++ b/src/core/runner_coroutine.h @@ -0,0 +1,33 @@ +/* + * The MIT License (MIT) + * + * Copyright © 2015 Franklin "Snaipe" Mathieu + * + * 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 RUNNER_COROUTINE_H_ +# define RUNNER_COROUTINE_H_ + +# include "coroutine.h" + +struct worker *run_next_test(struct criterion_test_set *p_set, + struct criterion_global_stats *p_stats, + ccrContParam); + +#endif /* !RUNNER_COROUTINE_H_ */ From 8db5def5e37ae61e47075bc81b29c10609bee268 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Fri, 25 Sep 2015 14:10:58 +0200 Subject: [PATCH 035/211] [Issue #56] Updated screencast --- doc/screencast.gif | Bin 1442426 -> 1388328 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/doc/screencast.gif b/doc/screencast.gif index b8289416f4dac87280173f516e9553f906317037..8b61b503f1e3334ac994b4c09f6d112348fb8d52 100644 GIT binary patch literal 1388328 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
    !Xd%< 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�saU2*y|q$L_QVB>G5nIeRw56?IJ?6C?u@T zJ?AjYakOd%av&};8?>OAgnPUoJ4axFQ7QmN4~;}SglF1#<=9Xz%7mmr$8|H0v=m`m z=R|tTgx`7>C1&w5X6$(4<_?%A&8o*8YIKB~i$YpY!-ehaLv>h*Xkw=)EU^V1bfje2 zL|q&{w!$=&*S@FSii1TEt2luqS2AHsu>50=yiKsm7Fe1}!F9rg65)S_j)`&moOTy` zYA{io!-Xhh8?m1*rtMb9bOz<%DdNd-KRuZdjgpL8wk7Vebo7+^@Bl}OI}}LW2W^UX zL*~aWdLN56A%A!Tn`Xsjqfe;_$K~{WacI|57H068um~K&n>Iam;X;hoTg(<3lA_H) zi+l%!r*WN;*xOMV1^JB|E+ z8jUoGKNc2$PnYtL>w`y}8Kj=c_Krt7oH^bZk5M`sV+LKfiXpMd?mRc2Es0W+gnH(2 zS?wdT)&U;@b7w|KIvlpyn|N>f)TT3%X=5TX%QLAjOsVsI(l^cyEcKD=$)o?Boc=9& z@?oD0=>r#*O_^+%GIeXp_vFckbCj+Ws%)zA4>f6(4=HoIQZ+xM(!O%`XZ5KI622!- zK9s!Z5i_QE>D@#KkY3b54c=;XBt@aC_{lMR5mQ^`&o zqFp#VX#|l=Blj~%CiJgzy7{>SY(k9i?0z4Zlz?bslE$_$kh{4!?}W_o;>-wHF?w$n zm^&52Bm&_f4;h(|l>p>)*|c3Lhz{bnY%-vctJ5tT+{JBHB9ZbXSgenX)*?MLXNRm>Xc8c`Q7$c|3XI@geu9 z6MXPPx~pMEmth`|)6M6mJxs_ODb9-w&l~-aCz8Fic_i<}c=BYi`K5Q`oLw#Z(wHm{ zX~er2o{aV7;m(dHPr7-F7ZL_Wc#|y@U!YJYgX6-NOH#v;QS|^7%4Qk5LDYUyt(z1vh};;Z>~IWZ&!S=?HuphQ>l{ zmqvUqCVAe+~c`_xjHZ}2}AL-_W0|!~gm07k2gEekkOgtDa{~ON!OY&rgMMDG0 zG^3}Y*>*wBft#%ndYAm_?iw#CNNn!u`I)o-l01pvHOb$4`J%~s^{r8z=75M>Pu-e7 z9nk9jbZep}{f)DedIglv0$8DS@}gF-Oc`l(OUh2;O=9cK)LZgvG{!!)Hcb{N+x?@Q zZXeOA?=R-;(u1vw%VsDkw8<_7%alLK>7XY4<1!^4aP}k_z}dqPZH!16uuOT

    5BP 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%0D@wPQi$K^6hc1H^0psh3k5h~o)uUxCo)%*mj zOzn(PNfT}BK8VMil-brAR}&4nYJ2IN;WForee}{RmD&d`1aOASw5Mhdq=)R&(aL~^ z%iauKxV*hN^ZJ@xS7^A*my}!n=i##d6_4AWRe9p&k)3+P{}U?5^PS55Y{}^u4EeoN(k zvE<}6&7p{-tmfuLQSOH&_uqrLL)#9VfGoK`z})(8mK;RoAW`mTOD@KH?>}2||7$S! zCq+*FAHkgIl?o^#`5!8BKfv6tirh^|ky}J^*REgt#gF?7l6&;)Jlgrv2RFxGuUmCRC8*hgQ)TR*RP0VnI?*sH6(~n}Q@+-W;NG6;MHP3Mxo) zEICd=QuwI$ocgb;Xp05OA}aXL1<9K~6(man7Yma6@Kj2O*s}w@(OT-rR-Kx6sgXYA zKr3Kp-dcg)s1yC!{g)k2G;9ob-h7Wvh5Idu)hP>! zx4YCpCXrDk*$B&%0{e#hle`CVvd9#n+qHmIR4gI3lLu^6J*;em)jhw?Q(k;Y=6}4f;1NMbUjjkvi;It z1^}~ITwgxllxJjGT|IwN!rOXhcJ%-CGhpuc!$MtTyuGoy3ChrJ$8^?mDB@ zFuUyC);*voa92`JplYpD)R56#vV&Wp`G8VyQN0X7*kEorvVz3w3mh81NlpqVFds^b zGqAftj`&JXGi!Nb?jk+~TLWpCg`?{$nGKI-xtL3X!< zz2};mKQ)F8=dB={A&g+p-+kKr(HKSaXjqA+LIp`QC`)2L@{+Dy!OE6^DceTcN0AX5 ziBhn6l%^5-oQKS(`>>aHNbo~4Vq3V zDq6~Oa>)wX3KE(TMZvx4L=DEIJTNM~hLi^6dS)0SLuD8+JC(GEeYXcGpZ-a#(OW6&xZ zx8_c06>SsOT8;EAAPOt%0T-2kL3$L{84wf946J`;Gf7H&}KZBhFRy;nX22cUm3gXB#|+uC+Tufv8;NjvrJGd2qu@ z)TY=jqilDT`W;E4H{ewI?HdB+Z*ZubF^9^zzXhmatH6gxR zYYB)1a(~8N1tpM>zNzq@ll-0}Ymh8IeF?2rppty$;n2k4vbz;zsW~b<$l~&i6ZjNf zBBvm^{4|;@HZL?`9^-Czo9ECV08u#vRFJ$qWQs`l2^TA2ws#5S)m#o$a{}^FM4S`Kg+^&^9@LoQh{dsw0Z^-N{I6Ns1a`7 zcZI5-Kj>XvAJuxGcbagFE6qCal;xDx%F>p_xuBoyFg=Cr(Kbsz zeEbwzdPc|%G_^kRxU1EKk>vR5t(Xg|ew7AHIl62uKjZQF0_SvbwS)bayou=sOEWQ* z2PJTb#z@-HnL|na&Yxb$o{%5Ce%9uY>QZ9K{q=Wl#5MnCmYfMc>_H(7IhXqB)mV## zkQqCWpw*34j4rO4UK*oPPJIpV&KN6uAmy;1+3=IK0v-`#q1B(z4)w)%<<1=rvrg<0 zkt)8ws>So@G8m3HM6I9aXN_Mtc@^t4aFpAoW#V%A=YO%}G(W+2QA!R*jJ-ZQ~U@4D|L6#i$;#TmEId~N$KtyLJlV>lBGQ>a< zN$_2^V2&nvkc2{}U^v#B1Gr5Sv|{*NIm<~&o|WaKB++36T()nYCWz$7aY6Kxej@ug z-AViq6_gLuumEp@7{W$a8WRtz4{ z^Ej{-s!5Io@=!yzFT*{wwYo|4g&X-I#yK@fJBO3{L!leBLN;3f{Pq5>*&wSOcWQs| zDq+KqLY_R2gFkr@=AoQqgcgCakdrK9A+t3CXQzF+JYnZW!teKmAjtkWF9Mzxu!0QS zV1yILy_RzLi|Z|*ec=e+`GbN_oE~| zq8>O{K`F^pC?(0X;D=I@tTQj}MYV)kB@TsCg(C(@5g9X~+4VuW2mI>eqmH5@`y9?S z9*BNq0s2?~w>;3ifgzu`qqOCsP`knqlmM=+f$mUY)(Cfj21f1=G?4dC3L_-fM|XLL z!ec@afg$Um}v4S7LRwV-U1xY-x0=MZ^%~$Hm8>#)4(IW7TJ=t1ZE2 z>dzHl}C4Zirf@lWf zxW~OVwqI=#6}Y<)kxZLOeC8wl*ypEJG`T>--xnkUJmr!<`XtZ%T9Ab6Fc8}rUk-|( z5*XMr2F@zk=>Y@$iOPv!Q_u-15-(DaZy1B@ly6iHvgE87;t8BpG&I1m9!$FBq9vD*ez*uT z2n1svXMAbk*$*jL58!>;aJMm(8zb}MaJsEx#>`E$E|Kmqvv3jcW&0(hOE{4+-Zo@5qb8Kagh-qwhWfFke<{da?+F5v{QG1tU(22H9M}hFt4YjM`olK8cq`NV$jVoj&S!JPt+?m*{9t@WsOw(fntSnmOq{nhjCKROV?9pMv z)IqckiJq=_ebVQ;*{NF=S2G}uuA$*NE{2iBI62UPNsvo^%DRSTVR`^qf6i@3Yx)K# zZ&{zWc?VrVm+l~s>fHuALPlAPp_ItTBV))B(xYH)EPg#e=ep&>Dw=YxkT8p< zZCTz1H%2xMKPYSu`o#7B@*dzN`x!rrD*E4e62`EnBh4$`u>Nd z%1ZP@)(c7A zmPF~^Zer7m$$0H~04{0Eb14!Kv_&@8a{4lRIvaF}EtbeQu z&A!otx#@NFCYn)D3Sqma)u(pkQe7+HdQ8N-WY=A=H`Z_iOL+M<&{pZT)61&2+n_`| zth2DPC;ZwTTe?`3;Vz}h!495@NJIGWwPTTn-8%GYYRpV{!K_=cA(dWw3T~t(UyEgc;b|$X?P1>Ucz-7mF_hHav>h?^<3Z04veiaY& zI8Hs%#4{jpQWMFj3=ShUZ1E_H@*TYSXV_5TTCrr)72dFXP=_WF9HIlc|tD zFOJSrVofvG3f4Q)#l5n~oYt7v}LZ}_DU6myJp zk~Hv5r(Zs-Pi)GWdnn}V)AFuK^HXD4ep8!c^Y+H3XO1bYiOrpz%^DHSUHFuj5-oj> zEz7XNTi$6iEm?P?Pfr-YjHELdvwm z_7{VIJ`3+JY)QQOwF1r4$r7*;`rLH5QF~)xAs4^XW62RgT02aVj0}Dbn(y5vl{Ei^ zQndHhVic2nR8hZ`5_ld7+be3*s#7VT{0hWXwvtB#v~7<-8s742ELFiaD-{8WV{zMP zt=!Z{*7{F3OFwEb`7bQFsUXA_8W+r_-9sON8bN4#98k$=_k}Dx5_uB~E=Wd(s66-b z2Qn_gWM9Ff^gFy(v|jY@_zx_(KMIn}15jD=rG0bz$B*r4LeI-=T7%u6hh2MKbFKB9 z3P_7aUhwa&>@SG=Y+&_EG-}6(j9b{nzc3LyCvryo1_z1#e8w3?bgX8M!-j!};x>J}`y zH;!)_->YU<^)%B}^IQ5KpHnS#9vL@&`@CwTvkNLnj<6-)_x#n8qd#k!f6ttFH$hNt zbsnugIx=%w`9;;}{QM{&H3l~vL;P&XEmFDjz2lPOLdK&4N2I4ukAF%T6-$=>(lt($ znvgM^kmXo%0l!c=66C}sgZzdc!gr0YNfr@J{t#9(uD4TE>gxw%!%5SflV$-NDmRl_ zvF`Qc`md9=Qd4$@QyUDXHYTfWNuJtXJ!P|V%JF)I!`G?Zh94=TeS4%nx+H(xK03AY z{6|;bDG1(m(54`G*T$SY^l0kv*N^L00vXJyIsiDi^P|n_k3JW$ANHf1dOAEt(*or|ECODlXlvza(A_#{8I0Wy^*|>Fva~T11j-%61@6r3nM?2mH z`Hlihfr6L}IWaaOjdh$O-xbc(dsv*~oy}PcVzP1N^MwIW9TO^IwizO&3umDsX7kr8 zE19s(6l672#Pnz%fb2UOt{k%Oh&+vM^F!C?-(8<77@cI(aK}a`0}W@&SAN=f1chVc z0KTS;)J+3uiJvVwPC=62S?A>Ydq!?UtQaK|icr}eL}QBXO>nc83$7u>`WQ{T%ml4Q zH}PaiXdlzR1ekNt&eS0-`v=yuqnq3 zS_4Ea-9CBXNrp|b8PCU~k5-AC_HSKI5$tTc-TSOROw~@4=8sYCI6-(t(&Q(kHpYMM z+#c0!z5~+346elby@|)}`2+%+SljBbxMQS(QuA8*6(WMFu2E%l z7LzHKX`xY6o~Hix;03@L!M+bvt=g~mXzZ?<`O=epMdnjwCWtfk!Jd1l9e#*rxU90v z6Rfb6!wpM0u2UAwb28dw@uN2^Nzz=0G5eQbwjIT+fUns&Ac9Ok)+E0qLz|CFYqR5g zjG1RJU#2jysb-aU+Mx(oK-X@6$$R3HoNZg1IfM9^)uM}+I-M#smk%@%35`Q-f;CUt{3VhGXYYhu0Ea1~Ae*fuzmt)6xSvgvBSB$PgDaw#|BjXn%@?1a2+Ga_QsCVeOrz=dm0#S{v2PC5O9N2ki1ugDkm&n|}wy#&> zSaPRSZ}tBFY{@NBxd-|uU!5GRJo!3++rYc~tXvhee`jvs(;vsJ|2td5WAnc zmOl}@zxC)2K_1=apFBEOPS9&OV{#{ zb%FPW7_WcnTK-Roose9pm`?1^QOkcIc1I)P)?TT!IbZ5^@jr@M9$$!B(k@+CAa<7* zqn6=Uum2!+1&hS4_`+W{-+qZ&{*dUR%l<~9`;^0Em(g4DBe;c*T=HNP}>q69WM;CJg zTi{n*cfS^}rloOk9TB_o2x+60F3r~Sz;|2+MJ@k~>lP)tUJkA^w?xcKI{(0R*J2ah zL^P&{vzaKRL#{!B*6oG$EAsMp)va-Rc7tW6q_U%B%c-Zgp6|6Aat%1{Ul!ENz-XRB-g z0@gUGoF;WsRo(s%wl>POO!KX}%QYTTwq6c|BV?OtNbW3u5($3)D5-|)wz`Gf4e}YJ zkq}KLa$X~kO{TRW8uUSBBeWM){zks>+NX$hMU5&ECN5;WAA_PLd|Km%IS<#~YcQ#V zn~B`ZqVx`F4QH={-z8tf-QZ@yeF$@ssj-LW$m%Wy+=Fl@e2COJh9lTQ2EBlRgb(Yf z?^19YzQbHgX*$DsxVE{s2(=C6AMOZWJhiNxw@-JhR!QUZ7<{QT0=cVrG_C_DN(EL_ z6G5w$Xd;=#3^eHtK_`ZV_M<7V9gHA^49$2J4V0Ad?Dhx|7bSs1YeM;`{7*`PxHCO) z87ih+j-ct-ofA~@J81+MZ!~-38MnkmGKx#U;y&uh>Oid&K5Z%)Ush)*2lk`>%K6)wz}jCB+=z;mrqx_9i(AP z4B|(3qbbxK4rB1gg$#~Fw_(y48hnEd1(Uc;>(22-ze`+{=+wab{Ad9Ijzs4YN(F1l z?|K!!Yje5*?}epskXHwDd3GA9OYWd zaAg;`ZU|I{Bszupphby}EflgK(bc1k(-GdEYn~;rekai#U6kmAA&CyL`wxk(ctN83 z!amCxe7j$sh7MSi=q60aPbMIV?i?i19cSob4v-OwG$N`nL|EMx76@VH?I29S<5LSJ zf)NDoMrdfnGm)x&z^hx1m<`!?1&>abA{y=*;V6wOjoDo4B+rw3ub9ac+=w1l$@I;z z=n<(GxzDvxjmzPXiA0rF-ASanfNO=>q|j!fI57#^b+tG4bjro)<{O&`)DYE^SFi() zNh%YTz?mEsvG*gn^G8-PG^=K#iR)+(P!8_3VM-bU3w7;fKpCFd){lWBHTxs+2 zD@4re(eb+@mOc#nF41i#26F3+LCbB65?#r+!M7qnD3K%4ea3A1 zCegY4RiaA@R;Dt(55A2kdY3+w{Ldu1cepS}qEmw;I(0~*TO54b6oU?9$t)47S(NA; zsNzo{iEd%=O#-vx5nOOZA#K~Y!8eXXC&H2FEad!l@Gbj8qO-My%LtJla3nfDzeR~o ziws|K5x&$QTkoX;B++I6D$ynXkmwv1B{~HJB+(7QjZ8Tb-JZWlbao38owdaSMdsts z;bJ4=O&UV+*1S>F+pi;|$Rhps#|>ld;gV;19({R#>gy+Vay9X#)@c(}DnY2kc@Ry8 z3(4*TU+@R>L+7MK00ntFgv*2-&|xU#&UyMGf(b5A&XUTJ;y9acMTq#5KCVnmGu7fI zjSxdRYQSWmvZr6fMw^+0cLO=wH4GNO6&CG!5!K1>gz1s?X@ZAAW zym9mN`UaL|udOG7O!fB_hqK@y!UE^G|6KM+vneXQaDNVNdQg+0KqP-yUt6S9o)=8HeGDA7F&i{32{x>$hr zkVF@A9vui>f96PZU&2Bs&VulU^W3{&{UjPsjqit&v)ji!rEHHZ89OU44?_7rxYj(J zGG=ejMoN?5sWbxEagNinByn1n-v-}GW1+z}?rqT!T^wekWDmrk7{SEB3nUC&eb)Z| zU^MSW9MrGe0!eh17rza@4aaf`Vw-7^D5DF@F~>G|ARQPSR`<=LW8;K0zIk;1D?lrc zQ;wqgFDWsQL>H_LZkO|e2Hz5%U+jQdmMqTT+mHthUKHowv7ehl7$*5*JmdRm@xG#X zXadd@^60k3Bd7_vmOx2i3{N-DVbVpzKl705p)>?|AIl# zp?{n`!K;%Z@KeE_I>b8?Mtwp* zrXH@r3>BWiZp{1)sbn7XlkM<+OZXvx`w%f}QXylLYsTzdv>u6moPi!ufX_#b7kTx`-hT^)88odu*;=sCUUk6r1C{Bk0kh zgkVdKWmitTR%w2%PvP_{b9#Mlem^r`oRWM*hu+Rc^(*A|HlTVHlYM=2{UU(e1j9fb zx*Cf+A(pEjlXrG|HmI0aJa-)sFSKYBN(V3_LwVeR3_%*teKJxOK%Mo-hg>^n267j` z^`-&i%;1ux#fn4%{3S?PN>s1tjb*yn-VRI;3&s0#p2w9~B;Zyg6$xC~P8S6N`!U>a zBam+7i_53my-LacNgE7OSHPuZG+2~V<3uMr# zCkKZy@tVocCzq0H$cLKJNN_P@Z9}&&JOAhM?pr;-Y zI|SW}pr?yRW<>(st`XO=!)I@n4r&)?N8aoWFWw7XS!2LY<4TM`IP)rZPy#H9h1R%_ zPK*TR=5B@Srq9onu*55$;25qcfrIlNl}SE?XIBd2u9oh6i60He-G{yr*|2BCGPEsh ziwCEXSzKQAf>o6t34MgYKe|;vz*gNXFDP~+e2xTkbm@AylC_b*2dj!TV=!z!^X%2@ z&EmIP#cP)6)x6CS67r}fvM&*tSCKWhov+@Rdq@|gl#8->hIHxOR;Yn1wX>~vUPscq z#;RvOoFAMko=q$0!{7z4B#*l?gK&sp%L;i4-MI65q;-u&;ysJcLYK-jxyuT9J{9tb zmrFO%Uy?C8G(-!gc0l%_7@<-sHEKxV6+DN`5c#Xd*vtNbeC*r{!ZJw91w;Rq?3vbH%&_ z3+|NCy^V$PXQ7i=SZMIg{g|e#E6>u$95-+IW1(hYv);YiAUAJCqVSi;ZYhXOz|p0) zCvcA+6Cqr8G6iv?0}QXLQC!;U67%@YokU0?4`OnWR9f{$1SQ72H!qrbPg~7+gd7*l zydWY%=46}gf|<8*U+YHyr`9oTsv~v|ub$eZKxQ6n3$abE`Kh!2Go#09$8(Td`~kt} zXC6+1yw~(Ro!U?Mw|ghG`&Ry&MCZQJ(gUf(ejL;M+?4cW1A_~0gi!M7i2H)zBa=6? z;SgU=<9QL|4`g118I8bmm%fajYP;d|^3H!H(Uoa+T(WuPk<>9+*MVSnJdb{wYV#s9 z`o(Mir}-*iK@zgiscXMGaI5)0ljs%)-{u9Lxp(jwoPSZ-k@Tg5kC4>u4$JU=k>lU} z$fpZI>v}uV-8tMP`>#>Uu3m%rUb18#ew=Mwb&S8|RhLuW>bP$4^<7r$j}cXSHWVCN zVbH(jbiV_=e|uHGV^_cPd_P5UV7I|vaGk2M>HNUg6McfJgEMt~y|21Y96mh1asI`r z`6HX>2ZIcTf}Mvr5*>XgqG~AWueh#-?MWYgY&Q7Hy*sh$katUWO4lL(g02iz_dxoa z{H`|z^KS|z-`+5Id+YCTopa@IZIwBl-glp{ChdJ+!+MP@gP!L126>VrZO$Xlpuso# z$cw+lb*EYP=NwCmoT7aGlWZ@io;_5Uvxg9bc5_e#UiH)ssJP9Y*?t zU9!mPom1g~9~{n$=vGf%>i*y?^%25#E;~Q&3;1{-d1ZU~$3w3_LU7JQYWnEwfup?B zV)oPC$e7ddOdUQ z^+zbLc`5)8P-cUx2SStOaw*CCJ$QEP54uGo)Khk(QNo6ZP?tSChr-Eg=9C^ECgbtF zC-@SeHV_BzL3vHLQ53)JXVXILsrlEl$x?H1J7+wl2u@HqfdWglB@9A{Zw!%Mc-$G< zykpD_(ePnybJwqP{5)qWvYLte7{~GRwt9Ts1j5VC6KKHKBn%f&Q`0DDH^lNOP3?7z zB$au0h>%7)OEt5-M|$`?d(6%)MaIAJR!vlOmp%{6z7xazCy6d~ErjcGSIItDg*%No zB|v^!nhxPQ|L_K4#HIEp8A|&@foqUW7jJ!bV6UQQgY#wUxP5zzy}}$^*T(JcFFh)L z1qKMJJ5rg}Ca3YG_>6}8{6z+fgKw8qcGe||W_5=vs=LqYrG)41dvbC7=yLY)Z6z+) z`h+Q~@IdQ3hn;F|VvQ~unVjT#vz+x9%55$UzYU{C-ZZBz70i0)y<~3a$vIF%*n{VMDR8iKFSj1M#1eY&t6eF*CuTUNb}tl*|p^WW+hw8j_Zt@7IwdgvoDjJ zijgxuBx409@&oEz2i{BIH?AwP(R>}eYQ6TZ?enU9cw5ndXjs$LRz=(eEp?WXGYMvE z#GT}xDO!1fbv@O*d2wRLCYusTCXl*n@C#xqUu zx_I+Kk&x{&(Rd96JiA{b$rCM0dC6`QAwJuZ!#9kHyn~=9dbW0EcMd717rVr6Fq>X-`|L-Z zW}&EMH79E62-DPSX9^GMaH5tKy7!iykM(>gm(Gb=o{wklryDV8a;F1xR}pu(zQo~v zj&;NBKO&mEQh`z{BSjR>{#Ux*H~4qyx=U8YUl;A{i|Sp=8~10hd~#ZU@&e=8mFLb^C($5?JzrSLae=}N&Ysz%dv!j zA1h*O!|J@9I|m@($KM43KVKV}Grt1AhSulu3b)nBeB%ecS2HgIAX!UeWPf*v$UYI_ zbyqmm%wovT(~v4#b6$hTqNGNF&8cR({j_3-IImVcv%72M{e^1gwcSlIby3SU=#3#- z&m0vAOM7yLbU%y|qO~sv^7DM#q)x0Vl4Ahr_hfg3DQxV(Be-0ckye+z%u}44o*f)a z@+M5~-6)S|A#~m=chm=Ef~(H*=iD>F2xWd=ayFRq5%TjC_Nt2~tg8}!?Kk!RQFos~ zP44}=$M5t2A>JU;(V(CdLF_akC@LUm>9%1Qypb6cN561X82NwS=T*J+*&0RS^m+Yn5hUk^?|okXQEs2- zCSvxUO_KKmiM-M%FG1usJrcLiJNX!omU8Fzc@$}_pZh#RYnX@dVvT)#Ad>m^hdxgz z_%HiB%|K!{r_akG2>L74TSI+bQuCe{bBgNoeV*+B20$k+ud7$2a;w+2@DkY#kk6H=!c|O2fPM?R@W!VqAl*5B|~TG5l1pH{rPXKCj+a8ZOts z>GP<32dG5ket<@V`aE4upC|E@+vibY#ZB3iMRuG%55W0MMK$8dSR&NtttSy0kue^E z%w34UD-9Yei+MM!ALy{FNOKN&kJ-v5ijb&>GO_q`aH$0>woO?=un?W z5nuEi>hsp{lA%6t-ISz&71ZbHKz*L#e4i(N%mE(mzKq-FWrDh**d+#`nC&;~Ks7l% zX|kokzKHv`QAh78`pNGw$++*F*C4yfRURZO$A^~SPIX(c^Ri~}?)aUJk`aC+o<2IM+Y$g;(TnX^#OZLS2SU`QA)zfjE&9OY2Vwc+K z8^UFz1u={C^h8o>J>>SrBGTlxtu-<5zPQeNF)DfUJC!|d?3j3)*YdC{R^ZFp-FNi( z`P2kr11w3$#dmsHsds(U!)z0De`DyYIV@l0jMt40y{UtKs@}M(jtB;mmgpR?0@Gys z?q1%}ff!Ifs93x{5pgKF$=jq(3%HezvKd`_9KF}Snv!wJsPiz-+uBFt?~iGrQgl8V z>~qt@<3iX2&DX12GFE;dNKHLa(IS^Dup_5X9$0Nc#p)f0B21XfoZbN*Yv3?=?fUH} zGE1egA%g9zu_hjyWy}yu+BzcU&wk*2Xl#iV7(BUI- z!EYS|e#iZuN~c^8YDhnOiEmBM!W!aJxy8QzVvHW~PImd~oHNu!(((1N8}B1p7()lx zostVy@f;`gyXLOEg|O~^cI4@1wf&)dE`oHjWt{h%bAELjU*EY4uFJ3s&*}tO8QYin z-H& z*T)A5O-Aw)fr*6!3K6x}mILw0+kr;?*g6BP?1Z9Fja{Z{)q688I^{nfHIMdOFz_Ke z)2HYz0tjuc{KtKsv&Ax&vB)D*mu=x}hu8$1N0SLjsZImCCbw9+r(g8-Y!`6E7nKK8 zP$VQ-dl+R#3u>${E5`6mozHvn;xpTK*QcKD4ArL_wZ>)bU`Q#fBYaME=f(4psu!)DZ@bZzI1T@Cj5jTPAfzuAsrO$A25KPZ%0mUC~_nVV`X|yo;Q@g(2-@ zze{S+K-EzsQ^n1z-F?)0&`Cn!ZBUW~l4ndVZ}aBTHh+Sfl=&OIj2ZJ zV{IQ54D>C|%srF711=cvE=5doX_MbG<(>zhP@Q)EwwierTFn%CIra2iJ77jUwK-?; zl!DMQsi#DNv8N`y{BFj18hZGtB(F7uzMMvWs@kb!=BXhtH@dR%{ z0;A`_&+QVTmIHq00bZuHUM>?Kq(T|{d+>APy9I$CG>8m=-{eIR_Q}KZ;MdK6U~uPi zhW;R#1Af~f@LSD04}P!b!7pijE*p2(j*p&8gcu6~zj&sn-7nxLf^&kvPel6z+6Dr@ z*(Z4Dbeg9x-ZXF5T)Q>Cn1D{=g5St3-vA54LwZ2%cHn9S@cuF!N%Xdw!gYoIp?z_B zzP)7MHtT;q|^h1^wi7T;4y`(lFGn2;~N z!TNc@=%cVNT{j71%B;0$NN zQM@lR55aYAZ~(8xZ%!@X<-p9e_gJ1mp8-IIwj%j9U^duTP&2j33`c_&ci6#RfSr_3|7b~fSJ)JY7v z!V~7M2AZyLQKsL-gi~8F_>R-y&I&y8+hpbllRKFij`#5ky*eDeWjfSNEeyUpA~E@z zXcgE^z-*qrou@CrfmuC)2Vnx@mDjXtk+sldX15(FG_qPusKieoo{Ybfcc;!#`h{9l zqhnNaIJeJR?xy|yie29!+D}*PT4-e=m*1%U^=jsfr6}Bl4uK!Gnl{06nFj*DnLqlx zA$_`VM2xse3}5vn2?+eYt!DQ6#Vn7ARVbiIRsXS?DeoVU}Kuu*n&_{HjYEGxd#G10LgaZoI&+b_kqfF9DCk};E# zQ7w!i^IOq9_>R&g7`#nnd?g#vDbLGfA#;6jHtMtkD!5(}-hDc%YCFD|kybRA)&)7= zWE4XoZJ3xQ0Y+PlM70tytg7Tr9!y6o%~m|+l0OjdukADvwU&Sle}G^mr%*-`SuGmj zafqocNtvzp=4S5cR0}5&c}Av^u)FDt82nWflnfCa$W9%kJVkwT} z;ruLrAl4cWf;7v*99FVtXTEodK~A^YgDy3%)9k24M2ux7(vAf`M8wQiStM9tby-pO zA3jXBy4Pumbznt7E3JDY?;4xt-*(Oip@0v>Hylqrp+HY(;(B>G65~Xg}?EMVh^0;fB#D=ScK20HX-zd1xS|Gap^aOcVon zLR9urNd;KeL!-H8dG_iLvCNEp0r{P?MXZ2mhyh1Q#S!`VT1OBiUJ%E}Ka$T^#o#Dl zOJ>2;UYH3fkO{)dB1<|lOLCv#&jN6yA){oZxY#tKEEUfi2&j%mscYo5wq?8wKrFE? z6-mo`=U+6UUh3Rh)GblARI{uPf-QjzsOIlOy5B0vLmbV5N~T7P+J=KivYP zsRwFXOFZrs!}AAfe-_Pf576$LiF&LO@;*PK%`|T_k@k}B@wztMuHihYVm`sJ%&fhf zH7iWxONK{e^0j3ycviT^h1O}!qnU{;qvJnH@E!vYJFI!fz{HD&750G@g9NlpCUWki z^;3(;r(MZqQp6(21APONBdU{WBkAz=CyN8M4Ra8(tj#(A&07U2=2Cv=6YQoW&-NX< zt5x#TM#`ZpcAOYsax0F<*YwP+L4Jy6O<()HZ3bn9 zewBS`#;sNpWhwSjFGZR)||Ps?@=t|f1lc4YO22!G;xG0F?B{?4(7i^L*Qo= z3luRG{F!*ET0x~4{!O*Zcx#2BD|YgRfghxTl)H7xFGRK?P90`} z0gaKXT7}2zJ~p;%=v{sH-Z>ztggz%Bd(2P>0p%f$(=!s=Zl1nz5t1z8|}t~G>I1$(@`d$ z>y`F5U4d%9wV~$BMhvs=s%!Ipn>ruw=D?2TYoD8`QZ4`Tirt6%NK*!4Lr`nnIi!XX zN|R!#Fx;AlhcB37{dxX+DbZls)xIf01Ljex9Jc|{Tujg*6PzW@7s2zPwzLYnYg1p z#x=GI%3be^`ZrGYtS;^%o7--<)_bzpR+BbxwsYY8pZmPx!8w;ss8brGEFR*3-{O@f z=0iYJ|H^Aa?BxS9n|cGUoIh>e9)h<%V?G>48;qitG>J!Tl#L#kq-y1elX_td1hT7%)fjf{{VhGZtpFkMR$~Z^y_|qK3H`3lF3^- zAMCDj!LMY}rEBs^@Tz`^DR=ED&m&XbSEqcnhkP$gi9MLQ_GOB?YRZ4fbbs5_&8yR4 zN2cAcP2Y~5rhS>Zv1>Z&%d{6Hg0=kDAQ5!qcUv+OqCFF@Jq4%phLqp{#!SSLp*vSs zWPs6UsJC8|-Se1uBL^Un?E9JweE|EVgVEu0L?EH+(ik%}sySv%1w+UL_~^(o;#3d- zM1s=~j?CtE%|u?E>W9XJQ~+TzG-ix#NnFKUYy0v+g z2+}0mIcKZ%Z4gVItRW`(@T^YxwWu&9&Bh|R`caWg*oi;AjqQ zYvcyG6+!Y&R%e=&qr~BPt*e*OGo&Kv>Cd}S5gCUgX{^@uZ>w%c`O`-0VqDM^A%lxb zW-%5m*{OzMHFiC7pIr8g&G&gxCLf?HcDJmwT4EPgFQh#$cp7AqWeT^Bx)qSXP&UsC z6$L)4`;WibrSC|@_8NBP^O5@mSg`+CcySL_2y7OXvJyWkE9_c4W z7E;!bMQoK<58b1OEdzv3hwWxMS9IgxO z#?2KUQaVU6d)&Qe*>XD0X#LXD*P!nh*NFR|M~5lac#X>iPbDb}DSP%ESa?uvI7n=W z{&Jhfx$GkzN)byq^tV^jY?kcwMmg&#xun;mtAKOG?%_nnUTX>ubj2>5pL4}-+VIoF z@kNP}7pkBucJHQ^HkrMw)?Sfi%ei8=u4YHDfZeOY&73QCmq+ZH|GU8tLk3XL(_vvI z1*6NFfWzVcVf~Z;G57nv&Z)at#6XDWyZ)KVitSt@_9y*Y{{N%?J=nL;_XqlewmV&d zxBAy`9nwEV@{vAB|JHK! z&*e}0_u`xWz5P-DD8K4o9&|Gg(!Xsl=k>4qSN#)uxtj6m*kYBZ^ZIx3c}N9yZLsD9 zmZN`xf3JVT9Q|YdmHz3fzv1ei&@xE>DmnTGApS=GYB>7$7W)_a$NulrzZV?++sDzr z;eV)q`~Io^oq+VO;UDOqVIVPwqks1ag4Ie5T>Wc5_J{uM^ z8$T~=$I1Qj@}=-Lex{o3LM3@mD~ddozvq56V=F1s&!qlQ?pO1gFAU24bfDbt80u`& zaem!k^<8GQSYK9|pm4XYMh?v?!x)fEv)5DYVV+O!GUHkP1}?lj6Ex%GeiycEWk9(f zp;T%)MNiJbR6yq8_nUcp%%I%QqC)IB%@)te{p`~(ZC7#M_Yi@-d0JyD_6T@Ta`B2Q z7|rdf7X<1SJbAOvUav>wefdnhm~|-IVXGR8;Hrv6irgZ5ZM;5r)V1Vu5h1(8b$rG3Db@n*PkBw7 z-ncGsc_-2*@$^C^s>jz%MGVd9{^oDyK?z+x zi8IQX1oF?GzN&l~cBBy%Q2~D52zHS!jW^)#c;ca(dHfE@_Xoi^=w_ac+sh_AFO_pM z&%}d|NixV|JM!7N!=ambI=s-$yp6uzJDNRrHB*|ld-ImMlo73oqP7$Dusv*RejCr( z2K)dK4}FDh0_k4|1rL3Pp432jSK&0Tf5v(Mb31UQ0(cjC`FNN&ljWMcfqO6yN_(aK zp;LR_svATIet{MqST|RVDPAVq(^1qm`VvS{y?TZPD;^5CYX|JH=IsRd0~;vlO#DVY zQ|K68(mub?FuzDWAZlo5w1s<2GrnjlfD`)ZI6bNi>M&M)VG)Rw_CZql44T0`##eJ4 zZ1cIHA6vwFfgae!Kx0DqYA%C*kOabl#wmVdbiXl%-%(W`q_kJ^W$%g8V5T*0WhFR0 zb!EYD@T9Njj0Gr6#{(^3>f|-2A=Hvd*awLIEI9Nx1VZ!&$=@7@{+5z?$C=dOZ}i86 z=R7KHGrSKZjta-GNcR^Zwj>m6^X z=5gq+mK-3N?66dfOMl$Z@0}iy9f}_yaOm$T6+cMf(jVE`m}gU$N(dD0QJ~OI#6_8M z6J6!kB7$#+uH`l15%S>W@K85LV3dWA4Fx@t@m`jpu2tbWEuqlCJoxH}yW!VFs=yu) zLu|R71JNH7*QqCPKTJR@k3)ZTbndmh%aN60LPZe$LC0o7?=T&upNT~^9Qvw%%jev* zzvg~ov|rab^J%4+%VT2EZ~sdFrYuDP?m8zrh4yCJ9y6c&ebc`IdAg8OjHr4HPr)Uz z)|kcL^sn18Mh05vjG#%h;^kXomANrS_`f-~L==*ZN z(I3dAKW5Y}b@kl^aS|r+#@uyI0z`jIym}I7W)%&sP_i5^uVO_lW20@^Xv2T|m zcq}8n{ZQiNh{XQs#4gK}0}=G#f|Rt@lr)I`tof~|9(+0+`fIkvSFsW8^1QVyWKJmV zf;jB}5!Xk?Q(B@b58_McX^$$>I>fHDH$@fmri~ENB-pf5)lqFArZYLYeHz_XK(m=i zwuSJ_U)!PjEB)Q7PE1s|*D+6j%aSq*?tN;#r_H6m;pQalYWgB3e>DZQstQ}=kAFr$ zo0HIMRA_VpT2lqSK`jeQa66&`e_REesTeGisv(TJoEOjmm3nq7l!xjuh zK{HuqM9i2zd_6^bEeMaXN*pmrF>FLECLtjDyJB!ppD$_4D2z+;L78jaGgjIwG@Jw6+y(iXMH0o`#3W=loy zP{AluQMT0Rz-=ksL}a`CjvX5JC{|bp28aH3JKsH^k$=-P9}m$V0pGAC^%yTborUWj z&Q`Oc<@)11lfKd)1EN1hRB8Y|eYOBgO^-|RNBL>T^3g8w6|Q|2QF~;xRfyYbusEy=|I!ge%;d*N@DEk-Rde01 zmCAKLVqh%@W0;n7T9;(E;m;D`0FF_VQv66GgHeb_2LkJ#MQv2fBL)DYt&ddMFd@Uz zSI(tFGmKG%><;eDyk5xtK!yzcmJBHpwVH0umvd$ZqyG@BBofw5DCr1Kw_rzY2-LnH zk)!-Ns)x#$dK}y(o;S5DqeCAjC?7q{Tk5HZ>}h$lvOS8_9u+v6N1e4_!-8eg>4f%j zb6nYl()??@bWCI>p9W)Snm?3**r9?OC6vSv&?=e8L>B&nc!jN5#pOW!F%|d@5_%4o zTDYk_%4FK6E&z~nsN{@#RwuWQlo+IyZg$>6Ai`G%S?K?CP%WYYz>N56`#It(7^!(_5rvZJiSoEDglAor=~Ub! zpX3Bc{~Tw-A6L_MJj&42u)K%9*P##hP*Lynd(rx-D*N`muqps!eM>T;dcdXTlR-S; zPNdIDTFG#%X(*2{GJ44D7G@)J{VQ>|PCQ;45=-MLo0s8-6VR#GZf;B)QLO?9Z0sO7G8a*+Nh6xFTlsM~OQ z%iV#xHA+$o0OPf;_0aYwxehO;;ccWWkQ6qfP`hD1B)1g)neosJV3$hFtF_)v_N}@3Xw+_CH?doX0?IrMC2Q zNL?-l%K5eB{eXdw`P=VvG4MD)qFSos_8h9I?qBKOw{_01xnHhcTaHmzNP3$~GY11p zg1Rm$wLdx6UdhjLc+n2;Za)lkpszKfi5>ily9Kqnh0ME!uXO*q&iSXCdAp8w<&O2d zN$Pqu*0yGG6#P7_+_k;RwYSobg`~4^|}Au8btnMpBCZD);N`34zpQ+wkYlU5{$chSl_zj-QPxW|eE5i=q96 z{{52sT`d~z$=F^@8|cSxcsxEZthKH}t8c7R>)GNr@6F%*tbaeRa|YM-(b(e`#~C&3 z;rrte_=%yn<3dYTy}Rz_sRN2`)Qaz7sF4;Q0F_aB+`bNk>BENWUZ zd8_*aC-?iVf5EG|3#S61xDV35CDYfthORG|7TY@=7CjyDa_VNubhq;~ZOKgRm+3&| z8M^jNQuK7xo9V>pnP3P5yZOT)3=H89D4B`un#t(mU|{4+C=Z;CFBwXJFpy0)uk(5#^+xe&rEH|iy0?;mB7a=t^{UI7k!y6y*hh$$u#uh zZ(agN7+)pObVUV@SOe6i0d8jF5dzlz$`PWCX0_BqrA1ku1W4rWdXKeNvFIoH zQtZc`ob4_h-zs*5VU5dsx^sEqDdC-GBf|F%8p2ZSBi{9&Td@{sIVDK^EBzZika4)^ z3QFR@YiOPG-uUz6Q;f{xH{f~4P9GRID=<{MW$0!Xsd0Iv0bHj?j?&m*Xd0!Fw=b%2 zgWlu(GdJI#*I1<2k{rpy4TqNF;Sz5t(~oCcv(Fur zQhKm8F?@w)d6AUn$G%6%k6LS280nOHIImi5?4+7iSAK3ym_okZ#j0wgodJSrl@Ou$ zdh=lCA(KJNICZ}qjI!CB%gl$du8Qa{icT9ueQ(Wf1&n*@?-A2{>z_p#JedekgWmxv z;!gC10m%mp$}*+K)>V@t&^d9>?}yiv#`xNuh(#h|YPPIe@!{gJRqLm4@mbp>E<9OX zAz|u?001=c$4%E^!K9LhF}H(O7Rv=iULYxJxpf6=xR<6F^QE2z>wJMGQy$Zwn6H`-|G zv0$6((HXMZz^e3%YfnE2&rve&ZeB-qm$|Xw^UdlD2I{_HCzp5k2pyD-t=ti4=K4y? zPD_Sp{-)jHVe_%f7Qd}mVYl^JcOvG}n~%l#EH4;J&#^oml+Lu3-hE=Z0P!Y0i1zH3 zOw-WRekzZgN5l2%kmGc|pqtB=J*BD>B`bUSYt~@iBI!5p3<@=_xY`1Xuqv7yaDIb8 zk18v^kDu0YgDI%=KPmPqE}T$zH4`q%S?Om*%^NnfR)oOEczjw>} zB^T!LezvpR>QiLX1nJ*Lansx=X7l9>t2yhO<{R2QmR!HwTf3CA&iTg5Vc@@%`~9eY zWVphjJR*7n(`|t#87Zr(!+U_~F7kwoUZ1Cfw`Y1RK_10!RoyIjo2m$d{YDAl2tL$r z8bRSjARpgyap4V8BEO7+Zjk-yh98fB68DCmf~3p_sWqxH%Vgx`<$hE`x%FzCQP6eE z|9r;pf|A%Fg=NqgKckH+EjGwlNZ|ej5gI9@z(|7;yJwfb~f-L+dczTfk^cQ?!{lG6y@eNd2}mp#7@ zTA6e6AFhK2=l|3QhSoGEKdH$s|5GFQ-?I+-Zz>`CKdywtpOrAMDK+$$MsWChBS<_@ ztTjbM3wn4En2 zYCwSfT?udgz7br`Z3Nxs8$rt-8o~EF=NrK%TqR82^E{+HaNz>YH^|3-(+I{r>AQAb zIzjj3S`bHvty0*1pWtPGiPH!Us4+vgma6~@2OmC=xs15^c88=99ll`s0nr(6Px1^; z5~mR~{niM^e{BSxag>lf-v|o2`TWobj{o;5VR@a;);sf!U=M=i`22e#*rCI11Ysg3 zY&IzG1FHBFP|%L&w(awc;C>H0deO!C8-CK8er^PJSaidoMo{jI!gkYu2gVGK2b`}4SsAmQ;6Iic~b1nSgL zP9w;MZuq^Ms9eTv1cMn+Bj`27z2P^`z2V2iaT~!sNI^~`DEX}s)cD&*u>M;ksE7Nb z5zK@dLF)HLkRn~SV!ja!*bg;=`{o z5D&rU-x@(sj<^{EQh#U!pTm&xY~MxLK0H+vjy%PNZurT3Zv@r;x)Buk%SJHsdn4%U zej*P0MvMsvWd|8o^C}G=hRqBN(!Iz7ezrw}|>KHn{Aw?dEk*Rj!io zFB?G%cD`2MpBlksP$L-lw~Zi`jn#k}!M#u;NMmEaH-c}8bTi=myN@rZmP0UiQ(C)qpLH#rc+ zHiCT%`ym`8pji|&|5N;7s1YP`8^MQohzn`o8^KaeBY2k012uv<41Ayp<@GO(pwG{v zpf=n_(E3{=$UJHKb0avwZ3MSLjiB_`MsW07Bbf7ZBN+ED8^MS8KBy6Nm~RB3m(#%4 zMsWDgjUbutq$=-Awrlb>E))(y>!tpls^6f{!2=uPp*h6+67X`8<3gd{RZA8Ox@ihQ z;chZ-2OAgIM?q8Zs(Pm74&R`#*)Lkue}$_5C_A8Zz7ZVcHiGX0E59~^*ac7{7#g6O z`%@!m1vP?X9v-L>gcd$ zfx_&S2nponR!{d60-NCF$%Z;s#0ha*__T9h+Nmi`mP+h`aEK$huTk z0k3zUz6x_q1-PYPE*>QhLXzn12n;hgrJ%1L-akLoT|Pn=+7Y!3gNH<;wZ)=cTL6 z#BElOhi>?7Q=ln2#p6sa!6GnJinb>O`#zj=!>?EWZrt&^U&P`KTJM_A+$F2WoS)zs zh2}s75?Q)ufyue#7fip~%ab(c-WqM@pWqvj z-?Pb1&oUoM`)1aITiPG6h=I zMtrdftyVp~2Py?O(wU-7Ow%Z;;~P4}yH!5KroZxbOzzonz7i@l3czrhK(Ejsu9{ zX&!PWXBSi)Dg~QSGNiyBwfnMXczbww``L470Y1pPvV;S&qyvE4&}Bcstxp~^oPs*1 z5-m$aOf5r5lT(~|?&f8J);?fJ1Oks;_=xs70m+Z3Lx|t z(42>J1@Lraj-6>KbOrD^R1K;ydZ*J*k!afjwH;DR2F38uIl#}x8U6vLfobHgeOI)GNDBNG^SJM~I0mrB30crp=gpn`V5)wMolFm!?7* z{?edoJUpVDjUI*0FLG`KKKD|i#fagcPyfNH^w{=Cfzt^#>WS{A5mgG&CTF30iB_)U zd%bFKHx>1Wf|_6;KYJTZ43#}l^|Z+4<&;aj{>;;81};31R&E(bnaRulM4xtHV$)x$ zjl@VtByU!aBAdnS1$Y)RXdmw|MWbq06ug8cMi-COZcVL)JJl{dT(|sijHK&aov%Ti zLPwqQCc6CRI`itfHHYgrY>H-uLpS{DH9P9HKGzeWoKV+F=Wqj56P`WUV9+75wfCec z3-lMh1KsdDlZ8AmUlR(v+Sl>wau!kn^D3D7*!*zgiQ0zI1Wrxp#YCJq*J#bH2@lQ# z;-V&}`I?Y~-J){Qc~di|CWM`|GHUiO5^{Y3niVxu$AmPXnvjCBFM6f4s3igd#N(l6 z)MgB|A#ziz+3E)GZLLXBttmyVX&tQ@pZ~bw_m`ufA7YV*G7)=>+Di^24@#jltSuFj z+pFiKI62`#XkgSD^-8JZ30Dv=jltVDbzWND-1pNBzkfXnns3owd5#tLqW#0ib|eW| zo6hny>Szq=XjSU=AM1d_I!y_kq8Tk{a_5piDWURQkILfSHCnyv%zHOn`RRt=E;m*c ze;>P&Rm0z*dnHQfJgh0Iqb;hhCb=8Q=w6KPZxib|@GnO}zcqq5={~y}+il}4@XFxa z#@s%mE8Q;UwtIH=yA|6SoBw_k^ruE}rTyX&Aaqb~=LmaXPB@PJ#hvMRYoEn` zJqr3$BRJO^SNyu})X0Lx-8D65Q^x!1$IssD>~7LJ_n`RqH~i+t*^A%2)p`@s@%nwn zc4qP5B!0sy{Lrk{x)$^PFP&N)T5R-HHa42gTf)Z8-|$;9A*ekebYw#K>V#-Cq=fY! zizmjfzo{Fa7_NJhrabp{NRYjJ$tqOz+m&5!mA|~@-0=IWMlio)g1BHMLHj*p^V@A- z6y>7dSKNPV`0a+@zQ1Y&eU;xIyCA*w$VXxK_ZB5fphi%v=lywT6jXcC?#QJ5kB#7$ zNeWj9d2~K{MvI=lI^`Gh(LY%9T-Ves*d$eZ`sR`8+fXA2DPi!cw{1`(I8BF?5Gn${ z49BmU5wo31DVa%oGo8>i^EPrOQ+xK|l3Ci$+51Ok3rc40Ett(OnT>$}v6ept0z^0d zsIJ-cFSCp<)9^VeZ~8qPK>3sdb=JWv(#g@5nYTvC?zs&7Goon%*>{x0$qCcQ(cwfO zrRvgaFfB?n_BF^cLvh$#&r5}g z;2!dvJV0S6*+0WRJci*96h2yF43f*o4+&=+*bEYL&kMe~^qOqVxGp=yT&dBJEm}X? z6a;HTDl8;zJ%8td%EHBldKm|EJ#kXJufvTejy(;M(&mhU_FcR3>aG|eEi4{Lzqn@( zJ?3zOBm`z>9rwY%s7rvt#=ToY_N$!|s?9P*2uK!g71(}n2W+?0PPdmpprG+nzmp{t zKJ_!ks_H$=@1vk{N)@biY~93{9WQ)79gbjFp6&~iCy%^;FNiIyhvQMSO_c?>IvIhq2^B4I2$uut+8s${3z(!hlcz(Z?Osyn0YDt@q+rb zK~V-}IzB;DSc{&>``7%A!+nhfQYtRZ@ja`s5C=fjZnVN6dTGsWA4vc!S01LS?m;5( zU}8xHy!-p^?^soWT>CsA%$ehgs$S}=4<9SrzGTqm!S=Olj?LL@64@fZLfp(`8H*z4 zq;^`$mdr3v%xJA!ou*%@mk_o{X2yu<-pn9MxZOE%j39hFbx+w2IIsvHA&5g6d`-IR z_wPS=GJC}{(Ngjvc?>b@)yEj)dDH(gI372BZfp(iHCk4p*6+;{2u>Zf63z*_cjnPErW0qBNbuK9t_3Kg)v z>!vlGBfghH0L|UD)x{Sh{Digr-Y;VS=W43>WA(fg6WiR6Rqmr3RTb@_ujE_vTKekt z<@qOWq`!Ms<@!qA!&hk6f!B%IzH1a%$Gt9Eg`JS8Ez_}jFxNW5yeFD*Tgui~hTH>d z5v6z7-4pN?0Al-|KiK)A{B4=r<^u~)-Q$dchO9g;ec-r^0O4k6`T68qs`YZhvAe97 zlW`}##8=?&I@qlh&rBLyD`_tpqDt(RR9S0djf!}JfGJp0kEezAI-Sdb8bRCZN&!zX z5oeF>v30DH?J!u|m5rO&yY)2G2<}!Y8f_{MEV6Gq&AH)MnCd#Iat=eY>w<3hO_e)s zG%sg`o>u0Lg39#8HBlW$7sW!OpxMz^{*6)4pOsMapD7{JbA|3v-u-!-g>#r*t2~e5 zPBw>7ezPr#;2snF-L@$ByKPZfF;%rC;*v`jiOMb#-+%=bxo)WVvm36MKPE_!Uni@m z_TxRlt>S_|Zi}8*{z``j*GubdSZ(o7wng`G>2S~A(c$t9+t+ApmH9@8f4JdZgS9sE zZfO0@4NbnUithLatD-mm!K$c}yD}#&y#94qRNd$6uqZ@_J8l^NLWhoidk@E&S;U(; zCLX>Te&TAljoTfK0KZMyUK&0(4Dy4Gex*bI3y*GG;BJc={?-jm!dC92Za5XN_CNyX zu;BSD37yD2=lrc4{J+zo#_dEd9X{G|?YDIJ_uHcP?uO30;ry^@dPZ7VK}OZX+h5(V zBAi)q%uNhUHGFL_Wk6B=^QuoMZDA)=WdI7 z{JeRZ}GB!?}pDgZusV}+;B`L*UXmY zKQelck+8fu(++j!bylVLw%7Mh$&S8$z`S4n`r*N?XU4Ldw{0EEF*rFomdhG=GM2Z- z>&$rm-yIXYN4h_CRA5EDP&-98{}XU?v90fuOws}$A)D9XW$z{Oja@n^CP!q{;trA6EvN;{NJ=O^P0~sq&tn1W zOu!Q`g&fj5|2aHT#|Ugk)UNR)V#1C+Q#@d3L|k-l$X!(z{T$Ha^>mijleyZi!h9tT zxaU{965;xfJp<0G%dEl4@7P714SYIG*zMyP z)1$$5bNR%WU@ayrF@RP;OwHX1zJ9il=`sfIIR9w;5_?=@OX1|4v!E`C{bA-xND&o= zJ-ZYKzYBOk`$ecvx$DS*K=rzt%P6RerT&7x6yB1BzFnR6z6^fl6OZLevCRo8aEkl9 z8@fT;q6|K7_Tff6$(Q4X>-AW#;4z4WOacWS-b~C{4$g0jmNx#lEec(x5ym2a+!i%< zHir&ZmA&|7TlA*b-))Oh1yoN&FMiXbcYK>sP(Z2s3=~fHC#Xv zhU09Dl7HG3WplPgE1RHg(a5jcqQaXYH~hLSN`0v@pSDG>|GX`_ zyxWSU_Q$p;cz5*+l!sm0GTH7wwneKRmL3+2g3l$(z?9{=+oJW{y3kMK#8)@uY>QIA zZ;Oid#CmhxaNGR0=rOJv%Kfx03jcXqbOLh2*WcWbTJwEdl+V&|3#TsB!A@7Ax4m`y zt8GyN7_7(H7Nw>_+oJYce%KbZgtkTJ-O%;P;iF%-MYnd&yJ5rpwkYI=H4MHGcEa~< zQH~puxZ9#5cM|uH%7a_Q_Y$@Pa|E6H1{B25G3%QTWtIy}6Me$~&uiGtjWp1&so+C6 zS{`Z0!#41gY`V*Qes`B6&!J+xCqhmMYZIhs+$XG?-*qePSdk*tV&|mqtMu0>q%?P1 zwCs;J4p+er~gpl_$c*K{w=TqB4W(#*2Nju%1-e&Dym`z`| zMiq|KfVM^B=eI@eMGDZvKWvLm9Q(R0IxKtYBy>zrtTOBo_n4sBV+rV(pgrookX72Y z_t)(R5?}{(Oz=1~|B8!$bno`vi-3|t%d-P=r$;Wj?Q#Qg=jyFj%^h@hhCLb%x_~_D zu9Tp|?2usLsBq`OLxkPlPi~e@_9@NIG_7dy zuyZqdeeA+8P_{nje&~zWr!;0;nAdV1CK`=dna;L0*W~2nz8E|2Jln>?=jK%yjbDtM zZ66XA=h={hQf}DT!M=8RTOJ9%z>dIcg3W$3`Qn1FU5n*sd>&)bF_;p=hJ_Vz5K6PI z_tcQ=G-!4&Ub551Zo5m*qL)*7t1>38g*x+?0y>zvZ8RV_vc2u#)csHmhqt#2KlQ5w z=RZHa^Ib&SrvcTM`8Aho-qB`14H6d=FnxBukCo_X5g}}OY~+CiwBvajRkw>@+j)tW z7b^hfd&#c6&vVIP(<`$q%0}Zc>IFu3$Nr{#!9B$&MMJW5F1w(;sMy=z;rIwzr%WB6 zK_$J4}l#OEP(SJJPoiH{nT0rN5J&#j}k>BwYK#RBCo_WqK^gbb4A zPPn$iHJ8q%iA(fYmpj0x8gmm`8!5unaB9W^8t)U;?W>E4;9le7QZLx$x`X4F9`VUY zTw3M(#%o&|VcLJOmr_#iT6luAk2cm=VVf^wiJ3^_i9mMSeM z*dz*Whytp5Aiph)zGPpW5wR6voit@S;shv&T7KifozEEh{S+G{=(e50Ss2|L21>}e zj?e+AX5e7h`dk)gVKg?8xKa+>2`!9*UiK9p=dfOT^t=S}TrHEpmm)ZqgPv@~$CV zNw&Z06XqKr2mPV`zH)efxed36e5rXJ*iu*G6mJdD>xv#n4?P_?diX?-tB2OS?JQiN zkQH+U_!NBcqMoDOl8(-~Z@N<$I!ZB!s?KcAYpLFncbnr?`4F15S z!_}2w2S7z;1tT}QNhF7$j=~06!Rbv7AM|X|4Ajy|*wk{EN1iv5J;&2eqHwH*0CMz@ z2v5kw3;6NP>mk%OM0(wT5<)FYs$?EMDva7<>~2kQ7qJ9(s$N{DdV@f^u~7|d1+FcC z-Q0Z0V2wUBM|xAE<%YJ{%`N)i(#imIx6=xJ+uc-@36rxhIt}fnp2qirxE&8vpOEo= zByMI%btX@1c36k(R|)fS3_HBtMTtV?t)g~J^0Q8Zq(uBqdC(Oa6Fp=)l!?C^3PJ%- zKvk%Re1s}bxc4D2IX~i!Y6w3JZ*6_kHa}7b#`}zTO~@@ktk!K}XrU3nZ|w+@R$O}2 zaz{t{j;IcAALw6mC`tq#)i}Q`%Bc%21t%B&sV;1xjZf3q+`6zw-^KPfZrEq}%?(rN zALV~`!|G^kM2sX<7y3sp82P~s4e0Z3C?Fm?^4$$h=!#Bpi{{-h;tw}m6A`y9g?uAc3}5L47}OymUmo8P^R}TZQR#ymk^uu8!`aqx+LDE343CS?G%_ z^f`rSqnY^KPMmqs?r_YtOip8XNP%`$JZbKeCDuuS=19frI3)x^#{_4RdRv6IQ*lkC z1RhxOyYPhmVcu|+KlD(6n7Gp)Ac@nUkx|zanuh`H-bl1F5!0)d8sMLt7m-?E5(gRL zD+*dG59BF;rIGpjtZ~{PEtZYjNp-GJNgOzYdQ8AW_x`HHY0p+bv%a*Jg7oe~S6C}( z&sx(4*&IW(5~sBQ(Cx^V<0FR^gQ&U>V zjv_q?+HGg_G8S5qkxzr7L}sxo^IMc?{Rm4gm<%XzFv&hROPk<>LmT|TKw(a5A=(9c zC!u|!)@_){poQZb96_}Dqw-nYSUz7Rw@++lKAPMMGo}Z=1Yvy=W$h|uEva}b0KW2h zS+!LuOX6N%0Des%U?4#=9L@j4SF+>-OzZVybH3D>Gxs!BMthS{yRERs%tX{3#?DVq z1X6{CnPmjvCV?J_I!bqrguC)R9ytW-jf8cvN_!kLP7!IRT(kq)$_IGx>s_?rEg4bH z+H3{dV{*uQ$9o6(3N~BQCZ3hgZEMr*NiOJaDd?%fxKj|L`dANUg{unoG6gWgmESb0 zx;7)sa85=QWJ%3tNsktpr_nm*2TLjV#ge>akTY01s*;%UygCE-tRFzjW+IQXt2`vC zdo0VP$R$|z?Vjo681l56u@#thIL}Wbqv$R?a86IrAh_w)N14)H#`@sa4tr=HCbCBilP~}7vxz;j9%wjzsCL+i0HoK;v@Qwqf|3AWqLs6q7=oRZ=%V)s2Q3v^_d3! zy~_hPwVcRm8oSNGM{k9en;k9YrLgOlQSQy)w*7}`uC3&W3;Z?!6z9tNv}W=PPa1=} zy<4(e+jhjX;$oWfI@)%YB0dhlj8$6wI`$O1wr|c_eYpyi;|g33YG=M!WHWcpqV}KH zg+{A(P*Ivd^TdnJZKUSi3`FR_^-0&R-5?BZhgwB~9VD>6NOfUI24aNPRa6#u{`5Vm ze_9uQb;Hg8Xqs~^zGK?;!Y3nO8>?&M;x?ET3w4F1eWi_08RRcUEimt^I0r1O=_4)f z-=o#P&-@=86Py!Tf4=LSd9Ye>*Jr80MzKC&A`5+uHD}*>XZub-zqrpeBWkDC-yReE z(G6?B3yVjzHV$fZ_Qum}9sUn*=NZ)0`taNI0wIPXO-d+A6#)xHg@B+mk)|Rd1VsfD zL9x(;&_fT13J4+ess==Q35Zf`U;$K0KsrdV(c|4gJx9+u|MK3s@BO}K_Ln`G%(I@g zes@Oos1s`QqXE+syAO|*{L`4=Z`^RLEy_@xc&6l@V>jBN5kaZwltx^K}+qF1smOr>(U`e{#bgZPB!ai260V z(0Zb<2tq%ILx}UH1y0OM)Rv=8_9`{u&Q@D$^GI4ixs-N{_3#fp$ z+6Ek+p5NR{fWW!L^b*YmbVIpBwSxbN8%jS60Jz~c4K_DK9?K6B+PZ&7q7%oUO?ea} zz;c8b|0yJpP?)H)m0MlFqqkTbc5eOVDkUr#4oyHQpb3+mn`CQqcxe-bhfjiFJZF;* zeXuEW?X3&haCo|heBx#Fat4tEw;X-Z0q;4qhtEp6p@~Sa>@9)7+$S#HpB56_+~{{- zu}MLvGfew)JQk| z+6N_=c|CAh{ch5EnmMR;PRRizG0)s-P`6!G8J?s6F(_OcVj74b^_fT_Lk{3f%!=UR z+gdB)363R(GHJo8Mxj%{n4m+`9N;o)CB*OKet0yO$NkBk=V&*Bott9N9FiOb8?MQ7 zBqQ8=Sa<8=TL6y{y1xKs2wT4`yy3l(1y7^WI{j_t`T_@Al`izPyMU}PC#^C!(IO1R zOdM1nq;E0ASn^$<>A2;}de7yH2&uk{+A7v*62YSyFBcjT^!a6n^bX|~L^gkwUzKaDhP&MTMUrZO(q!61Y(vsun3|y0F9c{L!;xFX!Yn zXtz8nTG0~F%MzpU>3zlqdm#kpQ$p~uCzoi)TzBRdi3h<;MS23k%=JCw4df%|WO6Ew zN8a2JDS||Zq&ht{&}B?0Noqvsdbc z5oyMV=o>+XLr)R-ZGgG=SD|bg=UyJRUHHza+J^pB6C66_lXa7p96l6Z3{XW+2OgQ2 zM{lEe^A|ZZK`F~F&x*B?WiJX6;`!0E!&P8?v%$v0r)$4BHwTU&YXK>d(8ZfweHvUE z*nQ{ur@Gyq17TrG^SR;W?ViIP``BZG_K!Wsl5Fd|C3D$hf}7+0meIG7{)#irGHEN* zk7Jd5zZ}p7#suTEzg_*?nBec+(CYt|8>;US?raZLYjVI|s@Nm;wLMH5b{rR?t|xg% z3IER?BJ}%KA)JGUhlih+hnIIf?|NYo5s?iWgoFjwuS0YF^H$;SJQ4kmJW>7!Pn4A3 z@kgz6-|r;R^(RR@wBtXJ#Dhk1--ikhT5fkXl5qui;=%16hg5%65xF;*ZBWz|k=iRH zbx3T7$sas%g92Mc{LT~Q51Z_?)zdVx+-_j{AE~18xqUt-{<>8dp(OmnM*K+??_N-g zJ*f%QO2b@?02MLziX)&Rey^4ONfpCYfw@A>(7#hflRxGPzf;B2f1`@!!MoX1G3Kv} zh1baEep1EX77GCzkzbZ9yfZ;+d&K6Wzf(oGKdGXX+YccTpo$lw*g~RFbfpI%BR@pQmOOr`@i;&-a}-A4SCDt5H|Nfn>B7W_M^_+3T(8&z!mUr-VMhdlBB z|5hRB_U~JT^OIeF;fcUj;g4D=?U0c%+e5?|XR|#->+f5I1YoO>^j8n@6(1f{U<7!G z-4Rz>?-zcrmGV*n57F(8yiTkNgE%I~$(9c#5x z9r?f2N@34c8bBxPe$-0uuhmM~TZI_5hxo5*r8!NX*LY$!n}#IcHd zLsFa>JW(R1MLe+^tpz!NTIrgH2vF9)dWdVa(m4#fR(kSx4{_#yjVG3Zj>pNoX7j}A z6%e2Jr9XJ0ch4G6WWohBc3q5+ge6)S=w!~4xOrZ$@x%^VkPf+fjVHSQjVIdH&;Xv; z`vM9stN4W{>Pi12PZW@9XY<5%#qg*=&h551#{l^XYhKQuJn;>iC(;6q6|GJ7Gu9W+ zvUy??z6Bi|q|+iD@QTe7Q2=T_B9QtmC`v61GUma>S=_P zuVs3$bM6ufkHBvLo=9fbN*U`t**p=1A+vd+JDI&zxYdmL8W9kLYXLmOA3V_n@DRy= z@21h;!#78*Lh4Om>k6dwMPO;2^b|S2kogd<%#O)5nk7*5AmGCHS!wp;nUlsO5%M& z@r{Hfg63{QV?tPkjt++Vv1QK3gtBc03id~y9O>kdP<=A22EDCx7<;hsj}h(EEpo=IkMJm+HG*a*oE?}_B^mvXsp5A__J0D z@Wi#P!da7+U6XQ#zF5aJ7(*JPN;p&!Xn_aFxm1#k;%icOM9Hq0}KR$E$!INY}}gWqFq= z81FVf63nC4b#f{>&jpS|qZ;e}*?k9>EIO{}3_B8G-$A>v7DRRg6+{8Lo`Q27B z-vZoFr;+eC)>GkxvFcrZU+XNx#UZ5(=*s4ySc&&pF5fzB46$?)(gd%Ap>wJ@(jXA9 z{`ML?;)o02aBKlr8EWt(D~HK{zT<`d7#76ONFW9?kdBnWM{TOn z`lTm*yLRr9&k(%Zf3i5z!FP|)OTiX}O$1z6;t6S+`H~H|V;sz7$AOIwnCzxCo~Q)y zL~G^K6PM%Gc;ahMfG7I@;1An)Kf-3P*92h^kkE z643#|+4`_+l=WqY6->lR4aM^|U^XObuzbA^WM^X^cg^XhS%ixICj4>mFLB9^L@Dy9y z#`S#$i23Cm3xQL0^Yv*4?_<+eJ}rwaGy-VxjXlLpxn4qm*vxTi#senX@R2Ld2gVI7 zez6w|2WSZHwZ%dyfFw5jSS+M5NLW+=yqLXMI0b^Gj3P3CY-s}L2QxIX8_Ut{J*4y#0*i1k%qu~2M{Csu;EauPVR%L$uhaR=0KIrxw(T|usbA(qx5yVY?{ z-MANOn5(CQw+m>C65zZ7q%(>B!vugQlCk!JhkD(yK>ROXI$%-8=Q~eq26!UzDh%(5 zq4;kifV>t=+X;U8r^sXjY()1F-gNIg04zF%$DqP@k#T(j!Nnjhq0zAI0yfBwV26iT zAX^IX#GH#DOUhcdR5}1b!(JgrwY5ZTFt~cF8=KmKO>4oXt4By!MksnlG+IYJ5)6aI z`9Cm-X-H**;kC^4D@)^x**076dY#v(pK;Y8@>~j;5j_ zGMqwtZ-&C$L+pupUng?H(0WYeP zMu{Z$R$&w#cNmY5z(exdvE2EbNq~o_Y?cAyDymRtZxuRIUWZZM=212YBIP{e5VOJ3 zhl93^lYp(lclfAv4FGC1N;kW%qH#@cO!M?s2x z#>}t}h=!4tm@y)@888qVU^ThdpMT;K@Pf0q3db)smqSt#DLt|g{Q}s*(>U{HY`5pl zN0ggBi@SiW!n~Wf;3RCQA;>fTrf+^C5G;iQTZM+8DtCXZ1opgg!nvedyb>Hw85h@| zj}#gR_z1v6Jl7d7oVnVis>&1{aEhP<@Xba%(MS~-OnLRkR$-4b&%&ov=HF|jKY8M~ zm+wWHw69)i3rT59m1!$)(pZaWAYmGWgBGf?wpEx+Xug?pz9 zSEY+ArEx7?68*VVxG6bJ$Q#%y%n)8mpJHSv3um%D#DX+An@rv+@F@mJT{B(jZ6-lD z3-Ayny)*S9XeF~KRx9!vNjr>=n#+gfNP(Gh*%^DXwU*NNRb{hzqD!W$1jiI8m}4$` zNeFvZnd;LF8PI^ZDI?t&IkT-nxjVD%R06ejahS09SA*;Z5NL+vtNSIB{!f}~0d|L6jL#@ffB#btQ`fMMTLA>1< zcAM$tH;81z#Bl&764IQP*!|K0xq|*h#OMU|qIW@fLBYbk+P$+V3mVf z6QrRIN+SbmBp$6q0)<3qgC9FDcobF(7xU~a=56CIAfii-tRcm^bFCL8|Sx%*EmNC6h_W)Ougq#Vt$enIs0_x(R^6mzk9Ox2ovsD(rxXVJ1y?yzV< z%yAH;KfiXAQQH>@8uljBWotWjQWKYJjh0hW*P5qt%2n9_UUaYbXXFaufj@he@%UO) zdsUG_8H#Y%`fINhOouW)UbGMuEkXT;8({b}J9roRRiGnsH5Q!htp$G>|tB!|_F(q=&_?_@=4PjgTo65~ErJ~Wkw4OiBm zjVd+$TvfYV-9L^D29=FDqe2)h{$?mIX4W;6>SLHkS+;GI3I4}t@}X~w#W$4fs-gB% z&^zg{CK|STC&%$wh%trZ13tH+=yA=|V_+3giVi!8FIl)(G}L-c3dumxZUii`AtN*C zy8jbuMA7|SY?J@QfEQ{Hv+3@JXW}GnkE43%<4%pOqtpxhm`Cza$kIc~zaDI1d8 zm#A-|KzD%el7lKuKxOb!Hv%3a=IEJ$eDfe1D)L>0pG_&(PCCQ*`FzSt&ECwtHqUFu zpA5^TY@Nu>f0ve7^U@&omA;Lj$WnUB+syXG78M)#HG1{l=$A&RuWg>D@7|xDJpbDM z*!`ou8P>ZyPhIWgc>CIEf6czy&U34sU-LWNqsv`)cU`{PHS#9aySB@>x65y}izM2u zd3sOQrtVOnmD+wNthW2A&NiS^j!k!}Ywb>W%5J4fcY&RAaq-9AP=Qt|QI$L0$!X?jhc;FqTvbbbVE1d#^G&OK@m@Thn}tvc6Ay~?fXlu z^z*U)uUGpQQu~)``&WAVS*!gZF(yQd2{YYdOo#7OeghX{?j^mkq(g5$is!6jTH(OZ z1o&n%@DbtwuN@OfG!i1d+uS}NeeU#wV}r8PLHW8t#lFFR;~^5nhJI`nK8r+Bnfpxp zxMJLJrl7s}0b{$K^?n0Fbpw`lJ>p6@i9Wa#b@-htNCrFNXg6}oZ^Vf@;!^h?w+dN& zhIg0&=i>LXnA~<_uZ|4!lLmyJ4MfzX95n?UV-3f}q#pPCPg{ko3A)&1iPmK4GhC3} zr1q7u17gD!cRZq|$E^D%)z!wYD@|$L9DhWe`p2!pztl<@7bXX_+^eW#!&+|je!~=i zD(;<-&{@1C;Jm~4bML5X3pKfe*W-&PS5|dLE7g(YNcl4Uo5o0{OTe4Uj1a- zucWCxXCJGi)jxg0UrE>h>+JE*F8yE6ef#SEuRO%N{dVFD^*mpLzbTybU#N@!8sVmR zwtuZw`m2XnznIehlP9K41!*twA799ElL${+T5ebv3nekD9$sU=OYuzrQi8d!Q}FH|hP`pSN_bB!mytzVtbXz2UK=81#a ztRZ_A(~k8%R%NW71<=EOf7bNfh6(X+pY6YW{Py9C_P4L~-=@}mo4flBRLu4e0iMVQ zZ0eNw5e>OpcCJ?s-`jb))eqP5<*VyX4LrZ1neJI) zr7{P?ns7a4;y}SHulNBmgP#WRYz)+|@1xJxL zauy!jreaHmAMGduTC26i!Ia0(;$1I)Ai4tr!M2?$M=uwhFdsRrya9R#ZMBuuU2Fs< zZbsP9d$xqa#f|xXY!%w)Bwh8HpPBiCt+z}s7AVb1C%}wx5AZ2|T-!7q+-~)`UV?r4i&F6W`-?s{DVsqB*5#fIHS+*yZ z#G=aW6Nba4w(uepb>B8(E!6lfA`lE-_n zwAf_pbG@xkZ#Y${KHgky^-@)2@eFH}=RAn79qk@ryf+5D>4NdyO{3n%$%vGq*~Wk; z#p$SvfKiSOL6~K$JgO79M&px;yk~hp8~#N!X?a`8^sFN|~>5?4j(k)z=GNCbUjIGYz7;qJ4;>9IZH0>y; ziVMH1SylhOt;chHHTmSM>`oi?mtO$T=$&~bQoty&+|DPg$Dos?q`|y(u}0{zB-C3) z=2{s~4ayLr$F8K}P9DOazRTMpg4E<2i;}Fd9Tjn;02>(AdzIX5TbL&+Pu{c_bKVrK zVb}cL(xI-kUlWabDDo|em4(td&5!Vw4CCrXh$3ZdzUq1?ZORkDB1<%mo<~A>^)H+s zsXBA_`S96^7;TpDrWZH%?7yE1?Tjcoej`6P(n`edWVv^MN8;$^XBvFllSa#c4l40>OWcF|1kUS) z4dGavjBd`in2!=6e46@rXFug4h?Us=s^a|`GIgHs6*8UY`~2${7v_b7w9-SoOLkuv zy$kTfTQnI(yZ-2INX({y8KPs z;2TVxkT@3$Y!wnAZvW4DB7X;YpWbnv>lJ#Nc65Xv2tLl2t*$SBs3YQVuss3vuTkT_ zN}dX=$D%Rclc$OpxR{i%%qG#@QbN1s#kT(iHS&Bb{y>d#0BZczTim;W$8e*N zg`|+}+A5+A9(!(!@b~KJA+`S&I9gin_z4`h{RiN<{fEFPEbj&YM=p``0CU`EX!sZA zxMTlm1*3myGP0SY<6oI0dGk-^_)7sblDKt^IU4@oGDj`0Up2=6x4`j#h#Eir|5q1(M~ztm ziq?M_Mic^u5#82?5t)bDOxUPV+4y8CfEpc>*3?B^05#J7iW;Z*@FaN?05vj`b6d9; zIUJt=lBbsJVZ=ZO%?H1u#*UZWa&iqS4DL_9KT+c?KwZ@M6E#xVsIeMQ7q^R79Xha` z%b=n`{yke=JoiiTRQiDG1JsE=<(9SNX>I(IxYooy&v$*~dk>(-gnywf<~8xfvXiG9 zx3QC_%JQziqsIGm2JZypUY0axfvSn9S*hxQO-BVaf1*aOzoW)>wz~L9*`)#4kKBGk@kE$?1sdLj{E=P#C16mZ7MuioL@qVt^eZ5GL6IS%Q63t5DH(59WQNg6l2| z;U@8Q&jun(nUPtW^`IxLn`TNcgYh5M)&1f&ECa%h0Kv`z;L<9RM$cak3M_M|BB zFe4)bsf0Y`@Pm@Y*L#hFxe*ZZi!Tm5xmJ2uj(F6O42$b|HQ740XyX$vUfe(>r7L-j z8xuM763>@z0@IIF2>YJHX{v7&Z#LxDR&sRS?*W$RN3g-Nfd-0O-rZ?M=>N%310)5(DiiTsxLw>@ZD6&lm%}o=!mAiNEf>}@lvusD8KrS|B=Y;xC-#AUq1 zhcgGZAgt1bhwcVt4`Ch=(e5#>`Lqv4mg`;wn2WrJ&My;?1#Qo~kAI;;jC zWrG`%pQpdvOqQf>Fb-A}$bsf75$_(gG7%fZ$>C9_!cGU^Sf;V*PiL%#!a!NWZW1KE zBQi%gE4obMNeDd}1bv)jmmmRMk86>=!;RpkA1|Lxp`qkufoZfoL1V>Sc^s;q7JDxuH)fXZw{aUWfV)Jhty^)HvA1d6grJ=v=**o0en<)sFXgy={ZWUD%i>QYYrI z*u_vn<1Y(M9p7-v7&#k|7yI9;i>BpO;2n^d013>(vGSVH=s0Bx11d^y6u7Z}#&3C9 z!p`q)J<`-Y#G1)zrdZL)c`ju0(8U4VO*LKyV}^WmS1<3~g@%dso5xApsAT;Y}s!Rz5rgym*9Z6~w zB_7^>SP>s{Xs4sdMe_XXE6;+j2RU%^TDK@MOs~)%q)QIwRp}(m#sqK4;%m4~=IN36 z8Z)$8DohO}uMXzstk}bKW_}T6Fdd-a>re(A0HF=qIj+DQKAq1s803`XeDvONHe|GA zY;(y{0EXJdb$-{7)VhmMU!5e5Mel)oq^L{MK^T~M$c{d4E(fd9X<}D3q3Zm6AS!L) zkvM7#qwi9{t^v_|%FQArENx`KlrAqF)T~-Hqt+-8JYR=o>50Vp4rhLwZxHvJi|uCx z24^mERg!kv5SG)VNa&kgxT<})EE3ic1UapYb;Uc(-~sFiaW=!<-ba|GBLJ_EYk|aV zjk8t59bjU0+r7>cI9`$rs%NqBB+?9>bmz1m)SLtmMnzfgwl0V7^N0YQ~ zaqAht^Iog_JOpM>5^>%b6%v#iYlA%SoM|{tJI|X4TRx1-H48y^1ayvKIc5X6NFg@& zIA6FMRTI52LxB)*2sD7hl6(cYln~r$?_!4}0_Wb^q(4{L_ z)(C|>0SZ0wg=-v-IY~3(&GWyfh7(|tDP$8n15npKP*5{y=?Vl!3!9bZ8qReA)Ws1x zIc+<4;mwGM7V^yna$I*1YVNA8I_C@8d4DI5%u9edd1#u65HpK<=xKx`!hv|_i*^HE zC(slr3{V%JwgkLx4xeF$PlF<+@ex_FsyW?(dFoM*Jfkic;Fk794X+W&XXG$Q1E+a6 z&br0Fw#DO^yK0E+<@s`4%;|sw3kYNbXO|Q1n^Uw{Vsx5dM5bqGUv4Oj6hhwzS|#J^ zDVVJ-xB)x`W*&z=PXT-3_~}@XkWcKDSdt(@dLDd31`KHlg_*H9#@$I$?ub}C&c+M@ zgii}*vAnIEDFARJm}TL)Znvnj)x~g1XD;Pk3q{5NDW4dJ0EKLn!Lda}LtL+N6x&<$ zGCG2W0EtwC%4+~^)X_+Q#c{l3L?XQ6Wsi6qX2R`f+3I40EUqROJ8Fix*`(e~!;aA~ z{M&G*?LZ)4_W&i%W=&nR5A)sJ9?tnDIuqshUfB;JacPuaA(b8_8;c1NaPk*kJXxky#n1tN?fv< zztt|p_b{A0kA%$-OzrlPc*#mi{bLw$Q=InD5$cE+bu5WGQAwTpi5mYHMr=8JW&T&x z_BVMI1+{5YPj z2n-`uWk^q8RctbMcxS37XMP&b(2PjmKtW*IGdF2w>H^7A?<|Al^j*nWT*;T9OUN4( z?Fc67Yb(2YI_#XC8I--pD8mFuo(kt2ugY}Q;h4q+bExEe)4;lssJ^3+5ktrYBJu(# z_X|4P!YF&u5=|gb{glzua**qcY}T+`Uhq;{WP9%LIMQ19%{|?+XFRQ?dZ*qp-a9t!)bBw4LXm>t^=N7)ryOXT#Z$#ZnL?u0dju;k(Xy%Qq zttEbG1=L0Obr2Lq$y?k*Pd!AnB%r16J7wvG^~uG;)y0@L{vryxJSiVlOj|$8^@I+W zc1Of9i^khon3Fh!6CRM(I8L@hrQ5HmMuG%o5z_APLIQQ?yL;NVw6jTA4@${<98z(z zMETY|RD1qN5_r86^)mjhy*u*D5y*B5dr0wiK^}^77kvh;MY|t43kCb+Ekfxhs-X|= z(?1&;qh^seL9q2^Xm@$Nb2}04x3tx=fH^scmV2>XTXCpQ1^E`uB^~})sN_)uEvNm; zm@^07Ag!nU4vNSz4g!znSEihyni){t$BM4|P|c1~t@9ATqTpo)Vm}eNnE}6yqeUSK zBZ#mex$>dbvNHbZ;YVvbSw6KR zfaplTzOpQGj-UZ|CB}s+btb4S1(@&(Y&=EVkV$@E2K=y7KitC3Y^X<(?vMo|hmGsT zysAF#yg$@hbygX2fd(ltuGYsvI22K&Wbkz&diz22a3rY4xS_5(m#9$oah!oCq9qCF zN0Fd;;WByzsAFdXics5K-Kbbo>@pYd0rw#74Ytb*$0=O*eka%LBIlEKD4q%Kq1P>1 zf{)RoUgE%D+a{)a)BGgX4Foa6JbYI0U{&ER_zCt<6zHHa^{{cZP!Hq!EL2?i(TS9@ zd)^I_D-XX^qK*=>BirG0%|_u}#UuHRn|+%-Me>2XsyPNiKtouyhQKQ;WtA(fdZ_C` z3?XH#t}S(}3NgCavdCK%nnE3-JY3vEnbxdc$;ZRa%@1rl z_^)O@R4mz1Lu)B0dZPJoHb1#l8Tm0$+XkOJMqy!e2vnK*B$DwDUs;23%cU5q$N-H=^2o=;Cv$TOXM#iP(M zWY{493?oKo7~6C-gf~ujrKrp2RlK9wuD%A;MI#$Q38M^}eAesmwjB}h8}u3%t|#XJ z)aaV-keYr=tvl$$egDmwzE^?dX*W!`J8JWjGppV4yWh-=cPI2V#$A1rT>EB8ib`F5 zLlb?QvHNY-vA3F6_GF)WTL1vc*+Ye^Z?6JljtB%W=J){puHq@bDILDC3+$4MD@%RX zcvZlZ7KL;Vz~XDq_-dcAL?4E`XZBdXX$N#+1bmFv%UHGey4tVXpmIeBF?|(uhl`1N zwm$Ew6S|LyWifI8%`l?fmi$48xF81Mt)`wSiA3FU$bU(x8Qa=#NCp_#%d+I#sN|U}~ z(;8PME6+`9cTG<8O;7(!p8lI*#DN7=K`O7>I$7BXn)qT|NNI>#NSY( zTfb`B7ayxn%x7PSnV*KSU-!KKRAu^gS_(*>{yB{JkI7S7?HAIFlAZsjpfsi9;&WlK zN~h`<<}$v<0K0EQ8tMXFt8 z!Gx{G%rf+&#df#6l(fj%e^@?5_)@-Q!NJ>h50einwC5eI^}a5AWAt#z$){BPTl_Ls z_gzCGKFESVAa@PXC%rpff3T~&y2{djyMC6K;I6^p{_v#`sb)QTEqUq~6e!1gec1HV zDYf2hY{x$-y=*ZpPbOSLAzEQ!aTWR&7L5K;6; zyv4^Kd2i7U6FXM*GG??zu$<;{ta_ZV-P$3$(gcH`_U=|75VkoVnaR1nc>Jt&Wamtl zS3~{A;Imhf2CIGcA+S}mlDn?7&1QsMwk1dSM}g0$k48xO`(h!c%Y zDqPi4#d^F4cI8W{A?UbkAjbjh!(>7S1|Cr5HJW;fa5NTlxzFnX&AMIUHtkYhz#iK9 zzBos`aIc{b?Q&V6tT4#Txw-AIyl!)V<>kRyNrmmD27058dRzBzKQKiOF;mpkNf7LE zWQ`kcKr>X5J@U+H`$RMxXf%mP=`jO!RWtpq1}U!;jUdVy0I@595g$jGk|9r;l!doS zZ57SjYGuA}V^OA>vic(t2N><7sm1=1Pmiu_lQ`WhmX1R*PEI5e@Ld;=UM%a%b0(R~ zW|yKwMPkfyCHZ68M??f-+qY$!?m3Hnb+~-E>|K$j?&+9H1X2H;Sz5d6R-YHI&qjwF zf9P?@vOPVg`9%>5asQ%Y-i+3Y_t>Q}lNU~#lGdZVUvxwcGH4qj6OVvNphTx2o7Bc3 zX;AdWPS2N@wJyCr8nh=^}-BlC$Rd$)fo`sz;I))(^?=)z=nf|>Jn8Er7 zXZ4gW7IWG?DpM^Bv0#0 zbcM>ALPUxHb+MaIc=}Iu@n56HrsMqgEA*8vcSPF5P6$3!->Z6~BkHu?3E|fjdv}y| zM7sr_5E)kAr`g#NbEWBo*q4fZT33!{L_lWp?<70DscXeDmMxLT3O}bRooz{AT0kERJm!Jg4_-@x$l)#+3o7=fyV9Z zfyRBp+`rPwbDM>16eNLx#(zYW`}c}C>xsBpi5VHn{^3S`N0n#UZsfL$hg5!ZBZdFT zjoe}R-HqfFWY08yN0k~zmg*LU|CJm03#YU`b@BWK_h@DIQsWJU4GF(+N&r%l&l=zH zJV5a{@jn+M|Adr(&#nFtBV+$6M#e|DRm7jE%WzyPuKvx9lnE8qyau?Diso_ObE}&U z<^r73{P))Cwy--FB5nd!Hlh4iN@QzG+vDc{jn?Y_kXHWx9%$?#Fn$lMMvXrHhk?c)p;ZzfM)E*F zd7$rNr0w^CMjgJ2GWWmI${s#EBj1Pv#(EVP)_O^SNF4ex(8%w5Q2yHQwDKWajI2~4 zanD}-Nh_0n53Q!KX=O!A6BP)p0t1a0gFLYOT4?p`FSPRWGZn_laj_p_WHDQeB(nz^ zQ7?lo2>h$iYEIMlfyV5u>o63ZE%GOS53Lp}lh^}|fEY=&h!Q!F2YJ5nND2fa!V@?y zLkrAlYCY?$x@hP7>Gga(l@=;r5E`HXZ8%%jAZ2n+en&1E#uBq>zh#t@;Ubr#Pzepb z0J3fG$<0J4OwsevrxcGhZ7Q592^F0zI`U+%!iUncyU%<$`07;QhcfeHleaB;LKUVf zG_IbxV=|OeI9)YWHaT5A`$%D?=5yznnc9Vs!kN02uah(NAf)0eMUwSr^mf!%e4G*i z^l+c3-BrUI}C0;hh_| zbr27S>Of%9PtD+{+-PML$eTd-254)1i)^{cOSsPZtP94h?erl6#An5?UW5DF?uD&Gzjk;LIWL0tTa z_jQJ7u&shLg5nO!9kd?DweAL}WBYynI^|FnEPa4)Q(O?zN{2@QM;6;;9*lfK;8Epk z;VI>><;`&qNsSEVbP&`R=4c9qG19SK)?0^Nxyev&N$zN}-bU4qa5LK$o?8ogkIf0e zF=GwTzUJoYrdWw=sFV%^}K9oj1!$_uviDs5LRN zMGB2G%w4}GMv^z8Nv+PagK52MmlbmXamH^6HGvi+#b0mMlSs>M)J880Al3z zA7bRwA7bQCRy#F!nyNUfL4lURwSLNDdxHDbA*dx3ZFZvI+s8QwHTRivrr)jl+_F?CVE_| zYRM&Fb9T5e$_wl6lURKVBWi)W2KZm)g$~FTRY1hC7b2^P@5R)j50!dJK6-iVBgJPh zK*Yg2o^+Rxn5)@|J|0XGEWN@N?W7;H1?T@v1zb}2Vo=oWO8dr^^xRx0h;o%T%t>^k zq^qORwI!db$E69#K}SQv5ns(mC3mhIi`N>8?_ywg+{Cm8nQ|_7x0wEyp;gYaFtJaK z0@B3k%hgAv?D0BCbwY@e;BxQ6v-v%xnC(}Wm-{*L2?80Y*+6It#}P(;gFxT(M$dsh zOssmPDE55#(Uo^5o&c>>nvU`(L4nF{GizU+>t=Va$KukJZHJ%zr_gHMSd1OCtsu7mTYPumSg%+6!UurG&k z*|WjufPnULESeU8!G|0T;(XqIqyprPNeG0b2SXh=_N!k}Hvl=c1e>BlT-9+Wx^Yis zFkS+|DyKn6f}3zN&Yiq!{!?TvUUT5rP2EV{kohH^4f9#+Ac>fyP$PfahW1Q){b=lgx0MfocXhFslN~kc|>0 zUBsAs*8`zdC-p}FtyB+##BmyT<1C!~t2{l9QdCJ!q32}%QE|XJW3a0`u2MM~F%bJA zG2nGYc0mvfHdpQwTRd`1nj#Zt9#~ya$ zZpQ@}fHJ=iG@fLjAOXOZ9Yo5VV+tQvNkgxrfS?;WxHNEVF;XrrO+7j(kMd?A92n@? z2)L27V7v_O`#|FxAhFtUP21V%@FEz1m(d<;gN_5&35)*ilt}oI_)TaJD+c@+?Xox% zx7iR>b_F|x$LN?{YjVc|dYtzr+p3qf6dDF$w-+mR* zadFZt8d7`{2(5-*!%iuCqt7RfQ4+nKF~DRa2^eTRg3HTiqsoN9V64^vtU{1`|NO;TAhfE&b|Z(G;r|d?UHrG9)z4nkM&y+*e-R_sXyuaS z&(P{y+M-vQ+bE4k^Czu*OAC!#3#}%nlpZdwl7A^+2O&hR2fiZWFaaP(%uL}jELCHH_g z$Xu8T0L#DvDn*le|83e;BJzDw;U}-c_=$Xma8Y9$?W_Z+la9~?qN@eq+wNRI>Qo0u z1-3g6xcjt{a!1}I`WhwkCm z22`4MP2C5?i$X{ffdFgio=A=X4WNjM+;WtpYJ6|U@;xM|;C(n4r%v@C-aSS@emnx% zM$uLULFiR^$o9KjJJGwD_sPIOrB|VdF@15Xo+ik4-G;Q1i)>YL4*?vH&%Iz=j=QC; zei5}B1ldh5UVK@MlP`&SR}oW4Jre-$pl_Fbmk&4M@H|Y-q6f@{bIo~!vWQq70yTYS z)%*P5f&9=HZIwfY_Xp)d0Nsy|SYV=zRHVT@m}%r4g<)o}0k3kmGjt@gER0sT_!8-f zOOqWguqPpdHLD(OptfwFT9}oGvN+1?mnz;?*Gd3NAqe~0vJxoM-eF=!!Yj3_s81p= zA!KYUMcaT7eqt6pAXHy$P>*EX$?1;hO4J@ZO1*Qm{_qCsy)|=Eo>X0B48ylG{PB5$ z-_1!%-2=|@1_kP}P1(IAD)$Qb8V(XiuR+oqPWgadpJ{N7tQC7)tF+R{C}3|uZtF>! zAfzI7>P8AH+uNx%G|aA9uqcUZ=9V@e9o~%Mvh!{-JexiB79oy%Xs&pBH-_=mh%xT| z5J|Z|PV?o73^`Ra{IOnB()6+)i&R%82}VYM%e_QP`bCV6-rR{BOlO9g^EkI)S?va zH`UFLe4p%C;vc;AK>l%w66ZYtj`q^fyBM$s6s-O(4q!&qgv2pL%6g#JObsKzPW7}wK7h~fM0@z? z1#o7^6CMLD<)uk_&Mh%c?iNnV_5~FnP!I*G6akgB zmAZfR74L>K@AJ(Yk5aMAAS51Az)R&Tr1QH{%{Qa%-!_U~?Q~jAH*D*u&u<((lCr(+ zb={eC;nYq*jBJXa0g`xTRpyKQHYFGMHDc9zn=a3*-DED>nXBp7ySk${mxa4#hKjyP zIQC|?vinAK*R|9)DZOvrhXZb8=PglyR=(-?`emTe)k7WTa(DN;7Xu(y{dX0;0(&2v zv}5AJ_){uHd(L#gj({$Rm;oWzca60@S2|z|DDJQwEl*gxdtHj(O^n>|%*=bSzqe;~ z{f1djo7phToJKtHSnt(7VuKr(1Bh$}lML&d<>Ie#!kLEl&Ry*{N$VR+UdkCi18g1$7feO6#wjdw<(5)@O}^7Eh-H z+JW``h7A2CpN5aYXk$^+lW!Ntn*63({yQ;}b8cd=&f{L+sK4Fx_M4N{c4HH!9t@?a znL8ejv}V5g%`8x7mg;6!`esw9h8}pH2Vm zK;vrdr{mA}X{Ak{T(@J-%(U}?ZTqyRT)$}p3$qu#5}q$imV6an zw>a_fYl8L`5C6sFU&Tm(R{kDZ-B`D9XNzKt_;RD|4gclV_{FMU#mKeLYD?P6 zpP|)H*yVONHm&48zT8jUvSs zBPCBh)lu+g?d>`8d8{MF@DuFzVE}jbaHtWZpMG?Hdw(^#?CRD_cHlzXRw(}HxpRXL zUk*N7b?Ln@a<*i%y_B**^(h#JrdeLobC(xpt8)5TI7oA3DjqCB;@stV`Mk8OpgZjU zkay?NP&fYn|6em^F_tm*JwtYqC|hJK)mUOmWlf`mkVwkXGWK1T$`WH_U$T}h%P4y) zB_)NiZ-q9I((g4?S6x@v`?}u0&-e2^zjJ>5;h)aQsUyqWUXS~e=a3NxA}T4Q`r|yU zBKj+`RIa|AeWO1_Rt+xf6?KmkvHz+dLkOH~otq40Oe(H5@AG$vQV4;Bz~}pXLYO%# z0J}Ob`DJ(EGe`P}%nBQ999a~+3AT>uxOTixP!X=R9sG(1NTL zaWc6#4NJBm_$HDJq23aPqnegzxPQ4_sPO6Q_hLz>`;Onmns??GV^8;atm;ut_W9Uj z6`vXCU?mt7cPj8uVqH=ZhU)SLwUp_H9lPqYl=c~*?imG}PG~^5@Zm4ajG^sOA*l`= z_yprUJknG5)lexttSly$#q3&%vk5?LygvhAJGKwlThoo@G8mdU!qr(ret&Y`vBVGZ zB`OM7ht$Kcuwy+hHG~s{jj8I&_oeDQw(zTqW2SC@u$N$~bK*<7VyfM1CkY;uOfnTd z1rW#C8NB!24bu-j^#0LNkzq9ILKOwYXH{BW7z79bEclzxBS(aLGNh zc?%NTJ&*8#-0Oo))HHfvF_Fa0*k5t5rd0SG}5rvPBr z)8W8G2Mx*k4KIT>noLIr17MzV$W)CKlX z4x%vdl)W#mBp07j8t*mtBEf6Bk3_H|01L!P4%>ih4s~xXzm?7P$6b`*!j<2WAdV`T z3s3EFq)pgRYP7X-P5h5sI9pu5`G8}$E*q;R@#wf=zg64Gw)2@mkfhHiFY=$p=%Vgb z7GE1L*yxaKSc^O6W{!WU(eh}gU7OGu6fO-omDl&k0jS--8!vV~HBFT?Df_gz-_x=2 zeAN3R!%&OZe0^Y_tM;Cn52<%k=SESAf&EvN(dstsHZ-4B?}t<37zPr9X>R6~^zu>w z!h(g}pj-CJWpeT+sj1t zZL06qj&+BMH4n4#-_a8*CWP(Qw7|rL#frUk4>xs9;mE+pO3t}QnA>0FD*GR5rM(z; z4Stu(OSC@aL%wJcR zAY}@P$^HXns?aG@cAFGPnFf4pKU3xj1%Y+SJfJED9*lHU5tq|bRyEVywo6g&=#C$h zX|P6_2P~wFbX9&(rn`+asF_}7Ds;^}F7D~9aq`q=4nfo3lwMWL1mx($%Rf=(R*$_3 zMkoI6a-`uedrOyf#|&2xT5r7maLf`<)&JHp_r$KBja(1B?mzu~Z24Qq47qIdAJ0bq z1~K`!C;p6>^qY|<%l>*W^1nh%ucB{=nVkrxUFnEfmYw(=F$;5wE7u+Kc4gjQ9TWWK zdYv-=bT%@)w*3#v?CuB0mN);e)Lp?ZX5g>?k~05q-;8{T!~IH`L2Z$Le=`zyu+xxE znKZ+nZ$|2Zlu7tAWp;64aWeGAYnQKM#|PQNhetrl>=_6Lc)a(DdHzb7Yd0frfy2vr z*YA{>_$y_m&?&QWoicgWDAQkNjWS(+qRg=eTN>UUA#ZM38(!ug>56MzyBP`mC(6uf zUcVW6j82(N3bKd(Oqo>r&B&~c%vY6+g$R_lCK48xNA3xJqs*+oQsy=~W!5v$DKqp} z%Dk13>cYGA<8&SsA?NBGz-{!bv|X~W$gWkz;1DU;0u}%yz>60CMOa3DBMjU;{{wP zmcwvUkGl>5p8I59^s1ct`tWiqIK1R17;Y*ig2PMm>UeN?$&J;+N^_xGvGKqWaCqs6 z!B5Dqup5Z8@$UFE9oGyFFGGQ~;U#))c-hSY4llb~4zMV7V37Q}Fdc*qd3mB#@B8o) zLD^9|11+1=&?!?kCB3U;4qAD0`^8Vg%VyZx@RCKCYM_XWdV3Fo#B5ch^@NE+rJv*p zL1amh2V$`>b6h%Ds8iKvjB(${i9qRhtAwxvT)lm|$l_RVcqz_6R0D^X4uBqbbCQkX z4=s}n6S_=9K)LX1!%Msl$98YhAH&Pk0P#}`Bw2lMc-avs9<@N?*Z*aB8T;$-^7!8j zFV&fXO4+r%zYQ<#xg<8W@UfI@SHtPUO94bSz40pU4&@huFvT)6Tag5Knp?2&Big}y zL`1qWlof-zjaQ8Kbk)T3q84@zv)VIV!bxx(cwVo|XNNr}eQ3i59YZ}D1slw_LDtl= z(^A0x$_*|_2vNo;sH^*G^%IHB@R56JCJ8{Vyb$Y-kD)@b@t0`gks`e1H*;>0Vo&;w ziEjW$eV@fdW5faRYrCq!C-JdYR>i3jxfzicCISS8wzhMK`6F*|H#3!K;vLro?1w2_F#sg-cPLOuzOJ&NQS#2yB(8etT?RGX z(VeB4B72-R=*wbu#JK##|AAxuA3=jHCn@kbS+y7Ey90$m{z`*r~ZN zh^sZ{r-S&Z-t4nR1Bc$E)ZIllXP)boY4!bN7PxevG~qIYPyEsSGSLqehxX3ss4bxE zyr~y9&`A4xWK4?<-v;zzS95Uj7+e7H3V>*b!`@Bz8iNukQ9X*e$pbfN=P7=0PFm$~ z#Qjbcl^U48gQ=JL^F~=u2B}SWk4r8VQ#{R>F0X9e+b;V!_*D~9Q0k+6xv zWZ|7^Fs*>ahW$+xU_Nbf)#XESRsDx(EFllRtzd68N^0&_h+pc6e7joPo}=6+$@n*?LN%e-L@Ykm zR(wz{c0Ak7%O5i=!gPMhU);(!YIOq^nsyXQA+TP+Q~a(!iB zp*4&b-wi<%{F&Qhsv16iu~X2D9s<~^b!Dk=X{OIKXfBk;HDV#8@fzw-d(~YjH@7gO z)Db?mvz%h&H!%r*qarj?`zkx_P5jyI%(ipo$UXl^nP9F~^##;{Sbh95Knt}Q7MQdM ze3bhj;h-8+tgl#aXR?q<3dP*@LN{3>T5G?iR9 zSVN1@CSHz+p@aIUnI+%dugL6o1cSJeNO<@Y55&#+b1>0)YW=b8v8=HqSRNr1qcDFa zg0BI40}s9iwfWo4NJg6HKx~WZ;2W*Y0B=-2rkHsZycrp~2UEfNee4i;FcLyP7-{~@qzgP4>F$9^f_*f{WMYC*8UBxR(I~1v z3oh8|DDy*_WhK^^IV%9#6vUvzWNL9%BQFG`%zb%*40}UZ-<+eCp4C(HM7RTstsVwp zA&aVX%ABAEuYS78I^NBE#N80%bg^WeGV#V%c%WxD*sKB;&DGEJnLNZ?$W;jomPUt8 zS#o;#W;un0snH!%Jq+_=GO&1og|{kHS;`8T5%ehw?a~baZ>VM21N(_gFBe#%VDxK| zr}0rBQ1bJgPpU?z*645if~V+AB^mxoaWvV$=~EZH^pg+VLjo4G3EW&M~$rt$iAn%pdP_T66_ueIqvHC`zn_J)W~szFwJxag2PMDF~QQS&ok(-0n`nPbOUl1YO=t~ zkxQH??S(Yo1;%N9sFf^vHJ~>8lMf?E8NQUdWwV)S%9Acx0jt+NLtp=+V*m4I&avZaHRw3g&|i9q*uz4V`r|Xft0CH z#N5e)AhJ4B1DQQ20;NpPaOid{Y)FQw8-Ry|vz##`n`2r0WRhq#=SI4jhd%iYGm*zW zo~Ieyco->rp>W(4jeM)l!O6J0IZ*=CBMrdFBlm>n;kzB!WOCt~N0{Y?h z;O}eI7GDKjd2Rg5gPm$hG7E5bObcb*n}N^0QV9oo>4@L*JVrb$< zZC)Uko(B9B!2v9U{Y9lWGs1TzP1SzQG^u4vJ%tAWl!CZMxIn(NUro}rn(?(J?55lF zTJ3ep*-;s$l#k>-#S$cVZ*l<`>8LFRFD)*mxvJgBl_Og*llOZgXa{9AETX!R+aOp1c>;hSGwYR|59T^}Cd9;%DB(gfxD6iX(QJm{9DTh+xMt!ob>Rzeteo^8gSNPhe zK?I8u1yIlY0NJieBo;2NNv`y5u!zjFEogWx*sN=u@7&}+?cSW4jDBnYAerSnM`FNhhXcG3-v?Kk%8E%DNDv6Lc;|dqjz^!YgCtNYWt{qS2UP{z1AQu z*Fh6{0E*{3!CFN*dTrRTjyym@X?DY!NN5WorXv72*JPR{=Dv4*xK#8Ie4I$U8+OdS zVoC4DSa^pJ;SLfAVA@lV6H!ngP%?wL_p0Nb?)%EkTVcb;8F$9EHNSkcfuw!b8oKLd z)zERqIO=NGWIi&Kxh&kUT3oo{+2=fLw07L~nyHn$L-G$a2YMt8A5i=-bo-RO0e{^& z>66m7fOs9I9mSut>pWn3o@MW*-U3V5tR{I@<57KKl7~jFSO4wIAYd;K)YnAut}YWt}ZWnngCcVW~JzitAye9$I+M_OOR{fu2R zJ$3orU|UwH_F1Rg^-FbqNomh{*V?kzJ2SiayEZ$+b|_7eo3npep&VUMf3TWl>=#=^)I^yUOxEpvRimS zZS|~PrsTlWO~Po}!DsaY;C2(N$)n@IxGdOsDbpw48omp7w!~`?JzMT5&=23 za$;DhfeSr|c|9;JHpit&I4MklBOVOOZyS+U;1bqLv@IP*PzE;Hj@sx91UrmsG>mEv zj_z0;{iE@EVGK_mGi>`OI)r zCS2zxUN)rOFab(7%#OyS-6YSw`gg-iL?hCYrKjq1!ynPDRc7(@#2!-)=yHofHKrbLGFIOka5tZOriM zrvG!4NxvESjWW&W*M^sHA&Uj#9gs42rP3)gT6leU`K|H#&f!6t*2PtXu+@8~$Ju+* zccs-jC2Z1U$_o*;RiWwRFmrPibVwg*0rxr39E?{a1e2uH*7|{z`|EdmN`RXgL*1VnZ`^As z6~cP6Pj|0Zv(u(DwS#Z66GafEIgKg^Y^J}4XdNfj!`p)$C*r^Lvgt7|Spq9OU`t3m zU}aFb#U%DgJjwN`<)o05lmw9G)u$N7eJV?SD%GnWGj+{Nh=0n;Yaa&R2jHjK_;^j1 zJ~R=(dP;ME2l~7k$LHY-{=Cl}${lDyIk5@SX6>G_fH+`3 z5{ttsJQ7#$QpmKUjQPy&aZCmP0$`H3;>OCIBW#+Is+R?l)C=m^UA{TfyR3k{SY|QOsn)aO*6eF|GdNCV|(2)|n7h`W?;i z$Jj&dP4@RZSwAHKgj738$PMMMmxLaztTZ%TyvOgrM+DrnKOea*$#>?Xfmm!RV&V0C z)JB`#UGteJOzMjmq>{OE)<+Ii#lttE zOOpG0sW%n;`2eB$eUy%w;9xi-4kBt1e39HFwqvlwm2*E~_PQEAic4BRhmi|zXouc( zL~1vK)!s;3uFPxfkK-{i9Nrsh41hzA6Ox)SVQMuUrdQ)dlRrO@-hJHgpcw4R;9dzS zYjvZ5y7;SA&BqkHYK&|bA15}#92A4q)s2tv^dz_HUx77Dc9uG)t=NzeMgO1PRxI8rmRfpbu*Ry)BN*SGexog-b}ZB zpMQ$WsZ0N4ra$JN){+7yO8lUi{#>d(rYh#FB>6L&nyf8APnrt>m$&()Box^=KnUH{%HZaj;De; z*Z!lQmi*%g^t+$N|2zT>zgF_+)0n?5K)X7AFQ?J9?G#u&2Q;TnxPGoCko)#gmc z-iv+ro5>_-Do4-u+Tf&pR~~9A;t-8_Sq5jh9Hz(9yeIN=aYUY$I{<+)icW}=Pl`}H zt>0v*ndIb=C&Ur5>_`dBdD7wPtg=4;eEe z&D65}G2KiR8NgVrLWt-U7J97K5eJ$nQWqt$W~P_vW*Wh=W~Mv-h}Cwt9OOHKVn<5s z`);PD|Ith*f0(JF#}6}IFxY~mD0QuyX>Y9P9qFfZGo?nFgJx>6W~Nm;>1L|@%}j}0 z&!%*d<=ty$dW1kXQ<6RlXr_6fnI2q=)qXcq;|vZ>@1J9}x)P@s0679^ro(y?F$;hI z0W{O&KVr2B|JqD396P?7X)~9^_MQB6Gv!`0Q`urLR;&0eR!bn+T69C7mSQ&}WH4qd z;QW))G#Nu+(7zMI5j`d($o6p&@5JcyPeTh`cD@7jyO@NnXD)&BPbUsR`uvlE zy7KKVX8*pQ?_w&^=bxS6UCgoXcQIMGpx@`8w)^i2^wQ^_`|x-TLOkZ@`DfPp{4*XA zoYcH_7nAtY{F8fq{yFo<{8IzGi}~IyADn+Ce4Br^{Fr|#WAr2%)PKxB_3c>L`X2r< z|Fn;5sc)2nnd#ly6~yO=-BG%BG0ZsQ`Q zPK9nz^lu)8^V7`~yyr^9G|8S?0nN0uink~Pv6Dm$<)d7?A~%fks@8ogX;$N}<^(b3 zZ$)~O5E5=hIIu;#@u^b7jD#(>L6rGChj`E}J)+IFJYR39&uIOKVIWq=RDfYPA)%X$y@Ej*}d5GfzeeZ4XSnB(Df zKnqDwlXjpRYQpxw{jBOR^O9S2^Sv(%VWyu)XlJ0!TOPdeaQVz2#HbEk)i62bb~59h z%_6bmpXZ+@ryZ;TR%X@v9Kh#TdHapRC!}ki_;5txar(R|rR`FEO(Fo^?auRLLG9YYKc*&kXrzh_w9UMzUsyH%Au z315IJahHFf9v$YJ##z(l`WDsbgIK8ZKJL~UybPhiKWj;_l_K>^QEYx3jyS)xt zop2ZpeY8{3c6FHb7;)$%X>3Y!**>P zXPx45z!NeS91enmAO{TEl}3C`$5SXsrFp8jR}=(Xl!-p)w7^)XVhFK5Nl0WSmNhJk z`85Uw>q8@xe1}yr5c=vfAkF+7v@C#r9W#$^tcrNd?N}6A2U3V-{Sta{vm?Z25uVzH z`KpQ;B6`h_(Jx~1d?XnXFT(AZ2uT=_A78}+g6)7=-nLo{Yg#sQMiov*8e^n}$)yFI zP7FNW7i7v8tgeQ!@54OU&EhK+qy)}C2`2?ZgB&gB7cqmv(AMpytKdb765{fkfYa4y~Cfl=qvNPE#)xRe8Tv^CSX3i|b~JW13VXZ6vOO z^EZqo4uMsK=69pnYM8HqW~xZYq{K3;o9T4;<1o6JlKaq}1iG0T@qIVbvTtUZ^Rt=e z)6Ep-&-B>$r4)LHct;cF-D9fm`Y(M6oDH$J=DFXc&8^Bm? zCz-v|OVsLHtd^@YL$?3A!l&zt>epWZ-{zm9o!8ZzGXzNV`6n)gtR#@7zZR>V&(Fjc zP!8}?E)Y;l35?OW^gW=QDv}RqXqa1Fw=_gqJCoHmW^Js^vbV}{@Xd7F!t{z7$mEgp z1-$M^Bzr%Dju}8b2uKfH?z`ozy&Bm|dMF&0d>)HheZ>#81^)t{vcKdrg6+!lwA{DJ zc~ks3Q|ei6zWGTh`F#C6hE$e*Y7QzR{{t#_f}c4JM;0R>ofjZ>1f)!9F2NVrCrc*D z<^|P~;|<9*GwBye$g$^z?`sOj4e}?C=U?|NYELOz?chO>SY1m4nKLK?3rx?6=uSo0 zh$Yiw47@s*#n+b{-H{liPVU?d{%0(1a4a5Gzc8pu?(e)YO}ilwo9-b?exV5du>~Xi z$PWVP=VS|GtqPZv^G4Jef@9S+DTSd0r4hbBeS*4%V)`XtU_TDE*&T?$$Qv~8^2$iAPncP}XB>!TyT%nNcTE>)w1G@Wj5QdO}QWh&5)B!*}_eFQ%5JY!` zQY<+WhtR@7)h%x#asGBVXp1!2g!xthmJIGOPf;s|0i?FzO}%^I?-q=OL)h_TukI3C zBJv&Bu_b9M1JIiVWk_5pmo;h!wK8IXVbq`;i7nE-$V?z5QY(X4r1l+OcmhrLdQaXJjhxLZHI$WdmpFKbK?NlOgS2AuaU^HQ`n=6& zUGfF8-O+3Wa)tHnv6`Tfnvmx+wc|3Cqw2xO70Fx#qzet^MTJ@ukYAIXs!|wtW643= z%b9Oi^{&blHh}(2LB0*&SI&g+CFXIE>PKqoN7Uf~k$KMw8FzwyibJJZ7m)>P-&;2( z7x3_4(Mr^qTt5twiTR;BxnL#pmHLeiT-Y=QwUh}OfnnY6_~Y{Ctx;QdqF^tpp1IUKlPmS~D_mG^5FwyM6;XqJ zz*gfbB&lJuYyII*4O_6}DA^o#=SJg~&GrR6g4O7KFOz2pX{#<2K%V-TMs6r&0k38X zQ&^dzw7ID8R%zD5R;`Zbvfs^sq}zHj^@ep()0dg18A2PcYE^1fUZY^7mUn+6Gx zZ`Utsi1>6@g(W?L0yisQv~e#CJJ*olPQLBjj2CK@-QH+Y*OBU)2~I}cKSMOZ#i%7F z|8{NV_O@9Ah;S5SSh00fy~LS7E|1c#y;oacOdcV%EiuF{ch)W4Eg3z|!eyBrCtvv5 zk34T(Gg{L%n#}mz515c6lZcGIx5;7djIRY5Lral+1@89I<0jc)k)Zq#|S zJq~K(j@S{Y-S11z?1Jch_SZ`-DC{pNaV~j9y*KaErF*(+vp#Grc@<>6_J?(kK}n5r z(T@?#zU+Q~<~cIJx-3<&XIkz-!p!5Pz?u~1#t|84PtSuCp@)X`Pxv(+esRG(HoWmP z;s#gRy_xWob}SNvR7+~g1c_z;dEn5dBw{^%M!JjgZ~|2#x~DGEGWTpsZnII!kZgL} zIiOII5w)GXk;s^-M?U}M+0whxlwD+j-qK0SvRf`sc5C(t$#qQe_g%)4MeR}2f{nY< zH1PG!#skmES{a6&Pa4&mrz}%doS!^m&Yb)Fyl9{wBGAvPaXptQtEZz&(HDM2v7sRC zN%6pohC}J4Co-<8zP!s?)wrpk@cc{AOsDu?c71s{oBXmHoPV~xe);75z_qmWzWRYi zR`TGN0h;jOh}PiPp+VKNdehF}TNnN$EQ?wlgW4Q01LTo6*z}!BS)luC?Tf9&R1vg-hbqxQ2 zduor9!M~5yx@|V;24lEG$89GJs6z+38K7}6+2x6ows4FhZq*vxl$OH%VkVETZA$s) zpaJA5a8oK(JQcJ0-^@Q_B0)U85i{mtd-AjiaAw1-V)5j;xk*yY>}HcGsNK|I(p1Ch zXq4^0oqvw(m>W~zE}5Gcw~epZG3j+-a(Xqj))sPpb<%%z?g8o*4Ew6tZT^MNtIvNo z|NOdu5qZO*{f6uC8=i}A_|o4nd&~(u^qjSwtr~oz!aM(NaCKJfu;)_oyi}v-YQx(< z?qVK(r*iR~TKYSU#&?=S?{<8BhZA|PyB@0*kr%r79{Bj?b@BVtBAJ=2F}xu{mf&4X3D!CZlHEOC-Ye^7y7dl}aTjQ&Rv(<7 z-Z<0-R?f`* zotf@9UFkMC)TS+1V%q@wJb_fCK0+J0mbGr+RMdfs-ZsYGSF={sMKQ~r&}H7-tf{n>jLM?p7%62GNyz4J!zk2})Gxdr~$v&2sF9 zSc#VN16}7b+=o5?fdXz)`9w7k3ejP_s&j59Qz+!2vf)o09xI*|? z5EjRa7d_#KMsX3aC`_>5z8S(bRXw+bg=tQnzsMQ3Ccqw#>c7Qebh+REcOo zGd+{)eF2x4p?}&>iHjutq~_#d^+(uL2EC@>Drlo11Z8$ z6d_kwl_j7hRhQW?H%%4Bl$(Y}>`O}Hf|aY1%#Ji~YjpxFEZcn@gK`d>Ke4Otu(aoX z2p7NUDx<_?uc1Q{5Sk(5m;#eLhwMupmBjAaR1`DpfN2|N#d?!V*oW#AQuAg z_zq{4Ib1mQ^4Wp3OI?qmnWIFd_#h7KR@<%%x=C?*h>_Kp+$#@+piwa2(>+Bp!KVcf zH&yt@y;4vB0N<7UNJuCaH~C7Sx47)J#!!f0+bJq2uLpL8GDqxL&YJw7)obB&GIK?t zCH1(Z%1tIBhn5t=DLbt)^sY<`jMX95(w`Dv6H}IIAH+TaJ>wWO8gOF&PQSE0P(TD& zV3@LfUuST3OB-InTY_H$LG>$U>PxA-z-LTpTvZ_5IB(aWyoIXzc$ig}znOQUFDP?$ zs{^KhoygVgz6**)*7GMbIQ3Q7#ygyeu@?{I17dd~-)&P*%_upoqO_agNM+1c?C`m~ zvb4KOI;59c#?A~Keac+kdj4Cxou-zOz}&q$zh$@Mtm5v);P@D6v`k z6iJvfih^XLYn(^z8>9`{cgt7f7&nWO_StON>f3)gy><$x$U$R)z2sD%TDaQ0&28TX z&M-)`sFJ7~>oF?}62OHGFmDetCPF!70U2>!p0_*IQ$jFKJN@^cjxjuO{ZZl_&#gI1 zHTSQ|-AOo0sxcN2Rz7e1NkZ9wx{F7mV*BIElG`lp_skI!lKb@~w>JG@roA;LXDWNr z=7StH$JI@JpZ1VHHaqV4P-A*wu_yg2%n1kAAO!F{p&)lU>2lW+LR6k)umwBmOK3cb zhQWTTtzc}Iff>etMErT7%Fn~i%Eb0#p(^t8UC=*byOP`jDku(6Tjd1g^S>)(x3OFh-V zk!r*VqarWUc#q%3cEgmn1Rm4~G2edG@&MV!D$(MHvpU3>IVb)xQaze!b0WvaC->0B zWc!QB9{#DCk>OfkZ};zZss8bN_IBfb?d?XV7RKe#kAjw!m)@xt8HXn;$>v?(Tl}?Aepv$9*qe4iDZNrS*=Djg5|tKB0}I8HB74Q2+7m|K}H~z^~dG z^l|p@7pjzloolgO%zA8hzt7rfP`b8~{;aKFY!{HFYiplxXveL>_1Ny(LiK{BZ04`p z+Co=I4c~&bQd^&)S->y$!|?<K4k&`ad7r<=XT;w);py_xG{g7BpLO z`C4ojBeR2e^IL3JWr0W#Q(KGe!aRP7?P{&ZcDpxeV~9V;cK6|b8{2i?0v({ocJE(j zl&M~e?dAo5vE8z%_1JFgrd^EofNXX1T5Ok{c{3Q>rGAU;5;)p_#CF@n6V_t8ru5jZ z)Gx8!t!uGeYaP6VzR+nrJ8V6+tMD&lyVT~NV!O>kiV;7>b~D#vyZ(o&!PqW!J+>=D zkL^-rB6Oha)i>;5d^@*QcSGbCbdNK4;P^NobvO8F7=NIN!MT)L#Hx#wpfmySBW3=l z_h8K^Ft!bffyFhLkX0pdJZnAjyTwsw& zhIPtub2+SCM~8*|o>|V@%avR4a)&LuET3|SZtEIX@LM+Whk35Y zcFn=qE~u^VL2ZS$|A_5cg0bE2+WI}V%eYw}q~rMek@PxxZ1+ykT5Pulx`|CJ*nnk! z*dRkDsIC46`^DJ#_N-~^Hs6z=woY;Im)$!8YU|~1+B*14Y#(3YkcLVD3&!o5v+4%t(Dvyt>JM!VjQtVYz4tw~d*CmzU0G0D|1P$x z%*Y_oU{IL_#&(Us*slIw7Pgn5wkCnG-Q(-A-M#eKZaf&jI+_2ejem9RxD~|)PM`}v-8P8q`H#%f^ zHvCC_5u8ycj0@9T-h6i>DxBK(us>0D*~n^@N37kCgyGxX<5GRfy%dE+-$4FB$HskU~`a-oET&SuuPuL77 zyqzZA678zDc@1jo`&QLPP+O}hySA~Y+O@DQxyM=yAp}2GAFl?rbqjee-q8kpAE=&d zL4NQ%n!RNv7;zXZqfHK@Z+h|(jTuHcX-t|exar;YBJI1j_HM+@%7WUO@ageT&p=MT zCPvy+w{yg^d`(;5H`V>W(pGEY#)Tx_2CP3_TLqS(Yub8xU0bzY!t=gqYb|zNTid^B zYtuhzt4q_pLkPQnsjV~?y0)&aVB~E^g{3T4LQ#CelT!=#?9YwIAWtqtsNjn*|E{f=b#1+)aYPiYMi4h(=qYrknL4t-<+a%_Rs1&g^}`n|X7?+eSK_jc*p>hxV(s}PxBZ1*zrELgd$ z{zY54{C(x{q;E$-@feIWrj|t4)&k(0wjP>*r&iImbpX`XCoF0E(L6~1pS5*nU0bWS z)hw{2U182>`$=2P&w;UBj^>bqe8Fz`HE>n^30&JS27Cu+6wzQZcXgsP*zOkVIKTq- zb}<$gi@}j9H7v&4*b)ys-VI!=0zQDfU3YqKm*(jF!7(f>FKqKvNUnF-NNkwBS$OnP z7@I{XL&kY6KITV6k8{$V8D5w`i;J$^kY;=o-CSeoJJsm5ooeOU%};n-IJhkR;HZ9G zS|=+kASVwE4pW6=PqWzh-dT(7($9xFMQSjHvVh?FEK;osUit%ERs9Y75XcPX?z5OL z7SRko(KEF08A|k#r1Qt{fLXQgC$)=+N6c-s0G3CrfB|Mj+MT04PS6s=?T%h;_l?|r zN%ve%w>R)6-*S~2#r@Vhud_+ zUBI2{oA~IX^quNmigL6W%LESHR_X|S1FQacbG*WETKV}5LZ_4%PS zaGmMCth$!gtqexbg5a8wG)YYY^Sk~&32{D2@Qjoq1E3y9->G_ZTb_P?je83?riGr5$C8k2!~#v()j zgl8=DB2%`%VSbQvURW*psv)^?hTh&CQ!jeYUo;+`Kb4<<%r__h6WIE^@fMU~dl#D6djzDz&&_@|(Pl7#2?wi$Qtyk|jUKAjb>}N0t#^ z1k$@S@`6*eLuJXzV1f581GP4feRi$Do5}F525DvpPXG(NBu11=S&9l+<5(;3V#)2k zz()O5Momi5q)%z8K*nRM3KhSKu@0UB@Dmm3hKKWdj+b8Jy@V+qU$60E8K%{lj)F%- zsR<_FaupBlkS3d7yS1#xGzK7dx{&aNH;t`tAxr7(%7G_)5=y}oFP&Y%^PvEg@m}Gw zp8gJORXAv_HRVWBk^W7F#@@2G>PAQ^@(O6KiYRZ5>fqV3^awjy*eJ$&@UW-UpN-2~6Wy$awzkIwP`? zG}(o(_?9)ETZc!&cp4BjMGua%C6q)%zP3(WAWBbZPE9 zFv=Uzc{>znKw=v}c@4RjH+T&kIcoDMqA1Mi4^nDBzi8YI$}50Yq6FqfU{If!9=Mas zKzXgXVJL>41W?PFu&ZixdF9fKMBP%>YTCAlN9J4v%sTg+xwCt1zlv>I)`M76qPiEd-B{YpYfDZn zK)j>ch7DUc+LTH~p;s@Q15U`1Pa4&ut~D!bqCk9&>S`Y_DpP-zhc9Y=lgwzTm>pgU zuh;0%wke;SZZ6<#SzaNp__gGm>y!c~tg&q(3kf3BYlt{X*|nN6nc~+55XmUW5Vdu* zrsOz*+>ol>w7qo_h4xR?hVqy8T+@baC%3rAedy>|W-yxaX}l>>huQ|v;;$=%d< zx#{ctJC|*u@ z8q)Ff#HN(HMA(r-RA& zX%=0tpVD8H_M%oRz4&~_#+d?~M%uH_*UfRLM!_s_whC(N^z#=y&OY6&16iy0UaDQA zYirl*m!P&T9tV571C}=iXj+4>rw7K)51O-(XX*!E4GhkG8C(z^QZ;89WP-gtKlH>O zQi@>(W4pn2TWu%cXm;>RW-1ulb$J7`#GDc$o?&KZnjz8{cMRLTfyr>PTk|GzH4Gny z&}MUnFNdK$6i*4+jvOt6#OA{N+cCxjmXppSiaU60CQg2yVod}_wvb0n-$WwHymazL zaf4jSgBXm$u+D|C?Q0NgT{^;~L)#TIw$F`oLtx@z(kKF8c2ygZaJs1zMJsEBS7?e)66pzNBr{hhg@1w_(6fh}s@YEfz_n~L{2VW1azNT%M zqid_}+{A^sDe~M*!|xZW`?kCaES}f(eic?cwR$1#p)DkC$MlsQ3lA(`!`xp#FJ5@j z@f!1!w*JFuQ0At2g@>L%`m1{z-l>`|AUD5OIqb!SOAUZ`H0KXiEMF=Dav!K<)` zuJ)G}qUT+YUwR#V@SUj6+-^}Dv7y71-GX8Hc1 z-<<|cDrJH}xo=ieD8WbcV}!MSa~hN$+wDq5Ffle$S|XWK{uJAl>4Gv|-4QJC&#~SA z`9k$SXzNo{;s(_~P+K)!t%hGyCx8 zh3bXX9}Cq|90Qv^sI9#A^o42=sI5|2rGKNXuUxA~2%xscC3&JXpjn=vw(@p95R2Mc zTee#SE^vvIdgfDEyV!GOB?E~>`*H)R^dKcencS>$L%EV>C8JGMW93GhYYe4~x3q~@ z7%M;2=e)mpv+=vGkNrW)ChBcAt37wrTh6^R(fY_z@qp=LSAwa|==%g++<@TLJ@jd; zpqe0&OHh;f%0l-d$4)cg;DkK_Fj&djs%xa~w^P{6^w>s0vu7B5qF0J2m9)QW%M~Fa z0ZVyewr4zucdwfFD+%6a##kNibBoQszz0w@3X{yYaa|b5leS0l;hp<-C?$~&> zVikndZBSr87f~wN6}pjJJ))K`;hB0^NTQ<0w53JGdh0U+De0&@3gC&?W^UPUgKBq3 z^Lk+S;SjXjGM6>bc2yMlG~j_{8>@eVB{JS$bIUfkzXqCiS*b1D$|R;OsI@=#)`c2- zM9=}5Zllg`7*uLev78#ke< ze9e?9Hdq?Rm3;7R+WMlJ!skI^$MICC>si0{QiLEK(=r!Ai1uUP9`?}L*DKEsW!h0s zdZkKYjUAu>4&o@>cIe}A?zR+{wwjnaofAm#sOJG3D+|+6(<_rcW<3^pp8n3QS>PV_ zk@{2F3mLak`Q8pB4sF=?^+UY!Rr($_i7dR}5rf(l#=OegiT+AF8slBZ&C7;lq*(MmFpIVyCN4+z`IrgIg|;D+{x>vF0KU~egAKv27$M162t zREIh}bT}i(*qxf8E6DbVCgxi8Yp(Q1F@25y=5y`H#C!-uN9 z29llvjA>Jrj+(chn|!Hzr}@@KN(*KGaDir)_DM6B4E&9@?u|J3W%a(lOj$0nhaTYzTer>7S*+l$B zHb)A`hJYpE??M}|dMrlyV2<4WJf*dmu!~Q`zLQ0J4&-PTG;Y6|>k*kuzla)H?Rllt zKDX|di>L{$>laav-|lqG?mkm^ALQAXEAe1Scs(N=n_pg3R0KAJD=I5OQcCFo;hR@~ z*lc&(hH4dUsLm(dD&5s`!F3B$n?daBJWWqJ{oh0jWecO!(24i-MIuPs zP6$Dej)tNX6$7FaQ38U}L{Jn#MVbXGSm-76P=sKkCWIzkLy=yBAWc+6KtM|99b=&))BOzw=$!`4h-Ro+S6W*Keg!P24XIRC#=y9eh@{{YfQ>C-0LI(|Gp#6^cor}CGDH2+@tU+)>D}1mijtYv*+=$K#rQ#>tEwleXnaJg zwu68GORzIJ!xdmpCafV@eE`XJ{4j&b=Ld% zE0TTnx>rfDRfV|jWAN_+EEO0H)>K z@^nysqudFyqJ`LV9v&xrlriTC5}EG zP|92=V}&LiDI0H-Tder|(O|s^J+eWDog;x~9e4-SoHQ@^+)tY9WFtnim=% zYR6`GC`IF##xk(X4?O!#?SfqN(L6Wz@xxVa2kqZ}wSw<~AQ-b8-p&l}m&&;VAAAsyF zB|zvh5~rt0!hr!LAx4#epmkk%5+t>kSh|^_WS55Er`Pu! z>wO}!PCt}$jM<3YKngKo5b=IY=(-K&K_*Odycx6qqp`;mp(`)eZM`ufct!yyzK$8H z(KXUei8I)Ug_8B;(gb3&^*3v|N*kSY5L7$>#u<+y_|KTmC5YzXGb(g;Op%z&}_pRZbG zW)X$LDVsnPywxTS2^{#I=`;KBHrWTSZ*12r<8%uhkKYXLoox?u_?X!nb;%*p1b2SP zGA?E?PgUKeGZ17|-gwzrS2*CLm69c+U5b2t8GR}h-3TEQgV9J;>yd7iV1pLfb5kbw zzDh0l@vf$~sCnAJi;j?>YOM9^6i(R1gL#B-EeZ^2xIlGa=|U6>>Uy#MqLVok=|cvW z8fmUeB!nqJAGx7a$$`S8yLLV##08wgQ?wj;-`3HsZ!ZpwSO_%U&NH*xty(S7oEyt7>NCcI_|~}N zMX?vRPT0JylnW@IC~$v%QCWIRY zq3w{Rl~V_=@&yGv`wR%M0*Ao_ZP#JY@bda{yVoQM$w4z@P&NMx_EmYG5x$u6(iFN& z_=)PbLO(!=UD2dS?}7ePjBEEeyI0=dPWm>kaOiLQrvtsh=KJaoHb6Oh^?BbOZ>5trBtz6$yGBd?s_c^Ozu*!$k9XI-4o^lu3HE3CLYao zBDc|l$AVFd ze&`;3a!4j+BXa1>sa;PbIFm3?kji@1h-wji-qzz`s%=Edu}fo8o%m4wZrjggycrUg zwv!iJAAJq@mNt7t#87C+p7(lt>gshIdAo)RuM0u;i|_S4x^|rH-u;K1*gzq5`P}KR zZ>Rj0N46VkjIwdOMO zrD4A3vHscCg6}<(r^86))_juf@S&6LIh{`nt z)e%tqsljadNYyFW!v-%~QEYu2E~t#eBY<^r!PQZG5CSpJ$T82Sv3IAj_v1r4n?s=V z;EbtglmMoU9l)m>GrJu9?Ey*mcnsVEJcp0rQ}GBVM{kjbhaXxJjBp~Nk?WnkBrC32v0>URFu-_~t+?Gv z$4=Q{G>SD`!?A6|a}Y4BQ2pLZL98LldzKV;qsOay3IepW?i>1!x%k2ZZY<*Nx+uoo zSk<0qW2tdCp9-v>bKG6)xIm-$b3JkLE4;Wq+&B?I_qd;LB#;f_+h-;4I!i#%Fq$X; z>n7eu1l%xwlUOSzRGc7?Pr_bXNow-kSnrwKR*~G^m;7QiS>9ErQH*0`h^30582qGWofE5G;i;*!dG&4JZ!BS0>v<}*&9`Zt2T%f9_Qw_W_jFhP2cb>dTv|$m>?j>DA2Z3U@!PmD^UC-=0VV za;W_*xN14>OAff0!8gss=;NumM82d}j7J33#szaN9J7x=Z8(Q*Bt0z4dic84_l-Jr z@JqoKI+)e>z*&Un5svmqiR#wzV8S_n`AFWfV0NbwPZ&va4?QoWjY0MTRR?MAwxjt| zGLE^R2ri%~b{6j0h1b@w`vgeg9Y`nOz=HJ19XyR*RLE`)b?!|*L84gIn|kRzItd@0 z>V;c10uOg!P6AFp9yO4NePIW8puk(bsM&V#y+jBhA)n6>Ql~(**!_6<4tkn^AkO*k zJ5h2VsU%a0dNdA;Ah~fo5g>1n9SJdM4cXu8hWCL?`_%Js;pWsod70c!uhbb65NNFy^dAW zDOTHQ4GX@QJ@^c{-$h5%1x59y)q>Cus_MS&egKRKj}!L1&IMjC-d8TvhgG0K=K>=K z>>L63kA+5^2Y4)XolnGiAJ9@;SVlGzL18u|l_Jbh>gH# zaC?EH4G3&PaG^XGQ62lQQ^;IwA`kk>6s9sUv$e?$xG6F=0k+NL!aY%0TUX z7i!gPqq$GrWKPpD?Y0ca|V6T{Sk?i^}!aT_jmRgJV@|Ngb ztnzNBj<8UB+0bW9?8RjCSvKSlyTnT3mEd=5tIh4RM93iu9QM5)v8|FucSR?=QR(1h zF-|&Hixto7RJe8;||c9-&7*~Wa(bhDbp*CJ zcZFND}3G|}n6W!VSnjTkik?hyL^so7DG!Tq{PU}s` ztRY3!1gmK6ul@e^{Y*aso%&@i6_-nGuzoI+2#crGGJ(P%k&tl!EUKa zzAve-Y6b@e2l=!HGx7(A)&$tksG;<&Lz8Prb{s_oknD#&!=FwKFZm9uWTE@Sp#YKv z*z99-KF%Ii$SbIf2pnsVeuqnf4zVu1f}Ui!O0sXF?SZE;3ribucmuXu&v;N=g{(<~k{vuVGFPys*KUOdhicRS+Yv=s;p>4I%1f=}7a+%cQxP7mY8ws*{A z0Mo;a(afLy)4xZu8|I(voo}?AZ}OWjIzLU0o_BaL{cdR*ikoStjo<;Ax4Sp__?H&5KUH$#~?VonWz2E;gNcK+xEc4n&heubn zV%TSNuIl(N;8K=G_J2xST>29F>DuXKH~(dilx45FWuM_?zaPt_KSqOp7hpMNOHnT` zo!hv8`mxefy2O8IwFSOB6utU<|8nw=Rrx*y+$e{g>M6_ORT_MMALp1;PpXN3j0Q^-fzjOYlqrrcJWdB}(tx&eV z28;&#>`&FdwT`I89Sw#RICQslU-bU+`ElO*-lYOx&iCSXpMm!eLhgTpWd9IgPY0{~ zLxA1?uBWZAS@PMI+3XA-xx-D%Mg6&XGI2fvI;8`Fkw%L4P?tX=**fTsKalK>gFCG* zWgS!><|5gt49=YwJ2msKzxe!Ny!epLaP{>Doxy?Y=KJ_B?=a`%-zH>n;H#zDzWv?a zC1wDj1xfCeVBVF`ldW;-e6N&wgmj$a0|y-vgmvp#9L;+wWqr;!UBY@0Hy!6rmu7;j zx?Gy8-J8uixVjJ5XB_hn|mOAgydGC$QP-+u~a9^w`#9=sLk~gRVq-*WIYxND)-Km!u zxt(>hIV!F{+!3TE&J;E~ucQ%hLZ>F=W3s(k$d2x#ee2y%Y7L6oiJehH(S`4y*kN$Y z0X02Ib?@QS?>r6Z^+aHU&g+J~3GDHd#|AWcp1U2eKlUgrpkHPGYe6lykIBLpbalt~ z8u=X&cR8~6>*Rge{9@SQfdQL^?rU!6rf8X(S&7i##Xf-0>e)C4#z*r69do+nG@JV< zG-+vwlA-`l16Wda_<^S7)HzM$_Zs7Vo2P zu%kh%&qg$(JpvW*vSO}U8#Zh!tKRj#ForMp4zG;H4sdoFB_sS^$%TohV!LjGoDEa+ z+vyfz@x5m5Z5I-W7-F=$xgMTg-LHm2lD0lkyazSikaBXh4c46_zE490X5-qtKNf8k z*Vgqw>#^n)ndze=D(AFEx?Wrn&rSZICch{1{2}9!BeXB39lPttUiw2m5g|MONr3(D zknHvlXVWuUM-p@8@PCPB!9UULU)r+#Xuh9l7T6~K#g_dyXjXF5e`m{z3;cp+38Fu_ z>@js|3l*jRku7`Ka`V4Qx^ivVf9A4UM*v%Plj`|DpzNP*+5ZS-uQ^*99p&1xKZ$Jo zuS6EGWg{+`6u2LzT>lpw8>j01zh|C9)K*FdMtvM5~i#|@21ZB5| zJ$e&b&;cY}i>scJN@k*%t^W?nrVM=eXDHkG7f^P7@@3yV`=>U`;c%9|eEGc0ZW|i; zciQa#5Y2x0zm8^^zuL0Nz&7zeq1ja|2y|r)&4R3c_FRc3Ydu%X*gtGp#y_K3ZqHST z+jAYieXjN9R(pG(=epsmK8Tm8aL;-ox$^thm5(W<9Pv-ncR#8fGd8}0Aq8tEK?%%r z+X_WqZvsK_*n?k=o(Iru6YS3BN-+dzyK15Qt+0pBW%+mnF3^oN=Dy1dO2CEhjYO&S zoOe7zsBy#)>f;enDwrp7X%`uyju|TB?fa4mdllTlk&2qYYBA!l$Jo8&XLB+SeB+9; zV6>gFX;FY^W~Aayt|_~-iYI5{* zbMD$ycJ6MiaMQg`4V|5P#C)*1mvIAj5kRxz`{#?!ZkhwoY|+#C5-Wp?0Gi!zuuy7z zW)48JlZ^}Isv#Hu9?d>7FZ*U6E8i{DPSUSIg1a`{BsVh5`NM=<4|oo|fA=)k9uz9F zTieoD26|V|P&a*r^lDwVq@=|YVjnX|H;hG(eI_BcuF*hEMCfDtc5h3SCSu%Du!yqD ztHOPi--txz?LNUpZMeeut{3}^z^#yt77JZ3b=^;i!BIFnwSDV_F1gh=A~Q_tA^c9f zGU@Yrw?v>v8Ewiv9cerq-9v((mWUOi(iCvcyk4a6VL=jXTdgG40$|9upRgP-GAO({ z#_1+J;N-)ijj{TjY*uRA1|tlQfgcjThquIYisZB5%QVj`JIzU+qnDoI@8Dc1(grvu z;zZoJMJ>5xZ)Mzc8ov{1CN*7|GMg{>sqzDqaHxt{Dw6V5s%rTKWwH9J8A$MeDeLnW zzgy2cz*Nk2l0vhj3rH9I^&p>^4EgZ$acDMiyMt~Z&aU1EGL!TcKmzpwOrb^q&GtMX zK!A;3m;>5OCO8)A zGTsTbYF&?Ux((%I%kA{3KXlr%Aqj4;C&wl|4m=6IkBHTi1AS>&xak@N$sx*Zb|pt_ za7fK?nieY)L6J8Ig-4X1QAKq?jf5=m8xJb%KZn{uhP$K**Gwy{&wV9&tt%b*e4iog zNm%R#{VbWC$f+UZi?mRKWaN7w8>)LNbJyqO%NON%fS#+{W+?4Lu+yG*ISk`A5RV<~ zqP#O6X_yg%SKLYNUU$tj&R7kOC0{)GsHG{VBHwpq!CNn$meu4@F$_$y-;sN^DzGca1uxXd27T9Ng0sI|&ix47;uJ^= z{vptq3ng$!+a<{_eQZ8Zu)&6?c|&Nvk?y(%Ii^k0OvlB_Pl*(Rt*)pKrnJeo&4<^xL*zxLXB}^F!Md3Cn=vcDNvOu&$g$wN@wv={b<^ljES1-gi~n zU(I0i!7AoWxC;rE4}mzovqwV*p0?Dk)+YE1EB3LAT71A#G1A2m! z<{`t+m36-nJ0MZ(qWIY$K4S9m0H`b3;O-{xXIr$D{Nf+7q+G)f`7{VU5^a__c2?Xm zN`Kny7*A^P)N)`ORF!(LOnQE<_Wi$0$C!ug3a$0c;UKvw$I6l^x32 z37=v$=&F|HoR=I`%GPMIkQF{lYhhmjzJ`W+;EhPOa$Q>}<5cCF0mzY!U!vB~>>!Um z?VKrT1_;PCHc+pj)}5agNCbu6-vG8$4>#cHdqtZZTG)Jf+(|}row2g&t#s2l8zACZ zTJrdzd%-526;@|8uuc5mqS+to>YHjop(}x32d0~lqTGn9Wj!y`tgL#9YQOzb!qCbK zbv-3ki2UqVV5%!n_yU?8m{Ns0O)je!S-c#)C3yt*vQ%*0hW8QIy+?tFYm$~g2J+; z)?qc`lV%84AuV-u0L=!kq1i!m0T%@z;(9);PDC|g;FuF?{&zInxE68k4S+LV`as3r zF{^@pi@4e~<9D@g?(=Z~@ z4ksy)Zvn%^9;C~LLAwljU$R|pmS3aZ#OcK!8h*n?v*~~y3rrHTF%bZorDHGuM6&|n zcaDe0#fRITM<iT5R{$+%s% zju;(sfx4(k<5@$qFeMt>`X=fNm%^@F+a?}z76p2)6BYE49PT#p>(tY z40A84ws__aCE6H~zmt&hsRD7^PA8O(ob7{V3WB>7AEfSkAb;UOEa|};=N)fbGi}ii z5O~^WbN&J*ozFPat1`fvdfq$;{VI#IEQY;Iq>i?tKN0!ez0gbhAlC?pYYfON zDht8Rd@Y6|61er(K{3e13sidBgU_BwU3028K5JStw{PY_zjIE!R@O)Y-x7%51Dz6_ zm{(buhXCe`>6m_eHmW}FgL5`nEANwCo|Mv>SBryRr$c5?dAYec$+I~Ft-0Mf1xu|6 zH*@MxE^Xif^w->rW%jMMjK=QlI-|6i(Us%deSiwy%>ZcbkbCy182={RDB`v;#fKhM$}BzwoT|igy{pE?-)l7CDO^*F?yA zgKUY28Nji%<2tqpUy2cwA^_{|wW|nY^K>PYAP5h2OL(dt7f-JmBN&J~fM(0A1m<$J zFY4@aLhc1Y_PUfT?RaPfLT!U;W#v-uM^+?m$s5tcekSmZv_7R~s0;Mpzb3xFRz`WX2tTy!svobB08DvBHCZOEf&Le0_Pj2Im#IhQ*@|bmbO!>DJ zy%%UQ-@vzV5DKmy!Dym+gCs6Bq1qqFNbnMqv`> z?2_$IG^h{Mbg-#^Y#tLYaW{{dNWM#7T2oCQh`xnyq_pK=822Qf#^zOj?kJ3rsJO$+ zOin72`Np$>@vN%4S;{omZJ=q=6KMl_5XOY{inohnP`#}MzTcYVs#A~I@LStFE{|yG zO@6Kjh`01MpoqPZnFvd*8St(xXy<}nX-O>Alq#A8?^%7ZR9t&EiaN?}I~I|-@oU|Z zY*CjH23ga1}@yAKup zy&1OciJT;4`YB{UlS3;seXN-OT={$Fx-Y^zw6i&yrDwcLop;wxwNr;lT>rL#j-_g& zomdbvI(osSO#gD1VL{gvam~M_ygpR@x(oF}lHM>{!TZUMf4nvS1-hV9i+X6aZA!C) zegdMb5AAkF?(cZU`@Ls_ozCME`ek#Ov4mGwjjLo$-`u8Gy4AE7D7{${tZsPwW=R(E z>Q3iK1@C88cd*ZM!k)gngLzj}UN?x-zqCE#w6zVdLK|`3SBcR}L9naN*e3R)OyB+- zslq09!hTlY8!?zqPNBq>XVG3Dic$`2t~CzD1Mz)!+4O=xtEdYo%i^@U!w1?f>!@vU z?)J1$D}olk<0JRYUs^kR$E?tK4jGg*s@#E^o2dN zlLh&2#bEOtFVu5;q2DqNT;N}#qsuCX7J=941?|X%RK8r)Ms#|=Q8Lmu-3pHqZXcHH z?}Yh{h|;JC+tiphBT}?#@ivy2Z6@!95m~=c(b^Hhwo!%J6g8WcZ5zg54@b8@A64~B z*{(VInR0mIz^1?G3^fch= z;&Ddo*xu-cqaZN2gqxy0L0lYBUVsyfMOjnIjKvQC4<=20^n15Ld-n&L1#M(QblA|- zY`8xgnZicbu`$DJ?4P!YiwzfguDoYFTv+T`fU+0Fug;9wE>6)ni_)iO7L;-CII#DA zA0F7gQ{MPdRp+DH-)s~A$(B7F@czx>r<*PB2NoAt%Ac8e*H1-`TRKzxVim?@jq`y8UZ^-KEDr-dhcS ze|rDxsqLKR$*)_la@sflpGUKQ*>jbf$uNn55N~ZTNc;`Wo{87z4O7|!-5d@&I(O{h zsTu&y3ZGk#geqNf)wMUVF1$Qg%e7?((%}*7n2d=?-pb$5EGrm>!~K^%*Z#zIDlkzNY4s;fhlMp3AeqHt{4z@PCbFRSrnGkGrP5 zUz}BG5$(>K&CL(iKm2s{h4IA#xfJbKo$61cyvAEBnGS5H zrNx0wk1dZJGT3?asMVRrN3BkW>^x?DF7xrR6IY+^v^wQJ@!0CLKWx`=`!EAR3x^nL zxP@%&nfsfJlByqBJDWVY+vfb}XzP(nWfP?*uGYcSPr5d5Dm!`orGfgXU2p8mPPq?< zsM~r@QLP3$r|*?%`z%kCopxW?^nBRuGjQ2Ds1N3$7KGYcZto{3e0hW|`M?S|%V(b* zhAa1+wIl1^5!H^ETF+YV9|xv82J3LPI(0kQ%b!i?>)kxL6FQnHbrwk=uD{{H*(Dz@ zh$LB0#_yEIOC`M3-H(KLsPs>}u_#0^>^2={djQ009KL)|c%zomD+~ zoPO3VUQua^dd?XEtS^hg=LeK}B<-`1DONmP|k8~NztWYlCB_@QfD z0@`f4a`@5kHbi{Xuz~eNY4c|9p`CEiCQ)NZ{KV%TVz?$Opwu~wdgDq@5(vQ64S4JJ zz6$z{e%F0;mws0#x|zccY)VU{TrF;kN-$dC8X*(|mAL==M z%iYaK9^`SZEqrspXh3r#1YJ};DKPGNg-KN6I5Z*W><@V_=ru`zSdnf8(!6uHlsBeJ z4?k8sJXIhl@l|!-qg^LSqT|R=&;?zc?p}U>W^u4as8zKBY0R~S90Y|PR!dhgcitZf z=Mis-o);jUQs5y$ikco8pTs+gsSU!PXVvoO9tuuUOoD<5q@(%sD(2+Gb{m1F_)L3g zXr00r@bPr zcX09fsd`aP6J*}TG*MSkCR+9gI92k+U1fr<;=w*xCAHAqxg;1| z8;iX<-Hxv%AU2bmw1XrmpfunD>^csiQKt5p4mRmctkr0?Gpvj z4R%_UMVk~6?%YX;(-iO6;|BP@L;8H;AG7vD7%Cnx$(9d^g(e>8#<xt#G*(8HM|kX3H@ei8iSV-bTs$yCbBwI&K>4 zT_7G~-2Q&Co=|1|!mXz`1$Ozo!ET$*`#mLD2A3}!t+MGU?Roqt}K^`72gN32gZvjWF*Q6ENB&dRRv6uSb|Q zWH0RaJ$d^#y6@qgzzFld!^#5Uzl<=;uZ=Ko+Gz=3WhG7Lzr@P_o#=bX`uxr7H?9Ms z@4cT`+4QIAOL%m7SAnYwxZW;5FFDqJc`SQP3Z?8wh0iv&2)PJ60c3%^HDR(J5|JQby|A$za{eK-RlYYg@Q3y=@ zKP7KxuprXqHLT3~nY=A0{5HZI@CR0=|1(wwlDDL_Ou65^Dd%JPK`29Gzmb_JJ z_|^D*`dU;;u|@^7j{WE4Em7ki#_wA4wyLFZNNr=~=9g+f^0r=y#Wj8}{mJqJo<|C1O3b${1{68b|vRdsSvlDT;q3A zvm?%+kN^^zDk+w8=gGbnC23It;g`40mcdA_3!IUs2Xd3Q&Z<9?x3_;w-fD7_xAlLO zysh~EE_r*#1W4W<<|c2ufaL9G`#+MmC5WHN+tW9IBp zR^VTfw>Q8I!W(zr1(LU{|1No3!A;&iR&a<=?z#aaZ}X=ep8t`&4dy0q=@H7sPC)YZ zc>CyD^0oo5Ahcn>^gZM?Zt|7@ByV|sN#2Gd*OIr&za(#kxXD}T|1xuHA<0R>y!N67;^@XuC^Hr7X;?gdS%AzVAR};#tiMV1Rk-=dmUT%h zjcpdh;FylouS*^xD=NWG0&+pRONcTD!1%R%M(;vDAqGIr@Iip_>*K1+YdIEJ0~o*N zDuD4zf~V}(Hf>O#SpH`GChgZS0fq_J zjNhD*NWU*>;=^i4L4{OA!TND@p*C4aL7)Tg_Ac@aVEiiBhwC3#TQh!N_wF$Uj9+6X z!1zt5H5RqRAG*0qkW9Z*n_xz$Yc#G=gB)0$wv8Htc>hg7ib!1_7f`?|HR6+zhULg zmIZeJto-gifR%T821=2+SUKu9tPJ!92$pF{j=y7NJE0~vX$>nsI6^zJX8htdK`HoS zT;taVT)$@g1_Q<~>441ngXnv}rQ#m0@%uWnH+bus@%zCtF1i~qe(io5zh|6vaa`k9 zZO!=oj2@%|#&3v%J{l?0H*%C1T<6U^J9T3HH)%e9Ua*srnzIcvbJuO2tt@aJo!GbJ zfDxsWh?bmE(^=If-ua z&Dy%2=f+5z)eDH`(KnIa=teu|ye6;W+!NI^x30oG13AjM_P3tsYPf=S4U7r7>o#dd zi!-Jr3?kxokMp@V@)!kvQYf?y*t-2@on+^Ha;NiQ8>_A`xW#0D7n4oTJj)FFl*yH*9l#K4*Kq6|}dd zwVd}*aarwh0R??SI^r8v zqb`pUl8FAsnz<4vGI@&~8gya=<6hoa#`iw_#K2oK_7j8#(-nI1+t`~P$bHVEZ@QHK zZ2W$kYA$7pVXh=@VlPV{XTr65L7yIc)EAB=wJ59E#~#Wbn@ycGhSlm`2qVd2r`^7^ zC*iMcchZIM_C4)>m+YSGL~ziB{2&K>4}GcW|SpoAHMOZqjw< zcW$h2+Ksz9f_37N!|QJ8Q3-BIr^=AFlefZS1ZzH0WfRH_rx9t(*6JDTumj(o^LD@- zl^SP#njxwk0T>mW{`y|K<{g337Nw{6EJ9v|zU2+{9{lKsuP)c>hCyI%?GBPI9(yIB zMUke=G>O)D;ATI^7T5QBXh~49`dz@g@BPDjm#f}=U*R3)Q`c^U%-IFZUiKqxzES@k z7O+Rx*aEBKL&vZfa0rmq1aV`x=ge{G>clxfDbnRGD#KN7@_=D?)jcnoqhGlgRxz=$ zZ2x&YDWln!ryh`gNit+lraW%*ivL>pmV`3I@hae|*J8K%z_y{fztYszQ!H3qGwzEz zZU}dCp$n7bgcT?w8RPt60cg{BoKTC;90erY0y>nvvkJtQ@R&Ebj3}poJD`Efp$A_r z3xt}78kGkh%ns!Nhw{bxG@85b?d6hXcBu=WMevsr>^K1%=z+D$J~Uv5<{O>!~x z)#$|u5qLXruI{~DzU+tO&Mz~OQGoh;lz|=u@kN%9;1sOOTJjdA8-AY*WCFwOjh-wv$gfe+4Y}_FQ{|b%kCrGOL8le|8d{7o1*z;V( zT+Q%7q{h5LQeKy16Uwnky&82ktSb5#AO`AZCQ`yCH6f6oZted=sTiGh(vN zdAy&#cADYwUKs3qJ|+|RvjN1+onGd^90A5mN6)h<)r>Xu*8pv6h*LGXvul--Y)F}R z35Q$Xk`hJW4P)Uh!II5^TUWu#s5?BVd;=>uU~f62gbSBdH1F*6yaO$~r)`AG!10xz z2MWlyw*lMBxL|8G7&{WC;)$6eVjC$tq8u?(=GYcikPl)qI?U`X>Q{r&J;n>ht4Ue2SpPYDqv3TcW@mpGW#rtq0 zI7Gt4{Zeazj1COTP@p?YK)5#=I3Ma{0QaJ9n7AjkhzZps2;`V!lj4&*Jf)wB{R1n@ za{_b*`lv&zRF)X+-xkGm9+!s>vtG~KtcsB#3v4FbZmpJwL;I@Ctx z+yy}gS^+XmlV)TNS7e{`N(sk7hx!l>ZM0}5nynTsKr4H&!t-2z>UHtlG_Bm_K4D`9 zrVp2e)XimEXR#D{sVu4t5#h`R+Yu3ppzMQ6+4pR+!xFP6JadK=^H*jN?ksB4EUobi zH9?7%WRtU!?(VNeJKvVu<5kc*O9dR@Hw?IXIS!f&W{~(MD42arfbsKL5WHIn1+1LJ zaa{bMwa*w1^D)u;b3b(`&UY~3;amiEAs76~Icp$?&y__jYolH#GUitEfeGl9pzHxn zo?xJZOURFkC zEK^w>qyg)KKJgO0-C39F(eaGvTrV8h7(777SQ8;<*vRP%*k=UzX*>8?C0Ztd8^qm} z@EB(ZdD=p?-(9-mh@Jr2+7hHACmsV6%?MWRP&jz+Tj~uadtG}1Y z-DDnAEJiT$_m%Ke8x+k04sgeB9bC`;@|Y7vD?z_)G7}#JIfP&x0%-G!a%qH2pcpUUfq^g9LuDhBR_0- zR*ZQ@J;Wiy2aUitfN5qTVk;eXgOU;i&nLS;2NWw*k_yA~Y6HFUSH=*YOxnSY3^E($ z$;e*UQ9FRD8_tVvSsANmDV7bc20K$~-fn>aR}WZQ zY5`cRhe3whFz?}x+-28CKC8`mR$D7x$jqg|zJc%IAa@9LD<2yX_(Ez@Bg-fsCdo4( zmcvGcPOLK5B{yA2PQ73sFw1UA$icqMDFId1OG)xg&-^yg+-LrTg8|@S2k4-JQD<9aYxHW%AJkoNpJyr-R{bvgojf`;G2

    6Ng6D_eW2pSU^sHo8}#iN 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%0D~kSR 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


    K zdN}c_jDQbWJkv~Y>TjmcE7h|(-g+biVk)ueF2#m9{U$EjbX0Kd@~1%VtupUoA4D zd~(Ac=Jvwkh`TeNe=~U*v%QG1*0ue;wWXc>Ds_wfO_m8=*!tf%+BE$Ia6Z;3_)+ zQ6^2Klo|Cz~*AdGTH`q!oz4%~H^KbBjwWb>90y-bRyqW69P=C=d33W4;eMbSO z%|2p5TrJlEm=Dg36B=+~^5<5We~3??rHd$!xk~fIU(Gqh_zN;-`~mY-n^wo1*q}Un zuK$ej*`>3+b}mzA{5H*m+XeS4ADHSqan_jY5E<#nRn(*eSzHYgEeVRv#g6{Y;ON-* zzZe|Hk30@CI4FIwIURY>7X&St(zx*nWC2-}*@Js8z~Ckc1eu`GbpSe#hMx?PfClM; zt7bofj^I@jHGud85C?EQq`fe-j|dMyngar|FHBN2`w~HA9Yi`&1mXl-Cx-`KJp(6( zpot+kTKL`vxCbDB6W|KIl2@w%cKSduF`PCOd>kFFtQ@(=Dco2eQp<_JdY@^t_qI^; zv8n`Y)PT9~k%TuK##=DOv;+EzDI7Mt&*~*7_2~zZF^#g zpddICq7TSxq@5u9r9C@`V=whYJx4{46Qjf1B0Yz(x#-Y*aLkMc-8BRhe?3RFk9*^$ z|8O#v%!qm98i}WeL(#FDRbw&6v2bt~=qhkImkx&#z-_YzK{#>|6G1=>(@uar1>fG9P)t+aPI_gqO7)!`HXiydy){q50P_**yZhkK@)T=5=0tAr-uNr z^?2Ro@)Avbln?f%Wjkx?KEQFqp~IJ)d=T zlrQwzY&rOMoXZh#f?N`Urk)5d3F@qXJsoDg)IVEBBn-I%&K%M4i742IprEH$yUPgg zi43$uVx;;xaN+E1d*WLlF;pGMi%JBc>yoFy025U#bG61|Q9d9#CV# z>SPw}U3b3rX)1Yjs%$TIl;VHSIZYat_9!Xs+0Uk9z~WhPR-eIt*mRUjk66t{2L6+# z;}>VP#Jt<~N7Jz&LrQMmZ3~>=GXveW-7Mv2nWD*15W|snXT2X0aiwG#RtcMqTFx?? zqS=QZr-yMdv!BqHNa@y0Lx9M#+HGi4m0?$faoEk$Phf2c%(jqY$pVDcKsH4#=TKFK zR|(<{Al5cP#jMWx3Su~WmaTxG1s+e&W4Kcq>CPSyb2(PZ1iaS(oy1|yDUq)YIOpw1 zPQL(>ISce2xpdG9+ZD|MXM_5Z0=<&+ldJOKRZ{i>A%?rjB;=?AsT%3WceBcgSn#+# zi2oDA1$tx$Pv@NjlZpkb3x=%Pg7k0!s$aI~(^TPrLH>|)etd_KcXDp-bP-?f`n%gw z4Mc2>{mvKqf=W*rKBocoTpHs)*rF30;Ds!6XC^#BjvKKIh=~6hg~H@iXAYCpp$` zO5%_zYkv6%I`uWDw_P-V#442&lDL}%*Un<|W|i}L)!{K5gY|;K2#=B|4@iBPfdMf+ zl$q_w!Dv$;OpwG?d-NF~l1Z>~ki_-67a{FUVmWZ02dl%9HEYJ|W74}p5?3uGao>k= zkE(KDhR|1#c@js(^d%F%&Xc$Ufvf@waswH5LqOPZhrXPO-~g=sxLduqv7cBc&e(>gY zX8;WnAZ<7(O#vc^lb&*`kVz5govK_FR1z6e7pze}Z$_&1s#q@y z@Iw^BI~ry-LFDEzwAa1y;tvv6$S4I#++NlRtJ-ls@^MP-GAc?7aKC1yDxzhKq14*1bD}sxTC}hR)(a>P@c>rzpgT(D+4QTyA;?()9 z^Rvi-e550baS&Xx9wPhLaFr*sbzyju22a zkKy zT@cM1b1uG1Lp3nl_V5#XJB;YxlJAn9%)*m{okapgb0cJX9v3G1c;xyA*1ltRzu4QJ z`OdI*XGxy{EY{wzAM-5pu952VlJC{cZ)8h(o{zBCOPa5gCR172wU}OKlQeP}!t2qE zPF90GM?a{E3N{_n(pO<07XYFj$5`osohv*Z4HRbC&k14%Ed2TNO-B)Iwsi72_eidm zMq1zAOee4sx<04j`7L47aV+zNO-4G{biDqv=~({HnvSpk+;rUUQ#5hi=tt9$jH{k+ zI{HTXiFsqkfmC^r#AO6bGl1$}B(CzRUqt2k-$~p%8cOFEiL;{N$7xKk>A3$xKjOY` zhTzIi5?2yr{-fzQm#8#P;xwMZjjDj$34%u5pbJab!_xzRU&z3F&hVw=(!@^#vyG*o?%hZpiV;A)=H687QO~?L6UkG9!uDn0yed0sP_hY^X#zD93uQVNZ zgH1;^NLm)%4>R1^^a);YuRl{z%rmki>)^ZnoShpw6wa}|9$=b(X#et--c zcA{IoH5MUtoFV0IQV;>%^JPHaIqk;IC|5s$fc>^uQu68)0sOk|7mP zw-ouJp{+u=56Sx8T9WtdG~WP; zrkC0uRXm-H$z;Fqd%f$lpVNuj7ryt>YP+7DXnVENzHI1K(O5OgsOWu@YI@;^J7(Vt zK0R=)KlAl zDk--{O5PABL;CZ`8@TYca^=busw?!gKn5tJfh)9xG;r;jH3s_Y!P&RXijo#8vfJiI z-fVQ_POSW+bh&j630!#d)Lrq<7v4Z1Xz|0#Tf2SRk9oHh-t$1vXWP$tHy;nf6DLU$ z3ik3ECbG&qmgw34q=C9l@*2X%rILx&3UdpMUDgIx+x6|uK@O;A(Shu`nqn&N1nQ5Vx zyHl&cL8mNueUZCfn2-K>FB?vfZ8l{$IO+BW0lcd7*Ihi<>>ncD5ut_0*mx^+W7K7< z+C+;AhSlG(ztni|mI83e&9S5UD6hn4o&W~?Ab>xLmOt>{>OGfM?TB6H9;IQMt-CWv z)44$RNTKd2uxlw4@$8NlIy-?B<-pzRw7}0bup|vZS$4~5j0Rq8-JNGO2531)!-pY9Q zK^n;8@!Hyd(ZC0H+wOFCcK0-Q_kcTZKh!*a=iR>^yZj$d18LX)rgT}f&g-Ahz@Mc{ z!A?tCkOr!etd69CUf$jxG!XRiDmi~o1K&vy$(q(64IIdv|ltZ2?CJ+L<7@*(!eD`8Yl+Rz&yI=1=ow7&f0LhUd_bxt1Y%bN@4EORU>9D|o@-*K>Rf&@FN`uLJIq!; zqqAp~#%)x3@aLx$LK+x-kiws*ff5NR(RaQ72@PaL3u)j-)hC=&e~||IM*J5v@Pz#> z{2>RmM?xA1-nQ&n8t^*}Jo9dz24*0n_qu>IFps1|(_l#WM1wT&;5-eyB)UPS98Cae z;Du$ze@6p@1yGbD6{LZcvm~+`eP&ec~Ynh-~CKrn+_JDenzv zg1C1W9n$D?CNWGy@NV)eUg%Tff_PpGJf;*BxO z%DeJp*DxL}UTnnz^OiJ(m-Lin&y}MRUT{eBHpxBAl+nwJ!!FC32g!wUu{#4UD4IJU zPCCY@uSsRu6j`gHkXCGQ=yscxPPb^KVg3|})`>ZY`juX&nE#seqbhkus!_mlaMrCz zCZd$wRvB28J!A zOM6x_PCu;fd6(grCo(d=w*IXn-BAEUnnR6&J5HNeOf$ zVC;AaQlOUw-#~`Tp74X1S@$hY;T=edsPNw%`+@Sn3Xs=?w5@;F8y8gLGWqD^dDAP( z{znR+-T9RIJv(2^Y%>t(SY5-)zkM=?k_m}<_%wkivOQ(Z=b%T{glt$~f68lgU)VmU zez}MlPTvZBT9e9gZ+Wj5{RN9+HvY(4>bPn#ms{UhJS{n&w=_wm0vB1@##$R|twZC1 zIPFsZc2B@OQmhQ2bb3^0Bh5xQ>sBq2SGWOi&brrAWpz3c(LHDx>>T{tnzGWX#}<>_ z5}xwoz`Ug(G}#hdc)Rx(Y2bG&@M?6TG|cP$*_rjq`-#TK5{{0Ylb;ocsY9eQBPJr& z&wB0U^f#%FQ#D-ZSrT27^+`m#^Fc2J3achTFOTqkg%9ZE#rug@QYc~y#6i*lzhsR2 z!^G#aZ}k5w8u+4^EK7<@R-r9k=EO&?e*yWe_|s;oi!}39I;%;3iD{4aW{~xdj{)92 z^w;}U4Ur%BeF~dweCNL|NI_$9+*;;CMO7M4eb#-EN+owt?ulsB?0~wF51uXciGXS8 z#hna4%u$v-NHo_h{SfC4m=Z5^Rj;qy#6144me{mv?gQ#0t}J06(ayh3i$7-^IrhMq zSi|3}#k(K-{`;}7A|v14hZ%q=9!3fY$ zILL>(5D8vHAZvnfU;?UQk3`%LL=F%@FHcN{F75^#UI*9-0>DFaFABCBVo@_exHtiI znIMP`2M((Os6-kLq=EMXbwMl$?!2kdCCmXSHK3M_0omFOqG*Q%ZPPj$-a**7Jg5p3 zPT*m5>SZoC1B#Bs3F|mt5#` z>w@6MQCApIOZ?BknP=b>f2=)}hGK-68{em%Esux>OP3e@L;ZM+5;wvH#%`8>RFYE+ zq8C@l1H?(V`xD`jd8eZCfEay99uKK75!;n#i6A42$%OmlHBwHHF+og(>G?jjOvaLz6!#u(QQlED(@v?~+6=mNH# z3A7V1vOyP7Orwf9qoSKeA~KQJn1q89P-QYQjtDprg{8~u69mO6Tq;Ng0f%hb1^9gF zQV|o8X?|faF!JC6Mo6zBMDb-Cn7#1Ur-0?DHlbJ38%RcL9(fm z2eDn`)6$F1$}I|+MN8O`ME%v1ccacV8l-Kar^+^f)W-jRQt7e)dgMpxazy0t-* z0StT^b%kRT%|}leIAp`2VCnKQSy;Mss$%JXVp)%7+Xu4b0D=xR`zTntl*{y@BY5OQ z{8hmHS$Z!7^>##LoDUmuhWS!azO>xQscXoI>>+2&9GS{GOTv5rN8Sop(N)*J-$olV zS?7S9uTS&Fo?aWrTkw{KkC( zdVq>jpUAb5%ew@&CZqEv-1A4&i@<_HAd}UaoZei(N_@sjw#=V7oO`yTpa(2nYNUI9 zz_BR$eG_PG16vNjJ!KQ_5=DlRu-y|NAGrQD3egHOK{no$#=7rHXeQricD*qifQWZK zI~-L!`V1yVJLeO~dT9@qGz*6UPzcZTF3<|BGKvHGByLSVp5;moPco7fdG6Yyb!G9;%cq zs*=L5oM|$Rp7-)rR~y~&KwKi3W{KyI&(pvWgRqV3D@;HdIA6B}uUh1gL^ZfL$Ha2f zZtVMs+apf{K6#`+r*V)>ArKsms_CdMyGUgfP2h({1KwgPhUeVyDcBXim?}& z358y!R85WGN|ISe?2+%}ssV)tZNuuDF^CQ(tZL>uS_8-DvhpVghH~k>f%tfyFmP#M z59-d)p`^xi9+;Zse3)QVG9qR^H7KRB9zAayXVwnguJt6seA%$x^+G|h zCHewe;ax*FDV@v3Z=8TCazs_VAamku#6vaFJ#xHI>uYcvDy4!q6xjCgImhS)f$0S~ zU2WvIzHZS>i`8C?k^LT4XPrVy<=ER6idT9J6JcM4-VG_r-rKVB4$Gy;&^4AjIns7K z_)cYT=F{kM1pm6+i|YDn*04spIH^L0NI0jJQ(V~T&M~rgYkSvTHafz@Xx7baZ=X4g zSISSn{w`ajlZC|B49VUb&PTuZgnSEP(W&SNTzV7@Edu^{F3NVE2HvP)4FtEo_Tr)y zV3Rk6b<1~LXz;gWPFL65eM5r@A*O>UQFg#gnVIZ!lzUY-Qd* zJ)JlXX%{CYfeUYE3Tg|dxW;Mi*HS%0X~M>3B-prAf0kWqq=74iy{H?rDD41&;LDPR z*3$iVSvmVKL+&P5sby%dN2OZn^^_WLpY*GxZZ&VTgIqM*Gd^XQp6@*Ea% zFP|0BhHnGCy!poEq^mCuY+S0})AT@GVb{Aq3phUS<>@_pDYqN;apUWc*Q>@sFE8zN zMe2)baN+ISYskHqVT*)b9`d+gFzMIA8(6y3_9-A2lYw3-TSXZn?g6z|0gT7DAx>8S znG=N8r@br2rLL$l(HTK1XZy5mrEaZ*Xq*MAzNW4^+g~Wzhdl@#BcoPD_LJ+Rbk71- z6#O_4Ys?xruzDasmXJp2w_Gx4-7r9XL$FXAbQ+g%+yrQ`2KN&rbw=P@H2Rj$4ITwE zmlo#ETmV7DRR_JHj!TNa!rO}fC#B0ThfZ$f_g$PDwqPPAdf=C@P{7iqBUrl3MrZ>+ zOP2*<(A|8*&(h^Y|9@J#Y@07#8viI=vgS*d#lq61!>`h%>;GQq(pFfywD|8TU2gqR zx?J_MbZIGCyISi1av;z#N7%a77!JoT@aE(JeIm-WYlrOU2k!qVl^ zzf`*1|9k0j)qLr4>0d8h-Vl~9-_4gUhv!R|LtyDrY}Nnd(xpw+=if`0))!mgmzTg2 zew8ls!P2F1ObllCpG%iq_O+OW(xtsIN~PT1RBVf$!xph4ZHj(U6KDmq?M~(0j9?2h z;_(gbnC&(Orx|H_CfgbnEgy`kh+CHMu=0nLvE4**{}s2>ZZ8s(T>3~$sRhd zma#9o`;2)Hy((ZR>A_jiM?Dcv^azo27UsUrv9y4kNWyN1A;-hR6Cu&g-3B*9P9(Nx zis%rH+h3l(yHR?Rzpm~hr*+7xJ{jMOm{9i4(g0VvLn4_(7c;Z{=Fh!)96-dj>A3m+ zee32hxsRa}l6eCO+m}ET;t&^)B+$cNN+*Y2YEgT$?#-EIcH$sqw;V!YTNOJ8VX{R| zm3c5XY5O^E#~q1Bd|d|;kK_bEvK*G6uiEU~8W|T?eYg=v&*noPT|=pDNh28&O%*cC z0)}G5EY+H*k!r&cvZ3wN&1^1emBQnIHO_;wA`wU_?-p6VV90?NOWfp(5h2M+JG-6R zQV;D!SB_Sq`dUXqG$zl`j#FHRe+zL@U9ad`r{9E^L|fi`5vpe!{Gm0xRVB^P+^t1X zYHqFFVd`>=wWl4sr>3Wy#Fq`GiLd?m)Za!8lDjLj%kCV+F?(ktNrDXZjg9x6K7^K< ztFwo#q?pPv4$uK_Ob3;CvAhwQt*B?Su$2yJk3mc2tD<_((Zvw>4qnp z9BZ0Fkq4EG^;R$ytFj`E@O_ZaQq@I+_K{Y~OXT%Q?G~&Yh$9tYkV$Wb;ukAXvkw%% zTL%{Q`$ZiGBvmvmAl~d=X%4elqi0R)!Hr?^#}g=9S4`a8kG3P8%SEve`&+d{JTk6Vve?vZQo*?b66?-nVC-c}tBWa02dt?>JktImD9 zAV2Q^+L%Q|$}oH7yWG;Xx>tvt+agF3uoGKIIm{h;zvVmFX}O!Mq#Ztd z>1Kz?p)Huj*vhmArKjb&r!9P+wcP{Pt~bAnlN)>%XO6w4aDT+Rse1n{j)~%^%ZcE@ z^#`UOJ+AxOa^mc7)d%LjJg)zapwbW94DN!x?WNc5TqPauNHzGBeK$q_)aZ-$vfQq8awztjMOohcEc5e( zeI4cb4|46ZEYmC>x^@>jl|3rzxLNr42Bj%l(Q0Sm(=zAwf_-;xU4LFdeVCbM<>&dL z+W*t&%R3dT8mnmV!p~NfoZcpect5_Aya2ct0QUmmUI5$+fO`ROF97ZZz`bB_FBsel z2KR!&y94DJPk+lcjS!Qif{pQ(90Q}=yl!QfsnxDTJVUi0u1 z)n?u6Fx@|T&boFRzYdhy8GRSgTQIm64DJPkd%@sdFt`^Iq)Q?TiE^S`<}$Uc9gNEJA+gJEzhkcUfCfc8=}7b?jwbxcsj1y;Y~jUbUp`dcVJVAyMwqxtdor zaIqG-roXdHyUn`Gq{ndqa4#gv7ZT+QiSqxSC(4mf7ytlLix(|gEF~!^DF=QKmzPph z6vGfy5U^#Ei#4UhS1L$tkdxAtkywL-uOP}VmQ)s((iE4`kdV=pl3Rzx5;f$N!O?9^ zbuHBuD!Qs_8ro}hHP&kD8IVY%wInT5MJb!5QrjeP)55wKOoZQII#JqG?BtEHCONG`FIR5X#-*s(&#N_P2CMQv9F zO~0kOfl3=alnhUkbxlth*?DhtU$@yo+uBRjB3RAFSJ%!{-#gI8YRB;d4xT%#PP*7` zb@be_)7!!=*!B1^$_alL>d8~5PQ|QL4Aqd2U%fOzm&he#e2Vv9=B7L^oBwPXub zmV*Y`r0N2=Rn96Px__JNfkD6rH4ZEPF}vYHLKbtx7y)Gol{n|6Q}<0_4;GEwO*Wh zmoo1067K0+jmhz0^@VZy>?_yu(#nd`lCuhF#r25=Ww$B|GxAG{%5GQJ+`dtibLH}l z*1C($HPNkHR%>H+Yf}-gxv06huA{B0gIC+$Ru)s!99q?UrM5M@qN%*LC579T)!16l z)K=WWt8Hv8YiqA=>u3cZUdx@1){c(GhIa7n4*2Tq>}+Y}LH>t5;08Awtzgb!|CK~} zdxF~bKN;K>WjTLqa4TAt3k~iBjXxROHwzwu2Dit{KMd|$MNiAz9{e)6`#aLCDvDqJ zG`MfPuBX9qORRqw+?xA4D@*#@n95cx>)WM+cM^3yUv=It8|q@4#w@X^Dj#`}x4m%x z-Kv{!A9D`hVcAsQ8hc*p+4}Tub;bMF+)$h}tGd#=yD35Qz>?X@PeUn5R_V41RlmKx zknj0AuD1GX^Yf-TtM9gFRl`+bHLskOc_-<*;;z7gR)yqE&a|)ec(%Rndz+GTqjIlauJ)!m=kq;PB4oMjv z7bH$HFT=c@FJ8r|XIceA9W!Haa(ee;r9~bJtTBM1IiP$S0>j54o^m?0Ei?v9b>00b z7TU|vpIzCZQXNcI@SEGN>995K2QD=vWi-n6D>)kLs^iNUD@PEJj-Xl0B~zU%FP62c z6lg4O2%6&114bTMQZzp$jEgD;X$ezH@2)!wM2C=saq+oF4o*fE`5 zcpq~e0$wjxce`E~W@+4Pci)W$tR}yh_t}FFsb;Qbss-cAaV$7u`_@!lY#1C4oiMpU zhG)azYD^^OSOxra<`D>7VtXVR3x7v4MoCLdaGCq9NeMVx!!!j)2nVWg=O!HngL5V# zPGZ9sv&oq?8~A78gMv<6jQ*$a#0(9WYs)&cF3=aXxF`W)chxfJD0>N!9Ao5XlW43g zQ7NMI$`*mO8{sN-`o_s8teM%O+akjeZn5?a z$B#lTq{<(>1mPlFI~^2FqMmFcL)PkTCmQRej9Nq2>GzWn6RTa0keDd0xfV<%BnF1w zxX*rByANZ{(Y5*y)EWDv%T0AeMaWRy=QxRQ30sXY%*u@8Cg>LGda;crV~h1@%6Ih= ztcno_KW^%sTE^=|cEfi!x1E9;q$l77coNVcxq>b7NoJUgwqz2q%gv!;PjW?%kDpS+ zz4X~l3)8Puf*Mhp;Fq|mYhxi0&%~F;%Q>;OE4zrbI5Hu55d@)5gU#JTzc$GeY2H)W z$7ptI9a9tF_Qo#5%!Z_!E>ntmdj!dF9A5Gj+Z_|M@{rWV7{+&GBYL;_1){ajG6~#C zM)jg>^iBIlR5A@OBe7ik9QUy?Qf<>g$ap9wgCb^a9D>7MWJ+735wmJQ*UFFa=vYT| z`ewy-JZ-`;a|pzctzZxaMcjbH+LN=GHiC=;?J3UrK8dkQ3{9aoN?Bc8Wb-OF!IcUH z^VdsyaeG|e9@}1&DY;4)a+qoyb3m6T>gT;II@W<0o7WTcubX}5|6rT(tZ;!c1@*;AK+yL^1|CT8jd1Ex;lunxd zHRBCc-7!+xuuimz?i2S->f9)$x1O)Ri!^qJdg&e5#A{gt=W>r94GE~qex#3UY(rB7 z`7!`PiNr7a^itvw&htqV3|JjuqeWk<$k?8tv7;dFxBMex&PJgo`Ig6szMaktXfzZ@ z?W0}>emkfo`!R}4ra>~cZPvcRff7h`0!-axF_{ZBTi#y)9e#Tt=xAA4)D92FvS$`5 z+pC{TZZ4&%pxv4(qg|jv@2%$7DyDp1ejYa^>iq^{*p4F_gqrtat(KnP(ahgK8rEnDmln~OT};K-`bsk_?uH)|tT?{#I}<{gs~ zOa0pE8b6q1c!p5UM%fIT$WQYbw&j`9cZavGpT5tGE6-N70f&L6yA$t~=d8OsVjDF5 zfK9lWXJ#|HEoHhV&-P})uDhc~;ci--xnSRVA+~P#q z%>VT~+gqhq@4h>_eg@p&zEz%UGv=}9KiJ@YKJ#kwUPay4yWj@*%xj2PCAe5Q5dv;- zqwOjirSAzhxO;*4%4SvD57B#O`((N*Ti4zD5EnGtPZYb&n=`Zhcrj&mK+W!U$F6%H zuT;+tlHzZ7y4rq9{wo{Y_VHCcxwgL*?D;n8)K&GU;@)q?LEqj|#HydP*?uWa`S#Au zuKL;IdtYu+qi#M^{cP*qc&<7);~?WQ{R%zaGks(G`nYwBLm+$XkJ?Xa2Mba%?!=RCXG(Oq5BkE-W>cx{p`8X5Xy;KE;o(`I=KFVu3=O7F6LF#;{b}e#8n%*#e?lWn(f}FyVtu-V6J5%mE|W-?tE4MDp)Z-F z6J4z+L3R&SFqLvtFHJR^gJDmUl9(vb+lu(6G1VjxzK)_I?sgzJuR6szgCZUCD=v4)zDhNm~DqTQ8 zL{zXB>|Ig8!n{vFoteFz*|X0%`@CnL!&)r9vKD+Gzw5s4`yXql6Km`gYZ?|y%!{>X zizQ9RTF=LlMdECA;_RK`9K+(A^5R_D;@qa=w#~=6i^O~C#8aH&eZu1X^5S>4#rsdk z@0pJe5J?EqNeFgI2n|aJ%S(u8ONg3II53|;6=BeI7_m-__%MbJBae~P#z>iFq|Gy! zB8eF~iCIpGIbn%;d5HyWiAB?iN9GfYMUqN&lFFQtD#DVg@{*3@0-;cd)B*y60zbqm zvp&e8;c3u>l@n^^gjzYFR!*pu6KdszS~;OsPN=P!>4 zJRK7W)^nxeUmp`UcTDDv&sD7d`efyVS~;P{z?`lEdIAy zl%^aji_*mXB#QzAr{Bd<@~k+@3aRDfr>mRSj2f&du&_%uCjFHZ3XGt@AnHGvLM=y7U>5cN zC51ZozdC|qafC$(+yD6#suC%W=(b263UzTQg-TK>ullPgREA{~+&+U7 zBcaxV5k|~RU^u`OYC^gV@|H6Vd9yx=l|sQac2M2fRpoz{LZx4%gDF%nR6`jvMO1mh zwUk1Y!SOlMFjfj>%u1oOGg&DVepHE{d+OH|ij2%`@*GuA|7{9Yi+98XqwxSnhNNM; zltRsaPod7u?Ic4x7)vQs8JI#rHCQQBRty~e9895*Wq2@!;$BXn9zc+Q(a%#TJH!Ml zg=(O~kX^q|p`J{TFsYiCzNJvZxCR5>es?g18kOmRqBpZrDD-PX3r=wfD40T7Odw+Zpb>dr4;JgC{#xi-or|vWYw5F^{f;sh!eh)LJhG}sCAl4DO5ik&x3LA!C&V@ znEZVTWlvo*supt|gZfDd1x#Spf+>{3AEr>G05FB}08=Op$N}S4_ zrw&1?cf%IPmQpBVRtnYUKKMd;BH1+s_S+Q7j+H|7CP!+0OQBBvK81=!Hxmufc>yUD z-tQ^Y8TaogRN%K1it)1)$_WD52&Pa`9!TgA1R!3Ki1UZ>e6_eWYEf=PnX4DYgk`^v zLTO_|Y4EoG2ZT=_7~7_#UH2Ax3f6|@!vwrIUA`0;?5RrTx1prKoQ+k+iNLl`e0i{$ zI7K!B#+Mt*ACDuB&iUy?NR5Fh)Y0FjP~-X5J~f#~1{cZl>kZ7z-wb(p_w9gl3Sp^2 z#WZh@9bT^|<(U#ko@O`r4=VG+FxtF`aL#;)2F%GO=FT0#I^1nY)jAtb>k9rVO`@5@ zP8+(LyQqOXYW>^nEr0zIA%{w&NDFduAfsWR{gQhrzK%(C7y5Jw$Qg4yE(@~?EvU7hY z-S|TtV!>Zz-Q5%s-P%)}J;v9xyR}={jhh$_i^^V->zP|0_h64yAu-zZ2=A)5K>Onw zBM!EDAeJB;ji#Y6eC9DFp^${PRM|ZqrypDIFHQB@(Hko?pGmp>={TI9{*?zS5b)^^Uw7IY6_^KMWy`18l^g*P7g_*`Az zF5v?8Uzb9mzv@eRh)3f4uZ%b3e$Au&l0P%yn9`Um`C_NI&$awhEiLev-4FdgUqATd zLr}NX%hQbYCm&d^+sfFjKni!g`8p>#lpu$y3VoYdBH`V;sBRrpcjwX3kE{F) zcnXeYbl#XfAQ$6$_uAXs>-tKMPA-h?x6Ur&Nq9s!nsmWz)m*8(_hX@T9h2$wV6@8D zC#E|-?JZtOq5fS{sPX?u3e}cWGo5sDKB-coG#gt!?3S)N0N`aAhT{CZe7`XaLA_8;gkN7w@V9y)->-V1 z_Of26tgNCSFRLM^u>M5x;afmWd%i42}}JM652DOSez{w7<#S%u3= zA?OzV#40rY2UcNqs2*q){>@d#@U{DMxA1pYU7q==M4QeEb5JboDETH9GO2s=Qlh)c zcP_hy-Hkg~Zed&GvRkNN$z+LzJId53$5?J5_}L*Oj^!36u-rm_TBZTD2Gk4fvRi)D z3oBT9;g(~a&Mdv~%uA zZJ;X^)C-s0!hyaMpj!wkg)F^ruoKh^Q@RFNZsD2VyM_HMxA4^9a97{CU&X@V|LI~O zD;{1t?2!M<4!hoeUN1z-!Mnx@((0lbKAhlT$Mfy58(Go|L!ty}YI4R|qXO1F-QN#8 z-ZwDQUiYQLPN)yR`p031cnymuu<1-DEgyC?mR`82=v0a%8+#9CH5U@p3(Kw{;9@3_!h5Q59&4RT^x1n?R@=R8%tJC-$CDP+2Vie!eKuJ2()ihiro8)Hi_Bu45hDT0O2IngW{gBnE=%9^
    H9sq$V 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.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%0DaxA$CItjMHSiBfKjZ@Fylg& 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

    )mgk^cHM1yOC+kw2W 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

  1. j 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�vL!4 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
  2. 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 z a(&qcbgzixTkZ_3e#`CTeTiezi)1L?uqUu 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�`7r`>%Y>5UP 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 U6%-W|6%-W|6%>{Kqo{cN4z>% From 2b9f14041c1e0ea2022524f1a0d95883d1293681 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Sat, 26 Sep 2015 00:22:21 +0200 Subject: [PATCH 036/211] Added sane option defaults when running valgrind --- CMakeLists.txt | 1 + .../valgrind/include/valgrind/valgrind.h | 6587 +++++++++++++++++ po/POTFILES.in | 1 + po/fr.po | 24 +- src/core/runner.c | 37 + src/entry/main.c | 39 +- 6 files changed, 6677 insertions(+), 12 deletions(-) create mode 100644 dependencies/valgrind/include/valgrind/valgrind.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 063037c2..d3c65a70 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -20,6 +20,7 @@ include_directories( /usr/local/include/ dependencies/libcsptr/include/ dependencies/dyncall/dyncall/ + dependencies/valgrind/include/ ) if (MSVC) diff --git a/dependencies/valgrind/include/valgrind/valgrind.h b/dependencies/valgrind/include/valgrind/valgrind.h new file mode 100644 index 00000000..6954d751 --- /dev/null +++ b/dependencies/valgrind/include/valgrind/valgrind.h @@ -0,0 +1,6587 @@ +/* -*- c -*- + ---------------------------------------------------------------- + + Notice that the following BSD-style license applies to this one + file (valgrind.h) only. The rest of Valgrind is licensed under the + terms of the GNU General Public License, version 2, unless + otherwise indicated. See the COPYING file in the source + distribution for details. + + ---------------------------------------------------------------- + + This file is part of Valgrind, a dynamic binary instrumentation + framework. + + Copyright (C) 2000-2013 Julian Seward. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. The origin of this software must not be misrepresented; you must + not claim that you wrote the original software. If you use this + software in a product, an acknowledgment in the product + documentation would be appreciated but is not required. + + 3. Altered source versions must be plainly marked as such, and must + not be misrepresented as being the original software. + + 4. The name of the author may not be used to endorse or promote + products derived from this software without specific prior written + permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + ---------------------------------------------------------------- + + Notice that the above BSD-style license applies to this one file + (valgrind.h) only. The entire rest of Valgrind is licensed under + the terms of the GNU General Public License, version 2. See the + COPYING file in the source distribution for details. + + ---------------------------------------------------------------- +*/ + + +/* This file is for inclusion into client (your!) code. + + You can use these macros to manipulate and query Valgrind's + execution inside your own programs. + + The resulting executables will still run without Valgrind, just a + little bit more slowly than they otherwise would, but otherwise + unchanged. When not running on valgrind, each client request + consumes very few (eg. 7) instructions, so the resulting performance + loss is negligible unless you plan to execute client requests + millions of times per second. Nevertheless, if that is still a + problem, you can compile with the NVALGRIND symbol defined (gcc + -DNVALGRIND) so that client requests are not even compiled in. */ + +#ifndef __VALGRIND_H +#define __VALGRIND_H + + +/* ------------------------------------------------------------------ */ +/* VERSION NUMBER OF VALGRIND */ +/* ------------------------------------------------------------------ */ + +/* Specify Valgrind's version number, so that user code can + conditionally compile based on our version number. Note that these + were introduced at version 3.6 and so do not exist in version 3.5 + or earlier. The recommended way to use them to check for "version + X.Y or later" is (eg) + +#if defined(__VALGRIND_MAJOR__) && defined(__VALGRIND_MINOR__) \ + && (__VALGRIND_MAJOR__ > 3 \ + || (__VALGRIND_MAJOR__ == 3 && __VALGRIND_MINOR__ >= 6)) +*/ +#define __VALGRIND_MAJOR__ 3 +#define __VALGRIND_MINOR__ 10 + + +#include + +/* Nb: this file might be included in a file compiled with -ansi. So + we can't use C++ style "//" comments nor the "asm" keyword (instead + use "__asm__"). */ + +/* Derive some tags indicating what the target platform is. Note + that in this file we're using the compiler's CPP symbols for + identifying architectures, which are different to the ones we use + within the rest of Valgrind. Note, __powerpc__ is active for both + 32 and 64-bit PPC, whereas __powerpc64__ is only active for the + latter (on Linux, that is). + + Misc note: how to find out what's predefined in gcc by default: + gcc -Wp,-dM somefile.c +*/ +#undef PLAT_x86_darwin +#undef PLAT_amd64_darwin +#undef PLAT_x86_win32 +#undef PLAT_amd64_win64 +#undef PLAT_x86_linux +#undef PLAT_amd64_linux +#undef PLAT_ppc32_linux +#undef PLAT_ppc64be_linux +#undef PLAT_ppc64le_linux +#undef PLAT_arm_linux +#undef PLAT_arm64_linux +#undef PLAT_s390x_linux +#undef PLAT_mips32_linux +#undef PLAT_mips64_linux + + +#if defined(__APPLE__) && defined(__i386__) +# define PLAT_x86_darwin 1 +#elif defined(__APPLE__) && defined(__x86_64__) +# define PLAT_amd64_darwin 1 +#elif (defined(__MINGW32__) && !defined(__MINGW64__)) \ + || defined(__CYGWIN32__) \ + || (defined(_WIN32) && defined(_M_IX86)) +# define PLAT_x86_win32 1 +#elif defined(__MINGW64__) \ + || (defined(_WIN64) && defined(_M_X64)) +# define PLAT_amd64_win64 1 +#elif defined(__linux__) && defined(__i386__) +# define PLAT_x86_linux 1 +#elif defined(__linux__) && defined(__x86_64__) +# define PLAT_amd64_linux 1 +#elif defined(__linux__) && defined(__powerpc__) && !defined(__powerpc64__) +# define PLAT_ppc32_linux 1 +#elif defined(__linux__) && defined(__powerpc__) && defined(__powerpc64__) && _CALL_ELF != 2 +/* Big Endian uses ELF version 1 */ +# define PLAT_ppc64be_linux 1 +#elif defined(__linux__) && defined(__powerpc__) && defined(__powerpc64__) && _CALL_ELF == 2 +/* Little Endian uses ELF version 2 */ +# define PLAT_ppc64le_linux 1 +#elif defined(__linux__) && defined(__arm__) && !defined(__aarch64__) +# define PLAT_arm_linux 1 +#elif defined(__linux__) && defined(__aarch64__) && !defined(__arm__) +# define PLAT_arm64_linux 1 +#elif defined(__linux__) && defined(__s390__) && defined(__s390x__) +# define PLAT_s390x_linux 1 +#elif defined(__linux__) && defined(__mips__) && (__mips==64) +# define PLAT_mips64_linux 1 +#elif defined(__linux__) && defined(__mips__) && (__mips!=64) +# define PLAT_mips32_linux 1 +#else +/* If we're not compiling for our target platform, don't generate + any inline asms. */ +# if !defined(NVALGRIND) +# define NVALGRIND 1 +# endif +#endif + + +/* ------------------------------------------------------------------ */ +/* ARCHITECTURE SPECIFICS for SPECIAL INSTRUCTIONS. There is nothing */ +/* in here of use to end-users -- skip to the next section. */ +/* ------------------------------------------------------------------ */ + +/* + * VALGRIND_DO_CLIENT_REQUEST(): a statement that invokes a Valgrind client + * request. Accepts both pointers and integers as arguments. + * + * VALGRIND_DO_CLIENT_REQUEST_STMT(): a statement that invokes a Valgrind + * client request that does not return a value. + + * VALGRIND_DO_CLIENT_REQUEST_EXPR(): a C expression that invokes a Valgrind + * client request and whose value equals the client request result. Accepts + * both pointers and integers as arguments. Note that such calls are not + * necessarily pure functions -- they may have side effects. + */ + +#define VALGRIND_DO_CLIENT_REQUEST(_zzq_rlval, _zzq_default, \ + _zzq_request, _zzq_arg1, _zzq_arg2, \ + _zzq_arg3, _zzq_arg4, _zzq_arg5) \ + do { (_zzq_rlval) = VALGRIND_DO_CLIENT_REQUEST_EXPR((_zzq_default), \ + (_zzq_request), (_zzq_arg1), (_zzq_arg2), \ + (_zzq_arg3), (_zzq_arg4), (_zzq_arg5)); } while (0) + +#define VALGRIND_DO_CLIENT_REQUEST_STMT(_zzq_request, _zzq_arg1, \ + _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \ + do { (void) VALGRIND_DO_CLIENT_REQUEST_EXPR(0, \ + (_zzq_request), (_zzq_arg1), (_zzq_arg2), \ + (_zzq_arg3), (_zzq_arg4), (_zzq_arg5)); } while (0) + +#if defined(NVALGRIND) + +/* Define NVALGRIND to completely remove the Valgrind magic sequence + from the compiled code (analogous to NDEBUG's effects on + assert()) */ +#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \ + _zzq_default, _zzq_request, \ + _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \ + (_zzq_default) + +#else /* ! NVALGRIND */ + +/* The following defines the magic code sequences which the JITter + spots and handles magically. Don't look too closely at them as + they will rot your brain. + + The assembly code sequences for all architectures is in this one + file. This is because this file must be stand-alone, and we don't + want to have multiple files. + + For VALGRIND_DO_CLIENT_REQUEST, we must ensure that the default + value gets put in the return slot, so that everything works when + this is executed not under Valgrind. Args are passed in a memory + block, and so there's no intrinsic limit to the number that could + be passed, but it's currently five. + + The macro args are: + _zzq_rlval result lvalue + _zzq_default default value (result returned when running on real CPU) + _zzq_request request code + _zzq_arg1..5 request params + + The other two macros are used to support function wrapping, and are + a lot simpler. VALGRIND_GET_NR_CONTEXT returns the value of the + guest's NRADDR pseudo-register and whatever other information is + needed to safely run the call original from the wrapper: on + ppc64-linux, the R2 value at the divert point is also needed. This + information is abstracted into a user-visible type, OrigFn. + + VALGRIND_CALL_NOREDIR_* behaves the same as the following on the + guest, but guarantees that the branch instruction will not be + redirected: x86: call *%eax, amd64: call *%rax, ppc32/ppc64: + branch-and-link-to-r11. VALGRIND_CALL_NOREDIR is just text, not a + complete inline asm, since it needs to be combined with more magic + inline asm stuff to be useful. +*/ + +/* ------------------------- x86-{linux,darwin} ---------------- */ + +#if defined(PLAT_x86_linux) || defined(PLAT_x86_darwin) \ + || (defined(PLAT_x86_win32) && defined(__GNUC__)) + +typedef + struct { + unsigned int nraddr; /* where's the code? */ + } + OrigFn; + +#define __SPECIAL_INSTRUCTION_PREAMBLE \ + "roll $3, %%edi ; roll $13, %%edi\n\t" \ + "roll $29, %%edi ; roll $19, %%edi\n\t" + +#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \ + _zzq_default, _zzq_request, \ + _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \ + __extension__ \ + ({volatile unsigned int _zzq_args[6]; \ + volatile unsigned int _zzq_result; \ + _zzq_args[0] = (unsigned int)(_zzq_request); \ + _zzq_args[1] = (unsigned int)(_zzq_arg1); \ + _zzq_args[2] = (unsigned int)(_zzq_arg2); \ + _zzq_args[3] = (unsigned int)(_zzq_arg3); \ + _zzq_args[4] = (unsigned int)(_zzq_arg4); \ + _zzq_args[5] = (unsigned int)(_zzq_arg5); \ + __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ + /* %EDX = client_request ( %EAX ) */ \ + "xchgl %%ebx,%%ebx" \ + : "=d" (_zzq_result) \ + : "a" (&_zzq_args[0]), "0" (_zzq_default) \ + : "cc", "memory" \ + ); \ + _zzq_result; \ + }) + +#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \ + { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \ + volatile unsigned int __addr; \ + __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ + /* %EAX = guest_NRADDR */ \ + "xchgl %%ecx,%%ecx" \ + : "=a" (__addr) \ + : \ + : "cc", "memory" \ + ); \ + _zzq_orig->nraddr = __addr; \ + } + +#define VALGRIND_CALL_NOREDIR_EAX \ + __SPECIAL_INSTRUCTION_PREAMBLE \ + /* call-noredir *%EAX */ \ + "xchgl %%edx,%%edx\n\t" + +#define VALGRIND_VEX_INJECT_IR() \ + do { \ + __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ + "xchgl %%edi,%%edi\n\t" \ + : : : "cc", "memory" \ + ); \ + } while (0) + +#endif /* PLAT_x86_linux || PLAT_x86_darwin || (PLAT_x86_win32 && __GNUC__) */ + +/* ------------------------- x86-Win32 ------------------------- */ + +#if defined(PLAT_x86_win32) && !defined(__GNUC__) + +typedef + struct { + unsigned int nraddr; /* where's the code? */ + } + OrigFn; + +#if defined(_MSC_VER) + +#define __SPECIAL_INSTRUCTION_PREAMBLE \ + __asm rol edi, 3 __asm rol edi, 13 \ + __asm rol edi, 29 __asm rol edi, 19 + +#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \ + _zzq_default, _zzq_request, \ + _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \ + valgrind_do_client_request_expr((uintptr_t)(_zzq_default), \ + (uintptr_t)(_zzq_request), (uintptr_t)(_zzq_arg1), \ + (uintptr_t)(_zzq_arg2), (uintptr_t)(_zzq_arg3), \ + (uintptr_t)(_zzq_arg4), (uintptr_t)(_zzq_arg5)) + +static __inline uintptr_t +valgrind_do_client_request_expr(uintptr_t _zzq_default, uintptr_t _zzq_request, + uintptr_t _zzq_arg1, uintptr_t _zzq_arg2, + uintptr_t _zzq_arg3, uintptr_t _zzq_arg4, + uintptr_t _zzq_arg5) +{ + volatile uintptr_t _zzq_args[6]; + volatile unsigned int _zzq_result; + _zzq_args[0] = (uintptr_t)(_zzq_request); + _zzq_args[1] = (uintptr_t)(_zzq_arg1); + _zzq_args[2] = (uintptr_t)(_zzq_arg2); + _zzq_args[3] = (uintptr_t)(_zzq_arg3); + _zzq_args[4] = (uintptr_t)(_zzq_arg4); + _zzq_args[5] = (uintptr_t)(_zzq_arg5); + __asm { __asm lea eax, _zzq_args __asm mov edx, _zzq_default + __SPECIAL_INSTRUCTION_PREAMBLE + /* %EDX = client_request ( %EAX ) */ + __asm xchg ebx,ebx + __asm mov _zzq_result, edx + } + return _zzq_result; +} + +#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \ + { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \ + volatile unsigned int __addr; \ + __asm { __SPECIAL_INSTRUCTION_PREAMBLE \ + /* %EAX = guest_NRADDR */ \ + __asm xchg ecx,ecx \ + __asm mov __addr, eax \ + } \ + _zzq_orig->nraddr = __addr; \ + } + +#define VALGRIND_CALL_NOREDIR_EAX ERROR + +#define VALGRIND_VEX_INJECT_IR() \ + do { \ + __asm { __SPECIAL_INSTRUCTION_PREAMBLE \ + __asm xchg edi,edi \ + } \ + } while (0) + +#else +#error Unsupported compiler. +#endif + +#endif /* PLAT_x86_win32 */ + +/* ------------------------ amd64-{linux,darwin} --------------- */ + +#if defined(PLAT_amd64_linux) || defined(PLAT_amd64_darwin) \ + || (defined(PLAT_amd64_win64) && defined(__GNUC__)) + +typedef + struct { + unsigned long long int nraddr; /* where's the code? */ + } + OrigFn; + +#define __SPECIAL_INSTRUCTION_PREAMBLE \ + "rolq $3, %%rdi ; rolq $13, %%rdi\n\t" \ + "rolq $61, %%rdi ; rolq $51, %%rdi\n\t" + +#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \ + _zzq_default, _zzq_request, \ + _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \ + __extension__ \ + ({ volatile unsigned long long int _zzq_args[6]; \ + volatile unsigned long long int _zzq_result; \ + _zzq_args[0] = (unsigned long long int)(_zzq_request); \ + _zzq_args[1] = (unsigned long long int)(_zzq_arg1); \ + _zzq_args[2] = (unsigned long long int)(_zzq_arg2); \ + _zzq_args[3] = (unsigned long long int)(_zzq_arg3); \ + _zzq_args[4] = (unsigned long long int)(_zzq_arg4); \ + _zzq_args[5] = (unsigned long long int)(_zzq_arg5); \ + __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ + /* %RDX = client_request ( %RAX ) */ \ + "xchgq %%rbx,%%rbx" \ + : "=d" (_zzq_result) \ + : "a" (&_zzq_args[0]), "0" (_zzq_default) \ + : "cc", "memory" \ + ); \ + _zzq_result; \ + }) + +#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \ + { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \ + volatile unsigned long long int __addr; \ + __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ + /* %RAX = guest_NRADDR */ \ + "xchgq %%rcx,%%rcx" \ + : "=a" (__addr) \ + : \ + : "cc", "memory" \ + ); \ + _zzq_orig->nraddr = __addr; \ + } + +#define VALGRIND_CALL_NOREDIR_RAX \ + __SPECIAL_INSTRUCTION_PREAMBLE \ + /* call-noredir *%RAX */ \ + "xchgq %%rdx,%%rdx\n\t" + +#define VALGRIND_VEX_INJECT_IR() \ + do { \ + __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ + "xchgq %%rdi,%%rdi\n\t" \ + : : : "cc", "memory" \ + ); \ + } while (0) + +#endif /* PLAT_amd64_linux || PLAT_amd64_darwin */ + +/* ------------------------- amd64-Win64 ------------------------- */ + +#if defined(PLAT_amd64_win64) && !defined(__GNUC__) + +#error Unsupported compiler. + +#endif /* PLAT_amd64_win64 */ + +/* ------------------------ ppc32-linux ------------------------ */ + +#if defined(PLAT_ppc32_linux) + +typedef + struct { + unsigned int nraddr; /* where's the code? */ + } + OrigFn; + +#define __SPECIAL_INSTRUCTION_PREAMBLE \ + "rlwinm 0,0,3,0,31 ; rlwinm 0,0,13,0,31\n\t" \ + "rlwinm 0,0,29,0,31 ; rlwinm 0,0,19,0,31\n\t" + +#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \ + _zzq_default, _zzq_request, \ + _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \ + \ + __extension__ \ + ({ unsigned int _zzq_args[6]; \ + unsigned int _zzq_result; \ + unsigned int* _zzq_ptr; \ + _zzq_args[0] = (unsigned int)(_zzq_request); \ + _zzq_args[1] = (unsigned int)(_zzq_arg1); \ + _zzq_args[2] = (unsigned int)(_zzq_arg2); \ + _zzq_args[3] = (unsigned int)(_zzq_arg3); \ + _zzq_args[4] = (unsigned int)(_zzq_arg4); \ + _zzq_args[5] = (unsigned int)(_zzq_arg5); \ + _zzq_ptr = _zzq_args; \ + __asm__ volatile("mr 3,%1\n\t" /*default*/ \ + "mr 4,%2\n\t" /*ptr*/ \ + __SPECIAL_INSTRUCTION_PREAMBLE \ + /* %R3 = client_request ( %R4 ) */ \ + "or 1,1,1\n\t" \ + "mr %0,3" /*result*/ \ + : "=b" (_zzq_result) \ + : "b" (_zzq_default), "b" (_zzq_ptr) \ + : "cc", "memory", "r3", "r4"); \ + _zzq_result; \ + }) + +#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \ + { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \ + unsigned int __addr; \ + __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ + /* %R3 = guest_NRADDR */ \ + "or 2,2,2\n\t" \ + "mr %0,3" \ + : "=b" (__addr) \ + : \ + : "cc", "memory", "r3" \ + ); \ + _zzq_orig->nraddr = __addr; \ + } + +#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ + __SPECIAL_INSTRUCTION_PREAMBLE \ + /* branch-and-link-to-noredir *%R11 */ \ + "or 3,3,3\n\t" + +#define VALGRIND_VEX_INJECT_IR() \ + do { \ + __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ + "or 5,5,5\n\t" \ + ); \ + } while (0) + +#endif /* PLAT_ppc32_linux */ + +/* ------------------------ ppc64-linux ------------------------ */ + +#if defined(PLAT_ppc64be_linux) + +typedef + struct { + unsigned long long int nraddr; /* where's the code? */ + unsigned long long int r2; /* what tocptr do we need? */ + } + OrigFn; + +#define __SPECIAL_INSTRUCTION_PREAMBLE \ + "rotldi 0,0,3 ; rotldi 0,0,13\n\t" \ + "rotldi 0,0,61 ; rotldi 0,0,51\n\t" + +#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \ + _zzq_default, _zzq_request, \ + _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \ + \ + __extension__ \ + ({ unsigned long long int _zzq_args[6]; \ + unsigned long long int _zzq_result; \ + unsigned long long int* _zzq_ptr; \ + _zzq_args[0] = (unsigned long long int)(_zzq_request); \ + _zzq_args[1] = (unsigned long long int)(_zzq_arg1); \ + _zzq_args[2] = (unsigned long long int)(_zzq_arg2); \ + _zzq_args[3] = (unsigned long long int)(_zzq_arg3); \ + _zzq_args[4] = (unsigned long long int)(_zzq_arg4); \ + _zzq_args[5] = (unsigned long long int)(_zzq_arg5); \ + _zzq_ptr = _zzq_args; \ + __asm__ volatile("mr 3,%1\n\t" /*default*/ \ + "mr 4,%2\n\t" /*ptr*/ \ + __SPECIAL_INSTRUCTION_PREAMBLE \ + /* %R3 = client_request ( %R4 ) */ \ + "or 1,1,1\n\t" \ + "mr %0,3" /*result*/ \ + : "=b" (_zzq_result) \ + : "b" (_zzq_default), "b" (_zzq_ptr) \ + : "cc", "memory", "r3", "r4"); \ + _zzq_result; \ + }) + +#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \ + { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \ + unsigned long long int __addr; \ + __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ + /* %R3 = guest_NRADDR */ \ + "or 2,2,2\n\t" \ + "mr %0,3" \ + : "=b" (__addr) \ + : \ + : "cc", "memory", "r3" \ + ); \ + _zzq_orig->nraddr = __addr; \ + __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ + /* %R3 = guest_NRADDR_GPR2 */ \ + "or 4,4,4\n\t" \ + "mr %0,3" \ + : "=b" (__addr) \ + : \ + : "cc", "memory", "r3" \ + ); \ + _zzq_orig->r2 = __addr; \ + } + +#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ + __SPECIAL_INSTRUCTION_PREAMBLE \ + /* branch-and-link-to-noredir *%R11 */ \ + "or 3,3,3\n\t" + +#define VALGRIND_VEX_INJECT_IR() \ + do { \ + __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ + "or 5,5,5\n\t" \ + ); \ + } while (0) + +#endif /* PLAT_ppc64be_linux */ + +#if defined(PLAT_ppc64le_linux) + +typedef + struct { + unsigned long long int nraddr; /* where's the code? */ + unsigned long long int r2; /* what tocptr do we need? */ + } + OrigFn; + +#define __SPECIAL_INSTRUCTION_PREAMBLE \ + "rotldi 0,0,3 ; rotldi 0,0,13\n\t" \ + "rotldi 0,0,61 ; rotldi 0,0,51\n\t" + +#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \ + _zzq_default, _zzq_request, \ + _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \ + \ + __extension__ \ + ({ unsigned long long int _zzq_args[6]; \ + unsigned long long int _zzq_result; \ + unsigned long long int* _zzq_ptr; \ + _zzq_args[0] = (unsigned long long int)(_zzq_request); \ + _zzq_args[1] = (unsigned long long int)(_zzq_arg1); \ + _zzq_args[2] = (unsigned long long int)(_zzq_arg2); \ + _zzq_args[3] = (unsigned long long int)(_zzq_arg3); \ + _zzq_args[4] = (unsigned long long int)(_zzq_arg4); \ + _zzq_args[5] = (unsigned long long int)(_zzq_arg5); \ + _zzq_ptr = _zzq_args; \ + __asm__ volatile("mr 3,%1\n\t" /*default*/ \ + "mr 4,%2\n\t" /*ptr*/ \ + __SPECIAL_INSTRUCTION_PREAMBLE \ + /* %R3 = client_request ( %R4 ) */ \ + "or 1,1,1\n\t" \ + "mr %0,3" /*result*/ \ + : "=b" (_zzq_result) \ + : "b" (_zzq_default), "b" (_zzq_ptr) \ + : "cc", "memory", "r3", "r4"); \ + _zzq_result; \ + }) + +#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \ + { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \ + unsigned long long int __addr; \ + __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ + /* %R3 = guest_NRADDR */ \ + "or 2,2,2\n\t" \ + "mr %0,3" \ + : "=b" (__addr) \ + : \ + : "cc", "memory", "r3" \ + ); \ + _zzq_orig->nraddr = __addr; \ + __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ + /* %R3 = guest_NRADDR_GPR2 */ \ + "or 4,4,4\n\t" \ + "mr %0,3" \ + : "=b" (__addr) \ + : \ + : "cc", "memory", "r3" \ + ); \ + _zzq_orig->r2 = __addr; \ + } + +#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R12 \ + __SPECIAL_INSTRUCTION_PREAMBLE \ + /* branch-and-link-to-noredir *%R12 */ \ + "or 3,3,3\n\t" + +#define VALGRIND_VEX_INJECT_IR() \ + do { \ + __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ + "or 5,5,5\n\t" \ + ); \ + } while (0) + +#endif /* PLAT_ppc64le_linux */ + +/* ------------------------- arm-linux ------------------------- */ + +#if defined(PLAT_arm_linux) + +typedef + struct { + unsigned int nraddr; /* where's the code? */ + } + OrigFn; + +#define __SPECIAL_INSTRUCTION_PREAMBLE \ + "mov r12, r12, ror #3 ; mov r12, r12, ror #13 \n\t" \ + "mov r12, r12, ror #29 ; mov r12, r12, ror #19 \n\t" + +#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \ + _zzq_default, _zzq_request, \ + _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \ + \ + __extension__ \ + ({volatile unsigned int _zzq_args[6]; \ + volatile unsigned int _zzq_result; \ + _zzq_args[0] = (unsigned int)(_zzq_request); \ + _zzq_args[1] = (unsigned int)(_zzq_arg1); \ + _zzq_args[2] = (unsigned int)(_zzq_arg2); \ + _zzq_args[3] = (unsigned int)(_zzq_arg3); \ + _zzq_args[4] = (unsigned int)(_zzq_arg4); \ + _zzq_args[5] = (unsigned int)(_zzq_arg5); \ + __asm__ volatile("mov r3, %1\n\t" /*default*/ \ + "mov r4, %2\n\t" /*ptr*/ \ + __SPECIAL_INSTRUCTION_PREAMBLE \ + /* R3 = client_request ( R4 ) */ \ + "orr r10, r10, r10\n\t" \ + "mov %0, r3" /*result*/ \ + : "=r" (_zzq_result) \ + : "r" (_zzq_default), "r" (&_zzq_args[0]) \ + : "cc","memory", "r3", "r4"); \ + _zzq_result; \ + }) + +#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \ + { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \ + unsigned int __addr; \ + __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ + /* R3 = guest_NRADDR */ \ + "orr r11, r11, r11\n\t" \ + "mov %0, r3" \ + : "=r" (__addr) \ + : \ + : "cc", "memory", "r3" \ + ); \ + _zzq_orig->nraddr = __addr; \ + } + +#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \ + __SPECIAL_INSTRUCTION_PREAMBLE \ + /* branch-and-link-to-noredir *%R4 */ \ + "orr r12, r12, r12\n\t" + +#define VALGRIND_VEX_INJECT_IR() \ + do { \ + __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ + "orr r9, r9, r9\n\t" \ + : : : "cc", "memory" \ + ); \ + } while (0) + +#endif /* PLAT_arm_linux */ + +/* ------------------------ arm64-linux ------------------------- */ + +#if defined(PLAT_arm64_linux) + +typedef + struct { + unsigned long long int nraddr; /* where's the code? */ + } + OrigFn; + +#define __SPECIAL_INSTRUCTION_PREAMBLE \ + "ror x12, x12, #3 ; ror x12, x12, #13 \n\t" \ + "ror x12, x12, #51 ; ror x12, x12, #61 \n\t" + +#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \ + _zzq_default, _zzq_request, \ + _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \ + \ + __extension__ \ + ({volatile unsigned long long int _zzq_args[6]; \ + volatile unsigned long long int _zzq_result; \ + _zzq_args[0] = (unsigned long long int)(_zzq_request); \ + _zzq_args[1] = (unsigned long long int)(_zzq_arg1); \ + _zzq_args[2] = (unsigned long long int)(_zzq_arg2); \ + _zzq_args[3] = (unsigned long long int)(_zzq_arg3); \ + _zzq_args[4] = (unsigned long long int)(_zzq_arg4); \ + _zzq_args[5] = (unsigned long long int)(_zzq_arg5); \ + __asm__ volatile("mov x3, %1\n\t" /*default*/ \ + "mov x4, %2\n\t" /*ptr*/ \ + __SPECIAL_INSTRUCTION_PREAMBLE \ + /* X3 = client_request ( X4 ) */ \ + "orr x10, x10, x10\n\t" \ + "mov %0, x3" /*result*/ \ + : "=r" (_zzq_result) \ + : "r" (_zzq_default), "r" (&_zzq_args[0]) \ + : "cc","memory", "x3", "x4"); \ + _zzq_result; \ + }) + +#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \ + { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \ + unsigned long long int __addr; \ + __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ + /* X3 = guest_NRADDR */ \ + "orr x11, x11, x11\n\t" \ + "mov %0, x3" \ + : "=r" (__addr) \ + : \ + : "cc", "memory", "x3" \ + ); \ + _zzq_orig->nraddr = __addr; \ + } + +#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8 \ + __SPECIAL_INSTRUCTION_PREAMBLE \ + /* branch-and-link-to-noredir X8 */ \ + "orr x12, x12, x12\n\t" + +#define VALGRIND_VEX_INJECT_IR() \ + do { \ + __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ + "orr x9, x9, x9\n\t" \ + : : : "cc", "memory" \ + ); \ + } while (0) + +#endif /* PLAT_arm64_linux */ + +/* ------------------------ s390x-linux ------------------------ */ + +#if defined(PLAT_s390x_linux) + +typedef + struct { + unsigned long long int nraddr; /* where's the code? */ + } + OrigFn; + +/* __SPECIAL_INSTRUCTION_PREAMBLE will be used to identify Valgrind specific + * code. This detection is implemented in platform specific toIR.c + * (e.g. VEX/priv/guest_s390_decoder.c). + */ +#define __SPECIAL_INSTRUCTION_PREAMBLE \ + "lr 15,15\n\t" \ + "lr 1,1\n\t" \ + "lr 2,2\n\t" \ + "lr 3,3\n\t" + +#define __CLIENT_REQUEST_CODE "lr 2,2\n\t" +#define __GET_NR_CONTEXT_CODE "lr 3,3\n\t" +#define __CALL_NO_REDIR_CODE "lr 4,4\n\t" +#define __VEX_INJECT_IR_CODE "lr 5,5\n\t" + +#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \ + _zzq_default, _zzq_request, \ + _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \ + __extension__ \ + ({volatile unsigned long long int _zzq_args[6]; \ + volatile unsigned long long int _zzq_result; \ + _zzq_args[0] = (unsigned long long int)(_zzq_request); \ + _zzq_args[1] = (unsigned long long int)(_zzq_arg1); \ + _zzq_args[2] = (unsigned long long int)(_zzq_arg2); \ + _zzq_args[3] = (unsigned long long int)(_zzq_arg3); \ + _zzq_args[4] = (unsigned long long int)(_zzq_arg4); \ + _zzq_args[5] = (unsigned long long int)(_zzq_arg5); \ + __asm__ volatile(/* r2 = args */ \ + "lgr 2,%1\n\t" \ + /* r3 = default */ \ + "lgr 3,%2\n\t" \ + __SPECIAL_INSTRUCTION_PREAMBLE \ + __CLIENT_REQUEST_CODE \ + /* results = r3 */ \ + "lgr %0, 3\n\t" \ + : "=d" (_zzq_result) \ + : "a" (&_zzq_args[0]), "0" (_zzq_default) \ + : "cc", "2", "3", "memory" \ + ); \ + _zzq_result; \ + }) + +#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \ + { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \ + volatile unsigned long long int __addr; \ + __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ + __GET_NR_CONTEXT_CODE \ + "lgr %0, 3\n\t" \ + : "=a" (__addr) \ + : \ + : "cc", "3", "memory" \ + ); \ + _zzq_orig->nraddr = __addr; \ + } + +#define VALGRIND_CALL_NOREDIR_R1 \ + __SPECIAL_INSTRUCTION_PREAMBLE \ + __CALL_NO_REDIR_CODE + +#define VALGRIND_VEX_INJECT_IR() \ + do { \ + __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ + __VEX_INJECT_IR_CODE); \ + } while (0) + +#endif /* PLAT_s390x_linux */ + +/* ------------------------- mips32-linux ---------------- */ + +#if defined(PLAT_mips32_linux) + +typedef + struct { + unsigned int nraddr; /* where's the code? */ + } + OrigFn; + +/* .word 0x342 + * .word 0x742 + * .word 0xC2 + * .word 0x4C2*/ +#define __SPECIAL_INSTRUCTION_PREAMBLE \ + "srl $0, $0, 13\n\t" \ + "srl $0, $0, 29\n\t" \ + "srl $0, $0, 3\n\t" \ + "srl $0, $0, 19\n\t" + +#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \ + _zzq_default, _zzq_request, \ + _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \ + __extension__ \ + ({ volatile unsigned int _zzq_args[6]; \ + volatile unsigned int _zzq_result; \ + _zzq_args[0] = (unsigned int)(_zzq_request); \ + _zzq_args[1] = (unsigned int)(_zzq_arg1); \ + _zzq_args[2] = (unsigned int)(_zzq_arg2); \ + _zzq_args[3] = (unsigned int)(_zzq_arg3); \ + _zzq_args[4] = (unsigned int)(_zzq_arg4); \ + _zzq_args[5] = (unsigned int)(_zzq_arg5); \ + __asm__ volatile("move $11, %1\n\t" /*default*/ \ + "move $12, %2\n\t" /*ptr*/ \ + __SPECIAL_INSTRUCTION_PREAMBLE \ + /* T3 = client_request ( T4 ) */ \ + "or $13, $13, $13\n\t" \ + "move %0, $11\n\t" /*result*/ \ + : "=r" (_zzq_result) \ + : "r" (_zzq_default), "r" (&_zzq_args[0]) \ + : "$11", "$12"); \ + _zzq_result; \ + }) + +#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \ + { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \ + volatile unsigned int __addr; \ + __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ + /* %t9 = guest_NRADDR */ \ + "or $14, $14, $14\n\t" \ + "move %0, $11" /*result*/ \ + : "=r" (__addr) \ + : \ + : "$11" \ + ); \ + _zzq_orig->nraddr = __addr; \ + } + +#define VALGRIND_CALL_NOREDIR_T9 \ + __SPECIAL_INSTRUCTION_PREAMBLE \ + /* call-noredir *%t9 */ \ + "or $15, $15, $15\n\t" + +#define VALGRIND_VEX_INJECT_IR() \ + do { \ + __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ + "or $11, $11, $11\n\t" \ + ); \ + } while (0) + + +#endif /* PLAT_mips32_linux */ + +/* ------------------------- mips64-linux ---------------- */ + +#if defined(PLAT_mips64_linux) + +typedef + struct { + unsigned long long nraddr; /* where's the code? */ + } + OrigFn; + +/* dsll $0,$0, 3 + * dsll $0,$0, 13 + * dsll $0,$0, 29 + * dsll $0,$0, 19*/ +#define __SPECIAL_INSTRUCTION_PREAMBLE \ + "dsll $0,$0, 3 ; dsll $0,$0,13\n\t" \ + "dsll $0,$0,29 ; dsll $0,$0,19\n\t" + +#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \ + _zzq_default, _zzq_request, \ + _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \ + __extension__ \ + ({ volatile unsigned long long int _zzq_args[6]; \ + volatile unsigned long long int _zzq_result; \ + _zzq_args[0] = (unsigned long long int)(_zzq_request); \ + _zzq_args[1] = (unsigned long long int)(_zzq_arg1); \ + _zzq_args[2] = (unsigned long long int)(_zzq_arg2); \ + _zzq_args[3] = (unsigned long long int)(_zzq_arg3); \ + _zzq_args[4] = (unsigned long long int)(_zzq_arg4); \ + _zzq_args[5] = (unsigned long long int)(_zzq_arg5); \ + __asm__ volatile("move $11, %1\n\t" /*default*/ \ + "move $12, %2\n\t" /*ptr*/ \ + __SPECIAL_INSTRUCTION_PREAMBLE \ + /* $11 = client_request ( $12 ) */ \ + "or $13, $13, $13\n\t" \ + "move %0, $11\n\t" /*result*/ \ + : "=r" (_zzq_result) \ + : "r" (_zzq_default), "r" (&_zzq_args[0]) \ + : "$11", "$12"); \ + _zzq_result; \ + }) + +#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \ + { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \ + volatile unsigned long long int __addr; \ + __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ + /* $11 = guest_NRADDR */ \ + "or $14, $14, $14\n\t" \ + "move %0, $11" /*result*/ \ + : "=r" (__addr) \ + : \ + : "$11"); \ + _zzq_orig->nraddr = __addr; \ + } + +#define VALGRIND_CALL_NOREDIR_T9 \ + __SPECIAL_INSTRUCTION_PREAMBLE \ + /* call-noredir $25 */ \ + "or $15, $15, $15\n\t" + +#define VALGRIND_VEX_INJECT_IR() \ + do { \ + __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ + "or $11, $11, $11\n\t" \ + ); \ + } while (0) + +#endif /* PLAT_mips64_linux */ + +/* Insert assembly code for other platforms here... */ + +#endif /* NVALGRIND */ + + +/* ------------------------------------------------------------------ */ +/* PLATFORM SPECIFICS for FUNCTION WRAPPING. This is all very */ +/* ugly. It's the least-worst tradeoff I can think of. */ +/* ------------------------------------------------------------------ */ + +/* This section defines magic (a.k.a appalling-hack) macros for doing + guaranteed-no-redirection macros, so as to get from function + wrappers to the functions they are wrapping. The whole point is to + construct standard call sequences, but to do the call itself with a + special no-redirect call pseudo-instruction that the JIT + understands and handles specially. This section is long and + repetitious, and I can't see a way to make it shorter. + + The naming scheme is as follows: + + CALL_FN_{W,v}_{v,W,WW,WWW,WWWW,5W,6W,7W,etc} + + 'W' stands for "word" and 'v' for "void". Hence there are + different macros for calling arity 0, 1, 2, 3, 4, etc, functions, + and for each, the possibility of returning a word-typed result, or + no result. +*/ + +/* Use these to write the name of your wrapper. NOTE: duplicates + VG_WRAP_FUNCTION_Z{U,Z} in pub_tool_redir.h. NOTE also: inserts + the default behaviour equivalance class tag "0000" into the name. + See pub_tool_redir.h for details -- normally you don't need to + think about this, though. */ + +/* Use an extra level of macroisation so as to ensure the soname/fnname + args are fully macro-expanded before pasting them together. */ +#define VG_CONCAT4(_aa,_bb,_cc,_dd) _aa##_bb##_cc##_dd + +#define I_WRAP_SONAME_FNNAME_ZU(soname,fnname) \ + VG_CONCAT4(_vgw00000ZU_,soname,_,fnname) + +#define I_WRAP_SONAME_FNNAME_ZZ(soname,fnname) \ + VG_CONCAT4(_vgw00000ZZ_,soname,_,fnname) + +/* Use this macro from within a wrapper function to collect the + context (address and possibly other info) of the original function. + Once you have that you can then use it in one of the CALL_FN_ + macros. The type of the argument _lval is OrigFn. */ +#define VALGRIND_GET_ORIG_FN(_lval) VALGRIND_GET_NR_CONTEXT(_lval) + +/* Also provide end-user facilities for function replacement, rather + than wrapping. A replacement function differs from a wrapper in + that it has no way to get hold of the original function being + called, and hence no way to call onwards to it. In a replacement + function, VALGRIND_GET_ORIG_FN always returns zero. */ + +#define I_REPLACE_SONAME_FNNAME_ZU(soname,fnname) \ + VG_CONCAT4(_vgr00000ZU_,soname,_,fnname) + +#define I_REPLACE_SONAME_FNNAME_ZZ(soname,fnname) \ + VG_CONCAT4(_vgr00000ZZ_,soname,_,fnname) + +/* Derivatives of the main macros below, for calling functions + returning void. */ + +#define CALL_FN_v_v(fnptr) \ + do { volatile unsigned long _junk; \ + CALL_FN_W_v(_junk,fnptr); } while (0) + +#define CALL_FN_v_W(fnptr, arg1) \ + do { volatile unsigned long _junk; \ + CALL_FN_W_W(_junk,fnptr,arg1); } while (0) + +#define CALL_FN_v_WW(fnptr, arg1,arg2) \ + do { volatile unsigned long _junk; \ + CALL_FN_W_WW(_junk,fnptr,arg1,arg2); } while (0) + +#define CALL_FN_v_WWW(fnptr, arg1,arg2,arg3) \ + do { volatile unsigned long _junk; \ + CALL_FN_W_WWW(_junk,fnptr,arg1,arg2,arg3); } while (0) + +#define CALL_FN_v_WWWW(fnptr, arg1,arg2,arg3,arg4) \ + do { volatile unsigned long _junk; \ + CALL_FN_W_WWWW(_junk,fnptr,arg1,arg2,arg3,arg4); } while (0) + +#define CALL_FN_v_5W(fnptr, arg1,arg2,arg3,arg4,arg5) \ + do { volatile unsigned long _junk; \ + CALL_FN_W_5W(_junk,fnptr,arg1,arg2,arg3,arg4,arg5); } while (0) + +#define CALL_FN_v_6W(fnptr, arg1,arg2,arg3,arg4,arg5,arg6) \ + do { volatile unsigned long _junk; \ + CALL_FN_W_6W(_junk,fnptr,arg1,arg2,arg3,arg4,arg5,arg6); } while (0) + +#define CALL_FN_v_7W(fnptr, arg1,arg2,arg3,arg4,arg5,arg6,arg7) \ + do { volatile unsigned long _junk; \ + CALL_FN_W_7W(_junk,fnptr,arg1,arg2,arg3,arg4,arg5,arg6,arg7); } while (0) + +/* ------------------------- x86-{linux,darwin} ---------------- */ + +#if defined(PLAT_x86_linux) || defined(PLAT_x86_darwin) + +/* These regs are trashed by the hidden call. No need to mention eax + as gcc can already see that, plus causes gcc to bomb. */ +#define __CALLER_SAVED_REGS /*"eax"*/ "ecx", "edx" + +/* Macros to save and align the stack before making a function + call and restore it afterwards as gcc may not keep the stack + pointer aligned if it doesn't realise calls are being made + to other functions. */ + +#define VALGRIND_ALIGN_STACK \ + "movl %%esp,%%edi\n\t" \ + "andl $0xfffffff0,%%esp\n\t" +#define VALGRIND_RESTORE_STACK \ + "movl %%edi,%%esp\n\t" + +/* These CALL_FN_ macros assume that on x86-linux, sizeof(unsigned + long) == 4. */ + +#define CALL_FN_W_v(lval, orig) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[1]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "movl (%%eax), %%eax\n\t" /* target->%eax */ \ + VALGRIND_CALL_NOREDIR_EAX \ + VALGRIND_RESTORE_STACK \ + : /*out*/ "=a" (_res) \ + : /*in*/ "a" (&_argvec[0]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_W(lval, orig, arg1) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[2]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "subl $12, %%esp\n\t" \ + "pushl 4(%%eax)\n\t" \ + "movl (%%eax), %%eax\n\t" /* target->%eax */ \ + VALGRIND_CALL_NOREDIR_EAX \ + VALGRIND_RESTORE_STACK \ + : /*out*/ "=a" (_res) \ + : /*in*/ "a" (&_argvec[0]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_WW(lval, orig, arg1,arg2) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[3]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "subl $8, %%esp\n\t" \ + "pushl 8(%%eax)\n\t" \ + "pushl 4(%%eax)\n\t" \ + "movl (%%eax), %%eax\n\t" /* target->%eax */ \ + VALGRIND_CALL_NOREDIR_EAX \ + VALGRIND_RESTORE_STACK \ + : /*out*/ "=a" (_res) \ + : /*in*/ "a" (&_argvec[0]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[4]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + _argvec[3] = (unsigned long)(arg3); \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "subl $4, %%esp\n\t" \ + "pushl 12(%%eax)\n\t" \ + "pushl 8(%%eax)\n\t" \ + "pushl 4(%%eax)\n\t" \ + "movl (%%eax), %%eax\n\t" /* target->%eax */ \ + VALGRIND_CALL_NOREDIR_EAX \ + VALGRIND_RESTORE_STACK \ + : /*out*/ "=a" (_res) \ + : /*in*/ "a" (&_argvec[0]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[5]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + _argvec[3] = (unsigned long)(arg3); \ + _argvec[4] = (unsigned long)(arg4); \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "pushl 16(%%eax)\n\t" \ + "pushl 12(%%eax)\n\t" \ + "pushl 8(%%eax)\n\t" \ + "pushl 4(%%eax)\n\t" \ + "movl (%%eax), %%eax\n\t" /* target->%eax */ \ + VALGRIND_CALL_NOREDIR_EAX \ + VALGRIND_RESTORE_STACK \ + : /*out*/ "=a" (_res) \ + : /*in*/ "a" (&_argvec[0]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[6]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + _argvec[3] = (unsigned long)(arg3); \ + _argvec[4] = (unsigned long)(arg4); \ + _argvec[5] = (unsigned long)(arg5); \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "subl $12, %%esp\n\t" \ + "pushl 20(%%eax)\n\t" \ + "pushl 16(%%eax)\n\t" \ + "pushl 12(%%eax)\n\t" \ + "pushl 8(%%eax)\n\t" \ + "pushl 4(%%eax)\n\t" \ + "movl (%%eax), %%eax\n\t" /* target->%eax */ \ + VALGRIND_CALL_NOREDIR_EAX \ + VALGRIND_RESTORE_STACK \ + : /*out*/ "=a" (_res) \ + : /*in*/ "a" (&_argvec[0]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[7]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + _argvec[3] = (unsigned long)(arg3); \ + _argvec[4] = (unsigned long)(arg4); \ + _argvec[5] = (unsigned long)(arg5); \ + _argvec[6] = (unsigned long)(arg6); \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "subl $8, %%esp\n\t" \ + "pushl 24(%%eax)\n\t" \ + "pushl 20(%%eax)\n\t" \ + "pushl 16(%%eax)\n\t" \ + "pushl 12(%%eax)\n\t" \ + "pushl 8(%%eax)\n\t" \ + "pushl 4(%%eax)\n\t" \ + "movl (%%eax), %%eax\n\t" /* target->%eax */ \ + VALGRIND_CALL_NOREDIR_EAX \ + VALGRIND_RESTORE_STACK \ + : /*out*/ "=a" (_res) \ + : /*in*/ "a" (&_argvec[0]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ + arg7) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[8]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + _argvec[3] = (unsigned long)(arg3); \ + _argvec[4] = (unsigned long)(arg4); \ + _argvec[5] = (unsigned long)(arg5); \ + _argvec[6] = (unsigned long)(arg6); \ + _argvec[7] = (unsigned long)(arg7); \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "subl $4, %%esp\n\t" \ + "pushl 28(%%eax)\n\t" \ + "pushl 24(%%eax)\n\t" \ + "pushl 20(%%eax)\n\t" \ + "pushl 16(%%eax)\n\t" \ + "pushl 12(%%eax)\n\t" \ + "pushl 8(%%eax)\n\t" \ + "pushl 4(%%eax)\n\t" \ + "movl (%%eax), %%eax\n\t" /* target->%eax */ \ + VALGRIND_CALL_NOREDIR_EAX \ + VALGRIND_RESTORE_STACK \ + : /*out*/ "=a" (_res) \ + : /*in*/ "a" (&_argvec[0]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ + arg7,arg8) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[9]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + _argvec[3] = (unsigned long)(arg3); \ + _argvec[4] = (unsigned long)(arg4); \ + _argvec[5] = (unsigned long)(arg5); \ + _argvec[6] = (unsigned long)(arg6); \ + _argvec[7] = (unsigned long)(arg7); \ + _argvec[8] = (unsigned long)(arg8); \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "pushl 32(%%eax)\n\t" \ + "pushl 28(%%eax)\n\t" \ + "pushl 24(%%eax)\n\t" \ + "pushl 20(%%eax)\n\t" \ + "pushl 16(%%eax)\n\t" \ + "pushl 12(%%eax)\n\t" \ + "pushl 8(%%eax)\n\t" \ + "pushl 4(%%eax)\n\t" \ + "movl (%%eax), %%eax\n\t" /* target->%eax */ \ + VALGRIND_CALL_NOREDIR_EAX \ + VALGRIND_RESTORE_STACK \ + : /*out*/ "=a" (_res) \ + : /*in*/ "a" (&_argvec[0]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ + arg7,arg8,arg9) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[10]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + _argvec[3] = (unsigned long)(arg3); \ + _argvec[4] = (unsigned long)(arg4); \ + _argvec[5] = (unsigned long)(arg5); \ + _argvec[6] = (unsigned long)(arg6); \ + _argvec[7] = (unsigned long)(arg7); \ + _argvec[8] = (unsigned long)(arg8); \ + _argvec[9] = (unsigned long)(arg9); \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "subl $12, %%esp\n\t" \ + "pushl 36(%%eax)\n\t" \ + "pushl 32(%%eax)\n\t" \ + "pushl 28(%%eax)\n\t" \ + "pushl 24(%%eax)\n\t" \ + "pushl 20(%%eax)\n\t" \ + "pushl 16(%%eax)\n\t" \ + "pushl 12(%%eax)\n\t" \ + "pushl 8(%%eax)\n\t" \ + "pushl 4(%%eax)\n\t" \ + "movl (%%eax), %%eax\n\t" /* target->%eax */ \ + VALGRIND_CALL_NOREDIR_EAX \ + VALGRIND_RESTORE_STACK \ + : /*out*/ "=a" (_res) \ + : /*in*/ "a" (&_argvec[0]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ + arg7,arg8,arg9,arg10) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[11]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + _argvec[3] = (unsigned long)(arg3); \ + _argvec[4] = (unsigned long)(arg4); \ + _argvec[5] = (unsigned long)(arg5); \ + _argvec[6] = (unsigned long)(arg6); \ + _argvec[7] = (unsigned long)(arg7); \ + _argvec[8] = (unsigned long)(arg8); \ + _argvec[9] = (unsigned long)(arg9); \ + _argvec[10] = (unsigned long)(arg10); \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "subl $8, %%esp\n\t" \ + "pushl 40(%%eax)\n\t" \ + "pushl 36(%%eax)\n\t" \ + "pushl 32(%%eax)\n\t" \ + "pushl 28(%%eax)\n\t" \ + "pushl 24(%%eax)\n\t" \ + "pushl 20(%%eax)\n\t" \ + "pushl 16(%%eax)\n\t" \ + "pushl 12(%%eax)\n\t" \ + "pushl 8(%%eax)\n\t" \ + "pushl 4(%%eax)\n\t" \ + "movl (%%eax), %%eax\n\t" /* target->%eax */ \ + VALGRIND_CALL_NOREDIR_EAX \ + VALGRIND_RESTORE_STACK \ + : /*out*/ "=a" (_res) \ + : /*in*/ "a" (&_argvec[0]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5, \ + arg6,arg7,arg8,arg9,arg10, \ + arg11) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[12]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + _argvec[3] = (unsigned long)(arg3); \ + _argvec[4] = (unsigned long)(arg4); \ + _argvec[5] = (unsigned long)(arg5); \ + _argvec[6] = (unsigned long)(arg6); \ + _argvec[7] = (unsigned long)(arg7); \ + _argvec[8] = (unsigned long)(arg8); \ + _argvec[9] = (unsigned long)(arg9); \ + _argvec[10] = (unsigned long)(arg10); \ + _argvec[11] = (unsigned long)(arg11); \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "subl $4, %%esp\n\t" \ + "pushl 44(%%eax)\n\t" \ + "pushl 40(%%eax)\n\t" \ + "pushl 36(%%eax)\n\t" \ + "pushl 32(%%eax)\n\t" \ + "pushl 28(%%eax)\n\t" \ + "pushl 24(%%eax)\n\t" \ + "pushl 20(%%eax)\n\t" \ + "pushl 16(%%eax)\n\t" \ + "pushl 12(%%eax)\n\t" \ + "pushl 8(%%eax)\n\t" \ + "pushl 4(%%eax)\n\t" \ + "movl (%%eax), %%eax\n\t" /* target->%eax */ \ + VALGRIND_CALL_NOREDIR_EAX \ + VALGRIND_RESTORE_STACK \ + : /*out*/ "=a" (_res) \ + : /*in*/ "a" (&_argvec[0]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5, \ + arg6,arg7,arg8,arg9,arg10, \ + arg11,arg12) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[13]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + _argvec[3] = (unsigned long)(arg3); \ + _argvec[4] = (unsigned long)(arg4); \ + _argvec[5] = (unsigned long)(arg5); \ + _argvec[6] = (unsigned long)(arg6); \ + _argvec[7] = (unsigned long)(arg7); \ + _argvec[8] = (unsigned long)(arg8); \ + _argvec[9] = (unsigned long)(arg9); \ + _argvec[10] = (unsigned long)(arg10); \ + _argvec[11] = (unsigned long)(arg11); \ + _argvec[12] = (unsigned long)(arg12); \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "pushl 48(%%eax)\n\t" \ + "pushl 44(%%eax)\n\t" \ + "pushl 40(%%eax)\n\t" \ + "pushl 36(%%eax)\n\t" \ + "pushl 32(%%eax)\n\t" \ + "pushl 28(%%eax)\n\t" \ + "pushl 24(%%eax)\n\t" \ + "pushl 20(%%eax)\n\t" \ + "pushl 16(%%eax)\n\t" \ + "pushl 12(%%eax)\n\t" \ + "pushl 8(%%eax)\n\t" \ + "pushl 4(%%eax)\n\t" \ + "movl (%%eax), %%eax\n\t" /* target->%eax */ \ + VALGRIND_CALL_NOREDIR_EAX \ + VALGRIND_RESTORE_STACK \ + : /*out*/ "=a" (_res) \ + : /*in*/ "a" (&_argvec[0]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#endif /* PLAT_x86_linux || PLAT_x86_darwin */ + +/* ------------------------ amd64-{linux,darwin} --------------- */ + +#if defined(PLAT_amd64_linux) || defined(PLAT_amd64_darwin) + +/* ARGREGS: rdi rsi rdx rcx r8 r9 (the rest on stack in R-to-L order) */ + +/* These regs are trashed by the hidden call. */ +#define __CALLER_SAVED_REGS /*"rax",*/ "rcx", "rdx", "rsi", \ + "rdi", "r8", "r9", "r10", "r11" + +/* This is all pretty complex. It's so as to make stack unwinding + work reliably. See bug 243270. The basic problem is the sub and + add of 128 of %rsp in all of the following macros. If gcc believes + the CFA is in %rsp, then unwinding may fail, because what's at the + CFA is not what gcc "expected" when it constructs the CFIs for the + places where the macros are instantiated. + + But we can't just add a CFI annotation to increase the CFA offset + by 128, to match the sub of 128 from %rsp, because we don't know + whether gcc has chosen %rsp as the CFA at that point, or whether it + has chosen some other register (eg, %rbp). In the latter case, + adding a CFI annotation to change the CFA offset is simply wrong. + + So the solution is to get hold of the CFA using + __builtin_dwarf_cfa(), put it in a known register, and add a + CFI annotation to say what the register is. We choose %rbp for + this (perhaps perversely), because: + + (1) %rbp is already subject to unwinding. If a new register was + chosen then the unwinder would have to unwind it in all stack + traces, which is expensive, and + + (2) %rbp is already subject to precise exception updates in the + JIT. If a new register was chosen, we'd have to have precise + exceptions for it too, which reduces performance of the + generated code. + + However .. one extra complication. We can't just whack the result + of __builtin_dwarf_cfa() into %rbp and then add %rbp to the + list of trashed registers at the end of the inline assembly + fragments; gcc won't allow %rbp to appear in that list. Hence + instead we need to stash %rbp in %r15 for the duration of the asm, + and say that %r15 is trashed instead. gcc seems happy to go with + that. + + Oh .. and this all needs to be conditionalised so that it is + unchanged from before this commit, when compiled with older gccs + that don't support __builtin_dwarf_cfa. Furthermore, since + this header file is freestanding, it has to be independent of + config.h, and so the following conditionalisation cannot depend on + configure time checks. + + Although it's not clear from + 'defined(__GNUC__) && defined(__GCC_HAVE_DWARF2_CFI_ASM)', + this expression excludes Darwin. + .cfi directives in Darwin assembly appear to be completely + different and I haven't investigated how they work. + + For even more entertainment value, note we have to use the + completely undocumented __builtin_dwarf_cfa(), which appears to + really compute the CFA, whereas __builtin_frame_address(0) claims + to but actually doesn't. See + https://bugs.kde.org/show_bug.cgi?id=243270#c47 +*/ +#if defined(__GNUC__) && defined(__GCC_HAVE_DWARF2_CFI_ASM) +# define __FRAME_POINTER \ + ,"r"(__builtin_dwarf_cfa()) +# define VALGRIND_CFI_PROLOGUE \ + "movq %%rbp, %%r15\n\t" \ + "movq %2, %%rbp\n\t" \ + ".cfi_remember_state\n\t" \ + ".cfi_def_cfa rbp, 0\n\t" +# define VALGRIND_CFI_EPILOGUE \ + "movq %%r15, %%rbp\n\t" \ + ".cfi_restore_state\n\t" +#else +# define __FRAME_POINTER +# define VALGRIND_CFI_PROLOGUE +# define VALGRIND_CFI_EPILOGUE +#endif + +/* Macros to save and align the stack before making a function + call and restore it afterwards as gcc may not keep the stack + pointer aligned if it doesn't realise calls are being made + to other functions. */ + +#define VALGRIND_ALIGN_STACK \ + "movq %%rsp,%%r14\n\t" \ + "andq $0xfffffffffffffff0,%%rsp\n\t" +#define VALGRIND_RESTORE_STACK \ + "movq %%r14,%%rsp\n\t" + +/* These CALL_FN_ macros assume that on amd64-linux, sizeof(unsigned + long) == 8. */ + +/* NB 9 Sept 07. There is a nasty kludge here in all these CALL_FN_ + macros. In order not to trash the stack redzone, we need to drop + %rsp by 128 before the hidden call, and restore afterwards. The + nastyness is that it is only by luck that the stack still appears + to be unwindable during the hidden call - since then the behaviour + of any routine using this macro does not match what the CFI data + says. Sigh. + + Why is this important? Imagine that a wrapper has a stack + allocated local, and passes to the hidden call, a pointer to it. + Because gcc does not know about the hidden call, it may allocate + that local in the redzone. Unfortunately the hidden call may then + trash it before it comes to use it. So we must step clear of the + redzone, for the duration of the hidden call, to make it safe. + + Probably the same problem afflicts the other redzone-style ABIs too + (ppc64-linux); but for those, the stack is + self describing (none of this CFI nonsense) so at least messing + with the stack pointer doesn't give a danger of non-unwindable + stack. */ + +#define CALL_FN_W_v(lval, orig) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[1]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + __asm__ volatile( \ + VALGRIND_CFI_PROLOGUE \ + VALGRIND_ALIGN_STACK \ + "subq $128,%%rsp\n\t" \ + "movq (%%rax), %%rax\n\t" /* target->%rax */ \ + VALGRIND_CALL_NOREDIR_RAX \ + VALGRIND_RESTORE_STACK \ + VALGRIND_CFI_EPILOGUE \ + : /*out*/ "=a" (_res) \ + : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_W(lval, orig, arg1) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[2]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + __asm__ volatile( \ + VALGRIND_CFI_PROLOGUE \ + VALGRIND_ALIGN_STACK \ + "subq $128,%%rsp\n\t" \ + "movq 8(%%rax), %%rdi\n\t" \ + "movq (%%rax), %%rax\n\t" /* target->%rax */ \ + VALGRIND_CALL_NOREDIR_RAX \ + VALGRIND_RESTORE_STACK \ + VALGRIND_CFI_EPILOGUE \ + : /*out*/ "=a" (_res) \ + : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_WW(lval, orig, arg1,arg2) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[3]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + __asm__ volatile( \ + VALGRIND_CFI_PROLOGUE \ + VALGRIND_ALIGN_STACK \ + "subq $128,%%rsp\n\t" \ + "movq 16(%%rax), %%rsi\n\t" \ + "movq 8(%%rax), %%rdi\n\t" \ + "movq (%%rax), %%rax\n\t" /* target->%rax */ \ + VALGRIND_CALL_NOREDIR_RAX \ + VALGRIND_RESTORE_STACK \ + VALGRIND_CFI_EPILOGUE \ + : /*out*/ "=a" (_res) \ + : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[4]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + _argvec[3] = (unsigned long)(arg3); \ + __asm__ volatile( \ + VALGRIND_CFI_PROLOGUE \ + VALGRIND_ALIGN_STACK \ + "subq $128,%%rsp\n\t" \ + "movq 24(%%rax), %%rdx\n\t" \ + "movq 16(%%rax), %%rsi\n\t" \ + "movq 8(%%rax), %%rdi\n\t" \ + "movq (%%rax), %%rax\n\t" /* target->%rax */ \ + VALGRIND_CALL_NOREDIR_RAX \ + VALGRIND_RESTORE_STACK \ + VALGRIND_CFI_EPILOGUE \ + : /*out*/ "=a" (_res) \ + : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[5]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + _argvec[3] = (unsigned long)(arg3); \ + _argvec[4] = (unsigned long)(arg4); \ + __asm__ volatile( \ + VALGRIND_CFI_PROLOGUE \ + VALGRIND_ALIGN_STACK \ + "subq $128,%%rsp\n\t" \ + "movq 32(%%rax), %%rcx\n\t" \ + "movq 24(%%rax), %%rdx\n\t" \ + "movq 16(%%rax), %%rsi\n\t" \ + "movq 8(%%rax), %%rdi\n\t" \ + "movq (%%rax), %%rax\n\t" /* target->%rax */ \ + VALGRIND_CALL_NOREDIR_RAX \ + VALGRIND_RESTORE_STACK \ + VALGRIND_CFI_EPILOGUE \ + : /*out*/ "=a" (_res) \ + : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[6]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + _argvec[3] = (unsigned long)(arg3); \ + _argvec[4] = (unsigned long)(arg4); \ + _argvec[5] = (unsigned long)(arg5); \ + __asm__ volatile( \ + VALGRIND_CFI_PROLOGUE \ + VALGRIND_ALIGN_STACK \ + "subq $128,%%rsp\n\t" \ + "movq 40(%%rax), %%r8\n\t" \ + "movq 32(%%rax), %%rcx\n\t" \ + "movq 24(%%rax), %%rdx\n\t" \ + "movq 16(%%rax), %%rsi\n\t" \ + "movq 8(%%rax), %%rdi\n\t" \ + "movq (%%rax), %%rax\n\t" /* target->%rax */ \ + VALGRIND_CALL_NOREDIR_RAX \ + VALGRIND_RESTORE_STACK \ + VALGRIND_CFI_EPILOGUE \ + : /*out*/ "=a" (_res) \ + : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[7]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + _argvec[3] = (unsigned long)(arg3); \ + _argvec[4] = (unsigned long)(arg4); \ + _argvec[5] = (unsigned long)(arg5); \ + _argvec[6] = (unsigned long)(arg6); \ + __asm__ volatile( \ + VALGRIND_CFI_PROLOGUE \ + VALGRIND_ALIGN_STACK \ + "subq $128,%%rsp\n\t" \ + "movq 48(%%rax), %%r9\n\t" \ + "movq 40(%%rax), %%r8\n\t" \ + "movq 32(%%rax), %%rcx\n\t" \ + "movq 24(%%rax), %%rdx\n\t" \ + "movq 16(%%rax), %%rsi\n\t" \ + "movq 8(%%rax), %%rdi\n\t" \ + "movq (%%rax), %%rax\n\t" /* target->%rax */ \ + VALGRIND_CALL_NOREDIR_RAX \ + VALGRIND_RESTORE_STACK \ + VALGRIND_CFI_EPILOGUE \ + : /*out*/ "=a" (_res) \ + : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ + arg7) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[8]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + _argvec[3] = (unsigned long)(arg3); \ + _argvec[4] = (unsigned long)(arg4); \ + _argvec[5] = (unsigned long)(arg5); \ + _argvec[6] = (unsigned long)(arg6); \ + _argvec[7] = (unsigned long)(arg7); \ + __asm__ volatile( \ + VALGRIND_CFI_PROLOGUE \ + VALGRIND_ALIGN_STACK \ + "subq $136,%%rsp\n\t" \ + "pushq 56(%%rax)\n\t" \ + "movq 48(%%rax), %%r9\n\t" \ + "movq 40(%%rax), %%r8\n\t" \ + "movq 32(%%rax), %%rcx\n\t" \ + "movq 24(%%rax), %%rdx\n\t" \ + "movq 16(%%rax), %%rsi\n\t" \ + "movq 8(%%rax), %%rdi\n\t" \ + "movq (%%rax), %%rax\n\t" /* target->%rax */ \ + VALGRIND_CALL_NOREDIR_RAX \ + VALGRIND_RESTORE_STACK \ + VALGRIND_CFI_EPILOGUE \ + : /*out*/ "=a" (_res) \ + : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ + arg7,arg8) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[9]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + _argvec[3] = (unsigned long)(arg3); \ + _argvec[4] = (unsigned long)(arg4); \ + _argvec[5] = (unsigned long)(arg5); \ + _argvec[6] = (unsigned long)(arg6); \ + _argvec[7] = (unsigned long)(arg7); \ + _argvec[8] = (unsigned long)(arg8); \ + __asm__ volatile( \ + VALGRIND_CFI_PROLOGUE \ + VALGRIND_ALIGN_STACK \ + "subq $128,%%rsp\n\t" \ + "pushq 64(%%rax)\n\t" \ + "pushq 56(%%rax)\n\t" \ + "movq 48(%%rax), %%r9\n\t" \ + "movq 40(%%rax), %%r8\n\t" \ + "movq 32(%%rax), %%rcx\n\t" \ + "movq 24(%%rax), %%rdx\n\t" \ + "movq 16(%%rax), %%rsi\n\t" \ + "movq 8(%%rax), %%rdi\n\t" \ + "movq (%%rax), %%rax\n\t" /* target->%rax */ \ + VALGRIND_CALL_NOREDIR_RAX \ + VALGRIND_RESTORE_STACK \ + VALGRIND_CFI_EPILOGUE \ + : /*out*/ "=a" (_res) \ + : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ + arg7,arg8,arg9) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[10]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + _argvec[3] = (unsigned long)(arg3); \ + _argvec[4] = (unsigned long)(arg4); \ + _argvec[5] = (unsigned long)(arg5); \ + _argvec[6] = (unsigned long)(arg6); \ + _argvec[7] = (unsigned long)(arg7); \ + _argvec[8] = (unsigned long)(arg8); \ + _argvec[9] = (unsigned long)(arg9); \ + __asm__ volatile( \ + VALGRIND_CFI_PROLOGUE \ + VALGRIND_ALIGN_STACK \ + "subq $136,%%rsp\n\t" \ + "pushq 72(%%rax)\n\t" \ + "pushq 64(%%rax)\n\t" \ + "pushq 56(%%rax)\n\t" \ + "movq 48(%%rax), %%r9\n\t" \ + "movq 40(%%rax), %%r8\n\t" \ + "movq 32(%%rax), %%rcx\n\t" \ + "movq 24(%%rax), %%rdx\n\t" \ + "movq 16(%%rax), %%rsi\n\t" \ + "movq 8(%%rax), %%rdi\n\t" \ + "movq (%%rax), %%rax\n\t" /* target->%rax */ \ + VALGRIND_CALL_NOREDIR_RAX \ + VALGRIND_RESTORE_STACK \ + VALGRIND_CFI_EPILOGUE \ + : /*out*/ "=a" (_res) \ + : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ + arg7,arg8,arg9,arg10) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[11]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + _argvec[3] = (unsigned long)(arg3); \ + _argvec[4] = (unsigned long)(arg4); \ + _argvec[5] = (unsigned long)(arg5); \ + _argvec[6] = (unsigned long)(arg6); \ + _argvec[7] = (unsigned long)(arg7); \ + _argvec[8] = (unsigned long)(arg8); \ + _argvec[9] = (unsigned long)(arg9); \ + _argvec[10] = (unsigned long)(arg10); \ + __asm__ volatile( \ + VALGRIND_CFI_PROLOGUE \ + VALGRIND_ALIGN_STACK \ + "subq $128,%%rsp\n\t" \ + "pushq 80(%%rax)\n\t" \ + "pushq 72(%%rax)\n\t" \ + "pushq 64(%%rax)\n\t" \ + "pushq 56(%%rax)\n\t" \ + "movq 48(%%rax), %%r9\n\t" \ + "movq 40(%%rax), %%r8\n\t" \ + "movq 32(%%rax), %%rcx\n\t" \ + "movq 24(%%rax), %%rdx\n\t" \ + "movq 16(%%rax), %%rsi\n\t" \ + "movq 8(%%rax), %%rdi\n\t" \ + "movq (%%rax), %%rax\n\t" /* target->%rax */ \ + VALGRIND_CALL_NOREDIR_RAX \ + VALGRIND_RESTORE_STACK \ + VALGRIND_CFI_EPILOGUE \ + : /*out*/ "=a" (_res) \ + : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ + arg7,arg8,arg9,arg10,arg11) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[12]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + _argvec[3] = (unsigned long)(arg3); \ + _argvec[4] = (unsigned long)(arg4); \ + _argvec[5] = (unsigned long)(arg5); \ + _argvec[6] = (unsigned long)(arg6); \ + _argvec[7] = (unsigned long)(arg7); \ + _argvec[8] = (unsigned long)(arg8); \ + _argvec[9] = (unsigned long)(arg9); \ + _argvec[10] = (unsigned long)(arg10); \ + _argvec[11] = (unsigned long)(arg11); \ + __asm__ volatile( \ + VALGRIND_CFI_PROLOGUE \ + VALGRIND_ALIGN_STACK \ + "subq $136,%%rsp\n\t" \ + "pushq 88(%%rax)\n\t" \ + "pushq 80(%%rax)\n\t" \ + "pushq 72(%%rax)\n\t" \ + "pushq 64(%%rax)\n\t" \ + "pushq 56(%%rax)\n\t" \ + "movq 48(%%rax), %%r9\n\t" \ + "movq 40(%%rax), %%r8\n\t" \ + "movq 32(%%rax), %%rcx\n\t" \ + "movq 24(%%rax), %%rdx\n\t" \ + "movq 16(%%rax), %%rsi\n\t" \ + "movq 8(%%rax), %%rdi\n\t" \ + "movq (%%rax), %%rax\n\t" /* target->%rax */ \ + VALGRIND_CALL_NOREDIR_RAX \ + VALGRIND_RESTORE_STACK \ + VALGRIND_CFI_EPILOGUE \ + : /*out*/ "=a" (_res) \ + : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ + arg7,arg8,arg9,arg10,arg11,arg12) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[13]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + _argvec[3] = (unsigned long)(arg3); \ + _argvec[4] = (unsigned long)(arg4); \ + _argvec[5] = (unsigned long)(arg5); \ + _argvec[6] = (unsigned long)(arg6); \ + _argvec[7] = (unsigned long)(arg7); \ + _argvec[8] = (unsigned long)(arg8); \ + _argvec[9] = (unsigned long)(arg9); \ + _argvec[10] = (unsigned long)(arg10); \ + _argvec[11] = (unsigned long)(arg11); \ + _argvec[12] = (unsigned long)(arg12); \ + __asm__ volatile( \ + VALGRIND_CFI_PROLOGUE \ + VALGRIND_ALIGN_STACK \ + "subq $128,%%rsp\n\t" \ + "pushq 96(%%rax)\n\t" \ + "pushq 88(%%rax)\n\t" \ + "pushq 80(%%rax)\n\t" \ + "pushq 72(%%rax)\n\t" \ + "pushq 64(%%rax)\n\t" \ + "pushq 56(%%rax)\n\t" \ + "movq 48(%%rax), %%r9\n\t" \ + "movq 40(%%rax), %%r8\n\t" \ + "movq 32(%%rax), %%rcx\n\t" \ + "movq 24(%%rax), %%rdx\n\t" \ + "movq 16(%%rax), %%rsi\n\t" \ + "movq 8(%%rax), %%rdi\n\t" \ + "movq (%%rax), %%rax\n\t" /* target->%rax */ \ + VALGRIND_CALL_NOREDIR_RAX \ + VALGRIND_RESTORE_STACK \ + VALGRIND_CFI_EPILOGUE \ + : /*out*/ "=a" (_res) \ + : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#endif /* PLAT_amd64_linux || PLAT_amd64_darwin */ + +/* ------------------------ ppc32-linux ------------------------ */ + +#if defined(PLAT_ppc32_linux) + +/* This is useful for finding out about the on-stack stuff: + + extern int f9 ( int,int,int,int,int,int,int,int,int ); + extern int f10 ( int,int,int,int,int,int,int,int,int,int ); + extern int f11 ( int,int,int,int,int,int,int,int,int,int,int ); + extern int f12 ( int,int,int,int,int,int,int,int,int,int,int,int ); + + int g9 ( void ) { + return f9(11,22,33,44,55,66,77,88,99); + } + int g10 ( void ) { + return f10(11,22,33,44,55,66,77,88,99,110); + } + int g11 ( void ) { + return f11(11,22,33,44,55,66,77,88,99,110,121); + } + int g12 ( void ) { + return f12(11,22,33,44,55,66,77,88,99,110,121,132); + } +*/ + +/* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */ + +/* These regs are trashed by the hidden call. */ +#define __CALLER_SAVED_REGS \ + "lr", "ctr", "xer", \ + "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \ + "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \ + "r11", "r12", "r13" + +/* Macros to save and align the stack before making a function + call and restore it afterwards as gcc may not keep the stack + pointer aligned if it doesn't realise calls are being made + to other functions. */ + +#define VALGRIND_ALIGN_STACK \ + "mr 28,1\n\t" \ + "rlwinm 1,1,0,0,27\n\t" +#define VALGRIND_RESTORE_STACK \ + "mr 1,28\n\t" + +/* These CALL_FN_ macros assume that on ppc32-linux, + sizeof(unsigned long) == 4. */ + +#define CALL_FN_W_v(lval, orig) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[1]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "mr 11,%1\n\t" \ + "lwz 11,0(11)\n\t" /* target->r11 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ + VALGRIND_RESTORE_STACK \ + "mr %0,3" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[0]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_W(lval, orig, arg1) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[2]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)arg1; \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "mr 11,%1\n\t" \ + "lwz 3,4(11)\n\t" /* arg1->r3 */ \ + "lwz 11,0(11)\n\t" /* target->r11 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ + VALGRIND_RESTORE_STACK \ + "mr %0,3" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[0]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_WW(lval, orig, arg1,arg2) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[3]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)arg1; \ + _argvec[2] = (unsigned long)arg2; \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "mr 11,%1\n\t" \ + "lwz 3,4(11)\n\t" /* arg1->r3 */ \ + "lwz 4,8(11)\n\t" \ + "lwz 11,0(11)\n\t" /* target->r11 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ + VALGRIND_RESTORE_STACK \ + "mr %0,3" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[0]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[4]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)arg1; \ + _argvec[2] = (unsigned long)arg2; \ + _argvec[3] = (unsigned long)arg3; \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "mr 11,%1\n\t" \ + "lwz 3,4(11)\n\t" /* arg1->r3 */ \ + "lwz 4,8(11)\n\t" \ + "lwz 5,12(11)\n\t" \ + "lwz 11,0(11)\n\t" /* target->r11 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ + VALGRIND_RESTORE_STACK \ + "mr %0,3" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[0]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[5]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)arg1; \ + _argvec[2] = (unsigned long)arg2; \ + _argvec[3] = (unsigned long)arg3; \ + _argvec[4] = (unsigned long)arg4; \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "mr 11,%1\n\t" \ + "lwz 3,4(11)\n\t" /* arg1->r3 */ \ + "lwz 4,8(11)\n\t" \ + "lwz 5,12(11)\n\t" \ + "lwz 6,16(11)\n\t" /* arg4->r6 */ \ + "lwz 11,0(11)\n\t" /* target->r11 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ + VALGRIND_RESTORE_STACK \ + "mr %0,3" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[0]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[6]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)arg1; \ + _argvec[2] = (unsigned long)arg2; \ + _argvec[3] = (unsigned long)arg3; \ + _argvec[4] = (unsigned long)arg4; \ + _argvec[5] = (unsigned long)arg5; \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "mr 11,%1\n\t" \ + "lwz 3,4(11)\n\t" /* arg1->r3 */ \ + "lwz 4,8(11)\n\t" \ + "lwz 5,12(11)\n\t" \ + "lwz 6,16(11)\n\t" /* arg4->r6 */ \ + "lwz 7,20(11)\n\t" \ + "lwz 11,0(11)\n\t" /* target->r11 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ + VALGRIND_RESTORE_STACK \ + "mr %0,3" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[0]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[7]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)arg1; \ + _argvec[2] = (unsigned long)arg2; \ + _argvec[3] = (unsigned long)arg3; \ + _argvec[4] = (unsigned long)arg4; \ + _argvec[5] = (unsigned long)arg5; \ + _argvec[6] = (unsigned long)arg6; \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "mr 11,%1\n\t" \ + "lwz 3,4(11)\n\t" /* arg1->r3 */ \ + "lwz 4,8(11)\n\t" \ + "lwz 5,12(11)\n\t" \ + "lwz 6,16(11)\n\t" /* arg4->r6 */ \ + "lwz 7,20(11)\n\t" \ + "lwz 8,24(11)\n\t" \ + "lwz 11,0(11)\n\t" /* target->r11 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ + VALGRIND_RESTORE_STACK \ + "mr %0,3" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[0]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ + arg7) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[8]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)arg1; \ + _argvec[2] = (unsigned long)arg2; \ + _argvec[3] = (unsigned long)arg3; \ + _argvec[4] = (unsigned long)arg4; \ + _argvec[5] = (unsigned long)arg5; \ + _argvec[6] = (unsigned long)arg6; \ + _argvec[7] = (unsigned long)arg7; \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "mr 11,%1\n\t" \ + "lwz 3,4(11)\n\t" /* arg1->r3 */ \ + "lwz 4,8(11)\n\t" \ + "lwz 5,12(11)\n\t" \ + "lwz 6,16(11)\n\t" /* arg4->r6 */ \ + "lwz 7,20(11)\n\t" \ + "lwz 8,24(11)\n\t" \ + "lwz 9,28(11)\n\t" \ + "lwz 11,0(11)\n\t" /* target->r11 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ + VALGRIND_RESTORE_STACK \ + "mr %0,3" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[0]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ + arg7,arg8) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[9]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)arg1; \ + _argvec[2] = (unsigned long)arg2; \ + _argvec[3] = (unsigned long)arg3; \ + _argvec[4] = (unsigned long)arg4; \ + _argvec[5] = (unsigned long)arg5; \ + _argvec[6] = (unsigned long)arg6; \ + _argvec[7] = (unsigned long)arg7; \ + _argvec[8] = (unsigned long)arg8; \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "mr 11,%1\n\t" \ + "lwz 3,4(11)\n\t" /* arg1->r3 */ \ + "lwz 4,8(11)\n\t" \ + "lwz 5,12(11)\n\t" \ + "lwz 6,16(11)\n\t" /* arg4->r6 */ \ + "lwz 7,20(11)\n\t" \ + "lwz 8,24(11)\n\t" \ + "lwz 9,28(11)\n\t" \ + "lwz 10,32(11)\n\t" /* arg8->r10 */ \ + "lwz 11,0(11)\n\t" /* target->r11 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ + VALGRIND_RESTORE_STACK \ + "mr %0,3" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[0]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ + arg7,arg8,arg9) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[10]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)arg1; \ + _argvec[2] = (unsigned long)arg2; \ + _argvec[3] = (unsigned long)arg3; \ + _argvec[4] = (unsigned long)arg4; \ + _argvec[5] = (unsigned long)arg5; \ + _argvec[6] = (unsigned long)arg6; \ + _argvec[7] = (unsigned long)arg7; \ + _argvec[8] = (unsigned long)arg8; \ + _argvec[9] = (unsigned long)arg9; \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "mr 11,%1\n\t" \ + "addi 1,1,-16\n\t" \ + /* arg9 */ \ + "lwz 3,36(11)\n\t" \ + "stw 3,8(1)\n\t" \ + /* args1-8 */ \ + "lwz 3,4(11)\n\t" /* arg1->r3 */ \ + "lwz 4,8(11)\n\t" \ + "lwz 5,12(11)\n\t" \ + "lwz 6,16(11)\n\t" /* arg4->r6 */ \ + "lwz 7,20(11)\n\t" \ + "lwz 8,24(11)\n\t" \ + "lwz 9,28(11)\n\t" \ + "lwz 10,32(11)\n\t" /* arg8->r10 */ \ + "lwz 11,0(11)\n\t" /* target->r11 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ + VALGRIND_RESTORE_STACK \ + "mr %0,3" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[0]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ + arg7,arg8,arg9,arg10) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[11]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)arg1; \ + _argvec[2] = (unsigned long)arg2; \ + _argvec[3] = (unsigned long)arg3; \ + _argvec[4] = (unsigned long)arg4; \ + _argvec[5] = (unsigned long)arg5; \ + _argvec[6] = (unsigned long)arg6; \ + _argvec[7] = (unsigned long)arg7; \ + _argvec[8] = (unsigned long)arg8; \ + _argvec[9] = (unsigned long)arg9; \ + _argvec[10] = (unsigned long)arg10; \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "mr 11,%1\n\t" \ + "addi 1,1,-16\n\t" \ + /* arg10 */ \ + "lwz 3,40(11)\n\t" \ + "stw 3,12(1)\n\t" \ + /* arg9 */ \ + "lwz 3,36(11)\n\t" \ + "stw 3,8(1)\n\t" \ + /* args1-8 */ \ + "lwz 3,4(11)\n\t" /* arg1->r3 */ \ + "lwz 4,8(11)\n\t" \ + "lwz 5,12(11)\n\t" \ + "lwz 6,16(11)\n\t" /* arg4->r6 */ \ + "lwz 7,20(11)\n\t" \ + "lwz 8,24(11)\n\t" \ + "lwz 9,28(11)\n\t" \ + "lwz 10,32(11)\n\t" /* arg8->r10 */ \ + "lwz 11,0(11)\n\t" /* target->r11 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ + VALGRIND_RESTORE_STACK \ + "mr %0,3" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[0]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ + arg7,arg8,arg9,arg10,arg11) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[12]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)arg1; \ + _argvec[2] = (unsigned long)arg2; \ + _argvec[3] = (unsigned long)arg3; \ + _argvec[4] = (unsigned long)arg4; \ + _argvec[5] = (unsigned long)arg5; \ + _argvec[6] = (unsigned long)arg6; \ + _argvec[7] = (unsigned long)arg7; \ + _argvec[8] = (unsigned long)arg8; \ + _argvec[9] = (unsigned long)arg9; \ + _argvec[10] = (unsigned long)arg10; \ + _argvec[11] = (unsigned long)arg11; \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "mr 11,%1\n\t" \ + "addi 1,1,-32\n\t" \ + /* arg11 */ \ + "lwz 3,44(11)\n\t" \ + "stw 3,16(1)\n\t" \ + /* arg10 */ \ + "lwz 3,40(11)\n\t" \ + "stw 3,12(1)\n\t" \ + /* arg9 */ \ + "lwz 3,36(11)\n\t" \ + "stw 3,8(1)\n\t" \ + /* args1-8 */ \ + "lwz 3,4(11)\n\t" /* arg1->r3 */ \ + "lwz 4,8(11)\n\t" \ + "lwz 5,12(11)\n\t" \ + "lwz 6,16(11)\n\t" /* arg4->r6 */ \ + "lwz 7,20(11)\n\t" \ + "lwz 8,24(11)\n\t" \ + "lwz 9,28(11)\n\t" \ + "lwz 10,32(11)\n\t" /* arg8->r10 */ \ + "lwz 11,0(11)\n\t" /* target->r11 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ + VALGRIND_RESTORE_STACK \ + "mr %0,3" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[0]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ + arg7,arg8,arg9,arg10,arg11,arg12) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[13]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)arg1; \ + _argvec[2] = (unsigned long)arg2; \ + _argvec[3] = (unsigned long)arg3; \ + _argvec[4] = (unsigned long)arg4; \ + _argvec[5] = (unsigned long)arg5; \ + _argvec[6] = (unsigned long)arg6; \ + _argvec[7] = (unsigned long)arg7; \ + _argvec[8] = (unsigned long)arg8; \ + _argvec[9] = (unsigned long)arg9; \ + _argvec[10] = (unsigned long)arg10; \ + _argvec[11] = (unsigned long)arg11; \ + _argvec[12] = (unsigned long)arg12; \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "mr 11,%1\n\t" \ + "addi 1,1,-32\n\t" \ + /* arg12 */ \ + "lwz 3,48(11)\n\t" \ + "stw 3,20(1)\n\t" \ + /* arg11 */ \ + "lwz 3,44(11)\n\t" \ + "stw 3,16(1)\n\t" \ + /* arg10 */ \ + "lwz 3,40(11)\n\t" \ + "stw 3,12(1)\n\t" \ + /* arg9 */ \ + "lwz 3,36(11)\n\t" \ + "stw 3,8(1)\n\t" \ + /* args1-8 */ \ + "lwz 3,4(11)\n\t" /* arg1->r3 */ \ + "lwz 4,8(11)\n\t" \ + "lwz 5,12(11)\n\t" \ + "lwz 6,16(11)\n\t" /* arg4->r6 */ \ + "lwz 7,20(11)\n\t" \ + "lwz 8,24(11)\n\t" \ + "lwz 9,28(11)\n\t" \ + "lwz 10,32(11)\n\t" /* arg8->r10 */ \ + "lwz 11,0(11)\n\t" /* target->r11 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ + VALGRIND_RESTORE_STACK \ + "mr %0,3" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[0]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#endif /* PLAT_ppc32_linux */ + +/* ------------------------ ppc64-linux ------------------------ */ + +#if defined(PLAT_ppc64be_linux) + +/* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */ + +/* These regs are trashed by the hidden call. */ +#define __CALLER_SAVED_REGS \ + "lr", "ctr", "xer", \ + "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \ + "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \ + "r11", "r12", "r13" + +/* Macros to save and align the stack before making a function + call and restore it afterwards as gcc may not keep the stack + pointer aligned if it doesn't realise calls are being made + to other functions. */ + +#define VALGRIND_ALIGN_STACK \ + "mr 28,1\n\t" \ + "rldicr 1,1,0,59\n\t" +#define VALGRIND_RESTORE_STACK \ + "mr 1,28\n\t" + +/* These CALL_FN_ macros assume that on ppc64-linux, sizeof(unsigned + long) == 8. */ + +#define CALL_FN_W_v(lval, orig) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[3+0]; \ + volatile unsigned long _res; \ + /* _argvec[0] holds current r2 across the call */ \ + _argvec[1] = (unsigned long)_orig.r2; \ + _argvec[2] = (unsigned long)_orig.nraddr; \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "mr 11,%1\n\t" \ + "std 2,-16(11)\n\t" /* save tocptr */ \ + "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ + "ld 11, 0(11)\n\t" /* target->r11 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ + "mr 11,%1\n\t" \ + "mr %0,3\n\t" \ + "ld 2,-16(11)\n\t" /* restore tocptr */ \ + VALGRIND_RESTORE_STACK \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[2]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_W(lval, orig, arg1) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[3+1]; \ + volatile unsigned long _res; \ + /* _argvec[0] holds current r2 across the call */ \ + _argvec[1] = (unsigned long)_orig.r2; \ + _argvec[2] = (unsigned long)_orig.nraddr; \ + _argvec[2+1] = (unsigned long)arg1; \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "mr 11,%1\n\t" \ + "std 2,-16(11)\n\t" /* save tocptr */ \ + "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ + "ld 3, 8(11)\n\t" /* arg1->r3 */ \ + "ld 11, 0(11)\n\t" /* target->r11 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ + "mr 11,%1\n\t" \ + "mr %0,3\n\t" \ + "ld 2,-16(11)\n\t" /* restore tocptr */ \ + VALGRIND_RESTORE_STACK \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[2]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_WW(lval, orig, arg1,arg2) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[3+2]; \ + volatile unsigned long _res; \ + /* _argvec[0] holds current r2 across the call */ \ + _argvec[1] = (unsigned long)_orig.r2; \ + _argvec[2] = (unsigned long)_orig.nraddr; \ + _argvec[2+1] = (unsigned long)arg1; \ + _argvec[2+2] = (unsigned long)arg2; \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "mr 11,%1\n\t" \ + "std 2,-16(11)\n\t" /* save tocptr */ \ + "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ + "ld 3, 8(11)\n\t" /* arg1->r3 */ \ + "ld 4, 16(11)\n\t" /* arg2->r4 */ \ + "ld 11, 0(11)\n\t" /* target->r11 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ + "mr 11,%1\n\t" \ + "mr %0,3\n\t" \ + "ld 2,-16(11)\n\t" /* restore tocptr */ \ + VALGRIND_RESTORE_STACK \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[2]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[3+3]; \ + volatile unsigned long _res; \ + /* _argvec[0] holds current r2 across the call */ \ + _argvec[1] = (unsigned long)_orig.r2; \ + _argvec[2] = (unsigned long)_orig.nraddr; \ + _argvec[2+1] = (unsigned long)arg1; \ + _argvec[2+2] = (unsigned long)arg2; \ + _argvec[2+3] = (unsigned long)arg3; \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "mr 11,%1\n\t" \ + "std 2,-16(11)\n\t" /* save tocptr */ \ + "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ + "ld 3, 8(11)\n\t" /* arg1->r3 */ \ + "ld 4, 16(11)\n\t" /* arg2->r4 */ \ + "ld 5, 24(11)\n\t" /* arg3->r5 */ \ + "ld 11, 0(11)\n\t" /* target->r11 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ + "mr 11,%1\n\t" \ + "mr %0,3\n\t" \ + "ld 2,-16(11)\n\t" /* restore tocptr */ \ + VALGRIND_RESTORE_STACK \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[2]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[3+4]; \ + volatile unsigned long _res; \ + /* _argvec[0] holds current r2 across the call */ \ + _argvec[1] = (unsigned long)_orig.r2; \ + _argvec[2] = (unsigned long)_orig.nraddr; \ + _argvec[2+1] = (unsigned long)arg1; \ + _argvec[2+2] = (unsigned long)arg2; \ + _argvec[2+3] = (unsigned long)arg3; \ + _argvec[2+4] = (unsigned long)arg4; \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "mr 11,%1\n\t" \ + "std 2,-16(11)\n\t" /* save tocptr */ \ + "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ + "ld 3, 8(11)\n\t" /* arg1->r3 */ \ + "ld 4, 16(11)\n\t" /* arg2->r4 */ \ + "ld 5, 24(11)\n\t" /* arg3->r5 */ \ + "ld 6, 32(11)\n\t" /* arg4->r6 */ \ + "ld 11, 0(11)\n\t" /* target->r11 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ + "mr 11,%1\n\t" \ + "mr %0,3\n\t" \ + "ld 2,-16(11)\n\t" /* restore tocptr */ \ + VALGRIND_RESTORE_STACK \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[2]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[3+5]; \ + volatile unsigned long _res; \ + /* _argvec[0] holds current r2 across the call */ \ + _argvec[1] = (unsigned long)_orig.r2; \ + _argvec[2] = (unsigned long)_orig.nraddr; \ + _argvec[2+1] = (unsigned long)arg1; \ + _argvec[2+2] = (unsigned long)arg2; \ + _argvec[2+3] = (unsigned long)arg3; \ + _argvec[2+4] = (unsigned long)arg4; \ + _argvec[2+5] = (unsigned long)arg5; \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "mr 11,%1\n\t" \ + "std 2,-16(11)\n\t" /* save tocptr */ \ + "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ + "ld 3, 8(11)\n\t" /* arg1->r3 */ \ + "ld 4, 16(11)\n\t" /* arg2->r4 */ \ + "ld 5, 24(11)\n\t" /* arg3->r5 */ \ + "ld 6, 32(11)\n\t" /* arg4->r6 */ \ + "ld 7, 40(11)\n\t" /* arg5->r7 */ \ + "ld 11, 0(11)\n\t" /* target->r11 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ + "mr 11,%1\n\t" \ + "mr %0,3\n\t" \ + "ld 2,-16(11)\n\t" /* restore tocptr */ \ + VALGRIND_RESTORE_STACK \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[2]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[3+6]; \ + volatile unsigned long _res; \ + /* _argvec[0] holds current r2 across the call */ \ + _argvec[1] = (unsigned long)_orig.r2; \ + _argvec[2] = (unsigned long)_orig.nraddr; \ + _argvec[2+1] = (unsigned long)arg1; \ + _argvec[2+2] = (unsigned long)arg2; \ + _argvec[2+3] = (unsigned long)arg3; \ + _argvec[2+4] = (unsigned long)arg4; \ + _argvec[2+5] = (unsigned long)arg5; \ + _argvec[2+6] = (unsigned long)arg6; \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "mr 11,%1\n\t" \ + "std 2,-16(11)\n\t" /* save tocptr */ \ + "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ + "ld 3, 8(11)\n\t" /* arg1->r3 */ \ + "ld 4, 16(11)\n\t" /* arg2->r4 */ \ + "ld 5, 24(11)\n\t" /* arg3->r5 */ \ + "ld 6, 32(11)\n\t" /* arg4->r6 */ \ + "ld 7, 40(11)\n\t" /* arg5->r7 */ \ + "ld 8, 48(11)\n\t" /* arg6->r8 */ \ + "ld 11, 0(11)\n\t" /* target->r11 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ + "mr 11,%1\n\t" \ + "mr %0,3\n\t" \ + "ld 2,-16(11)\n\t" /* restore tocptr */ \ + VALGRIND_RESTORE_STACK \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[2]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ + arg7) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[3+7]; \ + volatile unsigned long _res; \ + /* _argvec[0] holds current r2 across the call */ \ + _argvec[1] = (unsigned long)_orig.r2; \ + _argvec[2] = (unsigned long)_orig.nraddr; \ + _argvec[2+1] = (unsigned long)arg1; \ + _argvec[2+2] = (unsigned long)arg2; \ + _argvec[2+3] = (unsigned long)arg3; \ + _argvec[2+4] = (unsigned long)arg4; \ + _argvec[2+5] = (unsigned long)arg5; \ + _argvec[2+6] = (unsigned long)arg6; \ + _argvec[2+7] = (unsigned long)arg7; \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "mr 11,%1\n\t" \ + "std 2,-16(11)\n\t" /* save tocptr */ \ + "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ + "ld 3, 8(11)\n\t" /* arg1->r3 */ \ + "ld 4, 16(11)\n\t" /* arg2->r4 */ \ + "ld 5, 24(11)\n\t" /* arg3->r5 */ \ + "ld 6, 32(11)\n\t" /* arg4->r6 */ \ + "ld 7, 40(11)\n\t" /* arg5->r7 */ \ + "ld 8, 48(11)\n\t" /* arg6->r8 */ \ + "ld 9, 56(11)\n\t" /* arg7->r9 */ \ + "ld 11, 0(11)\n\t" /* target->r11 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ + "mr 11,%1\n\t" \ + "mr %0,3\n\t" \ + "ld 2,-16(11)\n\t" /* restore tocptr */ \ + VALGRIND_RESTORE_STACK \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[2]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ + arg7,arg8) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[3+8]; \ + volatile unsigned long _res; \ + /* _argvec[0] holds current r2 across the call */ \ + _argvec[1] = (unsigned long)_orig.r2; \ + _argvec[2] = (unsigned long)_orig.nraddr; \ + _argvec[2+1] = (unsigned long)arg1; \ + _argvec[2+2] = (unsigned long)arg2; \ + _argvec[2+3] = (unsigned long)arg3; \ + _argvec[2+4] = (unsigned long)arg4; \ + _argvec[2+5] = (unsigned long)arg5; \ + _argvec[2+6] = (unsigned long)arg6; \ + _argvec[2+7] = (unsigned long)arg7; \ + _argvec[2+8] = (unsigned long)arg8; \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "mr 11,%1\n\t" \ + "std 2,-16(11)\n\t" /* save tocptr */ \ + "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ + "ld 3, 8(11)\n\t" /* arg1->r3 */ \ + "ld 4, 16(11)\n\t" /* arg2->r4 */ \ + "ld 5, 24(11)\n\t" /* arg3->r5 */ \ + "ld 6, 32(11)\n\t" /* arg4->r6 */ \ + "ld 7, 40(11)\n\t" /* arg5->r7 */ \ + "ld 8, 48(11)\n\t" /* arg6->r8 */ \ + "ld 9, 56(11)\n\t" /* arg7->r9 */ \ + "ld 10, 64(11)\n\t" /* arg8->r10 */ \ + "ld 11, 0(11)\n\t" /* target->r11 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ + "mr 11,%1\n\t" \ + "mr %0,3\n\t" \ + "ld 2,-16(11)\n\t" /* restore tocptr */ \ + VALGRIND_RESTORE_STACK \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[2]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ + arg7,arg8,arg9) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[3+9]; \ + volatile unsigned long _res; \ + /* _argvec[0] holds current r2 across the call */ \ + _argvec[1] = (unsigned long)_orig.r2; \ + _argvec[2] = (unsigned long)_orig.nraddr; \ + _argvec[2+1] = (unsigned long)arg1; \ + _argvec[2+2] = (unsigned long)arg2; \ + _argvec[2+3] = (unsigned long)arg3; \ + _argvec[2+4] = (unsigned long)arg4; \ + _argvec[2+5] = (unsigned long)arg5; \ + _argvec[2+6] = (unsigned long)arg6; \ + _argvec[2+7] = (unsigned long)arg7; \ + _argvec[2+8] = (unsigned long)arg8; \ + _argvec[2+9] = (unsigned long)arg9; \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "mr 11,%1\n\t" \ + "std 2,-16(11)\n\t" /* save tocptr */ \ + "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ + "addi 1,1,-128\n\t" /* expand stack frame */ \ + /* arg9 */ \ + "ld 3,72(11)\n\t" \ + "std 3,112(1)\n\t" \ + /* args1-8 */ \ + "ld 3, 8(11)\n\t" /* arg1->r3 */ \ + "ld 4, 16(11)\n\t" /* arg2->r4 */ \ + "ld 5, 24(11)\n\t" /* arg3->r5 */ \ + "ld 6, 32(11)\n\t" /* arg4->r6 */ \ + "ld 7, 40(11)\n\t" /* arg5->r7 */ \ + "ld 8, 48(11)\n\t" /* arg6->r8 */ \ + "ld 9, 56(11)\n\t" /* arg7->r9 */ \ + "ld 10, 64(11)\n\t" /* arg8->r10 */ \ + "ld 11, 0(11)\n\t" /* target->r11 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ + "mr 11,%1\n\t" \ + "mr %0,3\n\t" \ + "ld 2,-16(11)\n\t" /* restore tocptr */ \ + VALGRIND_RESTORE_STACK \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[2]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ + arg7,arg8,arg9,arg10) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[3+10]; \ + volatile unsigned long _res; \ + /* _argvec[0] holds current r2 across the call */ \ + _argvec[1] = (unsigned long)_orig.r2; \ + _argvec[2] = (unsigned long)_orig.nraddr; \ + _argvec[2+1] = (unsigned long)arg1; \ + _argvec[2+2] = (unsigned long)arg2; \ + _argvec[2+3] = (unsigned long)arg3; \ + _argvec[2+4] = (unsigned long)arg4; \ + _argvec[2+5] = (unsigned long)arg5; \ + _argvec[2+6] = (unsigned long)arg6; \ + _argvec[2+7] = (unsigned long)arg7; \ + _argvec[2+8] = (unsigned long)arg8; \ + _argvec[2+9] = (unsigned long)arg9; \ + _argvec[2+10] = (unsigned long)arg10; \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "mr 11,%1\n\t" \ + "std 2,-16(11)\n\t" /* save tocptr */ \ + "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ + "addi 1,1,-128\n\t" /* expand stack frame */ \ + /* arg10 */ \ + "ld 3,80(11)\n\t" \ + "std 3,120(1)\n\t" \ + /* arg9 */ \ + "ld 3,72(11)\n\t" \ + "std 3,112(1)\n\t" \ + /* args1-8 */ \ + "ld 3, 8(11)\n\t" /* arg1->r3 */ \ + "ld 4, 16(11)\n\t" /* arg2->r4 */ \ + "ld 5, 24(11)\n\t" /* arg3->r5 */ \ + "ld 6, 32(11)\n\t" /* arg4->r6 */ \ + "ld 7, 40(11)\n\t" /* arg5->r7 */ \ + "ld 8, 48(11)\n\t" /* arg6->r8 */ \ + "ld 9, 56(11)\n\t" /* arg7->r9 */ \ + "ld 10, 64(11)\n\t" /* arg8->r10 */ \ + "ld 11, 0(11)\n\t" /* target->r11 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ + "mr 11,%1\n\t" \ + "mr %0,3\n\t" \ + "ld 2,-16(11)\n\t" /* restore tocptr */ \ + VALGRIND_RESTORE_STACK \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[2]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ + arg7,arg8,arg9,arg10,arg11) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[3+11]; \ + volatile unsigned long _res; \ + /* _argvec[0] holds current r2 across the call */ \ + _argvec[1] = (unsigned long)_orig.r2; \ + _argvec[2] = (unsigned long)_orig.nraddr; \ + _argvec[2+1] = (unsigned long)arg1; \ + _argvec[2+2] = (unsigned long)arg2; \ + _argvec[2+3] = (unsigned long)arg3; \ + _argvec[2+4] = (unsigned long)arg4; \ + _argvec[2+5] = (unsigned long)arg5; \ + _argvec[2+6] = (unsigned long)arg6; \ + _argvec[2+7] = (unsigned long)arg7; \ + _argvec[2+8] = (unsigned long)arg8; \ + _argvec[2+9] = (unsigned long)arg9; \ + _argvec[2+10] = (unsigned long)arg10; \ + _argvec[2+11] = (unsigned long)arg11; \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "mr 11,%1\n\t" \ + "std 2,-16(11)\n\t" /* save tocptr */ \ + "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ + "addi 1,1,-144\n\t" /* expand stack frame */ \ + /* arg11 */ \ + "ld 3,88(11)\n\t" \ + "std 3,128(1)\n\t" \ + /* arg10 */ \ + "ld 3,80(11)\n\t" \ + "std 3,120(1)\n\t" \ + /* arg9 */ \ + "ld 3,72(11)\n\t" \ + "std 3,112(1)\n\t" \ + /* args1-8 */ \ + "ld 3, 8(11)\n\t" /* arg1->r3 */ \ + "ld 4, 16(11)\n\t" /* arg2->r4 */ \ + "ld 5, 24(11)\n\t" /* arg3->r5 */ \ + "ld 6, 32(11)\n\t" /* arg4->r6 */ \ + "ld 7, 40(11)\n\t" /* arg5->r7 */ \ + "ld 8, 48(11)\n\t" /* arg6->r8 */ \ + "ld 9, 56(11)\n\t" /* arg7->r9 */ \ + "ld 10, 64(11)\n\t" /* arg8->r10 */ \ + "ld 11, 0(11)\n\t" /* target->r11 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ + "mr 11,%1\n\t" \ + "mr %0,3\n\t" \ + "ld 2,-16(11)\n\t" /* restore tocptr */ \ + VALGRIND_RESTORE_STACK \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[2]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ + arg7,arg8,arg9,arg10,arg11,arg12) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[3+12]; \ + volatile unsigned long _res; \ + /* _argvec[0] holds current r2 across the call */ \ + _argvec[1] = (unsigned long)_orig.r2; \ + _argvec[2] = (unsigned long)_orig.nraddr; \ + _argvec[2+1] = (unsigned long)arg1; \ + _argvec[2+2] = (unsigned long)arg2; \ + _argvec[2+3] = (unsigned long)arg3; \ + _argvec[2+4] = (unsigned long)arg4; \ + _argvec[2+5] = (unsigned long)arg5; \ + _argvec[2+6] = (unsigned long)arg6; \ + _argvec[2+7] = (unsigned long)arg7; \ + _argvec[2+8] = (unsigned long)arg8; \ + _argvec[2+9] = (unsigned long)arg9; \ + _argvec[2+10] = (unsigned long)arg10; \ + _argvec[2+11] = (unsigned long)arg11; \ + _argvec[2+12] = (unsigned long)arg12; \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "mr 11,%1\n\t" \ + "std 2,-16(11)\n\t" /* save tocptr */ \ + "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ + "addi 1,1,-144\n\t" /* expand stack frame */ \ + /* arg12 */ \ + "ld 3,96(11)\n\t" \ + "std 3,136(1)\n\t" \ + /* arg11 */ \ + "ld 3,88(11)\n\t" \ + "std 3,128(1)\n\t" \ + /* arg10 */ \ + "ld 3,80(11)\n\t" \ + "std 3,120(1)\n\t" \ + /* arg9 */ \ + "ld 3,72(11)\n\t" \ + "std 3,112(1)\n\t" \ + /* args1-8 */ \ + "ld 3, 8(11)\n\t" /* arg1->r3 */ \ + "ld 4, 16(11)\n\t" /* arg2->r4 */ \ + "ld 5, 24(11)\n\t" /* arg3->r5 */ \ + "ld 6, 32(11)\n\t" /* arg4->r6 */ \ + "ld 7, 40(11)\n\t" /* arg5->r7 */ \ + "ld 8, 48(11)\n\t" /* arg6->r8 */ \ + "ld 9, 56(11)\n\t" /* arg7->r9 */ \ + "ld 10, 64(11)\n\t" /* arg8->r10 */ \ + "ld 11, 0(11)\n\t" /* target->r11 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ + "mr 11,%1\n\t" \ + "mr %0,3\n\t" \ + "ld 2,-16(11)\n\t" /* restore tocptr */ \ + VALGRIND_RESTORE_STACK \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[2]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#endif /* PLAT_ppc64be_linux */ + +/* ------------------------- ppc64le-linux ----------------------- */ +#if defined(PLAT_ppc64le_linux) + +/* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */ + +/* These regs are trashed by the hidden call. */ +#define __CALLER_SAVED_REGS \ + "lr", "ctr", "xer", \ + "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \ + "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \ + "r11", "r12", "r13" + +/* Macros to save and align the stack before making a function + call and restore it afterwards as gcc may not keep the stack + pointer aligned if it doesn't realise calls are being made + to other functions. */ + +#define VALGRIND_ALIGN_STACK \ + "mr 28,1\n\t" \ + "rldicr 1,1,0,59\n\t" +#define VALGRIND_RESTORE_STACK \ + "mr 1,28\n\t" + +/* These CALL_FN_ macros assume that on ppc64-linux, sizeof(unsigned + long) == 8. */ + +#define CALL_FN_W_v(lval, orig) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[3+0]; \ + volatile unsigned long _res; \ + /* _argvec[0] holds current r2 across the call */ \ + _argvec[1] = (unsigned long)_orig.r2; \ + _argvec[2] = (unsigned long)_orig.nraddr; \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "mr 12,%1\n\t" \ + "std 2,-16(12)\n\t" /* save tocptr */ \ + "ld 2,-8(12)\n\t" /* use nraddr's tocptr */ \ + "ld 12, 0(12)\n\t" /* target->r12 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R12 \ + "mr 12,%1\n\t" \ + "mr %0,3\n\t" \ + "ld 2,-16(12)\n\t" /* restore tocptr */ \ + VALGRIND_RESTORE_STACK \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[2]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_W(lval, orig, arg1) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[3+1]; \ + volatile unsigned long _res; \ + /* _argvec[0] holds current r2 across the call */ \ + _argvec[1] = (unsigned long)_orig.r2; \ + _argvec[2] = (unsigned long)_orig.nraddr; \ + _argvec[2+1] = (unsigned long)arg1; \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "mr 12,%1\n\t" \ + "std 2,-16(12)\n\t" /* save tocptr */ \ + "ld 2,-8(12)\n\t" /* use nraddr's tocptr */ \ + "ld 3, 8(12)\n\t" /* arg1->r3 */ \ + "ld 12, 0(12)\n\t" /* target->r12 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R12 \ + "mr 12,%1\n\t" \ + "mr %0,3\n\t" \ + "ld 2,-16(12)\n\t" /* restore tocptr */ \ + VALGRIND_RESTORE_STACK \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[2]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_WW(lval, orig, arg1,arg2) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[3+2]; \ + volatile unsigned long _res; \ + /* _argvec[0] holds current r2 across the call */ \ + _argvec[1] = (unsigned long)_orig.r2; \ + _argvec[2] = (unsigned long)_orig.nraddr; \ + _argvec[2+1] = (unsigned long)arg1; \ + _argvec[2+2] = (unsigned long)arg2; \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "mr 12,%1\n\t" \ + "std 2,-16(12)\n\t" /* save tocptr */ \ + "ld 2,-8(12)\n\t" /* use nraddr's tocptr */ \ + "ld 3, 8(12)\n\t" /* arg1->r3 */ \ + "ld 4, 16(12)\n\t" /* arg2->r4 */ \ + "ld 12, 0(12)\n\t" /* target->r12 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R12 \ + "mr 12,%1\n\t" \ + "mr %0,3\n\t" \ + "ld 2,-16(12)\n\t" /* restore tocptr */ \ + VALGRIND_RESTORE_STACK \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[2]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[3+3]; \ + volatile unsigned long _res; \ + /* _argvec[0] holds current r2 across the call */ \ + _argvec[1] = (unsigned long)_orig.r2; \ + _argvec[2] = (unsigned long)_orig.nraddr; \ + _argvec[2+1] = (unsigned long)arg1; \ + _argvec[2+2] = (unsigned long)arg2; \ + _argvec[2+3] = (unsigned long)arg3; \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "mr 12,%1\n\t" \ + "std 2,-16(12)\n\t" /* save tocptr */ \ + "ld 2,-8(12)\n\t" /* use nraddr's tocptr */ \ + "ld 3, 8(12)\n\t" /* arg1->r3 */ \ + "ld 4, 16(12)\n\t" /* arg2->r4 */ \ + "ld 5, 24(12)\n\t" /* arg3->r5 */ \ + "ld 12, 0(12)\n\t" /* target->r12 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R12 \ + "mr 12,%1\n\t" \ + "mr %0,3\n\t" \ + "ld 2,-16(12)\n\t" /* restore tocptr */ \ + VALGRIND_RESTORE_STACK \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[2]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[3+4]; \ + volatile unsigned long _res; \ + /* _argvec[0] holds current r2 across the call */ \ + _argvec[1] = (unsigned long)_orig.r2; \ + _argvec[2] = (unsigned long)_orig.nraddr; \ + _argvec[2+1] = (unsigned long)arg1; \ + _argvec[2+2] = (unsigned long)arg2; \ + _argvec[2+3] = (unsigned long)arg3; \ + _argvec[2+4] = (unsigned long)arg4; \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "mr 12,%1\n\t" \ + "std 2,-16(12)\n\t" /* save tocptr */ \ + "ld 2,-8(12)\n\t" /* use nraddr's tocptr */ \ + "ld 3, 8(12)\n\t" /* arg1->r3 */ \ + "ld 4, 16(12)\n\t" /* arg2->r4 */ \ + "ld 5, 24(12)\n\t" /* arg3->r5 */ \ + "ld 6, 32(12)\n\t" /* arg4->r6 */ \ + "ld 12, 0(12)\n\t" /* target->r12 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R12 \ + "mr 12,%1\n\t" \ + "mr %0,3\n\t" \ + "ld 2,-16(12)\n\t" /* restore tocptr */ \ + VALGRIND_RESTORE_STACK \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[2]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[3+5]; \ + volatile unsigned long _res; \ + /* _argvec[0] holds current r2 across the call */ \ + _argvec[1] = (unsigned long)_orig.r2; \ + _argvec[2] = (unsigned long)_orig.nraddr; \ + _argvec[2+1] = (unsigned long)arg1; \ + _argvec[2+2] = (unsigned long)arg2; \ + _argvec[2+3] = (unsigned long)arg3; \ + _argvec[2+4] = (unsigned long)arg4; \ + _argvec[2+5] = (unsigned long)arg5; \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "mr 12,%1\n\t" \ + "std 2,-16(12)\n\t" /* save tocptr */ \ + "ld 2,-8(12)\n\t" /* use nraddr's tocptr */ \ + "ld 3, 8(12)\n\t" /* arg1->r3 */ \ + "ld 4, 16(12)\n\t" /* arg2->r4 */ \ + "ld 5, 24(12)\n\t" /* arg3->r5 */ \ + "ld 6, 32(12)\n\t" /* arg4->r6 */ \ + "ld 7, 40(12)\n\t" /* arg5->r7 */ \ + "ld 12, 0(12)\n\t" /* target->r12 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R12 \ + "mr 12,%1\n\t" \ + "mr %0,3\n\t" \ + "ld 2,-16(12)\n\t" /* restore tocptr */ \ + VALGRIND_RESTORE_STACK \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[2]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[3+6]; \ + volatile unsigned long _res; \ + /* _argvec[0] holds current r2 across the call */ \ + _argvec[1] = (unsigned long)_orig.r2; \ + _argvec[2] = (unsigned long)_orig.nraddr; \ + _argvec[2+1] = (unsigned long)arg1; \ + _argvec[2+2] = (unsigned long)arg2; \ + _argvec[2+3] = (unsigned long)arg3; \ + _argvec[2+4] = (unsigned long)arg4; \ + _argvec[2+5] = (unsigned long)arg5; \ + _argvec[2+6] = (unsigned long)arg6; \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "mr 12,%1\n\t" \ + "std 2,-16(12)\n\t" /* save tocptr */ \ + "ld 2,-8(12)\n\t" /* use nraddr's tocptr */ \ + "ld 3, 8(12)\n\t" /* arg1->r3 */ \ + "ld 4, 16(12)\n\t" /* arg2->r4 */ \ + "ld 5, 24(12)\n\t" /* arg3->r5 */ \ + "ld 6, 32(12)\n\t" /* arg4->r6 */ \ + "ld 7, 40(12)\n\t" /* arg5->r7 */ \ + "ld 8, 48(12)\n\t" /* arg6->r8 */ \ + "ld 12, 0(12)\n\t" /* target->r12 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R12 \ + "mr 12,%1\n\t" \ + "mr %0,3\n\t" \ + "ld 2,-16(12)\n\t" /* restore tocptr */ \ + VALGRIND_RESTORE_STACK \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[2]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ + arg7) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[3+7]; \ + volatile unsigned long _res; \ + /* _argvec[0] holds current r2 across the call */ \ + _argvec[1] = (unsigned long)_orig.r2; \ + _argvec[2] = (unsigned long)_orig.nraddr; \ + _argvec[2+1] = (unsigned long)arg1; \ + _argvec[2+2] = (unsigned long)arg2; \ + _argvec[2+3] = (unsigned long)arg3; \ + _argvec[2+4] = (unsigned long)arg4; \ + _argvec[2+5] = (unsigned long)arg5; \ + _argvec[2+6] = (unsigned long)arg6; \ + _argvec[2+7] = (unsigned long)arg7; \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "mr 12,%1\n\t" \ + "std 2,-16(12)\n\t" /* save tocptr */ \ + "ld 2,-8(12)\n\t" /* use nraddr's tocptr */ \ + "ld 3, 8(12)\n\t" /* arg1->r3 */ \ + "ld 4, 16(12)\n\t" /* arg2->r4 */ \ + "ld 5, 24(12)\n\t" /* arg3->r5 */ \ + "ld 6, 32(12)\n\t" /* arg4->r6 */ \ + "ld 7, 40(12)\n\t" /* arg5->r7 */ \ + "ld 8, 48(12)\n\t" /* arg6->r8 */ \ + "ld 9, 56(12)\n\t" /* arg7->r9 */ \ + "ld 12, 0(12)\n\t" /* target->r12 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R12 \ + "mr 12,%1\n\t" \ + "mr %0,3\n\t" \ + "ld 2,-16(12)\n\t" /* restore tocptr */ \ + VALGRIND_RESTORE_STACK \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[2]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ + arg7,arg8) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[3+8]; \ + volatile unsigned long _res; \ + /* _argvec[0] holds current r2 across the call */ \ + _argvec[1] = (unsigned long)_orig.r2; \ + _argvec[2] = (unsigned long)_orig.nraddr; \ + _argvec[2+1] = (unsigned long)arg1; \ + _argvec[2+2] = (unsigned long)arg2; \ + _argvec[2+3] = (unsigned long)arg3; \ + _argvec[2+4] = (unsigned long)arg4; \ + _argvec[2+5] = (unsigned long)arg5; \ + _argvec[2+6] = (unsigned long)arg6; \ + _argvec[2+7] = (unsigned long)arg7; \ + _argvec[2+8] = (unsigned long)arg8; \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "mr 12,%1\n\t" \ + "std 2,-16(12)\n\t" /* save tocptr */ \ + "ld 2,-8(12)\n\t" /* use nraddr's tocptr */ \ + "ld 3, 8(12)\n\t" /* arg1->r3 */ \ + "ld 4, 16(12)\n\t" /* arg2->r4 */ \ + "ld 5, 24(12)\n\t" /* arg3->r5 */ \ + "ld 6, 32(12)\n\t" /* arg4->r6 */ \ + "ld 7, 40(12)\n\t" /* arg5->r7 */ \ + "ld 8, 48(12)\n\t" /* arg6->r8 */ \ + "ld 9, 56(12)\n\t" /* arg7->r9 */ \ + "ld 10, 64(12)\n\t" /* arg8->r10 */ \ + "ld 12, 0(12)\n\t" /* target->r12 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R12 \ + "mr 12,%1\n\t" \ + "mr %0,3\n\t" \ + "ld 2,-16(12)\n\t" /* restore tocptr */ \ + VALGRIND_RESTORE_STACK \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[2]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ + arg7,arg8,arg9) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[3+9]; \ + volatile unsigned long _res; \ + /* _argvec[0] holds current r2 across the call */ \ + _argvec[1] = (unsigned long)_orig.r2; \ + _argvec[2] = (unsigned long)_orig.nraddr; \ + _argvec[2+1] = (unsigned long)arg1; \ + _argvec[2+2] = (unsigned long)arg2; \ + _argvec[2+3] = (unsigned long)arg3; \ + _argvec[2+4] = (unsigned long)arg4; \ + _argvec[2+5] = (unsigned long)arg5; \ + _argvec[2+6] = (unsigned long)arg6; \ + _argvec[2+7] = (unsigned long)arg7; \ + _argvec[2+8] = (unsigned long)arg8; \ + _argvec[2+9] = (unsigned long)arg9; \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "mr 12,%1\n\t" \ + "std 2,-16(12)\n\t" /* save tocptr */ \ + "ld 2,-8(12)\n\t" /* use nraddr's tocptr */ \ + "addi 1,1,-128\n\t" /* expand stack frame */ \ + /* arg9 */ \ + "ld 3,72(12)\n\t" \ + "std 3,96(1)\n\t" \ + /* args1-8 */ \ + "ld 3, 8(12)\n\t" /* arg1->r3 */ \ + "ld 4, 16(12)\n\t" /* arg2->r4 */ \ + "ld 5, 24(12)\n\t" /* arg3->r5 */ \ + "ld 6, 32(12)\n\t" /* arg4->r6 */ \ + "ld 7, 40(12)\n\t" /* arg5->r7 */ \ + "ld 8, 48(12)\n\t" /* arg6->r8 */ \ + "ld 9, 56(12)\n\t" /* arg7->r9 */ \ + "ld 10, 64(12)\n\t" /* arg8->r10 */ \ + "ld 12, 0(12)\n\t" /* target->r12 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R12 \ + "mr 12,%1\n\t" \ + "mr %0,3\n\t" \ + "ld 2,-16(12)\n\t" /* restore tocptr */ \ + VALGRIND_RESTORE_STACK \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[2]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ + arg7,arg8,arg9,arg10) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[3+10]; \ + volatile unsigned long _res; \ + /* _argvec[0] holds current r2 across the call */ \ + _argvec[1] = (unsigned long)_orig.r2; \ + _argvec[2] = (unsigned long)_orig.nraddr; \ + _argvec[2+1] = (unsigned long)arg1; \ + _argvec[2+2] = (unsigned long)arg2; \ + _argvec[2+3] = (unsigned long)arg3; \ + _argvec[2+4] = (unsigned long)arg4; \ + _argvec[2+5] = (unsigned long)arg5; \ + _argvec[2+6] = (unsigned long)arg6; \ + _argvec[2+7] = (unsigned long)arg7; \ + _argvec[2+8] = (unsigned long)arg8; \ + _argvec[2+9] = (unsigned long)arg9; \ + _argvec[2+10] = (unsigned long)arg10; \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "mr 12,%1\n\t" \ + "std 2,-16(12)\n\t" /* save tocptr */ \ + "ld 2,-8(12)\n\t" /* use nraddr's tocptr */ \ + "addi 1,1,-128\n\t" /* expand stack frame */ \ + /* arg10 */ \ + "ld 3,80(12)\n\t" \ + "std 3,104(1)\n\t" \ + /* arg9 */ \ + "ld 3,72(12)\n\t" \ + "std 3,96(1)\n\t" \ + /* args1-8 */ \ + "ld 3, 8(12)\n\t" /* arg1->r3 */ \ + "ld 4, 16(12)\n\t" /* arg2->r4 */ \ + "ld 5, 24(12)\n\t" /* arg3->r5 */ \ + "ld 6, 32(12)\n\t" /* arg4->r6 */ \ + "ld 7, 40(12)\n\t" /* arg5->r7 */ \ + "ld 8, 48(12)\n\t" /* arg6->r8 */ \ + "ld 9, 56(12)\n\t" /* arg7->r9 */ \ + "ld 10, 64(12)\n\t" /* arg8->r10 */ \ + "ld 12, 0(12)\n\t" /* target->r12 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R12 \ + "mr 12,%1\n\t" \ + "mr %0,3\n\t" \ + "ld 2,-16(12)\n\t" /* restore tocptr */ \ + VALGRIND_RESTORE_STACK \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[2]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ + arg7,arg8,arg9,arg10,arg11) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[3+11]; \ + volatile unsigned long _res; \ + /* _argvec[0] holds current r2 across the call */ \ + _argvec[1] = (unsigned long)_orig.r2; \ + _argvec[2] = (unsigned long)_orig.nraddr; \ + _argvec[2+1] = (unsigned long)arg1; \ + _argvec[2+2] = (unsigned long)arg2; \ + _argvec[2+3] = (unsigned long)arg3; \ + _argvec[2+4] = (unsigned long)arg4; \ + _argvec[2+5] = (unsigned long)arg5; \ + _argvec[2+6] = (unsigned long)arg6; \ + _argvec[2+7] = (unsigned long)arg7; \ + _argvec[2+8] = (unsigned long)arg8; \ + _argvec[2+9] = (unsigned long)arg9; \ + _argvec[2+10] = (unsigned long)arg10; \ + _argvec[2+11] = (unsigned long)arg11; \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "mr 12,%1\n\t" \ + "std 2,-16(12)\n\t" /* save tocptr */ \ + "ld 2,-8(12)\n\t" /* use nraddr's tocptr */ \ + "addi 1,1,-144\n\t" /* expand stack frame */ \ + /* arg11 */ \ + "ld 3,88(12)\n\t" \ + "std 3,112(1)\n\t" \ + /* arg10 */ \ + "ld 3,80(12)\n\t" \ + "std 3,104(1)\n\t" \ + /* arg9 */ \ + "ld 3,72(12)\n\t" \ + "std 3,96(1)\n\t" \ + /* args1-8 */ \ + "ld 3, 8(12)\n\t" /* arg1->r3 */ \ + "ld 4, 16(12)\n\t" /* arg2->r4 */ \ + "ld 5, 24(12)\n\t" /* arg3->r5 */ \ + "ld 6, 32(12)\n\t" /* arg4->r6 */ \ + "ld 7, 40(12)\n\t" /* arg5->r7 */ \ + "ld 8, 48(12)\n\t" /* arg6->r8 */ \ + "ld 9, 56(12)\n\t" /* arg7->r9 */ \ + "ld 10, 64(12)\n\t" /* arg8->r10 */ \ + "ld 12, 0(12)\n\t" /* target->r12 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R12 \ + "mr 12,%1\n\t" \ + "mr %0,3\n\t" \ + "ld 2,-16(12)\n\t" /* restore tocptr */ \ + VALGRIND_RESTORE_STACK \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[2]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ + arg7,arg8,arg9,arg10,arg11,arg12) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[3+12]; \ + volatile unsigned long _res; \ + /* _argvec[0] holds current r2 across the call */ \ + _argvec[1] = (unsigned long)_orig.r2; \ + _argvec[2] = (unsigned long)_orig.nraddr; \ + _argvec[2+1] = (unsigned long)arg1; \ + _argvec[2+2] = (unsigned long)arg2; \ + _argvec[2+3] = (unsigned long)arg3; \ + _argvec[2+4] = (unsigned long)arg4; \ + _argvec[2+5] = (unsigned long)arg5; \ + _argvec[2+6] = (unsigned long)arg6; \ + _argvec[2+7] = (unsigned long)arg7; \ + _argvec[2+8] = (unsigned long)arg8; \ + _argvec[2+9] = (unsigned long)arg9; \ + _argvec[2+10] = (unsigned long)arg10; \ + _argvec[2+11] = (unsigned long)arg11; \ + _argvec[2+12] = (unsigned long)arg12; \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "mr 12,%1\n\t" \ + "std 2,-16(12)\n\t" /* save tocptr */ \ + "ld 2,-8(12)\n\t" /* use nraddr's tocptr */ \ + "addi 1,1,-144\n\t" /* expand stack frame */ \ + /* arg12 */ \ + "ld 3,96(12)\n\t" \ + "std 3,120(1)\n\t" \ + /* arg11 */ \ + "ld 3,88(12)\n\t" \ + "std 3,112(1)\n\t" \ + /* arg10 */ \ + "ld 3,80(12)\n\t" \ + "std 3,104(1)\n\t" \ + /* arg9 */ \ + "ld 3,72(12)\n\t" \ + "std 3,96(1)\n\t" \ + /* args1-8 */ \ + "ld 3, 8(12)\n\t" /* arg1->r3 */ \ + "ld 4, 16(12)\n\t" /* arg2->r4 */ \ + "ld 5, 24(12)\n\t" /* arg3->r5 */ \ + "ld 6, 32(12)\n\t" /* arg4->r6 */ \ + "ld 7, 40(12)\n\t" /* arg5->r7 */ \ + "ld 8, 48(12)\n\t" /* arg6->r8 */ \ + "ld 9, 56(12)\n\t" /* arg7->r9 */ \ + "ld 10, 64(12)\n\t" /* arg8->r10 */ \ + "ld 12, 0(12)\n\t" /* target->r12 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R12 \ + "mr 12,%1\n\t" \ + "mr %0,3\n\t" \ + "ld 2,-16(12)\n\t" /* restore tocptr */ \ + VALGRIND_RESTORE_STACK \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[2]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#endif /* PLAT_ppc64le_linux */ + +/* ------------------------- arm-linux ------------------------- */ + +#if defined(PLAT_arm_linux) + +/* These regs are trashed by the hidden call. */ +#define __CALLER_SAVED_REGS "r0", "r1", "r2", "r3","r4","r14" + +/* Macros to save and align the stack before making a function + call and restore it afterwards as gcc may not keep the stack + pointer aligned if it doesn't realise calls are being made + to other functions. */ + +/* This is a bit tricky. We store the original stack pointer in r10 + as it is callee-saves. gcc doesn't allow the use of r11 for some + reason. Also, we can't directly "bic" the stack pointer in thumb + mode since r13 isn't an allowed register number in that context. + So use r4 as a temporary, since that is about to get trashed + anyway, just after each use of this macro. Side effect is we need + to be very careful about any future changes, since + VALGRIND_ALIGN_STACK simply assumes r4 is usable. */ +#define VALGRIND_ALIGN_STACK \ + "mov r10, sp\n\t" \ + "mov r4, sp\n\t" \ + "bic r4, r4, #7\n\t" \ + "mov sp, r4\n\t" +#define VALGRIND_RESTORE_STACK \ + "mov sp, r10\n\t" + +/* These CALL_FN_ macros assume that on arm-linux, sizeof(unsigned + long) == 4. */ + +#define CALL_FN_W_v(lval, orig) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[1]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "ldr r4, [%1] \n\t" /* target->r4 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \ + VALGRIND_RESTORE_STACK \ + "mov %0, r0\n" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "0" (&_argvec[0]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_W(lval, orig, arg1) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[2]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "ldr r0, [%1, #4] \n\t" \ + "ldr r4, [%1] \n\t" /* target->r4 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \ + VALGRIND_RESTORE_STACK \ + "mov %0, r0\n" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "0" (&_argvec[0]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_WW(lval, orig, arg1,arg2) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[3]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "ldr r0, [%1, #4] \n\t" \ + "ldr r1, [%1, #8] \n\t" \ + "ldr r4, [%1] \n\t" /* target->r4 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \ + VALGRIND_RESTORE_STACK \ + "mov %0, r0\n" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "0" (&_argvec[0]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[4]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + _argvec[3] = (unsigned long)(arg3); \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "ldr r0, [%1, #4] \n\t" \ + "ldr r1, [%1, #8] \n\t" \ + "ldr r2, [%1, #12] \n\t" \ + "ldr r4, [%1] \n\t" /* target->r4 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \ + VALGRIND_RESTORE_STACK \ + "mov %0, r0\n" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "0" (&_argvec[0]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[5]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + _argvec[3] = (unsigned long)(arg3); \ + _argvec[4] = (unsigned long)(arg4); \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "ldr r0, [%1, #4] \n\t" \ + "ldr r1, [%1, #8] \n\t" \ + "ldr r2, [%1, #12] \n\t" \ + "ldr r3, [%1, #16] \n\t" \ + "ldr r4, [%1] \n\t" /* target->r4 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \ + VALGRIND_RESTORE_STACK \ + "mov %0, r0" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "0" (&_argvec[0]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[6]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + _argvec[3] = (unsigned long)(arg3); \ + _argvec[4] = (unsigned long)(arg4); \ + _argvec[5] = (unsigned long)(arg5); \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "sub sp, sp, #4 \n\t" \ + "ldr r0, [%1, #20] \n\t" \ + "push {r0} \n\t" \ + "ldr r0, [%1, #4] \n\t" \ + "ldr r1, [%1, #8] \n\t" \ + "ldr r2, [%1, #12] \n\t" \ + "ldr r3, [%1, #16] \n\t" \ + "ldr r4, [%1] \n\t" /* target->r4 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \ + VALGRIND_RESTORE_STACK \ + "mov %0, r0" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "0" (&_argvec[0]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[7]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + _argvec[3] = (unsigned long)(arg3); \ + _argvec[4] = (unsigned long)(arg4); \ + _argvec[5] = (unsigned long)(arg5); \ + _argvec[6] = (unsigned long)(arg6); \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "ldr r0, [%1, #20] \n\t" \ + "ldr r1, [%1, #24] \n\t" \ + "push {r0, r1} \n\t" \ + "ldr r0, [%1, #4] \n\t" \ + "ldr r1, [%1, #8] \n\t" \ + "ldr r2, [%1, #12] \n\t" \ + "ldr r3, [%1, #16] \n\t" \ + "ldr r4, [%1] \n\t" /* target->r4 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \ + VALGRIND_RESTORE_STACK \ + "mov %0, r0" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "0" (&_argvec[0]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ + arg7) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[8]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + _argvec[3] = (unsigned long)(arg3); \ + _argvec[4] = (unsigned long)(arg4); \ + _argvec[5] = (unsigned long)(arg5); \ + _argvec[6] = (unsigned long)(arg6); \ + _argvec[7] = (unsigned long)(arg7); \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "sub sp, sp, #4 \n\t" \ + "ldr r0, [%1, #20] \n\t" \ + "ldr r1, [%1, #24] \n\t" \ + "ldr r2, [%1, #28] \n\t" \ + "push {r0, r1, r2} \n\t" \ + "ldr r0, [%1, #4] \n\t" \ + "ldr r1, [%1, #8] \n\t" \ + "ldr r2, [%1, #12] \n\t" \ + "ldr r3, [%1, #16] \n\t" \ + "ldr r4, [%1] \n\t" /* target->r4 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \ + VALGRIND_RESTORE_STACK \ + "mov %0, r0" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "0" (&_argvec[0]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ + arg7,arg8) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[9]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + _argvec[3] = (unsigned long)(arg3); \ + _argvec[4] = (unsigned long)(arg4); \ + _argvec[5] = (unsigned long)(arg5); \ + _argvec[6] = (unsigned long)(arg6); \ + _argvec[7] = (unsigned long)(arg7); \ + _argvec[8] = (unsigned long)(arg8); \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "ldr r0, [%1, #20] \n\t" \ + "ldr r1, [%1, #24] \n\t" \ + "ldr r2, [%1, #28] \n\t" \ + "ldr r3, [%1, #32] \n\t" \ + "push {r0, r1, r2, r3} \n\t" \ + "ldr r0, [%1, #4] \n\t" \ + "ldr r1, [%1, #8] \n\t" \ + "ldr r2, [%1, #12] \n\t" \ + "ldr r3, [%1, #16] \n\t" \ + "ldr r4, [%1] \n\t" /* target->r4 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \ + VALGRIND_RESTORE_STACK \ + "mov %0, r0" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "0" (&_argvec[0]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ + arg7,arg8,arg9) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[10]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + _argvec[3] = (unsigned long)(arg3); \ + _argvec[4] = (unsigned long)(arg4); \ + _argvec[5] = (unsigned long)(arg5); \ + _argvec[6] = (unsigned long)(arg6); \ + _argvec[7] = (unsigned long)(arg7); \ + _argvec[8] = (unsigned long)(arg8); \ + _argvec[9] = (unsigned long)(arg9); \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "sub sp, sp, #4 \n\t" \ + "ldr r0, [%1, #20] \n\t" \ + "ldr r1, [%1, #24] \n\t" \ + "ldr r2, [%1, #28] \n\t" \ + "ldr r3, [%1, #32] \n\t" \ + "ldr r4, [%1, #36] \n\t" \ + "push {r0, r1, r2, r3, r4} \n\t" \ + "ldr r0, [%1, #4] \n\t" \ + "ldr r1, [%1, #8] \n\t" \ + "ldr r2, [%1, #12] \n\t" \ + "ldr r3, [%1, #16] \n\t" \ + "ldr r4, [%1] \n\t" /* target->r4 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \ + VALGRIND_RESTORE_STACK \ + "mov %0, r0" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "0" (&_argvec[0]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ + arg7,arg8,arg9,arg10) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[11]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + _argvec[3] = (unsigned long)(arg3); \ + _argvec[4] = (unsigned long)(arg4); \ + _argvec[5] = (unsigned long)(arg5); \ + _argvec[6] = (unsigned long)(arg6); \ + _argvec[7] = (unsigned long)(arg7); \ + _argvec[8] = (unsigned long)(arg8); \ + _argvec[9] = (unsigned long)(arg9); \ + _argvec[10] = (unsigned long)(arg10); \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "ldr r0, [%1, #40] \n\t" \ + "push {r0} \n\t" \ + "ldr r0, [%1, #20] \n\t" \ + "ldr r1, [%1, #24] \n\t" \ + "ldr r2, [%1, #28] \n\t" \ + "ldr r3, [%1, #32] \n\t" \ + "ldr r4, [%1, #36] \n\t" \ + "push {r0, r1, r2, r3, r4} \n\t" \ + "ldr r0, [%1, #4] \n\t" \ + "ldr r1, [%1, #8] \n\t" \ + "ldr r2, [%1, #12] \n\t" \ + "ldr r3, [%1, #16] \n\t" \ + "ldr r4, [%1] \n\t" /* target->r4 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \ + VALGRIND_RESTORE_STACK \ + "mov %0, r0" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "0" (&_argvec[0]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5, \ + arg6,arg7,arg8,arg9,arg10, \ + arg11) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[12]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + _argvec[3] = (unsigned long)(arg3); \ + _argvec[4] = (unsigned long)(arg4); \ + _argvec[5] = (unsigned long)(arg5); \ + _argvec[6] = (unsigned long)(arg6); \ + _argvec[7] = (unsigned long)(arg7); \ + _argvec[8] = (unsigned long)(arg8); \ + _argvec[9] = (unsigned long)(arg9); \ + _argvec[10] = (unsigned long)(arg10); \ + _argvec[11] = (unsigned long)(arg11); \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "sub sp, sp, #4 \n\t" \ + "ldr r0, [%1, #40] \n\t" \ + "ldr r1, [%1, #44] \n\t" \ + "push {r0, r1} \n\t" \ + "ldr r0, [%1, #20] \n\t" \ + "ldr r1, [%1, #24] \n\t" \ + "ldr r2, [%1, #28] \n\t" \ + "ldr r3, [%1, #32] \n\t" \ + "ldr r4, [%1, #36] \n\t" \ + "push {r0, r1, r2, r3, r4} \n\t" \ + "ldr r0, [%1, #4] \n\t" \ + "ldr r1, [%1, #8] \n\t" \ + "ldr r2, [%1, #12] \n\t" \ + "ldr r3, [%1, #16] \n\t" \ + "ldr r4, [%1] \n\t" /* target->r4 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \ + VALGRIND_RESTORE_STACK \ + "mov %0, r0" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "0" (&_argvec[0]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5, \ + arg6,arg7,arg8,arg9,arg10, \ + arg11,arg12) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[13]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + _argvec[3] = (unsigned long)(arg3); \ + _argvec[4] = (unsigned long)(arg4); \ + _argvec[5] = (unsigned long)(arg5); \ + _argvec[6] = (unsigned long)(arg6); \ + _argvec[7] = (unsigned long)(arg7); \ + _argvec[8] = (unsigned long)(arg8); \ + _argvec[9] = (unsigned long)(arg9); \ + _argvec[10] = (unsigned long)(arg10); \ + _argvec[11] = (unsigned long)(arg11); \ + _argvec[12] = (unsigned long)(arg12); \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "ldr r0, [%1, #40] \n\t" \ + "ldr r1, [%1, #44] \n\t" \ + "ldr r2, [%1, #48] \n\t" \ + "push {r0, r1, r2} \n\t" \ + "ldr r0, [%1, #20] \n\t" \ + "ldr r1, [%1, #24] \n\t" \ + "ldr r2, [%1, #28] \n\t" \ + "ldr r3, [%1, #32] \n\t" \ + "ldr r4, [%1, #36] \n\t" \ + "push {r0, r1, r2, r3, r4} \n\t" \ + "ldr r0, [%1, #4] \n\t" \ + "ldr r1, [%1, #8] \n\t" \ + "ldr r2, [%1, #12] \n\t" \ + "ldr r3, [%1, #16] \n\t" \ + "ldr r4, [%1] \n\t" /* target->r4 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \ + VALGRIND_RESTORE_STACK \ + "mov %0, r0" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "0" (&_argvec[0]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#endif /* PLAT_arm_linux */ + +/* ------------------------ arm64-linux ------------------------ */ + +#if defined(PLAT_arm64_linux) + +/* These regs are trashed by the hidden call. */ +#define __CALLER_SAVED_REGS \ + "x0", "x1", "x2", "x3","x4", "x5", "x6", "x7", "x8", "x9", \ + "x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17", \ + "x18", "x19", "x20", "x30", \ + "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8", "v9", \ + "v10", "v11", "v12", "v13", "v14", "v15", "v16", "v17", \ + "v18", "v19", "v20", "v21", "v22", "v23", "v24", "v25", \ + "v26", "v27", "v28", "v29", "v30", "v31" + +/* x21 is callee-saved, so we can use it to save and restore SP around + the hidden call. */ +#define VALGRIND_ALIGN_STACK \ + "mov x21, sp\n\t" \ + "bic sp, x21, #15\n\t" +#define VALGRIND_RESTORE_STACK \ + "mov sp, x21\n\t" + +/* These CALL_FN_ macros assume that on arm64-linux, + sizeof(unsigned long) == 8. */ + +#define CALL_FN_W_v(lval, orig) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[1]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "ldr x8, [%1] \n\t" /* target->x8 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8 \ + VALGRIND_RESTORE_STACK \ + "mov %0, x0\n" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "0" (&_argvec[0]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_W(lval, orig, arg1) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[2]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "ldr x0, [%1, #8] \n\t" \ + "ldr x8, [%1] \n\t" /* target->x8 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8 \ + VALGRIND_RESTORE_STACK \ + "mov %0, x0\n" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "0" (&_argvec[0]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_WW(lval, orig, arg1,arg2) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[3]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "ldr x0, [%1, #8] \n\t" \ + "ldr x1, [%1, #16] \n\t" \ + "ldr x8, [%1] \n\t" /* target->x8 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8 \ + VALGRIND_RESTORE_STACK \ + "mov %0, x0\n" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "0" (&_argvec[0]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[4]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + _argvec[3] = (unsigned long)(arg3); \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "ldr x0, [%1, #8] \n\t" \ + "ldr x1, [%1, #16] \n\t" \ + "ldr x2, [%1, #24] \n\t" \ + "ldr x8, [%1] \n\t" /* target->x8 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8 \ + VALGRIND_RESTORE_STACK \ + "mov %0, x0\n" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "0" (&_argvec[0]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[5]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + _argvec[3] = (unsigned long)(arg3); \ + _argvec[4] = (unsigned long)(arg4); \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "ldr x0, [%1, #8] \n\t" \ + "ldr x1, [%1, #16] \n\t" \ + "ldr x2, [%1, #24] \n\t" \ + "ldr x3, [%1, #32] \n\t" \ + "ldr x8, [%1] \n\t" /* target->x8 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8 \ + VALGRIND_RESTORE_STACK \ + "mov %0, x0" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "0" (&_argvec[0]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[6]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + _argvec[3] = (unsigned long)(arg3); \ + _argvec[4] = (unsigned long)(arg4); \ + _argvec[5] = (unsigned long)(arg5); \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "ldr x0, [%1, #8] \n\t" \ + "ldr x1, [%1, #16] \n\t" \ + "ldr x2, [%1, #24] \n\t" \ + "ldr x3, [%1, #32] \n\t" \ + "ldr x4, [%1, #40] \n\t" \ + "ldr x8, [%1] \n\t" /* target->x8 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8 \ + VALGRIND_RESTORE_STACK \ + "mov %0, x0" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "0" (&_argvec[0]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[7]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + _argvec[3] = (unsigned long)(arg3); \ + _argvec[4] = (unsigned long)(arg4); \ + _argvec[5] = (unsigned long)(arg5); \ + _argvec[6] = (unsigned long)(arg6); \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "ldr x0, [%1, #8] \n\t" \ + "ldr x1, [%1, #16] \n\t" \ + "ldr x2, [%1, #24] \n\t" \ + "ldr x3, [%1, #32] \n\t" \ + "ldr x4, [%1, #40] \n\t" \ + "ldr x5, [%1, #48] \n\t" \ + "ldr x8, [%1] \n\t" /* target->x8 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8 \ + VALGRIND_RESTORE_STACK \ + "mov %0, x0" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "0" (&_argvec[0]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ + arg7) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[8]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + _argvec[3] = (unsigned long)(arg3); \ + _argvec[4] = (unsigned long)(arg4); \ + _argvec[5] = (unsigned long)(arg5); \ + _argvec[6] = (unsigned long)(arg6); \ + _argvec[7] = (unsigned long)(arg7); \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "ldr x0, [%1, #8] \n\t" \ + "ldr x1, [%1, #16] \n\t" \ + "ldr x2, [%1, #24] \n\t" \ + "ldr x3, [%1, #32] \n\t" \ + "ldr x4, [%1, #40] \n\t" \ + "ldr x5, [%1, #48] \n\t" \ + "ldr x6, [%1, #56] \n\t" \ + "ldr x8, [%1] \n\t" /* target->x8 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8 \ + VALGRIND_RESTORE_STACK \ + "mov %0, x0" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "0" (&_argvec[0]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ + arg7,arg8) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[9]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + _argvec[3] = (unsigned long)(arg3); \ + _argvec[4] = (unsigned long)(arg4); \ + _argvec[5] = (unsigned long)(arg5); \ + _argvec[6] = (unsigned long)(arg6); \ + _argvec[7] = (unsigned long)(arg7); \ + _argvec[8] = (unsigned long)(arg8); \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "ldr x0, [%1, #8] \n\t" \ + "ldr x1, [%1, #16] \n\t" \ + "ldr x2, [%1, #24] \n\t" \ + "ldr x3, [%1, #32] \n\t" \ + "ldr x4, [%1, #40] \n\t" \ + "ldr x5, [%1, #48] \n\t" \ + "ldr x6, [%1, #56] \n\t" \ + "ldr x7, [%1, #64] \n\t" \ + "ldr x8, [%1] \n\t" /* target->x8 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8 \ + VALGRIND_RESTORE_STACK \ + "mov %0, x0" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "0" (&_argvec[0]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ + arg7,arg8,arg9) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[10]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + _argvec[3] = (unsigned long)(arg3); \ + _argvec[4] = (unsigned long)(arg4); \ + _argvec[5] = (unsigned long)(arg5); \ + _argvec[6] = (unsigned long)(arg6); \ + _argvec[7] = (unsigned long)(arg7); \ + _argvec[8] = (unsigned long)(arg8); \ + _argvec[9] = (unsigned long)(arg9); \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "sub sp, sp, #0x20 \n\t" \ + "ldr x0, [%1, #8] \n\t" \ + "ldr x1, [%1, #16] \n\t" \ + "ldr x2, [%1, #24] \n\t" \ + "ldr x3, [%1, #32] \n\t" \ + "ldr x4, [%1, #40] \n\t" \ + "ldr x5, [%1, #48] \n\t" \ + "ldr x6, [%1, #56] \n\t" \ + "ldr x7, [%1, #64] \n\t" \ + "ldr x8, [%1, #72] \n\t" \ + "str x8, [sp, #0] \n\t" \ + "ldr x8, [%1] \n\t" /* target->x8 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8 \ + VALGRIND_RESTORE_STACK \ + "mov %0, x0" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "0" (&_argvec[0]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ + arg7,arg8,arg9,arg10) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[11]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + _argvec[3] = (unsigned long)(arg3); \ + _argvec[4] = (unsigned long)(arg4); \ + _argvec[5] = (unsigned long)(arg5); \ + _argvec[6] = (unsigned long)(arg6); \ + _argvec[7] = (unsigned long)(arg7); \ + _argvec[8] = (unsigned long)(arg8); \ + _argvec[9] = (unsigned long)(arg9); \ + _argvec[10] = (unsigned long)(arg10); \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "sub sp, sp, #0x20 \n\t" \ + "ldr x0, [%1, #8] \n\t" \ + "ldr x1, [%1, #16] \n\t" \ + "ldr x2, [%1, #24] \n\t" \ + "ldr x3, [%1, #32] \n\t" \ + "ldr x4, [%1, #40] \n\t" \ + "ldr x5, [%1, #48] \n\t" \ + "ldr x6, [%1, #56] \n\t" \ + "ldr x7, [%1, #64] \n\t" \ + "ldr x8, [%1, #72] \n\t" \ + "str x8, [sp, #0] \n\t" \ + "ldr x8, [%1, #80] \n\t" \ + "str x8, [sp, #8] \n\t" \ + "ldr x8, [%1] \n\t" /* target->x8 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8 \ + VALGRIND_RESTORE_STACK \ + "mov %0, x0" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "0" (&_argvec[0]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ + arg7,arg8,arg9,arg10,arg11) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[12]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + _argvec[3] = (unsigned long)(arg3); \ + _argvec[4] = (unsigned long)(arg4); \ + _argvec[5] = (unsigned long)(arg5); \ + _argvec[6] = (unsigned long)(arg6); \ + _argvec[7] = (unsigned long)(arg7); \ + _argvec[8] = (unsigned long)(arg8); \ + _argvec[9] = (unsigned long)(arg9); \ + _argvec[10] = (unsigned long)(arg10); \ + _argvec[11] = (unsigned long)(arg11); \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "sub sp, sp, #0x30 \n\t" \ + "ldr x0, [%1, #8] \n\t" \ + "ldr x1, [%1, #16] \n\t" \ + "ldr x2, [%1, #24] \n\t" \ + "ldr x3, [%1, #32] \n\t" \ + "ldr x4, [%1, #40] \n\t" \ + "ldr x5, [%1, #48] \n\t" \ + "ldr x6, [%1, #56] \n\t" \ + "ldr x7, [%1, #64] \n\t" \ + "ldr x8, [%1, #72] \n\t" \ + "str x8, [sp, #0] \n\t" \ + "ldr x8, [%1, #80] \n\t" \ + "str x8, [sp, #8] \n\t" \ + "ldr x8, [%1, #88] \n\t" \ + "str x8, [sp, #16] \n\t" \ + "ldr x8, [%1] \n\t" /* target->x8 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8 \ + VALGRIND_RESTORE_STACK \ + "mov %0, x0" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "0" (&_argvec[0]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ + arg7,arg8,arg9,arg10,arg11, \ + arg12) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[13]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + _argvec[3] = (unsigned long)(arg3); \ + _argvec[4] = (unsigned long)(arg4); \ + _argvec[5] = (unsigned long)(arg5); \ + _argvec[6] = (unsigned long)(arg6); \ + _argvec[7] = (unsigned long)(arg7); \ + _argvec[8] = (unsigned long)(arg8); \ + _argvec[9] = (unsigned long)(arg9); \ + _argvec[10] = (unsigned long)(arg10); \ + _argvec[11] = (unsigned long)(arg11); \ + _argvec[12] = (unsigned long)(arg12); \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "sub sp, sp, #0x30 \n\t" \ + "ldr x0, [%1, #8] \n\t" \ + "ldr x1, [%1, #16] \n\t" \ + "ldr x2, [%1, #24] \n\t" \ + "ldr x3, [%1, #32] \n\t" \ + "ldr x4, [%1, #40] \n\t" \ + "ldr x5, [%1, #48] \n\t" \ + "ldr x6, [%1, #56] \n\t" \ + "ldr x7, [%1, #64] \n\t" \ + "ldr x8, [%1, #72] \n\t" \ + "str x8, [sp, #0] \n\t" \ + "ldr x8, [%1, #80] \n\t" \ + "str x8, [sp, #8] \n\t" \ + "ldr x8, [%1, #88] \n\t" \ + "str x8, [sp, #16] \n\t" \ + "ldr x8, [%1, #96] \n\t" \ + "str x8, [sp, #24] \n\t" \ + "ldr x8, [%1] \n\t" /* target->x8 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8 \ + VALGRIND_RESTORE_STACK \ + "mov %0, x0" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "0" (&_argvec[0]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#endif /* PLAT_arm64_linux */ + +/* ------------------------- s390x-linux ------------------------- */ + +#if defined(PLAT_s390x_linux) + +/* Similar workaround as amd64 (see above), but we use r11 as frame + pointer and save the old r11 in r7. r11 might be used for + argvec, therefore we copy argvec in r1 since r1 is clobbered + after the call anyway. */ +#if defined(__GNUC__) && defined(__GCC_HAVE_DWARF2_CFI_ASM) +# define __FRAME_POINTER \ + ,"d"(__builtin_dwarf_cfa()) +# define VALGRIND_CFI_PROLOGUE \ + ".cfi_remember_state\n\t" \ + "lgr 1,%1\n\t" /* copy the argvec pointer in r1 */ \ + "lgr 7,11\n\t" \ + "lgr 11,%2\n\t" \ + ".cfi_def_cfa r11, 0\n\t" +# define VALGRIND_CFI_EPILOGUE \ + "lgr 11, 7\n\t" \ + ".cfi_restore_state\n\t" +#else +# define __FRAME_POINTER +# define VALGRIND_CFI_PROLOGUE \ + "lgr 1,%1\n\t" +# define VALGRIND_CFI_EPILOGUE +#endif + +/* Nb: On s390 the stack pointer is properly aligned *at all times* + according to the s390 GCC maintainer. (The ABI specification is not + precise in this regard.) Therefore, VALGRIND_ALIGN_STACK and + VALGRIND_RESTORE_STACK are not defined here. */ + +/* These regs are trashed by the hidden call. Note that we overwrite + r14 in s390_irgen_noredir (VEX/priv/guest_s390_irgen.c) to give the + function a proper return address. All others are ABI defined call + clobbers. */ +#define __CALLER_SAVED_REGS "0","1","2","3","4","5","14", \ + "f0","f1","f2","f3","f4","f5","f6","f7" + +/* Nb: Although r11 is modified in the asm snippets below (inside + VALGRIND_CFI_PROLOGUE) it is not listed in the clobber section, for + two reasons: + (1) r11 is restored in VALGRIND_CFI_EPILOGUE, so effectively it is not + modified + (2) GCC will complain that r11 cannot appear inside a clobber section, + when compiled with -O -fno-omit-frame-pointer + */ + +#define CALL_FN_W_v(lval, orig) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[1]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + __asm__ volatile( \ + VALGRIND_CFI_PROLOGUE \ + "aghi 15,-160\n\t" \ + "lg 1, 0(1)\n\t" /* target->r1 */ \ + VALGRIND_CALL_NOREDIR_R1 \ + "lgr %0, 2\n\t" \ + "aghi 15,160\n\t" \ + VALGRIND_CFI_EPILOGUE \ + : /*out*/ "=d" (_res) \ + : /*in*/ "d" (&_argvec[0]) __FRAME_POINTER \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"7" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +/* The call abi has the arguments in r2-r6 and stack */ +#define CALL_FN_W_W(lval, orig, arg1) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[2]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)arg1; \ + __asm__ volatile( \ + VALGRIND_CFI_PROLOGUE \ + "aghi 15,-160\n\t" \ + "lg 2, 8(1)\n\t" \ + "lg 1, 0(1)\n\t" \ + VALGRIND_CALL_NOREDIR_R1 \ + "lgr %0, 2\n\t" \ + "aghi 15,160\n\t" \ + VALGRIND_CFI_EPILOGUE \ + : /*out*/ "=d" (_res) \ + : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"7" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_WW(lval, orig, arg1, arg2) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[3]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)arg1; \ + _argvec[2] = (unsigned long)arg2; \ + __asm__ volatile( \ + VALGRIND_CFI_PROLOGUE \ + "aghi 15,-160\n\t" \ + "lg 2, 8(1)\n\t" \ + "lg 3,16(1)\n\t" \ + "lg 1, 0(1)\n\t" \ + VALGRIND_CALL_NOREDIR_R1 \ + "lgr %0, 2\n\t" \ + "aghi 15,160\n\t" \ + VALGRIND_CFI_EPILOGUE \ + : /*out*/ "=d" (_res) \ + : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"7" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_WWW(lval, orig, arg1, arg2, arg3) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[4]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)arg1; \ + _argvec[2] = (unsigned long)arg2; \ + _argvec[3] = (unsigned long)arg3; \ + __asm__ volatile( \ + VALGRIND_CFI_PROLOGUE \ + "aghi 15,-160\n\t" \ + "lg 2, 8(1)\n\t" \ + "lg 3,16(1)\n\t" \ + "lg 4,24(1)\n\t" \ + "lg 1, 0(1)\n\t" \ + VALGRIND_CALL_NOREDIR_R1 \ + "lgr %0, 2\n\t" \ + "aghi 15,160\n\t" \ + VALGRIND_CFI_EPILOGUE \ + : /*out*/ "=d" (_res) \ + : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"7" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_WWWW(lval, orig, arg1, arg2, arg3, arg4) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[5]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)arg1; \ + _argvec[2] = (unsigned long)arg2; \ + _argvec[3] = (unsigned long)arg3; \ + _argvec[4] = (unsigned long)arg4; \ + __asm__ volatile( \ + VALGRIND_CFI_PROLOGUE \ + "aghi 15,-160\n\t" \ + "lg 2, 8(1)\n\t" \ + "lg 3,16(1)\n\t" \ + "lg 4,24(1)\n\t" \ + "lg 5,32(1)\n\t" \ + "lg 1, 0(1)\n\t" \ + VALGRIND_CALL_NOREDIR_R1 \ + "lgr %0, 2\n\t" \ + "aghi 15,160\n\t" \ + VALGRIND_CFI_EPILOGUE \ + : /*out*/ "=d" (_res) \ + : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"7" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_5W(lval, orig, arg1, arg2, arg3, arg4, arg5) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[6]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)arg1; \ + _argvec[2] = (unsigned long)arg2; \ + _argvec[3] = (unsigned long)arg3; \ + _argvec[4] = (unsigned long)arg4; \ + _argvec[5] = (unsigned long)arg5; \ + __asm__ volatile( \ + VALGRIND_CFI_PROLOGUE \ + "aghi 15,-160\n\t" \ + "lg 2, 8(1)\n\t" \ + "lg 3,16(1)\n\t" \ + "lg 4,24(1)\n\t" \ + "lg 5,32(1)\n\t" \ + "lg 6,40(1)\n\t" \ + "lg 1, 0(1)\n\t" \ + VALGRIND_CALL_NOREDIR_R1 \ + "lgr %0, 2\n\t" \ + "aghi 15,160\n\t" \ + VALGRIND_CFI_EPILOGUE \ + : /*out*/ "=d" (_res) \ + : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_6W(lval, orig, arg1, arg2, arg3, arg4, arg5, \ + arg6) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[7]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)arg1; \ + _argvec[2] = (unsigned long)arg2; \ + _argvec[3] = (unsigned long)arg3; \ + _argvec[4] = (unsigned long)arg4; \ + _argvec[5] = (unsigned long)arg5; \ + _argvec[6] = (unsigned long)arg6; \ + __asm__ volatile( \ + VALGRIND_CFI_PROLOGUE \ + "aghi 15,-168\n\t" \ + "lg 2, 8(1)\n\t" \ + "lg 3,16(1)\n\t" \ + "lg 4,24(1)\n\t" \ + "lg 5,32(1)\n\t" \ + "lg 6,40(1)\n\t" \ + "mvc 160(8,15), 48(1)\n\t" \ + "lg 1, 0(1)\n\t" \ + VALGRIND_CALL_NOREDIR_R1 \ + "lgr %0, 2\n\t" \ + "aghi 15,168\n\t" \ + VALGRIND_CFI_EPILOGUE \ + : /*out*/ "=d" (_res) \ + : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_7W(lval, orig, arg1, arg2, arg3, arg4, arg5, \ + arg6, arg7) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[8]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)arg1; \ + _argvec[2] = (unsigned long)arg2; \ + _argvec[3] = (unsigned long)arg3; \ + _argvec[4] = (unsigned long)arg4; \ + _argvec[5] = (unsigned long)arg5; \ + _argvec[6] = (unsigned long)arg6; \ + _argvec[7] = (unsigned long)arg7; \ + __asm__ volatile( \ + VALGRIND_CFI_PROLOGUE \ + "aghi 15,-176\n\t" \ + "lg 2, 8(1)\n\t" \ + "lg 3,16(1)\n\t" \ + "lg 4,24(1)\n\t" \ + "lg 5,32(1)\n\t" \ + "lg 6,40(1)\n\t" \ + "mvc 160(8,15), 48(1)\n\t" \ + "mvc 168(8,15), 56(1)\n\t" \ + "lg 1, 0(1)\n\t" \ + VALGRIND_CALL_NOREDIR_R1 \ + "lgr %0, 2\n\t" \ + "aghi 15,176\n\t" \ + VALGRIND_CFI_EPILOGUE \ + : /*out*/ "=d" (_res) \ + : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_8W(lval, orig, arg1, arg2, arg3, arg4, arg5, \ + arg6, arg7 ,arg8) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[9]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)arg1; \ + _argvec[2] = (unsigned long)arg2; \ + _argvec[3] = (unsigned long)arg3; \ + _argvec[4] = (unsigned long)arg4; \ + _argvec[5] = (unsigned long)arg5; \ + _argvec[6] = (unsigned long)arg6; \ + _argvec[7] = (unsigned long)arg7; \ + _argvec[8] = (unsigned long)arg8; \ + __asm__ volatile( \ + VALGRIND_CFI_PROLOGUE \ + "aghi 15,-184\n\t" \ + "lg 2, 8(1)\n\t" \ + "lg 3,16(1)\n\t" \ + "lg 4,24(1)\n\t" \ + "lg 5,32(1)\n\t" \ + "lg 6,40(1)\n\t" \ + "mvc 160(8,15), 48(1)\n\t" \ + "mvc 168(8,15), 56(1)\n\t" \ + "mvc 176(8,15), 64(1)\n\t" \ + "lg 1, 0(1)\n\t" \ + VALGRIND_CALL_NOREDIR_R1 \ + "lgr %0, 2\n\t" \ + "aghi 15,184\n\t" \ + VALGRIND_CFI_EPILOGUE \ + : /*out*/ "=d" (_res) \ + : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_9W(lval, orig, arg1, arg2, arg3, arg4, arg5, \ + arg6, arg7 ,arg8, arg9) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[10]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)arg1; \ + _argvec[2] = (unsigned long)arg2; \ + _argvec[3] = (unsigned long)arg3; \ + _argvec[4] = (unsigned long)arg4; \ + _argvec[5] = (unsigned long)arg5; \ + _argvec[6] = (unsigned long)arg6; \ + _argvec[7] = (unsigned long)arg7; \ + _argvec[8] = (unsigned long)arg8; \ + _argvec[9] = (unsigned long)arg9; \ + __asm__ volatile( \ + VALGRIND_CFI_PROLOGUE \ + "aghi 15,-192\n\t" \ + "lg 2, 8(1)\n\t" \ + "lg 3,16(1)\n\t" \ + "lg 4,24(1)\n\t" \ + "lg 5,32(1)\n\t" \ + "lg 6,40(1)\n\t" \ + "mvc 160(8,15), 48(1)\n\t" \ + "mvc 168(8,15), 56(1)\n\t" \ + "mvc 176(8,15), 64(1)\n\t" \ + "mvc 184(8,15), 72(1)\n\t" \ + "lg 1, 0(1)\n\t" \ + VALGRIND_CALL_NOREDIR_R1 \ + "lgr %0, 2\n\t" \ + "aghi 15,192\n\t" \ + VALGRIND_CFI_EPILOGUE \ + : /*out*/ "=d" (_res) \ + : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_10W(lval, orig, arg1, arg2, arg3, arg4, arg5, \ + arg6, arg7 ,arg8, arg9, arg10) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[11]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)arg1; \ + _argvec[2] = (unsigned long)arg2; \ + _argvec[3] = (unsigned long)arg3; \ + _argvec[4] = (unsigned long)arg4; \ + _argvec[5] = (unsigned long)arg5; \ + _argvec[6] = (unsigned long)arg6; \ + _argvec[7] = (unsigned long)arg7; \ + _argvec[8] = (unsigned long)arg8; \ + _argvec[9] = (unsigned long)arg9; \ + _argvec[10] = (unsigned long)arg10; \ + __asm__ volatile( \ + VALGRIND_CFI_PROLOGUE \ + "aghi 15,-200\n\t" \ + "lg 2, 8(1)\n\t" \ + "lg 3,16(1)\n\t" \ + "lg 4,24(1)\n\t" \ + "lg 5,32(1)\n\t" \ + "lg 6,40(1)\n\t" \ + "mvc 160(8,15), 48(1)\n\t" \ + "mvc 168(8,15), 56(1)\n\t" \ + "mvc 176(8,15), 64(1)\n\t" \ + "mvc 184(8,15), 72(1)\n\t" \ + "mvc 192(8,15), 80(1)\n\t" \ + "lg 1, 0(1)\n\t" \ + VALGRIND_CALL_NOREDIR_R1 \ + "lgr %0, 2\n\t" \ + "aghi 15,200\n\t" \ + VALGRIND_CFI_EPILOGUE \ + : /*out*/ "=d" (_res) \ + : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_11W(lval, orig, arg1, arg2, arg3, arg4, arg5, \ + arg6, arg7 ,arg8, arg9, arg10, arg11) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[12]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)arg1; \ + _argvec[2] = (unsigned long)arg2; \ + _argvec[3] = (unsigned long)arg3; \ + _argvec[4] = (unsigned long)arg4; \ + _argvec[5] = (unsigned long)arg5; \ + _argvec[6] = (unsigned long)arg6; \ + _argvec[7] = (unsigned long)arg7; \ + _argvec[8] = (unsigned long)arg8; \ + _argvec[9] = (unsigned long)arg9; \ + _argvec[10] = (unsigned long)arg10; \ + _argvec[11] = (unsigned long)arg11; \ + __asm__ volatile( \ + VALGRIND_CFI_PROLOGUE \ + "aghi 15,-208\n\t" \ + "lg 2, 8(1)\n\t" \ + "lg 3,16(1)\n\t" \ + "lg 4,24(1)\n\t" \ + "lg 5,32(1)\n\t" \ + "lg 6,40(1)\n\t" \ + "mvc 160(8,15), 48(1)\n\t" \ + "mvc 168(8,15), 56(1)\n\t" \ + "mvc 176(8,15), 64(1)\n\t" \ + "mvc 184(8,15), 72(1)\n\t" \ + "mvc 192(8,15), 80(1)\n\t" \ + "mvc 200(8,15), 88(1)\n\t" \ + "lg 1, 0(1)\n\t" \ + VALGRIND_CALL_NOREDIR_R1 \ + "lgr %0, 2\n\t" \ + "aghi 15,208\n\t" \ + VALGRIND_CFI_EPILOGUE \ + : /*out*/ "=d" (_res) \ + : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_12W(lval, orig, arg1, arg2, arg3, arg4, arg5, \ + arg6, arg7 ,arg8, arg9, arg10, arg11, arg12)\ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[13]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)arg1; \ + _argvec[2] = (unsigned long)arg2; \ + _argvec[3] = (unsigned long)arg3; \ + _argvec[4] = (unsigned long)arg4; \ + _argvec[5] = (unsigned long)arg5; \ + _argvec[6] = (unsigned long)arg6; \ + _argvec[7] = (unsigned long)arg7; \ + _argvec[8] = (unsigned long)arg8; \ + _argvec[9] = (unsigned long)arg9; \ + _argvec[10] = (unsigned long)arg10; \ + _argvec[11] = (unsigned long)arg11; \ + _argvec[12] = (unsigned long)arg12; \ + __asm__ volatile( \ + VALGRIND_CFI_PROLOGUE \ + "aghi 15,-216\n\t" \ + "lg 2, 8(1)\n\t" \ + "lg 3,16(1)\n\t" \ + "lg 4,24(1)\n\t" \ + "lg 5,32(1)\n\t" \ + "lg 6,40(1)\n\t" \ + "mvc 160(8,15), 48(1)\n\t" \ + "mvc 168(8,15), 56(1)\n\t" \ + "mvc 176(8,15), 64(1)\n\t" \ + "mvc 184(8,15), 72(1)\n\t" \ + "mvc 192(8,15), 80(1)\n\t" \ + "mvc 200(8,15), 88(1)\n\t" \ + "mvc 208(8,15), 96(1)\n\t" \ + "lg 1, 0(1)\n\t" \ + VALGRIND_CALL_NOREDIR_R1 \ + "lgr %0, 2\n\t" \ + "aghi 15,216\n\t" \ + VALGRIND_CFI_EPILOGUE \ + : /*out*/ "=d" (_res) \ + : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + + +#endif /* PLAT_s390x_linux */ + +/* ------------------------- mips32-linux ----------------------- */ + +#if defined(PLAT_mips32_linux) + +/* These regs are trashed by the hidden call. */ +#define __CALLER_SAVED_REGS "$2", "$3", "$4", "$5", "$6", \ +"$7", "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15", "$24", \ +"$25", "$31" + +/* These CALL_FN_ macros assume that on mips-linux, sizeof(unsigned + long) == 4. */ + +#define CALL_FN_W_v(lval, orig) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[1]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + __asm__ volatile( \ + "subu $29, $29, 8 \n\t" \ + "sw $28, 0($29) \n\t" \ + "sw $31, 4($29) \n\t" \ + "subu $29, $29, 16 \n\t" \ + "lw $25, 0(%1) \n\t" /* target->t9 */ \ + VALGRIND_CALL_NOREDIR_T9 \ + "addu $29, $29, 16\n\t" \ + "lw $28, 0($29) \n\t" \ + "lw $31, 4($29) \n\t" \ + "addu $29, $29, 8 \n\t" \ + "move %0, $2\n" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "0" (&_argvec[0]) \ + : /*trash*/ "memory", __CALLER_SAVED_REGS \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_W(lval, orig, arg1) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[2]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + __asm__ volatile( \ + "subu $29, $29, 8 \n\t" \ + "sw $28, 0($29) \n\t" \ + "sw $31, 4($29) \n\t" \ + "subu $29, $29, 16 \n\t" \ + "lw $4, 4(%1) \n\t" /* arg1*/ \ + "lw $25, 0(%1) \n\t" /* target->t9 */ \ + VALGRIND_CALL_NOREDIR_T9 \ + "addu $29, $29, 16 \n\t" \ + "lw $28, 0($29) \n\t" \ + "lw $31, 4($29) \n\t" \ + "addu $29, $29, 8 \n\t" \ + "move %0, $2\n" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "0" (&_argvec[0]) \ + : /*trash*/ "memory", __CALLER_SAVED_REGS \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_WW(lval, orig, arg1,arg2) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[3]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + __asm__ volatile( \ + "subu $29, $29, 8 \n\t" \ + "sw $28, 0($29) \n\t" \ + "sw $31, 4($29) \n\t" \ + "subu $29, $29, 16 \n\t" \ + "lw $4, 4(%1) \n\t" \ + "lw $5, 8(%1) \n\t" \ + "lw $25, 0(%1) \n\t" /* target->t9 */ \ + VALGRIND_CALL_NOREDIR_T9 \ + "addu $29, $29, 16 \n\t" \ + "lw $28, 0($29) \n\t" \ + "lw $31, 4($29) \n\t" \ + "addu $29, $29, 8 \n\t" \ + "move %0, $2\n" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "0" (&_argvec[0]) \ + : /*trash*/ "memory", __CALLER_SAVED_REGS \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[4]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + _argvec[3] = (unsigned long)(arg3); \ + __asm__ volatile( \ + "subu $29, $29, 8 \n\t" \ + "sw $28, 0($29) \n\t" \ + "sw $31, 4($29) \n\t" \ + "subu $29, $29, 16 \n\t" \ + "lw $4, 4(%1) \n\t" \ + "lw $5, 8(%1) \n\t" \ + "lw $6, 12(%1) \n\t" \ + "lw $25, 0(%1) \n\t" /* target->t9 */ \ + VALGRIND_CALL_NOREDIR_T9 \ + "addu $29, $29, 16 \n\t" \ + "lw $28, 0($29) \n\t" \ + "lw $31, 4($29) \n\t" \ + "addu $29, $29, 8 \n\t" \ + "move %0, $2\n" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "0" (&_argvec[0]) \ + : /*trash*/ "memory", __CALLER_SAVED_REGS \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[5]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + _argvec[3] = (unsigned long)(arg3); \ + _argvec[4] = (unsigned long)(arg4); \ + __asm__ volatile( \ + "subu $29, $29, 8 \n\t" \ + "sw $28, 0($29) \n\t" \ + "sw $31, 4($29) \n\t" \ + "subu $29, $29, 16 \n\t" \ + "lw $4, 4(%1) \n\t" \ + "lw $5, 8(%1) \n\t" \ + "lw $6, 12(%1) \n\t" \ + "lw $7, 16(%1) \n\t" \ + "lw $25, 0(%1) \n\t" /* target->t9 */ \ + VALGRIND_CALL_NOREDIR_T9 \ + "addu $29, $29, 16 \n\t" \ + "lw $28, 0($29) \n\t" \ + "lw $31, 4($29) \n\t" \ + "addu $29, $29, 8 \n\t" \ + "move %0, $2\n" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "0" (&_argvec[0]) \ + : /*trash*/ "memory", __CALLER_SAVED_REGS \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[6]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + _argvec[3] = (unsigned long)(arg3); \ + _argvec[4] = (unsigned long)(arg4); \ + _argvec[5] = (unsigned long)(arg5); \ + __asm__ volatile( \ + "subu $29, $29, 8 \n\t" \ + "sw $28, 0($29) \n\t" \ + "sw $31, 4($29) \n\t" \ + "lw $4, 20(%1) \n\t" \ + "subu $29, $29, 24\n\t" \ + "sw $4, 16($29) \n\t" \ + "lw $4, 4(%1) \n\t" \ + "lw $5, 8(%1) \n\t" \ + "lw $6, 12(%1) \n\t" \ + "lw $7, 16(%1) \n\t" \ + "lw $25, 0(%1) \n\t" /* target->t9 */ \ + VALGRIND_CALL_NOREDIR_T9 \ + "addu $29, $29, 24 \n\t" \ + "lw $28, 0($29) \n\t" \ + "lw $31, 4($29) \n\t" \ + "addu $29, $29, 8 \n\t" \ + "move %0, $2\n" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "0" (&_argvec[0]) \ + : /*trash*/ "memory", __CALLER_SAVED_REGS \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) +#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[7]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + _argvec[3] = (unsigned long)(arg3); \ + _argvec[4] = (unsigned long)(arg4); \ + _argvec[5] = (unsigned long)(arg5); \ + _argvec[6] = (unsigned long)(arg6); \ + __asm__ volatile( \ + "subu $29, $29, 8 \n\t" \ + "sw $28, 0($29) \n\t" \ + "sw $31, 4($29) \n\t" \ + "lw $4, 20(%1) \n\t" \ + "subu $29, $29, 32\n\t" \ + "sw $4, 16($29) \n\t" \ + "lw $4, 24(%1) \n\t" \ + "nop\n\t" \ + "sw $4, 20($29) \n\t" \ + "lw $4, 4(%1) \n\t" \ + "lw $5, 8(%1) \n\t" \ + "lw $6, 12(%1) \n\t" \ + "lw $7, 16(%1) \n\t" \ + "lw $25, 0(%1) \n\t" /* target->t9 */ \ + VALGRIND_CALL_NOREDIR_T9 \ + "addu $29, $29, 32 \n\t" \ + "lw $28, 0($29) \n\t" \ + "lw $31, 4($29) \n\t" \ + "addu $29, $29, 8 \n\t" \ + "move %0, $2\n" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "0" (&_argvec[0]) \ + : /*trash*/ "memory", __CALLER_SAVED_REGS \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ + arg7) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[8]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + _argvec[3] = (unsigned long)(arg3); \ + _argvec[4] = (unsigned long)(arg4); \ + _argvec[5] = (unsigned long)(arg5); \ + _argvec[6] = (unsigned long)(arg6); \ + _argvec[7] = (unsigned long)(arg7); \ + __asm__ volatile( \ + "subu $29, $29, 8 \n\t" \ + "sw $28, 0($29) \n\t" \ + "sw $31, 4($29) \n\t" \ + "lw $4, 20(%1) \n\t" \ + "subu $29, $29, 32\n\t" \ + "sw $4, 16($29) \n\t" \ + "lw $4, 24(%1) \n\t" \ + "sw $4, 20($29) \n\t" \ + "lw $4, 28(%1) \n\t" \ + "sw $4, 24($29) \n\t" \ + "lw $4, 4(%1) \n\t" \ + "lw $5, 8(%1) \n\t" \ + "lw $6, 12(%1) \n\t" \ + "lw $7, 16(%1) \n\t" \ + "lw $25, 0(%1) \n\t" /* target->t9 */ \ + VALGRIND_CALL_NOREDIR_T9 \ + "addu $29, $29, 32 \n\t" \ + "lw $28, 0($29) \n\t" \ + "lw $31, 4($29) \n\t" \ + "addu $29, $29, 8 \n\t" \ + "move %0, $2\n" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "0" (&_argvec[0]) \ + : /*trash*/ "memory", __CALLER_SAVED_REGS \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ + arg7,arg8) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[9]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + _argvec[3] = (unsigned long)(arg3); \ + _argvec[4] = (unsigned long)(arg4); \ + _argvec[5] = (unsigned long)(arg5); \ + _argvec[6] = (unsigned long)(arg6); \ + _argvec[7] = (unsigned long)(arg7); \ + _argvec[8] = (unsigned long)(arg8); \ + __asm__ volatile( \ + "subu $29, $29, 8 \n\t" \ + "sw $28, 0($29) \n\t" \ + "sw $31, 4($29) \n\t" \ + "lw $4, 20(%1) \n\t" \ + "subu $29, $29, 40\n\t" \ + "sw $4, 16($29) \n\t" \ + "lw $4, 24(%1) \n\t" \ + "sw $4, 20($29) \n\t" \ + "lw $4, 28(%1) \n\t" \ + "sw $4, 24($29) \n\t" \ + "lw $4, 32(%1) \n\t" \ + "sw $4, 28($29) \n\t" \ + "lw $4, 4(%1) \n\t" \ + "lw $5, 8(%1) \n\t" \ + "lw $6, 12(%1) \n\t" \ + "lw $7, 16(%1) \n\t" \ + "lw $25, 0(%1) \n\t" /* target->t9 */ \ + VALGRIND_CALL_NOREDIR_T9 \ + "addu $29, $29, 40 \n\t" \ + "lw $28, 0($29) \n\t" \ + "lw $31, 4($29) \n\t" \ + "addu $29, $29, 8 \n\t" \ + "move %0, $2\n" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "0" (&_argvec[0]) \ + : /*trash*/ "memory", __CALLER_SAVED_REGS \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ + arg7,arg8,arg9) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[10]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + _argvec[3] = (unsigned long)(arg3); \ + _argvec[4] = (unsigned long)(arg4); \ + _argvec[5] = (unsigned long)(arg5); \ + _argvec[6] = (unsigned long)(arg6); \ + _argvec[7] = (unsigned long)(arg7); \ + _argvec[8] = (unsigned long)(arg8); \ + _argvec[9] = (unsigned long)(arg9); \ + __asm__ volatile( \ + "subu $29, $29, 8 \n\t" \ + "sw $28, 0($29) \n\t" \ + "sw $31, 4($29) \n\t" \ + "lw $4, 20(%1) \n\t" \ + "subu $29, $29, 40\n\t" \ + "sw $4, 16($29) \n\t" \ + "lw $4, 24(%1) \n\t" \ + "sw $4, 20($29) \n\t" \ + "lw $4, 28(%1) \n\t" \ + "sw $4, 24($29) \n\t" \ + "lw $4, 32(%1) \n\t" \ + "sw $4, 28($29) \n\t" \ + "lw $4, 36(%1) \n\t" \ + "sw $4, 32($29) \n\t" \ + "lw $4, 4(%1) \n\t" \ + "lw $5, 8(%1) \n\t" \ + "lw $6, 12(%1) \n\t" \ + "lw $7, 16(%1) \n\t" \ + "lw $25, 0(%1) \n\t" /* target->t9 */ \ + VALGRIND_CALL_NOREDIR_T9 \ + "addu $29, $29, 40 \n\t" \ + "lw $28, 0($29) \n\t" \ + "lw $31, 4($29) \n\t" \ + "addu $29, $29, 8 \n\t" \ + "move %0, $2\n" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "0" (&_argvec[0]) \ + : /*trash*/ "memory", __CALLER_SAVED_REGS \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ + arg7,arg8,arg9,arg10) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[11]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + _argvec[3] = (unsigned long)(arg3); \ + _argvec[4] = (unsigned long)(arg4); \ + _argvec[5] = (unsigned long)(arg5); \ + _argvec[6] = (unsigned long)(arg6); \ + _argvec[7] = (unsigned long)(arg7); \ + _argvec[8] = (unsigned long)(arg8); \ + _argvec[9] = (unsigned long)(arg9); \ + _argvec[10] = (unsigned long)(arg10); \ + __asm__ volatile( \ + "subu $29, $29, 8 \n\t" \ + "sw $28, 0($29) \n\t" \ + "sw $31, 4($29) \n\t" \ + "lw $4, 20(%1) \n\t" \ + "subu $29, $29, 48\n\t" \ + "sw $4, 16($29) \n\t" \ + "lw $4, 24(%1) \n\t" \ + "sw $4, 20($29) \n\t" \ + "lw $4, 28(%1) \n\t" \ + "sw $4, 24($29) \n\t" \ + "lw $4, 32(%1) \n\t" \ + "sw $4, 28($29) \n\t" \ + "lw $4, 36(%1) \n\t" \ + "sw $4, 32($29) \n\t" \ + "lw $4, 40(%1) \n\t" \ + "sw $4, 36($29) \n\t" \ + "lw $4, 4(%1) \n\t" \ + "lw $5, 8(%1) \n\t" \ + "lw $6, 12(%1) \n\t" \ + "lw $7, 16(%1) \n\t" \ + "lw $25, 0(%1) \n\t" /* target->t9 */ \ + VALGRIND_CALL_NOREDIR_T9 \ + "addu $29, $29, 48 \n\t" \ + "lw $28, 0($29) \n\t" \ + "lw $31, 4($29) \n\t" \ + "addu $29, $29, 8 \n\t" \ + "move %0, $2\n" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "0" (&_argvec[0]) \ + : /*trash*/ "memory", __CALLER_SAVED_REGS \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5, \ + arg6,arg7,arg8,arg9,arg10, \ + arg11) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[12]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + _argvec[3] = (unsigned long)(arg3); \ + _argvec[4] = (unsigned long)(arg4); \ + _argvec[5] = (unsigned long)(arg5); \ + _argvec[6] = (unsigned long)(arg6); \ + _argvec[7] = (unsigned long)(arg7); \ + _argvec[8] = (unsigned long)(arg8); \ + _argvec[9] = (unsigned long)(arg9); \ + _argvec[10] = (unsigned long)(arg10); \ + _argvec[11] = (unsigned long)(arg11); \ + __asm__ volatile( \ + "subu $29, $29, 8 \n\t" \ + "sw $28, 0($29) \n\t" \ + "sw $31, 4($29) \n\t" \ + "lw $4, 20(%1) \n\t" \ + "subu $29, $29, 48\n\t" \ + "sw $4, 16($29) \n\t" \ + "lw $4, 24(%1) \n\t" \ + "sw $4, 20($29) \n\t" \ + "lw $4, 28(%1) \n\t" \ + "sw $4, 24($29) \n\t" \ + "lw $4, 32(%1) \n\t" \ + "sw $4, 28($29) \n\t" \ + "lw $4, 36(%1) \n\t" \ + "sw $4, 32($29) \n\t" \ + "lw $4, 40(%1) \n\t" \ + "sw $4, 36($29) \n\t" \ + "lw $4, 44(%1) \n\t" \ + "sw $4, 40($29) \n\t" \ + "lw $4, 4(%1) \n\t" \ + "lw $5, 8(%1) \n\t" \ + "lw $6, 12(%1) \n\t" \ + "lw $7, 16(%1) \n\t" \ + "lw $25, 0(%1) \n\t" /* target->t9 */ \ + VALGRIND_CALL_NOREDIR_T9 \ + "addu $29, $29, 48 \n\t" \ + "lw $28, 0($29) \n\t" \ + "lw $31, 4($29) \n\t" \ + "addu $29, $29, 8 \n\t" \ + "move %0, $2\n" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "0" (&_argvec[0]) \ + : /*trash*/ "memory", __CALLER_SAVED_REGS \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5, \ + arg6,arg7,arg8,arg9,arg10, \ + arg11,arg12) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[13]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + _argvec[3] = (unsigned long)(arg3); \ + _argvec[4] = (unsigned long)(arg4); \ + _argvec[5] = (unsigned long)(arg5); \ + _argvec[6] = (unsigned long)(arg6); \ + _argvec[7] = (unsigned long)(arg7); \ + _argvec[8] = (unsigned long)(arg8); \ + _argvec[9] = (unsigned long)(arg9); \ + _argvec[10] = (unsigned long)(arg10); \ + _argvec[11] = (unsigned long)(arg11); \ + _argvec[12] = (unsigned long)(arg12); \ + __asm__ volatile( \ + "subu $29, $29, 8 \n\t" \ + "sw $28, 0($29) \n\t" \ + "sw $31, 4($29) \n\t" \ + "lw $4, 20(%1) \n\t" \ + "subu $29, $29, 56\n\t" \ + "sw $4, 16($29) \n\t" \ + "lw $4, 24(%1) \n\t" \ + "sw $4, 20($29) \n\t" \ + "lw $4, 28(%1) \n\t" \ + "sw $4, 24($29) \n\t" \ + "lw $4, 32(%1) \n\t" \ + "sw $4, 28($29) \n\t" \ + "lw $4, 36(%1) \n\t" \ + "sw $4, 32($29) \n\t" \ + "lw $4, 40(%1) \n\t" \ + "sw $4, 36($29) \n\t" \ + "lw $4, 44(%1) \n\t" \ + "sw $4, 40($29) \n\t" \ + "lw $4, 48(%1) \n\t" \ + "sw $4, 44($29) \n\t" \ + "lw $4, 4(%1) \n\t" \ + "lw $5, 8(%1) \n\t" \ + "lw $6, 12(%1) \n\t" \ + "lw $7, 16(%1) \n\t" \ + "lw $25, 0(%1) \n\t" /* target->t9 */ \ + VALGRIND_CALL_NOREDIR_T9 \ + "addu $29, $29, 56 \n\t" \ + "lw $28, 0($29) \n\t" \ + "lw $31, 4($29) \n\t" \ + "addu $29, $29, 8 \n\t" \ + "move %0, $2\n" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[0]) \ + : /*trash*/ "memory", __CALLER_SAVED_REGS \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#endif /* PLAT_mips32_linux */ + +/* ------------------------- mips64-linux ------------------------- */ + +#if defined(PLAT_mips64_linux) + +/* These regs are trashed by the hidden call. */ +#define __CALLER_SAVED_REGS "$2", "$3", "$4", "$5", "$6", \ +"$7", "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15", "$24", \ +"$25", "$31" + +/* These CALL_FN_ macros assume that on mips-linux, sizeof(unsigned + long) == 4. */ + +#define CALL_FN_W_v(lval, orig) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[1]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + __asm__ volatile( \ + "ld $25, 0(%1)\n\t" /* target->t9 */ \ + VALGRIND_CALL_NOREDIR_T9 \ + "move %0, $2\n" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "0" (&_argvec[0]) \ + : /*trash*/ "memory", __CALLER_SAVED_REGS \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_W(lval, orig, arg1) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[2]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + __asm__ volatile( \ + "ld $4, 8(%1)\n\t" /* arg1*/ \ + "ld $25, 0(%1)\n\t" /* target->t9 */ \ + VALGRIND_CALL_NOREDIR_T9 \ + "move %0, $2\n" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[0]) \ + : /*trash*/ "memory", __CALLER_SAVED_REGS \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_WW(lval, orig, arg1,arg2) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[3]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + __asm__ volatile( \ + "ld $4, 8(%1)\n\t" \ + "ld $5, 16(%1)\n\t" \ + "ld $25, 0(%1)\n\t" /* target->t9 */ \ + VALGRIND_CALL_NOREDIR_T9 \ + "move %0, $2\n" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[0]) \ + : /*trash*/ "memory", __CALLER_SAVED_REGS \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[4]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + _argvec[3] = (unsigned long)(arg3); \ + __asm__ volatile( \ + "ld $4, 8(%1)\n\t" \ + "ld $5, 16(%1)\n\t" \ + "ld $6, 24(%1)\n\t" \ + "ld $25, 0(%1)\n\t" /* target->t9 */ \ + VALGRIND_CALL_NOREDIR_T9 \ + "move %0, $2\n" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[0]) \ + : /*trash*/ "memory", __CALLER_SAVED_REGS \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[5]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + _argvec[3] = (unsigned long)(arg3); \ + _argvec[4] = (unsigned long)(arg4); \ + __asm__ volatile( \ + "ld $4, 8(%1)\n\t" \ + "ld $5, 16(%1)\n\t" \ + "ld $6, 24(%1)\n\t" \ + "ld $7, 32(%1)\n\t" \ + "ld $25, 0(%1)\n\t" /* target->t9 */ \ + VALGRIND_CALL_NOREDIR_T9 \ + "move %0, $2\n" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[0]) \ + : /*trash*/ "memory", __CALLER_SAVED_REGS \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[6]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + _argvec[3] = (unsigned long)(arg3); \ + _argvec[4] = (unsigned long)(arg4); \ + _argvec[5] = (unsigned long)(arg5); \ + __asm__ volatile( \ + "ld $4, 8(%1)\n\t" \ + "ld $5, 16(%1)\n\t" \ + "ld $6, 24(%1)\n\t" \ + "ld $7, 32(%1)\n\t" \ + "ld $8, 40(%1)\n\t" \ + "ld $25, 0(%1)\n\t" /* target->t9 */ \ + VALGRIND_CALL_NOREDIR_T9 \ + "move %0, $2\n" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[0]) \ + : /*trash*/ "memory", __CALLER_SAVED_REGS \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[7]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + _argvec[3] = (unsigned long)(arg3); \ + _argvec[4] = (unsigned long)(arg4); \ + _argvec[5] = (unsigned long)(arg5); \ + _argvec[6] = (unsigned long)(arg6); \ + __asm__ volatile( \ + "ld $4, 8(%1)\n\t" \ + "ld $5, 16(%1)\n\t" \ + "ld $6, 24(%1)\n\t" \ + "ld $7, 32(%1)\n\t" \ + "ld $8, 40(%1)\n\t" \ + "ld $9, 48(%1)\n\t" \ + "ld $25, 0(%1)\n\t" /* target->t9 */ \ + VALGRIND_CALL_NOREDIR_T9 \ + "move %0, $2\n" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[0]) \ + : /*trash*/ "memory", __CALLER_SAVED_REGS \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ + arg7) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[8]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + _argvec[3] = (unsigned long)(arg3); \ + _argvec[4] = (unsigned long)(arg4); \ + _argvec[5] = (unsigned long)(arg5); \ + _argvec[6] = (unsigned long)(arg6); \ + _argvec[7] = (unsigned long)(arg7); \ + __asm__ volatile( \ + "ld $4, 8(%1)\n\t" \ + "ld $5, 16(%1)\n\t" \ + "ld $6, 24(%1)\n\t" \ + "ld $7, 32(%1)\n\t" \ + "ld $8, 40(%1)\n\t" \ + "ld $9, 48(%1)\n\t" \ + "ld $10, 56(%1)\n\t" \ + "ld $25, 0(%1) \n\t" /* target->t9 */ \ + VALGRIND_CALL_NOREDIR_T9 \ + "move %0, $2\n" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[0]) \ + : /*trash*/ "memory", __CALLER_SAVED_REGS \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ + arg7,arg8) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[9]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + _argvec[3] = (unsigned long)(arg3); \ + _argvec[4] = (unsigned long)(arg4); \ + _argvec[5] = (unsigned long)(arg5); \ + _argvec[6] = (unsigned long)(arg6); \ + _argvec[7] = (unsigned long)(arg7); \ + _argvec[8] = (unsigned long)(arg8); \ + __asm__ volatile( \ + "ld $4, 8(%1)\n\t" \ + "ld $5, 16(%1)\n\t" \ + "ld $6, 24(%1)\n\t" \ + "ld $7, 32(%1)\n\t" \ + "ld $8, 40(%1)\n\t" \ + "ld $9, 48(%1)\n\t" \ + "ld $10, 56(%1)\n\t" \ + "ld $11, 64(%1)\n\t" \ + "ld $25, 0(%1) \n\t" /* target->t9 */ \ + VALGRIND_CALL_NOREDIR_T9 \ + "move %0, $2\n" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[0]) \ + : /*trash*/ "memory", __CALLER_SAVED_REGS \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ + arg7,arg8,arg9) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[10]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + _argvec[3] = (unsigned long)(arg3); \ + _argvec[4] = (unsigned long)(arg4); \ + _argvec[5] = (unsigned long)(arg5); \ + _argvec[6] = (unsigned long)(arg6); \ + _argvec[7] = (unsigned long)(arg7); \ + _argvec[8] = (unsigned long)(arg8); \ + _argvec[9] = (unsigned long)(arg9); \ + __asm__ volatile( \ + "dsubu $29, $29, 8\n\t" \ + "ld $4, 72(%1)\n\t" \ + "sd $4, 0($29)\n\t" \ + "ld $4, 8(%1)\n\t" \ + "ld $5, 16(%1)\n\t" \ + "ld $6, 24(%1)\n\t" \ + "ld $7, 32(%1)\n\t" \ + "ld $8, 40(%1)\n\t" \ + "ld $9, 48(%1)\n\t" \ + "ld $10, 56(%1)\n\t" \ + "ld $11, 64(%1)\n\t" \ + "ld $25, 0(%1)\n\t" /* target->t9 */ \ + VALGRIND_CALL_NOREDIR_T9 \ + "daddu $29, $29, 8\n\t" \ + "move %0, $2\n" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[0]) \ + : /*trash*/ "memory", __CALLER_SAVED_REGS \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ + arg7,arg8,arg9,arg10) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[11]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + _argvec[3] = (unsigned long)(arg3); \ + _argvec[4] = (unsigned long)(arg4); \ + _argvec[5] = (unsigned long)(arg5); \ + _argvec[6] = (unsigned long)(arg6); \ + _argvec[7] = (unsigned long)(arg7); \ + _argvec[8] = (unsigned long)(arg8); \ + _argvec[9] = (unsigned long)(arg9); \ + _argvec[10] = (unsigned long)(arg10); \ + __asm__ volatile( \ + "dsubu $29, $29, 16\n\t" \ + "ld $4, 72(%1)\n\t" \ + "sd $4, 0($29)\n\t" \ + "ld $4, 80(%1)\n\t" \ + "sd $4, 8($29)\n\t" \ + "ld $4, 8(%1)\n\t" \ + "ld $5, 16(%1)\n\t" \ + "ld $6, 24(%1)\n\t" \ + "ld $7, 32(%1)\n\t" \ + "ld $8, 40(%1)\n\t" \ + "ld $9, 48(%1)\n\t" \ + "ld $10, 56(%1)\n\t" \ + "ld $11, 64(%1)\n\t" \ + "ld $25, 0(%1)\n\t" /* target->t9 */ \ + VALGRIND_CALL_NOREDIR_T9 \ + "daddu $29, $29, 16\n\t" \ + "move %0, $2\n" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[0]) \ + : /*trash*/ "memory", __CALLER_SAVED_REGS \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5, \ + arg6,arg7,arg8,arg9,arg10, \ + arg11) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[12]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + _argvec[3] = (unsigned long)(arg3); \ + _argvec[4] = (unsigned long)(arg4); \ + _argvec[5] = (unsigned long)(arg5); \ + _argvec[6] = (unsigned long)(arg6); \ + _argvec[7] = (unsigned long)(arg7); \ + _argvec[8] = (unsigned long)(arg8); \ + _argvec[9] = (unsigned long)(arg9); \ + _argvec[10] = (unsigned long)(arg10); \ + _argvec[11] = (unsigned long)(arg11); \ + __asm__ volatile( \ + "dsubu $29, $29, 24\n\t" \ + "ld $4, 72(%1)\n\t" \ + "sd $4, 0($29)\n\t" \ + "ld $4, 80(%1)\n\t" \ + "sd $4, 8($29)\n\t" \ + "ld $4, 88(%1)\n\t" \ + "sd $4, 16($29)\n\t" \ + "ld $4, 8(%1)\n\t" \ + "ld $5, 16(%1)\n\t" \ + "ld $6, 24(%1)\n\t" \ + "ld $7, 32(%1)\n\t" \ + "ld $8, 40(%1)\n\t" \ + "ld $9, 48(%1)\n\t" \ + "ld $10, 56(%1)\n\t" \ + "ld $11, 64(%1)\n\t" \ + "ld $25, 0(%1)\n\t" /* target->t9 */ \ + VALGRIND_CALL_NOREDIR_T9 \ + "daddu $29, $29, 24\n\t" \ + "move %0, $2\n" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[0]) \ + : /*trash*/ "memory", __CALLER_SAVED_REGS \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5, \ + arg6,arg7,arg8,arg9,arg10, \ + arg11,arg12) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[13]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + _argvec[3] = (unsigned long)(arg3); \ + _argvec[4] = (unsigned long)(arg4); \ + _argvec[5] = (unsigned long)(arg5); \ + _argvec[6] = (unsigned long)(arg6); \ + _argvec[7] = (unsigned long)(arg7); \ + _argvec[8] = (unsigned long)(arg8); \ + _argvec[9] = (unsigned long)(arg9); \ + _argvec[10] = (unsigned long)(arg10); \ + _argvec[11] = (unsigned long)(arg11); \ + _argvec[12] = (unsigned long)(arg12); \ + __asm__ volatile( \ + "dsubu $29, $29, 32\n\t" \ + "ld $4, 72(%1)\n\t" \ + "sd $4, 0($29)\n\t" \ + "ld $4, 80(%1)\n\t" \ + "sd $4, 8($29)\n\t" \ + "ld $4, 88(%1)\n\t" \ + "sd $4, 16($29)\n\t" \ + "ld $4, 96(%1)\n\t" \ + "sd $4, 24($29)\n\t" \ + "ld $4, 8(%1)\n\t" \ + "ld $5, 16(%1)\n\t" \ + "ld $6, 24(%1)\n\t" \ + "ld $7, 32(%1)\n\t" \ + "ld $8, 40(%1)\n\t" \ + "ld $9, 48(%1)\n\t" \ + "ld $10, 56(%1)\n\t" \ + "ld $11, 64(%1)\n\t" \ + "ld $25, 0(%1)\n\t" /* target->t9 */ \ + VALGRIND_CALL_NOREDIR_T9 \ + "daddu $29, $29, 32\n\t" \ + "move %0, $2\n" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[0]) \ + : /*trash*/ "memory", __CALLER_SAVED_REGS \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#endif /* PLAT_mips64_linux */ + + +/* ------------------------------------------------------------------ */ +/* ARCHITECTURE INDEPENDENT MACROS for CLIENT REQUESTS. */ +/* */ +/* ------------------------------------------------------------------ */ + +/* Some request codes. There are many more of these, but most are not + exposed to end-user view. These are the public ones, all of the + form 0x1000 + small_number. + + Core ones are in the range 0x00000000--0x0000ffff. The non-public + ones start at 0x2000. +*/ + +/* These macros are used by tools -- they must be public, but don't + embed them into other programs. */ +#define VG_USERREQ_TOOL_BASE(a,b) \ + ((unsigned int)(((a)&0xff) << 24 | ((b)&0xff) << 16)) +#define VG_IS_TOOL_USERREQ(a, b, v) \ + (VG_USERREQ_TOOL_BASE(a,b) == ((v) & 0xffff0000)) + +/* !! ABIWARNING !! ABIWARNING !! ABIWARNING !! ABIWARNING !! + This enum comprises an ABI exported by Valgrind to programs + which use client requests. DO NOT CHANGE THE ORDER OF THESE + ENTRIES, NOR DELETE ANY -- add new ones at the end. */ +typedef + enum { VG_USERREQ__RUNNING_ON_VALGRIND = 0x1001, + VG_USERREQ__DISCARD_TRANSLATIONS = 0x1002, + + /* These allow any function to be called from the simulated + CPU but run on the real CPU. Nb: the first arg passed to + the function is always the ThreadId of the running + thread! So CLIENT_CALL0 actually requires a 1 arg + function, etc. */ + VG_USERREQ__CLIENT_CALL0 = 0x1101, + VG_USERREQ__CLIENT_CALL1 = 0x1102, + VG_USERREQ__CLIENT_CALL2 = 0x1103, + VG_USERREQ__CLIENT_CALL3 = 0x1104, + + /* Can be useful in regression testing suites -- eg. can + send Valgrind's output to /dev/null and still count + errors. */ + VG_USERREQ__COUNT_ERRORS = 0x1201, + + /* Allows the client program and/or gdbserver to execute a monitor + command. */ + VG_USERREQ__GDB_MONITOR_COMMAND = 0x1202, + + /* These are useful and can be interpreted by any tool that + tracks malloc() et al, by using vg_replace_malloc.c. */ + VG_USERREQ__MALLOCLIKE_BLOCK = 0x1301, + VG_USERREQ__RESIZEINPLACE_BLOCK = 0x130b, + VG_USERREQ__FREELIKE_BLOCK = 0x1302, + /* Memory pool support. */ + VG_USERREQ__CREATE_MEMPOOL = 0x1303, + VG_USERREQ__DESTROY_MEMPOOL = 0x1304, + VG_USERREQ__MEMPOOL_ALLOC = 0x1305, + VG_USERREQ__MEMPOOL_FREE = 0x1306, + VG_USERREQ__MEMPOOL_TRIM = 0x1307, + VG_USERREQ__MOVE_MEMPOOL = 0x1308, + VG_USERREQ__MEMPOOL_CHANGE = 0x1309, + VG_USERREQ__MEMPOOL_EXISTS = 0x130a, + + /* Allow printfs to valgrind log. */ + /* The first two pass the va_list argument by value, which + assumes it is the same size as or smaller than a UWord, + which generally isn't the case. Hence are deprecated. + The second two pass the vargs by reference and so are + immune to this problem. */ + /* both :: char* fmt, va_list vargs (DEPRECATED) */ + VG_USERREQ__PRINTF = 0x1401, + VG_USERREQ__PRINTF_BACKTRACE = 0x1402, + /* both :: char* fmt, va_list* vargs */ + VG_USERREQ__PRINTF_VALIST_BY_REF = 0x1403, + VG_USERREQ__PRINTF_BACKTRACE_VALIST_BY_REF = 0x1404, + + /* Stack support. */ + VG_USERREQ__STACK_REGISTER = 0x1501, + VG_USERREQ__STACK_DEREGISTER = 0x1502, + VG_USERREQ__STACK_CHANGE = 0x1503, + + /* Wine support */ + VG_USERREQ__LOAD_PDB_DEBUGINFO = 0x1601, + + /* Querying of debug info. */ + VG_USERREQ__MAP_IP_TO_SRCLOC = 0x1701, + + /* Disable/enable error reporting level. Takes a single + Word arg which is the delta to this thread's error + disablement indicator. Hence 1 disables or further + disables errors, and -1 moves back towards enablement. + Other values are not allowed. */ + VG_USERREQ__CHANGE_ERR_DISABLEMENT = 0x1801, + + /* Initialise IR injection */ + VG_USERREQ__VEX_INIT_FOR_IRI = 0x1901 + } Vg_ClientRequest; + +#if !defined(__GNUC__) +# define __extension__ /* */ +#endif + + +/* Returns the number of Valgrinds this code is running under. That + is, 0 if running natively, 1 if running under Valgrind, 2 if + running under Valgrind which is running under another Valgrind, + etc. */ +#define RUNNING_ON_VALGRIND \ + (unsigned)VALGRIND_DO_CLIENT_REQUEST_EXPR(0 /* if not */, \ + VG_USERREQ__RUNNING_ON_VALGRIND, \ + 0, 0, 0, 0, 0) \ + + +/* Discard translation of code in the range [_qzz_addr .. _qzz_addr + + _qzz_len - 1]. Useful if you are debugging a JITter or some such, + since it provides a way to make sure valgrind will retranslate the + invalidated area. Returns no value. */ +#define VALGRIND_DISCARD_TRANSLATIONS(_qzz_addr,_qzz_len) \ + VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__DISCARD_TRANSLATIONS, \ + _qzz_addr, _qzz_len, 0, 0, 0) + + +/* These requests are for getting Valgrind itself to print something. + Possibly with a backtrace. This is a really ugly hack. The return value + is the number of characters printed, excluding the "**** " part at the + start and the backtrace (if present). */ + +#if defined(__GNUC__) || defined(__INTEL_COMPILER) && !defined(_MSC_VER) +/* Modern GCC will optimize the static routine out if unused, + and unused attribute will shut down warnings about it. */ +static int VALGRIND_PRINTF(const char *format, ...) + __attribute__((format(__printf__, 1, 2), __unused__)); +#endif +static int +#if defined(_MSC_VER) +__inline +#endif +VALGRIND_PRINTF(const char *format, ...) +{ +#if defined(NVALGRIND) + return 0; +#else /* NVALGRIND */ +#if defined(_MSC_VER) || defined(__MINGW64__) + uintptr_t _qzz_res; +#else + unsigned long _qzz_res; +#endif + va_list vargs; + va_start(vargs, format); +#if defined(_MSC_VER) || defined(__MINGW64__) + _qzz_res = VALGRIND_DO_CLIENT_REQUEST_EXPR(0, + VG_USERREQ__PRINTF_VALIST_BY_REF, + (uintptr_t)format, + (uintptr_t)&vargs, + 0, 0, 0); +#else + _qzz_res = VALGRIND_DO_CLIENT_REQUEST_EXPR(0, + VG_USERREQ__PRINTF_VALIST_BY_REF, + (unsigned long)format, + (unsigned long)&vargs, + 0, 0, 0); +#endif + va_end(vargs); + return (int)_qzz_res; +#endif /* NVALGRIND */ +} + +#if defined(__GNUC__) || defined(__INTEL_COMPILER) && !defined(_MSC_VER) +static int VALGRIND_PRINTF_BACKTRACE(const char *format, ...) + __attribute__((format(__printf__, 1, 2), __unused__)); +#endif +static int +#if defined(_MSC_VER) +__inline +#endif +VALGRIND_PRINTF_BACKTRACE(const char *format, ...) +{ +#if defined(NVALGRIND) + return 0; +#else /* NVALGRIND */ +#if defined(_MSC_VER) || defined(__MINGW64__) + uintptr_t _qzz_res; +#else + unsigned long _qzz_res; +#endif + va_list vargs; + va_start(vargs, format); +#if defined(_MSC_VER) || defined(__MINGW64__) + _qzz_res = VALGRIND_DO_CLIENT_REQUEST_EXPR(0, + VG_USERREQ__PRINTF_BACKTRACE_VALIST_BY_REF, + (uintptr_t)format, + (uintptr_t)&vargs, + 0, 0, 0); +#else + _qzz_res = VALGRIND_DO_CLIENT_REQUEST_EXPR(0, + VG_USERREQ__PRINTF_BACKTRACE_VALIST_BY_REF, + (unsigned long)format, + (unsigned long)&vargs, + 0, 0, 0); +#endif + va_end(vargs); + return (int)_qzz_res; +#endif /* NVALGRIND */ +} + + +/* These requests allow control to move from the simulated CPU to the + real CPU, calling an arbitary function. + + Note that the current ThreadId is inserted as the first argument. + So this call: + + VALGRIND_NON_SIMD_CALL2(f, arg1, arg2) + + requires f to have this signature: + + Word f(Word tid, Word arg1, Word arg2) + + where "Word" is a word-sized type. + + Note that these client requests are not entirely reliable. For example, + if you call a function with them that subsequently calls printf(), + there's a high chance Valgrind will crash. Generally, your prospects of + these working are made higher if the called function does not refer to + any global variables, and does not refer to any libc or other functions + (printf et al). Any kind of entanglement with libc or dynamic linking is + likely to have a bad outcome, for tricky reasons which we've grappled + with a lot in the past. +*/ +#define VALGRIND_NON_SIMD_CALL0(_qyy_fn) \ + VALGRIND_DO_CLIENT_REQUEST_EXPR(0 /* default return */, \ + VG_USERREQ__CLIENT_CALL0, \ + _qyy_fn, \ + 0, 0, 0, 0) + +#define VALGRIND_NON_SIMD_CALL1(_qyy_fn, _qyy_arg1) \ + VALGRIND_DO_CLIENT_REQUEST_EXPR(0 /* default return */, \ + VG_USERREQ__CLIENT_CALL1, \ + _qyy_fn, \ + _qyy_arg1, 0, 0, 0) + +#define VALGRIND_NON_SIMD_CALL2(_qyy_fn, _qyy_arg1, _qyy_arg2) \ + VALGRIND_DO_CLIENT_REQUEST_EXPR(0 /* default return */, \ + VG_USERREQ__CLIENT_CALL2, \ + _qyy_fn, \ + _qyy_arg1, _qyy_arg2, 0, 0) + +#define VALGRIND_NON_SIMD_CALL3(_qyy_fn, _qyy_arg1, _qyy_arg2, _qyy_arg3) \ + VALGRIND_DO_CLIENT_REQUEST_EXPR(0 /* default return */, \ + VG_USERREQ__CLIENT_CALL3, \ + _qyy_fn, \ + _qyy_arg1, _qyy_arg2, \ + _qyy_arg3, 0) + + +/* Counts the number of errors that have been recorded by a tool. Nb: + the tool must record the errors with VG_(maybe_record_error)() or + VG_(unique_error)() for them to be counted. */ +#define VALGRIND_COUNT_ERRORS \ + (unsigned)VALGRIND_DO_CLIENT_REQUEST_EXPR( \ + 0 /* default return */, \ + VG_USERREQ__COUNT_ERRORS, \ + 0, 0, 0, 0, 0) + +/* Several Valgrind tools (Memcheck, Massif, Helgrind, DRD) rely on knowing + when heap blocks are allocated in order to give accurate results. This + happens automatically for the standard allocator functions such as + malloc(), calloc(), realloc(), memalign(), new, new[], free(), delete, + delete[], etc. + + But if your program uses a custom allocator, this doesn't automatically + happen, and Valgrind will not do as well. For example, if you allocate + superblocks with mmap() and then allocates chunks of the superblocks, all + Valgrind's observations will be at the mmap() level and it won't know that + the chunks should be considered separate entities. In Memcheck's case, + that means you probably won't get heap block overrun detection (because + there won't be redzones marked as unaddressable) and you definitely won't + get any leak detection. + + The following client requests allow a custom allocator to be annotated so + that it can be handled accurately by Valgrind. + + VALGRIND_MALLOCLIKE_BLOCK marks a region of memory as having been allocated + by a malloc()-like function. For Memcheck (an illustrative case), this + does two things: + + - It records that the block has been allocated. This means any addresses + within the block mentioned in error messages will be + identified as belonging to the block. It also means that if the block + isn't freed it will be detected by the leak checker. + + - It marks the block as being addressable and undefined (if 'is_zeroed' is + not set), or addressable and defined (if 'is_zeroed' is set). This + controls how accesses to the block by the program are handled. + + 'addr' is the start of the usable block (ie. after any + redzone), 'sizeB' is its size. 'rzB' is the redzone size if the allocator + can apply redzones -- these are blocks of padding at the start and end of + each block. Adding redzones is recommended as it makes it much more likely + Valgrind will spot block overruns. `is_zeroed' indicates if the memory is + zeroed (or filled with another predictable value), as is the case for + calloc(). + + VALGRIND_MALLOCLIKE_BLOCK should be put immediately after the point where a + heap block -- that will be used by the client program -- is allocated. + It's best to put it at the outermost level of the allocator if possible; + for example, if you have a function my_alloc() which calls + internal_alloc(), and the client request is put inside internal_alloc(), + stack traces relating to the heap block will contain entries for both + my_alloc() and internal_alloc(), which is probably not what you want. + + For Memcheck users: if you use VALGRIND_MALLOCLIKE_BLOCK to carve out + custom blocks from within a heap block, B, that has been allocated with + malloc/calloc/new/etc, then block B will be *ignored* during leak-checking + -- the custom blocks will take precedence. + + VALGRIND_FREELIKE_BLOCK is the partner to VALGRIND_MALLOCLIKE_BLOCK. For + Memcheck, it does two things: + + - It records that the block has been deallocated. This assumes that the + block was annotated as having been allocated via + VALGRIND_MALLOCLIKE_BLOCK. Otherwise, an error will be issued. + + - It marks the block as being unaddressable. + + VALGRIND_FREELIKE_BLOCK should be put immediately after the point where a + heap block is deallocated. + + VALGRIND_RESIZEINPLACE_BLOCK informs a tool about reallocation. For + Memcheck, it does four things: + + - It records that the size of a block has been changed. This assumes that + the block was annotated as having been allocated via + VALGRIND_MALLOCLIKE_BLOCK. Otherwise, an error will be issued. + + - If the block shrunk, it marks the freed memory as being unaddressable. + + - If the block grew, it marks the new area as undefined and defines a red + zone past the end of the new block. + + - The V-bits of the overlap between the old and the new block are preserved. + + VALGRIND_RESIZEINPLACE_BLOCK should be put after allocation of the new block + and before deallocation of the old block. + + In many cases, these three client requests will not be enough to get your + allocator working well with Memcheck. More specifically, if your allocator + writes to freed blocks in any way then a VALGRIND_MAKE_MEM_UNDEFINED call + will be necessary to mark the memory as addressable just before the zeroing + occurs, otherwise you'll get a lot of invalid write errors. For example, + you'll need to do this if your allocator recycles freed blocks, but it + zeroes them before handing them back out (via VALGRIND_MALLOCLIKE_BLOCK). + Alternatively, if your allocator reuses freed blocks for allocator-internal + data structures, VALGRIND_MAKE_MEM_UNDEFINED calls will also be necessary. + + Really, what's happening is a blurring of the lines between the client + program and the allocator... after VALGRIND_FREELIKE_BLOCK is called, the + memory should be considered unaddressable to the client program, but the + allocator knows more than the rest of the client program and so may be able + to safely access it. Extra client requests are necessary for Valgrind to + understand the distinction between the allocator and the rest of the + program. + + Ignored if addr == 0. +*/ +#define VALGRIND_MALLOCLIKE_BLOCK(addr, sizeB, rzB, is_zeroed) \ + VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__MALLOCLIKE_BLOCK, \ + addr, sizeB, rzB, is_zeroed, 0) + +/* See the comment for VALGRIND_MALLOCLIKE_BLOCK for details. + Ignored if addr == 0. +*/ +#define VALGRIND_RESIZEINPLACE_BLOCK(addr, oldSizeB, newSizeB, rzB) \ + VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__RESIZEINPLACE_BLOCK, \ + addr, oldSizeB, newSizeB, rzB, 0) + +/* See the comment for VALGRIND_MALLOCLIKE_BLOCK for details. + Ignored if addr == 0. +*/ +#define VALGRIND_FREELIKE_BLOCK(addr, rzB) \ + VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__FREELIKE_BLOCK, \ + addr, rzB, 0, 0, 0) + +/* Create a memory pool. */ +#define VALGRIND_CREATE_MEMPOOL(pool, rzB, is_zeroed) \ + VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__CREATE_MEMPOOL, \ + pool, rzB, is_zeroed, 0, 0) + +/* Destroy a memory pool. */ +#define VALGRIND_DESTROY_MEMPOOL(pool) \ + VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__DESTROY_MEMPOOL, \ + pool, 0, 0, 0, 0) + +/* Associate a piece of memory with a memory pool. */ +#define VALGRIND_MEMPOOL_ALLOC(pool, addr, size) \ + VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__MEMPOOL_ALLOC, \ + pool, addr, size, 0, 0) + +/* Disassociate a piece of memory from a memory pool. */ +#define VALGRIND_MEMPOOL_FREE(pool, addr) \ + VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__MEMPOOL_FREE, \ + pool, addr, 0, 0, 0) + +/* Disassociate any pieces outside a particular range. */ +#define VALGRIND_MEMPOOL_TRIM(pool, addr, size) \ + VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__MEMPOOL_TRIM, \ + pool, addr, size, 0, 0) + +/* Resize and/or move a piece associated with a memory pool. */ +#define VALGRIND_MOVE_MEMPOOL(poolA, poolB) \ + VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__MOVE_MEMPOOL, \ + poolA, poolB, 0, 0, 0) + +/* Resize and/or move a piece associated with a memory pool. */ +#define VALGRIND_MEMPOOL_CHANGE(pool, addrA, addrB, size) \ + VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__MEMPOOL_CHANGE, \ + pool, addrA, addrB, size, 0) + +/* Return 1 if a mempool exists, else 0. */ +#define VALGRIND_MEMPOOL_EXISTS(pool) \ + (unsigned)VALGRIND_DO_CLIENT_REQUEST_EXPR(0, \ + VG_USERREQ__MEMPOOL_EXISTS, \ + pool, 0, 0, 0, 0) + +/* Mark a piece of memory as being a stack. Returns a stack id. + start is the lowest addressable stack byte, end is the highest + addressable stack byte. */ +#define VALGRIND_STACK_REGISTER(start, end) \ + (unsigned)VALGRIND_DO_CLIENT_REQUEST_EXPR(0, \ + VG_USERREQ__STACK_REGISTER, \ + start, end, 0, 0, 0) + +/* Unmark the piece of memory associated with a stack id as being a + stack. */ +#define VALGRIND_STACK_DEREGISTER(id) \ + VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__STACK_DEREGISTER, \ + id, 0, 0, 0, 0) + +/* Change the start and end address of the stack id. + start is the new lowest addressable stack byte, end is the new highest + addressable stack byte. */ +#define VALGRIND_STACK_CHANGE(id, start, end) \ + VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__STACK_CHANGE, \ + id, start, end, 0, 0) + +/* Load PDB debug info for Wine PE image_map. */ +#define VALGRIND_LOAD_PDB_DEBUGINFO(fd, ptr, total_size, delta) \ + VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__LOAD_PDB_DEBUGINFO, \ + fd, ptr, total_size, delta, 0) + +/* Map a code address to a source file name and line number. buf64 + must point to a 64-byte buffer in the caller's address space. The + result will be dumped in there and is guaranteed to be zero + terminated. If no info is found, the first byte is set to zero. */ +#define VALGRIND_MAP_IP_TO_SRCLOC(addr, buf64) \ + (unsigned)VALGRIND_DO_CLIENT_REQUEST_EXPR(0, \ + VG_USERREQ__MAP_IP_TO_SRCLOC, \ + addr, buf64, 0, 0, 0) + +/* Disable error reporting for this thread. Behaves in a stack like + way, so you can safely call this multiple times provided that + VALGRIND_ENABLE_ERROR_REPORTING is called the same number of times + to re-enable reporting. The first call of this macro disables + reporting. Subsequent calls have no effect except to increase the + number of VALGRIND_ENABLE_ERROR_REPORTING calls needed to re-enable + reporting. Child threads do not inherit this setting from their + parents -- they are always created with reporting enabled. */ +#define VALGRIND_DISABLE_ERROR_REPORTING \ + VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__CHANGE_ERR_DISABLEMENT, \ + 1, 0, 0, 0, 0) + +/* Re-enable error reporting, as per comments on + VALGRIND_DISABLE_ERROR_REPORTING. */ +#define VALGRIND_ENABLE_ERROR_REPORTING \ + VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__CHANGE_ERR_DISABLEMENT, \ + -1, 0, 0, 0, 0) + +/* Execute a monitor command from the client program. + If a connection is opened with GDB, the output will be sent + according to the output mode set for vgdb. + If no connection is opened, output will go to the log output. + Returns 1 if command not recognised, 0 otherwise. */ +#define VALGRIND_MONITOR_COMMAND(command) \ + VALGRIND_DO_CLIENT_REQUEST_EXPR(0, VG_USERREQ__GDB_MONITOR_COMMAND, \ + command, 0, 0, 0, 0) + + +#undef PLAT_x86_darwin +#undef PLAT_amd64_darwin +#undef PLAT_x86_win32 +#undef PLAT_amd64_win64 +#undef PLAT_x86_linux +#undef PLAT_amd64_linux +#undef PLAT_ppc32_linux +#undef PLAT_ppc64be_linux +#undef PLAT_ppc64le_linux +#undef PLAT_arm_linux +#undef PLAT_s390x_linux +#undef PLAT_mips32_linux +#undef PLAT_mips64_linux + +#endif /* __VALGRIND_H */ diff --git a/po/POTFILES.in b/po/POTFILES.in index bec15638..358d39c7 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -1,3 +1,4 @@ # List of source files which contain translatable strings. src/log/normal.c src/string/i18n.c +src/core/runner.c diff --git a/po/fr.po b/po/fr.po index d9b7f118..1fe53b1d 100644 --- a/po/fr.po +++ b/po/fr.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: criterion 2.0.0\n" "Report-Msgid-Bugs-To: franklinmathieu+criterion@gmail.com\n" -"POT-Creation-Date: 2015-09-16 21:18+0200\n" +"POT-Creation-Date: 2015-09-26 00:02+0200\n" "PO-Revision-Date: 2015-04-03 17:58+0200\n" "Last-Translator: \n" "Language-Team: French\n" @@ -174,3 +174,25 @@ msgstr "L'instruction `%1$s` a levé une instance de l'exception `%2$s`." #, c-format msgid "The statement `%1$s` did not throw an instance of the `%2$s` exception." msgstr "L'instruction `%1$s` n'a pas levé d'instance de l'exception `%2$s`." + +#: src/core/runner.c:54 +#, c-format +msgid "" +"%1$sWarning! Criterion has detected that it is running under valgrind, but " +"the no_early_exit option is explicitely disabled. Reports will not be " +"accurate!%2$s\n" +msgstr "" +"%1$sAttention! Criterion a détecté qu'il a été lancé avec valgrind, mais " +"l'option no_early_exit est explicitement désactivée. Les rapports d'erreur " +"ne seront pas précis!%2$s\n" + +#: src/core/runner.c:58 +#, c-format +msgid "" +"%1$sWarning! Criterion has detected that it is running under valgrind, but " +"the number of jobs have been explicitely set. Reports might appear confusing!" +"%2$s\n" +msgstr "" +"%1$sAttention! Criterion a détecté qu'il a été lancé avec valgrind, mais " +"le nombre de tâches est explicitement défini. Les rapports d'erreur " +"risquent d'être déroutants!%2$s\n" diff --git a/src/core/runner.c b/src/core/runner.c index ea1a7fec..f0ae80b5 100644 --- a/src/core/runner.c +++ b/src/core/runner.c @@ -21,9 +21,11 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ +#define CRITERION_LOGGING_COLORS #include #include #include +#include #include "criterion/criterion.h" #include "criterion/options.h" #include "criterion/ordered-set.h" @@ -46,6 +48,27 @@ #include "string/extmatch.h" #endif +typedef const char *const msg_t; + +#ifdef ENABLE_NLS +static msg_t msg_valgrind_early_exit = N_("%1$sWarning! Criterion has detected " + "that it is running under valgrind, but the no_early_exit option is " + "explicitely disabled. Reports will not be accurate!%2$s\n"); + +static msg_t msg_valgrind_jobs = N_("%1$sWarning! Criterion has detected " + "that it is running under valgrind, but the number of jobs have been " + "explicitely set. Reports might appear confusing!%2$s\n"); +#else +static msg_t msg_valgrind_early_exit = "%sWarning! Criterion has detected " + "that it is running under valgrind, but the no_early_exit option is " + "explicitely disabled. Reports will not be accurate!%s\n"; + +static msg_t msg_valgrind_jobs = "%sWarning! Criterion has detected " + "that it is running under valgrind, but the number of jobs have been " + "explicitely set. Reports might appear confusing!%s\n"; +#endif + + #ifdef _MSC_VER struct criterion_test *SECTION_START_(cr_tst); struct criterion_suite *SECTION_START_(cr_sts); @@ -312,6 +335,11 @@ void disable_unmatching(struct criterion_test_set *set) { struct criterion_test_set *criterion_initialize(void) { init_i18n(); + if (RUNNING_ON_VALGRIND) { + criterion_options.no_early_exit = 1; + criterion_options.jobs = 1; + } + if (resume_child()) // (windows only) resume from the fork exit(0); @@ -386,6 +414,15 @@ static int criterion_run_all_tests_impl(struct criterion_test_set *set) { report(PRE_ALL, set); log(pre_all, set); + if (RUNNING_ON_VALGRIND) { + if (!criterion_options.no_early_exit) + criterion_pimportant(CRITERION_PREFIX_DASHES, + _(msg_valgrind_early_exit), FG_BOLD, RESET); + if (criterion_options.jobs != 1) + criterion_pimportant(CRITERION_PREFIX_DASHES, + _(msg_valgrind_jobs), FG_BOLD, RESET); + } + fflush(NULL); // flush everything before forking g_worker_pipe = stdpipe(); diff --git a/src/entry/main.c b/src/entry/main.c index 6fb07879..ee1d2e5d 100644 --- a/src/entry/main.c +++ b/src/entry/main.c @@ -144,24 +144,41 @@ int criterion_handle_args(int argc, char *argv[], bool handle_unknown_arg) { {0, 0, 0, 0 } }; - bool use_ascii = !strcmp("1", DEF(getenv("CRITERION_USE_ASCII"), "0")) - || !strcmp("dumb", DEF(getenv("TERM"), "dumb")); - setlocale(LC_ALL, ""); #if ENABLE_NLS textdomain (PACKAGE "-test"); #endif + char *env_always_succeed = getenv("CRITERION_ALWAYS_SUCCEED"); + char *env_no_early_exit = getenv("CRITERION_NO_EARLY_EXIT"); + char *env_fail_fast = getenv("CRITERION_FAIL_FAST"); + char *env_use_ascii = getenv("CRITERION_USE_ASCII"); + char *env_jobs = getenv("CRITERION_JOBS"); + char *env_logging_threshold = getenv("CRITERION_VERBOSITY_LEVEL"); + char *env_short_filename = getenv("CRITERION_SHORT_FILENAME"); + + bool is_term_dumb = !strcmp("dumb", DEF(getenv("TERM"), "dumb")); + struct criterion_options *opt = &criterion_options; - opt->always_succeed = !strcmp("1", DEF(getenv("CRITERION_ALWAYS_SUCCEED"), "0")); - opt->no_early_exit = !strcmp("1", DEF(getenv("CRITERION_NO_EARLY_EXIT") , "0")); - opt->fail_fast = !strcmp("1", DEF(getenv("CRITERION_FAIL_FAST") , "0")); - opt->use_ascii = use_ascii; - opt->jobs = atou(DEF(getenv("CRITERION_JOBS"), "0")); - opt->logging_threshold = atou(DEF(getenv("CRITERION_VERBOSITY_LEVEL"), "2")); - opt->short_filename = !strcmp("1", DEF(getenv("CRITERION_SHORT_FILENAME"), "0")); + if (env_always_succeed) + opt->always_succeed = !strcmp("1", env_always_succeed); + if (env_no_early_exit) + opt->no_early_exit = !strcmp("1", env_no_early_exit); + if (env_fail_fast) + opt->fail_fast = !strcmp("1", env_fail_fast); + if (env_use_ascii) + opt->use_ascii = !strcmp("1", env_use_ascii) || is_term_dumb; + if (env_jobs) + opt->jobs = atou(env_jobs); + if (env_logging_threshold) + opt->logging_threshold = atou(env_logging_threshold); + if (env_short_filename) + opt->short_filename = !strcmp("1", env_short_filename); + #ifdef HAVE_PCRE - opt->pattern = getenv("CRITERION_TEST_PATTERN"); + char *env_pattern = getenv("CRITERION_TEST_PATTERN"); + if (env_pattern) + opt->pattern = env_pattern; #endif bool use_tap = !strcmp("1", DEF(getenv("CRITERION_ENABLE_TAP"), "0")); From 6110f43d87f631dbe87a9d3e1def90baf700e84c Mon Sep 17 00:00:00 2001 From: Snaipe Date: Sat, 26 Sep 2015 00:31:57 +0200 Subject: [PATCH 037/211] Added regression tests on theories --- samples/outputs/theories.c.bin.err.expected | 21 ++++++++++++++++++++ samples/outputs/theories.c.bin.out.expected | 0 samples/outputs/theories.cc.bin.err.expected | 21 ++++++++++++++++++++ samples/outputs/theories.cc.bin.out.expected | 0 4 files changed, 42 insertions(+) create mode 100644 samples/outputs/theories.c.bin.err.expected create mode 100644 samples/outputs/theories.c.bin.out.expected create mode 100644 samples/outputs/theories.cc.bin.err.expected create mode 100644 samples/outputs/theories.cc.bin.out.expected diff --git a/samples/outputs/theories.c.bin.err.expected b/samples/outputs/theories.c.bin.err.expected new file mode 100644 index 00000000..f9937c1e --- /dev/null +++ b/samples/outputs/theories.c.bin.err.expected @@ -0,0 +1,21 @@ +[----] theories.c:27: Assertion failed: The expression (a) == (bad_div(bad_mul(a, b), b)) is false. +[----] Theory algebra::bad_divide_is_inverse_of_multiply failed with the following parameters: (2147483647, 2) +[----] theories.c:27: Assertion failed: The expression (a) == (bad_div(bad_mul(a, b), b)) is false. +[----] Theory algebra::bad_divide_is_inverse_of_multiply failed with the following parameters: (-2147483648, 2) +[----] theories.c:27: Unexpected signal caught below this line! +[FAIL] algebra::bad_divide_is_inverse_of_multiply: CRASH! +[----] theories.c:120: Assertion failed: The conditions for this assertion were not met. +[----] Theory theory::gen failed with the following parameters: (1) +[----] theories.c:120: Assertion failed: The conditions for this assertion were not met. +[----] Theory theory::gen failed with the following parameters: (2) +[----] theories.c:120: Assertion failed: The conditions for this assertion were not met. +[----] Theory theory::gen failed with the following parameters: (3) +[----] theories.c:120: Assertion failed: The conditions for this assertion were not met. +[----] Theory theory::gen failed with the following parameters: (4) +[----] theories.c:120: Assertion failed: The conditions for this assertion were not met. +[----] Theory theory::gen failed with the following parameters: (5) +[FAIL] theory::gen: (0.00s) +[----] theories.c:103: Assertion failed: The conditions for this assertion were not met. +[----] Theory theory::misc failed with the following parameters: ('a', true, 1, 1, 1l, 1l, 3.14f, 3.14, "test", "other test", 0x604698) +[FAIL] theory::misc: (0.00s) +[====] Synthesis: Tested: 6 | Passing: 3 | Failing: 3 | Crashing: 1  diff --git a/samples/outputs/theories.c.bin.out.expected b/samples/outputs/theories.c.bin.out.expected new file mode 100644 index 00000000..e69de29b diff --git a/samples/outputs/theories.cc.bin.err.expected b/samples/outputs/theories.cc.bin.err.expected new file mode 100644 index 00000000..c35d60c4 --- /dev/null +++ b/samples/outputs/theories.cc.bin.err.expected @@ -0,0 +1,21 @@ +[----] theories.cc:31: Assertion failed: The expression (a) == (bad_div(bad_mul(a, b), b)) is false. +[----] Theory algebra::bad_divide_is_inverse_of_multiply failed with the following parameters: (2147483647, 2) +[----] theories.cc:31: Assertion failed: The expression (a) == (bad_div(bad_mul(a, b), b)) is false. +[----] Theory algebra::bad_divide_is_inverse_of_multiply failed with the following parameters: (-2147483648, 2) +[----] theories.cc:31: Unexpected signal caught below this line! +[FAIL] algebra::bad_divide_is_inverse_of_multiply: CRASH! +[----] theories.cc:128: Assertion failed: The conditions for this assertion were not met. +[----] Theory theory::gen failed with the following parameters: (1) +[----] theories.cc:128: Assertion failed: The conditions for this assertion were not met. +[----] Theory theory::gen failed with the following parameters: (2) +[----] theories.cc:128: Assertion failed: The conditions for this assertion were not met. +[----] Theory theory::gen failed with the following parameters: (3) +[----] theories.cc:128: Assertion failed: The conditions for this assertion were not met. +[----] Theory theory::gen failed with the following parameters: (4) +[----] theories.cc:128: Assertion failed: The conditions for this assertion were not met. +[----] Theory theory::gen failed with the following parameters: (5) +[FAIL] theory::gen: (0.00s) +[----] theories.cc:111: Assertion failed: The conditions for this assertion were not met. +[----] Theory theory::misc failed with the following parameters: ('a', true, 1, 1, 1l, 1l, 3.14f, 3.14, "test", "other test", 0x605480) +[FAIL] theory::misc: (0.00s) +[====] Synthesis: Tested: 6 | Passing: 3 | Failing: 3 | Crashing: 1  diff --git a/samples/outputs/theories.cc.bin.out.expected b/samples/outputs/theories.cc.bin.out.expected new file mode 100644 index 00000000..e69de29b From 4cc826eae345063803466f1254648ca46adb2101 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Sat, 26 Sep 2015 00:36:51 +0200 Subject: [PATCH 038/211] Removed theory parameter printing from sample & regression test --- samples/outputs/theories.c.bin.err.expected | 15 ++++++--------- samples/outputs/theories.cc.bin.err.expected | 15 ++++++--------- samples/theories.c | 3 --- samples/theories.cc | 3 --- 4 files changed, 12 insertions(+), 24 deletions(-) diff --git a/samples/outputs/theories.c.bin.err.expected b/samples/outputs/theories.c.bin.err.expected index f9937c1e..95b4603c 100644 --- a/samples/outputs/theories.c.bin.err.expected +++ b/samples/outputs/theories.c.bin.err.expected @@ -4,18 +4,15 @@ [----] Theory algebra::bad_divide_is_inverse_of_multiply failed with the following parameters: (-2147483648, 2) [----] theories.c:27: Unexpected signal caught below this line! [FAIL] algebra::bad_divide_is_inverse_of_multiply: CRASH! -[----] theories.c:120: Assertion failed: The conditions for this assertion were not met. +[----] theories.c:117: Assertion failed: The conditions for this assertion were not met. [----] Theory theory::gen failed with the following parameters: (1) -[----] theories.c:120: Assertion failed: The conditions for this assertion were not met. +[----] theories.c:117: Assertion failed: The conditions for this assertion were not met. [----] Theory theory::gen failed with the following parameters: (2) -[----] theories.c:120: Assertion failed: The conditions for this assertion were not met. +[----] theories.c:117: Assertion failed: The conditions for this assertion were not met. [----] Theory theory::gen failed with the following parameters: (3) -[----] theories.c:120: Assertion failed: The conditions for this assertion were not met. +[----] theories.c:117: Assertion failed: The conditions for this assertion were not met. [----] Theory theory::gen failed with the following parameters: (4) -[----] theories.c:120: Assertion failed: The conditions for this assertion were not met. +[----] theories.c:117: Assertion failed: The conditions for this assertion were not met. [----] Theory theory::gen failed with the following parameters: (5) [FAIL] theory::gen: (0.00s) -[----] theories.c:103: Assertion failed: The conditions for this assertion were not met. -[----] Theory theory::misc failed with the following parameters: ('a', true, 1, 1, 1l, 1l, 3.14f, 3.14, "test", "other test", 0x604698) -[FAIL] theory::misc: (0.00s) -[====] Synthesis: Tested: 6 | Passing: 3 | Failing: 3 | Crashing: 1  +[====] Synthesis: Tested: 6 | Passing: 4 | Failing: 2 | Crashing: 1  diff --git a/samples/outputs/theories.cc.bin.err.expected b/samples/outputs/theories.cc.bin.err.expected index c35d60c4..bc647a1b 100644 --- a/samples/outputs/theories.cc.bin.err.expected +++ b/samples/outputs/theories.cc.bin.err.expected @@ -4,18 +4,15 @@ [----] Theory algebra::bad_divide_is_inverse_of_multiply failed with the following parameters: (-2147483648, 2) [----] theories.cc:31: Unexpected signal caught below this line! [FAIL] algebra::bad_divide_is_inverse_of_multiply: CRASH! -[----] theories.cc:128: Assertion failed: The conditions for this assertion were not met. +[----] theories.cc:125: Assertion failed: The conditions for this assertion were not met. [----] Theory theory::gen failed with the following parameters: (1) -[----] theories.cc:128: Assertion failed: The conditions for this assertion were not met. +[----] theories.cc:125: Assertion failed: The conditions for this assertion were not met. [----] Theory theory::gen failed with the following parameters: (2) -[----] theories.cc:128: Assertion failed: The conditions for this assertion were not met. +[----] theories.cc:125: Assertion failed: The conditions for this assertion were not met. [----] Theory theory::gen failed with the following parameters: (3) -[----] theories.cc:128: Assertion failed: The conditions for this assertion were not met. +[----] theories.cc:125: Assertion failed: The conditions for this assertion were not met. [----] Theory theory::gen failed with the following parameters: (4) -[----] theories.cc:128: Assertion failed: The conditions for this assertion were not met. +[----] theories.cc:125: Assertion failed: The conditions for this assertion were not met. [----] Theory theory::gen failed with the following parameters: (5) [FAIL] theory::gen: (0.00s) -[----] theories.cc:111: Assertion failed: The conditions for this assertion were not met. -[----] Theory theory::misc failed with the following parameters: ('a', true, 1, 1, 1l, 1l, 3.14f, 3.14, "test", "other test", 0x605480) -[FAIL] theory::misc: (0.00s) -[====] Synthesis: Tested: 6 | Passing: 3 | Failing: 3 | Crashing: 1  +[====] Synthesis: Tested: 6 | Passing: 4 | Failing: 2 | Crashing: 1  diff --git a/samples/theories.c b/samples/theories.c index 0bbe7cc2..b4ca6d26 100644 --- a/samples/theories.c +++ b/samples/theories.c @@ -98,9 +98,6 @@ Theory((char c, bool b, short s, int i, long l, long long ll, float f, double d, cr_assert_str_eq(str, "test"); cr_assert_str_eq(cstr, "other test"); cr_assert_eq(obj->foo, 42); - - // abort to see the formatted string of all parameters - cr_assert_fail(); } // Manually generate datapoints diff --git a/samples/theories.cc b/samples/theories.cc index 56027542..23c0ebc5 100644 --- a/samples/theories.cc +++ b/samples/theories.cc @@ -106,9 +106,6 @@ Theory((char c, bool b, short s, int i, long l, long long ll, float f, double d, cr_assert_str_eq(str, "test"); cr_assert_str_eq(cstr, "other test"); cr_assert_eq(obj->foo, 42); - - // abort to see the formatted string of all parameters - cr_assert_fail(); } // Manually generate datapoints From 5ffd88301573080ca8441e1effcba9ab9a757094 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Sat, 26 Sep 2015 01:33:14 +0200 Subject: [PATCH 039/211] Fixed inconsistent message strings for failed theories --- src/log/normal.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/log/normal.c b/src/log/normal.c index 834c1827..3bb0c418 100644 --- a/src/log/normal.c +++ b/src/log/normal.c @@ -77,7 +77,7 @@ static msg_t msg_post_test = "%s::%s\n"; static msg_t msg_post_suite_test = "%s::%s: Test is disabled\n"; static msg_t msg_post_suite_suite = "%s::%s: Suite is disabled\n"; static msg_t msg_assert_fail = "%s%s%s:%s%d%s: Assertion failed: %s\n"; -static msg_t msg_theory_fail = " Theory %s::%s failed with the following parameters: %s\n"; +static msg_t msg_theory_fail = " Theory %s::%s failed with the following parameters: (%s)\n"; static msg_t msg_test_timeout = "%s::%s: Timed out. (%3.2fs)\n"; static msg_t msg_test_crash_line = "%s%s%s:%s%u%s: Unexpected signal caught below this line!\n"; static msg_t msg_test_crash = "%s::%s: CRASH!\n"; From 974b7d039337e382e61bdc523fbd6dac635093d3 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Sat, 26 Sep 2015 01:37:36 +0200 Subject: [PATCH 040/211] Revert "Removed theory parameter printing from sample & regression test" & "Added regression tests on theories" This reverts commits 4cc826eae345063803466f1254648ca46adb2101 and 6110f43d87f631dbe87a9d3e1def90baf700e84c. Regression tests cannot be done on the two theory samples, as they both illustrate the consequences of testing against undefined behaviour. A full-fledged internal test should be set up in ./samples/tests for this purpose. --- samples/outputs/theories.c.bin.err.expected | 18 ------------------ samples/outputs/theories.c.bin.out.expected | 0 samples/outputs/theories.cc.bin.err.expected | 18 ------------------ samples/outputs/theories.cc.bin.out.expected | 0 samples/theories.c | 3 +++ samples/theories.cc | 3 +++ 6 files changed, 6 insertions(+), 36 deletions(-) delete mode 100644 samples/outputs/theories.c.bin.err.expected delete mode 100644 samples/outputs/theories.c.bin.out.expected delete mode 100644 samples/outputs/theories.cc.bin.err.expected delete mode 100644 samples/outputs/theories.cc.bin.out.expected diff --git a/samples/outputs/theories.c.bin.err.expected b/samples/outputs/theories.c.bin.err.expected deleted file mode 100644 index 95b4603c..00000000 --- a/samples/outputs/theories.c.bin.err.expected +++ /dev/null @@ -1,18 +0,0 @@ -[----] theories.c:27: Assertion failed: The expression (a) == (bad_div(bad_mul(a, b), b)) is false. -[----] Theory algebra::bad_divide_is_inverse_of_multiply failed with the following parameters: (2147483647, 2) -[----] theories.c:27: Assertion failed: The expression (a) == (bad_div(bad_mul(a, b), b)) is false. -[----] Theory algebra::bad_divide_is_inverse_of_multiply failed with the following parameters: (-2147483648, 2) -[----] theories.c:27: Unexpected signal caught below this line! -[FAIL] algebra::bad_divide_is_inverse_of_multiply: CRASH! -[----] theories.c:117: Assertion failed: The conditions for this assertion were not met. -[----] Theory theory::gen failed with the following parameters: (1) -[----] theories.c:117: Assertion failed: The conditions for this assertion were not met. -[----] Theory theory::gen failed with the following parameters: (2) -[----] theories.c:117: Assertion failed: The conditions for this assertion were not met. -[----] Theory theory::gen failed with the following parameters: (3) -[----] theories.c:117: Assertion failed: The conditions for this assertion were not met. -[----] Theory theory::gen failed with the following parameters: (4) -[----] theories.c:117: Assertion failed: The conditions for this assertion were not met. -[----] Theory theory::gen failed with the following parameters: (5) -[FAIL] theory::gen: (0.00s) -[====] Synthesis: Tested: 6 | Passing: 4 | Failing: 2 | Crashing: 1  diff --git a/samples/outputs/theories.c.bin.out.expected b/samples/outputs/theories.c.bin.out.expected deleted file mode 100644 index e69de29b..00000000 diff --git a/samples/outputs/theories.cc.bin.err.expected b/samples/outputs/theories.cc.bin.err.expected deleted file mode 100644 index bc647a1b..00000000 --- a/samples/outputs/theories.cc.bin.err.expected +++ /dev/null @@ -1,18 +0,0 @@ -[----] theories.cc:31: Assertion failed: The expression (a) == (bad_div(bad_mul(a, b), b)) is false. -[----] Theory algebra::bad_divide_is_inverse_of_multiply failed with the following parameters: (2147483647, 2) -[----] theories.cc:31: Assertion failed: The expression (a) == (bad_div(bad_mul(a, b), b)) is false. -[----] Theory algebra::bad_divide_is_inverse_of_multiply failed with the following parameters: (-2147483648, 2) -[----] theories.cc:31: Unexpected signal caught below this line! -[FAIL] algebra::bad_divide_is_inverse_of_multiply: CRASH! -[----] theories.cc:125: Assertion failed: The conditions for this assertion were not met. -[----] Theory theory::gen failed with the following parameters: (1) -[----] theories.cc:125: Assertion failed: The conditions for this assertion were not met. -[----] Theory theory::gen failed with the following parameters: (2) -[----] theories.cc:125: Assertion failed: The conditions for this assertion were not met. -[----] Theory theory::gen failed with the following parameters: (3) -[----] theories.cc:125: Assertion failed: The conditions for this assertion were not met. -[----] Theory theory::gen failed with the following parameters: (4) -[----] theories.cc:125: Assertion failed: The conditions for this assertion were not met. -[----] Theory theory::gen failed with the following parameters: (5) -[FAIL] theory::gen: (0.00s) -[====] Synthesis: Tested: 6 | Passing: 4 | Failing: 2 | Crashing: 1  diff --git a/samples/outputs/theories.cc.bin.out.expected b/samples/outputs/theories.cc.bin.out.expected deleted file mode 100644 index e69de29b..00000000 diff --git a/samples/theories.c b/samples/theories.c index b4ca6d26..0bbe7cc2 100644 --- a/samples/theories.c +++ b/samples/theories.c @@ -98,6 +98,9 @@ Theory((char c, bool b, short s, int i, long l, long long ll, float f, double d, cr_assert_str_eq(str, "test"); cr_assert_str_eq(cstr, "other test"); cr_assert_eq(obj->foo, 42); + + // abort to see the formatted string of all parameters + cr_assert_fail(); } // Manually generate datapoints diff --git a/samples/theories.cc b/samples/theories.cc index 23c0ebc5..56027542 100644 --- a/samples/theories.cc +++ b/samples/theories.cc @@ -106,6 +106,9 @@ Theory((char c, bool b, short s, int i, long l, long long ll, float f, double d, cr_assert_str_eq(str, "test"); cr_assert_str_eq(cstr, "other test"); cr_assert_eq(obj->foo, 42); + + // abort to see the formatted string of all parameters + cr_assert_fail(); } // Manually generate datapoints From c546bcef5ca93971214398dd3bdd16cd59756be6 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Sat, 26 Sep 2015 17:02:28 +0200 Subject: [PATCH 041/211] Added valgrind error suppression for the runner process --- CMakeLists.txt | 7 ++++++- src/config.h.in | 1 + src/core/runner.c | 11 +++++++++++ 3 files changed, 18 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index d3c65a70..09923a39 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -51,9 +51,14 @@ endif() # Setup coveralls -option(CTESTS "Turn on the samples and test" OFF) option(COVERALLS "Turn on coveralls support" OFF) option(COVERALLS_UPLOAD "Upload the generated coveralls json" ON) +option(DEV_BUILD "Compile in developer mode" OFF) +option(CTESTS "Turn on the samples and test" ${DEV_BUILD}) + +if (DEV_BUILD) + set(ENABLE_VALGRIND_ERRORS 1) +endif () if (COVERALLS) include(Coveralls) diff --git a/src/config.h.in b/src/config.h.in index 5928b0bd..fef0a5c9 100644 --- a/src/config.h.in +++ b/src/config.h.in @@ -3,6 +3,7 @@ #cmakedefine ENABLE_NLS @ENABLE_NLS@ #cmakedefine HAVE_PCRE @HAVE_PCRE@ +#cmakedefine ENABLE_VALGRIND_ERRORS @ENABLE_VALGRIND_ERRORS@ # define LOCALEDIR "${LOCALEDIR}" # define PACKAGE "${PROJECT_NAME}" diff --git a/src/core/runner.c b/src/core/runner.c index f0ae80b5..92fdb5f8 100644 --- a/src/core/runner.c +++ b/src/core/runner.c @@ -158,6 +158,10 @@ struct criterion_test_set *criterion_init(void) { void run_test_child(struct criterion_test *test, struct criterion_suite *suite) { +#ifndef ENABLE_VALGRIND_ERRORS + VALGRIND_ENABLE_ERROR_REPORTING; +#endif + if (suite->data && suite->data->timeout != 0 && test->data->timeout == 0) setup_timeout((uint64_t) (suite->data->timeout * 1e9)); else if (test->data->timeout != 0) @@ -335,6 +339,9 @@ void disable_unmatching(struct criterion_test_set *set) { struct criterion_test_set *criterion_initialize(void) { init_i18n(); +#ifndef ENABLE_VALGRIND_ERRORS + VALGRIND_DISABLE_ERROR_REPORTING; +#endif if (RUNNING_ON_VALGRIND) { criterion_options.no_early_exit = 1; criterion_options.jobs = 1; @@ -348,6 +355,10 @@ struct criterion_test_set *criterion_initialize(void) { void criterion_finalize(struct criterion_test_set *set) { sfree(set); + +#ifndef ENABLE_VALGRIND_ERRORS + VALGRIND_ENABLE_ERROR_REPORTING; +#endif } static void run_tests_async(struct criterion_test_set *set, From 49106f491610fc34c1b60f56f60eb3176349caa7 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Sat, 26 Sep 2015 17:36:39 +0200 Subject: [PATCH 042/211] Made child processes finalize and exit before returning from criterion_run_all_tests --- src/core/runner.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/core/runner.c b/src/core/runner.c index ea1a7fec..cd9c7967 100644 --- a/src/core/runner.c +++ b/src/core/runner.c @@ -419,5 +419,10 @@ int criterion_run_all_tests(struct criterion_test_set *set) { int res = criterion_run_all_tests_impl(set); unset_runner_process(); + if (res == -1) { + criterion_finalize(set); + exit(0); + } + return criterion_options.always_succeed || res; } From f1dfff5756378d775fc6523a08ef3461811accc3 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Sat, 26 Sep 2015 18:48:15 +0200 Subject: [PATCH 043/211] Abort the runner when failing in the middle of reading an event --- src/io/event.c | 53 +++++++++++++++++++++----------------------------- 1 file changed, 22 insertions(+), 31 deletions(-) diff --git a/src/io/event.c b/src/io/event.c index 4760020d..8bb6a95b 100644 --- a/src/io/event.c +++ b/src/io/event.c @@ -44,14 +44,24 @@ void destroy_assert_event(void *ptr, UNUSED void *meta) { free(ev->data); } +#ifdef __GNUC__ +# define unlikely(x) __builtin_expect((x),0) +#else +# define unlikely(x) (x) +#endif + +#define ASSERT(Cond) \ + do { \ + if (unlikely(Cond)) \ + abort(); \ + } while (0) + struct event *read_event(FILE *f) { unsigned kind; - if (fread(&kind, sizeof (unsigned), 1, f) == 0) - return NULL; + ASSERT(fread(&kind, sizeof (unsigned), 1, f) == 0); unsigned long long pid; - if (fread(&pid, sizeof (unsigned long long), 1, f) == 0) - return NULL; + ASSERT(fread(&pid, sizeof (unsigned long long), 1, f) == 0); switch (kind) { case ASSERT: { @@ -60,16 +70,13 @@ struct event *read_event(FILE *f) { char *msg = NULL; buf = malloc(assert_size); - if (fread(buf, assert_size, 1, f) == 0) - goto fail_assert; + ASSERT(fread(buf, assert_size, 1, f) == 0); size_t len = 0; - if (fread(&len, sizeof (size_t), 1, f) == 0) - goto fail_assert; + ASSERT(fread(&len, sizeof (size_t), 1, f) == 0); msg = malloc(len); - if (fread(msg, len, 1, f) == 0) - goto fail_assert; + ASSERT(fread(msg, len, 1, f) == 0); buf->message = msg; @@ -79,22 +86,13 @@ struct event *read_event(FILE *f) { ); *ev = (struct event) { .pid = pid, .kind = kind, .data = buf }; return ev; - -fail_assert: - free(buf); - free(msg); - return NULL; } case THEORY_FAIL: { size_t len = 0; - if (fread(&len, sizeof (size_t), 1, f) == 0) - return NULL; + ASSERT(fread(&len, sizeof (size_t), 1, f) == 0); char *buf = malloc(len); - if (fread(buf, len, 1, f) == 0) { - free(buf); - return NULL; - } + ASSERT(fread(buf, len, 1, f) == 0); struct event *ev = smalloc( .size = sizeof (struct event), @@ -105,10 +103,7 @@ struct event *read_event(FILE *f) { } case POST_TEST: { double *elapsed_time = malloc(sizeof (double)); - if (fread(elapsed_time, sizeof (double), 1, f) == 0) { - free(elapsed_time); - return NULL; - } + ASSERT(fread(elapsed_time, sizeof (double), 1, f) == 0); struct event *ev = smalloc( .size = sizeof (struct event), @@ -119,10 +114,7 @@ struct event *read_event(FILE *f) { } case WORKER_TERMINATED: { struct worker_status *status = malloc(sizeof (struct worker_status)); - if (fread(status, sizeof (struct worker_status), 1, f) == 0) { - free(status); - return NULL; - } + ASSERT(fread(status, sizeof (struct worker_status), 1, f) == 0); struct event *ev = smalloc( .size = sizeof (struct event), @@ -146,8 +138,7 @@ void send_event(int kind, void *data, size_t size) { memcpy(buf, &kind, sizeof (int)); memcpy(buf + sizeof (int), &pid, sizeof (pid)); memcpy(buf + sizeof (int) + sizeof (pid), data, size); - if (fwrite(buf, sizeof (int) + sizeof (pid) + size, 1, g_event_pipe) == 0) - abort(); + ASSERT(fwrite(buf, sizeof (int) + sizeof (pid) + size, 1, g_event_pipe) == 0); free(buf); } From 3fb26eb5056204bc4c45125f6522558e70ed8130 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Sun, 27 Sep 2015 01:20:27 +0200 Subject: [PATCH 044/211] [Issue #58] Switched event pipe IO to use native read/write syscalls --- src/compat/pipe-internal.h | 8 +++ src/compat/pipe.c | 129 +++++++++++++++++++++++++++++++++++++ src/compat/pipe.h | 9 +++ src/core/runner.c | 4 +- src/core/worker.c | 10 +-- src/core/worker.h | 4 +- src/io/event.c | 24 +++---- src/io/event.h | 4 +- 8 files changed, 169 insertions(+), 23 deletions(-) diff --git a/src/compat/pipe-internal.h b/src/compat/pipe-internal.h index 54a52422..17f114f3 100644 --- a/src/compat/pipe-internal.h +++ b/src/compat/pipe-internal.h @@ -35,4 +35,12 @@ struct pipe_handle { #endif }; +struct pipe_file_handle { +#ifdef VANILLA_WIN32 + HANDLE fh; +#else + int fd; +#endif +}; + #endif /* !PIPE_INTERNAL_H_ */ diff --git a/src/compat/pipe.c b/src/compat/pipe.c index 39167d97..23c4b4a7 100644 --- a/src/compat/pipe.c +++ b/src/compat/pipe.c @@ -182,6 +182,135 @@ void pipe_std_redirect(s_pipe_handle *pipe, enum criterion_std_fd fd) { #endif } +void close_pipe_file_handle(void *ptr, UNUSED void *meta) { + s_pipe_file_handle *h = ptr; +#ifdef VANILLA_WIN32 + CloseHandle(h->fh); +#else + close(h->fd); +#endif +} + +#ifdef VANILLA_WIN32 +static HANDLE win_dup(HANDLE h) { + HANDLE dup; + DuplicateHandle(GetCurrentProcess(), + h, + GetCurrentProcess(), + &dup, + 0, + TRUE, + DUPLICATE_SAME_ACCESS); + return dup; +} +#endif + +s_pipe_file_handle *pipe_out_handle(s_pipe_handle *p, enum pipe_opt opts) { +#ifdef VANILLA_WIN32 + if (opts & PIPE_CLOSE) + CloseHandle(p->fhs[0]); + HANDLE fh = p->fhs[1]; + if (opts & PIPE_DUP) + fh = win_dup(fh); + + s_pipe_file_handle *h = smalloc( + .size = sizeof (s_pipe_file_handle), + .dtor = close_pipe_file_handle); + + h->fh = fh; + return h; +#else + if (opts & PIPE_CLOSE) + close(p->fds[0]); + int fd = p->fds[1]; + if (opts & PIPE_DUP) + fd = dup(fd); + + s_pipe_file_handle *h = smalloc( + .size = sizeof (s_pipe_file_handle), + .dtor = close_pipe_file_handle); + + h->fd = fd; + return h; +#endif +} + +s_pipe_file_handle *pipe_in_handle(s_pipe_handle *p, enum pipe_opt opts) { +#ifdef VANILLA_WIN32 + if (opts & PIPE_CLOSE) + CloseHandle(p->fhs[1]); + HANDLE fh = p->fhs[0]; + if (opts & PIPE_DUP) + fh = win_dup(fh); + + s_pipe_file_handle *h = smalloc( + .size = sizeof (s_pipe_file_handle), + .dtor = close_pipe_file_handle); + + h->fh = fh; + return h; +#else + if (opts & PIPE_CLOSE) + close(p->fds[1]); + int fd = p->fds[0]; + if (opts & PIPE_DUP) + fd = dup(fd); + + s_pipe_file_handle *h = smalloc( + .size = sizeof (s_pipe_file_handle), + .dtor = close_pipe_file_handle); + + h->fd = fd; + return h; +#endif +} + +int pipe_write(const void *buf, size_t size, s_pipe_file_handle *pipe) { +#ifdef VANILLA_WIN32 + DWORD written = 0; + size_t off = 0; + while (size > 0) { + if (!WriteFile(pipe->fh, (const char *) buf + off, size, &written, NULL)) + return -1; + size -= written; + off += written; + } + if (off > 0) + return 1; + return 0; +#else + ssize_t res = write(pipe->fd, buf, size); + if (res < 0) + return -1; + if (res > 0) + return 1; + return 0; +#endif +} + +int pipe_read(void *buf, size_t size, s_pipe_file_handle *pipe) { +#ifdef VANILLA_WIN32 + DWORD read = 0; + size_t off = 0; + while (size > 0) { + if (!ReadFile(pipe->fh, (char *) buf + off, size, &read, NULL)) + return -1; + size -= read; + off += read; + } + if (off > 0) + return 1; + return 0; +#else + ssize_t res = read(pipe->fd, buf, size); + if (res < 0) + return -1; + if (res > 0) + return 1; + return 0; +#endif +} + static s_pipe_handle stdout_redir_; static s_pipe_handle stderr_redir_; static s_pipe_handle stdin_redir_; diff --git a/src/compat/pipe.h b/src/compat/pipe.h index c2f7d13a..148bb1e8 100644 --- a/src/compat/pipe.h +++ b/src/compat/pipe.h @@ -31,6 +31,9 @@ struct pipe_handle; typedef struct pipe_handle s_pipe_handle; +struct pipe_file_handle; +typedef struct pipe_file_handle s_pipe_file_handle; + enum pipe_end { PIPE_READ = 0, PIPE_WRITE = 1, @@ -51,9 +54,15 @@ s_pipe_handle *stdpipe(); FILE *pipe_in(s_pipe_handle *p, enum pipe_opt opts); FILE *pipe_out(s_pipe_handle *p, enum pipe_opt opts); +s_pipe_file_handle *pipe_out_handle(s_pipe_handle *p, enum pipe_opt opts); +s_pipe_file_handle *pipe_in_handle(s_pipe_handle *p, enum pipe_opt opts); + int stdpipe_options(s_pipe_handle *pipe, int id, int noblock); void pipe_std_redirect(s_pipe_handle *pipe, enum criterion_std_fd fd); +int pipe_write(const void *buf, size_t size, s_pipe_file_handle *pipe); +int pipe_read(void *buf, size_t size, s_pipe_file_handle *pipe); + INLINE FILE* get_std_file(enum criterion_std_fd fd_kind) { switch (fd_kind) { case CR_STDIN: return stdin; diff --git a/src/core/runner.c b/src/core/runner.c index cd9c7967..68148dcd 100644 --- a/src/core/runner.c +++ b/src/core/runner.c @@ -335,7 +335,7 @@ static void run_tests_async(struct criterion_test_set *set, size_t active_workers = 0; - FILE *event_pipe = pipe_in(g_worker_pipe, PIPE_DUP); + s_pipe_file_handle *event_pipe = pipe_in_handle(g_worker_pipe, PIPE_DUP); struct event *ev = NULL; // initialization of coroutine @@ -374,7 +374,7 @@ static void run_tests_async(struct criterion_test_set *set, ev = NULL; cleanup: - fclose(event_pipe); + sfree(event_pipe); sfree(ev); for (size_t i = 0; i < nb_workers; ++i) sfree(workers.workers[i]); diff --git a/src/core/worker.c b/src/core/worker.c index 8912b193..bbc26df8 100644 --- a/src/core/worker.c +++ b/src/core/worker.c @@ -48,14 +48,14 @@ bool is_runner(void) { static void close_process(void *ptr, UNUSED void *meta) { struct worker *proc = ptr; - fclose(proc->in); + sfree(proc->in); sfree(proc->ctx.suite_stats); sfree(proc->ctx.test_stats); sfree(proc->ctx.stats); sfree(proc->proc); } -struct event *worker_read_event(struct worker_set *workers, FILE *pipe) { +struct event *worker_read_event(struct worker_set *workers, s_pipe_file_handle *pipe) { struct event *ev = read_event(pipe); if (ev) { ev->worker_index = -1; @@ -76,10 +76,10 @@ struct event *worker_read_event(struct worker_set *workers, FILE *pipe) { void run_worker(struct worker_context *ctx) { cr_redirect_stdin(); - g_event_pipe = pipe_out(ctx->pipe, PIPE_CLOSE); + g_event_pipe = pipe_out_handle(ctx->pipe, PIPE_CLOSE); ctx->func(ctx->test, ctx->suite); - fclose(g_event_pipe); + sfree(g_event_pipe); fflush(NULL); // flush all opened streams if (criterion_options.no_early_exit) @@ -118,7 +118,7 @@ struct worker *spawn_test_worker(struct execution_context *ctx, *ptr = (struct worker) { .proc = proc, - .in = pipe_in(pipe, PIPE_DUP), + .in = pipe_in_handle(pipe, PIPE_DUP), .ctx = *ctx, }; return ptr; diff --git a/src/core/worker.h b/src/core/worker.h index 865ab966..95a6ab7f 100644 --- a/src/core/worker.h +++ b/src/core/worker.h @@ -49,7 +49,7 @@ struct execution_context { struct worker { int active; s_proc_handle *proc; - FILE *in; + s_pipe_file_handle *in; struct execution_context ctx; }; @@ -85,6 +85,6 @@ struct process_status get_status(int status); struct worker *spawn_test_worker(struct execution_context *ctx, f_worker_func func, s_pipe_handle *pipe); -struct event *worker_read_event(struct worker_set *workers, FILE *pipe); +struct event *worker_read_event(struct worker_set *workers, s_pipe_file_handle *pipe); #endif /* !PROCESS_H_ */ diff --git a/src/io/event.c b/src/io/event.c index 8bb6a95b..fd7623c5 100644 --- a/src/io/event.c +++ b/src/io/event.c @@ -31,7 +31,7 @@ #include "core/worker.h" #include "event.h" -FILE *g_event_pipe = NULL; +s_pipe_file_handle *g_event_pipe = NULL; void destroy_event(void *ptr, UNUSED void *meta) { struct event *ev = ptr; @@ -56,12 +56,12 @@ void destroy_assert_event(void *ptr, UNUSED void *meta) { abort(); \ } while (0) -struct event *read_event(FILE *f) { +struct event *read_event(s_pipe_file_handle *f) { unsigned kind; - ASSERT(fread(&kind, sizeof (unsigned), 1, f) == 0); + ASSERT(pipe_read(&kind, sizeof (unsigned), f) == 0); unsigned long long pid; - ASSERT(fread(&pid, sizeof (unsigned long long), 1, f) == 0); + ASSERT(pipe_read(&pid, sizeof (unsigned long long), f) == 0); switch (kind) { case ASSERT: { @@ -70,13 +70,13 @@ struct event *read_event(FILE *f) { char *msg = NULL; buf = malloc(assert_size); - ASSERT(fread(buf, assert_size, 1, f) == 0); + ASSERT(pipe_read(buf, assert_size, f) == 0); size_t len = 0; - ASSERT(fread(&len, sizeof (size_t), 1, f) == 0); + ASSERT(pipe_read(&len, sizeof (size_t), f) == 0); msg = malloc(len); - ASSERT(fread(msg, len, 1, f) == 0); + ASSERT(pipe_read(msg, len, f) == 0); buf->message = msg; @@ -89,10 +89,10 @@ struct event *read_event(FILE *f) { } case THEORY_FAIL: { size_t len = 0; - ASSERT(fread(&len, sizeof (size_t), 1, f) == 0); + ASSERT(pipe_read(&len, sizeof (size_t), f) == 0); char *buf = malloc(len); - ASSERT(fread(buf, len, 1, f) == 0); + ASSERT(pipe_read(buf, len, f) == 0); struct event *ev = smalloc( .size = sizeof (struct event), @@ -103,7 +103,7 @@ struct event *read_event(FILE *f) { } case POST_TEST: { double *elapsed_time = malloc(sizeof (double)); - ASSERT(fread(elapsed_time, sizeof (double), 1, f) == 0); + ASSERT(pipe_read(elapsed_time, sizeof (double), f) == 0); struct event *ev = smalloc( .size = sizeof (struct event), @@ -114,7 +114,7 @@ struct event *read_event(FILE *f) { } case WORKER_TERMINATED: { struct worker_status *status = malloc(sizeof (struct worker_status)); - ASSERT(fread(status, sizeof (struct worker_status), 1, f) == 0); + ASSERT(pipe_read(status, sizeof (struct worker_status), f) == 0); struct event *ev = smalloc( .size = sizeof (struct event), @@ -138,7 +138,7 @@ void send_event(int kind, void *data, size_t size) { memcpy(buf, &kind, sizeof (int)); memcpy(buf + sizeof (int), &pid, sizeof (pid)); memcpy(buf + sizeof (int) + sizeof (pid), data, size); - ASSERT(fwrite(buf, sizeof (int) + sizeof (pid) + size, 1, g_event_pipe) == 0); + ASSERT(pipe_write(buf, sizeof (int) + sizeof (pid) + size, g_event_pipe) == 0); free(buf); } diff --git a/src/io/event.h b/src/io/event.h index 641c9660..37818fb1 100644 --- a/src/io/event.h +++ b/src/io/event.h @@ -28,7 +28,7 @@ # include "core/worker.h" # include -extern FILE *g_event_pipe; +extern s_pipe_file_handle *g_event_pipe; struct event { unsigned long long pid; @@ -43,6 +43,6 @@ enum other_event_kinds { WORKER_TERMINATED = 1 << 30, }; -struct event *read_event(FILE *f); +struct event *read_event(s_pipe_file_handle *f); #endif /* !EVENT_H_ */ From 2d016b61f9292fca50d47e740ed523a8c9c3bfda Mon Sep 17 00:00:00 2001 From: Snaipe Date: Sun, 27 Sep 2015 02:36:28 +0200 Subject: [PATCH 045/211] Fixed the semantics of ASSERT in event IO --- src/io/event.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/io/event.c b/src/io/event.c index fd7623c5..3820ba3f 100644 --- a/src/io/event.c +++ b/src/io/event.c @@ -50,18 +50,18 @@ void destroy_assert_event(void *ptr, UNUSED void *meta) { # define unlikely(x) (x) #endif -#define ASSERT(Cond) \ - do { \ - if (unlikely(Cond)) \ - abort(); \ +#define ASSERT(Cond) \ + do { \ + if (unlikely(!(Cond))) \ + abort(); \ } while (0) struct event *read_event(s_pipe_file_handle *f) { unsigned kind; - ASSERT(pipe_read(&kind, sizeof (unsigned), f) == 0); + ASSERT(pipe_read(&kind, sizeof (unsigned), f) == 1); unsigned long long pid; - ASSERT(pipe_read(&pid, sizeof (unsigned long long), f) == 0); + ASSERT(pipe_read(&pid, sizeof (unsigned long long), f) == 1); switch (kind) { case ASSERT: { @@ -70,13 +70,13 @@ struct event *read_event(s_pipe_file_handle *f) { char *msg = NULL; buf = malloc(assert_size); - ASSERT(pipe_read(buf, assert_size, f) == 0); + ASSERT(pipe_read(buf, assert_size, f) == 1); size_t len = 0; - ASSERT(pipe_read(&len, sizeof (size_t), f) == 0); + ASSERT(pipe_read(&len, sizeof (size_t), f) == 1); msg = malloc(len); - ASSERT(pipe_read(msg, len, f) == 0); + ASSERT(pipe_read(msg, len, f) == 1); buf->message = msg; @@ -89,10 +89,10 @@ struct event *read_event(s_pipe_file_handle *f) { } case THEORY_FAIL: { size_t len = 0; - ASSERT(pipe_read(&len, sizeof (size_t), f) == 0); + ASSERT(pipe_read(&len, sizeof (size_t), f) == 1); char *buf = malloc(len); - ASSERT(pipe_read(buf, len, f) == 0); + ASSERT(pipe_read(buf, len, f) == 1); struct event *ev = smalloc( .size = sizeof (struct event), @@ -103,7 +103,7 @@ struct event *read_event(s_pipe_file_handle *f) { } case POST_TEST: { double *elapsed_time = malloc(sizeof (double)); - ASSERT(pipe_read(elapsed_time, sizeof (double), f) == 0); + ASSERT(pipe_read(elapsed_time, sizeof (double), f) == 1); struct event *ev = smalloc( .size = sizeof (struct event), @@ -114,7 +114,7 @@ struct event *read_event(s_pipe_file_handle *f) { } case WORKER_TERMINATED: { struct worker_status *status = malloc(sizeof (struct worker_status)); - ASSERT(pipe_read(status, sizeof (struct worker_status), f) == 0); + ASSERT(pipe_read(status, sizeof (struct worker_status), f) == 1); struct event *ev = smalloc( .size = sizeof (struct event), @@ -138,7 +138,7 @@ void send_event(int kind, void *data, size_t size) { memcpy(buf, &kind, sizeof (int)); memcpy(buf + sizeof (int), &pid, sizeof (pid)); memcpy(buf + sizeof (int) + sizeof (pid), data, size); - ASSERT(pipe_write(buf, sizeof (int) + sizeof (pid) + size, g_event_pipe) == 0); + ASSERT(pipe_write(buf, sizeof (int) + sizeof (pid) + size, g_event_pipe) == 1); free(buf); } From 0b38972f4dd14f4a59bfdd161bffba5fb622942a Mon Sep 17 00:00:00 2001 From: Snaipe Date: Sun, 27 Sep 2015 12:26:01 +0200 Subject: [PATCH 046/211] Used suggested string format from generated POT file --- po/fr.po | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/po/fr.po b/po/fr.po index 1fe53b1d..92ad06ab 100644 --- a/po/fr.po +++ b/po/fr.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: criterion 2.0.0\n" "Report-Msgid-Bugs-To: franklinmathieu+criterion@gmail.com\n" -"POT-Creation-Date: 2015-09-26 00:02+0200\n" +"POT-Creation-Date: 2015-09-27 12:24+0200\n" "PO-Revision-Date: 2015-04-03 17:58+0200\n" "Last-Translator: \n" "Language-Team: French\n" @@ -193,6 +193,6 @@ msgid "" "the number of jobs have been explicitely set. Reports might appear confusing!" "%2$s\n" msgstr "" -"%1$sAttention! Criterion a détecté qu'il a été lancé avec valgrind, mais " -"le nombre de tâches est explicitement défini. Les rapports d'erreur " -"risquent d'être déroutants!%2$s\n" +"%1$sAttention! Criterion a détecté qu'il a été lancé avec valgrind, mais le " +"nombre de tâches est explicitement défini. Les rapports d'erreur risquent " +"d'être déroutants!%2$s\n" From 906fec94446aa363bf9e0a6897e6aedfa4773a90 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Sun, 27 Sep 2015 13:59:40 +0200 Subject: [PATCH 047/211] Added parallel building and testing to speed up builds --- .travis.yml | 5 ++--- appveyor.yml | 7 +++++-- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/.travis.yml b/.travis.yml index 621b5a15..48b11f03 100644 --- a/.travis.yml +++ b/.travis.yml @@ -35,9 +35,8 @@ script: -DCMAKE_BUILD_TYPE=${CONFIGURATION} -DCMAKE_INSTALL_PREFIX=criterion-${TRAVIS_TAG} .. - - make - - make criterion_tests - - make test + - cmake --build . --target criterion_tests -- -j4 + - ctest -j4 after_success: - make gcov diff --git a/appveyor.yml b/appveyor.yml index 1f71d410..318deb8c 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -15,8 +15,11 @@ environment: matrix: - COMPILER: mingw GENERATOR: "MSYS Makefiles" + BUILD_OPT: -- -j4 - COMPILER: msvc GENERATOR: "Visual Studio 14 2015" + CFLAGS: /MP + CXXFLAGS: /MP clone_depth: 5 @@ -56,8 +59,8 @@ before_deploy: Push-AppveyorArtifact "../$archive.tar.bz2" test_script: - - cmake --build . --target criterion_tests - - ps: try { ctest } catch { type Testing/Temporary/LastTest.log } + - cmake --build . --target criterion_tests %BUILD_OPT% + - ps: try { ctest -j4 } catch { type Testing/Temporary/LastTest.log } #after_test: # - 'make coveralls' From 670e923b3f20fcbabe574d3cc997e3e81aece40f Mon Sep 17 00:00:00 2001 From: Snaipe Date: Sun, 27 Sep 2015 14:06:23 +0200 Subject: [PATCH 048/211] Reduced number of cmake parallel jobs on appveyor to 2 --- appveyor.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 318deb8c..9c77ac6c 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -15,7 +15,7 @@ environment: matrix: - COMPILER: mingw GENERATOR: "MSYS Makefiles" - BUILD_OPT: -- -j4 + BUILD_OPT: -- -j2 - COMPILER: msvc GENERATOR: "Visual Studio 14 2015" CFLAGS: /MP @@ -60,7 +60,7 @@ before_deploy: test_script: - cmake --build . --target criterion_tests %BUILD_OPT% - - ps: try { ctest -j4 } catch { type Testing/Temporary/LastTest.log } + - ps: try { ctest -j2 } catch { type Testing/Temporary/LastTest.log } #after_test: # - 'make coveralls' From ee4e811bd0b68cb923f7c426448392fb7e23282e Mon Sep 17 00:00:00 2001 From: Snaipe Date: Sun, 27 Sep 2015 14:15:23 +0200 Subject: [PATCH 049/211] Removed parallelization on mingw builds on appveyor --- appveyor.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 9c77ac6c..ae991136 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -15,7 +15,6 @@ environment: matrix: - COMPILER: mingw GENERATOR: "MSYS Makefiles" - BUILD_OPT: -- -j2 - COMPILER: msvc GENERATOR: "Visual Studio 14 2015" CFLAGS: /MP @@ -59,7 +58,7 @@ before_deploy: Push-AppveyorArtifact "../$archive.tar.bz2" test_script: - - cmake --build . --target criterion_tests %BUILD_OPT% + - cmake --build . --target criterion_tests - ps: try { ctest -j2 } catch { type Testing/Temporary/LastTest.log } #after_test: From 3fe7b41256704ea9263373aae13546457836194c Mon Sep 17 00:00:00 2001 From: Snaipe Date: Sun, 27 Sep 2015 23:49:22 +0200 Subject: [PATCH 050/211] [Issue #59] Added more explicit abort messages --- include/criterion/logging.h | 4 ++++ src/compat/alloc.c | 3 ++- src/compat/pipe.h | 2 ++ src/compat/process.c | 7 ++++++- src/core/runner.c | 6 +++++- src/core/worker.c | 4 ++++ src/io/event.c | 11 +++++++---- src/log/logging.c | 17 ++++++++++++++++- 8 files changed, 46 insertions(+), 8 deletions(-) diff --git a/include/criterion/logging.h b/include/criterion/logging.h index 17baf4b5..d823b9c7 100644 --- a/include/criterion/logging.h +++ b/include/criterion/logging.h @@ -47,6 +47,7 @@ enum criterion_logging_prefix { CRITERION_LOGGING_PREFIX_SKIP, CRITERION_LOGGING_PREFIX_PASS, CRITERION_LOGGING_PREFIX_FAIL, + CRITERION_LOGGING_PREFIX_ERR, }; struct criterion_prefix_data { @@ -82,6 +83,7 @@ extern const struct criterion_prefix_data g_criterion_logging_prefixes[]; # define CRITERION_PREFIX_SKIP (&g_criterion_logging_prefixes[CRITERION_LOGGING_PREFIX_SKIP ]) # define CRITERION_PREFIX_PASS (&g_criterion_logging_prefixes[CRITERION_LOGGING_PREFIX_PASS ]) # define CRITERION_PREFIX_FAIL (&g_criterion_logging_prefixes[CRITERION_LOGGING_PREFIX_FAIL ]) +# define CRITERION_PREFIX_ERR (&g_criterion_logging_prefixes[CRITERION_LOGGING_PREFIX_ERR ]) CR_API void criterion_vlog(enum criterion_logging_level level, const char *msg, va_list args); @@ -97,6 +99,8 @@ CR_API void criterion_log(enum criterion_logging_level level, const char *msg, . # define criterion_pinfo(...) criterion_plog(CRITERION_INFO, __VA_ARGS__) # define criterion_pimportant(...) criterion_plog(CRITERION_IMPORTANT, __VA_ARGS__) +# define criterion_perror(...) criterion_plog(CRITERION_IMPORTANT, CRITERION_PREFIX_ERR, __VA_ARGS__) + struct criterion_output_provider { void (*log_pre_all )(struct criterion_test_set *set); void (*log_pre_suite )(struct criterion_suite_set *set); diff --git a/src/compat/alloc.c b/src/compat/alloc.c index 7ae9d6d3..48d83f54 100644 --- a/src/compat/alloc.c +++ b/src/compat/alloc.c @@ -23,6 +23,7 @@ */ #include "alloc.h" #include "internal.h" +#include "criterion/logging.h" #include #ifdef VANILLA_WIN32 @@ -51,7 +52,7 @@ void init_inheritable_heap(void) { HeapDestroy(h->handle); if (g_heap == (HANDLE) NULL) { - fputs("Could not create the private inheritable heap.", stderr); + criterion_perror("Could not create the private inheritable heap.\n"); abort(); } } diff --git a/src/compat/pipe.h b/src/compat/pipe.h index 148bb1e8..f6a607e8 100644 --- a/src/compat/pipe.h +++ b/src/compat/pipe.h @@ -27,6 +27,7 @@ # include # include # include "common.h" +# include "criterion/logging.h" struct pipe_handle; typedef struct pipe_handle s_pipe_handle; @@ -69,6 +70,7 @@ INLINE FILE* get_std_file(enum criterion_std_fd fd_kind) { case CR_STDOUT: return stdout; case CR_STDERR: return stderr; } + criterion_perror("get_std_file: invalid parameter.\n"); abort(); } diff --git a/src/compat/process.c b/src/compat/process.c index 08b66255..4e6c2869 100644 --- a/src/compat/process.c +++ b/src/compat/process.c @@ -23,6 +23,7 @@ */ #include #include +#include #include #include "core/worker.h" #include "core/runner.h" @@ -133,8 +134,12 @@ static void handle_sigchld(UNUSED int sig) { memcpy(buf + sizeof (kind), &pid_ull, sizeof (pid_ull)); memcpy(buf + sizeof (kind) + sizeof (pid_ull), &ws, sizeof (ws)); - if (write(fd, &buf, sizeof (buf)) < (ssize_t) sizeof (buf)) + if (write(fd, &buf, sizeof (buf)) < (ssize_t) sizeof (buf)) { + criterion_perror("Could not write the WORKER_TERMINATED event " + "down the event pipe: %s.\n", + strerror(errno)); abort(); + } } } #endif diff --git a/src/core/runner.c b/src/core/runner.c index d12e3f82..ca72f179 100644 --- a/src/core/runner.c +++ b/src/core/runner.c @@ -24,6 +24,7 @@ #define CRITERION_LOGGING_COLORS #include #include +#include #include #include #include "criterion/criterion.h" @@ -437,8 +438,11 @@ static int criterion_run_all_tests_impl(struct criterion_test_set *set) { fflush(NULL); // flush everything before forking g_worker_pipe = stdpipe(); - if (g_worker_pipe == NULL) + if (g_worker_pipe == NULL) { + criterion_perror("Could not initialize the event pipe: %s.\n", + strerror(errno)); abort(); + } struct criterion_global_stats *stats = stats_init(); run_tests_async(set, stats); diff --git a/src/core/worker.c b/src/core/worker.c index bbc26df8..3a6240db 100644 --- a/src/core/worker.c +++ b/src/core/worker.c @@ -23,6 +23,7 @@ */ #include #include +#include #include #include "criterion/types.h" @@ -69,6 +70,8 @@ struct event *worker_read_event(struct worker_set *workers, s_pipe_file_handle * return ev; } } + criterion_perror("Could not link back the event PID to the active workers.\n"); + criterion_perror("The event pipe might have been corrupted.\n"); abort(); } return NULL; @@ -102,6 +105,7 @@ struct worker *spawn_test_worker(struct execution_context *ctx, s_proc_handle *proc = fork_process(); if (proc == (void *) -1) { + criterion_perror("Could not fork the current process and start a worker: %s.\n", strerror(errno)); abort(); } else if (proc == NULL) { run_worker(&g_worker_context); diff --git a/src/io/event.c b/src/io/event.c index 3820ba3f..2747f638 100644 --- a/src/io/event.c +++ b/src/io/event.c @@ -28,6 +28,7 @@ #include "criterion/stats.h" #include "criterion/common.h" #include "criterion/hooks.h" +#include "criterion/logging.h" #include "core/worker.h" #include "event.h" @@ -50,10 +51,12 @@ void destroy_assert_event(void *ptr, UNUSED void *meta) { # define unlikely(x) (x) #endif -#define ASSERT(Cond) \ - do { \ - if (unlikely(!(Cond))) \ - abort(); \ +#define ASSERT(Cond) \ + do { \ + if (unlikely(!(Cond))){ \ + criterion_perror("Corrupted event IO in the worker pipe.\n"); \ + abort(); \ + } \ } while (0) struct event *read_event(s_pipe_file_handle *f) { diff --git a/src/log/logging.c b/src/log/logging.c index 7ef465b8..a09b2d71 100644 --- a/src/log/logging.c +++ b/src/log/logging.c @@ -31,8 +31,10 @@ #ifdef ENABLE_NLS # define LOG_FORMAT "[%1$s%2$s%3$s] %4$s" +# define ERROR_FORMAT "[%1$s%2$s%3$s] %4$s%5$s%6$s%7$s" #else # define LOG_FORMAT "[%s%s%s] %s" +# define ERROR_FORMAT "[%s%s%s] %s%s%s%s" #endif const struct criterion_prefix_data g_criterion_logging_prefixes[] = { @@ -42,6 +44,7 @@ const struct criterion_prefix_data g_criterion_logging_prefixes[] = { [CRITERION_LOGGING_PREFIX_SKIP] = { "SKIP", CRIT_FG_GOLD }, [CRITERION_LOGGING_PREFIX_PASS] = { "PASS", CRIT_FG_GREEN }, [CRITERION_LOGGING_PREFIX_FAIL] = { "FAIL", CRIT_FG_RED }, + [CRITERION_LOGGING_PREFIX_ERR] = { "ERR ", CRIT_FG_RED }, { NULL, NULL } }; @@ -56,11 +59,23 @@ void criterion_plog(enum criterion_logging_level level, const struct criterion_p vsnprintf(formatted_msg, sizeof formatted_msg, msg, args); va_end(args); - fprintf(stderr, _(LOG_FORMAT), + if (prefix == &g_criterion_logging_prefixes[CRITERION_LOGGING_PREFIX_ERR]) { + fprintf(stderr, _(ERROR_FORMAT), + CRIT_COLOR_NORMALIZE(prefix->color), + prefix->prefix, + RESET, + FG_RED, + FG_BOLD, + formatted_msg, + RESET); + } else { + fprintf(stderr, _(LOG_FORMAT), CRIT_COLOR_NORMALIZE(prefix->color), prefix->prefix, RESET, formatted_msg); + } + } void criterion_log(enum criterion_logging_level level, const char *msg, ...) { From 218cd9ecfac6e195b37711b608167b6332e106eb Mon Sep 17 00:00:00 2001 From: Snaipe Date: Mon, 28 Sep 2015 12:26:40 +0200 Subject: [PATCH 051/211] Added /usr/local/include as a system include directory --- CMakeLists.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 09923a39..71ae77d2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -16,8 +16,9 @@ endif () add_subdirectory(dependencies/libcsptr/ EXCLUDE_FROM_ALL) add_subdirectory(dependencies/dyncall/ EXCLUDE_FROM_ALL) +include_directories(SYSTEM /usr/local/include) + include_directories( - /usr/local/include/ dependencies/libcsptr/include/ dependencies/dyncall/dyncall/ dependencies/valgrind/include/ From 9549db4fac82b5e8ac83ec30d33219d956144296 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Mon, 28 Sep 2015 13:30:02 +0200 Subject: [PATCH 052/211] [Issue #60] Added regression tests for theories --- samples/tests/CMakeLists.txt | 2 + .../theories_regression.c.bin.err.expected | 15 +++++ .../theories_regression.c.bin.out.expected | 0 .../theories_regression.cc.bin.err.expected | 15 +++++ .../theories_regression.cc.bin.out.expected | 0 samples/tests/theories_regression.c | 53 ++++++++++++++++++ samples/tests/theories_regression.cc | 55 +++++++++++++++++++ 7 files changed, 140 insertions(+) create mode 100644 samples/tests/outputs/theories_regression.c.bin.err.expected create mode 100644 samples/tests/outputs/theories_regression.c.bin.out.expected create mode 100644 samples/tests/outputs/theories_regression.cc.bin.err.expected create mode 100644 samples/tests/outputs/theories_regression.cc.bin.out.expected create mode 100644 samples/tests/theories_regression.c create mode 100644 samples/tests/theories_regression.cc diff --git a/samples/tests/CMakeLists.txt b/samples/tests/CMakeLists.txt index 463d4da7..388c5aef 100644 --- a/samples/tests/CMakeLists.txt +++ b/samples/tests/CMakeLists.txt @@ -3,11 +3,13 @@ set(SAMPLES exit.c long-messages.c other-crashes.c + theories_regression.c failmessages.cc exit.cc long-messages.cc other-crashes.cc + theories_regression.cc ) add_samples("${CMAKE_CURRENT_LIST_DIR}" "${SAMPLES}") diff --git a/samples/tests/outputs/theories_regression.c.bin.err.expected b/samples/tests/outputs/theories_regression.c.bin.err.expected new file mode 100644 index 00000000..c09ce14c --- /dev/null +++ b/samples/tests/outputs/theories_regression.c.bin.err.expected @@ -0,0 +1,15 @@ +[----] theories_regression.c:52: Assertion failed: The conditions for this assertion were not met. +[----] Theory theory::gen failed with the following parameters: (1) +[----] theories_regression.c:52: Assertion failed: The conditions for this assertion were not met. +[----] Theory theory::gen failed with the following parameters: (2) +[----] theories_regression.c:52: Assertion failed: The conditions for this assertion were not met. +[----] Theory theory::gen failed with the following parameters: (3) +[----] theories_regression.c:52: Assertion failed: The conditions for this assertion were not met. +[----] Theory theory::gen failed with the following parameters: (4) +[----] theories_regression.c:52: Assertion failed: The conditions for this assertion were not met. +[----] Theory theory::gen failed with the following parameters: (5) +[FAIL] theory::gen: (0.00s) +[----] theories_regression.c:35: Assertion failed: The conditions for this assertion were not met. +[----] Theory theory::misc failed with the following parameters: ('a', true, 1, 1, 1l, 1l, 3.14f, 3.14, "test", "other test") +[FAIL] theory::misc: (0.00s) +[====] Synthesis: Tested: 2 | Passing: 0 | Failing: 2 | Crashing: 0  diff --git a/samples/tests/outputs/theories_regression.c.bin.out.expected b/samples/tests/outputs/theories_regression.c.bin.out.expected new file mode 100644 index 00000000..e69de29b diff --git a/samples/tests/outputs/theories_regression.cc.bin.err.expected b/samples/tests/outputs/theories_regression.cc.bin.err.expected new file mode 100644 index 00000000..4c10ddd4 --- /dev/null +++ b/samples/tests/outputs/theories_regression.cc.bin.err.expected @@ -0,0 +1,15 @@ +[----] theories_regression.cc:54: Assertion failed: The conditions for this assertion were not met. +[----] Theory theory::gen failed with the following parameters: (1) +[----] theories_regression.cc:54: Assertion failed: The conditions for this assertion were not met. +[----] Theory theory::gen failed with the following parameters: (2) +[----] theories_regression.cc:54: Assertion failed: The conditions for this assertion were not met. +[----] Theory theory::gen failed with the following parameters: (3) +[----] theories_regression.cc:54: Assertion failed: The conditions for this assertion were not met. +[----] Theory theory::gen failed with the following parameters: (4) +[----] theories_regression.cc:54: Assertion failed: The conditions for this assertion were not met. +[----] Theory theory::gen failed with the following parameters: (5) +[FAIL] theory::gen: (0.00s) +[----] theories_regression.cc:37: Assertion failed: The conditions for this assertion were not met. +[----] Theory theory::misc failed with the following parameters: ('a', true, 1, 1, 1l, 1l, 3.14f, 3.14, "test", "other test") +[FAIL] theory::misc: (0.00s) +[====] Synthesis: Tested: 2 | Passing: 0 | Failing: 2 | Crashing: 0  diff --git a/samples/tests/outputs/theories_regression.cc.bin.out.expected b/samples/tests/outputs/theories_regression.cc.bin.out.expected new file mode 100644 index 00000000..e69de29b diff --git a/samples/tests/theories_regression.c b/samples/tests/theories_regression.c new file mode 100644 index 00000000..b8d4ca57 --- /dev/null +++ b/samples/tests/theories_regression.c @@ -0,0 +1,53 @@ +#ifdef _MSC_VER +#pragma warning(disable : 4090) +#endif + +#include + +// Testing for various parameters + +TheoryDataPoints(theory, misc) = { + DataPoints(char, 'a'), + DataPoints(bool, true), + DataPoints(short, 1), + DataPoints(int, 1), + DataPoints(long, 1), + DataPoints(long long, 1), + DataPoints(float, 3.14f), + DataPoints(double, 3.14), + DataPoints(char *, "test"), + DataPoints(const char *, "other test"), +}; + +Theory((char c, bool b, short s, int i, long l, long long ll, float f, double d, char *str, const char *cstr), theory, misc) { + cr_assert(b); + cr_assert_eq(c, 'a'); + cr_assert_eq(s, 1); + cr_assert_eq(i, 1); + cr_assert_eq(l, 1); + cr_assert_eq(ll, 1); + cr_assert_eq(f, 3.14f); + cr_assert_eq(d, 3.14); + cr_assert_str_eq(str, "test"); + cr_assert_str_eq(cstr, "other test"); + + // abort to see the formatted string of all parameters + cr_assert_fail(); +} + +// Manually generate datapoints + +TheoryDataPoints(theory, gen) = { + DataPoints(int, 0), // placeholder +}; + +static void generate_datapoints(void) { + static int arr[] = {1, 2, 3, 4, 5}; + TheoryDataPoint(theory, gen)[0].len = 5; + TheoryDataPoint(theory, gen)[0].arr = &arr; +} + +Theory((int i), theory, gen, .init = generate_datapoints) { + (void) i; + cr_assert_fail(); // we fail to display the parameter +} diff --git a/samples/tests/theories_regression.cc b/samples/tests/theories_regression.cc new file mode 100644 index 00000000..5bebea19 --- /dev/null +++ b/samples/tests/theories_regression.cc @@ -0,0 +1,55 @@ +#ifdef _MSC_VER +#pragma warning(disable : 4090) +#endif + +#include + +// Testing for various parameters + +char test_str[] = {'t', 'e', 's', 't', '\0'}; + +TheoryDataPoints(theory, misc) = { + DataPoints(char, 'a'), + DataPoints(bool, true), + DataPoints(short, 1), + DataPoints(int, 1), + DataPoints(long, 1), + DataPoints(long long, 1), + DataPoints(float, 3.14f), + DataPoints(double, 3.14), + DataPoints(char *, test_str), + DataPoints(const char *, "other test"), +}; + +Theory((char c, bool b, short s, int i, long l, long long ll, float f, double d, char *str, const char *cstr), theory, misc) { + cr_assert(b); + cr_assert_eq(c, 'a'); + cr_assert_eq(s, 1); + cr_assert_eq(i, 1); + cr_assert_eq(l, 1); + cr_assert_eq(ll, 1); + cr_assert_eq(f, 3.14f); + cr_assert_eq(d, 3.14); + cr_assert_str_eq(str, "test"); + cr_assert_str_eq(cstr, "other test"); + + // abort to see the formatted string of all parameters + cr_assert_fail(); +} + +// Manually generate datapoints + +TheoryDataPoints(theory, gen) = { + DataPoints(int, 0), // placeholder +}; + +static void generate_datapoints(void) { + static int arr[] = {1, 2, 3, 4, 5}; + TheoryDataPoint(theory, gen)[0].len = 5; + TheoryDataPoint(theory, gen)[0].arr = &arr; +} + +Theory((int i), theory, gen, .init = generate_datapoints) { + (void) i; + cr_assert_fail(); // we fail to display the parameter +} From 4352878db6a1acc7fe68e8c2e82c001f8118260d Mon Sep 17 00:00:00 2001 From: Snaipe Date: Mon, 28 Sep 2015 19:56:28 +0200 Subject: [PATCH 053/211] Fixed incorrect float comparison on MinGW-GCC for theory samples --- samples/tests/theories_regression.c | 7 +++++-- samples/tests/theories_regression.cc | 7 +++++-- samples/theories.c | 7 +++++-- samples/theories.cc | 7 +++++-- 4 files changed, 20 insertions(+), 8 deletions(-) diff --git a/samples/tests/theories_regression.c b/samples/tests/theories_regression.c index b8d4ca57..061c6de3 100644 --- a/samples/tests/theories_regression.c +++ b/samples/tests/theories_regression.c @@ -20,14 +20,17 @@ TheoryDataPoints(theory, misc) = { }; Theory((char c, bool b, short s, int i, long l, long long ll, float f, double d, char *str, const char *cstr), theory, misc) { + float reff = 3.14f; + double refd = 3.14; + cr_assert(b); cr_assert_eq(c, 'a'); cr_assert_eq(s, 1); cr_assert_eq(i, 1); cr_assert_eq(l, 1); cr_assert_eq(ll, 1); - cr_assert_eq(f, 3.14f); - cr_assert_eq(d, 3.14); + cr_assert_eq(f, reff); + cr_assert_eq(d, refd); cr_assert_str_eq(str, "test"); cr_assert_str_eq(cstr, "other test"); diff --git a/samples/tests/theories_regression.cc b/samples/tests/theories_regression.cc index 5bebea19..5bb020d2 100644 --- a/samples/tests/theories_regression.cc +++ b/samples/tests/theories_regression.cc @@ -22,14 +22,17 @@ TheoryDataPoints(theory, misc) = { }; Theory((char c, bool b, short s, int i, long l, long long ll, float f, double d, char *str, const char *cstr), theory, misc) { + float reff = 3.14f; + double refd = 3.14; + cr_assert(b); cr_assert_eq(c, 'a'); cr_assert_eq(s, 1); cr_assert_eq(i, 1); cr_assert_eq(l, 1); cr_assert_eq(ll, 1); - cr_assert_eq(f, 3.14f); - cr_assert_eq(d, 3.14); + cr_assert_eq(f, reff); + cr_assert_eq(d, refd); cr_assert_str_eq(str, "test"); cr_assert_str_eq(cstr, "other test"); diff --git a/samples/theories.c b/samples/theories.c index 0bbe7cc2..c918f4a7 100644 --- a/samples/theories.c +++ b/samples/theories.c @@ -87,14 +87,17 @@ TheoryDataPoints(theory, misc) = { }; Theory((char c, bool b, short s, int i, long l, long long ll, float f, double d, char *str, const char *cstr, struct my_object *obj), theory, misc) { + float reff = 3.14f; + double refd = 3.14; + cr_assert(b); cr_assert_eq(c, 'a'); cr_assert_eq(s, 1); cr_assert_eq(i, 1); cr_assert_eq(l, 1); cr_assert_eq(ll, 1); - cr_assert_eq(f, 3.14f); - cr_assert_eq(d, 3.14); + cr_assert_eq(f, reff); + cr_assert_eq(d, refd); cr_assert_str_eq(str, "test"); cr_assert_str_eq(cstr, "other test"); cr_assert_eq(obj->foo, 42); diff --git a/samples/theories.cc b/samples/theories.cc index 56027542..4ee981bf 100644 --- a/samples/theories.cc +++ b/samples/theories.cc @@ -95,14 +95,17 @@ TheoryDataPoints(theory, misc) = { }; Theory((char c, bool b, short s, int i, long l, long long ll, float f, double d, char *str, const char *cstr, struct my_object *obj), theory, misc) { + float reff = 3.14f; + double refd = 3.14; + cr_assert(b); cr_assert_eq(c, 'a'); cr_assert_eq(s, 1); cr_assert_eq(i, 1); cr_assert_eq(l, 1); cr_assert_eq(ll, 1); - cr_assert_eq(f, 3.14f); - cr_assert_eq(d, 3.14); + cr_assert_eq(f, reff); + cr_assert_eq(d, refd); cr_assert_str_eq(str, "test"); cr_assert_str_eq(cstr, "other test"); cr_assert_eq(obj->foo, 42); From fb6b0a6eaf3cef4e59ecb1e9af248da7586c38be Mon Sep 17 00:00:00 2001 From: Snaipe Date: Mon, 28 Sep 2015 22:01:51 +0200 Subject: [PATCH 054/211] Updated theory regression test output --- .../outputs/theories_regression.c.bin.err.expected | 14 +++++++------- .../theories_regression.cc.bin.err.expected | 14 +++++++------- samples/tests/theories_regression.c | 6 +----- samples/tests/theories_regression.cc | 6 +----- 4 files changed, 16 insertions(+), 24 deletions(-) diff --git a/samples/tests/outputs/theories_regression.c.bin.err.expected b/samples/tests/outputs/theories_regression.c.bin.err.expected index c09ce14c..0db8e129 100644 --- a/samples/tests/outputs/theories_regression.c.bin.err.expected +++ b/samples/tests/outputs/theories_regression.c.bin.err.expected @@ -1,15 +1,15 @@ -[----] theories_regression.c:52: Assertion failed: The conditions for this assertion were not met. +[----] theories_regression.c:51: Assertion failed: The conditions for this assertion were not met. [----] Theory theory::gen failed with the following parameters: (1) -[----] theories_regression.c:52: Assertion failed: The conditions for this assertion were not met. +[----] theories_regression.c:51: Assertion failed: The conditions for this assertion were not met. [----] Theory theory::gen failed with the following parameters: (2) -[----] theories_regression.c:52: Assertion failed: The conditions for this assertion were not met. +[----] theories_regression.c:51: Assertion failed: The conditions for this assertion were not met. [----] Theory theory::gen failed with the following parameters: (3) -[----] theories_regression.c:52: Assertion failed: The conditions for this assertion were not met. +[----] theories_regression.c:51: Assertion failed: The conditions for this assertion were not met. [----] Theory theory::gen failed with the following parameters: (4) -[----] theories_regression.c:52: Assertion failed: The conditions for this assertion were not met. +[----] theories_regression.c:51: Assertion failed: The conditions for this assertion were not met. [----] Theory theory::gen failed with the following parameters: (5) [FAIL] theory::gen: (0.00s) -[----] theories_regression.c:35: Assertion failed: The conditions for this assertion were not met. -[----] Theory theory::misc failed with the following parameters: ('a', true, 1, 1, 1l, 1l, 3.14f, 3.14, "test", "other test") +[----] theories_regression.c:34: Assertion failed: The conditions for this assertion were not met. +[----] Theory theory::misc failed with the following parameters: ('a', true, 1, 1, 3.14f, 3.14, "test", "other test") [FAIL] theory::misc: (0.00s) [====] Synthesis: Tested: 2 | Passing: 0 | Failing: 2 | Crashing: 0  diff --git a/samples/tests/outputs/theories_regression.cc.bin.err.expected b/samples/tests/outputs/theories_regression.cc.bin.err.expected index 4c10ddd4..a4e378ef 100644 --- a/samples/tests/outputs/theories_regression.cc.bin.err.expected +++ b/samples/tests/outputs/theories_regression.cc.bin.err.expected @@ -1,15 +1,15 @@ -[----] theories_regression.cc:54: Assertion failed: The conditions for this assertion were not met. +[----] theories_regression.cc:53: Assertion failed: The conditions for this assertion were not met. [----] Theory theory::gen failed with the following parameters: (1) -[----] theories_regression.cc:54: Assertion failed: The conditions for this assertion were not met. +[----] theories_regression.cc:53: Assertion failed: The conditions for this assertion were not met. [----] Theory theory::gen failed with the following parameters: (2) -[----] theories_regression.cc:54: Assertion failed: The conditions for this assertion were not met. +[----] theories_regression.cc:53: Assertion failed: The conditions for this assertion were not met. [----] Theory theory::gen failed with the following parameters: (3) -[----] theories_regression.cc:54: Assertion failed: The conditions for this assertion were not met. +[----] theories_regression.cc:53: Assertion failed: The conditions for this assertion were not met. [----] Theory theory::gen failed with the following parameters: (4) -[----] theories_regression.cc:54: Assertion failed: The conditions for this assertion were not met. +[----] theories_regression.cc:53: Assertion failed: The conditions for this assertion were not met. [----] Theory theory::gen failed with the following parameters: (5) [FAIL] theory::gen: (0.00s) -[----] theories_regression.cc:37: Assertion failed: The conditions for this assertion were not met. -[----] Theory theory::misc failed with the following parameters: ('a', true, 1, 1, 1l, 1l, 3.14f, 3.14, "test", "other test") +[----] theories_regression.cc:36: Assertion failed: The conditions for this assertion were not met. +[----] Theory theory::misc failed with the following parameters: ('a', true, 1, 1, 3.14f, 3.14, "test", "other test") [FAIL] theory::misc: (0.00s) [====] Synthesis: Tested: 2 | Passing: 0 | Failing: 2 | Crashing: 0  diff --git a/samples/tests/theories_regression.c b/samples/tests/theories_regression.c index 061c6de3..6661f9fd 100644 --- a/samples/tests/theories_regression.c +++ b/samples/tests/theories_regression.c @@ -11,15 +11,13 @@ TheoryDataPoints(theory, misc) = { DataPoints(bool, true), DataPoints(short, 1), DataPoints(int, 1), - DataPoints(long, 1), - DataPoints(long long, 1), DataPoints(float, 3.14f), DataPoints(double, 3.14), DataPoints(char *, "test"), DataPoints(const char *, "other test"), }; -Theory((char c, bool b, short s, int i, long l, long long ll, float f, double d, char *str, const char *cstr), theory, misc) { +Theory((char c, bool b, short s, int i, float f, double d, char *str, const char *cstr), theory, misc) { float reff = 3.14f; double refd = 3.14; @@ -27,8 +25,6 @@ Theory((char c, bool b, short s, int i, long l, long long ll, float f, double d, cr_assert_eq(c, 'a'); cr_assert_eq(s, 1); cr_assert_eq(i, 1); - cr_assert_eq(l, 1); - cr_assert_eq(ll, 1); cr_assert_eq(f, reff); cr_assert_eq(d, refd); cr_assert_str_eq(str, "test"); diff --git a/samples/tests/theories_regression.cc b/samples/tests/theories_regression.cc index 5bb020d2..608954fe 100644 --- a/samples/tests/theories_regression.cc +++ b/samples/tests/theories_regression.cc @@ -13,15 +13,13 @@ TheoryDataPoints(theory, misc) = { DataPoints(bool, true), DataPoints(short, 1), DataPoints(int, 1), - DataPoints(long, 1), - DataPoints(long long, 1), DataPoints(float, 3.14f), DataPoints(double, 3.14), DataPoints(char *, test_str), DataPoints(const char *, "other test"), }; -Theory((char c, bool b, short s, int i, long l, long long ll, float f, double d, char *str, const char *cstr), theory, misc) { +Theory((char c, bool b, short s, int i, float f, double d, char *str, const char *cstr), theory, misc) { float reff = 3.14f; double refd = 3.14; @@ -29,8 +27,6 @@ Theory((char c, bool b, short s, int i, long l, long long ll, float f, double d, cr_assert_eq(c, 'a'); cr_assert_eq(s, 1); cr_assert_eq(i, 1); - cr_assert_eq(l, 1); - cr_assert_eq(ll, 1); cr_assert_eq(f, reff); cr_assert_eq(d, refd); cr_assert_str_eq(str, "test"); From 93e766b3fe1ed412ce37b88c55b65500afafc64b Mon Sep 17 00:00:00 2001 From: Adeel Date: Tue, 29 Sep 2015 13:21:41 +0300 Subject: [PATCH 055/211] Deps: Mark UNUSED parameters in valgrind header. Clang on FreeBSD was complaining: ```csh [ 26%] Building C object CMakeFiles/criterion.dir/src/core/abort.c.o [ 30%] Building C object CMakeFiles/criterion.dir/src/core/report.c.o [ 30%] Building C object CMakeFiles/criterion.dir/src/core/runner.c.o In file included from /root/projects/Criterion/Criterion/Criterion/src/core/runner.c:29: /root/projects/Criterion/Criterion/Criterion/dependencies/valgrind/include/valgrind/valgrind.h:6223:29: error: unused parameter 'format' [-Werror,-Wunused-parameter] VALGRIND_PRINTF(const char *format, ...) ^ /root/projects/Criterion/Criterion/Criterion/dependencies/valgrind/include/valgrind/valgrind.h:6261:39: error: unused parameter 'format' [-Werror,-Wunused-parameter] VALGRIND_PRINTF_BACKTRACE(const char *format, ...) ^ 2 errors generated. ``` The other way to fix it was to add a compiler option in CMake: ```cmake add_compile_options(-Wno-unused-parameter) ``` but this approach disables the check globally. I am not sure whether there is a way to scope the compiler option to a subdirectory; especially in cases where submodule (via `add_subdirectory`) headers have unsed parameters. --- dependencies/valgrind/include/valgrind/valgrind.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/dependencies/valgrind/include/valgrind/valgrind.h b/dependencies/valgrind/include/valgrind/valgrind.h index 6954d751..bf5620a6 100644 --- a/dependencies/valgrind/include/valgrind/valgrind.h +++ b/dependencies/valgrind/include/valgrind/valgrind.h @@ -93,6 +93,7 @@ #include +#include /* Nb: this file might be included in a file compiled with -ansi. So we can't use C++ style "//" comments nor the "asm" keyword (instead @@ -6220,7 +6221,7 @@ static int #if defined(_MSC_VER) __inline #endif -VALGRIND_PRINTF(const char *format, ...) +VALGRIND_PRINTF(UNUSED const char *format, ...) { #if defined(NVALGRIND) return 0; @@ -6258,7 +6259,7 @@ static int #if defined(_MSC_VER) __inline #endif -VALGRIND_PRINTF_BACKTRACE(const char *format, ...) +VALGRIND_PRINTF_BACKTRACE(UNUSED const char *format, ...) { #if defined(NVALGRIND) return 0; From 4dcde5259cd241791f288da8c6864b2673c71ab7 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Thu, 1 Oct 2015 15:05:22 +0200 Subject: [PATCH 056/211] Added C/C++ language isolation wrappers --- CMakeLists.txt | 3 ++ include/criterion/criterion.h | 3 ++ include/criterion/types.h | 6 +++ src/core/runner.c | 35 +++---------- src/core/wrappers/wrap.c | 65 ++++++++++++++++++++++++ src/core/wrappers/wrap.cc | 96 +++++++++++++++++++++++++++++++++++ src/core/wrappers/wrap.h | 36 +++++++++++++ 7 files changed, 216 insertions(+), 28 deletions(-) create mode 100644 src/core/wrappers/wrap.c create mode 100644 src/core/wrappers/wrap.cc create mode 100644 src/core/wrappers/wrap.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 71ae77d2..8a9e1bb6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -40,6 +40,7 @@ add_definitions(-DCRITERION_BUILDING_DLL=1) if (NOT MSVC) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Werror -g -std=gnu99") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Werror -g -std=c++11") endif () if (MSVC) @@ -84,6 +85,8 @@ find_package(PCRE) # List sources and headers set(SOURCE_FILES + src/core/wrappers/wrap.c + src/core/wrappers/wrap.cc src/core/abort.c src/core/abort.h src/core/report.c diff --git a/include/criterion/criterion.h b/include/criterion/criterion.h index db9dfdcb..6182434a 100644 --- a/include/criterion/criterion.h +++ b/include/criterion/criterion.h @@ -36,9 +36,11 @@ # ifdef __cplusplus # define TEST_PROTOTYPE_(Category, Name) \ extern "C" void IDENTIFIER_(Category, Name, impl)(void) +# define CR_LANG CR_LANG_CPP # else # define TEST_PROTOTYPE_(Category, Name) \ void IDENTIFIER_(Category, Name, impl)(void) +# define CR_LANG CR_LANG_C # endif # define SUITE_IDENTIFIER_(Name, Suffix) \ @@ -49,6 +51,7 @@ TEST_PROTOTYPE_(Category, Name); \ struct criterion_test_extra_data IDENTIFIER_(Category, Name, extra) = \ CR_EXPAND(CRITERION_MAKE_STRUCT(struct criterion_test_extra_data, \ + .lang_ = CR_LANG, \ .kind_ = CR_TEST_NORMAL, \ .param_ = (struct criterion_test_params(*)(void)) NULL, \ .identifier_ = #Category "/" #Name, \ diff --git a/include/criterion/types.h b/include/criterion/types.h index a28d833f..33540981 100644 --- a/include/criterion/types.h +++ b/include/criterion/types.h @@ -35,6 +35,11 @@ using std::size_t; # endif # include "common.h" +enum criterion_language { + CR_LANG_C, + CR_LANG_CPP, +}; + enum criterion_test_kind { CR_TEST_NORMAL, CR_TEST_PARAMETERIZED, @@ -84,6 +89,7 @@ struct criterion_test_params { struct criterion_test_extra_data { int sentinel_; + enum criterion_language lang_; enum criterion_test_kind kind_; struct criterion_test_params (*param_)(void); const char *identifier_; diff --git a/src/core/runner.c b/src/core/runner.c index ca72f179..9e2d08e5 100644 --- a/src/core/runner.c +++ b/src/core/runner.c @@ -34,6 +34,7 @@ #include "compat/time.h" #include "compat/posix.h" #include "compat/processor.h" +#include "wrappers/wrap.h" #include "string/i18n.h" #include "io/event.h" #include "runner_coroutine.h" @@ -156,6 +157,11 @@ struct criterion_test_set *criterion_init(void) { return set; } +f_wrapper *g_wrappers[] = { + [CR_LANG_C] = c_wrap, + [CR_LANG_CPP] = cpp_wrap, +}; + void run_test_child(struct criterion_test *test, struct criterion_suite *suite) { @@ -168,34 +174,7 @@ void run_test_child(struct criterion_test *test, else if (test->data->timeout != 0) setup_timeout((uint64_t) (test->data->timeout * 1e9)); - send_event(PRE_INIT, NULL, 0); - if (suite->data) - (suite->data->init ? suite->data->init : nothing)(); - (test->data->init ? test->data->init : nothing)(); - send_event(PRE_TEST, NULL, 0); - - struct timespec_compat ts; - if (!setjmp(g_pre_test)) { - timer_start(&ts); - if (test->test) { - if (!test->data->param_) { - test->test(); - } else { - void(*param_test_func)(void *) = (void(*)(void*)) test->test; - param_test_func(g_worker_context.param->ptr); - } - } - } - - double elapsed_time; - if (!timer_end(&elapsed_time, &ts)) - elapsed_time = -1; - - send_event(POST_TEST, &elapsed_time, sizeof (double)); - (test->data->fini ? test->data->fini : nothing)(); - if (suite->data) - (suite->data->fini ? suite->data->fini : nothing)(); - send_event(POST_FINI, NULL, 0); + g_wrappers[test->data->lang_](test, suite); } #define push_event(Kind, ...) \ diff --git a/src/core/wrappers/wrap.c b/src/core/wrappers/wrap.c new file mode 100644 index 00000000..01acf622 --- /dev/null +++ b/src/core/wrappers/wrap.c @@ -0,0 +1,65 @@ +/* + * The MIT License (MIT) + * + * Copyright © 2015 Franklin "Snaipe" Mathieu + * + * 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. + */ +#include "core/abort.h" +#include "core/stats.h" +#include "core/worker.h" +#include "core/report.h" +#include "compat/time.h" +#include "io/event.h" +#include "wrap.h" + +static INLINE void nothing(void) {} + +void c_wrap(struct criterion_test *test, struct criterion_suite *suite) { + + send_event(PRE_INIT, NULL, 0); + if (suite->data) + (suite->data->init ? suite->data->init : nothing)(); + (test->data->init ? test->data->init : nothing)(); + send_event(PRE_TEST, NULL, 0); + + struct timespec_compat ts; + if (!setjmp(g_pre_test)) { + timer_start(&ts); + if (test->test) { + if (!test->data->param_) { + test->test(); + } else { + void(*param_test_func)(void *) = (void(*)(void*)) test->test; + param_test_func(g_worker_context.param->ptr); + } + } + } + + double elapsed_time; + if (!timer_end(&elapsed_time, &ts)) + elapsed_time = -1; + + send_event(POST_TEST, &elapsed_time, sizeof (double)); + (test->data->fini ? test->data->fini : nothing)(); + if (suite->data) + (suite->data->fini ? suite->data->fini : nothing)(); + send_event(POST_FINI, NULL, 0); + +} diff --git a/src/core/wrappers/wrap.cc b/src/core/wrappers/wrap.cc new file mode 100644 index 00000000..386e3eb5 --- /dev/null +++ b/src/core/wrappers/wrap.cc @@ -0,0 +1,96 @@ +/* + * The MIT License (MIT) + * + * Copyright © 2015 Franklin "Snaipe" Mathieu + * + * 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. + */ +#include +#include "criterion/assert.h" + +extern "C" { + +#include "core/abort.h" +#include "core/stats.h" +#include "core/worker.h" +#include "core/report.h" +#include "compat/time.h" +#include "io/event.h" +#include "wrap.h" + +static INLINE void nothing(void) {} + +void cpp_wrap(struct criterion_test *test, struct criterion_suite *suite) { + + send_event(PRE_INIT, NULL, 0); + try { + if (suite->data) + (suite->data->init ? suite->data->init : nothing)(); + (test->data->init ? test->data->init : nothing)(); + } catch (const std::exception &e) { + cr_assert_fail("Caught an unexpected exception during the test initialization: %s.", e.what()); + std::exit(1); + } catch (...) { + cr_assert_fail("Caught some unexpected exception during the test initialization."); + std::exit(1); + } + send_event(PRE_TEST, NULL, 0); + + struct timespec_compat ts; + if (!setjmp(g_pre_test)) { + timer_start(&ts); + if (test->test) { + try { + if (!test->data->param_) { + test->test(); + } else { + void(*param_test_func)(void *) = (void(*)(void*)) test->test; + param_test_func(g_worker_context.param->ptr); + } + } catch (const std::exception &e) { + cr_assert_fail("Caught an unexpected exception during the test execution: %s.", e.what()); + std::exit(1); + } catch (...) { + cr_assert_fail("Caught some unexpected exception during the test execution."); + std::exit(1); + } + } + } + + double elapsed_time; + if (!timer_end(&elapsed_time, &ts)) + elapsed_time = -1; + + send_event(POST_TEST, &elapsed_time, sizeof (double)); + try { + (test->data->fini ? test->data->fini : nothing)(); + if (suite->data) + (suite->data->fini ? suite->data->fini : nothing)(); + } catch (const std::exception &e) { + cr_assert_fail("Caught an unexpected exception during the test finalization: %s.", e.what()); + std::exit(1); + } catch (...) { + cr_assert_fail("Caught some unexpected exception during the test finalization."); + std::exit(1); + } + send_event(POST_FINI, NULL, 0); + +} + +} diff --git a/src/core/wrappers/wrap.h b/src/core/wrappers/wrap.h new file mode 100644 index 00000000..b7d518f4 --- /dev/null +++ b/src/core/wrappers/wrap.h @@ -0,0 +1,36 @@ +/* + * The MIT License (MIT) + * + * Copyright © 2015 Franklin "Snaipe" Mathieu + * + * 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 WRAP_H_ +# define WRAP_H_ + +# include "criterion/types.h" + +typedef void (f_wrapper)(struct criterion_test *, struct criterion_suite *); + +void c_wrap(struct criterion_test *test, struct criterion_suite *suite); +void cpp_wrap(struct criterion_test *test, struct criterion_suite *suite); + +extern f_wrapper *g_wrappers[]; + +#endif /* !WRAP_H_ */ From 55553a06814c02eece5a7e46181fc6e45ca6f8d2 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Thu, 1 Oct 2015 15:36:51 +0200 Subject: [PATCH 057/211] Cleaned up headers for wrap.cc --- src/core/wrappers/wrap.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/core/wrappers/wrap.cc b/src/core/wrappers/wrap.cc index 386e3eb5..f2ae058e 100644 --- a/src/core/wrappers/wrap.cc +++ b/src/core/wrappers/wrap.cc @@ -23,16 +23,16 @@ */ #include #include "criterion/assert.h" +#include "criterion/event.h" extern "C" { #include "core/abort.h" -#include "core/stats.h" -#include "core/worker.h" #include "core/report.h" +#include "core/worker.h" #include "compat/time.h" -#include "io/event.h" #include "wrap.h" +#include "common.h" static INLINE void nothing(void) {} From d4c306f7cd5ba3a6d544412b89a6e6a38b9711c6 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Thu, 1 Oct 2015 15:38:24 +0200 Subject: [PATCH 058/211] Fixed MinGW header bug where off_t/off64_t is not defined in io.h (See http://sourceforge.net/p/mingw/bugs/2024/) --- src/compat/internal.h | 8 ++++++++ src/compat/posix.h | 8 ++++++++ 2 files changed, 16 insertions(+) diff --git a/src/compat/internal.h b/src/compat/internal.h index 43ff62d8..551212b9 100644 --- a/src/compat/internal.h +++ b/src/compat/internal.h @@ -30,7 +30,15 @@ # undef _WIN32_WINNT # define _WIN32_WINNT 0x0502 # include +# if defined(__MINGW32__) || defined(__MINGW64__) +# define off_t _off_t +# define off64_t _off64_t +# endif # include +# if defined(__MINGW32__) || defined(__MINGW64__) +# undef off_t +# undef off64_t +# endif # include # include # include diff --git a/src/compat/posix.h b/src/compat/posix.h index 043562db..fc0e8d8a 100644 --- a/src/compat/posix.h +++ b/src/compat/posix.h @@ -40,7 +40,15 @@ # define _POSIX_SOURCE 1 # define TMP_POSIX # endif +# if defined(__MINGW32__) || defined(__MINGW64__) +# define off_t _off_t +# define off64_t _off64_t +# endif # include +# if defined(__MINGW32__) || defined(__MINGW64__) +# undef off_t +# undef off64_t +# endif # ifdef TMP_POSIX # undef _POSIX_SOURCE # undef TMP_POSIX From 547c77266b2cc935f045042d62efb25c5c0d9aef Mon Sep 17 00:00:00 2001 From: Snaipe Date: Thu, 1 Oct 2015 23:11:56 +0200 Subject: [PATCH 059/211] Added criterion_test_die to abort tests with a message on unhandled exceptions --- include/criterion/logging.h | 1 + po/fr.po | 22 ++++++++++++++++------ samples/tests/CMakeLists.txt | 2 ++ samples/tests/exception.cc | 18 ++++++++++++++++++ src/core/abort.c | 24 ++++++++++++++++++++++++ src/core/abort.h | 2 ++ src/core/report.h | 8 ++++---- src/core/runner.c | 17 +++++++++++++++++ src/core/worker.h | 1 + src/core/wrappers/wrap.cc | 18 ++++++------------ src/io/event.c | 16 ++++++++++++++++ src/io/event.h | 1 + src/log/normal.c | 30 ++++++++++++++++++++++++++++++ 13 files changed, 138 insertions(+), 22 deletions(-) create mode 100644 samples/tests/exception.cc diff --git a/include/criterion/logging.h b/include/criterion/logging.h index d823b9c7..2f8e1d9f 100644 --- a/include/criterion/logging.h +++ b/include/criterion/logging.h @@ -110,6 +110,7 @@ struct criterion_output_provider { void (*log_theory_fail )(struct criterion_theory_stats *stats); void (*log_test_timeout )(struct criterion_test_stats *stats); void (*log_test_crash )(struct criterion_test_stats *stats); + void (*log_test_abort )(struct criterion_test_stats *stats, const char *msg); void (*log_other_crash )(struct criterion_test_stats *stats); void (*log_abnormal_exit)(struct criterion_test_stats *stats); void (*log_post_test )(struct criterion_test_stats *stats); diff --git a/po/fr.po b/po/fr.po index 92ad06ab..65717ee0 100644 --- a/po/fr.po +++ b/po/fr.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: criterion 2.0.0\n" "Report-Msgid-Bugs-To: franklinmathieu+criterion@gmail.com\n" -"POT-Creation-Date: 2015-09-27 12:24+0200\n" +"POT-Creation-Date: 2015-10-01 23:09+0200\n" "PO-Revision-Date: 2015-04-03 17:58+0200\n" "Last-Translator: \n" "Language-Team: French\n" @@ -78,6 +78,11 @@ msgstr "%1$s::%2$s: PLANTAGE!\n" #: src/log/normal.c:64 #, fuzzy, c-format +msgid "%1$s::%2$s: %3$s\n" +msgstr "%1$s::%2$s: (%3$3.2fs)\n" + +#: src/log/normal.c:65 +#, fuzzy, c-format msgid "" "%1$sWarning! The test `%2$s::%3$s` crashed during its setup or teardown." "%4$s\n" @@ -85,7 +90,7 @@ msgstr "" "%1$sAttention! Le test `%2$s::%3$s` a planté pendant son initialisation ou " "sa finalisation.%4$s\n" -#: src/log/normal.c:65 +#: src/log/normal.c:66 #, fuzzy, c-format msgid "" "%1$sWarning! The test `%2$s::%3$s` exited during its setup or teardown.%4$s\n" @@ -93,14 +98,14 @@ msgstr "" "%1$sAttention! Le test `%2$s::%3$s` a quitté pendant son initialisation ou " "sa finalisation.%4$s\n" -#: src/log/normal.c:66 +#: src/log/normal.c:67 #, c-format msgid "Running %1$s%2$lu%3$s test from %4$s%5$s%6$s:\n" msgid_plural "Running %1$s%2$lu%3$s tests from %4$s%5$s%6$s:\n" msgstr[0] "Lancement de %1$s%2$lu%3$s test dans %4$s%5$s%6$s:\n" msgstr[1] "Lancement de %1$s%2$lu%3$s tests dans %4$s%5$s%6$s:\n" -#: src/log/normal.c:68 +#: src/log/normal.c:69 #, c-format msgid "" "%1$sSynthesis: Tested: %2$s%3$lu%4$s | Passing: %5$s%6$lu%7$s | Failing: %8$s" @@ -109,6 +114,11 @@ msgstr "" "%1$sSynthèse: Testés: %2$s%3$lu%4$s | Validés: %5$s%6$lu%7$s | Échoués: %8$s" "%9$lu%10$s | Plantages: %11$s%12$lu%13$s %14$s\n" +#: src/log/normal.c:85 +#, fuzzy, c-format +msgid "%s::%s: %s\n" +msgstr "%1$s::%2$s: (%3$3.2fs)\n" + #: src/string/i18n.c:13 msgid "The conditions for this assertion were not met." msgstr "Les conditions de cette assertion n'ont pas été remplies." @@ -175,7 +185,7 @@ msgstr "L'instruction `%1$s` a levé une instance de l'exception `%2$s`." msgid "The statement `%1$s` did not throw an instance of the `%2$s` exception." msgstr "L'instruction `%1$s` n'a pas levé d'instance de l'exception `%2$s`." -#: src/core/runner.c:54 +#: src/core/runner.c:56 #, c-format msgid "" "%1$sWarning! Criterion has detected that it is running under valgrind, but " @@ -186,7 +196,7 @@ msgstr "" "l'option no_early_exit est explicitement désactivée. Les rapports d'erreur " "ne seront pas précis!%2$s\n" -#: src/core/runner.c:58 +#: src/core/runner.c:60 #, c-format msgid "" "%1$sWarning! Criterion has detected that it is running under valgrind, but " diff --git a/samples/tests/CMakeLists.txt b/samples/tests/CMakeLists.txt index 388c5aef..b2d2fca4 100644 --- a/samples/tests/CMakeLists.txt +++ b/samples/tests/CMakeLists.txt @@ -10,6 +10,8 @@ set(SAMPLES long-messages.cc other-crashes.cc theories_regression.cc + + exception.cc ) add_samples("${CMAKE_CURRENT_LIST_DIR}" "${SAMPLES}") diff --git a/samples/tests/exception.cc b/samples/tests/exception.cc new file mode 100644 index 00000000..2cbf7f31 --- /dev/null +++ b/samples/tests/exception.cc @@ -0,0 +1,18 @@ +#include +#include + +void raise_std(void) { + throw std::invalid_argument("Some exception message"); +} + +void raise_any(void) { + throw 1; +} + +Test(exception, raise_std) { raise_std(); } +Test(exception, raise_any) { raise_any(); } + +Test(exception, raise_std_init, .init = raise_std) {} +Test(exception, raise_any_init, .init = raise_any) {} +Test(exception, raise_std_fini, .fini = raise_std) {} +Test(exception, raise_any_fini, .fini = raise_any) {} diff --git a/src/core/abort.c b/src/core/abort.c index 1124244c..d8d7c65e 100644 --- a/src/core/abort.c +++ b/src/core/abort.c @@ -21,10 +21,34 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ +#include #include "abort.h" +#include "criterion/asprintf-compat.h" +#include "io/event.h" jmp_buf g_pre_test; void criterion_abort_test(void) { longjmp(g_pre_test, 1); } + +void criterion_test_die(const char *msg, ...) { + va_list vl; + va_start(vl, msg); + char *formatted_msg = NULL; + int res = cr_vasprintf(&formatted_msg, msg, vl); + va_end(vl); + + if (res < 0) + abort(); + + size_t *buf = malloc(sizeof (size_t) + res + 1); + *buf = res + 1; + memcpy(buf + 1, formatted_msg, res + 1); + + send_event(TEST_ABORT, buf, sizeof (size_t) + res + 1); + free(buf); + free(formatted_msg); + + exit(0); +} diff --git a/src/core/abort.h b/src/core/abort.h index 064fe67d..401f09b7 100644 --- a/src/core/abort.h +++ b/src/core/abort.h @@ -29,4 +29,6 @@ extern jmp_buf g_pre_test; +void criterion_test_die(const char *msg, ...); + #endif /* !ABORT_H_ */ diff --git a/src/core/report.h b/src/core/report.h index bdcffac5..69f11266 100644 --- a/src/core/report.h +++ b/src/core/report.h @@ -45,9 +45,9 @@ DECL_CALL_REPORT_HOOKS(POST_FINI); DECL_CALL_REPORT_HOOKS(POST_SUITE); DECL_CALL_REPORT_HOOKS(POST_ALL); -#define log(Type, Arg) \ - log_(criterion_options.output_provider->log_ ## Type, Arg); -#define log_(Log, Arg) \ - (Log ? Log(Arg) : nothing()); +#define log(Type, ...) \ + log_(criterion_options.output_provider->log_ ## Type, __VA_ARGS__); +#define log_(Log, ...) \ + (Log ? Log(__VA_ARGS__) : nothing()); #endif /* !REPORT_H_ */ diff --git a/src/core/runner.c b/src/core/runner.c index 9e2d08e5..3ca32815 100644 --- a/src/core/runner.c +++ b/src/core/runner.c @@ -228,6 +228,18 @@ static void handle_worker_terminated(struct event *ev, log(post_fini, ctx->test_stats); } } else { + if (ctx->aborted) { + if (!ctx->normal_finish) { + double elapsed_time = 0; + push_event(POST_TEST, .data = &elapsed_time); + log(post_test, ctx->test_stats); + } + if (!ctx->cleaned_up) { + push_event(POST_FINI); + log(post_fini, ctx->test_stats); + } + return; + } if ((ctx->normal_finish && !ctx->cleaned_up) || !ctx->test_started) { log(abnormal_exit, ctx->test_stats); if (!ctx->test_started) { @@ -280,6 +292,11 @@ static void handle_event(struct event *ev) { report(ASSERT, ev->data); log(assert, ev->data); break; + case TEST_ABORT: + log(test_abort, ctx->test_stats, ev->data); + ctx->test_stats->failed = 1; + ctx->aborted = true; + break; case POST_TEST: report(POST_TEST, ctx->test_stats); log(post_test, ctx->test_stats); diff --git a/src/core/worker.h b/src/core/worker.h index 95a6ab7f..649e3eb1 100644 --- a/src/core/worker.h +++ b/src/core/worker.h @@ -38,6 +38,7 @@ struct execution_context { bool test_started; bool normal_finish; bool cleaned_up; + bool aborted; struct criterion_global_stats *stats; struct criterion_test *test; struct criterion_test_stats *test_stats; diff --git a/src/core/wrappers/wrap.cc b/src/core/wrappers/wrap.cc index f2ae058e..f6b140a6 100644 --- a/src/core/wrappers/wrap.cc +++ b/src/core/wrappers/wrap.cc @@ -44,11 +44,9 @@ void cpp_wrap(struct criterion_test *test, struct criterion_suite *suite) { (suite->data->init ? suite->data->init : nothing)(); (test->data->init ? test->data->init : nothing)(); } catch (const std::exception &e) { - cr_assert_fail("Caught an unexpected exception during the test initialization: %s.", e.what()); - std::exit(1); + criterion_test_die("Caught an unexpected exception during the test initialization: %s.", e.what()); } catch (...) { - cr_assert_fail("Caught some unexpected exception during the test initialization."); - std::exit(1); + criterion_test_die("Caught some unexpected exception during the test initialization."); } send_event(PRE_TEST, NULL, 0); @@ -64,11 +62,9 @@ void cpp_wrap(struct criterion_test *test, struct criterion_suite *suite) { param_test_func(g_worker_context.param->ptr); } } catch (const std::exception &e) { - cr_assert_fail("Caught an unexpected exception during the test execution: %s.", e.what()); - std::exit(1); + criterion_test_die("Caught an unexpected exception during the test execution: %s.", e.what()); } catch (...) { - cr_assert_fail("Caught some unexpected exception during the test execution."); - std::exit(1); + criterion_test_die("Caught some unexpected exception during the test execution."); } } } @@ -83,11 +79,9 @@ void cpp_wrap(struct criterion_test *test, struct criterion_suite *suite) { if (suite->data) (suite->data->fini ? suite->data->fini : nothing)(); } catch (const std::exception &e) { - cr_assert_fail("Caught an unexpected exception during the test finalization: %s.", e.what()); - std::exit(1); + criterion_test_die("Caught an unexpected exception during the test finalization: %s.", e.what()); } catch (...) { - cr_assert_fail("Caught some unexpected exception during the test finalization."); - std::exit(1); + criterion_test_die("Caught some unexpected exception during the test finalization."); } send_event(POST_FINI, NULL, 0); diff --git a/src/io/event.c b/src/io/event.c index 2747f638..99bdd00e 100644 --- a/src/io/event.c +++ b/src/io/event.c @@ -90,6 +90,22 @@ struct event *read_event(s_pipe_file_handle *f) { *ev = (struct event) { .pid = pid, .kind = kind, .data = buf }; return ev; } + case TEST_ABORT: { + char *msg = NULL; + + size_t len = 0; + ASSERT(pipe_read(&len, sizeof (size_t), f) == 1); + + msg = malloc(len); + ASSERT(pipe_read(msg, len, f) == 1); + + struct event *ev = smalloc( + .size = sizeof (struct event), + .dtor = destroy_event + ); + *ev = (struct event) { .pid = pid, .kind = kind, .data = msg }; + return ev; + } case THEORY_FAIL: { size_t len = 0; ASSERT(pipe_read(&len, sizeof (size_t), f) == 1); diff --git a/src/io/event.h b/src/io/event.h index 37818fb1..e4e555ba 100644 --- a/src/io/event.h +++ b/src/io/event.h @@ -41,6 +41,7 @@ struct event { enum other_event_kinds { WORKER_TERMINATED = 1 << 30, + TEST_ABORT, }; struct event *read_event(s_pipe_file_handle *f); diff --git a/src/log/normal.c b/src/log/normal.c index 3bb0c418..b48486aa 100644 --- a/src/log/normal.c +++ b/src/log/normal.c @@ -61,6 +61,7 @@ static msg_t msg_theory_fail = N_(" Theory %1$s::%2$s failed with the following static msg_t msg_test_timeout = N_("%1$s::%2$s: Timed out. (%3$3.2fs)\n"); static msg_t msg_test_crash_line = N_("%1$s%2$s%3$s:%4$s%5$u%6$s: Unexpected signal caught below this line!\n"); static msg_t msg_test_crash = N_("%1$s::%2$s: CRASH!\n"); +static msg_t msg_test_abort = N_("%1$s::%2$s: %3$s\n"); static msg_t msg_test_other_crash = N_("%1$sWarning! The test `%2$s::%3$s` crashed during its setup or teardown.%4$s\n"); static msg_t msg_test_abnormal_exit = N_("%1$sWarning! The test `%2$s::%3$s` exited during its setup or teardown.%4$s\n"); static msg_t msg_pre_suite[] = N_s("Running %1$s%2$lu%3$s test from %4$s%5$s%6$s:\n", @@ -81,6 +82,7 @@ static msg_t msg_theory_fail = " Theory %s::%s failed with the following parame static msg_t msg_test_timeout = "%s::%s: Timed out. (%3.2fs)\n"; static msg_t msg_test_crash_line = "%s%s%s:%s%u%s: Unexpected signal caught below this line!\n"; static msg_t msg_test_crash = "%s::%s: CRASH!\n"; +static msg_t msg_test_abort = N_("%s::%s: %s\n"); static msg_t msg_test_other_crash = "%sWarning! The test `%s::%s` crashed during its setup or teardown.%s\n"; static msg_t msg_test_abnormal_exit = "%sWarning! The test `%s::%s` exited during its setup or teardown.%s\n"; static msg_t msg_pre_suite[] = { "Running %s%lu%s test from %s%s%s:\n", @@ -230,6 +232,33 @@ void normal_log_test_timeout(UNUSED struct criterion_test_stats *stats) { stats->elapsed_time); } +void normal_log_test_abort(UNUSED struct criterion_test_stats *stats, const char *msg) { + + char *dup = strdup(msg); + +#ifdef VANILLA_WIN32 + char *line = strtok(dup, "\n"); +#else + char *saveptr = NULL; + char *line = strtok_r(dup, "\n", &saveptr); +#endif + + criterion_pimportant(CRITERION_PREFIX_DASHES, + _(msg_test_abort), + stats->test->category, + stats->test->name, + line); + +#ifdef VANILLA_WIN32 + while ((line = strtok(NULL, "\n"))) +#else + while ((line = strtok_r(NULL, "\n", &saveptr))) +#endif + criterion_pimportant(CRITERION_PREFIX_DASHES, _(msg_desc), line); + + free(dup); +} + struct criterion_output_provider normal_logging = { .log_pre_all = normal_log_pre_all, .log_pre_init = normal_log_pre_init, @@ -238,6 +267,7 @@ struct criterion_output_provider normal_logging = { .log_theory_fail = normal_log_theory_fail, .log_test_timeout = normal_log_test_timeout, .log_test_crash = normal_log_test_crash, + .log_test_abort = normal_log_test_abort, .log_other_crash = normal_log_other_crash, .log_abnormal_exit = normal_log_abnormal_exit, .log_post_test = normal_log_post_test, From 2d7c35b4f02266d6719e1e524c2855fea4337db4 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Thu, 1 Oct 2015 23:21:59 +0200 Subject: [PATCH 060/211] Set TERM=dumb when building on travis to get clean output --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 48b11f03..97c285a1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -35,7 +35,7 @@ script: -DCMAKE_BUILD_TYPE=${CONFIGURATION} -DCMAKE_INSTALL_PREFIX=criterion-${TRAVIS_TAG} .. - - cmake --build . --target criterion_tests -- -j4 + - TERM=dumb cmake --build . --target criterion_tests -- -j4 - ctest -j4 after_success: From 8197bef66c72a15c6d81ba1cefaafab748b16249 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Fri, 2 Oct 2015 00:58:38 +0200 Subject: [PATCH 061/211] Fixed assert message being freed too early, leading to some dangling pointers to invalid memory --- src/core/stats.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/core/stats.c b/src/core/stats.c index 488aa5c4..8980f2bb 100644 --- a/src/core/stats.c +++ b/src/core/stats.c @@ -184,6 +184,7 @@ static void push_assert(s_glob_stats *stats, s_assert_stats *dup = smalloc(sizeof (s_assert_stats)); memcpy(dup, data, sizeof (s_assert_stats)); + dup->message = strdup(data->message); dup->next = test->asserts; test->asserts = dup; From 12787b34bab2f514fa3424119fb6f71af849b1e5 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Fri, 2 Oct 2015 09:35:25 +0200 Subject: [PATCH 062/211] Added analytics in README --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 54ebc939..a9d2edb1 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,8 @@ [![License](https://img.shields.io/badge/license-MIT-blue.svg?style=flat)](https://github.com/Snaipe/Criterion/blob/master/LICENSE) [![Version](https://img.shields.io/github/tag/Snaipe/Criterion.svg?label=version&style=flat)](https://github.com/Snaipe/Criterion/releases) +![Analytics](https://ga-beacon.appspot.com/UA-68371536-1/Criterion/README.md?pixel) + A dead-simple, yet extensible, C and C++ unit testing framework. ![Screencast](./doc/screencast.gif) From 10c9e4eed28991a2c689efe682f5e97b4cb64292 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Fri, 2 Oct 2015 10:00:51 +0200 Subject: [PATCH 063/211] [Issues #65,#66] Delayed TAP output until the end of the tests --- include/criterion/stats.h | 1 + src/core/stats.c | 1 + src/log/tap.c | 75 ++++++++++++++++++++------------------- 3 files changed, 41 insertions(+), 36 deletions(-) diff --git a/include/criterion/stats.h b/include/criterion/stats.h index ec80c2ff..e21a50fc 100644 --- a/include/criterion/stats.h +++ b/include/criterion/stats.h @@ -45,6 +45,7 @@ struct criterion_test_stats { int exit_code; float elapsed_time; bool timed_out; + bool crashed; unsigned progress; const char *file; diff --git a/src/core/stats.c b/src/core/stats.c index 8980f2bb..bba2f8b2 100644 --- a/src/core/stats.c +++ b/src/core/stats.c @@ -232,6 +232,7 @@ static void push_test_crash(s_glob_stats *stats, s_test_stats *test, UNUSED void *ptr) { test->failed = 1; + test->crashed = 1; ++suite->tests_failed; ++suite->tests_crashed; ++stats->tests_failed; diff --git a/src/log/tap.c b/src/log/tap.c index 4615f707..3a482318 100644 --- a/src/log/tap.c +++ b/src/log/tap.c @@ -38,44 +38,22 @@ # define strdup _strdup #endif -void tap_log_pre_all(struct criterion_test_set *set) { - size_t enabled_count = 0; - FOREACH_SET(struct criterion_suite_set *s, set->suites) { - if ((s->suite.data && s->suite.data->disabled) || !s->tests) - continue; - - FOREACH_SET(struct criterion_test *test, s->tests) { - if (!test->data->disabled) - ++enabled_count; - } - } - criterion_important("TAP version 13\n1.." SIZE_T_FORMAT "\n", set->tests); +static void print_prelude(struct criterion_global_stats *stats) { + criterion_important("TAP version 13\n1.." SIZE_T_FORMAT "\n", stats->nb_tests); criterion_important("# Criterion v%s\n", VERSION); } -void tap_log_pre_suite(struct criterion_suite_set *set) { +static void print_pre_suite(struct criterion_suite_stats *stats) { criterion_important("\n# Running " SIZE_T_FORMAT " tests from %s\n", - set->tests->size, - set->suite.name); + stats->nb_tests, + stats->suite->name); } static INLINE bool is_disabled(struct criterion_test *t, struct criterion_suite *s) { return t->data->disabled || (s->data && s->data->disabled); } -void tap_log_post_suite(struct criterion_suite_stats *stats) { - for (struct criterion_test_stats *ts = stats->tests; ts; ts = ts->next) { - if (is_disabled(ts->test, stats->suite)) { - criterion_important("ok - %s::%s %s # SKIP %s is disabled\n", - ts->test->category, - ts->test->name, - DEF(ts->test->data->description, ""), - ts->test->data->disabled ? "test" : "suite"); - } - } -} - -void tap_log_post_test(struct criterion_test_stats *stats) { +static void print_test_normal(struct criterion_test_stats *stats) { const char *format = can_measure_time() ? "%s - %s::%s %s (%3.2fs)\n" : "%s - %s::%s %s\n"; criterion_important(format, @@ -109,7 +87,7 @@ void tap_log_post_test(struct criterion_test_stats *stats) { } } -void tap_log_test_crash(struct criterion_test_stats *stats) { +static void print_test_crashed(struct criterion_test_stats *stats) { bool sf = criterion_options.short_filename; criterion_important("not ok - %s::%s unexpected signal after %s:%u\n", stats->test->category, @@ -118,18 +96,43 @@ void tap_log_test_crash(struct criterion_test_stats *stats) { stats->progress); } -void tap_log_test_timeout(struct criterion_test_stats *stats) { +static void print_test_timeout(struct criterion_test_stats *stats) { criterion_important("not ok - %s::%s timed out (%3.2fs)\n", stats->test->category, stats->test->name, stats->elapsed_time); } +static void print_test(struct criterion_test_stats *ts, + struct criterion_suite_stats *ss) { + + if (is_disabled(ts->test, ss->suite)) { + criterion_important("ok - %s::%s %s # SKIP %s is disabled\n", + ts->test->category, + ts->test->name, + DEF(ts->test->data->description, ""), + ts->test->data->disabled ? "test" : "suite"); + } else if (ts->crashed) { + print_test_crashed(ts); + } else if (ts->timed_out) { + print_test_timeout(ts); + } else { + print_test_normal(ts); + } +} + +void tap_log_post_all(struct criterion_global_stats *stats) { + print_prelude(stats); + + for (struct criterion_suite_stats *ss = stats->suites; ss; ss = ss->next) { + print_pre_suite(ss); + + for (struct criterion_test_stats *ts = ss->tests; ts; ts = ts->next) { + print_test(ts, ss); + } + } +} + struct criterion_output_provider tap_logging = { - .log_pre_all = tap_log_pre_all, - .log_pre_suite = tap_log_pre_suite, - .log_test_crash = tap_log_test_crash, - .log_test_timeout = tap_log_test_timeout, - .log_post_test = tap_log_post_test, - .log_post_suite = tap_log_post_suite, + .log_post_all = tap_log_post_all, }; From 0d17ecc0f58e75510ff745be86ff6cf3c9e289b5 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Fri, 2 Oct 2015 14:45:28 +0200 Subject: [PATCH 064/211] Added missing header exports in CMake config --- CMakeLists.txt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 8a9e1bb6..7024e7ce 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -95,6 +95,7 @@ set(SOURCE_FILES src/core/runner.h src/core/runner_coroutine.c src/core/runner_coroutine.h + src/core/coroutine.h src/core/worker.c src/core/worker.h src/core/stats.c @@ -104,6 +105,7 @@ set(SOURCE_FILES src/compat/internal.h src/compat/pipe.c src/compat/pipe.h + src/compat/pipe-internal.h src/compat/section.c src/compat/section.h src/compat/process.c @@ -131,6 +133,8 @@ set(SOURCE_FILES src/entry/options.c src/entry/main.c src/entry/entry.c + src/common.h + src/config.h ) if (PCRE_FOUND) @@ -158,6 +162,8 @@ set(INTERFACE_FILES include/criterion/designated-initializer-compat.h include/criterion/preprocess.h include/criterion/alloc.h + include/criterion/parameterized.h + include/criterion/redirect.h ) # Generate the configure file From c3fdc08b02aa9cb3d1924047912f91c17798c871 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Fri, 2 Oct 2015 14:58:56 +0200 Subject: [PATCH 065/211] [Issue #64] Prefixed all unprefixed macros with CR_ --- .../valgrind/include/valgrind/valgrind.h | 4 +- include/criterion/abort.h | 2 +- include/criterion/asprintf-compat.h | 2 +- include/criterion/common.h | 82 +++++++++---------- include/criterion/criterion.h | 42 +++++----- include/criterion/hooks.h | 82 +++++++++---------- include/criterion/logging.h | 20 ++--- include/criterion/parameterized.h | 22 ++--- include/criterion/theories.h | 6 +- src/compat/pipe.c | 2 +- src/compat/process.c | 4 +- src/compat/section.h | 6 +- src/core/ordered-set.c | 4 +- src/core/report.c | 72 ++++++++-------- src/core/report.h | 2 +- src/core/runner.c | 20 ++--- src/core/runner.h | 4 +- src/core/stats.c | 22 ++--- src/core/worker.c | 2 +- src/entry/main.c | 4 +- src/io/event.c | 4 +- src/log/logging.c | 10 +-- src/log/normal.c | 38 ++++----- src/log/tap.c | 8 +- src/string/extmatch.c | 6 +- 25 files changed, 238 insertions(+), 232 deletions(-) diff --git a/dependencies/valgrind/include/valgrind/valgrind.h b/dependencies/valgrind/include/valgrind/valgrind.h index bf5620a6..9cfb7003 100644 --- a/dependencies/valgrind/include/valgrind/valgrind.h +++ b/dependencies/valgrind/include/valgrind/valgrind.h @@ -6221,7 +6221,7 @@ static int #if defined(_MSC_VER) __inline #endif -VALGRIND_PRINTF(UNUSED const char *format, ...) +VALGRIND_PRINTF(CR_UNUSED const char *format, ...) { #if defined(NVALGRIND) return 0; @@ -6259,7 +6259,7 @@ static int #if defined(_MSC_VER) __inline #endif -VALGRIND_PRINTF_BACKTRACE(UNUSED const char *format, ...) +VALGRIND_PRINTF_BACKTRACE(CR_UNUSED const char *format, ...) { #if defined(NVALGRIND) return 0; diff --git a/include/criterion/abort.h b/include/criterion/abort.h index 026289f2..449c0de4 100644 --- a/include/criterion/abort.h +++ b/include/criterion/abort.h @@ -28,7 +28,7 @@ CR_BEGIN_C_API -CR_API NORETURN void criterion_abort_test(void); +CR_API CR_NORETURN void criterion_abort_test(void); CR_INLINE static void criterion_continue_test(void) {} CR_END_C_API diff --git a/include/criterion/asprintf-compat.h b/include/criterion/asprintf-compat.h index 6f78efdd..e0316fe8 100644 --- a/include/criterion/asprintf-compat.h +++ b/include/criterion/asprintf-compat.h @@ -34,7 +34,7 @@ CR_BEGIN_C_API -FORMAT(printf, 2, 3) +CR_FORMAT(printf, 2, 3) CR_API int cr_asprintf(char **strp, const char *fmt, ...); CR_API int cr_vasprintf(char **strp, const char *fmt, va_list ap); diff --git a/include/criterion/common.h b/include/criterion/common.h index ae962eb7..41cc2ffa 100644 --- a/include/criterion/common.h +++ b/include/criterion/common.h @@ -52,74 +52,74 @@ # endif # ifdef __APPLE__ -# define SECTION_START_PREFIX __first -# define SECTION_END_PREFIX __last -# define SECTION_START_SUFFIX(Name) __asm("section$start$__DATA$" Name) -# define SECTION_END_SUFFIX(Name) __asm("section$end$__DATA$" Name) -# define SECTION_(Name) CR_ATTRIBUTE(section("__DATA," Name)) -# define SECTION_SUFFIX_ +# define CR_SECTION_START_PREFIX __first +# define CR_SECTION_END_PREFIX __last +# define CR_SECTION_START_SUFFIX(Name) __asm("section$start$__DATA$" Name) +# define CR_SECTION_END_SUFFIX(Name) __asm("section$end$__DATA$" Name) +# define CR_SECTION_(Name) CR_ATTRIBUTE(section("__DATA," Name)) +# define CR_SECTION_SUFFIX_ # elif CR_IS_MSVC -# define SECTION_START_PREFIX __start -# define SECTION_END_PREFIX __stop -# define SECTION_START_SUFFIX(Name) -# define SECTION_END_SUFFIX(Name) -# define SECTION_(Name) \ +# define CR_SECTION_START_PREFIX __start +# define CR_SECTION_END_PREFIX __stop +# define CR_SECTION_START_SUFFIX(Name) +# define CR_SECTION_END_SUFFIX(Name) +# define CR_SECTION_(Name) \ __pragma(data_seg(push)) \ __pragma(section(Name, read)) \ __declspec(allocate(Name)) -# define SECTION_SUFFIX_ \ +# define CR_SECTION_SUFFIX_ \ __pragma(data_seg(pop)) # else -# define SECTION_START_PREFIX __start -# define SECTION_END_PREFIX __stop -# define SECTION_START_SUFFIX(Name) -# define SECTION_END_SUFFIX(Name) -# define SECTION_(Name) CR_ATTRIBUTE(section(Name)) -# define SECTION_SUFFIX_ +# define CR_SECTION_START_PREFIX __start +# define CR_SECTION_END_PREFIX __stop +# define CR_SECTION_START_SUFFIX(Name) +# define CR_SECTION_END_SUFFIX(Name) +# define CR_SECTION_(Name) CR_ATTRIBUTE(section(Name)) +# define CR_SECTION_SUFFIX_ # endif -# define MAKE_IDENTIFIER_(Prefix, Id) MAKE_IDENTIFIER__(Prefix, Id) -# define MAKE_IDENTIFIER__(Prefix, Id) Prefix ## _ ## Id +# define CR_MAKE_IDENTIFIER_(Prefix, Id) CR_MAKE_IDENTIFIER__(Prefix, Id) +# define CR_MAKE_IDENTIFIER__(Prefix, Id) Prefix ## _ ## Id -# define SECTION_START_(Name) MAKE_IDENTIFIER_(SECTION_START_PREFIX, Name) -# define SECTION_END_(Name) MAKE_IDENTIFIER_(SECTION_END_PREFIX, Name) +# define CR_SECTION_START_(Name) CR_MAKE_IDENTIFIER_(CR_SECTION_START_PREFIX, Name) +# define CR_SECTION_END_(Name) CR_MAKE_IDENTIFIER_(CR_SECTION_END_PREFIX, Name) -# define SECTION_START(Name) g_ ## Name ## _section_start -# define SECTION_END(Name) g_ ## Name ## _section_end +# define CR_SECTION_START(Name) g_ ## Name ## _section_start +# define CR_SECTION_END(Name) g_ ## Name ## _section_end -# define DECL_SECTION_LIMITS(Type, Name) DECL_SECTION_LIMITS_(Type, Name) -# define DECL_SECTION_LIMITS_(Type, Name) \ - extern Type SECTION_START_(Name) SECTION_START_SUFFIX(#Name); \ - extern Type SECTION_END_(Name) SECTION_END_SUFFIX(#Name) +# define CR_DECL_SECTION_LIMITS(Type, Name) CR_DECL_SECTION_LIMITS_(Type, Name) +# define CR_DECL_SECTION_LIMITS_(Type, Name) \ + extern Type CR_SECTION_START_(Name) CR_SECTION_START_SUFFIX(#Name); \ + extern Type CR_SECTION_END_(Name) CR_SECTION_END_SUFFIX(#Name) -# define IMPL_SECTION_LIMITS(Type, Name) \ - Type *const SECTION_START(Name) = &SECTION_START_(Name); \ - Type *const SECTION_END(Name) = &SECTION_END_(Name) +# define CR_IMPL_SECTION_LIMITS(Type, Name) \ + Type *const CR_SECTION_START(Name) = &CR_SECTION_START_(Name); \ + Type *const CR_SECTION_END(Name) = &CR_SECTION_END_(Name) # ifdef __GNUC__ -# define UNUSED CR_ATTRIBUTE(unused) -# define NORETURN CR_ATTRIBUTE(noreturn) +# define CR_UNUSED CR_ATTRIBUTE(unused) +# define CR_NORETURN CR_ATTRIBUTE(noreturn) # define CR_INLINE CR_ATTRIBUTE(always_inline) inline # elif CR_IS_MSVC -# define UNUSED -# define NORETURN __declspec(noreturn) +# define CR_UNUSED +# define CR_NORETURN __declspec(noreturn) # define CR_INLINE __forceinline # else -# define UNUSED -# define NORETURN +# define CR_UNUSED +# define CR_NORETURN # define CR_INLINE inline # endif # ifdef _WIN32 -# define SIZE_T_FORMAT "%Iu" +# define CR_SIZE_T_FORMAT "%Iu" # else -# define SIZE_T_FORMAT "%zu" +# define CR_SIZE_T_FORMAT "%zu" # endif # ifdef __GNUC__ -# define FORMAT(Archetype, Index, Ftc) CR_ATTRIBUTE(format(Archetype, Index, Ftc)) +# define CR_FORMAT(Archetype, Index, Ftc) CR_ATTRIBUTE(format(Archetype, Index, Ftc)) # else -# define FORMAT(Archetype, Index, Ftc) +# define CR_FORMAT(Archetype, Index, Ftc) # endif # if defined _WIN32 || defined __CYGWIN__ diff --git a/include/criterion/criterion.h b/include/criterion/criterion.h index 6182434a..549cdcdd 100644 --- a/include/criterion/criterion.h +++ b/include/criterion/criterion.h @@ -30,26 +30,26 @@ # include "assert.h" # include "alloc.h" -# define IDENTIFIER_(Category, Name, Suffix) \ +# define CR_IDENTIFIER_(Category, Name, Suffix) \ Category ## _ ## Name ## _ ## Suffix # ifdef __cplusplus -# define TEST_PROTOTYPE_(Category, Name) \ - extern "C" void IDENTIFIER_(Category, Name, impl)(void) +# define CR_TEST_PROTOTYPE_(Category, Name) \ + extern "C" void CR_IDENTIFIER_(Category, Name, impl)(void) # define CR_LANG CR_LANG_CPP # else -# define TEST_PROTOTYPE_(Category, Name) \ - void IDENTIFIER_(Category, Name, impl)(void) +# define CR_TEST_PROTOTYPE_(Category, Name) \ + void CR_IDENTIFIER_(Category, Name, impl)(void) # define CR_LANG CR_LANG_C # endif -# define SUITE_IDENTIFIER_(Name, Suffix) \ +# define CR_SUITE_IDENTIFIER_(Name, Suffix) \ suite_ ## Name ## _ ## Suffix # define Test(...) CR_EXPAND(Test_(__VA_ARGS__, .sentinel_ = 0)) # define Test_(Category, Name, ...) \ - TEST_PROTOTYPE_(Category, Name); \ - struct criterion_test_extra_data IDENTIFIER_(Category, Name, extra) = \ + CR_TEST_PROTOTYPE_(Category, Name); \ + struct criterion_test_extra_data CR_IDENTIFIER_(Category, Name, extra) = \ CR_EXPAND(CRITERION_MAKE_STRUCT(struct criterion_test_extra_data, \ .lang_ = CR_LANG, \ .kind_ = CR_TEST_NORMAL, \ @@ -59,32 +59,32 @@ .line_ = __LINE__, \ __VA_ARGS__ \ )); \ - struct criterion_test IDENTIFIER_(Category, Name, meta) = { \ + struct criterion_test CR_IDENTIFIER_(Category, Name, meta) = { \ #Name, \ #Category, \ - IDENTIFIER_(Category, Name, impl), \ - &IDENTIFIER_(Category, Name, extra) \ + CR_IDENTIFIER_(Category, Name, impl), \ + &CR_IDENTIFIER_(Category, Name, extra) \ }; \ - SECTION_("cr_tst") \ - struct criterion_test *IDENTIFIER_(Category, Name, ptr) \ - = &IDENTIFIER_(Category, Name, meta) SECTION_SUFFIX_; \ - TEST_PROTOTYPE_(Category, Name) + CR_SECTION_("cr_tst") \ + struct criterion_test *CR_IDENTIFIER_(Category, Name, ptr) \ + = &CR_IDENTIFIER_(Category, Name, meta) CR_SECTION_SUFFIX_; \ + CR_TEST_PROTOTYPE_(Category, Name) # define TestSuite(...) CR_EXPAND(TestSuite_(__VA_ARGS__, .sentinel_ = 0)) # define TestSuite_(Name, ...) \ - struct criterion_test_extra_data SUITE_IDENTIFIER_(Name, extra) = \ + struct criterion_test_extra_data CR_SUITE_IDENTIFIER_(Name, extra) = \ CR_EXPAND(CRITERION_MAKE_STRUCT(struct criterion_test_extra_data, \ .file_ = __FILE__, \ .line_ = 0, \ __VA_ARGS__ \ )); \ - struct criterion_suite SUITE_IDENTIFIER_(Name, meta) = { \ + struct criterion_suite CR_SUITE_IDENTIFIER_(Name, meta) = { \ #Name, \ - &SUITE_IDENTIFIER_(Name, extra), \ + &CR_SUITE_IDENTIFIER_(Name, extra), \ }; \ - SECTION_("cr_sts") \ - struct criterion_suite *SUITE_IDENTIFIER_(Name, ptr) \ - = &SUITE_IDENTIFIER_(Name, meta) SECTION_SUFFIX_ + CR_SECTION_("cr_sts") \ + struct criterion_suite *CR_SUITE_IDENTIFIER_(Name, ptr) \ + = &CR_SUITE_IDENTIFIER_(Name, meta) CR_SECTION_SUFFIX_ CR_BEGIN_C_API diff --git a/include/criterion/hooks.h b/include/criterion/hooks.h index 62ab4834..497b0476 100644 --- a/include/criterion/hooks.h +++ b/include/criterion/hooks.h @@ -43,57 +43,57 @@ typedef enum { typedef void (*f_report_hook)(); -# define HOOK_IDENTIFIER_(Suffix) HOOK_IDENTIFIER__(__LINE__, Suffix) -# define HOOK_IDENTIFIER__(Line, Suffix) HOOK_IDENTIFIER___(Line, Suffix) -# define HOOK_IDENTIFIER___(Line, Suffix) hook_l ## Line ## _ ## Suffix +# define CR_HOOK_IDENTIFIER_(Suffix) CR_HOOK_IDENTIFIER__(__LINE__, Suffix) +# define CR_HOOK_IDENTIFIER__(Line, Suffix) CR_HOOK_IDENTIFIER___(Line, Suffix) +# define CR_HOOK_IDENTIFIER___(Line, Suffix) hook_l ## Line ## _ ## Suffix # ifdef __cplusplus -# define HOOK_PROTOTYPE_ \ - extern "C" void HOOK_IDENTIFIER_(impl) +# define CR_HOOK_PROTOTYPE_ \ + extern "C" void CR_HOOK_IDENTIFIER_(impl) # else -# define HOOK_PROTOTYPE_ \ - void HOOK_IDENTIFIER_(impl) +# define CR_HOOK_PROTOTYPE_ \ + void CR_HOOK_IDENTIFIER_(impl) # endif // Section abbreviations -# define HOOK_SECTION_PRE_ALL cr_pra -# define HOOK_SECTION_PRE_SUITE cr_prs -# define HOOK_SECTION_PRE_INIT cr_pri -# define HOOK_SECTION_PRE_TEST cr_prt -# define HOOK_SECTION_ASSERT cr_ast -# define HOOK_SECTION_THEORY_FAIL cr_thf -# define HOOK_SECTION_TEST_CRASH cr_tsc -# define HOOK_SECTION_POST_TEST cr_pot -# define HOOK_SECTION_POST_FINI cr_pof -# define HOOK_SECTION_POST_SUITE cr_pos -# define HOOK_SECTION_POST_ALL cr_poa +# define CR_HOOK_SECTION_PRE_ALL cr_pra +# define CR_HOOK_SECTION_PRE_SUITE cr_prs +# define CR_HOOK_SECTION_PRE_INIT cr_pri +# define CR_HOOK_SECTION_PRE_TEST cr_prt +# define CR_HOOK_SECTION_ASSERT cr_ast +# define CR_HOOK_SECTION_THEORY_FAIL cr_thf +# define CR_HOOK_SECTION_TEST_CRASH cr_tsc +# define CR_HOOK_SECTION_POST_TEST cr_pot +# define CR_HOOK_SECTION_POST_FINI cr_pof +# define CR_HOOK_SECTION_POST_SUITE cr_pos +# define CR_HOOK_SECTION_POST_ALL cr_poa -# define HOOK_SECTION(Kind) HOOK_SECTION_ ## Kind +# define CR_HOOK_SECTION(Kind) CR_HOOK_SECTION_ ## Kind -# define HOOK_SECTION_STRINGIFY__(Sec) #Sec -# define HOOK_SECTION_STRINGIFY_(Sec) HOOK_SECTION_STRINGIFY__(Sec) -# define HOOK_SECTION_STRINGIFY(Kind) HOOK_SECTION_STRINGIFY_(HOOK_SECTION(Kind)) +# define CR_HOOK_SECTION_STRINGIFY__(Sec) #Sec +# define CR_HOOK_SECTION_STRINGIFY_(Sec) CR_HOOK_SECTION_STRINGIFY__(Sec) +# define CR_HOOK_SECTION_STRINGIFY(Kind) CR_HOOK_SECTION_STRINGIFY_(CR_HOOK_SECTION(Kind)) -# define HOOK_PARAM_TYPE_PRE_ALL struct criterion_test_set * -# define HOOK_PARAM_TYPE_PRE_SUITE struct criterion_suite_set * -# define HOOK_PARAM_TYPE_PRE_INIT struct criterion_test * -# define HOOK_PARAM_TYPE_PRE_TEST struct criterion_test * -# define HOOK_PARAM_TYPE_ASSERT struct criterion_assert_stats * -# define HOOK_PARAM_TYPE_THEORY_FAIL struct criterion_theory_stats * -# define HOOK_PARAM_TYPE_TEST_CRASH struct criterion_test_stats * -# define HOOK_PARAM_TYPE_POST_TEST struct criterion_test_stats * -# define HOOK_PARAM_TYPE_POST_FINI struct criterion_test_stats * -# define HOOK_PARAM_TYPE_POST_SUITE struct criterion_suite_stats * -# define HOOK_PARAM_TYPE_POST_ALL struct criterion_global_stats * +# define CR_HOOK_PARAM_TYPE_PRE_ALL struct criterion_test_set * +# define CR_HOOK_PARAM_TYPE_PRE_SUITE struct criterion_suite_set * +# define CR_HOOK_PARAM_TYPE_PRE_INIT struct criterion_test * +# define CR_HOOK_PARAM_TYPE_PRE_TEST struct criterion_test * +# define CR_HOOK_PARAM_TYPE_ASSERT struct criterion_assert_stats * +# define CR_HOOK_PARAM_TYPE_THEORY_FAIL struct criterion_theory_stats * +# define CR_HOOK_PARAM_TYPE_TEST_CRASH struct criterion_test_stats * +# define CR_HOOK_PARAM_TYPE_POST_TEST struct criterion_test_stats * +# define CR_HOOK_PARAM_TYPE_POST_FINI struct criterion_test_stats * +# define CR_HOOK_PARAM_TYPE_POST_SUITE struct criterion_suite_stats * +# define CR_HOOK_PARAM_TYPE_POST_ALL struct criterion_global_stats * -# define HOOK_PARAM_TYPE(Kind) HOOK_PARAM_TYPE_ ## Kind +# define CR_HOOK_PARAM_TYPE(Kind) CR_HOOK_PARAM_TYPE_ ## Kind -# define ReportHook(Kind) \ - HOOK_PROTOTYPE_(HOOK_PARAM_TYPE(Kind)); \ - SECTION_(HOOK_SECTION_STRINGIFY(Kind)) \ - f_report_hook HOOK_IDENTIFIER_(func) = \ - (f_report_hook) HOOK_IDENTIFIER_(impl) \ - SECTION_SUFFIX_; \ - HOOK_PROTOTYPE_ +# define ReportHook(Kind) \ + CR_HOOK_PROTOTYPE_(CR_HOOK_PARAM_TYPE(Kind)); \ + CR_SECTION_(CR_HOOK_SECTION_STRINGIFY(Kind)) \ + f_report_hook CR_HOOK_IDENTIFIER_(func) = \ + (f_report_hook) CR_HOOK_IDENTIFIER_(impl) \ + CR_SECTION_SUFFIX_; \ + CR_HOOK_PROTOTYPE_ #endif /* !CRITERION_HOOKS_H_ */ diff --git a/include/criterion/logging.h b/include/criterion/logging.h index 2f8e1d9f..aca55ce2 100644 --- a/include/criterion/logging.h +++ b/include/criterion/logging.h @@ -65,12 +65,12 @@ struct criterion_prefix_data { # define CRIT_FG_BLUE "\33[0;34m" # define CRIT_RESET "\33[0m" -# define FG_BOLD CRIT_COLOR_NORMALIZE(CRIT_FG_BOLD) -# define FG_RED CRIT_COLOR_NORMALIZE(CRIT_FG_RED) -# define FG_GREEN CRIT_COLOR_NORMALIZE(CRIT_FG_GREEN) -# define FG_GOLD CRIT_COLOR_NORMALIZE(CRIT_FG_GOLD) -# define FG_BLUE CRIT_COLOR_NORMALIZE(CRIT_FG_BLUE) -# define RESET CRIT_COLOR_NORMALIZE(CRIT_RESET) +# define CR_FG_BOLD CRIT_COLOR_NORMALIZE(CRIT_FG_BOLD) +# define CR_FG_RED CRIT_COLOR_NORMALIZE(CRIT_FG_RED) +# define CR_FG_GREEN CRIT_COLOR_NORMALIZE(CRIT_FG_GREEN) +# define CR_FG_GOLD CRIT_COLOR_NORMALIZE(CRIT_FG_GOLD) +# define CR_FG_BLUE CRIT_COLOR_NORMALIZE(CRIT_FG_BLUE) +# define CR_RESET CRIT_COLOR_NORMALIZE(CRIT_RESET) # endif CR_BEGIN_C_API @@ -87,10 +87,10 @@ extern const struct criterion_prefix_data g_criterion_logging_prefixes[]; CR_API void criterion_vlog(enum criterion_logging_level level, const char *msg, va_list args); -FORMAT(printf, 3, 4) +CR_FORMAT(printf, 3, 4) CR_API void criterion_plog(enum criterion_logging_level level, const struct criterion_prefix_data *prefix, const char *msg, ...); -FORMAT(printf, 2, 3) +CR_FORMAT(printf, 2, 3) CR_API void criterion_log(enum criterion_logging_level level, const char *msg, ...); # define criterion_info(...) criterion_log(CRITERION_INFO, __VA_ARGS__) @@ -124,7 +124,7 @@ extern struct criterion_output_provider tap_logging; CR_END_C_API -#define NORMAL_LOGGING (&normal_logging) -#define TAP_LOGGING (&tap_logging) +#define CR_NORMAL_LOGGING (&normal_logging) +#define CR_TAP_LOGGING (&tap_logging) #endif /* !CRITERION_LOGGING_H_ */ diff --git a/include/criterion/parameterized.h b/include/criterion/parameterized.h index d5cde423..cbf0aa30 100644 --- a/include/criterion/parameterized.h +++ b/include/criterion/parameterized.h @@ -9,10 +9,10 @@ # ifdef __cplusplus # define CR_PARAM_TEST_PROTOTYPE_(Param, Category, Name) \ - extern "C" void IDENTIFIER_(Category, Name, impl)(Param) + extern "C" void CR_IDENTIFIER_(Category, Name, impl)(Param) # else # define CR_PARAM_TEST_PROTOTYPE_(Param, Category, Name) \ - void IDENTIFIER_(Category, Name, impl)(Param) + void CR_IDENTIFIER_(Category, Name, impl)(Param) # endif # define ParameterizedTest(...) \ @@ -20,28 +20,28 @@ # define ParameterizedTest_(Param, Category, Name, ...) \ CR_PARAM_TEST_PROTOTYPE_(Param, Category, Name); \ - struct criterion_test_extra_data IDENTIFIER_(Category, Name, extra) = \ + struct criterion_test_extra_data CR_IDENTIFIER_(Category, Name, extra) = \ CR_EXPAND(CRITERION_MAKE_STRUCT(struct criterion_test_extra_data, \ .kind_ = CR_TEST_PARAMETERIZED, \ - .param_ = IDENTIFIER_(Category, Name, param), \ + .param_ = CR_IDENTIFIER_(Category, Name, param), \ .identifier_ = #Category "/" #Name, \ .file_ = __FILE__, \ .line_ = __LINE__, \ __VA_ARGS__ \ )); \ - struct criterion_test IDENTIFIER_(Category, Name, meta) = { \ + struct criterion_test CR_IDENTIFIER_(Category, Name, meta) = { \ #Name, \ #Category, \ - (void(*)(void)) IDENTIFIER_(Category, Name, impl), \ - &IDENTIFIER_(Category, Name, extra) \ + (void(*)(void)) CR_IDENTIFIER_(Category, Name, impl), \ + &CR_IDENTIFIER_(Category, Name, extra) \ }; \ - SECTION_("cr_tst") \ - struct criterion_test *IDENTIFIER_(Category, Name, ptr) \ - = &IDENTIFIER_(Category, Name, meta) SECTION_SUFFIX_; \ + CR_SECTION_("cr_tst") \ + struct criterion_test *CR_IDENTIFIER_(Category, Name, ptr) \ + = &CR_IDENTIFIER_(Category, Name, meta) CR_SECTION_SUFFIX_; \ CR_PARAM_TEST_PROTOTYPE_(Param, Category, Name) # define ParameterizedTestParameters(Category, Name) \ - static struct criterion_test_params IDENTIFIER_(Category, Name, param)(void) + static struct criterion_test_params CR_IDENTIFIER_(Category, Name, param)(void) # ifdef __cplusplus # define cr_make_param_array(Type, Array, ...) \ diff --git a/include/criterion/theories.h b/include/criterion/theories.h index 5cdf76af..5a1227e7 100644 --- a/include/criterion/theories.h +++ b/include/criterion/theories.h @@ -54,10 +54,10 @@ CR_API void cr_theory_reset(struct criterion_theory_context *ctx); CR_API void cr_theory_call(struct criterion_theory_context *ctx, void (*fnptr)(void)); # define TheoryDataPoints(Category, Name) \ - static struct criterion_datapoints IDENTIFIER_(Category, Name, dps)[] + static struct criterion_datapoints CR_IDENTIFIER_(Category, Name, dps)[] # define TheoryDataPoint(Category, Name) \ - (IDENTIFIER_(Category, Name, dps)) + (CR_IDENTIFIER_(Category, Name, dps)) # ifdef __cplusplus # define CR_TH_VA_NUM(Type, ...) criterion_va_num__(__VA_ARGS__) @@ -127,7 +127,7 @@ struct criterion_datapoints { CR_API void cr_theory_main(struct criterion_datapoints *dps, size_t datapoints, void (*fnptr)(void)); # define CR_VAARG_ID(Suffix, Category, Name, ...) \ - IDENTIFIER_(Category, Name, Suffix) + CR_IDENTIFIER_(Category, Name, Suffix) # define Theory(Args, ...) \ void CR_EXPAND(CR_VAARG_ID(theory, __VA_ARGS__,))Args; \ diff --git a/src/compat/pipe.c b/src/compat/pipe.c index 23c4b4a7..30a3ef12 100644 --- a/src/compat/pipe.c +++ b/src/compat/pipe.c @@ -182,7 +182,7 @@ void pipe_std_redirect(s_pipe_handle *pipe, enum criterion_std_fd fd) { #endif } -void close_pipe_file_handle(void *ptr, UNUSED void *meta) { +void close_pipe_file_handle(void *ptr, CR_UNUSED void *meta) { s_pipe_file_handle *h = ptr; #ifdef VANILLA_WIN32 CloseHandle(h->fh); diff --git a/src/compat/process.c b/src/compat/process.c index 4e6c2869..5b246ac0 100644 --- a/src/compat/process.c +++ b/src/compat/process.c @@ -115,7 +115,7 @@ static struct full_context local_ctx; # error Unsupported compiler. Use GCC or Clang under *nixes. # endif -static void handle_sigchld(UNUSED int sig) { +static void handle_sigchld(CR_UNUSED int sig) { assert(sig == SIGCHLD); int fd = g_worker_pipe->fds[1]; @@ -151,7 +151,7 @@ struct wait_context { }; static void CALLBACK handle_child_terminated(PVOID lpParameter, - UNUSED BOOLEAN TimerOrWaitFired) { + CR_UNUSED BOOLEAN TimerOrWaitFired) { assert(!TimerOrWaitFired); diff --git a/src/compat/section.h b/src/compat/section.h index 9f6359e6..7ff07555 100644 --- a/src/compat/section.h +++ b/src/compat/section.h @@ -24,6 +24,8 @@ #ifndef SECTION_H_ # define SECTION_H_ +# include "criterion/common.h" + # ifdef _WIN32 void *get_win_section_start(const char *section); void *get_win_section_end(const char *section); @@ -39,8 +41,8 @@ void *get_osx_section_end(const char *section); # define GET_SECTION_START(Name) get_osx_section_start(CR_STRINGIFY(Name)) # define GET_SECTION_END(Name) get_osx_section_end(CR_STRINGIFY(Name)) # else -# define GET_SECTION_START(Name) SECTION_START(Name) -# define GET_SECTION_END(Name) SECTION_END(Name) +# define GET_SECTION_START(Name) CR_SECTION_START(Name) +# define GET_SECTION_END(Name) CR_SECTION_END(Name) # endif #endif /* !SECTION_H_ */ diff --git a/src/core/ordered-set.c b/src/core/ordered-set.c index 00630238..fa9c5c5e 100644 --- a/src/core/ordered-set.c +++ b/src/core/ordered-set.c @@ -27,11 +27,11 @@ #include #include "common.h" -static void destroy_ordered_set(void *ptr, UNUSED void *meta) { +static void destroy_ordered_set(void *ptr, CR_UNUSED void *meta) { sfree(((struct criterion_ordered_set *) ptr)->first); } -static INLINE void nothing(UNUSED void *ptr, UNUSED void *meta) {} +static INLINE void nothing(CR_UNUSED void *ptr, CR_UNUSED void *meta) {} static void destroy_ordered_set_node(void *ptr, void *meta) { struct criterion_ordered_set *set = *(void **) meta; diff --git a/src/core/report.c b/src/core/report.c index 025d4849..71123192 100644 --- a/src/core/report.c +++ b/src/core/report.c @@ -36,39 +36,39 @@ static inline void nothing() {} #define IMPL_CALL_REPORT_HOOKS(Kind) \ - IMPL_SECTION_LIMITS(f_report_hook, HOOK_SECTION(Kind)); \ + CR_IMPL_SECTION_LIMITS(f_report_hook, CR_HOOK_SECTION(Kind)); \ void call_report_hooks_##Kind(void *data) { \ - for (f_report_hook *hook = GET_SECTION_START(HOOK_SECTION(Kind)); \ - hook < (f_report_hook*) GET_SECTION_END(HOOK_SECTION(Kind)); \ + for (f_report_hook *hook = GET_SECTION_START(CR_HOOK_SECTION(Kind)); \ + hook < (f_report_hook*) GET_SECTION_END(CR_HOOK_SECTION(Kind)); \ ++hook) { \ (*hook ? *hook : nothing)(data); \ } \ } #ifdef _MSC_VER -f_report_hook SECTION_START_(HOOK_SECTION(PRE_ALL)); -f_report_hook SECTION_START_(HOOK_SECTION(PRE_SUITE)); -f_report_hook SECTION_START_(HOOK_SECTION(PRE_INIT)); -f_report_hook SECTION_START_(HOOK_SECTION(PRE_TEST)); -f_report_hook SECTION_START_(HOOK_SECTION(ASSERT)); -f_report_hook SECTION_START_(HOOK_SECTION(THEORY_FAIL)); -f_report_hook SECTION_START_(HOOK_SECTION(TEST_CRASH)); -f_report_hook SECTION_START_(HOOK_SECTION(POST_TEST)); -f_report_hook SECTION_START_(HOOK_SECTION(POST_FINI)); -f_report_hook SECTION_START_(HOOK_SECTION(POST_SUITE)); -f_report_hook SECTION_START_(HOOK_SECTION(POST_ALL)); +f_report_hook CR_SECTION_START_(CR_HOOK_SECTION(PRE_ALL)); +f_report_hook CR_SECTION_START_(CR_HOOK_SECTION(PRE_SUITE)); +f_report_hook CR_SECTION_START_(CR_HOOK_SECTION(PRE_INIT)); +f_report_hook CR_SECTION_START_(CR_HOOK_SECTION(PRE_TEST)); +f_report_hook CR_SECTION_START_(CR_HOOK_SECTION(ASSERT)); +f_report_hook CR_SECTION_START_(CR_HOOK_SECTION(THEORY_FAIL)); +f_report_hook CR_SECTION_START_(CR_HOOK_SECTION(TEST_CRASH)); +f_report_hook CR_SECTION_START_(CR_HOOK_SECTION(POST_TEST)); +f_report_hook CR_SECTION_START_(CR_HOOK_SECTION(POST_FINI)); +f_report_hook CR_SECTION_START_(CR_HOOK_SECTION(POST_SUITE)); +f_report_hook CR_SECTION_START_(CR_HOOK_SECTION(POST_ALL)); -f_report_hook SECTION_END_(HOOK_SECTION(PRE_ALL)); -f_report_hook SECTION_END_(HOOK_SECTION(PRE_SUITE)); -f_report_hook SECTION_END_(HOOK_SECTION(PRE_INIT)); -f_report_hook SECTION_END_(HOOK_SECTION(PRE_TEST)); -f_report_hook SECTION_END_(HOOK_SECTION(ASSERT)); -f_report_hook SECTION_END_(HOOK_SECTION(THEORY_FAIL)); -f_report_hook SECTION_END_(HOOK_SECTION(TEST_CRASH)); -f_report_hook SECTION_END_(HOOK_SECTION(POST_TEST)); -f_report_hook SECTION_END_(HOOK_SECTION(POST_FINI)); -f_report_hook SECTION_END_(HOOK_SECTION(POST_SUITE)); -f_report_hook SECTION_END_(HOOK_SECTION(POST_ALL)); +f_report_hook CR_SECTION_END_(CR_HOOK_SECTION(PRE_ALL)); +f_report_hook CR_SECTION_END_(CR_HOOK_SECTION(PRE_SUITE)); +f_report_hook CR_SECTION_END_(CR_HOOK_SECTION(PRE_INIT)); +f_report_hook CR_SECTION_END_(CR_HOOK_SECTION(PRE_TEST)); +f_report_hook CR_SECTION_END_(CR_HOOK_SECTION(ASSERT)); +f_report_hook CR_SECTION_END_(CR_HOOK_SECTION(THEORY_FAIL)); +f_report_hook CR_SECTION_END_(CR_HOOK_SECTION(TEST_CRASH)); +f_report_hook CR_SECTION_END_(CR_HOOK_SECTION(POST_TEST)); +f_report_hook CR_SECTION_END_(CR_HOOK_SECTION(POST_FINI)); +f_report_hook CR_SECTION_END_(CR_HOOK_SECTION(POST_SUITE)); +f_report_hook CR_SECTION_END_(CR_HOOK_SECTION(POST_ALL)); #endif IMPL_CALL_REPORT_HOOKS(PRE_ALL); @@ -83,15 +83,15 @@ IMPL_CALL_REPORT_HOOKS(POST_FINI); IMPL_CALL_REPORT_HOOKS(POST_SUITE); IMPL_CALL_REPORT_HOOKS(POST_ALL); -ReportHook(PRE_ALL)(UNUSED struct criterion_test_set *arg) {} -ReportHook(PRE_SUITE)(UNUSED struct criterion_suite_set *arg) {} -ReportHook(PRE_INIT)(UNUSED struct criterion_test *arg) {} -ReportHook(PRE_TEST)(UNUSED struct criterion_test *arg) {} -ReportHook(ASSERT)(UNUSED struct criterion_assert_stats *arg) {} -ReportHook(THEORY_FAIL)(UNUSED struct criterion_theory_stats *arg) {} -ReportHook(TEST_CRASH)(UNUSED struct criterion_test_stats *arg) {} -ReportHook(POST_TEST)(UNUSED struct criterion_test_stats *arg) {} -ReportHook(POST_FINI)(UNUSED struct criterion_test_stats *arg) {} -ReportHook(POST_SUITE)(UNUSED struct criterion_suite_stats *arg) {} -ReportHook(POST_ALL)(UNUSED struct criterion_global_stats *arg) {} +ReportHook(PRE_ALL)(CR_UNUSED struct criterion_test_set *arg) {} +ReportHook(PRE_SUITE)(CR_UNUSED struct criterion_suite_set *arg) {} +ReportHook(PRE_INIT)(CR_UNUSED struct criterion_test *arg) {} +ReportHook(PRE_TEST)(CR_UNUSED struct criterion_test *arg) {} +ReportHook(ASSERT)(CR_UNUSED struct criterion_assert_stats *arg) {} +ReportHook(THEORY_FAIL)(CR_UNUSED struct criterion_theory_stats *arg) {} +ReportHook(TEST_CRASH)(CR_UNUSED struct criterion_test_stats *arg) {} +ReportHook(POST_TEST)(CR_UNUSED struct criterion_test_stats *arg) {} +ReportHook(POST_FINI)(CR_UNUSED struct criterion_test_stats *arg) {} +ReportHook(POST_SUITE)(CR_UNUSED struct criterion_suite_stats *arg) {} +ReportHook(POST_ALL)(CR_UNUSED struct criterion_global_stats *arg) {} diff --git a/src/core/report.h b/src/core/report.h index 69f11266..dfee5ba1 100644 --- a/src/core/report.h +++ b/src/core/report.h @@ -30,7 +30,7 @@ # define report(Kind, Data) call_report_hooks_##Kind(Data) # define DECL_CALL_REPORT_HOOKS(Kind) \ - DECL_SECTION_LIMITS(f_report_hook, HOOK_SECTION(Kind)); \ + CR_DECL_SECTION_LIMITS(f_report_hook, CR_HOOK_SECTION(Kind)); \ void call_report_hooks_##Kind(void *data) DECL_CALL_REPORT_HOOKS(PRE_ALL); diff --git a/src/core/runner.c b/src/core/runner.c index 3ca32815..1f657bf7 100644 --- a/src/core/runner.c +++ b/src/core/runner.c @@ -72,14 +72,14 @@ static msg_t msg_valgrind_jobs = "%sWarning! Criterion has detected " #ifdef _MSC_VER -struct criterion_test *SECTION_START_(cr_tst); -struct criterion_suite *SECTION_START_(cr_sts); -struct criterion_test *SECTION_END_(cr_tst); -struct criterion_suite *SECTION_END_(cr_sts); +struct criterion_test *CR_SECTION_START_(cr_tst); +struct criterion_suite *CR_SECTION_START_(cr_sts); +struct criterion_test *CR_SECTION_END_(cr_tst); +struct criterion_suite *CR_SECTION_END_(cr_sts); #endif -IMPL_SECTION_LIMITS(struct criterion_test*, cr_tst); -IMPL_SECTION_LIMITS(struct criterion_suite*, cr_sts); +CR_IMPL_SECTION_LIMITS(struct criterion_test*, cr_tst); +CR_IMPL_SECTION_LIMITS(struct criterion_suite*, cr_sts); // This is here to make the test suite & test sections non-empty TestSuite(); @@ -97,12 +97,12 @@ int cmp_test(void *a, void *b) { return strcmp(s1->name, s2->name); } -static void dtor_suite_set(void *ptr, UNUSED void *meta) { +static void dtor_suite_set(void *ptr, CR_UNUSED void *meta) { struct criterion_suite_set *s = ptr; sfree(s->tests); } -static void dtor_test_set(void *ptr, UNUSED void *meta) { +static void dtor_test_set(void *ptr, CR_UNUSED void *meta) { struct criterion_test_set *t = ptr; sfree(t->suites); } @@ -425,10 +425,10 @@ static int criterion_run_all_tests_impl(struct criterion_test_set *set) { if (RUNNING_ON_VALGRIND) { if (!criterion_options.no_early_exit) criterion_pimportant(CRITERION_PREFIX_DASHES, - _(msg_valgrind_early_exit), FG_BOLD, RESET); + _(msg_valgrind_early_exit), CR_FG_BOLD, CR_RESET); if (criterion_options.jobs != 1) criterion_pimportant(CRITERION_PREFIX_DASHES, - _(msg_valgrind_jobs), FG_BOLD, RESET); + _(msg_valgrind_jobs), CR_FG_BOLD, CR_RESET); } fflush(NULL); // flush everything before forking diff --git a/src/core/runner.h b/src/core/runner.h index 9b498393..0eafbb78 100644 --- a/src/core/runner.h +++ b/src/core/runner.h @@ -27,8 +27,8 @@ # include "criterion/types.h" # include "compat/pipe.h" -DECL_SECTION_LIMITS(struct criterion_test*, cr_tst); -DECL_SECTION_LIMITS(struct criterion_suite*, cr_sts); +CR_DECL_SECTION_LIMITS(struct criterion_test*, cr_tst); +CR_DECL_SECTION_LIMITS(struct criterion_suite*, cr_sts); struct criterion_test_set *criterion_init(void); void run_test_child(struct criterion_test *test, struct criterion_suite *suite); diff --git a/src/core/stats.c b/src/core/stats.c index bba2f8b2..dd8969b0 100644 --- a/src/core/stats.c +++ b/src/core/stats.c @@ -55,13 +55,13 @@ static void push_test_crash(s_glob_stats *stats, s_test_stats *tstats, void *data); -static void nothing(UNUSED s_glob_stats *stats, - UNUSED s_suite_stats *sstats, - UNUSED s_test_stats *tstats, - UNUSED void *data) { +static void nothing(CR_UNUSED s_glob_stats *stats, + CR_UNUSED s_suite_stats *sstats, + CR_UNUSED s_test_stats *tstats, + CR_UNUSED void *data) { }; -static void destroy_stats(void *ptr, UNUSED void *meta) { +static void destroy_stats(void *ptr, CR_UNUSED void *meta) { s_glob_stats *stats = ptr; for (s_suite_stats *s = stats->suites, *next; s; s = next) { next = s->next; @@ -79,7 +79,7 @@ s_glob_stats *stats_init(void) { return stats; } -static void destroy_suite_stats(void *ptr, UNUSED void *meta) { +static void destroy_suite_stats(void *ptr, CR_UNUSED void *meta) { s_suite_stats *stats = ptr; for (s_test_stats *t = stats->tests, *next; t; t = next) { next = t->next; @@ -97,7 +97,7 @@ s_suite_stats *suite_stats_init(struct criterion_suite *s) { return stats; } -static void destroy_test_stats(void *ptr, UNUSED void *meta) { +static void destroy_test_stats(void *ptr, CR_UNUSED void *meta) { s_test_stats *stats = ptr; for (s_assert_stats *a = stats->asserts, *next; a; a = next) { next = a->next; @@ -147,8 +147,8 @@ void stat_push_event(s_glob_stats *stats, static void push_pre_suite(s_glob_stats *stats, s_suite_stats *suite, - UNUSED s_test_stats *test, - UNUSED void *ptr) { + CR_UNUSED s_test_stats *test, + CR_UNUSED void *ptr) { suite->next = stats->suites; stats->suites = sref(suite); ++stats->nb_suites; @@ -163,7 +163,7 @@ static INLINE bool is_disabled(struct criterion_test *t, static void push_pre_init(s_glob_stats *stats, s_suite_stats *suite, s_test_stats *test, - UNUSED void *ptr) { + CR_UNUSED void *ptr) { test->next = suite->tests; suite->tests = sref(test); ++stats->nb_tests; @@ -230,7 +230,7 @@ static void push_post_test(s_glob_stats *stats, static void push_test_crash(s_glob_stats *stats, s_suite_stats *suite, s_test_stats *test, - UNUSED void *ptr) { + CR_UNUSED void *ptr) { test->failed = 1; test->crashed = 1; ++suite->tests_failed; diff --git a/src/core/worker.c b/src/core/worker.c index 3a6240db..8049fac4 100644 --- a/src/core/worker.c +++ b/src/core/worker.c @@ -47,7 +47,7 @@ bool is_runner(void) { return is_current_process(g_current_proc); } -static void close_process(void *ptr, UNUSED void *meta) { +static void close_process(void *ptr, CR_UNUSED void *meta) { struct worker *proc = ptr; sfree(proc->in); sfree(proc->ctx.suite_stats); diff --git a/src/entry/main.c b/src/entry/main.c index ee1d2e5d..d67989f0 100644 --- a/src/entry/main.c +++ b/src/entry/main.c @@ -102,7 +102,7 @@ int list_tests(bool unicode) { if (!tests) continue; - printf("%s: " SIZE_T_FORMAT " test%s\n", + printf("%s: " CR_SIZE_T_FORMAT " test%s\n", s->suite.name, tests, tests == 1 ? "" : "s"); @@ -206,7 +206,7 @@ int criterion_handle_args(int argc, char *argv[], bool handle_unknown_arg) { } } if (use_tap) - criterion_options.output_provider = TAP_LOGGING; + criterion_options.output_provider = CR_TAP_LOGGING; if (do_print_usage) return print_usage(argv[0]); if (do_print_version) diff --git a/src/io/event.c b/src/io/event.c index 99bdd00e..d7b4dc61 100644 --- a/src/io/event.c +++ b/src/io/event.c @@ -34,12 +34,12 @@ s_pipe_file_handle *g_event_pipe = NULL; -void destroy_event(void *ptr, UNUSED void *meta) { +void destroy_event(void *ptr, CR_UNUSED void *meta) { struct event *ev = ptr; free(ev->data); } -void destroy_assert_event(void *ptr, UNUSED void *meta) { +void destroy_assert_event(void *ptr, CR_UNUSED void *meta) { struct event *ev = ptr; free((void*) ((struct criterion_assert_stats *) ev->data)->message); free(ev->data); diff --git a/src/log/logging.c b/src/log/logging.c index a09b2d71..932337fc 100644 --- a/src/log/logging.c +++ b/src/log/logging.c @@ -63,16 +63,16 @@ void criterion_plog(enum criterion_logging_level level, const struct criterion_p fprintf(stderr, _(ERROR_FORMAT), CRIT_COLOR_NORMALIZE(prefix->color), prefix->prefix, - RESET, - FG_RED, - FG_BOLD, + CR_RESET, + CR_FG_RED, + CR_FG_BOLD, formatted_msg, - RESET); + CR_RESET); } else { fprintf(stderr, _(LOG_FORMAT), CRIT_COLOR_NORMALIZE(prefix->color), prefix->prefix, - RESET, + CR_RESET, formatted_msg); } diff --git a/src/log/normal.c b/src/log/normal.c index b48486aa..e549f1f1 100644 --- a/src/log/normal.c +++ b/src/log/normal.c @@ -94,7 +94,7 @@ static msg_t msg_post_all = "%sSynthesis: Tested: %s%lu%s " "%s\n"; #endif -void normal_log_pre_all(UNUSED struct criterion_test_set *set) { +void normal_log_pre_all(CR_UNUSED struct criterion_test_set *set) { criterion_pinfo(CRITERION_PREFIX_DASHES, _(msg_pre_all), VERSION); } @@ -150,12 +150,12 @@ void normal_log_post_all(struct criterion_global_stats *stats) { criterion_pimportant(CRITERION_PREFIX_EQUALS, _(msg_post_all), - FG_BOLD, - FG_BLUE, (unsigned long) tested, FG_BOLD, - FG_GREEN, (unsigned long) stats->tests_passed, FG_BOLD, - FG_RED, (unsigned long) stats->tests_failed, FG_BOLD, - FG_RED, (unsigned long) stats->tests_crashed, FG_BOLD, - RESET); + CR_FG_BOLD, + CR_FG_BLUE, (unsigned long) tested, CR_FG_BOLD, + CR_FG_GREEN, (unsigned long) stats->tests_passed, CR_FG_BOLD, + CR_FG_RED, (unsigned long) stats->tests_failed, CR_FG_BOLD, + CR_FG_RED, (unsigned long) stats->tests_crashed, CR_FG_BOLD, + CR_RESET); } void normal_log_assert(struct criterion_assert_stats *stats) { @@ -172,8 +172,8 @@ void normal_log_assert(struct criterion_assert_stats *stats) { bool sf = criterion_options.short_filename; criterion_pimportant(CRITERION_PREFIX_DASHES, _(msg_assert_fail), - FG_BOLD, sf ? basename_compat(stats->file) : stats->file, RESET, - FG_RED, stats->line, RESET, + CR_FG_BOLD, sf ? basename_compat(stats->file) : stats->file, CR_RESET, + CR_FG_RED, stats->line, CR_RESET, line); #ifdef VANILLA_WIN32 @@ -190,30 +190,30 @@ void normal_log_test_crash(struct criterion_test_stats *stats) { bool sf = criterion_options.short_filename; criterion_pimportant(CRITERION_PREFIX_DASHES, _(msg_test_crash_line), - FG_BOLD, sf ? basename_compat(stats->file) : stats->file, RESET, - FG_RED, stats->progress, RESET); + CR_FG_BOLD, sf ? basename_compat(stats->file) : stats->file, CR_RESET, + CR_FG_RED, stats->progress, CR_RESET); criterion_pimportant(CRITERION_PREFIX_FAIL, _(msg_test_crash), stats->test->category, stats->test->name); } -void normal_log_other_crash(UNUSED struct criterion_test_stats *stats) { +void normal_log_other_crash(CR_UNUSED struct criterion_test_stats *stats) { criterion_pimportant(CRITERION_PREFIX_DASHES, _(msg_test_other_crash), - FG_BOLD, stats->test->category, stats->test->name, RESET); + CR_FG_BOLD, stats->test->category, stats->test->name, CR_RESET); } -void normal_log_abnormal_exit(UNUSED struct criterion_test_stats *stats) { +void normal_log_abnormal_exit(CR_UNUSED struct criterion_test_stats *stats) { criterion_pimportant(CRITERION_PREFIX_DASHES, _(msg_test_abnormal_exit), - FG_BOLD, stats->test->category, stats->test->name, RESET); + CR_FG_BOLD, stats->test->category, stats->test->name, CR_RESET); } void normal_log_pre_suite(struct criterion_suite_set *set) { criterion_pinfo(CRITERION_PREFIX_EQUALS, _s(msg_pre_suite[0], msg_pre_suite[1], set->tests->size), - FG_BLUE, (unsigned long) set->tests->size, RESET, - FG_GOLD, set->suite.name, RESET); + CR_FG_BLUE, (unsigned long) set->tests->size, CR_RESET, + CR_FG_GOLD, set->suite.name, CR_RESET); } void normal_log_theory_fail(struct criterion_theory_stats *stats) { @@ -224,7 +224,7 @@ void normal_log_theory_fail(struct criterion_theory_stats *stats) { stats->formatted_args); } -void normal_log_test_timeout(UNUSED struct criterion_test_stats *stats) { +void normal_log_test_timeout(CR_UNUSED struct criterion_test_stats *stats) { criterion_pimportant(CRITERION_PREFIX_FAIL, _(msg_test_timeout), stats->test->category, @@ -232,7 +232,7 @@ void normal_log_test_timeout(UNUSED struct criterion_test_stats *stats) { stats->elapsed_time); } -void normal_log_test_abort(UNUSED struct criterion_test_stats *stats, const char *msg) { +void normal_log_test_abort(CR_UNUSED struct criterion_test_stats *stats, const char *msg) { char *dup = strdup(msg); diff --git a/src/log/tap.c b/src/log/tap.c index 3a482318..70edb148 100644 --- a/src/log/tap.c +++ b/src/log/tap.c @@ -39,12 +39,16 @@ #endif static void print_prelude(struct criterion_global_stats *stats) { - criterion_important("TAP version 13\n1.." SIZE_T_FORMAT "\n", stats->nb_tests); + criterion_important("TAP version 13\n1.." + CR_SIZE_T_FORMAT + "\n", stats->nb_tests); criterion_important("# Criterion v%s\n", VERSION); } static void print_pre_suite(struct criterion_suite_stats *stats) { - criterion_important("\n# Running " SIZE_T_FORMAT " tests from %s\n", + criterion_important("\n# Running " + CR_SIZE_T_FORMAT + " tests from %s\n", stats->nb_tests, stats->suite->name); } diff --git a/src/string/extmatch.c b/src/string/extmatch.c index e6c75fc0..b838ff94 100644 --- a/src/string/extmatch.c +++ b/src/string/extmatch.c @@ -127,7 +127,7 @@ static inline void handle_special(struct context *ctx, handler_arg strs[5]) { } # define Handler(Name, ...) \ - static void Name(struct context *ctx, UNUSED char c) { \ + static void Name(struct context *ctx, CR_UNUSED char c) { \ handle_special(ctx, (handler_arg[5]) { \ __VA_ARGS__ \ }); \ @@ -146,7 +146,7 @@ Handler(handle_excl, Handler(handle_at, [ELSESTR] = {_, "@"}); # undef _ -static void handle_rbra(struct context *ctx, UNUSED char c) { +static void handle_rbra(struct context *ctx, CR_UNUSED char c) { copy_char(ctx, c); if (peek_char(ctx) == '!') { read_char(ctx); @@ -159,7 +159,7 @@ static void escape_char(struct context *ctx, char c) { copy_char(ctx, c); } -static void escape_pipe(struct context *ctx, UNUSED char c) { +static void escape_pipe(struct context *ctx, CR_UNUSED char c) { if (ctx->depth == 0) copy_char(ctx, '\\'); copy_char(ctx, '|'); From 4148d3d5d450ffc26c720b531c14df5ff478de5c Mon Sep 17 00:00:00 2001 From: Snaipe Date: Fri, 2 Oct 2015 15:10:41 +0200 Subject: [PATCH 066/211] [Issue #64] Prefixed all unprefixed API functions and types --- include/criterion/assert.h | 6 +++--- include/criterion/event.h | 2 +- include/criterion/types.h | 2 +- src/compat/process.c | 2 +- src/compat/process.h | 2 +- src/core/abort.c | 2 +- src/core/theories.c | 2 +- src/core/worker.c | 2 +- src/core/worker.h | 2 +- src/core/wrappers/wrap.c | 8 ++++---- src/core/wrappers/wrap.cc | 8 ++++---- src/io/event.c | 2 +- src/string/i18n.c | 2 +- 13 files changed, 21 insertions(+), 21 deletions(-) diff --git a/include/criterion/assert.h b/include/criterion/assert.h index c09fa004..444d6a12 100644 --- a/include/criterion/assert.h +++ b/include/criterion/assert.h @@ -72,7 +72,7 @@ enum criterion_assert_messages { CR_BEGIN_C_API -CR_API char *translate_assert_msg(int msg_index, ...); +CR_API char *cr_translate_assert_msg(int msg_index, ...); CR_END_C_API @@ -90,7 +90,7 @@ CR_END_C_API CR_IDENTITY Arg # define CR_TRANSLATE_DEF_MSG_(...) \ - CR_EXPAND(translate_assert_msg( \ + CR_EXPAND(cr_translate_assert_msg( \ CR_VA_HEAD(__VA_ARGS__), \ "" CR_TRANSLATE_DEF_MSG__(CR_VA_HEAD(CR_VA_TAIL(__VA_ARGS__))) \ )) @@ -145,7 +145,7 @@ CR_END_C_API stat->file = __FILE__; \ stat->line = __LINE__; \ \ - send_event(ASSERT, stat, bufsize); \ + criterion_send_event(ASSERT, stat, bufsize); \ CR_STDN free(stat); \ \ if (!passed) \ diff --git a/include/criterion/event.h b/include/criterion/event.h index 51389018..6ccc649d 100644 --- a/include/criterion/event.h +++ b/include/criterion/event.h @@ -33,7 +33,7 @@ CR_BEGIN_C_API -CR_API void send_event(int kind, void *data, size_t size); +CR_API void criterion_send_event(int kind, void *data, size_t size); CR_END_C_API diff --git a/include/criterion/types.h b/include/criterion/types.h index 33540981..27cecdd2 100644 --- a/include/criterion/types.h +++ b/include/criterion/types.h @@ -129,6 +129,6 @@ struct criterion_test_set { size_t tests; }; -typedef void (*f_worker_func)(struct criterion_test *, struct criterion_suite *); +typedef void (*cr_worker_func)(struct criterion_test *, struct criterion_suite *); #endif /* !CRITERION_TYPES_H_ */ diff --git a/src/compat/process.c b/src/compat/process.c index 5b246ac0..08392995 100644 --- a/src/compat/process.c +++ b/src/compat/process.c @@ -98,7 +98,7 @@ struct full_context { struct criterion_test_extra_data test_data; struct criterion_suite suite; struct criterion_test_extra_data suite_data; - f_worker_func func; + cr_worker_func func; struct pipe_handle pipe; struct test_single_param param; HANDLE sync; diff --git a/src/compat/process.h b/src/compat/process.h index 103d835b..8b965ab4 100644 --- a/src/compat/process.h +++ b/src/compat/process.h @@ -40,7 +40,7 @@ typedef struct proc_handle s_proc_handle; struct worker_context { struct criterion_test *test; struct criterion_suite *suite; - f_worker_func func; + cr_worker_func func; struct pipe_handle *pipe; struct test_single_param *param; }; diff --git a/src/core/abort.c b/src/core/abort.c index d8d7c65e..0d32188b 100644 --- a/src/core/abort.c +++ b/src/core/abort.c @@ -46,7 +46,7 @@ void criterion_test_die(const char *msg, ...) { *buf = res + 1; memcpy(buf + 1, formatted_msg, res + 1); - send_event(TEST_ABORT, buf, sizeof (size_t) + res + 1); + criterion_send_event(TEST_ABORT, buf, sizeof(size_t) + res + 1); free(buf); free(formatted_msg); diff --git a/src/core/theories.c b/src/core/theories.c index 1af29bcb..28d0d127 100644 --- a/src/core/theories.c +++ b/src/core/theories.c @@ -222,7 +222,7 @@ void cr_theory_main(struct criterion_datapoints *dps, size_t datapoints, void (* concat_arg(&result.msg, dps, indices, datapoints - 1); result.len = strlen(result.msg) + 1; - send_event(THEORY_FAIL, &result, result.len + sizeof (size_t)); + criterion_send_event(THEORY_FAIL, &result, result.len + sizeof(size_t)); } } diff --git a/src/core/worker.c b/src/core/worker.c index 8049fac4..54d68684 100644 --- a/src/core/worker.c +++ b/src/core/worker.c @@ -91,7 +91,7 @@ void run_worker(struct worker_context *ctx) { } struct worker *spawn_test_worker(struct execution_context *ctx, - f_worker_func func, + cr_worker_func func, s_pipe_handle *pipe) { g_worker_context = (struct worker_context) { .test = ctx->test, diff --git a/src/core/worker.h b/src/core/worker.h index 649e3eb1..414f374c 100644 --- a/src/core/worker.h +++ b/src/core/worker.h @@ -84,7 +84,7 @@ bool is_runner(void); struct process_status wait_proc(struct worker *proc); struct process_status get_status(int status); struct worker *spawn_test_worker(struct execution_context *ctx, - f_worker_func func, + cr_worker_func func, s_pipe_handle *pipe); struct event *worker_read_event(struct worker_set *workers, s_pipe_file_handle *pipe); diff --git a/src/core/wrappers/wrap.c b/src/core/wrappers/wrap.c index 01acf622..38009a2b 100644 --- a/src/core/wrappers/wrap.c +++ b/src/core/wrappers/wrap.c @@ -33,11 +33,11 @@ static INLINE void nothing(void) {} void c_wrap(struct criterion_test *test, struct criterion_suite *suite) { - send_event(PRE_INIT, NULL, 0); + criterion_send_event(PRE_INIT, NULL, 0); if (suite->data) (suite->data->init ? suite->data->init : nothing)(); (test->data->init ? test->data->init : nothing)(); - send_event(PRE_TEST, NULL, 0); + criterion_send_event(PRE_TEST, NULL, 0); struct timespec_compat ts; if (!setjmp(g_pre_test)) { @@ -56,10 +56,10 @@ void c_wrap(struct criterion_test *test, struct criterion_suite *suite) { if (!timer_end(&elapsed_time, &ts)) elapsed_time = -1; - send_event(POST_TEST, &elapsed_time, sizeof (double)); + criterion_send_event(POST_TEST, &elapsed_time, sizeof(double)); (test->data->fini ? test->data->fini : nothing)(); if (suite->data) (suite->data->fini ? suite->data->fini : nothing)(); - send_event(POST_FINI, NULL, 0); + criterion_send_event(POST_FINI, NULL, 0); } diff --git a/src/core/wrappers/wrap.cc b/src/core/wrappers/wrap.cc index f6b140a6..67eeb93f 100644 --- a/src/core/wrappers/wrap.cc +++ b/src/core/wrappers/wrap.cc @@ -38,7 +38,7 @@ static INLINE void nothing(void) {} void cpp_wrap(struct criterion_test *test, struct criterion_suite *suite) { - send_event(PRE_INIT, NULL, 0); + criterion_send_event(PRE_INIT, NULL, 0); try { if (suite->data) (suite->data->init ? suite->data->init : nothing)(); @@ -48,7 +48,7 @@ void cpp_wrap(struct criterion_test *test, struct criterion_suite *suite) { } catch (...) { criterion_test_die("Caught some unexpected exception during the test initialization."); } - send_event(PRE_TEST, NULL, 0); + criterion_send_event(PRE_TEST, NULL, 0); struct timespec_compat ts; if (!setjmp(g_pre_test)) { @@ -73,7 +73,7 @@ void cpp_wrap(struct criterion_test *test, struct criterion_suite *suite) { if (!timer_end(&elapsed_time, &ts)) elapsed_time = -1; - send_event(POST_TEST, &elapsed_time, sizeof (double)); + criterion_send_event(POST_TEST, &elapsed_time, sizeof(double)); try { (test->data->fini ? test->data->fini : nothing)(); if (suite->data) @@ -83,7 +83,7 @@ void cpp_wrap(struct criterion_test *test, struct criterion_suite *suite) { } catch (...) { criterion_test_die("Caught some unexpected exception during the test finalization."); } - send_event(POST_FINI, NULL, 0); + criterion_send_event(POST_FINI, NULL, 0); } diff --git a/src/io/event.c b/src/io/event.c index d7b4dc61..97204267 100644 --- a/src/io/event.c +++ b/src/io/event.c @@ -150,7 +150,7 @@ struct event *read_event(s_pipe_file_handle *f) { } } -void send_event(int kind, void *data, size_t size) { +void criterion_send_event(int kind, void *data, size_t size) { unsigned long long pid = get_process_id(); unsigned char *buf = malloc(sizeof (int) + sizeof (pid) + size); diff --git a/src/string/i18n.c b/src/string/i18n.c index c83a119c..ecc2e4de 100644 --- a/src/string/i18n.c +++ b/src/string/i18n.c @@ -8,7 +8,7 @@ void init_i18n(void) { #endif } -char *translate_assert_msg(int msg_index, ...) { +char *cr_translate_assert_msg(int msg_index, ...) { static char *messages[] = { [CRITERION_ASSERT_MSG_FAIL] = N_("The conditions for this assertion were not met."), [CRITERION_ASSERT_MSG_EXPR_FALSE] = N_("The expression %s is false."), From 1fbcecc520815a5acb2267f6915310109463a698 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Sat, 3 Oct 2015 00:54:16 +0200 Subject: [PATCH 067/211] Fixed dummy test still being registered --- src/core/runner.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/core/runner.c b/src/core/runner.c index 1f657bf7..bbe870a3 100644 --- a/src/core/runner.c +++ b/src/core/runner.c @@ -125,7 +125,7 @@ struct criterion_test_set *criterion_init(void) { struct criterion_ordered_set *suites = new_ordered_set(cmp_suite, dtor_suite_set); FOREACH_SUITE_SEC(s) { - if (!*s) + if (!*s || !*(*s)->name) continue; struct criterion_suite_set css = { @@ -148,7 +148,7 @@ struct criterion_test_set *criterion_init(void) { if (!*test) continue; - if (!(*test)->category) + if (!*(*test)->category || !*(*test)->name) continue; criterion_register_test(set, *test); From 2da6588eab77655dc3de2e8be40725a5c2c38d27 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Sat, 3 Oct 2015 02:43:24 +0200 Subject: [PATCH 068/211] Added better integration for multiple native languages tests --- .cmake/Modules/Languages.cmake | 15 +++++++++++ .travis.yml | 1 + CMakeLists.txt | 17 +++++++++--- appveyor.yml | 1 + include/criterion/criterion.h | 16 +++++++++-- include/criterion/parameterized.h | 1 + include/criterion/types.h | 8 +++++- samples/CMakeLists.txt | 27 +++++++++++-------- samples/tests/CMakeLists.txt | 19 ++++++++----- src/config.h.in | 3 +++ src/core/runner.c | 14 +++++----- src/core/wrappers/wrap.cc | 2 +- src/core/wrappers/wrap.h | 10 ++++++- src/core/wrappers/wrappers.c | 45 +++++++++++++++++++++++++++++++ test/CMakeLists.txt | 11 ++++++-- 15 files changed, 156 insertions(+), 34 deletions(-) create mode 100644 .cmake/Modules/Languages.cmake create mode 100644 src/core/wrappers/wrappers.c diff --git a/.cmake/Modules/Languages.cmake b/.cmake/Modules/Languages.cmake new file mode 100644 index 00000000..0ad61d49 --- /dev/null +++ b/.cmake/Modules/Languages.cmake @@ -0,0 +1,15 @@ + +if (NOT LANGUAGES) + set(LANGUAGES "") +endif () + +string(REPLACE "," ";" LANGUAGES "${LANGUAGES}") + +foreach (LANG ${LANGUAGES}) + enable_language(${LANG} OPTIONAL) + if (CMAKE_${LANG}_COMPILER_WORKS) + string(TOUPPER ${LANG} LANG_NAME) + set(${LANG_NAME}_BRIDGE 1) + endif () +endforeach () + diff --git a/.travis.yml b/.travis.yml index 97c285a1..07926e03 100644 --- a/.travis.yml +++ b/.travis.yml @@ -34,6 +34,7 @@ script: -DCOVERALLS=${COVERAGE} -DCMAKE_BUILD_TYPE=${CONFIGURATION} -DCMAKE_INSTALL_PREFIX=criterion-${TRAVIS_TAG} + -DLANGUAGES=CXX .. - TERM=dumb cmake --build . --target criterion_tests -- -j4 - ctest -j4 diff --git a/CMakeLists.txt b/CMakeLists.txt index 7024e7ce..969a77cc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,6 @@ cmake_minimum_required(VERSION 2.8) -project(Criterion C CXX) +project(Criterion C) set(MODULE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/.cmake/Modules") set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${MODULE_DIR}) @@ -29,6 +29,10 @@ if (MSVC) include_directories(dependencies/wingetopt/src/) endif () +# Language support + +include(Languages) + # Project setup & environment variables set(PROJECT_VERSION "2.1.0") @@ -40,7 +44,9 @@ add_definitions(-DCRITERION_BUILDING_DLL=1) if (NOT MSVC) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Werror -g -std=gnu99") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Werror -g -std=c++11") + if (CMAKE_CXX_COMPILER_WORKS) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Werror -g -std=c++11") + endif () endif () if (MSVC) @@ -85,8 +91,9 @@ find_package(PCRE) # List sources and headers set(SOURCE_FILES + src/core/wrappers/wrap.h src/core/wrappers/wrap.c - src/core/wrappers/wrap.cc + src/core/wrappers/wrappers.c src/core/abort.c src/core/abort.h src/core/report.c @@ -145,6 +152,10 @@ if (PCRE_FOUND) set(HAVE_PCRE 1) endif () +if (CMAKE_CXX_COMPILER_WORKS) + set(SOURCE_FILES ${SOURCE_FILES} src/core/wrappers/wrap.cc) +endif () + set(INTERFACE_FILES include/criterion/assert.h include/criterion/abort.h diff --git a/appveyor.yml b/appveyor.yml index ae991136..4b1cc8d0 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -43,6 +43,7 @@ install: -DCTESTS=ON -DCMAKE_INSTALL_PREFIX="criterion-%RELEASE_NAME%" -DCMAKE_BUILD_TYPE="%CONFIGURATION%" + -DLANGUAGES=CXX -G "%GENERATOR%" .. diff --git a/include/criterion/criterion.h b/include/criterion/criterion.h index 549cdcdd..a2f4ae2b 100644 --- a/include/criterion/criterion.h +++ b/include/criterion/criterion.h @@ -33,14 +33,26 @@ # define CR_IDENTIFIER_(Category, Name, Suffix) \ Category ## _ ## Name ## _ ## Suffix +# ifdef __cplusplus +# ifdef __OBJC__ +# define CR_LANG CR_LANG_OBJCXX +# else +# define CR_LANG CR_LANG_CXX +# endif +# else +# ifdef __OBJC__ +# define CR_LANG CR_LANG_OBJC +# else +# define CR_LANG CR_LANG_C +# endif +# endif + # ifdef __cplusplus # define CR_TEST_PROTOTYPE_(Category, Name) \ extern "C" void CR_IDENTIFIER_(Category, Name, impl)(void) -# define CR_LANG CR_LANG_CPP # else # define CR_TEST_PROTOTYPE_(Category, Name) \ void CR_IDENTIFIER_(Category, Name, impl)(void) -# define CR_LANG CR_LANG_C # endif # define CR_SUITE_IDENTIFIER_(Name, Suffix) \ diff --git a/include/criterion/parameterized.h b/include/criterion/parameterized.h index cbf0aa30..2c6d96ca 100644 --- a/include/criterion/parameterized.h +++ b/include/criterion/parameterized.h @@ -22,6 +22,7 @@ CR_PARAM_TEST_PROTOTYPE_(Param, Category, Name); \ struct criterion_test_extra_data CR_IDENTIFIER_(Category, Name, extra) = \ CR_EXPAND(CRITERION_MAKE_STRUCT(struct criterion_test_extra_data, \ + .lang_ = CR_LANG, \ .kind_ = CR_TEST_PARAMETERIZED, \ .param_ = CR_IDENTIFIER_(Category, Name, param), \ .identifier_ = #Category "/" #Name, \ diff --git a/include/criterion/types.h b/include/criterion/types.h index 27cecdd2..c2c40a2c 100644 --- a/include/criterion/types.h +++ b/include/criterion/types.h @@ -37,9 +37,15 @@ using std::size_t; enum criterion_language { CR_LANG_C, - CR_LANG_CPP, + CR_LANG_CXX, + CR_LANG_OBJC, + CR_LANG_OBJCXX, + + CR_LANG_SIZE_ // leave this at the end }; +extern const char *const cr_language_names[CR_LANG_SIZE_]; + enum criterion_test_kind { CR_TEST_NORMAL, CR_TEST_PARAMETERIZED, diff --git a/samples/CMakeLists.txt b/samples/CMakeLists.txt index 7bde575c..136a1e02 100644 --- a/samples/CMakeLists.txt +++ b/samples/CMakeLists.txt @@ -19,19 +19,24 @@ set(SAMPLES redirect.c parameterized.c - signal.cc - report.cc - suites.cc - fixtures.cc - asserts.cc - more-suites.cc - description.cc - simple.cc - theories.cc - redirect.cc - parameterized.cc ) +if (CMAKE_CXX_COMPILER_WORKS) + set(SAMPLES ${SAMPLES} + signal.cc + report.cc + suites.cc + fixtures.cc + asserts.cc + more-suites.cc + description.cc + simple.cc + theories.cc + redirect.cc + parameterized.cc + ) +endif () + set(SCRIPTS tap_test early_exit diff --git a/samples/tests/CMakeLists.txt b/samples/tests/CMakeLists.txt index b2d2fca4..4a38382e 100644 --- a/samples/tests/CMakeLists.txt +++ b/samples/tests/CMakeLists.txt @@ -5,13 +5,18 @@ set(SAMPLES other-crashes.c theories_regression.c - failmessages.cc - exit.cc - long-messages.cc - other-crashes.cc - theories_regression.cc - - exception.cc ) +if (CMAKE_CXX_COMPILER_WORKS) + set(SAMPLES ${SAMPLES} + failmessages.cc + exit.cc + long-messages.cc + other-crashes.cc + theories_regression.cc + + exception.cc + ) +endif () + add_samples("${CMAKE_CURRENT_LIST_DIR}" "${SAMPLES}") diff --git a/src/config.h.in b/src/config.h.in index fef0a5c9..4bc9f70e 100644 --- a/src/config.h.in +++ b/src/config.h.in @@ -5,6 +5,9 @@ #cmakedefine HAVE_PCRE @HAVE_PCRE@ #cmakedefine ENABLE_VALGRIND_ERRORS @ENABLE_VALGRIND_ERRORS@ +#cmakedefine CXX_BRIDGE @CXX_BRIDGE@ +#cmakedefine OBJC_BRIDGE @OBJC_BRIDGE@ + # define LOCALEDIR "${LOCALEDIR}" # define PACKAGE "${PROJECT_NAME}" # define VERSION "${PROJECT_VERSION}" diff --git a/src/core/runner.c b/src/core/runner.c index bbe870a3..cd448559 100644 --- a/src/core/runner.c +++ b/src/core/runner.c @@ -157,11 +157,6 @@ struct criterion_test_set *criterion_init(void) { return set; } -f_wrapper *g_wrappers[] = { - [CR_LANG_C] = c_wrap, - [CR_LANG_CPP] = cpp_wrap, -}; - void run_test_child(struct criterion_test *test, struct criterion_suite *suite) { @@ -174,7 +169,14 @@ void run_test_child(struct criterion_test *test, else if (test->data->timeout != 0) setup_timeout((uint64_t) (test->data->timeout * 1e9)); - g_wrappers[test->data->lang_](test, suite); + if (g_wrappers[test->data->lang_]) { + g_wrappers[test->data->lang_](test, suite); + } else { + criterion_test_die( + "The test is compiled in the %s programming language, but the \n" + "criterion runner have been compiled without its language support.", + cr_language_names[test->data->lang_]); + } } #define push_event(Kind, ...) \ diff --git a/src/core/wrappers/wrap.cc b/src/core/wrappers/wrap.cc index 67eeb93f..b9e2d1ed 100644 --- a/src/core/wrappers/wrap.cc +++ b/src/core/wrappers/wrap.cc @@ -36,7 +36,7 @@ extern "C" { static INLINE void nothing(void) {} -void cpp_wrap(struct criterion_test *test, struct criterion_suite *suite) { +void cxx_wrap(struct criterion_test *test, struct criterion_suite *suite) { criterion_send_event(PRE_INIT, NULL, 0); try { diff --git a/src/core/wrappers/wrap.h b/src/core/wrappers/wrap.h index b7d518f4..5f20da93 100644 --- a/src/core/wrappers/wrap.h +++ b/src/core/wrappers/wrap.h @@ -25,11 +25,19 @@ # define WRAP_H_ # include "criterion/types.h" +# include "config.h" typedef void (f_wrapper)(struct criterion_test *, struct criterion_suite *); void c_wrap(struct criterion_test *test, struct criterion_suite *suite); -void cpp_wrap(struct criterion_test *test, struct criterion_suite *suite); + +# ifdef CXX_BRIDGE +void cxx_wrap(struct criterion_test *test, struct criterion_suite *suite); +# endif + +# ifdef OBJC_BRIDGE +void objc_wrap(struct criterion_test *test, struct criterion_suite *suite); +# endif extern f_wrapper *g_wrappers[]; diff --git a/src/core/wrappers/wrappers.c b/src/core/wrappers/wrappers.c new file mode 100644 index 00000000..a4094e11 --- /dev/null +++ b/src/core/wrappers/wrappers.c @@ -0,0 +1,45 @@ +/* + * The MIT License (MIT) + * + * Copyright © 2015 Franklin "Snaipe" Mathieu + * + * 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. + */ +#include "wrap.h" + +f_wrapper *g_wrappers[CR_LANG_SIZE_] = { + [CR_LANG_C] = c_wrap, + +#ifdef CXX_BRIDGE + [CR_LANG_CXX] = cxx_wrap, +#endif + +#ifdef OBJC_BRIDGE + [CR_LANG_OBJC] = objc_wrap, + [CR_LANG_OBJCXX] = objc_wrap, +#endif +}; + +const char *const cr_language_names[CR_LANG_SIZE_] = { + [CR_LANG_C] = "C", + [CR_LANG_CXX] = "C++", + [CR_LANG_OBJC] = "Objective-C", + [CR_LANG_OBJCXX] = "Objective-C++", +}; + diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index da638527..2899c6b0 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -1,6 +1,8 @@ if (NOT MSVC) set(CMAKE_C_FLAGS "-std=gnu99 -Wall -Wextra") - set(CMAKE_CXX_FLAGS "-std=c++11 -Wall -Wextra") + if (CMAKE_CXX_COMPILER_WORKS) + set(CMAKE_CXX_FLAGS "-std=c++11 -Wall -Wextra") + endif () endif () include_directories(../include ../src) @@ -8,9 +10,14 @@ include_directories(../include ../src) set(TEST_SOURCES ordered-set.c asprintf.c - redirect.cc ) +if (CMAKE_CXX_COMPILER_WORKS) + set(TEST_SOURCES ${TEST_SOURCES} + redirect.cc + ) +endif () + add_executable(criterion_unit_tests EXCLUDE_FROM_ALL ${TEST_SOURCES}) target_link_libraries(criterion_unit_tests criterion) From 786e70dd1b5cb094f175c5563819abbab8b0e40f Mon Sep 17 00:00:00 2001 From: Adeel Date: Sat, 3 Oct 2015 01:08:15 +0300 Subject: [PATCH 069/211] config: Check strtok_s capability. Also cleans up redundancies and adds pragma in `UNUSED` macro. --- .cmake/Modules/Capabilities.cmake | 12 ++++++++++++ CMakeLists.txt | 1 + include/criterion/common.h | 2 +- src/config.h.in | 1 + src/log/normal.c | 27 +++++++-------------------- src/log/tap.c | 19 +++++++++++-------- 6 files changed, 33 insertions(+), 29 deletions(-) create mode 100644 .cmake/Modules/Capabilities.cmake diff --git a/.cmake/Modules/Capabilities.cmake b/.cmake/Modules/Capabilities.cmake new file mode 100644 index 00000000..6b6395e7 --- /dev/null +++ b/.cmake/Modules/Capabilities.cmake @@ -0,0 +1,12 @@ +# Copyright (C) 2015 Franklin "Snaipe" Mathieu. +# Redistribution and use of this file is allowed according to the terms of the MIT license. +# For details see the LICENSE file distributed with Criterion. + +include(CheckPrototypeDefinition) + +check_prototype_definition( + strtok_s + "char *strtok_s(char *strToken, const char *strDelimit, char **context)" + NULL + "string.h" + HAVE_STRTOK_S) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7024e7ce..559f093d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -8,6 +8,7 @@ set(LIBCSPTR_DISABLE_TESTS ON) set(LIBCSPTR_DISABLE_COVERALLS ON) include(Submodules) +include(Capabilities) if (MSVC) add_definitions(-D_CRT_SECURE_NO_WARNINGS=1) diff --git a/include/criterion/common.h b/include/criterion/common.h index 41cc2ffa..8b547e5c 100644 --- a/include/criterion/common.h +++ b/include/criterion/common.h @@ -101,7 +101,7 @@ # define CR_NORETURN CR_ATTRIBUTE(noreturn) # define CR_INLINE CR_ATTRIBUTE(always_inline) inline # elif CR_IS_MSVC -# define CR_UNUSED +# define CR_UNUSED __pragma(warning(suppress:4100)) # define CR_NORETURN __declspec(noreturn) # define CR_INLINE __forceinline # else diff --git a/src/config.h.in b/src/config.h.in index fef0a5c9..6455bff3 100644 --- a/src/config.h.in +++ b/src/config.h.in @@ -4,6 +4,7 @@ #cmakedefine ENABLE_NLS @ENABLE_NLS@ #cmakedefine HAVE_PCRE @HAVE_PCRE@ #cmakedefine ENABLE_VALGRIND_ERRORS @ENABLE_VALGRIND_ERRORS@ +#cmakedefine01 HAVE_STRTOK_S # define LOCALEDIR "${LOCALEDIR}" # define PACKAGE "${PROJECT_NAME}" diff --git a/src/log/normal.c b/src/log/normal.c index e549f1f1..ba86e6fd 100644 --- a/src/log/normal.c +++ b/src/log/normal.c @@ -37,8 +37,13 @@ #include "common.h" #ifdef VANILLA_WIN32 -// fallback to strtok on windows since strtok_s is not available everywhere -# define strtok_r(str, delim, saveptr) strtok(str, delim) +# if HAVE_STRTOK_S +# define strtok_r strtok_s +# else + static char *strtok_r(char *str, const char *delim, CR_UNUSED char **saveptr) { + return strtok(str, delim); + } +# endif #endif #ifdef _MSC_VER @@ -161,13 +166,8 @@ void normal_log_post_all(struct criterion_global_stats *stats) { void normal_log_assert(struct criterion_assert_stats *stats) { if (!stats->passed) { char *dup = strdup(*stats->message ? stats->message : ""); - -#ifdef VANILLA_WIN32 - char *line = strtok(dup, "\n"); -#else char *saveptr = NULL; char *line = strtok_r(dup, "\n", &saveptr); -#endif bool sf = criterion_options.short_filename; criterion_pimportant(CRITERION_PREFIX_DASHES, @@ -176,11 +176,7 @@ void normal_log_assert(struct criterion_assert_stats *stats) { CR_FG_RED, stats->line, CR_RESET, line); -#ifdef VANILLA_WIN32 - while ((line = strtok(NULL, "\n"))) -#else while ((line = strtok_r(NULL, "\n", &saveptr))) -#endif criterion_pimportant(CRITERION_PREFIX_DASHES, _(msg_desc), line); free(dup); } @@ -235,13 +231,8 @@ void normal_log_test_timeout(CR_UNUSED struct criterion_test_stats *stats) { void normal_log_test_abort(CR_UNUSED struct criterion_test_stats *stats, const char *msg) { char *dup = strdup(msg); - -#ifdef VANILLA_WIN32 - char *line = strtok(dup, "\n"); -#else char *saveptr = NULL; char *line = strtok_r(dup, "\n", &saveptr); -#endif criterion_pimportant(CRITERION_PREFIX_DASHES, _(msg_test_abort), @@ -249,11 +240,7 @@ void normal_log_test_abort(CR_UNUSED struct criterion_test_stats *stats, const c stats->test->name, line); -#ifdef VANILLA_WIN32 - while ((line = strtok(NULL, "\n"))) -#else while ((line = strtok_r(NULL, "\n", &saveptr))) -#endif criterion_pimportant(CRITERION_PREFIX_DASHES, _(msg_desc), line); free(dup); diff --git a/src/log/tap.c b/src/log/tap.c index 70edb148..8e3bab97 100644 --- a/src/log/tap.c +++ b/src/log/tap.c @@ -34,6 +34,16 @@ #include "config.h" #include "common.h" +#ifdef VANILLA_WIN32 +# if HAVE_STRTOK_S +# define strtok_r strtok_s +# else + static char *strtok_r(char *str, const char *delim, CR_UNUSED char **saveptr) { + return strtok(str, delim); + } +# endif +#endif + #ifdef _MSC_VER # define strdup _strdup #endif @@ -69,22 +79,15 @@ static void print_test_normal(struct criterion_test_stats *stats) { for (struct criterion_assert_stats *asrt = stats->asserts; asrt; asrt = asrt->next) { if (!asrt->passed) { char *dup = strdup(*asrt->message ? asrt->message : ""); -#ifdef VANILLA_WIN32 - char *line = strtok(dup, "\n"); -#else char *saveptr = NULL; char *line = strtok_r(dup, "\n", &saveptr); -#endif bool sf = criterion_options.short_filename; criterion_important(" %s:%u: Assertion failed: %s\n", sf ? basename_compat(asrt->file) : asrt->file, asrt->line, line); -#ifdef VANILLA_WIN32 - while ((line = strtok(NULL, "\n"))) -#else + while ((line = strtok_r(NULL, "\n", &saveptr))) -#endif criterion_important(" %s\n", line); free(dup); } From 5a1049ce2cdee2485c6bba4811cd8c23ad030390 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Sun, 4 Oct 2015 10:49:44 +0200 Subject: [PATCH 070/211] Added Objective-C language support --- .../CMakeDetermineObjectiveCCompiler.cmake | 54 +++++ .../Modules/CMakeObjectiveCCompiler.cmake.in | 10 + .../Modules/CMakeObjectiveCInformation.cmake | 187 ++++++++++++++++++ .../Modules/CMakeTestObjectiveCCompiler.cmake | 62 ++++++ .gitignore | 2 + CMakeLists.txt | 9 + src/config.h.in | 6 +- src/core/wrappers/wrap.m | 96 +++++++++ 8 files changed, 425 insertions(+), 1 deletion(-) create mode 100644 .cmake/Modules/CMakeDetermineObjectiveCCompiler.cmake create mode 100644 .cmake/Modules/CMakeObjectiveCCompiler.cmake.in create mode 100644 .cmake/Modules/CMakeObjectiveCInformation.cmake create mode 100644 .cmake/Modules/CMakeTestObjectiveCCompiler.cmake create mode 100644 src/core/wrappers/wrap.m diff --git a/.cmake/Modules/CMakeDetermineObjectiveCCompiler.cmake b/.cmake/Modules/CMakeDetermineObjectiveCCompiler.cmake new file mode 100644 index 00000000..613cd38f --- /dev/null +++ b/.cmake/Modules/CMakeDetermineObjectiveCCompiler.cmake @@ -0,0 +1,54 @@ +# Copyright (C) 2015 Franklin "Snaipe" Mathieu. +# Redistribution and use of this file is allowed according to the terms of the MIT license. +# For details see the LICENSE file distributed with Criterion. + +include(${CMAKE_ROOT}/Modules/CMakeDetermineCompiler.cmake) + +if("${CMAKE_GENERATOR}" MATCHES "Visual Studio") +elseif("${CMAKE_GENERATOR}" MATCHES "Xcode") + set(CMAKE_ObjectiveC_COMPILER_XCODE_TYPE sourcecode.m) + _cmake_find_compiler_path(ObjectiveC) +else() + if(NOT CMAKE_ObjectiveC_COMPILER) + set(CMAKE_ObjectiveC_COMPILER_INIT NOTFOUND) + + if(NOT CMAKE_ObjectiveC_COMPILER_INIT) + set(CMAKE_ObjectiveC_COMPILER_LIST ${_CMAKE_TOOLCHAIN_PREFIX}gcc clang) + endif() + + _cmake_find_compiler(ObjectiveC) + else() + _cmake_find_compiler_path(ObjectiveC) + endif() + mark_as_advanced(CMAKE_ObjectiveC_COMPILER) + + set(CMAKE_ObjectiveC_COMPILER_ID_TEST_FLAGS_FIRST) + set(CMAKE_ObjectiveC_COMPILER_ID_TEST_FLAGS "-c") + +endif() + +if(NOT CMAKE_ObjectiveC_COMPILER_ID_RUN) + set(CMAKE_ObjectiveC_COMPILER_ID_RUN 1) + + # Try to identify the compiler. + set(CMAKE_ObjectiveC_COMPILER_ID) + set(CMAKE_ObjectiveC_PLATFORM_ID) + file(READ ${CMAKE_ROOT}/Modules/CMakePlatformId.h.in + CMAKE_ObjectiveC_COMPILER_ID_PLATFORM_CONTENT) + + include(${CMAKE_ROOT}/Modules/CMakeDetermineCompilerId.cmake) + + # we use the same compiler id source than C + CMAKE_DETERMINE_COMPILER_ID(ObjectiveC CFLAGS CMakeCCompilerId.c) + +endif() + +include(CMakeFindBinUtils) + +# configure variables set in this file for fast reload later on +configure_file(${CMAKE_CURRENT_LIST_DIR}/CMakeObjectiveCCompiler.cmake.in + ${CMAKE_PLATFORM_INFO_DIR}/CMakeObjectiveCCompiler.cmake + @ONLY + ) + +set(CMAKE_ObjectiveC_COMPILER_ENV_VAR "OBJCC") diff --git a/.cmake/Modules/CMakeObjectiveCCompiler.cmake.in b/.cmake/Modules/CMakeObjectiveCCompiler.cmake.in new file mode 100644 index 00000000..ab197365 --- /dev/null +++ b/.cmake/Modules/CMakeObjectiveCCompiler.cmake.in @@ -0,0 +1,10 @@ +set(CMAKE_ObjectiveC_COMPILER "@CMAKE_ObjectiveC_COMPILER@") +set(CMAKE_ObjectiveC_COMPILER_ID "@CMAKE_ObjectiveC_COMPILER_ID@") + +set(CMAKE_ObjectiveC_IMPLICIT_LINK_LIBRARIES "@CMAKE_ObjectiveC_IMPLICIT_LINK_LIBRARIES@") + +set(CMAKE_ObjectiveC_COMPILER_LOADED 1) +set(CMAKE_ObjectiveC_COMPILER_WORKS @CMAKE_ObjectiveC_COMPILER_WORKS@) + +set(CMAKE_ObjectiveC_COMPILER_ID_RUN 1) +set(CMAKE_ObjectiveC_SOURCE_FILE_EXTENSIONS m) diff --git a/.cmake/Modules/CMakeObjectiveCInformation.cmake b/.cmake/Modules/CMakeObjectiveCInformation.cmake new file mode 100644 index 00000000..ba3f47cf --- /dev/null +++ b/.cmake/Modules/CMakeObjectiveCInformation.cmake @@ -0,0 +1,187 @@ +if(UNIX) + set(CMAKE_ObjectiveC_OUTPUT_EXTENSION .o) +else() + set(CMAKE_ObjectiveC_OUTPUT_EXTENSION .obj) +endif() + +set(_INCLUDED_FILE 0) +set(_INCLUDED_FILE_2 0) + +# Load compiler-specific information. +if(CMAKE_ObjectiveC_COMPILER_ID) + include(Compiler/${CMAKE_ObjectiveC_COMPILER_ID}-C OPTIONAL) +endif() + +set(CMAKE_BASE_NAME) +get_filename_component(CMAKE_BASE_NAME "${CMAKE_ObjectiveC_COMPILER}" NAME_WE) + +# load a hardware specific file, mostly useful for embedded compilers +if(CMAKE_SYSTEM_PROCESSOR) + if(CMAKE_ObjectiveC_COMPILER_ID) + include(Platform/${CMAKE_SYSTEM_NAME}-${CMAKE_ObjectiveC_COMPILER_ID}-C-${CMAKE_SYSTEM_PROCESSOR} OPTIONAL RESULT_VARIABLE _INCLUDED_FILE) + include(Platform/${CMAKE_SYSTEM_NAME}-${CMAKE_ObjectiveC_COMPILER_ID}-ObjectiveC-${CMAKE_SYSTEM_PROCESSOR} OPTIONAL RESULT_VARIABLE _INCLUDED_FILE_2) + endif() + if (NOT _INCLUDED_FILE AND NOT _INCLUDED_FILE_2) + include(Platform/${CMAKE_SYSTEM_NAME}-${CMAKE_BASE_NAME}-${CMAKE_SYSTEM_PROCESSOR} OPTIONAL) + endif () +endif() + +# load the system- and compiler specific files +if(CMAKE_ObjectiveC_COMPILER_ID) + include(Platform/${CMAKE_SYSTEM_NAME}-${CMAKE_ObjectiveC_COMPILER_ID}-C + OPTIONAL RESULT_VARIABLE _INCLUDED_FILE) + include(Platform/${CMAKE_SYSTEM_NAME}-${CMAKE_ObjectiveC_COMPILER_ID}-ObjectiveC + OPTIONAL RESULT_VARIABLE _INCLUDED_FILE_2) +endif() +if (NOT _INCLUDED_FILE AND _INCLUDED_FILE_2) + include(Platform/${CMAKE_SYSTEM_NAME}-${CMAKE_BASE_NAME} + OPTIONAL RESULT_VARIABLE _INCLUDED_FILE) +endif () + +# We specify the compiler information in the system file for some +# platforms, but this language may not have been enabled when the file +# was first included. Include it again to get the language info. +# Remove this when all compiler info is removed from system files. +if (NOT _INCLUDED_FILE) + include(Platform/${CMAKE_SYSTEM_NAME} OPTIONAL) +endif () + +if(CMAKE_ObjectiveC_COMPILER_LINKS_STATICALLY) + set_property(GLOBAL PROPERTY TARGET_SUPPORTS_SHARED_LIBS FALSE) +endif() + +# This should be included before the _INIT variables are +# used to initialize the cache. Since the rule variables +# have if blocks on them, users can still define them here. +# But, it should still be after the platform file so changes can +# be made to those values. + +if(CMAKE_USER_MAKE_RULES_OVERRIDE) + # Save the full path of the file so try_compile can use it. + include(${CMAKE_USER_MAKE_RULES_OVERRIDE} RESULT_VARIABLE _override) + set(CMAKE_USER_MAKE_RULES_OVERRIDE "${_override}") +endif() + +if(CMAKE_USER_MAKE_RULES_OVERRIDE_ObjectiveC) + # Save the full path of the file so try_compile can use it. + include(${CMAKE_USER_MAKE_RULES_OVERRIDE_ObjectiveC} RESULT_VARIABLE _override) + set(CMAKE_USER_MAKE_RULES_OVERRIDE_ObjectiveC "${_override}") +endif() + + +# for most systems a module is the same as a shared library +# so unless the variable CMAKE_MODULE_EXISTS is set just +# copy the values from the LIBRARY variables +if(NOT CMAKE_MODULE_EXISTS) + set(CMAKE_SHARED_MODULE_ObjectiveC_FLAGS ${CMAKE_SHARED_LIBRARY_ObjectiveC_FLAGS}) + set(CMAKE_SHARED_MODULE_CREATE_ObjectiveC_FLAGS ${CMAKE_SHARED_LIBRARY_CREATE_ObjectiveC_FLAGS}) +endif() + +if(NOT CMAKE_NOT_USING_CONFIG_FLAGS) +# default build type is none + if(NOT CMAKE_NO_BUILD_TYPE) + set (CMAKE_BUILD_TYPE ${CMAKE_BUILD_TYPE_INIT} CACHE STRING + "Choose the type of build, options are: None(CMAKE_CXX_FLAGS or CMAKE_C_FLAGS used) Debug Release RelWithDebInfo MinSizeRel.") + endif() + set (CMAKE_ObjectiveC_FLAGS_DEBUG "${CMAKE_ObjectiveC_FLAGS_DEBUG_INIT}" CACHE STRING + "Flags used by the compiler during debug builds.") + set (CMAKE_ObjectiveC_FLAGS_MINSIZEREL "${CMAKE_ObjectiveC_FLAGS_MINSIZEREL_INIT}" CACHE STRING + "Flags used by the compiler during release builds for minimum size.") + set (CMAKE_ObjectiveC_FLAGS_RELEASE "${CMAKE_ObjectiveC_FLAGS_RELEASE_INIT}" CACHE STRING + "Flags used by the compiler during release builds.") + set (CMAKE_ObjectiveC_FLAGS_RELWITHDEBINFO "${CMAKE_ObjectiveC_FLAGS_RELWITHDEBINFO_INIT}" CACHE STRING + "Flags used by the compiler during release builds with debug info.") +endif() + +if(CMAKE_ObjectiveC_STANDARD_LIBRARIES_INIT) + set(CMAKE_ObjectiveC_STANDARD_LIBRARIES "${CMAKE_C_STANDARD_LIBRARIES_INIT}" + CACHE STRING "Libraries linked by default with all C applications.") + mark_as_advanced(CMAKE_ObjectiveC_STANDARD_LIBRARIES) +endif() + +include(CMakeCommonLanguageInclude) + +# now define the following rule variables + +# CMAKE_ObjectiveC_CREATE_SHARED_LIBRARY +# CMAKE_ObjectiveC_CREATE_SHARED_MODULE +# CMAKE_ObjectiveC_COMPILE_OBJECT +# CMAKE_ObjectiveC_LINK_EXECUTABLE + +# variables supplied by the generator at use time +# +# the target without the suffix +# +# +# +# +# + +# C compiler information +# +# +# +# + +# Static library tools +# +# + + +# create a C shared library +if(NOT CMAKE_ObjectiveC_CREATE_SHARED_LIBRARY) + set(CMAKE_ObjectiveC_CREATE_SHARED_LIBRARY + " -o ") +endif() + +# create a C shared module just copy the shared library rule +if(NOT CMAKE_ObjectiveC_CREATE_SHARED_MODULE) + set(CMAKE_ObjectiveC_CREATE_SHARED_MODULE ${CMAKE_ObjectiveC_CREATE_SHARED_LIBRARY}) +endif() + +# Create a static archive incrementally for large object file counts. +# If CMAKE_ObjectiveC_CREATE_STATIObjectiveC_LIBRARY is set it will override these. +if(NOT DEFINED CMAKE_ObjectiveC_ARCHIVE_CREATE) + set(CMAKE_ObjectiveC_ARCHIVE_CREATE " qc ") +endif() +if(NOT DEFINED CMAKE_ObjectiveC_ARCHIVE_APPEND) + set(CMAKE_ObjectiveC_ARCHIVE_APPEND " q ") +endif() +if(NOT DEFINED CMAKE_ObjectiveC_ARCHIVE_FINISH) + set(CMAKE_ObjectiveC_ARCHIVE_FINISH " ") +endif() + +set(CMAKE_INCLUDE_FLAG_ObjectiveC "-I") +set(CMAKE_ObjectiveC_IMPLICIT_LINK_LIBRARIES objc) + +# compile a C file into an object file +if(NOT CMAKE_ObjectiveC_COMPILE_OBJECT) + set(CMAKE_ObjectiveC_COMPILE_OBJECT + " -o -c ") +endif() + +if(NOT CMAKE_ObjectiveC_LINK_EXECUTABLE) + set(CMAKE_ObjectiveC_LINK_EXECUTABLE + " -o ") +endif() + +if(NOT CMAKE_EXECUTABLE_RUNTIME_ObjectiveC_FLAG) + set(CMAKE_EXECUTABLE_RUNTIME_ObjectiveC_FLAG ${CMAKE_SHARED_LIBRARY_RUNTIME_ObjectiveC_FLAG}) +endif() + +if(NOT CMAKE_EXECUTABLE_RUNTIME_ObjectiveC_FLAG_SEP) + set(CMAKE_EXECUTABLE_RUNTIME_ObjectiveC_FLAG_SEP ${CMAKE_SHARED_LIBRARY_RUNTIME_ObjectiveC_FLAG_SEP}) +endif() + +if(NOT CMAKE_EXECUTABLE_RPATH_LINK_ObjectiveC_FLAG) + set(CMAKE_EXECUTABLE_RPATH_LINK_ObjectiveC_FLAG ${CMAKE_SHARED_LIBRARY_RPATH_LINK_ObjectiveC_FLAG}) +endif() + +mark_as_advanced( + CMAKE_ObjectiveC_FLAGS + CMAKE_ObjectiveC_FLAGS_DEBUG + CMAKE_ObjectiveC_FLAGS_MINSIZEREL + CMAKE_ObjectiveC_FLAGS_RELEASE + CMAKE_ObjectiveC_FLAGS_RELWITHDEBINFO +) +set(CMAKE_ObjectiveC_INFORMATION_LOADED 1) diff --git a/.cmake/Modules/CMakeTestObjectiveCCompiler.cmake b/.cmake/Modules/CMakeTestObjectiveCCompiler.cmake new file mode 100644 index 00000000..e6d5ff10 --- /dev/null +++ b/.cmake/Modules/CMakeTestObjectiveCCompiler.cmake @@ -0,0 +1,62 @@ +if(CMAKE_ObjectiveC_COMPILER_FORCED) + # The compiler configuration was forced by the user. + # Assume the user has configured all compiler information. + set(CMAKE_ObjectiveC_COMPILER_WORKS TRUE) + return() +endif() + +include(CMakeTestCompilerCommon) + +# Remove any cached result from an older CMake version. +# We now store this in CMakeCCompiler.cmake. +unset(CMAKE_ObjectiveC_COMPILER_WORKS CACHE) + +# This file is used by EnableLanguage in cmGlobalGenerator to +# determine that that selected C compiler can actually compile +# and link the most basic of programs. If not, a fatal error +# is set and cmake stops processing commands and will not generate +# any makefiles or projects. +if(NOT CMAKE_ObjectiveC_COMPILER_WORKS) + PrintTestCompilerStatus("ObjectiveC" "") + file(WRITE ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/testObjectiveCCompiler.m + "#ifdef __cplusplus\n" + "# error \"The CMAKE_ObjectiveC_COMPILER is set to an ObjectiveC++ compiler\"\n" + "#endif\n" + "int main(int argc, char* argv[])\n" + "{ (void)argv; return argc-1;}\n") +try_compile(CMAKE_ObjectiveC_COMPILER_WORKS ${CMAKE_BINARY_DIR} + ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/testObjectiveCCompiler.m + OUTPUT_VARIABLE __CMAKE_ObjectiveC_COMPILER_OUTPUT) + # Move result from cache to normal variable. + set(CMAKE_ObjectiveC_COMPILER_WORKS ${CMAKE_ObjectiveC_COMPILER_WORKS}) + unset(CMAKE_ObjectiveC_COMPILER_WORKS CACHE) + set(ObjectiveC_TEST_WAS_RUN 1) +endif() + +if(NOT CMAKE_ObjectiveC_COMPILER_WORKS) + PrintTestCompilerStatus("ObjectiveC" " -- broken") + file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log + "Determining if the ObjectiveC compiler works failed with " + "the following output:\n${__CMAKE_ObjectiveC_COMPILER_OUTPUT}\n\n") +message(FATAL_ERROR "The ObjectiveC compiler \"${CMAKE_ObjectiveC_COMPILER}\" " + "is not able to compile a simple test program.\nIt fails " + "with the following output:\n ${__CMAKE_ObjectiveC_COMPILER_OUTPUT}\n\n" + "CMake will not be able to correctly generate this project.") +else() + if(ObjectiveC_TEST_WAS_RUN) + PrintTestCompilerStatus("ObjectiveC" " -- works") + file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log + "Determining if the ObjectiveC compiler works passed with " + "the following output:\n${__CMAKE_ObjectiveC_COMPILER_OUTPUT}\n\n") + endif() + + # Re-configure file + configure_file( + ${CMAKE_CURRENT_LIST_DIR}/CMakeObjectiveCCompiler.cmake.in + ${CMAKE_PLATFORM_INFO_DIR}/CMakeObjectiveCCompiler.cmake + @ONLY + ) + include(${CMAKE_PLATFORM_INFO_DIR}/CMakeObjectiveCCompiler.cmake) +endif() + +unset(__CMAKE_ObjectiveC_COMPILER_OUTPUT) diff --git a/.gitignore b/.gitignore index e28ebbfa..55e2d534 100644 --- a/.gitignore +++ b/.gitignore @@ -10,11 +10,13 @@ !doc/* !*.c +!*.m !*.cc !*.h !*.rst !*.po !*.in +!.cmake/*.cmake !samples/tests/*.sh !samples/*.expected diff --git a/CMakeLists.txt b/CMakeLists.txt index 969a77cc..e0313d87 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -49,6 +49,7 @@ if (NOT MSVC) endif () endif () + if (MSVC) set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /SAFESEH:NO") endif () @@ -156,6 +157,14 @@ if (CMAKE_CXX_COMPILER_WORKS) set(SOURCE_FILES ${SOURCE_FILES} src/core/wrappers/wrap.cc) endif () +if (CMAKE_ObjectiveC_COMPILER_WORKS) + set(CMAKE_ObjectiveC_FLAGS "${CMAKE_ObjectiveC_FLAGS} ${CMAKE_C_FLAGS} -fobjc-exceptions") + if (NOT WIN32) + set(CMAKE_ObjectiveC_FLAGS "${CMAKE_ObjectiveC_FLAGS} -fPIC") + endif () + set(SOURCE_FILES ${SOURCE_FILES} src/core/wrappers/wrap.m) +endif () + set(INTERFACE_FILES include/criterion/assert.h include/criterion/abort.h diff --git a/src/config.h.in b/src/config.h.in index 4bc9f70e..fc911973 100644 --- a/src/config.h.in +++ b/src/config.h.in @@ -6,7 +6,11 @@ #cmakedefine ENABLE_VALGRIND_ERRORS @ENABLE_VALGRIND_ERRORS@ #cmakedefine CXX_BRIDGE @CXX_BRIDGE@ -#cmakedefine OBJC_BRIDGE @OBJC_BRIDGE@ +#cmakedefine OBJECTIVEC_BRIDGE @OBJECTIVEC_BRIDGE@ + +# ifdef OBJECTIVEC_BRIDGE +# define OBJC_BRIDGE OBJECTIVEC_BRIDGE +# endif # define LOCALEDIR "${LOCALEDIR}" # define PACKAGE "${PROJECT_NAME}" diff --git a/src/core/wrappers/wrap.m b/src/core/wrappers/wrap.m new file mode 100644 index 00000000..db3f75be --- /dev/null +++ b/src/core/wrappers/wrap.m @@ -0,0 +1,96 @@ +/* + * The MIT License (MIT) + * + * Copyright © 2015 Franklin "Snaipe" Mathieu + * + * 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. + */ +#import + +#include "criterion/assert.h" +#include "criterion/event.h" + +#include "core/abort.h" +#include "core/report.h" +#include "core/worker.h" +#include "compat/time.h" +#include "wrap.h" +#include "common.h" + +static INLINE void nothing(void) {} + +void objc_wrap(struct criterion_test *test, struct criterion_suite *suite) { + + criterion_send_event(PRE_INIT, NULL, 0); + @try { + if (suite->data) + (suite->data->init ? suite->data->init : nothing)(); + (test->data->init ? test->data->init : nothing)(); + } + @catch (NSException *e) { + NSString *reason = [e reason]; + criterion_test_die("Caught an unexpected exception during the test initialization: %s.", [reason UTF8String]); + } + @catch (...) { + criterion_test_die("Caught some unexpected exception during the test initialization."); + } + criterion_send_event(PRE_TEST, NULL, 0); + + struct timespec_compat ts; + if (!setjmp(g_pre_test)) { + timer_start(&ts); + if (test->test) { + @try { + if (!test->data->param_) { + test->test(); + } else { + void(*param_test_func)(void *) = (void(*)(void*)) test->test; + param_test_func(g_worker_context.param->ptr); + } + } + @catch (NSException *e) { + NSString *reason = [e reason]; + criterion_test_die("Caught an unexpected exception during the test execution: %s.", [reason UTF8String]); + } + @catch (...) { + criterion_test_die("Caught some unexpected exception during the test execution."); + } + } + } + + double elapsed_time; + if (!timer_end(&elapsed_time, &ts)) + elapsed_time = -1; + + criterion_send_event(POST_TEST, &elapsed_time, sizeof(double)); + @try { + (test->data->fini ? test->data->fini : nothing)(); + if (suite->data) + (suite->data->fini ? suite->data->fini : nothing)(); + } + @catch (NSException *e) { + NSString *reason = [e reason]; + criterion_test_die("Caught an unexpected exception during the test finalization: %s.", [reason UTF8String]); + } + @catch (...) { + criterion_test_die("Caught some unexpected exception during the test finalization."); + } + criterion_send_event(POST_FINI, NULL, 0); + +} From 317c851581ace17cefdeab51d053664dc45b38ce Mon Sep 17 00:00:00 2001 From: Snaipe Date: Mon, 5 Oct 2015 11:13:28 +0200 Subject: [PATCH 071/211] Added objective C support on travis builds --- .travis.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 07926e03..a4a4c06d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -15,6 +15,7 @@ addons: packages: - gcc-4.9 - g++-4.9 + - gobjc-4.9 env: global: GCOV: gcov-4.9 @@ -34,7 +35,7 @@ script: -DCOVERALLS=${COVERAGE} -DCMAKE_BUILD_TYPE=${CONFIGURATION} -DCMAKE_INSTALL_PREFIX=criterion-${TRAVIS_TAG} - -DLANGUAGES=CXX + -DLANGUAGES=CXX,ObjectiveC .. - TERM=dumb cmake --build . --target criterion_tests -- -j4 - ctest -j4 From 02d46df36048139736dacf354d94cf416da65842 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Mon, 5 Oct 2015 13:55:02 +0200 Subject: [PATCH 072/211] Revert "Added objective C support on travis builds" This reverts commit 317c851581ace17cefdeab51d053664dc45b38ce. --- .travis.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index a4a4c06d..07926e03 100644 --- a/.travis.yml +++ b/.travis.yml @@ -15,7 +15,6 @@ addons: packages: - gcc-4.9 - g++-4.9 - - gobjc-4.9 env: global: GCOV: gcov-4.9 @@ -35,7 +34,7 @@ script: -DCOVERALLS=${COVERAGE} -DCMAKE_BUILD_TYPE=${CONFIGURATION} -DCMAKE_INSTALL_PREFIX=criterion-${TRAVIS_TAG} - -DLANGUAGES=CXX,ObjectiveC + -DLANGUAGES=CXX .. - TERM=dumb cmake --build . --target criterion_tests -- -j4 - ctest -j4 From 0d3537d891438d59fc61a22e4b4600412f7b9421 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Mon, 5 Oct 2015 16:22:16 +0200 Subject: [PATCH 073/211] Refactored strtok_r compatibility layer to compat/posix.h --- po/fr.po | 36 ++++++++++++++++++------------------ src/compat/posix.h | 22 +++++++++++++++++++--- src/log/normal.c | 14 -------------- src/log/tap.c | 14 -------------- 4 files changed, 37 insertions(+), 49 deletions(-) diff --git a/po/fr.po b/po/fr.po index 65717ee0..e6c75a48 100644 --- a/po/fr.po +++ b/po/fr.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: criterion 2.0.0\n" "Report-Msgid-Bugs-To: franklinmathieu+criterion@gmail.com\n" -"POT-Creation-Date: 2015-10-01 23:09+0200\n" +"POT-Creation-Date: 2015-10-05 16:20+0200\n" "PO-Revision-Date: 2015-04-03 17:58+0200\n" "Last-Translator: \n" "Language-Team: French\n" @@ -18,70 +18,70 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n" -#: src/log/normal.c:50 +#: src/log/normal.c:41 #, c-format msgid "Criterion v%s\n" msgstr "Criterion v%s\n" -#: src/log/normal.c:51 +#: src/log/normal.c:42 #, c-format msgid " %s\n" msgstr " %s\n" -#: src/log/normal.c:54 src/log/normal.c:56 +#: src/log/normal.c:45 src/log/normal.c:47 #, c-format msgid "%1$s::%2$s\n" msgstr "%1$s::%2$s\n" -#: src/log/normal.c:55 +#: src/log/normal.c:46 #, fuzzy, c-format msgid "%1$s::%2$s: (%3$3.2fs)\n" msgstr "%1$s::%2$s: (%3$3.2fs)\n" -#: src/log/normal.c:57 +#: src/log/normal.c:48 #, c-format msgid "%1$s::%2$s: Test is disabled\n" msgstr "%1$s::%2$s: Le test est désactivé\n" -#: src/log/normal.c:58 +#: src/log/normal.c:49 #, c-format msgid "%1$s::%2$s: Suite is disabled\n" msgstr "%1$s::%2$s: La suite est désactivée\n" -#: src/log/normal.c:59 +#: src/log/normal.c:50 #, c-format msgid "%1$s%2$s%3$s:%4$s%5$d%6$s: Assertion failed: %7$s\n" msgstr "%1$s%2$s%3$s:%4$s%5$d%6$s: Échec d'assertion: %7$s\n" -#: src/log/normal.c:60 +#: src/log/normal.c:51 #, fuzzy, c-format msgid " Theory %1$s::%2$s failed with the following parameters: (%3$s)\n" msgstr "" " La théorie %1$s::%2$s a échoué avec les paramètres suivants: (%3$s)\n" -#: src/log/normal.c:61 +#: src/log/normal.c:52 #, fuzzy, c-format msgid "%1$s::%2$s: Timed out. (%3$3.2fs)\n" msgstr "%1$s::%2$s: Délai expiré. (%3$3.2fs)\n" -#: src/log/normal.c:62 +#: src/log/normal.c:53 #, c-format msgid "%1$s%2$s%3$s:%4$s%5$u%6$s: Unexpected signal caught below this line!\n" msgstr "" "%1$s%2$s%3$s:%4$s%5$u%6$s: Un signal inattendu a été reçu après cette " "ligne!\n" -#: src/log/normal.c:63 +#: src/log/normal.c:54 #, c-format msgid "%1$s::%2$s: CRASH!\n" msgstr "%1$s::%2$s: PLANTAGE!\n" -#: src/log/normal.c:64 +#: src/log/normal.c:55 #, fuzzy, c-format msgid "%1$s::%2$s: %3$s\n" msgstr "%1$s::%2$s: (%3$3.2fs)\n" -#: src/log/normal.c:65 +#: src/log/normal.c:56 #, fuzzy, c-format msgid "" "%1$sWarning! The test `%2$s::%3$s` crashed during its setup or teardown." @@ -90,7 +90,7 @@ msgstr "" "%1$sAttention! Le test `%2$s::%3$s` a planté pendant son initialisation ou " "sa finalisation.%4$s\n" -#: src/log/normal.c:66 +#: src/log/normal.c:57 #, fuzzy, c-format msgid "" "%1$sWarning! The test `%2$s::%3$s` exited during its setup or teardown.%4$s\n" @@ -98,14 +98,14 @@ msgstr "" "%1$sAttention! Le test `%2$s::%3$s` a quitté pendant son initialisation ou " "sa finalisation.%4$s\n" -#: src/log/normal.c:67 +#: src/log/normal.c:58 #, c-format msgid "Running %1$s%2$lu%3$s test from %4$s%5$s%6$s:\n" msgid_plural "Running %1$s%2$lu%3$s tests from %4$s%5$s%6$s:\n" msgstr[0] "Lancement de %1$s%2$lu%3$s test dans %4$s%5$s%6$s:\n" msgstr[1] "Lancement de %1$s%2$lu%3$s tests dans %4$s%5$s%6$s:\n" -#: src/log/normal.c:69 +#: src/log/normal.c:60 #, c-format msgid "" "%1$sSynthesis: Tested: %2$s%3$lu%4$s | Passing: %5$s%6$lu%7$s | Failing: %8$s" @@ -114,7 +114,7 @@ msgstr "" "%1$sSynthèse: Testés: %2$s%3$lu%4$s | Validés: %5$s%6$lu%7$s | Échoués: %8$s" "%9$lu%10$s | Plantages: %11$s%12$lu%13$s %14$s\n" -#: src/log/normal.c:85 +#: src/log/normal.c:76 #, fuzzy, c-format msgid "%s::%s: %s\n" msgstr "%1$s::%2$s: (%3$3.2fs)\n" diff --git a/src/compat/posix.h b/src/compat/posix.h index fc0e8d8a..fdd634ca 100644 --- a/src/compat/posix.h +++ b/src/compat/posix.h @@ -24,9 +24,11 @@ #ifndef POSIX_COMPAT_H_ # define POSIX_COMPAT_H_ -#if defined(_WIN32) && !defined(__CYGWIN__) -# define VANILLA_WIN32 -#endif +# include "config.h" + +# if defined(_WIN32) && !defined(__CYGWIN__) +# define VANILLA_WIN32 +# endif # if defined(BSD) \ || defined(__FreeBSD__) \ @@ -45,6 +47,7 @@ # define off64_t _off64_t # endif # include +# include # if defined(__MINGW32__) || defined(__MINGW64__) # undef off_t # undef off64_t @@ -62,6 +65,19 @@ # define SIGPROF 27 # define CR_EXCEPTION_TIMEOUT 0xC0001042 + +# if HAVE_STRTOK_S +# define strtok_r strtok_s +# else +static CR_INLINE char *strtok_r(char *str, const char *delim, CR_UNUSED char **saveptr) { + return strtok(str, delim); +} +# endif + +# ifdef _MSC_VER +# define strdup _strdup +# endif + # else # include # endif diff --git a/src/log/normal.c b/src/log/normal.c index ba86e6fd..78b2ece2 100644 --- a/src/log/normal.c +++ b/src/log/normal.c @@ -36,20 +36,6 @@ #include "config.h" #include "common.h" -#ifdef VANILLA_WIN32 -# if HAVE_STRTOK_S -# define strtok_r strtok_s -# else - static char *strtok_r(char *str, const char *delim, CR_UNUSED char **saveptr) { - return strtok(str, delim); - } -# endif -#endif - -#ifdef _MSC_VER -# define strdup _strdup -#endif - typedef const char *const msg_t; static msg_t msg_pre_all = N_("Criterion v%s\n"); diff --git a/src/log/tap.c b/src/log/tap.c index 8e3bab97..5922fb25 100644 --- a/src/log/tap.c +++ b/src/log/tap.c @@ -34,20 +34,6 @@ #include "config.h" #include "common.h" -#ifdef VANILLA_WIN32 -# if HAVE_STRTOK_S -# define strtok_r strtok_s -# else - static char *strtok_r(char *str, const char *delim, CR_UNUSED char **saveptr) { - return strtok(str, delim); - } -# endif -#endif - -#ifdef _MSC_VER -# define strdup _strdup -#endif - static void print_prelude(struct criterion_global_stats *stats) { criterion_important("TAP version 13\n1.." CR_SIZE_T_FORMAT From a838e7786fcb9b9f84ea596f06c48ff33fcc43e4 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Mon, 5 Oct 2015 16:22:55 +0200 Subject: [PATCH 074/211] Added XML logging --- CMakeLists.txt | 1 + include/criterion/logging.h | 2 + src/entry/main.c | 5 + src/log/xml.c | 188 ++++++++++++++++++++++++++++++++++++ 4 files changed, 196 insertions(+) create mode 100644 src/log/xml.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 559f093d..f3b6e5df 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -129,6 +129,7 @@ set(SOURCE_FILES src/log/logging.c src/log/tap.c src/log/normal.c + src/log/xml.c src/string/i18n.c src/string/i18n.h src/entry/options.c diff --git a/include/criterion/logging.h b/include/criterion/logging.h index aca55ce2..450023be 100644 --- a/include/criterion/logging.h +++ b/include/criterion/logging.h @@ -121,10 +121,12 @@ struct criterion_output_provider { extern struct criterion_output_provider normal_logging; extern struct criterion_output_provider tap_logging; +extern struct criterion_output_provider xml_logging; CR_END_C_API #define CR_NORMAL_LOGGING (&normal_logging) #define CR_TAP_LOGGING (&tap_logging) +#define CR_XML_LOGGING (&xml_logging) #endif /* !CRITERION_LOGGING_H_ */ diff --git a/src/entry/main.c b/src/entry/main.c index d67989f0..5c1de36d 100644 --- a/src/entry/main.c +++ b/src/entry/main.c @@ -130,6 +130,7 @@ int criterion_handle_args(int argc, char *argv[], bool handle_unknown_arg) { {"verbose", optional_argument, 0, 'b'}, {"version", no_argument, 0, 'v'}, {"tap", no_argument, 0, 't'}, + {"xml", no_argument, 0, 'x'}, {"help", no_argument, 0, 'h'}, {"list", no_argument, 0, 'l'}, {"ascii", no_argument, 0, 'k'}, @@ -182,6 +183,7 @@ int criterion_handle_args(int argc, char *argv[], bool handle_unknown_arg) { #endif bool use_tap = !strcmp("1", DEF(getenv("CRITERION_ENABLE_TAP"), "0")); + bool use_xml = !strcmp("1", DEF(getenv("CRITERION_ENABLE_XML"), "0")); bool do_list_tests = false; bool do_print_version = false; @@ -199,6 +201,7 @@ int criterion_handle_args(int argc, char *argv[], bool handle_unknown_arg) { case 'p': criterion_options.pattern = optarg; break; #endif case 't': use_tap = true; break; + case 'x': use_xml = true; break; case 'l': do_list_tests = true; break; case 'v': do_print_version = true; break; case 'h': do_print_usage = true; break; @@ -207,6 +210,8 @@ int criterion_handle_args(int argc, char *argv[], bool handle_unknown_arg) { } if (use_tap) criterion_options.output_provider = CR_TAP_LOGGING; + else if (use_xml) + criterion_options.output_provider = CR_XML_LOGGING; if (do_print_usage) return print_usage(argv[0]); if (do_print_version) diff --git a/src/log/xml.c b/src/log/xml.c new file mode 100644 index 00000000..eb9be513 --- /dev/null +++ b/src/log/xml.c @@ -0,0 +1,188 @@ +/* + * The MIT License (MIT) + * + * Copyright © 2015 Franklin "Snaipe" Mathieu + * + * 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. + */ +#define _GNU_SOURCE +#include +#include +#include +#include "criterion/stats.h" +#include "criterion/logging.h" +#include "criterion/options.h" +#include "criterion/ordered-set.h" +#include "compat/posix.h" +#include "compat/time.h" +#include "config.h" +#include "common.h" + +#define TESTSUITES_PROPERTIES \ + "name=\"Criterion Tests\" " \ + "tests=\"" CR_SIZE_T_FORMAT "\" " \ + "failures=\"" CR_SIZE_T_FORMAT "\" " \ + "errors=\"" CR_SIZE_T_FORMAT "\" " \ + "disabled=\"" CR_SIZE_T_FORMAT "\"" + +#define XML_BASE_TEMPLATE_BEGIN \ + "\n" \ + "\n" \ + "\n" \ + +#define XML_BASE_TEMPLATE_END \ + "\n" + +#define TESTSUITE_PROPERTIES \ + "name=\"%s\" " \ + "tests=\"" CR_SIZE_T_FORMAT "\" " \ + "failures=\"" CR_SIZE_T_FORMAT "\" " \ + "errors=\"" CR_SIZE_T_FORMAT "\" " \ + "disabled=\"" CR_SIZE_T_FORMAT "\" " \ + "skipped=\"" CR_SIZE_T_FORMAT "\"" + +#define XML_TESTSUITE_TEMPLATE_BEGIN \ + " \n" + +#define XML_TESTSUITE_TEMPLATE_END \ + " \n" + +#define TEST_PROPERTIES \ + "name=\"%s\" " \ + "assertions=\"" CR_SIZE_T_FORMAT "\" " \ + "status=\"%s\"" + +#define XML_TEST_TEMPLATE_BEGIN \ + " \n" \ + +#define XML_TEST_TEMPLATE_END \ + " \n" + +#define XML_TEST_SKIPPED " \n" + +#define LF " " + +#define XML_FAILURE_MSG_ENTRY \ + "%s:%u: %s" LF + +#define XML_TEST_FAILED_TEMPLATE_BEGIN \ + " " + +#define XML_TEST_FAILED_TEMPLATE_END \ + "\n" + +#define XML_CRASH_MSG_ENTRY \ + " " + +#define XML_TIMEOUT_MSG_ENTRY \ + " " + +static INLINE bool is_disabled(struct criterion_test *t, struct criterion_suite *s) { + return t->data->disabled || (s->data && s->data->disabled); +} + +static CR_INLINE +const char *get_status_string(struct criterion_test_stats *ts, + struct criterion_suite_stats *ss) { + + const char *status = "PASSED"; + if (ts->crashed || ts->timed_out) + status = "ERRORED"; + else if (ts->failed) + status = "FAILED"; + else if (is_disabled(ts->test, ss->suite)) + status = "SKIPPED"; + return status; +} + +static void print_test(struct criterion_test_stats *ts, + struct criterion_suite_stats *ss) { + + criterion_important(XML_TEST_TEMPLATE_BEGIN, + ts->test->name, + (size_t) (ts->passed_asserts + ts->failed_asserts), + get_status_string(ts, ss) + ); + + if (is_disabled(ts->test, ss->suite)) { + criterion_important(XML_TEST_SKIPPED); + } else if (ts->crashed) { + criterion_important(XML_CRASH_MSG_ENTRY); + } else if (ts->timed_out) { + criterion_important(XML_TIMEOUT_MSG_ENTRY); + } else { + if (ts->failed) { + criterion_important(XML_TEST_FAILED_TEMPLATE_BEGIN, ts->failed_asserts); + for (struct criterion_assert_stats *asrt = ts->asserts; asrt; asrt = asrt->next) { + if (!asrt->passed) { + bool sf = criterion_options.short_filename; + char *dup = strdup(*asrt->message ? asrt->message : ""); + char *saveptr = NULL; + char *line = strtok_r(dup, "\n", &saveptr); + + criterion_important(XML_FAILURE_MSG_ENTRY, + sf ? basename_compat(asrt->file) : asrt->file, + asrt->line, + line + ); + + while ((line = strtok_r(NULL, "\n", &saveptr))) + criterion_important(" %s" LF, line); + free(dup); + } + } + criterion_important(XML_TEST_FAILED_TEMPLATE_END); + } + } + + criterion_important(XML_TEST_TEMPLATE_END); +} + +void xml_log_post_all(struct criterion_global_stats *stats) { + criterion_important(XML_BASE_TEMPLATE_BEGIN, + stats->nb_tests, + stats->tests_failed, + stats->tests_crashed, + stats->tests_skipped + ); + + for (struct criterion_suite_stats *ss = stats->suites; ss; ss = ss->next) { + + criterion_important(XML_TESTSUITE_TEMPLATE_BEGIN, + ss->suite->name, + ss->nb_tests, + ss->tests_failed, + ss->tests_crashed, + ss->tests_skipped, + ss->tests_skipped + ); + + for (struct criterion_test_stats *ts = ss->tests; ts; ts = ts->next) { + print_test(ts, ss); + } + + criterion_important(XML_TESTSUITE_TEMPLATE_END); + } + + criterion_important(XML_BASE_TEMPLATE_END); +} + +struct criterion_output_provider xml_logging = { + .log_post_all = xml_log_post_all, +}; From c0e7486df3b422fce7ed9bdcd1fa58da2ce8cefb Mon Sep 17 00:00:00 2001 From: Snaipe Date: Mon, 5 Oct 2015 16:26:25 +0200 Subject: [PATCH 075/211] Added --xml to help message and documentation --- doc/env.rst | 2 ++ src/entry/main.c | 1 + 2 files changed, 3 insertions(+) diff --git a/doc/env.rst b/doc/env.rst index 97ab252c..d3e6aee9 100644 --- a/doc/env.rst +++ b/doc/env.rst @@ -23,6 +23,7 @@ Command line arguments * ``-S or --short-filename``: The filenames are displayed in their short form. * ``--always-succeed``: The process shall exit with a status of ``0``. * ``--tap``: Enables the TAP (Test Anything Protocol) output format. +* ``--xml``: Enables the JUnit4 XML output format. * ``--verbose[=level]``: Makes the output verbose. When provided with an integer, sets the verbosity level to that integer. @@ -71,6 +72,7 @@ Environment variables are alternatives to command line switches when set to 1. * ``CRITERION_ALWAYS_SUCCEED``: Same as ``--always-succeed``. * ``CRITERION_NO_EARLY_EXIT``: Same as ``--no-early-exit``. * ``CRITERION_ENABLE_TAP``: Same as ``--tap``. +* ``CRITERION_ENABLE_XML``: Same as ``--xml``. * ``CRITERION_FAIL_FAST``: Same as ``--fail-fast``. * ``CRITERION_USE_ASCII``: Same as ``--ascii``. * ``CRITERION_JOBS``: Same as ``jobs``. Sets the number of jobs to diff --git a/src/entry/main.c b/src/entry/main.c index 5c1de36d..6b5f914d 100644 --- a/src/entry/main.c +++ b/src/entry/main.c @@ -62,6 +62,7 @@ "name of the source file on a failure\n" \ PATTERN_USAGE \ " --tap: enables TAP formatting\n" \ + " --xml: enables XML formatting\n" \ " --always-succeed: always exit with 0\n" \ " --no-early-exit: do not exit the test worker " \ "prematurely after the test\n" \ From ec6ea154913f4ba91c7318c2f8d2e5d668e95ee2 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Mon, 5 Oct 2015 19:11:59 +0200 Subject: [PATCH 076/211] Added IRC channel to README page --- README.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index a9d2edb1..cd345d42 100644 --- a/README.md +++ b/README.md @@ -77,7 +77,8 @@ Sample tests can be found in the [sample directory][samples]. ### Getting help -Gitter.im chat room: [![Join the chat at https://gitter.im/Snaipe/Criterion](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/Snaipe/Criterion?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) +Gitter.im chat room: [![Join the chat at https://gitter.im/Snaipe/Criterion](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/Snaipe/Criterion?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) +IRC channel: [#criterion][irc-chan] on irc.freenode.net ### Misc @@ -101,3 +102,5 @@ Logo done by [Greehm](http://www.cargocollective.com/pbouigue) [sample-report]: ./samples/report.c [find-module]: ./dev/FindCriterion.cmake + +[irc-chan]: http://webchat.freenode.net/?channels=%23criterion&uio=MTY9dHJ1ZSYyPXRydWUmOT10cnVlJjExPTE5NQ4e From 15f3af54fe0f4a8d4964291b7b188494b7ddb70d Mon Sep 17 00:00:00 2001 From: Snaipe Date: Mon, 5 Oct 2015 19:54:49 +0200 Subject: [PATCH 077/211] Fixed compilation error on MinGW due to how C++ attributes are handled --- src/compat/posix.h | 14 -------------- src/compat/strtok.h | 43 +++++++++++++++++++++++++++++++++++++++++++ src/log/normal.c | 1 + src/log/tap.c | 1 + src/log/xml.c | 1 + 5 files changed, 46 insertions(+), 14 deletions(-) create mode 100644 src/compat/strtok.h diff --git a/src/compat/posix.h b/src/compat/posix.h index fdd634ca..4468f63e 100644 --- a/src/compat/posix.h +++ b/src/compat/posix.h @@ -24,8 +24,6 @@ #ifndef POSIX_COMPAT_H_ # define POSIX_COMPAT_H_ -# include "config.h" - # if defined(_WIN32) && !defined(__CYGWIN__) # define VANILLA_WIN32 # endif @@ -66,18 +64,6 @@ # define SIGPROF 27 # define CR_EXCEPTION_TIMEOUT 0xC0001042 -# if HAVE_STRTOK_S -# define strtok_r strtok_s -# else -static CR_INLINE char *strtok_r(char *str, const char *delim, CR_UNUSED char **saveptr) { - return strtok(str, delim); -} -# endif - -# ifdef _MSC_VER -# define strdup _strdup -# endif - # else # include # endif diff --git a/src/compat/strtok.h b/src/compat/strtok.h new file mode 100644 index 00000000..6dbe96ce --- /dev/null +++ b/src/compat/strtok.h @@ -0,0 +1,43 @@ +/* + * The MIT License (MIT) + * + * Copyright © 2015 Franklin "Snaipe" Mathieu + * + * 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 COMPAT_STRTOK_H_ +# define COMPAT_STRTOK_H_ + +# include "config.h" + +# ifdef VANILLA_WIN32 +# if HAVE_STRTOK_S +# define strtok_r strtok_s +# else +static CR_INLINE char *strtok_r(char *str, const char *delim, CR_UNUSED char **saveptr) { + return strtok(str, delim); +} +# endif + +# ifdef _MSC_VER +# define strdup _strdup +# endif +# endif + +#endif /* !COMPAT_STRTOK_H_ */ diff --git a/src/log/normal.c b/src/log/normal.c index 78b2ece2..f7319d38 100644 --- a/src/log/normal.c +++ b/src/log/normal.c @@ -31,6 +31,7 @@ #include "criterion/options.h" #include "criterion/ordered-set.h" #include "compat/posix.h" +#include "compat/strtok.h" #include "compat/time.h" #include "string/i18n.h" #include "config.h" diff --git a/src/log/tap.c b/src/log/tap.c index 5922fb25..c960951e 100644 --- a/src/log/tap.c +++ b/src/log/tap.c @@ -30,6 +30,7 @@ #include "criterion/options.h" #include "criterion/ordered-set.h" #include "compat/posix.h" +#include "compat/strtok.h" #include "compat/time.h" #include "config.h" #include "common.h" diff --git a/src/log/xml.c b/src/log/xml.c index eb9be513..fd7c9d6f 100644 --- a/src/log/xml.c +++ b/src/log/xml.c @@ -30,6 +30,7 @@ #include "criterion/options.h" #include "criterion/ordered-set.h" #include "compat/posix.h" +#include "compat/strtok.h" #include "compat/time.h" #include "config.h" #include "common.h" From 72d47ef43cd6a07d8fb91f4abc3afc7fcb0c0dab Mon Sep 17 00:00:00 2001 From: Snaipe Date: Tue, 6 Oct 2015 14:58:46 +0200 Subject: [PATCH 078/211] Added xml tests --- samples/CMakeLists.txt | 1 + samples/tests/xml_test.sh | 7 +++++++ 2 files changed, 8 insertions(+) create mode 100755 samples/tests/xml_test.sh diff --git a/samples/CMakeLists.txt b/samples/CMakeLists.txt index 7bde575c..1d850587 100644 --- a/samples/CMakeLists.txt +++ b/samples/CMakeLists.txt @@ -34,6 +34,7 @@ set(SAMPLES set(SCRIPTS tap_test + xml_test early_exit verbose list diff --git a/samples/tests/xml_test.sh b/samples/tests/xml_test.sh new file mode 100755 index 00000000..9f0ab261 --- /dev/null +++ b/samples/tests/xml_test.sh @@ -0,0 +1,7 @@ +#!/bin/sh +./simple.c.bin --xml --always-succeed +./signal.c.bin --xml --always-succeed +./asserts.c.bin --xml --always-succeed +./more-suites.c.bin --xml --always-succeed +./long-messages.c.bin --xml --always-succeed +./description.c.bin --xml --always-succeed From 3733c858cb195878f11fb84962346430d339a173 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Tue, 6 Oct 2015 15:44:09 +0200 Subject: [PATCH 079/211] Fixed regression tests sometimes failing because of them being time-dependent --- include/criterion/options.h | 1 + samples/CMakeLists.txt | 1 + samples/outputs/asserts.c.bin.err.expected | 4 ++-- samples/outputs/asserts.cc.bin.err.expected | 8 ++++---- samples/outputs/description.c.bin.err.expected | 2 +- .../outputs/description.cc.bin.err.expected | 2 +- .../outputs/parameterized.c.bin.err.expected | 18 +++++++++--------- samples/outputs/report.c.bin.err.expected | 2 +- samples/outputs/report.cc.bin.err.expected | 2 +- samples/outputs/signal.c.bin.err.expected | 2 +- samples/outputs/signal.cc.bin.err.expected | 2 +- samples/outputs/simple.c.bin.err.expected | 2 +- samples/outputs/simple.cc.bin.err.expected | 2 +- .../outputs/failmessages.c.bin.err.expected | 4 ++-- .../outputs/failmessages.cc.bin.err.expected | 4 ++-- .../outputs/long-messages.c.bin.err.expected | 2 +- .../outputs/long-messages.cc.bin.err.expected | 2 +- .../theories_regression.c.bin.err.expected | 4 ++-- .../theories_regression.cc.bin.err.expected | 4 ++-- src/compat/time.c | 9 ++++----- src/entry/main.c | 2 ++ src/entry/options.c | 1 + 22 files changed, 42 insertions(+), 38 deletions(-) diff --git a/include/criterion/options.h b/include/criterion/options.h index 49c05486..ee3a9c37 100644 --- a/include/criterion/options.h +++ b/include/criterion/options.h @@ -37,6 +37,7 @@ struct criterion_options { const char *pattern; bool short_filename; size_t jobs; + bool measure_time; }; CR_BEGIN_C_API diff --git a/samples/CMakeLists.txt b/samples/CMakeLists.txt index 7bde575c..ada809f1 100644 --- a/samples/CMakeLists.txt +++ b/samples/CMakeLists.txt @@ -67,6 +67,7 @@ macro(add_samples DIR_ SAMPLES_) ENVIRONMENT "CRITERION_SHORT_FILENAME=1" ENVIRONMENT "CRITERION_NO_EARLY_EXIT=1" # for coverage ENVIRONMENT "CRITERION_JOBS=1" # for output ordering + ENVIRONMENT "CRITERION_DISABLE_TIME_MEASUREMENTS=1" # do not compare timings ) endif () endforeach() diff --git a/samples/outputs/asserts.c.bin.err.expected b/samples/outputs/asserts.c.bin.err.expected index 95d9a944..10e2e904 100644 --- a/samples/outputs/asserts.c.bin.err.expected +++ b/samples/outputs/asserts.c.bin.err.expected @@ -1,7 +1,7 @@ [----] asserts.c:11: Assertion failed: assert is fatal, expect isn't [----] asserts.c:12: Assertion failed: This assert runs -[FAIL] asserts::base: (0.00s) +[FAIL] asserts::base [----] asserts.c:17: Assertion failed: You can fail an assertion with a message from anywhere [----] asserts.c:18: Assertion failed: The conditions for this assertion were not met. -[FAIL] asserts::old_school: (0.00s) +[FAIL] asserts::old_school [====] Synthesis: Tested: 6 | Passing: 4 | Failing: 2 | Crashing: 0  diff --git a/samples/outputs/asserts.cc.bin.err.expected b/samples/outputs/asserts.cc.bin.err.expected index ebeb3553..ddc7623e 100644 --- a/samples/outputs/asserts.cc.bin.err.expected +++ b/samples/outputs/asserts.cc.bin.err.expected @@ -1,11 +1,11 @@ [----] asserts.cc:83: Assertion failed: The expression (&s1)[0 .. 2] == (&s2)[0 .. 2] is false. -[FAIL] asserts::array: (0.00s) +[FAIL] asserts::array [----] asserts.cc:13: Assertion failed: assert is fatal, expect isn't [----] asserts.cc:14: Assertion failed: This assert runs -[FAIL] asserts::base: (0.00s) +[FAIL] asserts::base [----] asserts.cc:89: Assertion failed: The statement `throw std::exception()` did not throw an instance of the `std::bad_alloc` exception. -[FAIL] asserts::exception: (0.00s) +[FAIL] asserts::exception [----] asserts.cc:19: Assertion failed: You can fail an assertion with a message from anywhere [----] asserts.cc:20: Assertion failed: The conditions for this assertion were not met. -[FAIL] asserts::old_school: (0.00s) +[FAIL] asserts::old_school [====] Synthesis: Tested: 7 | Passing: 3 | Failing: 4 | Crashing: 0  diff --git a/samples/outputs/description.c.bin.err.expected b/samples/outputs/description.c.bin.err.expected index 2cc0d104..ffcd02dd 100644 --- a/samples/outputs/description.c.bin.err.expected +++ b/samples/outputs/description.c.bin.err.expected @@ -1,3 +1,3 @@ [----] description.c:4: Assertion failed: The expression 0 is false. -[FAIL] misc::failing: (0.00s) +[FAIL] misc::failing [====] Synthesis: Tested: 1 | Passing: 0 | Failing: 1 | Crashing: 0  diff --git a/samples/outputs/description.cc.bin.err.expected b/samples/outputs/description.cc.bin.err.expected index b9cebe4b..ff63cc4f 100644 --- a/samples/outputs/description.cc.bin.err.expected +++ b/samples/outputs/description.cc.bin.err.expected @@ -1,3 +1,3 @@ [----] description.cc:4: Assertion failed: The expression 0 is false. -[FAIL] misc::failing: (0.00s) +[FAIL] misc::failing [====] Synthesis: Tested: 1 | Passing: 0 | Failing: 1 | Crashing: 0  diff --git a/samples/outputs/parameterized.c.bin.err.expected b/samples/outputs/parameterized.c.bin.err.expected index a080c6d6..62992988 100644 --- a/samples/outputs/parameterized.c.bin.err.expected +++ b/samples/outputs/parameterized.c.bin.err.expected @@ -1,19 +1,19 @@ [----] parameterized.c:76: Assertion failed: Parameters: (1, 2.000000) -[FAIL] params::cleanup: (0.00s) +[FAIL] params::cleanup [----] parameterized.c:76: Assertion failed: Parameters: (3, 4.000000) -[FAIL] params::cleanup: (0.00s) +[FAIL] params::cleanup [----] parameterized.c:76: Assertion failed: Parameters: (5, 6.000000) -[FAIL] params::cleanup: (0.00s) +[FAIL] params::cleanup [----] parameterized.c:36: Assertion failed: Parameters: (1, 2.000000) -[FAIL] params::multiple: (0.00s) +[FAIL] params::multiple [----] parameterized.c:36: Assertion failed: Parameters: (3, 4.000000) -[FAIL] params::multiple: (0.00s) +[FAIL] params::multiple [----] parameterized.c:36: Assertion failed: Parameters: (5, 6.000000) -[FAIL] params::multiple: (0.00s) +[FAIL] params::multiple [----] parameterized.c:15: Assertion failed: Parameter: foo -[FAIL] params::str: (0.00s) +[FAIL] params::str [----] parameterized.c:15: Assertion failed: Parameter: bar -[FAIL] params::str: (0.00s) +[FAIL] params::str [----] parameterized.c:15: Assertion failed: Parameter: baz -[FAIL] params::str: (0.00s) +[FAIL] params::str [====] Synthesis: Tested: 9 | Passing: 0 | Failing: 9 | Crashing: 0  diff --git a/samples/outputs/report.c.bin.err.expected b/samples/outputs/report.c.bin.err.expected index f08bf9aa..5de68252 100644 --- a/samples/outputs/report.c.bin.err.expected +++ b/samples/outputs/report.c.bin.err.expected @@ -1,3 +1,3 @@ [----] report.c:5: Assertion failed: The expression 0 is false. -[FAIL] sample::test: (0.00s) +[FAIL] sample::test [====] Synthesis: Tested: 1 | Passing: 0 | Failing: 1 | Crashing: 0  diff --git a/samples/outputs/report.cc.bin.err.expected b/samples/outputs/report.cc.bin.err.expected index 72c59aa4..0436a29f 100644 --- a/samples/outputs/report.cc.bin.err.expected +++ b/samples/outputs/report.cc.bin.err.expected @@ -1,3 +1,3 @@ [----] report.cc:5: Assertion failed: The expression 0 is false. -[FAIL] sample::test: (0.00s) +[FAIL] sample::test [====] Synthesis: Tested: 1 | Passing: 0 | Failing: 1 | Crashing: 0  diff --git a/samples/outputs/signal.c.bin.err.expected b/samples/outputs/signal.c.bin.err.expected index 8bc2b303..02d96bb8 100644 --- a/samples/outputs/signal.c.bin.err.expected +++ b/samples/outputs/signal.c.bin.err.expected @@ -1,4 +1,4 @@ [----] signal.c:16: Unexpected signal caught below this line! [FAIL] simple::uncaught: CRASH! -[FAIL] simple::wrong_signal: (0.00s) +[FAIL] simple::wrong_signal [====] Synthesis: Tested: 3 | Passing: 1 | Failing: 2 | Crashing: 1  diff --git a/samples/outputs/signal.cc.bin.err.expected b/samples/outputs/signal.cc.bin.err.expected index 8ac44c18..8ec51039 100644 --- a/samples/outputs/signal.cc.bin.err.expected +++ b/samples/outputs/signal.cc.bin.err.expected @@ -1,4 +1,4 @@ [----] signal.cc:16: Unexpected signal caught below this line! [FAIL] simple::uncaught: CRASH! -[FAIL] simple::wrong_signal: (0.00s) +[FAIL] simple::wrong_signal [====] Synthesis: Tested: 3 | Passing: 1 | Failing: 2 | Crashing: 1  diff --git a/samples/outputs/simple.c.bin.err.expected b/samples/outputs/simple.c.bin.err.expected index a6878985..4898f354 100644 --- a/samples/outputs/simple.c.bin.err.expected +++ b/samples/outputs/simple.c.bin.err.expected @@ -1,3 +1,3 @@ [----] simple.c:4: Assertion failed: The expression 0 is false. -[FAIL] misc::failing: (0.00s) +[FAIL] misc::failing [====] Synthesis: Tested: 2 | Passing: 1 | Failing: 1 | Crashing: 0  diff --git a/samples/outputs/simple.cc.bin.err.expected b/samples/outputs/simple.cc.bin.err.expected index 816d6cd4..e2e6e05b 100644 --- a/samples/outputs/simple.cc.bin.err.expected +++ b/samples/outputs/simple.cc.bin.err.expected @@ -1,3 +1,3 @@ [----] simple.cc:4: Assertion failed: The expression 0 is false. -[FAIL] misc::failing: (0.00s) +[FAIL] misc::failing [====] Synthesis: Tested: 2 | Passing: 1 | Failing: 1 | Crashing: 0  diff --git a/samples/tests/outputs/failmessages.c.bin.err.expected b/samples/tests/outputs/failmessages.c.bin.err.expected index 3a6b0e7a..fc2dc0c6 100644 --- a/samples/tests/outputs/failmessages.c.bin.err.expected +++ b/samples/tests/outputs/failmessages.c.bin.err.expected @@ -17,7 +17,7 @@ [----] failmessages.c:22: Assertion failed: The expression (as strings) ("abc") <= ("aba") is false. [----] failmessages.c:23: Assertion failed: The expression (as strings) ("abc") > ("abd") is false. [----] failmessages.c:24: Assertion failed: The expression (as strings) ("abc") >= ("abd") is false. -[FAIL] messages::default: (0.00s) +[FAIL] messages::default [----] failmessages.c:28: Assertion failed: foo bar [----] failmessages.c:29: Assertion failed: foo bar [----] failmessages.c:30: Assertion failed: foo bar @@ -37,5 +37,5 @@ [----] failmessages.c:46: Assertion failed: foo bar [----] failmessages.c:47: Assertion failed: foo bar [----] failmessages.c:48: Assertion failed: foo bar -[FAIL] messages::user: (0.00s) +[FAIL] messages::user [====] Synthesis: Tested: 2 | Passing: 0 | Failing: 2 | Crashing: 0  diff --git a/samples/tests/outputs/failmessages.cc.bin.err.expected b/samples/tests/outputs/failmessages.cc.bin.err.expected index f060bace..5a573553 100644 --- a/samples/tests/outputs/failmessages.cc.bin.err.expected +++ b/samples/tests/outputs/failmessages.cc.bin.err.expected @@ -21,7 +21,7 @@ [----] failmessages.cc:28: Assertion failed: The statement `throw std::exception()` did throw an instance of the `std::exception` exception. [----] failmessages.cc:29: Assertion failed: The statement `{}` did not throw any exception. [----] failmessages.cc:30: Assertion failed: The statement `throw std::exception()` threw some exception. -[FAIL] messages::default: (0.00s) +[FAIL] messages::default [----] failmessages.cc:34: Assertion failed: foo bar [----] failmessages.cc:35: Assertion failed: foo bar [----] failmessages.cc:36: Assertion failed: foo bar @@ -45,5 +45,5 @@ [----] failmessages.cc:57: Assertion failed: foo bar [----] failmessages.cc:58: Assertion failed: foo bar [----] failmessages.cc:59: Assertion failed: foo bar -[FAIL] messages::user: (0.00s) +[FAIL] messages::user [====] Synthesis: Tested: 2 | Passing: 0 | Failing: 2 | Crashing: 0  diff --git a/samples/tests/outputs/long-messages.c.bin.err.expected b/samples/tests/outputs/long-messages.c.bin.err.expected index 9658ae52..f97a7f4e 100644 --- a/samples/tests/outputs/long-messages.c.bin.err.expected +++ b/samples/tests/outputs/long-messages.c.bin.err.expected @@ -2,5 +2,5 @@ [----] A long message [----] Spawning multiple lines. [----] Formatting is respected. -[FAIL] sample::long_msg: (0.00s) +[FAIL] sample::long_msg [====] Synthesis: Tested: 1 | Passing: 0 | Failing: 1 | Crashing: 0  diff --git a/samples/tests/outputs/long-messages.cc.bin.err.expected b/samples/tests/outputs/long-messages.cc.bin.err.expected index fa56cf28..0237997c 100644 --- a/samples/tests/outputs/long-messages.cc.bin.err.expected +++ b/samples/tests/outputs/long-messages.cc.bin.err.expected @@ -2,5 +2,5 @@ [----] A long message [----] Spawning multiple lines. [----] Formatting is respected. -[FAIL] sample::long_msg: (0.00s) +[FAIL] sample::long_msg [====] Synthesis: Tested: 1 | Passing: 0 | Failing: 1 | Crashing: 0  diff --git a/samples/tests/outputs/theories_regression.c.bin.err.expected b/samples/tests/outputs/theories_regression.c.bin.err.expected index 0db8e129..fa88f2bb 100644 --- a/samples/tests/outputs/theories_regression.c.bin.err.expected +++ b/samples/tests/outputs/theories_regression.c.bin.err.expected @@ -8,8 +8,8 @@ [----] Theory theory::gen failed with the following parameters: (4) [----] theories_regression.c:51: Assertion failed: The conditions for this assertion were not met. [----] Theory theory::gen failed with the following parameters: (5) -[FAIL] theory::gen: (0.00s) +[FAIL] theory::gen [----] theories_regression.c:34: Assertion failed: The conditions for this assertion were not met. [----] Theory theory::misc failed with the following parameters: ('a', true, 1, 1, 3.14f, 3.14, "test", "other test") -[FAIL] theory::misc: (0.00s) +[FAIL] theory::misc [====] Synthesis: Tested: 2 | Passing: 0 | Failing: 2 | Crashing: 0  diff --git a/samples/tests/outputs/theories_regression.cc.bin.err.expected b/samples/tests/outputs/theories_regression.cc.bin.err.expected index a4e378ef..03039376 100644 --- a/samples/tests/outputs/theories_regression.cc.bin.err.expected +++ b/samples/tests/outputs/theories_regression.cc.bin.err.expected @@ -8,8 +8,8 @@ [----] Theory theory::gen failed with the following parameters: (4) [----] theories_regression.cc:53: Assertion failed: The conditions for this assertion were not met. [----] Theory theory::gen failed with the following parameters: (5) -[FAIL] theory::gen: (0.00s) +[FAIL] theory::gen [----] theories_regression.cc:36: Assertion failed: The conditions for this assertion were not met. [----] Theory theory::misc failed with the following parameters: ('a', true, 1, 1, 3.14f, 3.14, "test", "other test") -[FAIL] theory::misc: (0.00s) +[FAIL] theory::misc [====] Synthesis: Tested: 2 | Passing: 0 | Failing: 2 | Crashing: 0  diff --git a/src/compat/time.c b/src/compat/time.c index 14de484f..f8c8fee7 100644 --- a/src/compat/time.c +++ b/src/compat/time.c @@ -2,6 +2,7 @@ #include #include #include "criterion/common.h" +#include "criterion/options.h" #include "compat/time.h" #include "compat/posix.h" @@ -28,6 +29,9 @@ extern __attribute__ ((weak)) int clock_gettime(clockid_t, struct timespec *); #endif bool can_measure_time(void) { + if (!criterion_options.measure_time) + return false; + #if defined(__unix__) && !defined(__CYGWIN__) return clock_gettime != NULL; #else @@ -128,11 +132,6 @@ int setup_timeout(uint64_t nanos) { CloseHandle(thread); return 0; #elif defined(__unix__) - if (!can_measure_time()) { - errno = ENOTSUP; - return -1; - } - timer_t timer; int res = timer_create(CLOCK_MONOTONIC, &(struct sigevent) { .sigev_notify = SIGEV_SIGNAL, diff --git a/src/entry/main.c b/src/entry/main.c index d67989f0..6de122aa 100644 --- a/src/entry/main.c +++ b/src/entry/main.c @@ -183,6 +183,8 @@ int criterion_handle_args(int argc, char *argv[], bool handle_unknown_arg) { bool use_tap = !strcmp("1", DEF(getenv("CRITERION_ENABLE_TAP"), "0")); + opt->measure_time = !!strcmp("1", DEF(getenv("CRITERION_DISABLE_TIME_MEASUREMENTS"), "0")); + bool do_list_tests = false; bool do_print_version = false; bool do_print_usage = false; diff --git a/src/entry/options.c b/src/entry/options.c index c83b294a..20295f92 100644 --- a/src/entry/options.c +++ b/src/entry/options.c @@ -26,4 +26,5 @@ struct criterion_options criterion_options = { .logging_threshold = CRITERION_IMPORTANT, .output_provider = &normal_logging, + .measure_time = true, }; From 06088a856c078714f75cb50368d4a10039609f95 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Tue, 6 Oct 2015 16:07:28 +0200 Subject: [PATCH 080/211] [Fixes #72] Added --jobs to help message --- src/entry/main.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/entry/main.c b/src/entry/main.c index cac5eace..8a8c5269 100644 --- a/src/entry/main.c +++ b/src/entry/main.c @@ -55,6 +55,7 @@ " -v or --version: prints the version of criterion " \ "these tests have been linked against\n" \ " -l or --list: prints all the tests in a list\n" \ + " -jN or --jobs N: use N concurrent jobs\n" \ " -f or --fail-fast: exit after the first failure\n" \ " --ascii: don't use fancy unicode symbols " \ "or colors in the output\n" \ From 2ecb8e164b6ae639514c2a88e94c57156b2e86eb Mon Sep 17 00:00:00 2001 From: Snaipe Date: Wed, 7 Oct 2015 13:07:11 +0200 Subject: [PATCH 081/211] Fixed criterion_handle_args printing an error message on unknown parameters when handle_unknown_arg is true --- src/entry/main.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/entry/main.c b/src/entry/main.c index 8a8c5269..007b3201 100644 --- a/src/entry/main.c +++ b/src/entry/main.c @@ -152,6 +152,9 @@ int criterion_handle_args(int argc, char *argv[], bool handle_unknown_arg) { textdomain (PACKAGE "-test"); #endif + if (!handle_unknown_arg) + opterr = 0; + char *env_always_succeed = getenv("CRITERION_ALWAYS_SUCCEED"); char *env_no_early_exit = getenv("CRITERION_NO_EARLY_EXIT"); char *env_fail_fast = getenv("CRITERION_FAIL_FAST"); @@ -209,6 +212,7 @@ int criterion_handle_args(int argc, char *argv[], bool handle_unknown_arg) { case 'l': do_list_tests = true; break; case 'v': do_print_version = true; break; case 'h': do_print_usage = true; break; + case '?': default : do_print_usage = handle_unknown_arg; break; } } From 0ee96494469eb3409a15d7ec4ff9d84f44eb48ba Mon Sep 17 00:00:00 2001 From: Snaipe Date: Wed, 7 Oct 2015 17:42:12 +0200 Subject: [PATCH 082/211] Fixed ObjectiveC cmake language to use the C compiler by default --- .../CMakeDetermineObjectiveCCompiler.cmake | 44 +------------------ .../Modules/CMakeTestObjectiveCCompiler.cmake | 2 + .cmake/Modules/Languages.cmake | 24 +++++----- CMakeLists.txt | 1 - 4 files changed, 17 insertions(+), 54 deletions(-) diff --git a/.cmake/Modules/CMakeDetermineObjectiveCCompiler.cmake b/.cmake/Modules/CMakeDetermineObjectiveCCompiler.cmake index 613cd38f..a7a42d17 100644 --- a/.cmake/Modules/CMakeDetermineObjectiveCCompiler.cmake +++ b/.cmake/Modules/CMakeDetermineObjectiveCCompiler.cmake @@ -2,48 +2,8 @@ # Redistribution and use of this file is allowed according to the terms of the MIT license. # For details see the LICENSE file distributed with Criterion. -include(${CMAKE_ROOT}/Modules/CMakeDetermineCompiler.cmake) - -if("${CMAKE_GENERATOR}" MATCHES "Visual Studio") -elseif("${CMAKE_GENERATOR}" MATCHES "Xcode") - set(CMAKE_ObjectiveC_COMPILER_XCODE_TYPE sourcecode.m) - _cmake_find_compiler_path(ObjectiveC) -else() - if(NOT CMAKE_ObjectiveC_COMPILER) - set(CMAKE_ObjectiveC_COMPILER_INIT NOTFOUND) - - if(NOT CMAKE_ObjectiveC_COMPILER_INIT) - set(CMAKE_ObjectiveC_COMPILER_LIST ${_CMAKE_TOOLCHAIN_PREFIX}gcc clang) - endif() - - _cmake_find_compiler(ObjectiveC) - else() - _cmake_find_compiler_path(ObjectiveC) - endif() - mark_as_advanced(CMAKE_ObjectiveC_COMPILER) - - set(CMAKE_ObjectiveC_COMPILER_ID_TEST_FLAGS_FIRST) - set(CMAKE_ObjectiveC_COMPILER_ID_TEST_FLAGS "-c") - -endif() - -if(NOT CMAKE_ObjectiveC_COMPILER_ID_RUN) - set(CMAKE_ObjectiveC_COMPILER_ID_RUN 1) - - # Try to identify the compiler. - set(CMAKE_ObjectiveC_COMPILER_ID) - set(CMAKE_ObjectiveC_PLATFORM_ID) - file(READ ${CMAKE_ROOT}/Modules/CMakePlatformId.h.in - CMAKE_ObjectiveC_COMPILER_ID_PLATFORM_CONTENT) - - include(${CMAKE_ROOT}/Modules/CMakeDetermineCompilerId.cmake) - - # we use the same compiler id source than C - CMAKE_DETERMINE_COMPILER_ID(ObjectiveC CFLAGS CMakeCCompilerId.c) - -endif() - -include(CMakeFindBinUtils) +set(CMAKE_ObjectiveC_COMPILER_ID ${CMAKE_C_COMPILER_ID}) +set(CMAKE_ObjectiveC_COMPILER ${CMAKE_C_COMPILER}) # configure variables set in this file for fast reload later on configure_file(${CMAKE_CURRENT_LIST_DIR}/CMakeObjectiveCCompiler.cmake.in diff --git a/.cmake/Modules/CMakeTestObjectiveCCompiler.cmake b/.cmake/Modules/CMakeTestObjectiveCCompiler.cmake index e6d5ff10..a32b33f1 100644 --- a/.cmake/Modules/CMakeTestObjectiveCCompiler.cmake +++ b/.cmake/Modules/CMakeTestObjectiveCCompiler.cmake @@ -22,6 +22,8 @@ if(NOT CMAKE_ObjectiveC_COMPILER_WORKS) "#ifdef __cplusplus\n" "# error \"The CMAKE_ObjectiveC_COMPILER is set to an ObjectiveC++ compiler\"\n" "#endif\n" + "@interface Foo\n" + "@end\n" "int main(int argc, char* argv[])\n" "{ (void)argv; return argc-1;}\n") try_compile(CMAKE_ObjectiveC_COMPILER_WORKS ${CMAKE_BINARY_DIR} diff --git a/.cmake/Modules/Languages.cmake b/.cmake/Modules/Languages.cmake index 0ad61d49..615d0670 100644 --- a/.cmake/Modules/Languages.cmake +++ b/.cmake/Modules/Languages.cmake @@ -1,15 +1,17 @@ -if (NOT LANGUAGES) - set(LANGUAGES "") -endif () - -string(REPLACE "," ";" LANGUAGES "${LANGUAGES}") +option(LANG_CXX "Turn on C++ support" ON) +option(LANG_OBJC "Turn on Objective-C support" OFF) -foreach (LANG ${LANGUAGES}) - enable_language(${LANG} OPTIONAL) - if (CMAKE_${LANG}_COMPILER_WORKS) - string(TOUPPER ${LANG} LANG_NAME) - set(${LANG_NAME}_BRIDGE 1) +if (LANG_CXX) + enable_language(CXX) + if (CMAKE_CXX_COMPILER_WORKS) + set(CXX_BRIDGE 1) endif () -endforeach () +endif () +if (LANG_OBJC) + enable_language(ObjectiveC) + if (CMAKE_ObjectiveC_COMPILER_WORKS) + set(OBJC_BRIDGE 1) + endif () +endif () diff --git a/CMakeLists.txt b/CMakeLists.txt index e0313d87..2f0a2970 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -49,7 +49,6 @@ if (NOT MSVC) endif () endif () - if (MSVC) set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /SAFESEH:NO") endif () From e85bfcef089b333e89ff6fdee22828a8dfe1b241 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Wed, 7 Oct 2015 17:43:17 +0200 Subject: [PATCH 083/211] Added objective C support for CI builds with GNU compilers --- .travis.yml | 2 +- appveyor.yml | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 07926e03..42a9a1f4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -34,7 +34,7 @@ script: -DCOVERALLS=${COVERAGE} -DCMAKE_BUILD_TYPE=${CONFIGURATION} -DCMAKE_INSTALL_PREFIX=criterion-${TRAVIS_TAG} - -DLANGUAGES=CXX + -DLANG_OBJC=ON .. - TERM=dumb cmake --build . --target criterion_tests -- -j4 - ctest -j4 diff --git a/appveyor.yml b/appveyor.yml index 4b1cc8d0..6b91c6b3 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -15,6 +15,7 @@ environment: matrix: - COMPILER: mingw GENERATOR: "MSYS Makefiles" + CMAKE_OPTS: -DLANG_OBJC=ON - COMPILER: msvc GENERATOR: "Visual Studio 14 2015" CFLAGS: /MP @@ -43,7 +44,7 @@ install: -DCTESTS=ON -DCMAKE_INSTALL_PREFIX="criterion-%RELEASE_NAME%" -DCMAKE_BUILD_TYPE="%CONFIGURATION%" - -DLANGUAGES=CXX + %CMAKE_OPTS% -G "%GENERATOR%" .. From baf93fb2f2f7bf431d068568ffda81e927b32b75 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Wed, 7 Oct 2015 17:57:53 +0200 Subject: [PATCH 084/211] Added CMAKE_PLATFORM_INFO_DIR definition for CMake <2.8.10 backward compatibility --- .cmake/Modules/CMakeDetermineObjectiveCCompiler.cmake | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.cmake/Modules/CMakeDetermineObjectiveCCompiler.cmake b/.cmake/Modules/CMakeDetermineObjectiveCCompiler.cmake index a7a42d17..9a9680a5 100644 --- a/.cmake/Modules/CMakeDetermineObjectiveCCompiler.cmake +++ b/.cmake/Modules/CMakeDetermineObjectiveCCompiler.cmake @@ -2,6 +2,11 @@ # Redistribution and use of this file is allowed according to the terms of the MIT license. # For details see the LICENSE file distributed with Criterion. +# CMake <2.8.10 backward compat +if(NOT CMAKE_PLATFORM_INFO_DIR) + set(CMAKE_PLATFORM_INFO_DIR ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}) +endif(NOT CMAKE_PLATFORM_INFO_DIR) + set(CMAKE_ObjectiveC_COMPILER_ID ${CMAKE_C_COMPILER_ID}) set(CMAKE_ObjectiveC_COMPILER ${CMAKE_C_COMPILER}) From 1f0743a8f542f82eab3a6157b3de139b5f0c3278 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Wed, 7 Oct 2015 18:10:31 +0200 Subject: [PATCH 085/211] Disabled Objective C support on windows-mingw and installed gobjc & gnustep on travis --- .travis.yml | 2 ++ appveyor.yml | 1 - 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 42a9a1f4..0e5eae8c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -15,6 +15,8 @@ addons: packages: - gcc-4.9 - g++-4.9 + - gobjc-4.9 + - gnustep-base env: global: GCOV: gcov-4.9 diff --git a/appveyor.yml b/appveyor.yml index 6b91c6b3..88ab0e95 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -15,7 +15,6 @@ environment: matrix: - COMPILER: mingw GENERATOR: "MSYS Makefiles" - CMAKE_OPTS: -DLANG_OBJC=ON - COMPILER: msvc GENERATOR: "Visual Studio 14 2015" CFLAGS: /MP From 4be3a015e5aaaff5e86eb31de03252fd307fe3a6 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Thu, 8 Oct 2015 13:54:21 +0200 Subject: [PATCH 086/211] Installed gnustep-devel rather than gnustep-base on travis CI --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 0e5eae8c..bf515dda 100644 --- a/.travis.yml +++ b/.travis.yml @@ -16,7 +16,7 @@ addons: - gcc-4.9 - g++-4.9 - gobjc-4.9 - - gnustep-base + - gnustep-devel env: global: GCOV: gcov-4.9 From 6f1a4721147efe78160544b710969b9582df5253 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Sat, 10 Oct 2015 03:12:32 +0200 Subject: [PATCH 087/211] Added GNUStep include path to cmake include directories --- CMakeLists.txt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 2f0a2970..c552e1c3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -16,7 +16,10 @@ endif () add_subdirectory(dependencies/libcsptr/ EXCLUDE_FROM_ALL) add_subdirectory(dependencies/dyncall/ EXCLUDE_FROM_ALL) -include_directories(SYSTEM /usr/local/include) +include_directories(SYSTEM + /usr/local/include + /usr/include/GNUStep +) include_directories( dependencies/libcsptr/include/ From 7f8c2052ac6707810f6bce78b21ec0fade853945 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Sun, 11 Oct 2015 05:18:28 +0200 Subject: [PATCH 088/211] Fixed typo in GNUStep include path --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index c552e1c3..8eb4d5ec 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -18,7 +18,7 @@ add_subdirectory(dependencies/dyncall/ EXCLUDE_FROM_ALL) include_directories(SYSTEM /usr/local/include - /usr/include/GNUStep + /usr/include/GNUstep ) include_directories( From 400e98912595fc6919d96c0a408c24b343ee16be Mon Sep 17 00:00:00 2001 From: Snaipe Date: Mon, 12 Oct 2015 18:01:23 +0200 Subject: [PATCH 089/211] Fixed native exceptions gnustep compilation error --- CMakeLists.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 8eb4d5ec..b95a7843 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -161,6 +161,8 @@ endif () if (CMAKE_ObjectiveC_COMPILER_WORKS) set(CMAKE_ObjectiveC_FLAGS "${CMAKE_ObjectiveC_FLAGS} ${CMAKE_C_FLAGS} -fobjc-exceptions") + add_definitions(-D_NATIVE_OBJC_EXCEPTIONS) + if (NOT WIN32) set(CMAKE_ObjectiveC_FLAGS "${CMAKE_ObjectiveC_FLAGS} -fPIC") endif () From a45b04df4ab9732af89bde028f9af9d198d00402 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Sat, 10 Oct 2015 12:32:14 +0100 Subject: [PATCH 090/211] Added klib dependency --- .gitmodules | 3 +++ dependencies/klib | 1 + 2 files changed, 4 insertions(+) create mode 160000 dependencies/klib diff --git a/.gitmodules b/.gitmodules index 7c24be15..7ff4b273 100644 --- a/.gitmodules +++ b/.gitmodules @@ -7,3 +7,6 @@ [submodule "dependencies/wingetopt"] path = dependencies/wingetopt url = https://github.com/alex85k/wingetopt.git +[submodule "dependencies/klib"] + path = dependencies/klib + url = https://github.com/attractivechaos/klib.git diff --git a/dependencies/klib b/dependencies/klib new file mode 160000 index 00000000..cdb7e923 --- /dev/null +++ b/dependencies/klib @@ -0,0 +1 @@ +Subproject commit cdb7e9236dc47abf8da7ebd702cc6f7f21f0c502 From 1928e161f784b8ff5a9055defb6c95890b5dce93 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Sun, 11 Oct 2015 13:21:23 +0100 Subject: [PATCH 091/211] Added klib cmake dependency --- CMakeLists.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index f3b6e5df..e5baa7b5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -23,6 +23,7 @@ include_directories( dependencies/libcsptr/include/ dependencies/dyncall/dyncall/ dependencies/valgrind/include/ + dependencies/klib/ ) if (MSVC) @@ -127,6 +128,7 @@ set(SOURCE_FILES src/io/asprintf.c src/io/file.c src/log/logging.c + src/log/output.c src/log/tap.c src/log/normal.c src/log/xml.c From 36543fb956fa882d73274e61a8054479a3675aed Mon Sep 17 00:00:00 2001 From: Snaipe Date: Mon, 12 Oct 2015 10:34:01 +0100 Subject: [PATCH 092/211] Added basic reporter/output registration --- src/log/output.c | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 src/log/output.c diff --git a/src/log/output.c b/src/log/output.c new file mode 100644 index 00000000..3b9918d4 --- /dev/null +++ b/src/log/output.c @@ -0,0 +1,36 @@ +#include +#include +#include +#include "criterion/stats.h" + +typedef void criterion_reporter(FILE *stream, struct criterion_global_stats *); + +KHASH_MAP_INIT_STR(ht_str, criterion_reporter*) +KHASH_MAP_INIT_STR(ht_path, const char *) + +static khash_t(ht_str) *reporters; +static khash_t(ht_path) *outputs; + +void criterion_init_output(void) { + reporters = kh_init(ht_str); + outputs = kh_init(ht_path); +} + +int criterion_register_output_provider(const char *name, criterion_reporter *reporter) { + int absent; + khint_t k = kh_put(ht_str, reporters, name, &absent); + kh_value(reporters, k) = reporter; + return absent; +} + +int criterion_add_output(const char *provider, const char *path) { + int absent; + khint_t k = kh_put(ht_path, outputs, provider, &absent); + kh_value(outputs, k) = path; + return absent; +} + +void criterion_free_output(void) { + kh_destroy(ht_str, reporters); + kh_destroy(ht_path, outputs); +} From 27991e7f661abfb26ffa6e663f0f645e1efe2cd2 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Tue, 20 Oct 2015 14:10:12 +0100 Subject: [PATCH 093/211] Exported API for output registration --- include/criterion/output.h | 36 ++++++++++++++++++++++++++++++++++++ src/log/output.c | 4 +--- 2 files changed, 37 insertions(+), 3 deletions(-) create mode 100644 include/criterion/output.h diff --git a/include/criterion/output.h b/include/criterion/output.h new file mode 100644 index 00000000..baeeaba2 --- /dev/null +++ b/include/criterion/output.h @@ -0,0 +1,36 @@ +/* + * The MIT License (MIT) + * + * Copyright © 2015 Franklin "Snaipe" Mathieu + * + * 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 CRITERION_OUTPUT_H_ +# define CRITERION_OUTPUT_H_ + +# include "stats.h" + +typedef void criterion_reporter(FILE *stream, struct criterion_global_stats *); + +void criterion_init_output(void); +int criterion_register_output_provider(const char *name, criterion_reporter *reporter); +int criterion_add_output(const char *provider, const char *path); +void criterion_free_output(void); + +#endif /* !CRITERION_OUTPUT_H_ */ diff --git a/src/log/output.c b/src/log/output.c index 3b9918d4..f23aa1d3 100644 --- a/src/log/output.c +++ b/src/log/output.c @@ -1,9 +1,7 @@ #include #include #include -#include "criterion/stats.h" - -typedef void criterion_reporter(FILE *stream, struct criterion_global_stats *); +#include "criterion/output.h" KHASH_MAP_INIT_STR(ht_str, criterion_reporter*) KHASH_MAP_INIT_STR(ht_path, const char *) From dcfbc13773c0066e71609914fe9445017e15db4c Mon Sep 17 00:00:00 2001 From: Snaipe Date: Wed, 21 Oct 2015 12:41:23 +0100 Subject: [PATCH 094/211] Removed TAP & XML reporters --- include/criterion/logging.h | 4 ---- src/entry/main.c | 9 --------- 2 files changed, 13 deletions(-) diff --git a/include/criterion/logging.h b/include/criterion/logging.h index 450023be..76fc6eae 100644 --- a/include/criterion/logging.h +++ b/include/criterion/logging.h @@ -120,13 +120,9 @@ struct criterion_output_provider { }; extern struct criterion_output_provider normal_logging; -extern struct criterion_output_provider tap_logging; -extern struct criterion_output_provider xml_logging; CR_END_C_API #define CR_NORMAL_LOGGING (&normal_logging) -#define CR_TAP_LOGGING (&tap_logging) -#define CR_XML_LOGGING (&xml_logging) #endif /* !CRITERION_LOGGING_H_ */ diff --git a/src/entry/main.c b/src/entry/main.c index 007b3201..f711c8b0 100644 --- a/src/entry/main.c +++ b/src/entry/main.c @@ -187,9 +187,6 @@ int criterion_handle_args(int argc, char *argv[], bool handle_unknown_arg) { opt->pattern = env_pattern; #endif - bool use_tap = !strcmp("1", DEF(getenv("CRITERION_ENABLE_TAP"), "0")); - bool use_xml = !strcmp("1", DEF(getenv("CRITERION_ENABLE_XML"), "0")); - opt->measure_time = !!strcmp("1", DEF(getenv("CRITERION_DISABLE_TIME_MEASUREMENTS"), "0")); bool do_list_tests = false; @@ -207,8 +204,6 @@ int criterion_handle_args(int argc, char *argv[], bool handle_unknown_arg) { #ifdef HAVE_PCRE case 'p': criterion_options.pattern = optarg; break; #endif - case 't': use_tap = true; break; - case 'x': use_xml = true; break; case 'l': do_list_tests = true; break; case 'v': do_print_version = true; break; case 'h': do_print_usage = true; break; @@ -216,10 +211,6 @@ int criterion_handle_args(int argc, char *argv[], bool handle_unknown_arg) { default : do_print_usage = handle_unknown_arg; break; } } - if (use_tap) - criterion_options.output_provider = CR_TAP_LOGGING; - else if (use_xml) - criterion_options.output_provider = CR_XML_LOGGING; if (do_print_usage) return print_usage(argv[0]); if (do_print_version) From da66a5704ed884ee3a6e1b498a8a08d2cea9e9b3 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Thu, 22 Oct 2015 18:13:29 +0100 Subject: [PATCH 095/211] Integrated new report system into core --- src/core/runner.c | 5 +++++ src/entry/main.c | 1 + src/log/output.c | 50 ++++++++++++++++++++++++++++++++++++++++++----- 3 files changed, 51 insertions(+), 5 deletions(-) diff --git a/src/core/runner.c b/src/core/runner.c index bbe870a3..be6ff1e1 100644 --- a/src/core/runner.c +++ b/src/core/runner.c @@ -37,6 +37,7 @@ #include "wrappers/wrap.h" #include "string/i18n.h" #include "io/event.h" +#include "log/output.h" #include "runner_coroutine.h" #include "stats.h" #include "runner.h" @@ -347,6 +348,8 @@ struct criterion_test_set *criterion_initialize(void) { if (resume_child()) // (windows only) resume from the fork exit(0); + criterion_init_output(); + return criterion_init(); } @@ -451,6 +454,8 @@ static int criterion_run_all_tests_impl(struct criterion_test_set *set) { report(POST_ALL, stats); log(post_all, stats); + process_all_output(stats); + cleanup: sfree(g_worker_pipe); sfree(stats); diff --git a/src/entry/main.c b/src/entry/main.c index f711c8b0..eaad0748 100644 --- a/src/entry/main.c +++ b/src/entry/main.c @@ -30,6 +30,7 @@ #include "criterion/options.h" #include "criterion/ordered-set.h" #include "core/runner.h" +#include "log/output.h" #include "config.h" #include "common.h" diff --git a/src/log/output.c b/src/log/output.c index f23aa1d3..b7893ff5 100644 --- a/src/log/output.c +++ b/src/log/output.c @@ -1,10 +1,13 @@ #include #include #include +#include #include "criterion/output.h" +typedef kvec_t(const char *) str_vec; + KHASH_MAP_INIT_STR(ht_str, criterion_reporter*) -KHASH_MAP_INIT_STR(ht_path, const char *) +KHASH_MAP_INIT_STR(ht_path, str_vec*) static khash_t(ht_str) *reporters; static khash_t(ht_path) *outputs; @@ -22,13 +25,50 @@ int criterion_register_output_provider(const char *name, criterion_reporter *rep } int criterion_add_output(const char *provider, const char *path) { - int absent; - khint_t k = kh_put(ht_path, outputs, provider, &absent); - kh_value(outputs, k) = path; - return absent; + khint_t k = kh_get(ht_path, outputs, provider); + + if (k == kh_end(outputs)) { + int absent; + k = kh_put(ht_path, outputs, provider, &absent); + if (absent == -1) + return -1; + + str_vec *vec = malloc(sizeof (str_vec)); + kv_init(*vec); + kh_value(outputs, k) = vec; + } + str_vec *vec = kh_value(outputs, k); + + kv_push(const char *, *vec, path); + return 1; } void criterion_free_output(void) { kh_destroy(ht_str, reporters); kh_destroy(ht_path, outputs); } + +void process_all_output(struct criterion_global_stats *stats) { + for (khint_t k = kh_begin(reporters); k != kh_end(reporters); ++k) { + if (!kh_exist(reporters, k)) + continue; + + criterion_reporter *report = kh_value(reporters, k); + khint_t ko = kh_get(ht_path, outputs, kh_key(reporters, k)); + if (ko == kh_end(outputs)) + continue; + + str_vec *vec = kh_value(outputs, ko); + for (size_t i = 0; i < kv_size(*vec); ++i) { + const char *path = kv_A(*vec, i); + + FILE *f; + if (path[0] == '-' && !path[1]) + f = stderr; + else + f = fopen(path, "w"); + + report(f, stats); + } + } +} From 3b0264c4c8253d25b93a3750b048f288dd36eb4d Mon Sep 17 00:00:00 2001 From: Snaipe Date: Fri, 23 Oct 2015 10:54:09 +0100 Subject: [PATCH 096/211] Added missing output header --- src/log/output.h | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 src/log/output.h diff --git a/src/log/output.h b/src/log/output.h new file mode 100644 index 00000000..0c734146 --- /dev/null +++ b/src/log/output.h @@ -0,0 +1,31 @@ +/* + * The MIT License (MIT) + * + * Copyright © 2015 Franklin "Snaipe" Mathieu + * + * 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 OUTPUT_H_ +# define OUTPUT_H_ + +# include "criterion/output.h" + +void process_all_output(struct criterion_global_stats *stats); + +#endif /* !OUTPUT_H_ */ From 5d8a32bd83a222c9dfba24ece6e91df4d87a6103 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Sat, 24 Oct 2015 21:43:54 +0100 Subject: [PATCH 097/211] Added TAP format into the new report system --- src/core/runner.c | 1 + src/entry/main.c | 3 ++- src/log/output.h | 2 ++ src/log/tap.c | 49 ++++++++++++++++++++++------------------------- 4 files changed, 28 insertions(+), 27 deletions(-) diff --git a/src/core/runner.c b/src/core/runner.c index be6ff1e1..011050ff 100644 --- a/src/core/runner.c +++ b/src/core/runner.c @@ -349,6 +349,7 @@ struct criterion_test_set *criterion_initialize(void) { exit(0); criterion_init_output(); + criterion_register_output_provider("tap", tap_report); return criterion_init(); } diff --git a/src/entry/main.c b/src/entry/main.c index eaad0748..34ca2aa5 100644 --- a/src/entry/main.c +++ b/src/entry/main.c @@ -132,7 +132,7 @@ int criterion_handle_args(int argc, char *argv[], bool handle_unknown_arg) { static struct option opts[] = { {"verbose", optional_argument, 0, 'b'}, {"version", no_argument, 0, 'v'}, - {"tap", no_argument, 0, 't'}, + {"tap", optional_argument, 0, 't'}, {"xml", no_argument, 0, 'x'}, {"help", no_argument, 0, 'h'}, {"list", no_argument, 0, 'l'}, @@ -205,6 +205,7 @@ int criterion_handle_args(int argc, char *argv[], bool handle_unknown_arg) { #ifdef HAVE_PCRE case 'p': criterion_options.pattern = optarg; break; #endif + case 't': criterion_add_output("tap", DEF(optarg, "-")); break; case 'l': do_list_tests = true; break; case 'v': do_print_version = true; break; case 'h': do_print_usage = true; break; diff --git a/src/log/output.h b/src/log/output.h index 0c734146..bd3f1250 100644 --- a/src/log/output.h +++ b/src/log/output.h @@ -28,4 +28,6 @@ void process_all_output(struct criterion_global_stats *stats); +void tap_report(FILE *f, struct criterion_global_stats *stats); + #endif /* !OUTPUT_H_ */ diff --git a/src/log/tap.c b/src/log/tap.c index c960951e..779707df 100644 --- a/src/log/tap.c +++ b/src/log/tap.c @@ -35,15 +35,15 @@ #include "config.h" #include "common.h" -static void print_prelude(struct criterion_global_stats *stats) { - criterion_important("TAP version 13\n1.." +static void print_prelude(FILE *f, struct criterion_global_stats *stats) { + fprintf(f, "TAP version 13\n1.." CR_SIZE_T_FORMAT "\n", stats->nb_tests); - criterion_important("# Criterion v%s\n", VERSION); + fprintf(f, "# Criterion v%s\n", VERSION); } -static void print_pre_suite(struct criterion_suite_stats *stats) { - criterion_important("\n# Running " +static void print_pre_suite(FILE *f, struct criterion_suite_stats *stats) { + fprintf(f, "\n# Running " CR_SIZE_T_FORMAT " tests from %s\n", stats->nb_tests, @@ -54,10 +54,10 @@ static INLINE bool is_disabled(struct criterion_test *t, struct criterion_suite return t->data->disabled || (s->data && s->data->disabled); } -static void print_test_normal(struct criterion_test_stats *stats) { +static void print_test_normal(FILE *f, struct criterion_test_stats *stats) { const char *format = can_measure_time() ? "%s - %s::%s %s (%3.2fs)\n" : "%s - %s::%s %s\n"; - criterion_important(format, + fprintf(f, format, stats->failed ? "not ok" : "ok", stats->test->category, stats->test->name, @@ -69,64 +69,61 @@ static void print_test_normal(struct criterion_test_stats *stats) { char *saveptr = NULL; char *line = strtok_r(dup, "\n", &saveptr); bool sf = criterion_options.short_filename; - criterion_important(" %s:%u: Assertion failed: %s\n", + fprintf(f, " %s:%u: Assertion failed: %s\n", sf ? basename_compat(asrt->file) : asrt->file, asrt->line, line); while ((line = strtok_r(NULL, "\n", &saveptr))) - criterion_important(" %s\n", line); + fprintf(f, " %s\n", line); free(dup); } } } -static void print_test_crashed(struct criterion_test_stats *stats) { +static void print_test_crashed(FILE *f, struct criterion_test_stats *stats) { bool sf = criterion_options.short_filename; - criterion_important("not ok - %s::%s unexpected signal after %s:%u\n", + fprintf(f, "not ok - %s::%s unexpected signal after %s:%u\n", stats->test->category, stats->test->name, sf ? basename_compat(stats->file) : stats->file, stats->progress); } -static void print_test_timeout(struct criterion_test_stats *stats) { - criterion_important("not ok - %s::%s timed out (%3.2fs)\n", +static void print_test_timeout(FILE *f, struct criterion_test_stats *stats) { + fprintf(f, "not ok - %s::%s timed out (%3.2fs)\n", stats->test->category, stats->test->name, stats->elapsed_time); } -static void print_test(struct criterion_test_stats *ts, +static void print_test(FILE *f, + struct criterion_test_stats *ts, struct criterion_suite_stats *ss) { if (is_disabled(ts->test, ss->suite)) { - criterion_important("ok - %s::%s %s # SKIP %s is disabled\n", + fprintf(f, "ok - %s::%s %s # SKIP %s is disabled\n", ts->test->category, ts->test->name, DEF(ts->test->data->description, ""), ts->test->data->disabled ? "test" : "suite"); } else if (ts->crashed) { - print_test_crashed(ts); + print_test_crashed(f, ts); } else if (ts->timed_out) { - print_test_timeout(ts); + print_test_timeout(f, ts); } else { - print_test_normal(ts); + print_test_normal(f, ts); } } -void tap_log_post_all(struct criterion_global_stats *stats) { - print_prelude(stats); +void tap_report(FILE *f, struct criterion_global_stats *stats) { + print_prelude(f, stats); for (struct criterion_suite_stats *ss = stats->suites; ss; ss = ss->next) { - print_pre_suite(ss); + print_pre_suite(f, ss); for (struct criterion_test_stats *ts = ss->tests; ts; ts = ts->next) { - print_test(ts, ss); + print_test(f, ts, ss); } } } - -struct criterion_output_provider tap_logging = { - .log_post_all = tap_log_post_all, -}; From d2d36052d7f8d44e5609a869a18aca14b0faf886 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Sun, 25 Oct 2015 10:02:39 +0100 Subject: [PATCH 098/211] Added XML format into the new report system --- src/core/runner.c | 1 + src/entry/main.c | 3 ++- src/log/output.h | 1 + src/log/xml.c | 37 +++++++++++++++++-------------------- 4 files changed, 21 insertions(+), 21 deletions(-) diff --git a/src/core/runner.c b/src/core/runner.c index 011050ff..34ac6ce2 100644 --- a/src/core/runner.c +++ b/src/core/runner.c @@ -350,6 +350,7 @@ struct criterion_test_set *criterion_initialize(void) { criterion_init_output(); criterion_register_output_provider("tap", tap_report); + criterion_register_output_provider("xml", xml_report); return criterion_init(); } diff --git a/src/entry/main.c b/src/entry/main.c index 34ca2aa5..9ee14b9e 100644 --- a/src/entry/main.c +++ b/src/entry/main.c @@ -133,7 +133,7 @@ int criterion_handle_args(int argc, char *argv[], bool handle_unknown_arg) { {"verbose", optional_argument, 0, 'b'}, {"version", no_argument, 0, 'v'}, {"tap", optional_argument, 0, 't'}, - {"xml", no_argument, 0, 'x'}, + {"xml", optional_argument, 0, 'x'}, {"help", no_argument, 0, 'h'}, {"list", no_argument, 0, 'l'}, {"ascii", no_argument, 0, 'k'}, @@ -206,6 +206,7 @@ int criterion_handle_args(int argc, char *argv[], bool handle_unknown_arg) { case 'p': criterion_options.pattern = optarg; break; #endif case 't': criterion_add_output("tap", DEF(optarg, "-")); break; + case 'x': criterion_add_output("xml", DEF(optarg, "-")); break; case 'l': do_list_tests = true; break; case 'v': do_print_version = true; break; case 'h': do_print_usage = true; break; diff --git a/src/log/output.h b/src/log/output.h index bd3f1250..e3322897 100644 --- a/src/log/output.h +++ b/src/log/output.h @@ -29,5 +29,6 @@ void process_all_output(struct criterion_global_stats *stats); void tap_report(FILE *f, struct criterion_global_stats *stats); +void xml_report(FILE *f, struct criterion_global_stats *stats); #endif /* !OUTPUT_H_ */ diff --git a/src/log/xml.c b/src/log/xml.c index fd7c9d6f..3bce465f 100644 --- a/src/log/xml.c +++ b/src/log/xml.c @@ -112,24 +112,25 @@ const char *get_status_string(struct criterion_test_stats *ts, return status; } -static void print_test(struct criterion_test_stats *ts, +static void print_test(FILE *f, + struct criterion_test_stats *ts, struct criterion_suite_stats *ss) { - criterion_important(XML_TEST_TEMPLATE_BEGIN, + fprintf(f, XML_TEST_TEMPLATE_BEGIN, ts->test->name, (size_t) (ts->passed_asserts + ts->failed_asserts), get_status_string(ts, ss) ); if (is_disabled(ts->test, ss->suite)) { - criterion_important(XML_TEST_SKIPPED); + fprintf(f, XML_TEST_SKIPPED); } else if (ts->crashed) { - criterion_important(XML_CRASH_MSG_ENTRY); + fprintf(f, XML_CRASH_MSG_ENTRY); } else if (ts->timed_out) { - criterion_important(XML_TIMEOUT_MSG_ENTRY); + fprintf(f, XML_TIMEOUT_MSG_ENTRY); } else { if (ts->failed) { - criterion_important(XML_TEST_FAILED_TEMPLATE_BEGIN, ts->failed_asserts); + fprintf(f, XML_TEST_FAILED_TEMPLATE_BEGIN, ts->failed_asserts); for (struct criterion_assert_stats *asrt = ts->asserts; asrt; asrt = asrt->next) { if (!asrt->passed) { bool sf = criterion_options.short_filename; @@ -137,26 +138,26 @@ static void print_test(struct criterion_test_stats *ts, char *saveptr = NULL; char *line = strtok_r(dup, "\n", &saveptr); - criterion_important(XML_FAILURE_MSG_ENTRY, + fprintf(f, XML_FAILURE_MSG_ENTRY, sf ? basename_compat(asrt->file) : asrt->file, asrt->line, line ); while ((line = strtok_r(NULL, "\n", &saveptr))) - criterion_important(" %s" LF, line); + fprintf(f, " %s" LF, line); free(dup); } } - criterion_important(XML_TEST_FAILED_TEMPLATE_END); + fprintf(f, XML_TEST_FAILED_TEMPLATE_END); } } - criterion_important(XML_TEST_TEMPLATE_END); + fprintf(f, XML_TEST_TEMPLATE_END); } -void xml_log_post_all(struct criterion_global_stats *stats) { - criterion_important(XML_BASE_TEMPLATE_BEGIN, +void xml_report(FILE *f, struct criterion_global_stats *stats) { + fprintf(f, XML_BASE_TEMPLATE_BEGIN, stats->nb_tests, stats->tests_failed, stats->tests_crashed, @@ -165,7 +166,7 @@ void xml_log_post_all(struct criterion_global_stats *stats) { for (struct criterion_suite_stats *ss = stats->suites; ss; ss = ss->next) { - criterion_important(XML_TESTSUITE_TEMPLATE_BEGIN, + fprintf(f, XML_TESTSUITE_TEMPLATE_BEGIN, ss->suite->name, ss->nb_tests, ss->tests_failed, @@ -175,15 +176,11 @@ void xml_log_post_all(struct criterion_global_stats *stats) { ); for (struct criterion_test_stats *ts = ss->tests; ts; ts = ts->next) { - print_test(ts, ss); + print_test(f, ts, ss); } - criterion_important(XML_TESTSUITE_TEMPLATE_END); + fprintf(f, XML_TESTSUITE_TEMPLATE_END); } - criterion_important(XML_BASE_TEMPLATE_END); + fprintf(f, XML_BASE_TEMPLATE_END); } - -struct criterion_output_provider xml_logging = { - .log_post_all = xml_log_post_all, -}; From 13c8fa79a8448107bc106f275e25edebe2847fa3 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Mon, 26 Oct 2015 10:29:00 +0100 Subject: [PATCH 099/211] Updated CLI help message for --tap and --xml --- src/entry/main.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/entry/main.c b/src/entry/main.c index 9ee14b9e..c27506fa 100644 --- a/src/entry/main.c +++ b/src/entry/main.c @@ -63,8 +63,10 @@ " -S or --short-filename: only display the base " \ "name of the source file on a failure\n" \ PATTERN_USAGE \ - " --tap: enables TAP formatting\n" \ - " --xml: enables XML formatting\n" \ + " --tap[=FILE]: writes TAP report in FILE " \ + "(no file or \"-\" means stderr)\n" \ + " --xml[=FILE]: writes XML report in FILE " \ + "(no file or \"-\" means stderr)\n" \ " --always-succeed: always exit with 0\n" \ " --no-early-exit: do not exit the test worker " \ "prematurely after the test\n" \ From 770c312f708e1e47424253d46c528b1137c7812f Mon Sep 17 00:00:00 2001 From: Snaipe Date: Tue, 27 Oct 2015 13:56:47 +0100 Subject: [PATCH 100/211] Added --quiet CLI switch --- include/criterion/logging.h | 2 ++ src/entry/main.c | 13 ++++++++++--- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/include/criterion/logging.h b/include/criterion/logging.h index 76fc6eae..2e07f43f 100644 --- a/include/criterion/logging.h +++ b/include/criterion/logging.h @@ -38,6 +38,8 @@ using std::va_list; enum criterion_logging_level { CRITERION_INFO = 1, CRITERION_IMPORTANT, + + CRITERION_LOG_LEVEL_QUIET = 1 << 30, }; enum criterion_logging_prefix { diff --git a/src/entry/main.c b/src/entry/main.c index c27506fa..e6c9722e 100644 --- a/src/entry/main.c +++ b/src/entry/main.c @@ -53,6 +53,7 @@ "usage: %s OPTIONS\n" \ "options: \n" \ " -h or --help: prints this message\n" \ + " -q or --quiet: disables all logging\n" \ " -v or --version: prints the version of criterion " \ "these tests have been linked against\n" \ " -l or --list: prints all the tests in a list\n" \ @@ -133,6 +134,7 @@ int atou(const char *str) { int criterion_handle_args(int argc, char *argv[], bool handle_unknown_arg) { static struct option opts[] = { {"verbose", optional_argument, 0, 'b'}, + {"quiet", no_argument, 0, 'q'}, {"version", no_argument, 0, 'v'}, {"tap", optional_argument, 0, 't'}, {"xml", optional_argument, 0, 'x'}, @@ -195,7 +197,8 @@ int criterion_handle_args(int argc, char *argv[], bool handle_unknown_arg) { bool do_list_tests = false; bool do_print_version = false; bool do_print_usage = false; - for (int c; (c = getopt_long(argc, argv, "hvlfj:S", opts, NULL)) != -1;) { + bool quiet = false; + for (int c; (c = getopt_long(argc, argv, "hvlfj:Sq", opts, NULL)) != -1;) { switch (c) { case 'b': criterion_options.logging_threshold = atou(DEF(optarg, "1")); break; case 'y': criterion_options.always_succeed = true; break; @@ -207,8 +210,9 @@ int criterion_handle_args(int argc, char *argv[], bool handle_unknown_arg) { #ifdef HAVE_PCRE case 'p': criterion_options.pattern = optarg; break; #endif - case 't': criterion_add_output("tap", DEF(optarg, "-")); break; - case 'x': criterion_add_output("xml", DEF(optarg, "-")); break; + case 'q': quiet = true; break; + case 't': quiet = true; criterion_add_output("tap", DEF(optarg, "-")); break; + case 'x': quiet = true; criterion_add_output("xml", DEF(optarg, "-")); break; case 'l': do_list_tests = true; break; case 'v': do_print_version = true; break; case 'h': do_print_usage = true; break; @@ -216,6 +220,9 @@ int criterion_handle_args(int argc, char *argv[], bool handle_unknown_arg) { default : do_print_usage = handle_unknown_arg; break; } } + if (quiet) + criterion_options.logging_threshold = CRITERION_LOG_LEVEL_QUIET; + if (do_print_usage) return print_usage(argv[0]); if (do_print_version) From 446dc0f380fe4bc682b60fde0970857106ddf4dd Mon Sep 17 00:00:00 2001 From: Snaipe Date: Wed, 28 Oct 2015 20:45:55 +0100 Subject: [PATCH 101/211] Properly free output file hash map --- src/core/runner.c | 2 ++ src/log/output.c | 7 +++++++ 2 files changed, 9 insertions(+) diff --git a/src/core/runner.c b/src/core/runner.c index 34ac6ce2..1aae9359 100644 --- a/src/core/runner.c +++ b/src/core/runner.c @@ -361,6 +361,8 @@ void criterion_finalize(struct criterion_test_set *set) { #ifndef ENABLE_VALGRIND_ERRORS VALGRIND_ENABLE_ERROR_REPORTING; #endif + + criterion_free_output(); } static void run_tests_async(struct criterion_test_set *set, diff --git a/src/log/output.c b/src/log/output.c index b7893ff5..b5ce1fb2 100644 --- a/src/log/output.c +++ b/src/log/output.c @@ -44,6 +44,13 @@ int criterion_add_output(const char *provider, const char *path) { } void criterion_free_output(void) { + for (khint_t k = kh_begin(outputs); k != kh_end(outputs); ++k) { + if (!kh_exist(outputs, k)) + continue; + str_vec *vec = kh_value(outputs, k); + kv_destroy(*vec); + free(vec); + } kh_destroy(ht_str, reporters); kh_destroy(ht_path, outputs); } From cda6b93212766c3a54a132c5431322b9e27e326e Mon Sep 17 00:00:00 2001 From: Snaipe Date: Thu, 29 Oct 2015 02:12:34 +0100 Subject: [PATCH 102/211] Updated line counts for po files --- po/fr.po | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/po/fr.po b/po/fr.po index e6c75a48..6e8fe381 100644 --- a/po/fr.po +++ b/po/fr.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: criterion 2.0.0\n" "Report-Msgid-Bugs-To: franklinmathieu+criterion@gmail.com\n" -"POT-Creation-Date: 2015-10-05 16:20+0200\n" +"POT-Creation-Date: 2015-11-11 00:24+0100\n" "PO-Revision-Date: 2015-04-03 17:58+0200\n" "Last-Translator: \n" "Language-Team: French\n" @@ -18,70 +18,70 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n" -#: src/log/normal.c:41 +#: src/log/normal.c:42 #, c-format msgid "Criterion v%s\n" msgstr "Criterion v%s\n" -#: src/log/normal.c:42 +#: src/log/normal.c:43 #, c-format msgid " %s\n" msgstr " %s\n" -#: src/log/normal.c:45 src/log/normal.c:47 +#: src/log/normal.c:46 src/log/normal.c:48 #, c-format msgid "%1$s::%2$s\n" msgstr "%1$s::%2$s\n" -#: src/log/normal.c:46 +#: src/log/normal.c:47 #, fuzzy, c-format msgid "%1$s::%2$s: (%3$3.2fs)\n" msgstr "%1$s::%2$s: (%3$3.2fs)\n" -#: src/log/normal.c:48 +#: src/log/normal.c:49 #, c-format msgid "%1$s::%2$s: Test is disabled\n" msgstr "%1$s::%2$s: Le test est désactivé\n" -#: src/log/normal.c:49 +#: src/log/normal.c:50 #, c-format msgid "%1$s::%2$s: Suite is disabled\n" msgstr "%1$s::%2$s: La suite est désactivée\n" -#: src/log/normal.c:50 +#: src/log/normal.c:51 #, c-format msgid "%1$s%2$s%3$s:%4$s%5$d%6$s: Assertion failed: %7$s\n" msgstr "%1$s%2$s%3$s:%4$s%5$d%6$s: Échec d'assertion: %7$s\n" -#: src/log/normal.c:51 +#: src/log/normal.c:52 #, fuzzy, c-format msgid " Theory %1$s::%2$s failed with the following parameters: (%3$s)\n" msgstr "" " La théorie %1$s::%2$s a échoué avec les paramètres suivants: (%3$s)\n" -#: src/log/normal.c:52 +#: src/log/normal.c:53 #, fuzzy, c-format msgid "%1$s::%2$s: Timed out. (%3$3.2fs)\n" msgstr "%1$s::%2$s: Délai expiré. (%3$3.2fs)\n" -#: src/log/normal.c:53 +#: src/log/normal.c:54 #, c-format msgid "%1$s%2$s%3$s:%4$s%5$u%6$s: Unexpected signal caught below this line!\n" msgstr "" "%1$s%2$s%3$s:%4$s%5$u%6$s: Un signal inattendu a été reçu après cette " "ligne!\n" -#: src/log/normal.c:54 +#: src/log/normal.c:55 #, c-format msgid "%1$s::%2$s: CRASH!\n" msgstr "%1$s::%2$s: PLANTAGE!\n" -#: src/log/normal.c:55 +#: src/log/normal.c:56 #, fuzzy, c-format msgid "%1$s::%2$s: %3$s\n" msgstr "%1$s::%2$s: (%3$3.2fs)\n" -#: src/log/normal.c:56 +#: src/log/normal.c:57 #, fuzzy, c-format msgid "" "%1$sWarning! The test `%2$s::%3$s` crashed during its setup or teardown." @@ -90,7 +90,7 @@ msgstr "" "%1$sAttention! Le test `%2$s::%3$s` a planté pendant son initialisation ou " "sa finalisation.%4$s\n" -#: src/log/normal.c:57 +#: src/log/normal.c:58 #, fuzzy, c-format msgid "" "%1$sWarning! The test `%2$s::%3$s` exited during its setup or teardown.%4$s\n" @@ -98,14 +98,14 @@ msgstr "" "%1$sAttention! Le test `%2$s::%3$s` a quitté pendant son initialisation ou " "sa finalisation.%4$s\n" -#: src/log/normal.c:58 +#: src/log/normal.c:59 #, c-format msgid "Running %1$s%2$lu%3$s test from %4$s%5$s%6$s:\n" msgid_plural "Running %1$s%2$lu%3$s tests from %4$s%5$s%6$s:\n" msgstr[0] "Lancement de %1$s%2$lu%3$s test dans %4$s%5$s%6$s:\n" msgstr[1] "Lancement de %1$s%2$lu%3$s tests dans %4$s%5$s%6$s:\n" -#: src/log/normal.c:60 +#: src/log/normal.c:61 #, c-format msgid "" "%1$sSynthesis: Tested: %2$s%3$lu%4$s | Passing: %5$s%6$lu%7$s | Failing: %8$s" @@ -114,7 +114,7 @@ msgstr "" "%1$sSynthèse: Testés: %2$s%3$lu%4$s | Validés: %5$s%6$lu%7$s | Échoués: %8$s" "%9$lu%10$s | Plantages: %11$s%12$lu%13$s %14$s\n" -#: src/log/normal.c:76 +#: src/log/normal.c:77 #, fuzzy, c-format msgid "%s::%s: %s\n" msgstr "%1$s::%2$s: (%3$3.2fs)\n" From d527d2db802e270f95c64142edbd9990469423d6 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Fri, 30 Oct 2015 10:20:55 +0100 Subject: [PATCH 103/211] Fixed missing destructor, causing a memory leak --- src/core/stats.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/core/stats.c b/src/core/stats.c index dd8969b0..f68e9187 100644 --- a/src/core/stats.c +++ b/src/core/stats.c @@ -105,6 +105,11 @@ static void destroy_test_stats(void *ptr, CR_UNUSED void *meta) { } } +static void destroy_assert_stats(void *ptr, CR_UNUSED void *meta) { + s_assert_stats *stats = ptr; + free((void *) stats->message); +} + s_test_stats *test_stats_init(struct criterion_test *t) { s_test_stats *stats = smalloc( .size = sizeof (s_test_stats), @@ -182,7 +187,9 @@ static void push_assert(s_glob_stats *stats, s_assert_stats *data = ptr; - s_assert_stats *dup = smalloc(sizeof (s_assert_stats)); + s_assert_stats *dup = smalloc( + .size = sizeof (s_assert_stats), + .dtor = destroy_assert_stats); memcpy(dup, data, sizeof (s_assert_stats)); dup->message = strdup(data->message); From a3477d689acb338a51a16cfbcabe37930672d13a Mon Sep 17 00:00:00 2001 From: Snaipe Date: Sat, 31 Oct 2015 12:43:55 +0100 Subject: [PATCH 104/211] Added i18n cmake option --- CMakeLists.txt | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index f3b6e5df..3a934621 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -70,12 +70,16 @@ endif() # Find dependencies -find_package(Gettext) -find_package(Libintl) -if (GETTEXT_FOUND AND LIBINTL_LIB_FOUND) - include(GettextTranslate) - add_subdirectory(po) - set(ENABLE_NLS 1) +option(I18N "Turn on internationalization" ON) + +if (I18N) + find_package(Gettext) + find_package(Libintl) + if (GETTEXT_FOUND AND LIBINTL_LIB_FOUND) + include(GettextTranslate) + add_subdirectory(po) + set(ENABLE_NLS 1) + endif () endif () include(CheckLibraryExists) From 94eb04d9ff7eb50987c1e2369632312d55393c00 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Sun, 1 Nov 2015 10:02:19 +0100 Subject: [PATCH 105/211] Disabled i18n on appveyor builds --- appveyor.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/appveyor.yml b/appveyor.yml index ae991136..5940648d 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -41,6 +41,7 @@ install: cmake -Wno-dev -DCTESTS=ON + -DI18N=OFF -DCMAKE_INSTALL_PREFIX="criterion-%RELEASE_NAME%" -DCMAKE_BUILD_TYPE="%CONFIGURATION%" -G "%GENERATOR%" From c5c5fe86993ae0a3c085530f1fa32060733aa898 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Mon, 2 Nov 2015 12:32:40 +0100 Subject: [PATCH 106/211] Updated documentation for the new reporting system --- doc/env.rst | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/doc/env.rst b/doc/env.rst index d3e6aee9..4291f799 100644 --- a/doc/env.rst +++ b/doc/env.rst @@ -8,6 +8,7 @@ Command line arguments ---------------------- * ``-h or --help``: Show a help message with the available switches. +* ``-q or --quiet``: Disables all logging. * ``-v or --version``: Prints the version of criterion that has been linked against. * ``-l or --list``: Print all the tests in a list. @@ -22,8 +23,10 @@ Command line arguments This is useful when tracking memory leaks with ``valgrind --tool=memcheck``. * ``-S or --short-filename``: The filenames are displayed in their short form. * ``--always-succeed``: The process shall exit with a status of ``0``. -* ``--tap``: Enables the TAP (Test Anything Protocol) output format. -* ``--xml``: Enables the JUnit4 XML output format. +* ``--tap[=FILE]``: Writes a TAP (Test Anything Protocol) report to FILE. + No file or ``"-"`` means ``stderr``. +* ``--xml[=FILE]``: Writes JUnit4 XML report to FILE. + No file or ``"-"`` means ``stderr``. * ``--verbose[=level]``: Makes the output verbose. When provided with an integer, sets the verbosity level to that integer. @@ -71,8 +74,6 @@ Environment variables are alternatives to command line switches when set to 1. * ``CRITERION_ALWAYS_SUCCEED``: Same as ``--always-succeed``. * ``CRITERION_NO_EARLY_EXIT``: Same as ``--no-early-exit``. -* ``CRITERION_ENABLE_TAP``: Same as ``--tap``. -* ``CRITERION_ENABLE_XML``: Same as ``--xml``. * ``CRITERION_FAIL_FAST``: Same as ``--fail-fast``. * ``CRITERION_USE_ASCII``: Same as ``--ascii``. * ``CRITERION_JOBS``: Same as ``jobs``. Sets the number of jobs to From 06dcdc32c7ee4a88ee3b02d972b49a42ef769e30 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Tue, 3 Nov 2015 10:07:26 +0100 Subject: [PATCH 107/211] Fixed typo in env doc, added missing doc for CRITERION_DISABLE_TIME_MEASUREMENTS --- doc/env.rst | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/doc/env.rst b/doc/env.rst index d3e6aee9..67fcfd5a 100644 --- a/doc/env.rst +++ b/doc/env.rst @@ -75,10 +75,12 @@ Environment variables are alternatives to command line switches when set to 1. * ``CRITERION_ENABLE_XML``: Same as ``--xml``. * ``CRITERION_FAIL_FAST``: Same as ``--fail-fast``. * ``CRITERION_USE_ASCII``: Same as ``--ascii``. -* ``CRITERION_JOBS``: Same as ``jobs``. Sets the number of jobs to +* ``CRITERION_JOBS``: Same as ``--jobs``. Sets the number of jobs to its value. * ``CRITERION_SHORT_FILENAME``: Same as ``--short-filename``. * ``CRITERION_VERBOSITY_LEVEL``: Same as ``--verbose``. Sets the verbosity level to its value. * ``CRITERION_TEST_PATTERN``: Same as ``--pattern``. Sets the test pattern to its value. (\*nix only) +* ``CRITERION_DISABLE_TIME_MEASUREMENTS``: Disables any time measurements on + the tests. From 8659994fa9408014559f17d2fa7f4d7aa5cdb906 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Tue, 3 Nov 2015 10:03:05 +0100 Subject: [PATCH 108/211] Added auto-initializing output registration, to allow output provider registration before criterion_initialize() --- include/criterion/output.h | 2 -- src/core/runner.c | 1 - src/log/output.c | 34 +++++++++++++++++++++------------- src/log/output.h | 1 + 4 files changed, 22 insertions(+), 16 deletions(-) diff --git a/include/criterion/output.h b/include/criterion/output.h index baeeaba2..a5a0c666 100644 --- a/include/criterion/output.h +++ b/include/criterion/output.h @@ -28,9 +28,7 @@ typedef void criterion_reporter(FILE *stream, struct criterion_global_stats *); -void criterion_init_output(void); int criterion_register_output_provider(const char *name, criterion_reporter *reporter); int criterion_add_output(const char *provider, const char *path); -void criterion_free_output(void); #endif /* !CRITERION_OUTPUT_H_ */ diff --git a/src/core/runner.c b/src/core/runner.c index 1aae9359..7a87b811 100644 --- a/src/core/runner.c +++ b/src/core/runner.c @@ -348,7 +348,6 @@ struct criterion_test_set *criterion_initialize(void) { if (resume_child()) // (windows only) resume from the fork exit(0); - criterion_init_output(); criterion_register_output_provider("tap", tap_report); criterion_register_output_provider("xml", xml_report); diff --git a/src/log/output.c b/src/log/output.c index b5ce1fb2..25831e42 100644 --- a/src/log/output.c +++ b/src/log/output.c @@ -12,12 +12,10 @@ KHASH_MAP_INIT_STR(ht_path, str_vec*) static khash_t(ht_str) *reporters; static khash_t(ht_path) *outputs; -void criterion_init_output(void) { - reporters = kh_init(ht_str); - outputs = kh_init(ht_path); -} - int criterion_register_output_provider(const char *name, criterion_reporter *reporter) { + if (!reporters) + reporters = kh_init(ht_str); + int absent; khint_t k = kh_put(ht_str, reporters, name, &absent); kh_value(reporters, k) = reporter; @@ -25,6 +23,9 @@ int criterion_register_output_provider(const char *name, criterion_reporter *rep } int criterion_add_output(const char *provider, const char *path) { + if (!outputs) + outputs = kh_init(ht_path); + khint_t k = kh_get(ht_path, outputs, provider); if (k == kh_end(outputs)) { @@ -44,18 +45,25 @@ int criterion_add_output(const char *provider, const char *path) { } void criterion_free_output(void) { - for (khint_t k = kh_begin(outputs); k != kh_end(outputs); ++k) { - if (!kh_exist(outputs, k)) - continue; - str_vec *vec = kh_value(outputs, k); - kv_destroy(*vec); - free(vec); + if (reporters) + kh_destroy(ht_str, reporters); + + if (outputs) { + for (khint_t k = kh_begin(outputs); k != kh_end(outputs); ++k) { + if (!kh_exist(outputs, k)) + continue; + str_vec *vec = kh_value(outputs, k); + kv_destroy(*vec); + free(vec); + } + kh_destroy(ht_path, outputs); } - kh_destroy(ht_str, reporters); - kh_destroy(ht_path, outputs); } void process_all_output(struct criterion_global_stats *stats) { + if (!outputs || !reporters) + return; + for (khint_t k = kh_begin(reporters); k != kh_end(reporters); ++k) { if (!kh_exist(reporters, k)) continue; diff --git a/src/log/output.h b/src/log/output.h index e3322897..576ac342 100644 --- a/src/log/output.h +++ b/src/log/output.h @@ -27,6 +27,7 @@ # include "criterion/output.h" void process_all_output(struct criterion_global_stats *stats); +void criterion_free_output(void); void tap_report(FILE *f, struct criterion_global_stats *stats); void xml_report(FILE *f, struct criterion_global_stats *stats); From 554f25608fc467f8f04ca16b32c16380682ebfed Mon Sep 17 00:00:00 2001 From: Snaipe Date: Wed, 4 Nov 2015 20:18:47 +0100 Subject: [PATCH 109/211] Refactored output_provider -> logger, and moved actual output providers to io/ --- CMakeLists.txt | 8 +++++--- doc/internal.rst | 14 +++++++------- include/criterion/logging.h | 4 ++-- include/criterion/options.h | 2 +- src/core/report.h | 2 +- src/core/runner.c | 2 +- src/entry/main.c | 2 +- src/entry/options.c | 2 +- src/{log => io}/output.c | 0 src/{log => io}/output.h | 0 src/{log => io}/tap.c | 2 -- src/{log => io}/xml.c | 0 src/log/normal.c | 2 +- 13 files changed, 20 insertions(+), 20 deletions(-) rename src/{log => io}/output.c (100%) rename src/{log => io}/output.h (100%) rename src/{log => io}/tap.c (98%) rename src/{log => io}/xml.c (100%) diff --git a/CMakeLists.txt b/CMakeLists.txt index e5baa7b5..dd568704 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -127,11 +127,12 @@ set(SOURCE_FILES src/io/event.h src/io/asprintf.c src/io/file.c + src/io/output.c + src/io/output.h + src/io/tap.c + src/io/xml.c src/log/logging.c - src/log/output.c - src/log/tap.c src/log/normal.c - src/log/xml.c src/string/i18n.c src/string/i18n.h src/entry/options.c @@ -168,6 +169,7 @@ set(INTERFACE_FILES include/criterion/alloc.h include/criterion/parameterized.h include/criterion/redirect.h + include/criterion/output.h ) # Generate the configure file diff --git a/doc/internal.rst b/doc/internal.rst index 69b5f0ad..f1296282 100644 --- a/doc/internal.rst +++ b/doc/internal.rst @@ -28,7 +28,7 @@ Field Type Description =================== ================================== ============================================================== logging_threshold enum criterion_logging_level The logging level ------------------- ---------------------------------- -------------------------------------------------------------- -output_provider struct criterion_output_provider * The output provider (see below) +logger struct criterion_logger * The logger (see below) ------------------- ---------------------------------- -------------------------------------------------------------- no_early_exit bool True iff the test worker should exit early ------------------- ---------------------------------- -------------------------------------------------------------- @@ -75,15 +75,15 @@ Example main return result; } -Implementing your own output provider -------------------------------------- +Implementing your own logger +---------------------------- -In case you are not satisfied by the default output provider, you can implement -yours. To do so, simply set the ``output_provider`` option to your custom -output provider. +In case you are not satisfied by the default logger, you can implement +yours. To do so, simply set the ``logger`` option to your custom +logger. Each function contained in the structure is called during one of the standard phase of the criterion runner. -For more insight on how to implement this, see other existing output providers +For more insight on how to implement this, see other existing loggers in ``src/log/``. diff --git a/include/criterion/logging.h b/include/criterion/logging.h index 2e07f43f..3fbc27c3 100644 --- a/include/criterion/logging.h +++ b/include/criterion/logging.h @@ -103,7 +103,7 @@ CR_API void criterion_log(enum criterion_logging_level level, const char *msg, . # define criterion_perror(...) criterion_plog(CRITERION_IMPORTANT, CRITERION_PREFIX_ERR, __VA_ARGS__) -struct criterion_output_provider { +struct criterion_logger { void (*log_pre_all )(struct criterion_test_set *set); void (*log_pre_suite )(struct criterion_suite_set *set); void (*log_pre_init )(struct criterion_test *test); @@ -121,7 +121,7 @@ struct criterion_output_provider { void (*log_post_all )(struct criterion_global_stats *stats); }; -extern struct criterion_output_provider normal_logging; +extern struct criterion_logger normal_logging; CR_END_C_API diff --git a/include/criterion/options.h b/include/criterion/options.h index ee3a9c37..220e32c9 100644 --- a/include/criterion/options.h +++ b/include/criterion/options.h @@ -29,7 +29,7 @@ struct criterion_options { enum criterion_logging_level logging_threshold; - struct criterion_output_provider *output_provider; + struct criterion_logger *logger; bool no_early_exit; bool always_succeed; bool use_ascii; diff --git a/src/core/report.h b/src/core/report.h index dfee5ba1..aa545ea3 100644 --- a/src/core/report.h +++ b/src/core/report.h @@ -46,7 +46,7 @@ DECL_CALL_REPORT_HOOKS(POST_SUITE); DECL_CALL_REPORT_HOOKS(POST_ALL); #define log(Type, ...) \ - log_(criterion_options.output_provider->log_ ## Type, __VA_ARGS__); + log_(criterion_options.logger->log_ ## Type, __VA_ARGS__); #define log_(Log, ...) \ (Log ? Log(__VA_ARGS__) : nothing()); diff --git a/src/core/runner.c b/src/core/runner.c index 7a87b811..6ebae261 100644 --- a/src/core/runner.c +++ b/src/core/runner.c @@ -37,7 +37,7 @@ #include "wrappers/wrap.h" #include "string/i18n.h" #include "io/event.h" -#include "log/output.h" +#include "io/output.h" #include "runner_coroutine.h" #include "stats.h" #include "runner.h" diff --git a/src/entry/main.c b/src/entry/main.c index e6c9722e..6a73b37d 100644 --- a/src/entry/main.c +++ b/src/entry/main.c @@ -30,7 +30,7 @@ #include "criterion/options.h" #include "criterion/ordered-set.h" #include "core/runner.h" -#include "log/output.h" +#include "io/output.h" #include "config.h" #include "common.h" diff --git a/src/entry/options.c b/src/entry/options.c index 20295f92..0569a402 100644 --- a/src/entry/options.c +++ b/src/entry/options.c @@ -25,6 +25,6 @@ struct criterion_options criterion_options = { .logging_threshold = CRITERION_IMPORTANT, - .output_provider = &normal_logging, + .logger = &normal_logging, .measure_time = true, }; diff --git a/src/log/output.c b/src/io/output.c similarity index 100% rename from src/log/output.c rename to src/io/output.c diff --git a/src/log/output.h b/src/io/output.h similarity index 100% rename from src/log/output.h rename to src/io/output.h diff --git a/src/log/tap.c b/src/io/tap.c similarity index 98% rename from src/log/tap.c rename to src/io/tap.c index 779707df..6c7b7977 100644 --- a/src/log/tap.c +++ b/src/io/tap.c @@ -26,9 +26,7 @@ #include #include #include "criterion/stats.h" -#include "criterion/logging.h" #include "criterion/options.h" -#include "criterion/ordered-set.h" #include "compat/posix.h" #include "compat/strtok.h" #include "compat/time.h" diff --git a/src/log/xml.c b/src/io/xml.c similarity index 100% rename from src/log/xml.c rename to src/io/xml.c diff --git a/src/log/normal.c b/src/log/normal.c index f7319d38..9789d27e 100644 --- a/src/log/normal.c +++ b/src/log/normal.c @@ -233,7 +233,7 @@ void normal_log_test_abort(CR_UNUSED struct criterion_test_stats *stats, const c free(dup); } -struct criterion_output_provider normal_logging = { +struct criterion_logger normal_logging = { .log_pre_all = normal_log_pre_all, .log_pre_init = normal_log_pre_init, .log_pre_suite = normal_log_pre_suite, From d165e99e91d5f5ba550658f23d218d5b4a5e4517 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Thu, 5 Nov 2015 10:57:33 +0100 Subject: [PATCH 110/211] Relaxed io tests timeout to 1 second --- test/redirect.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/redirect.cc b/test/redirect.cc index daa4fbf1..3afd0ac5 100644 --- a/test/redirect.cc +++ b/test/redirect.cc @@ -4,7 +4,7 @@ #include // set a timeout for I/O tests -TestSuite(redirect, .timeout = 0.1); +TestSuite(redirect, .timeout = 1); #if __GNUC__ >= 5 Test(redirect, mock) { From a046cb2b3bf8d5527637dd38966b746f9f42b1a0 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Fri, 6 Nov 2015 10:21:48 +0100 Subject: [PATCH 111/211] Added documentation for registering custom output providers --- doc/index.rst | 1 + doc/output.rst | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+) create mode 100644 doc/output.rst diff --git a/doc/index.rst b/doc/index.rst index 1b2183b3..edb8e4c3 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -10,6 +10,7 @@ Criterion assert hooks env + output parameterized theories internal diff --git a/doc/output.rst b/doc/output.rst new file mode 100644 index 00000000..da4db3ff --- /dev/null +++ b/doc/output.rst @@ -0,0 +1,36 @@ +Writing tests reports in a custom format +======================================== + +Outputs providers are used to write tests reports in the format of your choice: +for instance, TAP and XML reporting are implemented with output providers. + +Adding a custom output provider +------------------------------- + +An output provider is a function with the following signature: + +.. code-block:: c + + void func(FILE *out, struct criterion_global_stats *stats); + +Once implemented, you then need to register it as an output provider: + +.. code-block:: c + + criterion_register_output_provider("provider name", func); + +This needs to be done before the test runner stops, so you may want to register +it either in a self-provided main, or in a PRE_ALL or POST_ALL report hook. + +Writing to a file with an output provider +----------------------------------------- + +To tell criterion to write a report to a specific file using the output provider +of your choice, you need to call ``criterion_add_output``: + +.. code-block:: c + + criterion_add_output("provider name", "/path/to/file"); + +The path may be relative. If ``"-"`` is passed as a filename, the report will +be written to ``stderr``. From 68b1d4dfcd1d5f776fd0048808986527690bbd9f Mon Sep 17 00:00:00 2001 From: Snaipe Date: Sat, 7 Nov 2015 10:58:10 +0100 Subject: [PATCH 112/211] Added --output CLI switch --- doc/env.rst | 9 +++++++-- doc/output.rst | 10 +++++++++- src/entry/main.c | 17 ++++++++++++++++- 3 files changed, 32 insertions(+), 4 deletions(-) diff --git a/doc/env.rst b/doc/env.rst index 4291f799..db7a480e 100644 --- a/doc/env.rst +++ b/doc/env.rst @@ -24,11 +24,16 @@ Command line arguments * ``-S or --short-filename``: The filenames are displayed in their short form. * ``--always-succeed``: The process shall exit with a status of ``0``. * ``--tap[=FILE]``: Writes a TAP (Test Anything Protocol) report to FILE. - No file or ``"-"`` means ``stderr``. + No file or ``"-"`` means ``stderr``. This option is equivalent to + ``--output=tap:FILE``. * ``--xml[=FILE]``: Writes JUnit4 XML report to FILE. - No file or ``"-"`` means ``stderr``. + No file or ``"-"`` means ``stderr``. This option is equivalent to + ``--output=xml:FILE``. * ``--verbose[=level]``: Makes the output verbose. When provided with an integer, sets the verbosity level to that integer. +* ``-OPROVIDER:FILE or --output=PROVIDER:FILE``: Write a test report to FILE + using the output provider named by PROVIDER. FILE may be a relative path, or + ``"-"`` to write to ``stderr``. Shell Wildcard Pattern ---------------------- diff --git a/doc/output.rst b/doc/output.rst index da4db3ff..482a6315 100644 --- a/doc/output.rst +++ b/doc/output.rst @@ -26,7 +26,15 @@ Writing to a file with an output provider ----------------------------------------- To tell criterion to write a report to a specific file using the output provider -of your choice, you need to call ``criterion_add_output``: +of your choice, you can either pass ``--output`` as a command-line +parameter: + +.. code-block:: bash + + ./my_tests --output="provider name":/path/to/file + +Or, you can do so directly by calling ``criterion_add_output`` before the +runner stops: .. code-block:: c diff --git a/src/entry/main.c b/src/entry/main.c index 6a73b37d..5783fd95 100644 --- a/src/entry/main.c +++ b/src/entry/main.c @@ -149,6 +149,7 @@ int criterion_handle_args(int argc, char *argv[], bool handle_unknown_arg) { #endif {"always-succeed", no_argument, 0, 'y'}, {"no-early-exit", no_argument, 0, 'z'}, + {"output", required_argument, 0, 'O'}, {0, 0, 0, 0 } }; @@ -198,7 +199,7 @@ int criterion_handle_args(int argc, char *argv[], bool handle_unknown_arg) { bool do_print_version = false; bool do_print_usage = false; bool quiet = false; - for (int c; (c = getopt_long(argc, argv, "hvlfj:Sq", opts, NULL)) != -1;) { + for (int c; (c = getopt_long(argc, argv, "hvlfj:SqO:", opts, NULL)) != -1;) { switch (c) { case 'b': criterion_options.logging_threshold = atou(DEF(optarg, "1")); break; case 'y': criterion_options.always_succeed = true; break; @@ -216,6 +217,20 @@ int criterion_handle_args(int argc, char *argv[], bool handle_unknown_arg) { case 'l': do_list_tests = true; break; case 'v': do_print_version = true; break; case 'h': do_print_usage = true; break; + case 'O': { + char *arg = strdup(optarg); + char *buf; + strtok_r(arg, ":", &buf); + + char *path = strtok_r(NULL, ":", &buf); + if (arg == NULL || path == NULL) { + do_print_usage = true; + break; + } + + quiet = true; + criterion_add_output(arg, path); + } break; case '?': default : do_print_usage = handle_unknown_arg; break; } From e4b1a6b3da34f80ec1b2effc27ae1f826b79d1a6 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Sun, 8 Nov 2015 11:17:49 +0100 Subject: [PATCH 113/211] Fixed warnings in entry/main.c --- src/entry/main.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/entry/main.c b/src/entry/main.c index 5783fd95..9e96dfa3 100644 --- a/src/entry/main.c +++ b/src/entry/main.c @@ -29,6 +29,7 @@ #include "criterion/criterion.h" #include "criterion/options.h" #include "criterion/ordered-set.h" +#include "compat/strtok.h" #include "core/runner.h" #include "io/output.h" #include "config.h" @@ -219,7 +220,7 @@ int criterion_handle_args(int argc, char *argv[], bool handle_unknown_arg) { case 'h': do_print_usage = true; break; case 'O': { char *arg = strdup(optarg); - char *buf; + char *buf = NULL; strtok_r(arg, ":", &buf); char *path = strtok_r(NULL, ":", &buf); From c240b6ff2f95519013e89a885cc84e3fc40955de Mon Sep 17 00:00:00 2001 From: Snaipe Date: Tue, 10 Nov 2015 13:49:59 +0100 Subject: [PATCH 114/211] Added --output to CLI help message --- src/entry/main.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/entry/main.c b/src/entry/main.c index 9e96dfa3..c4defad4 100644 --- a/src/entry/main.c +++ b/src/entry/main.c @@ -73,7 +73,9 @@ " --no-early-exit: do not exit the test worker " \ "prematurely after the test\n" \ " --verbose[=level]: sets verbosity to level " \ - "(1 by default)\n" + "(1 by default)\n" \ + " -OP:F or --output=PROVIDER=FILE: write test " \ + "report to FILE using the specified provider\n" int print_usage(char *progname) { fprintf(stderr, USAGE, progname); From 1b3be6458feb06ace38427562d479a1646e43f34 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Wed, 11 Nov 2015 14:10:23 +0100 Subject: [PATCH 115/211] Fixed missing import for windows compat in entry/main.c --- src/entry/main.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/entry/main.c b/src/entry/main.c index c4defad4..a1de7edb 100644 --- a/src/entry/main.c +++ b/src/entry/main.c @@ -29,6 +29,7 @@ #include "criterion/criterion.h" #include "criterion/options.h" #include "criterion/ordered-set.h" +#include "compat/posix.h" #include "compat/strtok.h" #include "core/runner.h" #include "io/output.h" From f940632c3a41d7c599fbef71d9ab47e1b3f192a5 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Sat, 7 Nov 2015 22:37:24 +0100 Subject: [PATCH 116/211] Added json output provider --- CMakeLists.txt | 1 + src/entry/main.c | 2 + src/io/json.c | 209 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 212 insertions(+) create mode 100644 src/io/json.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 266d38f7..4124c0a5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -135,6 +135,7 @@ set(SOURCE_FILES src/io/output.h src/io/tap.c src/io/xml.c + src/io/json.c src/log/logging.c src/log/normal.c src/string/i18n.c diff --git a/src/entry/main.c b/src/entry/main.c index a1de7edb..6e561de7 100644 --- a/src/entry/main.c +++ b/src/entry/main.c @@ -142,6 +142,7 @@ int criterion_handle_args(int argc, char *argv[], bool handle_unknown_arg) { {"version", no_argument, 0, 'v'}, {"tap", optional_argument, 0, 't'}, {"xml", optional_argument, 0, 'x'}, + {"json", optional_argument, 0, 'n'}, {"help", no_argument, 0, 'h'}, {"list", no_argument, 0, 'l'}, {"ascii", no_argument, 0, 'k'}, @@ -218,6 +219,7 @@ int criterion_handle_args(int argc, char *argv[], bool handle_unknown_arg) { case 'q': quiet = true; break; case 't': quiet = true; criterion_add_output("tap", DEF(optarg, "-")); break; case 'x': quiet = true; criterion_add_output("xml", DEF(optarg, "-")); break; + case 'n': quiet = true; criterion_add_output("json", DEF(optarg, "-")); break; case 'l': do_list_tests = true; break; case 'v': do_print_version = true; break; case 'h': do_print_usage = true; break; diff --git a/src/io/json.c b/src/io/json.c new file mode 100644 index 00000000..6c4d9bda --- /dev/null +++ b/src/io/json.c @@ -0,0 +1,209 @@ +/* + * The MIT License (MIT) + * + * Copyright © 2015 Franklin "Snaipe" Mathieu + * + * 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. + */ +#define _GNU_SOURCE +#include +#include +#include +#include "criterion/stats.h" +#include "criterion/logging.h" +#include "criterion/options.h" +#include "criterion/ordered-set.h" +#include "compat/posix.h" +#include "compat/strtok.h" +#include "compat/time.h" +#include "config.h" +#include "common.h" + +#define JSON_TEST_TEMPLATE_BEGIN \ + " {\n" \ + " \"name\": \"%s\",\n" \ + " \"assertions\": " CR_SIZE_T_FORMAT ",\n" \ + " \"status\": \"%s\"" + +#define JSON_TEST_TEMPLATE_END \ + "\n" \ + " }" + +#define JSON_TEST_FAILED_TEMPLATE_BEGIN \ + ",\n" \ + " \"messages\": [\n" + +#define JSON_TEST_FAILED_TEMPLATE_END \ + "\n" \ + " ]" + +#define JSON_FAILURE_MSG_ENTRY \ + " \"%s:%u: %s\"" + +#define JSON_CRASH_MSG_ENTRY \ + ",\n" \ + " \"messages\": [\"The test crashed.\"]" + +#define JSON_TIMEOUT_MSG_ENTRY \ + ",\n" \ + " \"messages\": [\"The test timed out.\"]" + +#define JSON_SKIPPED_MSG_ENTRY \ + ",\n" \ + " \"messages\": [\"The test was skipped.\"]" + +#define JSON_TEST_LIST_TEMPLATE_BEGIN \ + " \"tests\": [\n" + +#define JSON_TEST_LIST_TEMPLATE_END \ + " ]\n" + +#define JSON_TESTSUITE_TEMPLATE_BEGIN \ + " {\n" \ + " \"name\": \"%s\",\n" \ + " \"passed\": " CR_SIZE_T_FORMAT ",\n" \ + " \"failed\": " CR_SIZE_T_FORMAT ",\n" \ + " \"errored\": " CR_SIZE_T_FORMAT ",\n" \ + " \"skipped\": " CR_SIZE_T_FORMAT ",\n" + +#define JSON_TESTSUITE_TEMPLATE_END \ + " }" + +#define JSON_TESTSUITE_LIST_TEMPLATE_BEGIN \ + " \"test_suites\": [\n" + +#define JSON_TESTSUITE_LIST_TEMPLATE_END \ + " ]\n" + +#define JSON_BASE_TEMPLATE_BEGIN \ + "{\n" \ + " \"id\": \"Criterion v" VERSION "\",\n" \ + " \"passed\": " CR_SIZE_T_FORMAT ",\n" \ + " \"failed\": " CR_SIZE_T_FORMAT ",\n" \ + " \"errored\": " CR_SIZE_T_FORMAT ",\n" \ + " \"skipped\": " CR_SIZE_T_FORMAT ",\n" \ + +#define JSON_BASE_TEMPLATE_END \ + "}\n" + +static INLINE bool is_disabled(struct criterion_test *t, struct criterion_suite *s) { + return t->data->disabled || (s->data && s->data->disabled); +} + +static CR_INLINE +const char *get_status_string(struct criterion_test_stats *ts, + struct criterion_suite_stats *ss) { + + const char *status = "PASSED"; + if (ts->crashed || ts->timed_out) + status = "ERRORED"; + else if (ts->failed) + status = "FAILED"; + else if (is_disabled(ts->test, ss->suite)) + status = "SKIPPED"; + return status; +} + +static void print_test(struct criterion_test_stats *ts, + struct criterion_suite_stats *ss) { + + criterion_important(JSON_TEST_TEMPLATE_BEGIN, + ts->test->name, + (size_t) (ts->passed_asserts + ts->failed_asserts), + get_status_string(ts, ss) + ); + + if (is_disabled(ts->test, ss->suite)) { + criterion_important(JSON_SKIPPED_MSG_ENTRY); + } else if (ts->crashed) { + criterion_important(JSON_CRASH_MSG_ENTRY); + } else if (ts->timed_out) { + criterion_important(JSON_TIMEOUT_MSG_ENTRY); + } else if (ts->failed) { + criterion_important(JSON_TEST_FAILED_TEMPLATE_BEGIN); + + bool first = true; + for (struct criterion_assert_stats *asrt = ts->asserts; asrt; asrt = asrt->next) { + if (!asrt->passed) { + if (!first) { + criterion_important(",\n"); + } else { + first = false; + } + + bool sf = criterion_options.short_filename; + char *dup = strdup(*asrt->message ? asrt->message : ""); + char *saveptr = NULL; + char *line = strtok_r(dup, "\n", &saveptr); + + criterion_important(JSON_FAILURE_MSG_ENTRY, + sf ? basename_compat(asrt->file) : asrt->file, + asrt->line, + line + ); + + while ((line = strtok_r(NULL, "\n", &saveptr))) { + criterion_important(",\n \" %s\"\n", line); + } + free(dup); + } + } + criterion_important(JSON_TEST_FAILED_TEMPLATE_END); + } + + criterion_important(JSON_TEST_TEMPLATE_END); +} + +void json_log_post_all(struct criterion_global_stats *stats) { + criterion_important(JSON_BASE_TEMPLATE_BEGIN, + stats->tests_passed, + stats->tests_failed, + stats->tests_crashed, + stats->tests_skipped + ); + + criterion_important(JSON_TESTSUITE_LIST_TEMPLATE_BEGIN); + for (struct criterion_suite_stats *ss = stats->suites; ss; ss = ss->next) { + + criterion_important(JSON_TESTSUITE_TEMPLATE_BEGIN, + ss->suite->name, + ss->tests_passed, + ss->tests_failed, + ss->tests_crashed, + ss->tests_skipped + ); + + criterion_important(JSON_TEST_LIST_TEMPLATE_BEGIN); + for (struct criterion_test_stats *ts = ss->tests; ts; ts = ts->next) { + print_test(ts, ss); + criterion_important(ts->next ? ",\n" : "\n"); + } + criterion_important(JSON_TEST_LIST_TEMPLATE_END); + + criterion_important(JSON_TESTSUITE_TEMPLATE_END); + criterion_important(ss->next ? ",\n" : "\n"); + } + criterion_important(JSON_TESTSUITE_LIST_TEMPLATE_END); + + criterion_important(JSON_BASE_TEMPLATE_END); +} + +struct criterion_output_provider json_logging = { + .log_post_all = json_log_post_all, +}; From e59adbff47eb7eed71f0bef6d21c3f29d87926c0 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Mon, 9 Nov 2015 01:18:56 +0100 Subject: [PATCH 117/211] Updated json reporter for the new reporting system --- src/core/runner.c | 1 + src/io/json.c | 51 ++++++++++++++++++++++------------------------- src/io/output.h | 1 + 3 files changed, 26 insertions(+), 27 deletions(-) diff --git a/src/core/runner.c b/src/core/runner.c index 6ebae261..22a0f911 100644 --- a/src/core/runner.c +++ b/src/core/runner.c @@ -350,6 +350,7 @@ struct criterion_test_set *criterion_initialize(void) { criterion_register_output_provider("tap", tap_report); criterion_register_output_provider("xml", xml_report); + criterion_register_output_provider("json", json_report); return criterion_init(); } diff --git a/src/io/json.c b/src/io/json.c index 6c4d9bda..c23ebdcf 100644 --- a/src/io/json.c +++ b/src/io/json.c @@ -120,29 +120,30 @@ const char *get_status_string(struct criterion_test_stats *ts, return status; } -static void print_test(struct criterion_test_stats *ts, +static void print_test(FILE *f, + struct criterion_test_stats *ts, struct criterion_suite_stats *ss) { - criterion_important(JSON_TEST_TEMPLATE_BEGIN, + fprintf(f, JSON_TEST_TEMPLATE_BEGIN, ts->test->name, (size_t) (ts->passed_asserts + ts->failed_asserts), get_status_string(ts, ss) ); if (is_disabled(ts->test, ss->suite)) { - criterion_important(JSON_SKIPPED_MSG_ENTRY); + fprintf(f, JSON_SKIPPED_MSG_ENTRY); } else if (ts->crashed) { - criterion_important(JSON_CRASH_MSG_ENTRY); + fprintf(f, JSON_CRASH_MSG_ENTRY); } else if (ts->timed_out) { - criterion_important(JSON_TIMEOUT_MSG_ENTRY); + fprintf(f, JSON_TIMEOUT_MSG_ENTRY); } else if (ts->failed) { - criterion_important(JSON_TEST_FAILED_TEMPLATE_BEGIN); + fprintf(f, JSON_TEST_FAILED_TEMPLATE_BEGIN); bool first = true; for (struct criterion_assert_stats *asrt = ts->asserts; asrt; asrt = asrt->next) { if (!asrt->passed) { if (!first) { - criterion_important(",\n"); + fprintf(f, ",\n"); } else { first = false; } @@ -152,36 +153,36 @@ static void print_test(struct criterion_test_stats *ts, char *saveptr = NULL; char *line = strtok_r(dup, "\n", &saveptr); - criterion_important(JSON_FAILURE_MSG_ENTRY, + fprintf(f, JSON_FAILURE_MSG_ENTRY, sf ? basename_compat(asrt->file) : asrt->file, asrt->line, line ); while ((line = strtok_r(NULL, "\n", &saveptr))) { - criterion_important(",\n \" %s\"\n", line); + fprintf(f, ",\n \" %s\"\n", line); } free(dup); } } - criterion_important(JSON_TEST_FAILED_TEMPLATE_END); + fprintf(f, JSON_TEST_FAILED_TEMPLATE_END); } - criterion_important(JSON_TEST_TEMPLATE_END); + fprintf(f, JSON_TEST_TEMPLATE_END); } -void json_log_post_all(struct criterion_global_stats *stats) { - criterion_important(JSON_BASE_TEMPLATE_BEGIN, +void json_report(FILE *f, struct criterion_global_stats *stats) { + fprintf(f, JSON_BASE_TEMPLATE_BEGIN, stats->tests_passed, stats->tests_failed, stats->tests_crashed, stats->tests_skipped ); - criterion_important(JSON_TESTSUITE_LIST_TEMPLATE_BEGIN); + fprintf(f, JSON_TESTSUITE_LIST_TEMPLATE_BEGIN); for (struct criterion_suite_stats *ss = stats->suites; ss; ss = ss->next) { - criterion_important(JSON_TESTSUITE_TEMPLATE_BEGIN, + fprintf(f, JSON_TESTSUITE_TEMPLATE_BEGIN, ss->suite->name, ss->tests_passed, ss->tests_failed, @@ -189,21 +190,17 @@ void json_log_post_all(struct criterion_global_stats *stats) { ss->tests_skipped ); - criterion_important(JSON_TEST_LIST_TEMPLATE_BEGIN); + fprintf(f, JSON_TEST_LIST_TEMPLATE_BEGIN); for (struct criterion_test_stats *ts = ss->tests; ts; ts = ts->next) { - print_test(ts, ss); - criterion_important(ts->next ? ",\n" : "\n"); + print_test(f, ts, ss); + fprintf(f, ts->next ? ",\n" : "\n"); } - criterion_important(JSON_TEST_LIST_TEMPLATE_END); + fprintf(f, JSON_TEST_LIST_TEMPLATE_END); - criterion_important(JSON_TESTSUITE_TEMPLATE_END); - criterion_important(ss->next ? ",\n" : "\n"); + fprintf(f, JSON_TESTSUITE_TEMPLATE_END); + fprintf(f, ss->next ? ",\n" : "\n"); } - criterion_important(JSON_TESTSUITE_LIST_TEMPLATE_END); + fprintf(f, JSON_TESTSUITE_LIST_TEMPLATE_END); - criterion_important(JSON_BASE_TEMPLATE_END); + fprintf(f, JSON_BASE_TEMPLATE_END); } - -struct criterion_output_provider json_logging = { - .log_post_all = json_log_post_all, -}; diff --git a/src/io/output.h b/src/io/output.h index 576ac342..eccf24bf 100644 --- a/src/io/output.h +++ b/src/io/output.h @@ -31,5 +31,6 @@ void criterion_free_output(void); void tap_report(FILE *f, struct criterion_global_stats *stats); void xml_report(FILE *f, struct criterion_global_stats *stats); +void json_report(FILE *f, struct criterion_global_stats *stats); #endif /* !OUTPUT_H_ */ From 3cfb0aa5a8bb97237461968c979d92c348e0a65e Mon Sep 17 00:00:00 2001 From: Snaipe Date: Wed, 11 Nov 2015 13:26:49 +0100 Subject: [PATCH 118/211] Added documentation for --json --- doc/env.rst | 3 +++ 1 file changed, 3 insertions(+) diff --git a/doc/env.rst b/doc/env.rst index 5ff950ca..234a4966 100644 --- a/doc/env.rst +++ b/doc/env.rst @@ -29,6 +29,9 @@ Command line arguments * ``--xml[=FILE]``: Writes JUnit4 XML report to FILE. No file or ``"-"`` means ``stderr``. This option is equivalent to ``--output=xml:FILE``. +* ``--json[=FILE]``: Writes a JSON report to FILE. + No file or ``"-"`` means ``stderr``. This option is equivalent to + ``--output=json:FILE``. * ``--verbose[=level]``: Makes the output verbose. When provided with an integer, sets the verbosity level to that integer. * ``-OPROVIDER:FILE or --output=PROVIDER:FILE``: Write a test report to FILE From 3c9086dd6374c923d72c5936f2ae3d4c1ec95b4a Mon Sep 17 00:00:00 2001 From: Snaipe Date: Wed, 11 Nov 2015 13:41:08 +0100 Subject: [PATCH 119/211] Fixed typo in json output --- src/io/json.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/io/json.c b/src/io/json.c index c23ebdcf..a893e57e 100644 --- a/src/io/json.c +++ b/src/io/json.c @@ -160,7 +160,7 @@ static void print_test(FILE *f, ); while ((line = strtok_r(NULL, "\n", &saveptr))) { - fprintf(f, ",\n \" %s\"\n", line); + fprintf(f, ",\n \" %s\"", line); } free(dup); } From a6ff1f110cc527c01fe823163b96644c23987948 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Wed, 11 Nov 2015 13:41:47 +0100 Subject: [PATCH 120/211] Added json regression test --- samples/CMakeLists.txt | 1 + samples/tests/json_test.sh | 7 + .../tests/outputs/json_test.sh.err.expected | 237 ++++++++++++++++++ .../tests/outputs/json_test.sh.out.expected | 0 4 files changed, 245 insertions(+) create mode 100755 samples/tests/json_test.sh create mode 100644 samples/tests/outputs/json_test.sh.err.expected create mode 100644 samples/tests/outputs/json_test.sh.out.expected diff --git a/samples/CMakeLists.txt b/samples/CMakeLists.txt index 954dd097..cfe0e39b 100644 --- a/samples/CMakeLists.txt +++ b/samples/CMakeLists.txt @@ -35,6 +35,7 @@ set(SAMPLES set(SCRIPTS tap_test xml_test + json_test early_exit verbose list diff --git a/samples/tests/json_test.sh b/samples/tests/json_test.sh new file mode 100755 index 00000000..2546c00e --- /dev/null +++ b/samples/tests/json_test.sh @@ -0,0 +1,7 @@ +#!/bin/sh +./simple.c.bin --json --always-succeed +./signal.c.bin --json --always-succeed +./asserts.c.bin --json --always-succeed +./more-suites.c.bin --json --always-succeed +./tests/long-messages.c.bin --json --always-succeed +./description.c.bin --json --always-succeed diff --git a/samples/tests/outputs/json_test.sh.err.expected b/samples/tests/outputs/json_test.sh.err.expected new file mode 100644 index 00000000..001f0dc1 --- /dev/null +++ b/samples/tests/outputs/json_test.sh.err.expected @@ -0,0 +1,237 @@ +{ + "id": "Criterion v2.1.0", + "passed": 1, + "failed": 1, + "errored": 0, + "skipped": 0, + "test_suites": [ + { + "name": "misc", + "passed": 1, + "failed": 1, + "errored": 0, + "skipped": 0, + "tests": [ + { + "name": "passing", + "assertions": 1, + "status": "PASSED" + }, + { + "name": "failing", + "assertions": 1, + "status": "FAILED", + "messages": [ + "simple.c:4: The expression 0 is false." + ] + } + ] + } + ] +} +{ + "id": "Criterion v2.1.0", + "passed": 1, + "failed": 2, + "errored": 1, + "skipped": 0, + "test_suites": [ + { + "name": "simple", + "passed": 1, + "failed": 2, + "errored": 1, + "skipped": 0, + "tests": [ + { + "name": "wrong_signal", + "assertions": 0, + "status": "FAILED", + "messages": [ + + ] + }, + { + "name": "uncaught", + "assertions": 0, + "status": "ERRORED", + "messages": ["The test crashed."] + }, + { + "name": "caught", + "assertions": 0, + "status": "PASSED" + } + ] + } + ] +} +{ + "id": "Criterion v2.1.0", + "passed": 4, + "failed": 2, + "errored": 0, + "skipped": 0, + "test_suites": [ + { + "name": "asserts", + "passed": 4, + "failed": 2, + "errored": 0, + "skipped": 0, + "tests": [ + { + "name": "string", + "assertions": 10, + "status": "PASSED" + }, + { + "name": "old_school", + "assertions": 2, + "status": "FAILED", + "messages": [ + "asserts.c:18: The conditions for this assertion were not met.", + "asserts.c:17: You can fail an assertion with a message from anywhere" + ] + }, + { + "name": "native", + "assertions": 8, + "status": "PASSED" + }, + { + "name": "float", + "assertions": 2, + "status": "PASSED" + }, + { + "name": "base", + "assertions": 6, + "status": "FAILED", + "messages": [ + "asserts.c:12: This assert runs", + "asserts.c:11: assert is fatal, expect isn't" + ] + }, + { + "name": "array", + "assertions": 3, + "status": "PASSED" + } + ] + } + ] +} +{ + "id": "Criterion v2.1.0", + "passed": 2, + "failed": 0, + "errored": 0, + "skipped": 1, + "test_suites": [ + { + "name": "suite2", + "passed": 1, + "failed": 0, + "errored": 0, + "skipped": 0, + "tests": [ + { + "name": "test", + "assertions": 1, + "status": "PASSED" + } + ] + }, + { + "name": "suite1", + "passed": 1, + "failed": 0, + "errored": 0, + "skipped": 0, + "tests": [ + { + "name": "test", + "assertions": 1, + "status": "PASSED" + } + ] + }, + { + "name": "disabled", + "passed": 0, + "failed": 0, + "errored": 0, + "skipped": 1, + "tests": [ + { + "name": "test", + "assertions": 0, + "status": "SKIPPED", + "messages": ["The test was skipped."] + } + ] + } + ] +} +{ + "id": "Criterion v2.1.0", + "passed": 0, + "failed": 1, + "errored": 0, + "skipped": 0, + "test_suites": [ + { + "name": "sample", + "passed": 0, + "failed": 1, + "errored": 0, + "skipped": 0, + "tests": [ + { + "name": "long_msg", + "assertions": 1, + "status": "FAILED", + "messages": [ + "long-messages.c:4: This is", + " A long message", + " Spawning multiple lines.", + " Formatting is respected." + ] + } + ] + } + ] +} +{ + "id": "Criterion v2.1.0", + "passed": 0, + "failed": 1, + "errored": 0, + "skipped": 1, + "test_suites": [ + { + "name": "misc", + "passed": 0, + "failed": 1, + "errored": 0, + "skipped": 1, + "tests": [ + { + "name": "skipped", + "assertions": 0, + "status": "SKIPPED", + "messages": ["The test was skipped."] + }, + { + "name": "failing", + "assertions": 1, + "status": "FAILED", + "messages": [ + "description.c:4: The expression 0 is false." + ] + } + ] + } + ] +} diff --git a/samples/tests/outputs/json_test.sh.out.expected b/samples/tests/outputs/json_test.sh.out.expected new file mode 100644 index 00000000..e69de29b From 586be28378578d3c08edb1f8fd9d28b4f83ebf6e Mon Sep 17 00:00:00 2001 From: Snaipe Date: Wed, 11 Nov 2015 13:45:52 +0100 Subject: [PATCH 121/211] Fixed script regression tests --- samples/CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/samples/CMakeLists.txt b/samples/CMakeLists.txt index 954dd097..d707767c 100644 --- a/samples/CMakeLists.txt +++ b/samples/CMakeLists.txt @@ -79,13 +79,13 @@ add_samples("${CMAKE_CURRENT_LIST_DIR}/tests" "${SAMPLES}") if (NOT MSVC) # we disable the scripted tests when building with MSVC foreach(script ${SCRIPTS}) - add_test(${script} sh ${CMAKE_CURRENT_LIST_DIR}/tests/${script}.sh) + add_test(${script} sh "${CMAKE_CURRENT_LIST_DIR}/tests/${script}.sh") set_property(TEST ${script} PROPERTY ENVIRONMENT "CRITERION_ALWAYS_SUCCEED=1" ENVIRONMENT "CRITERION_NO_EARLY_EXIT=1" # for coverage ) - add_test(${script}_compare sh ${CMAKE_CURRENT_LIST_DIR}/tests/run_test.sh "${CMAKE_CURRENT_LIST_DIR}" . "${CMAKE_CURRENT_LIST_DIR}" tests/${script}) + add_test(${script}_compare sh ${CMAKE_CURRENT_LIST_DIR}/tests/run_test.sh "${CMAKE_CURRENT_LIST_DIR}" . "${CMAKE_CURRENT_LIST_DIR}" "tests/${script}.sh") set_property(TEST ${script}_compare PROPERTY ENVIRONMENT "LC_ALL=en_US.utf8" ENVIRONMENT "CRITERION_ALWAYS_SUCCEED=1" From 17f16f60ce2e80809768813dd340d94b0ee5148a Mon Sep 17 00:00:00 2001 From: Snaipe Date: Wed, 11 Nov 2015 13:48:18 +0100 Subject: [PATCH 122/211] Updated gitignore --- .gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index e28ebbfa..4cc4aa25 100644 --- a/.gitignore +++ b/.gitignore @@ -16,7 +16,7 @@ !*.po !*.in !samples/tests/*.sh -!samples/*.expected +!samples/**/*.expected !LICENSE !HEADER From 3e5f43ff74cd5099b8f76362e2de7838beacc851 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Wed, 11 Nov 2015 13:52:22 +0100 Subject: [PATCH 123/211] Fixed XML regression tests --- .../tests/outputs/xml_test.sh.err.expected | 82 +++++++++++++++++++ .../tests/outputs/xml_test.sh.out.expected | 0 samples/tests/xml_test.sh | 2 +- 3 files changed, 83 insertions(+), 1 deletion(-) create mode 100644 samples/tests/outputs/xml_test.sh.err.expected create mode 100644 samples/tests/outputs/xml_test.sh.out.expected diff --git a/samples/tests/outputs/xml_test.sh.err.expected b/samples/tests/outputs/xml_test.sh.err.expected new file mode 100644 index 00000000..b3f83625 --- /dev/null +++ b/samples/tests/outputs/xml_test.sh.err.expected @@ -0,0 +1,82 @@ + + + + + + + + simple.c:4: The expression 0 is false. + + + + + + + + + + + + + + + + + + + + + + + + asserts.c:18: The conditions for this assertion were not met. asserts.c:17: You can fail an assertion with a message from anywhere + + + + + + + asserts.c:12: This assert runs asserts.c:11: assert is fatal, expect isn't + + + + + + + + + + + + + + + + + + + + + + + + + + + + long-messages.c:4: This is A long message Spawning multiple lines. Formatting is respected. + + + + + + + + + + + + description.c:4: The expression 0 is false. + + + diff --git a/samples/tests/outputs/xml_test.sh.out.expected b/samples/tests/outputs/xml_test.sh.out.expected new file mode 100644 index 00000000..e69de29b diff --git a/samples/tests/xml_test.sh b/samples/tests/xml_test.sh index 9f0ab261..d0740d92 100755 --- a/samples/tests/xml_test.sh +++ b/samples/tests/xml_test.sh @@ -3,5 +3,5 @@ ./signal.c.bin --xml --always-succeed ./asserts.c.bin --xml --always-succeed ./more-suites.c.bin --xml --always-succeed -./long-messages.c.bin --xml --always-succeed +./tests/long-messages.c.bin --xml --always-succeed ./description.c.bin --xml --always-succeed From f6cf64f71f81c9b1f5c2b3a71eed679bf1376cd1 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Thu, 12 Nov 2015 16:02:33 +0100 Subject: [PATCH 124/211] Cleaned up travis config --- .travis.yml | 87 ++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 66 insertions(+), 21 deletions(-) diff --git a/.travis.yml b/.travis.yml index bf515dda..aa4ddb60 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,13 +1,9 @@ language: c -os: -- linux -- osx - -compiler: -- gcc-4.9 sudo: false +osx_image: xcode7 + addons: apt: sources: @@ -17,33 +13,82 @@ addons: - g++-4.9 - gobjc-4.9 - gnustep-devel -env: - global: - GCOV: gcov-4.9 - CXX: g++-4.9 - matrix: - - CONFIGURATION=Debug COVERAGE=ON - - CONFIGURATION=Release COVERAGE=OFF - - CONFIGURATION=RelWithDebInfo COVERAGE=OFF + +matrix: + include: + # Linux Debug, GCC 4.9 + - compiler: gcc-4.9 + env: + CONFIGURATION: Debug + GCOV: gcov-4.9 + CMAKE_OPTS: -DLANG_OBJC=ON + COVERAGE: ON + # Linux Release, GCC 4.9 + - compiler: gcc-4.9 + env: + CONFIGURATION: Release + CMAKE_OPTS: -DLANG_OBJC=ON + # Linux RelWithDebInfo, GCC 4.9 + - compiler: gcc-4.9 + env: + CONFIGURATION: RelWithDebInfo + CMAKE_OPTS: -DLANG_OBJC=ON + DEPLOY: true + # OSX Debug, GCC 4.9 + - os: osx + compiler: gcc-4.9 + env: + CONFIGURATION: Debug + GCOV: gcov-4.9 + COVERAGE: ON + # OSX Release, GCC 4.9 + - os: osx + compiler: gcc-4.9 + env: CONFIGURATION=Release + # OSX RelWithDebInfo, GCC 4.9 + - os: osx + compiler: gcc-4.9 + env: CONFIGURATION=RelWithDebInfo + # OSX Debug, Clang + - os: osx + compiler: clang + env: + CONFIGURATION: Debug + CMAKE_OPTS: -DLANG_OBJC=ON + # OSX Release, Clang + - os: osx + compiler: clang + env: + CONFIGURATION: Release + CMAKE_OPTS: -DLANG_OBJC=ON + # OSX RelWithDebInfo, Clang + - os: osx + compiler: clang + env: + CONFIGURATION: RelWithDebInfo + CMAKE_OPTS: -DLANG_OBJC=ON + DEPLOY: true script: - - mkdir -p build - - cd build + - export CXX=${${CC/gcc/g++/}/clang/clang++} + - mkdir -p build && cd $_ - > cmake -Wno-dev -DCTESTS=ON - -DCOVERALLS=${COVERAGE} + -DCOVERALLS=${COVERAGE:-OFF} -DCMAKE_BUILD_TYPE=${CONFIGURATION} -DCMAKE_INSTALL_PREFIX=criterion-${TRAVIS_TAG} - -DLANG_OBJC=ON + ${CMAKE_OPTS} .. - TERM=dumb cmake --build . --target criterion_tests -- -j4 - ctest -j4 after_success: - - make gcov - - bash <(curl -s https://codecov.io/bash) + - > + [ "$COVERAGE" = "ON" ] && + make gcov && + bash <(curl -s https://codecov.io/bash) after_failure: - cat Testing/Temporary/LastTest.log samples/*.{out,err} ../samples/tests/*.{out,err} @@ -61,4 +106,4 @@ deploy: on: repo: Snaipe/Criterion tags: true - condition: $CONFIGURATION = RelWithDebInfo + condition: $DEPLOY = true From 022cc88e247d2c6e14ea5e7e3b64ecf70b183e69 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Thu, 12 Nov 2015 16:20:40 +0100 Subject: [PATCH 125/211] Fixed substitution chaining not working on bash --- .travis.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index aa4ddb60..216d04f3 100644 --- a/.travis.yml +++ b/.travis.yml @@ -70,7 +70,8 @@ matrix: DEPLOY: true script: - - export CXX=${${CC/gcc/g++/}/clang/clang++} + - export CXX=${CC/gcc/g++/} + - export CXX=${CXX/clang/clang++} - mkdir -p build && cd $_ - > cmake From 947bdbf4e191792eb1b405162aef76860e17703b Mon Sep 17 00:00:00 2001 From: Snaipe Date: Thu, 12 Nov 2015 16:23:25 +0100 Subject: [PATCH 126/211] Fixed typo in travis config --- .travis.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 216d04f3..109e4e6b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -70,8 +70,7 @@ matrix: DEPLOY: true script: - - export CXX=${CC/gcc/g++/} - - export CXX=${CXX/clang/clang++} + - export CXX=${CC/gcc/g++}; export CXX=${CXX/clang/clang++} - mkdir -p build && cd $_ - > cmake From b25756b46e520fcc2ec7d70a7b4bf79b162373c2 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Thu, 12 Nov 2015 16:36:42 +0100 Subject: [PATCH 127/211] Install cmake on travis osx build --- .travis.yml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.travis.yml b/.travis.yml index 109e4e6b..f5328bd7 100644 --- a/.travis.yml +++ b/.travis.yml @@ -69,6 +69,13 @@ matrix: CMAKE_OPTS: -DLANG_OBJC=ON DEPLOY: true +before_install: + - > + [ "$TRAVIS_OS_NAME" = "osx" ] && ( + brew update; + brew outdated cmake || brew upgrade cmake + ) + script: - export CXX=${CC/gcc/g++}; export CXX=${CXX/clang/clang++} - mkdir -p build && cd $_ From 4322fb50cf91a2e0dd134c137782059e9571da71 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Thu, 12 Nov 2015 16:45:32 +0100 Subject: [PATCH 128/211] Fixed travis script conditions --- .travis.yml | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/.travis.yml b/.travis.yml index f5328bd7..cc657c36 100644 --- a/.travis.yml +++ b/.travis.yml @@ -70,11 +70,11 @@ matrix: DEPLOY: true before_install: - - > - [ "$TRAVIS_OS_NAME" = "osx" ] && ( + - | + if [ "$TRAVIS_OS_NAME" = "osx" ]; then brew update; brew outdated cmake || brew upgrade cmake - ) + fi script: - export CXX=${CC/gcc/g++}; export CXX=${CXX/clang/clang++} @@ -92,10 +92,11 @@ script: - ctest -j4 after_success: - - > - [ "$COVERAGE" = "ON" ] && - make gcov && - bash <(curl -s https://codecov.io/bash) + - | + if [ "$COVERAGE" = "ON" ]; then + make gcov + bash <(curl -s https://codecov.io/bash) + fi after_failure: - cat Testing/Temporary/LastTest.log samples/*.{out,err} ../samples/tests/*.{out,err} From 03ed0a910a217997c59fda24ca229f9e2e809c73 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Thu, 12 Nov 2015 16:54:48 +0100 Subject: [PATCH 129/211] Switched OSX image to default on travis CI builds --- .travis.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index cc657c36..f773b186 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,8 +2,6 @@ language: c sudo: false -osx_image: xcode7 - addons: apt: sources: @@ -73,11 +71,13 @@ before_install: - | if [ "$TRAVIS_OS_NAME" = "osx" ]; then brew update; - brew outdated cmake || brew upgrade cmake + brew install llvm --with-clang --with-asan --HEAD fi + - export CXX=${CC/gcc/g++}; export CXX=${CXX/clang/clang++} + - $CC --version + - $CXX --version script: - - export CXX=${CC/gcc/g++}; export CXX=${CXX/clang/clang++} - mkdir -p build && cd $_ - > cmake From 62e01eed74d0b98de3ff3fb3b0b79d7fa8741e48 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Thu, 12 Nov 2015 17:02:14 +0100 Subject: [PATCH 130/211] Removed clang installation on OSX gcc builds --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index f773b186..a362b033 100644 --- a/.travis.yml +++ b/.travis.yml @@ -69,7 +69,7 @@ matrix: before_install: - | - if [ "$TRAVIS_OS_NAME" = "osx" ]; then + if [ "$TRAVIS_OS_NAME" = "osx" ] && [ "$CC" = "clang" ]; then brew update; brew install llvm --with-clang --with-asan --HEAD fi From e41b3a6572742291c2af00c2208dfd60e7b83d49 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Thu, 12 Nov 2015 17:13:41 +0100 Subject: [PATCH 131/211] Removed source build for clang on osx travis builds --- .travis.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index a362b033..3426f55d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -70,8 +70,9 @@ matrix: before_install: - | if [ "$TRAVIS_OS_NAME" = "osx" ] && [ "$CC" = "clang" ]; then - brew update; - brew install llvm --with-clang --with-asan --HEAD + brew update + brew unlink cmake + brew install llvm cmake fi - export CXX=${CC/gcc/g++}; export CXX=${CXX/clang/clang++} - $CC --version From c77ec236780a36dc0f146d87af21515a5efd24ee Mon Sep 17 00:00:00 2001 From: Snaipe Date: Thu, 12 Nov 2015 23:37:13 +0100 Subject: [PATCH 132/211] Fixed regression test for TAP output format --- .../tests/outputs/tap_test.sh.err.expected | 61 +++++++++++++++++++ .../tests/outputs/tap_test.sh.out.expected | 0 samples/tests/tap_test.sh | 2 +- 3 files changed, 62 insertions(+), 1 deletion(-) create mode 100644 samples/tests/outputs/tap_test.sh.err.expected create mode 100644 samples/tests/outputs/tap_test.sh.out.expected diff --git a/samples/tests/outputs/tap_test.sh.err.expected b/samples/tests/outputs/tap_test.sh.err.expected new file mode 100644 index 00000000..56f3268c --- /dev/null +++ b/samples/tests/outputs/tap_test.sh.err.expected @@ -0,0 +1,61 @@ +TAP version 13 +1..2 +# Criterion v2.1.0 + +# Running 2 tests from misc +ok - misc::passing (0.00s) +not ok - misc::failing (0.00s) + simple.c:4: Assertion failed: The expression 0 is false. +TAP version 13 +1..3 +# Criterion v2.1.0 + +# Running 3 tests from simple +not ok - simple::wrong_signal (0.00s) +not ok - simple::uncaught unexpected signal after signal.c:16 +ok - simple::caught (0.00s) +TAP version 13 +1..6 +# Criterion v2.1.0 + +# Running 6 tests from asserts +ok - asserts::string (0.00s) +not ok - asserts::old_school (0.00s) + asserts.c:18: Assertion failed: The conditions for this assertion were not met. + asserts.c:17: Assertion failed: You can fail an assertion with a message from anywhere +ok - asserts::native (0.00s) +ok - asserts::float (0.00s) +not ok - asserts::base (0.00s) + asserts.c:12: Assertion failed: This assert runs + asserts.c:11: Assertion failed: assert is fatal, expect isn't +ok - asserts::array (0.00s) +TAP version 13 +1..3 +# Criterion v2.1.0 + +# Running 1 tests from suite2 +ok - suite2::test (0.00s) + +# Running 1 tests from suite1 +ok - suite1::test (0.00s) + +# Running 1 tests from disabled +ok - disabled::test # SKIP suite is disabled +TAP version 13 +1..1 +# Criterion v2.1.0 + +# Running 1 tests from sample +not ok - sample::long_msg (0.00s) + long-messages.c:4: Assertion failed: This is + A long message + Spawning multiple lines. + Formatting is respected. +TAP version 13 +1..2 +# Criterion v2.1.0 + +# Running 2 tests from misc +ok - misc::skipped This one is skipped # SKIP test is disabled +not ok - misc::failing Just a failing test (0.00s) + description.c:4: Assertion failed: The expression 0 is false. diff --git a/samples/tests/outputs/tap_test.sh.out.expected b/samples/tests/outputs/tap_test.sh.out.expected new file mode 100644 index 00000000..e69de29b diff --git a/samples/tests/tap_test.sh b/samples/tests/tap_test.sh index 5e81fbf6..9faca2d2 100755 --- a/samples/tests/tap_test.sh +++ b/samples/tests/tap_test.sh @@ -3,5 +3,5 @@ ./signal.c.bin --tap --always-succeed ./asserts.c.bin --tap --always-succeed ./more-suites.c.bin --tap --always-succeed -./long-messages.c.bin --tap --always-succeed +./tests/long-messages.c.bin --tap --always-succeed ./description.c.bin --tap --always-succeed From 161719070c972a12afe36b42c2a18ea1e58ed765 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Fri, 13 Nov 2015 19:31:32 +0100 Subject: [PATCH 133/211] Fixed recent MinGW builds failing due to quick fix on the definitions of off_t and off64_t --- src/compat/internal.h | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/compat/internal.h b/src/compat/internal.h index 551212b9..5a04bdc1 100644 --- a/src/compat/internal.h +++ b/src/compat/internal.h @@ -30,9 +30,19 @@ # undef _WIN32_WINNT # define _WIN32_WINNT 0x0502 # include + +# include + +typedef int32_t cr_off32 +typedef int64_t cr_off64 + # if defined(__MINGW32__) || defined(__MINGW64__) -# define off_t _off_t -# define off64_t _off64_t +# if !defined(__MINGW64__) +# define off_t cr_off32 +# else +# define off_t cr_off64 +# endif +# define off64_t cr_off64 # endif # include # if defined(__MINGW32__) || defined(__MINGW64__) From 969f0fed747fb4713a88db7effa10f51128a7a22 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Sat, 14 Nov 2015 11:13:43 +0100 Subject: [PATCH 134/211] Extend commit 1617190 on src/compat/posix.h --- src/compat/posix.h | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/compat/posix.h b/src/compat/posix.h index 4468f63e..c3d94a55 100644 --- a/src/compat/posix.h +++ b/src/compat/posix.h @@ -41,8 +41,18 @@ # define TMP_POSIX # endif # if defined(__MINGW32__) || defined(__MINGW64__) -# define off_t _off_t -# define off64_t _off64_t + +# include + +typedef int32_t cr_off32 +typedef int64_t cr_off64 + +# if !defined(__MINGW64__) +# define off_t cr_off32 +# else +# define off_t cr_off64 +# endif +# define off64_t cr_off64 # endif # include # include From a76e828dc7ee66114b0974285da4feca2d8a7d8d Mon Sep 17 00:00:00 2001 From: Snaipe Date: Sun, 15 Nov 2015 12:00:49 +0100 Subject: [PATCH 135/211] Fixed typo on MinGW code --- src/compat/internal.h | 4 ++-- src/compat/posix.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/compat/internal.h b/src/compat/internal.h index 5a04bdc1..d56f1a08 100644 --- a/src/compat/internal.h +++ b/src/compat/internal.h @@ -33,8 +33,8 @@ # include -typedef int32_t cr_off32 -typedef int64_t cr_off64 +typedef int32_t cr_off32; +typedef int64_t cr_off64; # if defined(__MINGW32__) || defined(__MINGW64__) # if !defined(__MINGW64__) diff --git a/src/compat/posix.h b/src/compat/posix.h index c3d94a55..b4a35b57 100644 --- a/src/compat/posix.h +++ b/src/compat/posix.h @@ -44,8 +44,8 @@ # include -typedef int32_t cr_off32 -typedef int64_t cr_off64 +typedef int32_t cr_off32; +typedef int64_t cr_off64; # if !defined(__MINGW64__) # define off_t cr_off32 From 900a1e0a29d7e8e98fd04fa6ee21f838771c4e54 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Sun, 15 Nov 2015 19:48:29 +0100 Subject: [PATCH 136/211] Refactored cr_off{32,64} definitions to its own header file to avoid collisions --- src/compat/internal.h | 6 ++---- src/compat/off_t.h | 9 +++++++++ src/compat/posix.h | 5 +---- 3 files changed, 12 insertions(+), 8 deletions(-) create mode 100644 src/compat/off_t.h diff --git a/src/compat/internal.h b/src/compat/internal.h index d56f1a08..47d32cdd 100644 --- a/src/compat/internal.h +++ b/src/compat/internal.h @@ -31,12 +31,10 @@ # define _WIN32_WINNT 0x0502 # include -# include +# if defined(__MINGW32__) || defined(__MINGW64__) -typedef int32_t cr_off32; -typedef int64_t cr_off64; +# include "off_t.h" -# if defined(__MINGW32__) || defined(__MINGW64__) # if !defined(__MINGW64__) # define off_t cr_off32 # else diff --git a/src/compat/off_t.h b/src/compat/off_t.h new file mode 100644 index 00000000..24dc65d0 --- /dev/null +++ b/src/compat/off_t.h @@ -0,0 +1,9 @@ +#ifndef OFF_T_H_ +# define OFF_T_H_ + +# include + +typedef int32_t cr_off32; +typedef int64_t cr_off64; + +#endif /* !OFF_T_H_ */ diff --git a/src/compat/posix.h b/src/compat/posix.h index b4a35b57..81af6b31 100644 --- a/src/compat/posix.h +++ b/src/compat/posix.h @@ -42,10 +42,7 @@ # endif # if defined(__MINGW32__) || defined(__MINGW64__) -# include - -typedef int32_t cr_off32; -typedef int64_t cr_off64; +# include "off_t.h" # if !defined(__MINGW64__) # define off_t cr_off32 From dd557f6f68b40077bcdee9bc3adb0ec348a9e506 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Sun, 15 Nov 2015 22:41:17 +0100 Subject: [PATCH 137/211] Added __STRICT_ANSI__ check for off_t definition on MinGW builds --- src/compat/internal.h | 14 ++++++++------ src/compat/off_t.h | 29 ++++++++++++++++++++++++++--- src/compat/posix.h | 14 ++++++++------ 3 files changed, 42 insertions(+), 15 deletions(-) diff --git a/src/compat/internal.h b/src/compat/internal.h index 47d32cdd..d1c342ce 100644 --- a/src/compat/internal.h +++ b/src/compat/internal.h @@ -33,14 +33,16 @@ # if defined(__MINGW32__) || defined(__MINGW64__) -# include "off_t.h" +# if defined(__STRICT_ANSI__) || defined(MINGW_DEFINE_OFF_T) +# include "off_t.h" -# if !defined(__MINGW64__) -# define off_t cr_off32 -# else -# define off_t cr_off64 +# if !defined(__MINGW64__) +# define off_t cr_off32 +# else +# define off_t cr_off64 +# endif +# define off64_t cr_off64 # endif -# define off64_t cr_off64 # endif # include # if defined(__MINGW32__) || defined(__MINGW64__) diff --git a/src/compat/off_t.h b/src/compat/off_t.h index 24dc65d0..5918cea5 100644 --- a/src/compat/off_t.h +++ b/src/compat/off_t.h @@ -1,9 +1,32 @@ -#ifndef OFF_T_H_ -# define OFF_T_H_ +/* + * The MIT License (MIT) + * + * Copyright © 2015 Franklin "Snaipe" Mathieu + * + * 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 CR_OFF_T_DEFINED +# define CR_OFF_T_DEFINED # include typedef int32_t cr_off32; typedef int64_t cr_off64; -#endif /* !OFF_T_H_ */ +#endif /* !CR_OFF_T_DEFINED */ diff --git a/src/compat/posix.h b/src/compat/posix.h index 81af6b31..0a7bbda0 100644 --- a/src/compat/posix.h +++ b/src/compat/posix.h @@ -42,14 +42,16 @@ # endif # if defined(__MINGW32__) || defined(__MINGW64__) -# include "off_t.h" +# if defined(__STRICT_ANSI__) || defined(MINGW_DEFINE_OFF_T) +# include "off_t.h" -# if !defined(__MINGW64__) -# define off_t cr_off32 -# else -# define off_t cr_off64 +# if !defined(__MINGW64__) +# define off_t cr_off32 +# else +# define off_t cr_off64 +# endif +# define off64_t cr_off64 # endif -# define off64_t cr_off64 # endif # include # include From e7faf8aaed010f0ddc66539bed3fcf886b3a7c75 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Sun, 15 Nov 2015 22:52:25 +0100 Subject: [PATCH 138/211] Removed ansi checks for off_t definition, and added option to define it if needed. --- CMakeLists.txt | 4 ++++ src/compat/internal.h | 19 ++++++++----------- src/compat/posix.h | 19 ++++++++----------- src/config.h.in | 1 + 4 files changed, 21 insertions(+), 22 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 4124c0a5..96e093c5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -53,6 +53,10 @@ if (WIN32 AND NOT MSVC) set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,-no-undefined") endif() +# Compilation options + +option(MINGW_DEFINE_OFF_T "Define off_t and off64_t ourselves before including io.h" OFF) + # Setup coveralls option(COVERALLS "Turn on coveralls support" OFF) diff --git a/src/compat/internal.h b/src/compat/internal.h index d1c342ce..deb41bc0 100644 --- a/src/compat/internal.h +++ b/src/compat/internal.h @@ -31,21 +31,18 @@ # define _WIN32_WINNT 0x0502 # include -# if defined(__MINGW32__) || defined(__MINGW64__) +# if defined(MINGW_DEFINE_OFF_T) && (defined(__MINGW32__) || defined(__MINGW64__)) +# include "off_t.h" -# if defined(__STRICT_ANSI__) || defined(MINGW_DEFINE_OFF_T) -# include "off_t.h" - -# if !defined(__MINGW64__) -# define off_t cr_off32 -# else -# define off_t cr_off64 -# endif -# define off64_t cr_off64 +# if !defined(__MINGW64__) +# define off_t cr_off32 +# else +# define off_t cr_off64 # endif +# define off64_t cr_off64 # endif # include -# if defined(__MINGW32__) || defined(__MINGW64__) +# if defined(MINGW_DEFINE_OFF_T) && (defined(__MINGW32__) || defined(__MINGW64__)) # undef off_t # undef off64_t # endif diff --git a/src/compat/posix.h b/src/compat/posix.h index 0a7bbda0..1081942b 100644 --- a/src/compat/posix.h +++ b/src/compat/posix.h @@ -40,22 +40,19 @@ # define _POSIX_SOURCE 1 # define TMP_POSIX # endif -# if defined(__MINGW32__) || defined(__MINGW64__) +# if defined(MINGW_DEFINE_OFF_T) && (defined(__MINGW32__) || defined(__MINGW64__)) +# include "off_t.h" -# if defined(__STRICT_ANSI__) || defined(MINGW_DEFINE_OFF_T) -# include "off_t.h" - -# if !defined(__MINGW64__) -# define off_t cr_off32 -# else -# define off_t cr_off64 -# endif -# define off64_t cr_off64 +# if !defined(__MINGW64__) +# define off_t cr_off32 +# else +# define off_t cr_off64 # endif +# define off64_t cr_off64 # endif # include # include -# if defined(__MINGW32__) || defined(__MINGW64__) +# if defined(MINGW_DEFINE_OFF_T) && defined(__MINGW32__) || defined(__MINGW64__) # undef off_t # undef off64_t # endif diff --git a/src/config.h.in b/src/config.h.in index 6455bff3..43f70588 100644 --- a/src/config.h.in +++ b/src/config.h.in @@ -5,6 +5,7 @@ #cmakedefine HAVE_PCRE @HAVE_PCRE@ #cmakedefine ENABLE_VALGRIND_ERRORS @ENABLE_VALGRIND_ERRORS@ #cmakedefine01 HAVE_STRTOK_S +#cmakedefine01 MINGW_DEFINE_OFF_T # define LOCALEDIR "${LOCALEDIR}" # define PACKAGE "${PROJECT_NAME}" From 10e933d7588725ba3c89b8bb26ff3e4b06bda114 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Mon, 16 Nov 2015 00:21:30 +0100 Subject: [PATCH 139/211] Fixed pedantic warnings for C99 + POSIX 2008 compatibility --- CMakeLists.txt | 6 +++++- include/criterion/ordered-set.h | 3 +-- src/core/ordered-set.c | 10 +++++----- src/core/report.c | 22 +++++++++++----------- src/core/report.h | 3 ++- src/core/runner.c | 12 ++++++++---- src/core/runner_coroutine.c | 4 ++-- src/core/stats.c | 2 +- src/core/theories.c | 2 +- src/string/extmatch.c | 10 +++++----- 10 files changed, 41 insertions(+), 33 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 96e093c5..3fb7ca7a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -41,7 +41,7 @@ set(GettextTranslate_GMO_BINARY 1) add_definitions(-DCRITERION_BUILDING_DLL=1) if (NOT MSVC) - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Werror -g -std=gnu99") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Werror -pedantic -pedantic-errors -Wno-format -std=c99") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Werror -g -std=c++11") endif () @@ -53,6 +53,10 @@ if (WIN32 AND NOT MSVC) set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,-no-undefined") endif() +# Enable standard extensions + +add_definitions(-D_XOPEN_SOURCE=700) + # Compilation options option(MINGW_DEFINE_OFF_T "Define off_t and off64_t ourselves before including io.h" OFF) diff --git a/include/criterion/ordered-set.h b/include/criterion/ordered-set.h index 24044f81..07c5148f 100644 --- a/include/criterion/ordered-set.h +++ b/include/criterion/ordered-set.h @@ -37,7 +37,6 @@ struct criterion_ordered_set { struct criterion_ordered_set_node { struct criterion_ordered_set_node *next; - char data[0]; }; CR_BEGIN_C_API @@ -54,6 +53,6 @@ CR_END_C_API # define FOREACH_SET(Elt, Set) \ for (struct criterion_ordered_set_node *n = Set->first; n; n = n->next) \ for (int cond = 1; cond;) \ - for (Elt = (void*) n->data; cond && (cond = 0, 1);) + for (Elt = (void*) (n + 1); cond && (cond = 0, 1);) #endif /* !CRITERION_ORDERED_SET_H_ */ diff --git a/src/core/ordered-set.c b/src/core/ordered-set.c index fa9c5c5e..c7c6f38c 100644 --- a/src/core/ordered-set.c +++ b/src/core/ordered-set.c @@ -36,7 +36,7 @@ static INLINE void nothing(CR_UNUSED void *ptr, CR_UNUSED void *meta) {} static void destroy_ordered_set_node(void *ptr, void *meta) { struct criterion_ordered_set *set = *(void **) meta; struct criterion_ordered_set_node *n = ptr; - DEF(set->dtor, nothing)(n->data, NULL); + DEF(set->dtor, nothing)(n + 1, NULL); sfree(((struct criterion_ordered_set_node *) ptr)->next); } @@ -58,11 +58,11 @@ void *insert_ordered_set(struct criterion_ordered_set *l, size_t size) { int cmp; struct criterion_ordered_set_node *n, *prev = NULL; - for (n = l->first; n && (cmp = l->cmp(ptr, n->data)) > 0; n = n->next) + for (n = l->first; n && (cmp = l->cmp(ptr, n + 1)) > 0; n = n->next) prev = n; if (n && !cmp) // element already exists - return n->data; + return n + 1; struct criterion_ordered_set_node *new = smalloc( .size = sizeof(struct criterion_ordered_set_node) + size, @@ -72,7 +72,7 @@ void *insert_ordered_set(struct criterion_ordered_set *l, if (!new) return NULL; - memcpy(new->data, ptr, size); + memcpy(new + 1, ptr, size); new->next = n; if (prev) { prev->next = new; @@ -81,5 +81,5 @@ void *insert_ordered_set(struct criterion_ordered_set *l, } ++l->size; - return new->data; + return new + 1; } diff --git a/src/core/report.c b/src/core/report.c index 71123192..c91e7807 100644 --- a/src/core/report.c +++ b/src/core/report.c @@ -71,17 +71,17 @@ f_report_hook CR_SECTION_END_(CR_HOOK_SECTION(POST_SUITE)); f_report_hook CR_SECTION_END_(CR_HOOK_SECTION(POST_ALL)); #endif -IMPL_CALL_REPORT_HOOKS(PRE_ALL); -IMPL_CALL_REPORT_HOOKS(PRE_SUITE); -IMPL_CALL_REPORT_HOOKS(PRE_INIT); -IMPL_CALL_REPORT_HOOKS(PRE_TEST); -IMPL_CALL_REPORT_HOOKS(ASSERT); -IMPL_CALL_REPORT_HOOKS(THEORY_FAIL); -IMPL_CALL_REPORT_HOOKS(TEST_CRASH); -IMPL_CALL_REPORT_HOOKS(POST_TEST); -IMPL_CALL_REPORT_HOOKS(POST_FINI); -IMPL_CALL_REPORT_HOOKS(POST_SUITE); -IMPL_CALL_REPORT_HOOKS(POST_ALL); +IMPL_CALL_REPORT_HOOKS(PRE_ALL) +IMPL_CALL_REPORT_HOOKS(PRE_SUITE) +IMPL_CALL_REPORT_HOOKS(PRE_INIT) +IMPL_CALL_REPORT_HOOKS(PRE_TEST) +IMPL_CALL_REPORT_HOOKS(ASSERT) +IMPL_CALL_REPORT_HOOKS(THEORY_FAIL) +IMPL_CALL_REPORT_HOOKS(TEST_CRASH) +IMPL_CALL_REPORT_HOOKS(POST_TEST) +IMPL_CALL_REPORT_HOOKS(POST_FINI) +IMPL_CALL_REPORT_HOOKS(POST_SUITE) +IMPL_CALL_REPORT_HOOKS(POST_ALL) ReportHook(PRE_ALL)(CR_UNUSED struct criterion_test_set *arg) {} ReportHook(PRE_SUITE)(CR_UNUSED struct criterion_suite_set *arg) {} diff --git a/src/core/report.h b/src/core/report.h index aa545ea3..27139741 100644 --- a/src/core/report.h +++ b/src/core/report.h @@ -27,7 +27,8 @@ # include "criterion/hooks.h" # include "criterion/options.h" -# define report(Kind, Data) call_report_hooks_##Kind(Data) +# define report(Kind, Data) report_(Kind, Data) +# define report_(Kind, Data) call_report_hooks_##Kind(Data) # define DECL_CALL_REPORT_HOOKS(Kind) \ CR_DECL_SECTION_LIMITS(f_report_hook, CR_HOOK_SECTION(Kind)); \ diff --git a/src/core/runner.c b/src/core/runner.c index 22a0f911..30d990a7 100644 --- a/src/core/runner.c +++ b/src/core/runner.c @@ -31,6 +31,7 @@ #include "criterion/options.h" #include "criterion/ordered-set.h" #include "criterion/logging.h" +#include "criterion/preprocess.h" #include "compat/time.h" #include "compat/posix.h" #include "compat/processor.h" @@ -84,7 +85,7 @@ CR_IMPL_SECTION_LIMITS(struct criterion_suite*, cr_sts); // This is here to make the test suite & test sections non-empty TestSuite(); -Test(,) {}; +Test(,) {} static INLINE void nothing(void) {} @@ -178,13 +179,16 @@ void run_test_child(struct criterion_test *test, g_wrappers[test->data->lang_](test, suite); } -#define push_event(Kind, ...) \ +#define push_event(...) \ do { \ stat_push_event(ctx->stats, \ ctx->suite_stats, \ ctx->test_stats, \ - &(struct event) { .kind = Kind, __VA_ARGS__ }); \ - report(Kind, ctx->test_stats); \ + &(struct event) { \ + .kind = CR_VA_HEAD(__VA_ARGS__), \ + CR_VA_TAIL(__VA_ARGS__) \ + }); \ + report(CR_VA_HEAD(__VA_ARGS__), ctx->test_stats); \ } while (0) s_pipe_handle *g_worker_pipe; diff --git a/src/core/runner_coroutine.c b/src/core/runner_coroutine.c index 31a271c2..6e557a3d 100644 --- a/src/core/runner_coroutine.c +++ b/src/core/runner_coroutine.c @@ -112,7 +112,7 @@ struct worker *run_next_test(struct criterion_test_set *p_set, ccrReturn(NULL); for (ctx->ns = ctx->set->suites->first; ctx->ns; ctx->ns = ctx->ns->next) { - ctx->suite_set = (void*) ctx->ns->data; + ctx->suite_set = (void*) (ctx->ns + 1); if (!ctx->suite_set->tests) continue; @@ -126,7 +126,7 @@ struct worker *run_next_test(struct criterion_test_set *p_set, stat_push_event(ctx->stats, ctx->suite_stats, NULL, &ev); for (ctx->nt = ctx->suite_set->tests->first; ctx->nt; ctx->nt = ctx->nt->next) { - ctx->test = (void*) ctx->nt->data; + ctx->test = (void*) (ctx->nt + 1); if (ctx->test->data->kind_ == CR_TEST_PARAMETERIZED && ctx->test->data->param_) { diff --git a/src/core/stats.c b/src/core/stats.c index f68e9187..bb10bac9 100644 --- a/src/core/stats.c +++ b/src/core/stats.c @@ -59,7 +59,7 @@ static void nothing(CR_UNUSED s_glob_stats *stats, CR_UNUSED s_suite_stats *sstats, CR_UNUSED s_test_stats *tstats, CR_UNUSED void *data) { -}; +} static void destroy_stats(void *ptr, CR_UNUSED void *meta) { s_glob_stats *stats = ptr; diff --git a/src/core/theories.c b/src/core/theories.c index 28d0d127..d1a027c1 100644 --- a/src/core/theories.c +++ b/src/core/theories.c @@ -91,7 +91,7 @@ void cr_theory_reset(struct criterion_theory_context *ctx) { } void cr_theory_call(struct criterion_theory_context *ctx, void (*fnptr)(void)) { - dcCallVoid(ctx->vm, (DCpointer) fnptr); + dcCallVoid(ctx->vm, (DCpointer) (unsigned long long) fnptr); } static bool contains_word(const char *str, const char *pattern, size_t sz) { diff --git a/src/string/extmatch.c b/src/string/extmatch.c index b838ff94..3af6da9e 100644 --- a/src/string/extmatch.c +++ b/src/string/extmatch.c @@ -134,16 +134,16 @@ static inline void handle_special(struct context *ctx, handler_arg strs[5]) { } # define _ active -Handler(handle_plus, [POSTSUFFIX] = {_, "+"}, [ELSESTR] = {_, "+" }); -Handler(handle_star, [POSTSUFFIX] = {_, "*"}, [ELSESTR] = {_, ".*"}); -Handler(handle_wild, [POSTSUFFIX] = {_, "?"}, [ELSESTR] = {_, "." }); +Handler(handle_plus, [POSTSUFFIX] = {_, "+"}, [ELSESTR] = {_, "+" }) +Handler(handle_star, [POSTSUFFIX] = {_, "*"}, [ELSESTR] = {_, ".*"}) +Handler(handle_wild, [POSTSUFFIX] = {_, "?"}, [ELSESTR] = {_, "." }) Handler(handle_excl, [POSTPREFIX] = {_, "?!"}, [PRESUFFIX] = {is_eos, "$" }, [POSTSUFFIX] = {_, ".*"}, [ELSESTR] = {_, "!" } - ); -Handler(handle_at, [ELSESTR] = {_, "@"}); + ) +Handler(handle_at, [ELSESTR] = {_, "@"}) # undef _ static void handle_rbra(struct context *ctx, CR_UNUSED char c) { From cb02a30576727c222c654e3f87e1b309c006f52d Mon Sep 17 00:00:00 2001 From: Snaipe Date: Mon, 16 Nov 2015 00:33:58 +0100 Subject: [PATCH 140/211] Removed MINGW_DEFINE_OFF_T definition when option is off --- src/config.h.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/config.h.in b/src/config.h.in index 43f70588..0040dad9 100644 --- a/src/config.h.in +++ b/src/config.h.in @@ -4,8 +4,8 @@ #cmakedefine ENABLE_NLS @ENABLE_NLS@ #cmakedefine HAVE_PCRE @HAVE_PCRE@ #cmakedefine ENABLE_VALGRIND_ERRORS @ENABLE_VALGRIND_ERRORS@ +#cmakedefine MINGW_DEFINE_OFF_T @MINGW_DEFINE_OFF_T@ #cmakedefine01 HAVE_STRTOK_S -#cmakedefine01 MINGW_DEFINE_OFF_T # define LOCALEDIR "${LOCALEDIR}" # define PACKAGE "${PROJECT_NAME}" From 44d9e436fe9498513ca80cbc3c6d16649f2b7d4f Mon Sep 17 00:00:00 2001 From: Snaipe Date: Mon, 16 Nov 2015 00:40:20 +0100 Subject: [PATCH 141/211] Removed pedantic warnings and used GNU C 99 standard --- CMakeLists.txt | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 3fb7ca7a..96e093c5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -41,7 +41,7 @@ set(GettextTranslate_GMO_BINARY 1) add_definitions(-DCRITERION_BUILDING_DLL=1) if (NOT MSVC) - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Werror -pedantic -pedantic-errors -Wno-format -std=c99") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Werror -g -std=gnu99") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Werror -g -std=c++11") endif () @@ -53,10 +53,6 @@ if (WIN32 AND NOT MSVC) set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,-no-undefined") endif() -# Enable standard extensions - -add_definitions(-D_XOPEN_SOURCE=700) - # Compilation options option(MINGW_DEFINE_OFF_T "Define off_t and off64_t ourselves before including io.h" OFF) From 5388dd03417b730c12c2e288e6236ff774cb0661 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Mon, 16 Nov 2015 14:50:00 +0100 Subject: [PATCH 142/211] Removed intermediate function pointer cast to integer in theory function call --- src/core/theories.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/theories.c b/src/core/theories.c index d1a027c1..28d0d127 100644 --- a/src/core/theories.c +++ b/src/core/theories.c @@ -91,7 +91,7 @@ void cr_theory_reset(struct criterion_theory_context *ctx) { } void cr_theory_call(struct criterion_theory_context *ctx, void (*fnptr)(void)) { - dcCallVoid(ctx->vm, (DCpointer) (unsigned long long) fnptr); + dcCallVoid(ctx->vm, (DCpointer) fnptr); } static bool contains_word(const char *str, const char *pattern, size_t sz) { From 5e329559356e63e9731e289b1088b0c19aeb79d9 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Mon, 16 Nov 2015 15:13:34 +0100 Subject: [PATCH 143/211] Added cmake 3.4.0 objective C compiler include fix --- .cmake/Modules/CMakeObjectiveCInformation.cmake | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/.cmake/Modules/CMakeObjectiveCInformation.cmake b/.cmake/Modules/CMakeObjectiveCInformation.cmake index ba3f47cf..1a49d7c4 100644 --- a/.cmake/Modules/CMakeObjectiveCInformation.cmake +++ b/.cmake/Modules/CMakeObjectiveCInformation.cmake @@ -156,8 +156,13 @@ set(CMAKE_ObjectiveC_IMPLICIT_LINK_LIBRARIES objc) # compile a C file into an object file if(NOT CMAKE_ObjectiveC_COMPILE_OBJECT) - set(CMAKE_ObjectiveC_COMPILE_OBJECT - " -o -c ") + if("${CMAKE_VERSION}" VERSION_GREATER 3.3.2) + set(CMAKE_ObjectiveC_COMPILE_OBJECT + " -o -c ") + else () + set(CMAKE_ObjectiveC_COMPILE_OBJECT + " -o -c ") + endif () endif() if(NOT CMAKE_ObjectiveC_LINK_EXECUTABLE) From d59b810a56b1b390d6b1b9e1fd7b684102210a30 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Mon, 16 Nov 2015 16:06:25 +0100 Subject: [PATCH 144/211] Added Foundation framework to link flags on OS X + Clang --- CMakeLists.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index b95a7843..85127b01 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -161,6 +161,9 @@ endif () if (CMAKE_ObjectiveC_COMPILER_WORKS) set(CMAKE_ObjectiveC_FLAGS "${CMAKE_ObjectiveC_FLAGS} ${CMAKE_C_FLAGS} -fobjc-exceptions") + if ("${CMAKE_ObjectiveC_COMPILER_ID}" STREQUAL "Clang" AND APPLE) + set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -framework Foundation") + endif () add_definitions(-D_NATIVE_OBJC_EXCEPTIONS) if (NOT WIN32) From 3e0cba01f45ed53b9b8211eeb4243ceee40ecfad Mon Sep 17 00:00:00 2001 From: Snaipe Date: Mon, 16 Nov 2015 16:34:00 +0100 Subject: [PATCH 145/211] Fixed appveyor not displaying the test logs in the event of failure --- appveyor.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index 5940648d..22a8ea99 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -60,7 +60,11 @@ before_deploy: test_script: - cmake --build . --target criterion_tests - - ps: try { ctest -j2 } catch { type Testing/Temporary/LastTest.log } + - ps: | + ctest -j2 + if (-not $lastexitcode -eq 0) { + type Testing/Temporary/LastTest.log + } #after_test: # - 'make coveralls' From f0e4f758d20b71ecb88b99c5f06db0a7183eb0c7 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Mon, 16 Nov 2015 08:27:23 -0800 Subject: [PATCH 146/211] Fixed regression tests being sensitive to line endings --- samples/tests/run_test.sh | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/samples/tests/run_test.sh b/samples/tests/run_test.sh index 8d81472d..14d386d0 100755 --- a/samples/tests/run_test.sh +++ b/samples/tests/run_test.sh @@ -13,14 +13,14 @@ else sh -c "$bin_dir/$*" > $out_dir/$1.out 2> $out_dir/$1.err fi -dos2unix $out_dir/$1.err $out_dir/$1.out - if [ -f $cmp_dir/$1.out.expected ] && [ "$(md5sum $out_dir/$1.out | cut -d' ' -f1)" != "$(md5sum $cmp_dir/$1.out.expected | cut -d' ' -f1)" ]; then - diff $out_dir/$1.out $cmp_dir/$1.out.expected - exit 255 + if ! diff --strip-trailing-cr $out_dir/$1.out $cmp_dir/$1.out.expected ; then + exit 255 + fi fi if [ -f $cmp_dir/$1.err.expected ] && [ "$(md5sum $out_dir/$1.err | cut -d' ' -f1)" != "$(md5sum $cmp_dir/$1.err.expected | cut -d' ' -f1)" ]; then - diff $out_dir/$1.err $cmp_dir/$1.err.expected - exit 255 + if ! diff --strip-trailing-cr $out_dir/$1.err $cmp_dir/$1.err.expected ; then + exit 255 + fi fi From edc72c95547570f2c0f27cfbe3e4e4368199b582 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Mon, 16 Nov 2015 18:15:34 +0100 Subject: [PATCH 147/211] Removed math.h dependency on base assertions --- include/criterion/assert.h | 179 +-------------- include/criterion/assert_base.h | 373 ++++++++++++++++++++++++++++++++ src/core/wrappers/wrap.cc | 2 +- 3 files changed, 375 insertions(+), 179 deletions(-) create mode 100644 include/criterion/assert_base.h diff --git a/include/criterion/assert.h b/include/criterion/assert.h index 444d6a12..41da0aef 100644 --- a/include/criterion/assert.h +++ b/include/criterion/assert.h @@ -24,188 +24,11 @@ #ifndef CRITERION_ASSERT_H_ # define CRITERION_ASSERT_H_ -# include "preprocess.h" -# include "asprintf-compat.h" - # ifdef __cplusplus -# include -# include # include -# else -# include -# include -# include -# endif -# include "designated-initializer-compat.h" -# include "types.h" -# include "stats.h" -# include "hooks.h" -# include "event.h" -# include "abort.h" - -struct criterion_assert_args { - const char *msg; - int sentinel_; - -#ifdef __cplusplus - constexpr criterion_assert_args(const char *msg) : msg(msg), sentinel_(0) {} - constexpr criterion_assert_args(const char *msg, int sentinel_) : msg(msg), sentinel_(sentinel_) {} -#endif -}; - -// Do NOT reorder unless you want to break the ABI -enum criterion_assert_messages { - CRITERION_ASSERT_MSG_FAIL, - CRITERION_ASSERT_MSG_EXPR_FALSE, - CRITERION_ASSERT_MSG_EXPR_AS_STRINGS_FALSE, - CRITERION_ASSERT_MSG_IS_NULL, - CRITERION_ASSERT_MSG_IS_NOT_NULL, - CRITERION_ASSERT_MSG_IS_EMPTY, - CRITERION_ASSERT_MSG_IS_NOT_EMPTY, - CRITERION_ASSERT_MSG_FILE_STR_MATCH, - CRITERION_ASSERT_MSG_FILE_MATCH, - CRITERION_ASSERT_MSG_THROW, - CRITERION_ASSERT_MSG_NO_THROW, - CRITERION_ASSERT_MSG_ANY_THROW, - CRITERION_ASSERT_MSG_NONE_THROW, -}; - -CR_BEGIN_C_API - -CR_API char *cr_translate_assert_msg(int msg_index, ...); - -CR_END_C_API - -# define CR_GET_CONDITION(Condition, ...) Condition -# define CR_GET_CONDITION_STR(Condition, ...) #Condition -# define CR_VA_SKIP(_, ...) __VA_ARGS__ - -# ifdef __cplusplus -# define CR_STDN std:: -# else -# define CR_STDN # endif -# define CR_TRANSLATE_DEF_MSG__(Arg) \ - CR_IDENTITY Arg - -# define CR_TRANSLATE_DEF_MSG_(...) \ - CR_EXPAND(cr_translate_assert_msg( \ - CR_VA_HEAD(__VA_ARGS__), \ - "" CR_TRANSLATE_DEF_MSG__(CR_VA_HEAD(CR_VA_TAIL(__VA_ARGS__))) \ - )) - -# define CR_INIT_STATS_(BufSize, MsgVar, ...) CR_EXPAND( \ - do { \ - char *def_msg = CR_EXPAND(CR_TRANSLATE_DEF_MSG_(__VA_ARGS__)); \ - char *formatted_msg = NULL; \ - int msglen = cr_asprintf(&formatted_msg, \ - "" CR_VA_TAIL(CR_VA_TAIL(__VA_ARGS__))); \ - if (formatted_msg && *formatted_msg) { \ - MsgVar = formatted_msg; \ - CR_STDN free(def_msg); \ - } else { \ - MsgVar = def_msg; \ - msglen = strlen(def_msg); \ - CR_STDN free(formatted_msg); \ - } \ - \ - BufSize = sizeof(struct criterion_assert_stats) \ - + sizeof (size_t) + msglen + 1; \ - \ - char *buf = (char*) CR_STDN malloc(BufSize); \ - stat = (struct criterion_assert_stats*) buf; \ - CR_STDN memset(buf, 0, sizeof (struct criterion_assert_stats)); \ - buf += sizeof (struct criterion_assert_stats); \ - *((size_t*) buf) = msglen + 1; \ - buf += sizeof (size_t); \ - CR_STDN strcpy(buf, MsgVar); \ - CR_STDN free(MsgVar); \ - } while (0)) - -# define CR_FAIL_ABORT_ criterion_abort_test -# define CR_FAIL_CONTINUES_ criterion_continue_test - -# ifdef __GNUC__ -// We disable the format-zero-length warning because we use the validity of -// asprintf(out, "") for empty assertion messages -# pragma GCC diagnostic ignored "-Wformat-zero-length" -# endif - -# define cr_assert_impl(Fail, Condition, ...) \ - do { \ - bool passed = !!(Condition); \ - \ - char *msg = NULL; \ - size_t bufsize; \ - \ - struct criterion_assert_stats *stat; \ - CR_EXPAND(CR_INIT_STATS_(bufsize, msg, CR_VA_TAIL(__VA_ARGS__))); \ - stat->passed = passed; \ - stat->file = __FILE__; \ - stat->line = __LINE__; \ - \ - criterion_send_event(ASSERT, stat, bufsize); \ - CR_STDN free(stat); \ - \ - if (!passed) \ - Fail(); \ - } while (0) - -// Base assertions - -# define cr_fail(Fail, ...) \ - CR_EXPAND(cr_assert_impl( \ - Fail, \ - 0, \ - dummy, \ - CRITERION_ASSERT_MSG_FAIL, \ - (), \ - __VA_ARGS__ \ - )) - -# define cr_assert_fail(...) CR_EXPAND(cr_fail(CR_FAIL_ABORT_, __VA_ARGS__)) -# define cr_expect_fail(...) CR_EXPAND(cr_fail(CR_FAIL_CONTINUES_, __VA_ARGS__)) - -# define cr_assert(...) \ - CR_EXPAND(cr_assert_impl( \ - CR_FAIL_ABORT_, \ - CR_VA_HEAD(__VA_ARGS__), \ - dummy, \ - CRITERION_ASSERT_MSG_EXPR_FALSE, \ - (CR_STR(CR_VA_HEAD(__VA_ARGS__))), \ - CR_VA_TAIL(__VA_ARGS__) \ - )) - -# define cr_expect(...) \ - CR_EXPAND(cr_assert_impl( \ - CR_FAIL_CONTINUES_, \ - CR_VA_HEAD(__VA_ARGS__), \ - dummy, \ - CRITERION_ASSERT_MSG_EXPR_FALSE, \ - (CR_STR(CR_VA_HEAD(__VA_ARGS__))), \ - CR_VA_TAIL(__VA_ARGS__) \ - )) - -# define cr_assert_not(...) \ - CR_EXPAND(cr_assert_impl( \ - CR_FAIL_ABORT_, \ - !(CR_VA_HEAD(__VA_ARGS__)), \ - dummy, \ - CRITERION_ASSERT_MSG_EXPR_FALSE, \ - (CR_STR(!(CR_VA_HEAD(__VA_ARGS__)))), \ - CR_VA_TAIL(__VA_ARGS__) \ - )) - -# define cr_expect_not(...) \ - CR_EXPAND(cr_assert_impl( \ - CR_FAIL_CONTINUES_, \ - !(CR_VA_HEAD(__VA_ARGS__)), \ - dummy, \ - CRITERION_ASSERT_MSG_EXPR_FALSE, \ - (CR_STR(!(CR_VA_HEAD(__VA_ARGS__)))), \ - CR_VA_TAIL(__VA_ARGS__) \ - )) +# include "assert_base.h" // Common binary assertions diff --git a/include/criterion/assert_base.h b/include/criterion/assert_base.h new file mode 100644 index 00000000..3caa62a2 --- /dev/null +++ b/include/criterion/assert_base.h @@ -0,0 +1,373 @@ +/* + * The MIT License (MIT) + * + * Copyright © 2015 Franklin "Snaipe" Mathieu + * + * 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 CRITERION_ASSERT_BASE_H_ +# define CRITERION_ASSERT_BASE_H_ + +# include "preprocess.h" +# include "asprintf-compat.h" + +# ifdef __cplusplus +# include +# include +# else +# include +# include +# include +# endif +# include "designated-initializer-compat.h" +# include "types.h" +# include "stats.h" +# include "hooks.h" +# include "event.h" +# include "abort.h" + +struct criterion_assert_args { + const char *msg; + int sentinel_; + +#ifdef __cplusplus + constexpr criterion_assert_args(const char *msg) : msg(msg), sentinel_(0) {} + constexpr criterion_assert_args(const char *msg, int sentinel_) : msg(msg), sentinel_(sentinel_) {} +#endif +}; + +// Do NOT reorder unless you want to break the ABI +enum criterion_assert_messages { + CRITERION_ASSERT_MSG_FAIL, + CRITERION_ASSERT_MSG_EXPR_FALSE, + CRITERION_ASSERT_MSG_EXPR_AS_STRINGS_FALSE, + CRITERION_ASSERT_MSG_IS_NULL, + CRITERION_ASSERT_MSG_IS_NOT_NULL, + CRITERION_ASSERT_MSG_IS_EMPTY, + CRITERION_ASSERT_MSG_IS_NOT_EMPTY, + CRITERION_ASSERT_MSG_FILE_STR_MATCH, + CRITERION_ASSERT_MSG_FILE_MATCH, + CRITERION_ASSERT_MSG_THROW, + CRITERION_ASSERT_MSG_NO_THROW, + CRITERION_ASSERT_MSG_ANY_THROW, + CRITERION_ASSERT_MSG_NONE_THROW, +}; + +CR_BEGIN_C_API + +CR_API char *cr_translate_assert_msg(int msg_index, ...); + +CR_END_C_API + +# define CR_GET_CONDITION(Condition, ...) Condition +# define CR_GET_CONDITION_STR(Condition, ...) #Condition +# define CR_VA_SKIP(_, ...) __VA_ARGS__ + +# ifdef __cplusplus +# define CR_STDN std:: +# else +# define CR_STDN +# endif + +# define CR_TRANSLATE_DEF_MSG__(Arg) \ + CR_IDENTITY Arg + +# define CR_TRANSLATE_DEF_MSG_(...) \ + CR_EXPAND(cr_translate_assert_msg( \ + CR_VA_HEAD(__VA_ARGS__), \ + "" CR_TRANSLATE_DEF_MSG__(CR_VA_HEAD(CR_VA_TAIL(__VA_ARGS__))) \ + )) + +# define CR_INIT_STATS_(BufSize, MsgVar, ...) CR_EXPAND( \ + do { \ + char *def_msg = CR_EXPAND(CR_TRANSLATE_DEF_MSG_(__VA_ARGS__)); \ + char *formatted_msg = NULL; \ + int msglen = cr_asprintf(&formatted_msg, \ + "" CR_VA_TAIL(CR_VA_TAIL(__VA_ARGS__))); \ + if (formatted_msg && *formatted_msg) { \ + MsgVar = formatted_msg; \ + CR_STDN free(def_msg); \ + } else { \ + MsgVar = def_msg; \ + msglen = strlen(def_msg); \ + CR_STDN free(formatted_msg); \ + } \ + \ + BufSize = sizeof(struct criterion_assert_stats) \ + + sizeof (size_t) + msglen + 1; \ + \ + char *buf = (char*) CR_STDN malloc(BufSize); \ + stat = (struct criterion_assert_stats*) buf; \ + CR_STDN memset(buf, 0, sizeof (struct criterion_assert_stats)); \ + buf += sizeof (struct criterion_assert_stats); \ + *((size_t*) buf) = msglen + 1; \ + buf += sizeof (size_t); \ + CR_STDN strcpy(buf, MsgVar); \ + CR_STDN free(MsgVar); \ + } while (0)) + +# define CR_FAIL_ABORT_ criterion_abort_test +# define CR_FAIL_CONTINUES_ criterion_continue_test + +# ifdef __GNUC__ +// We disable the format-zero-length warning because we use the validity of +// asprintf(out, "") for empty assertion messages +# pragma GCC diagnostic ignored "-Wformat-zero-length" +# endif + +# define cr_assert_impl(Fail, Condition, ...) \ + do { \ + bool passed = !!(Condition); \ + \ + char *msg = NULL; \ + size_t bufsize; \ + \ + struct criterion_assert_stats *stat; \ + CR_EXPAND(CR_INIT_STATS_(bufsize, msg, CR_VA_TAIL(__VA_ARGS__))); \ + stat->passed = passed; \ + stat->file = __FILE__; \ + stat->line = __LINE__; \ + \ + criterion_send_event(ASSERT, stat, bufsize); \ + CR_STDN free(stat); \ + \ + if (!passed) \ + Fail(); \ + } while (0) + +// Base assertions + +# define cr_fail(Fail, ...) \ + CR_EXPAND(cr_assert_impl( \ + Fail, \ + 0, \ + dummy, \ + CRITERION_ASSERT_MSG_FAIL, \ + (), \ + __VA_ARGS__ \ + )) + +# define cr_assert_fail(...) CR_EXPAND(cr_fail(CR_FAIL_ABORT_, __VA_ARGS__)) +# define cr_expect_fail(...) CR_EXPAND(cr_fail(CR_FAIL_CONTINUES_, __VA_ARGS__)) + +# define cr_assert(...) \ + CR_EXPAND(cr_assert_impl( \ + CR_FAIL_ABORT_, \ + CR_VA_HEAD(__VA_ARGS__), \ + dummy, \ + CRITERION_ASSERT_MSG_EXPR_FALSE, \ + (CR_STR(CR_VA_HEAD(__VA_ARGS__))), \ + CR_VA_TAIL(__VA_ARGS__) \ + )) + +# define cr_expect(...) \ + CR_EXPAND(cr_assert_impl( \ + CR_FAIL_CONTINUES_, \ + CR_VA_HEAD(__VA_ARGS__), \ + dummy, \ + CRITERION_ASSERT_MSG_EXPR_FALSE, \ + (CR_STR(CR_VA_HEAD(__VA_ARGS__))), \ + CR_VA_TAIL(__VA_ARGS__) \ + )) + +# define cr_assert_not(...) \ + CR_EXPAND(cr_assert_impl( \ + CR_FAIL_ABORT_, \ + !(CR_VA_HEAD(__VA_ARGS__)), \ + dummy, \ + CRITERION_ASSERT_MSG_EXPR_FALSE, \ + (CR_STR(!(CR_VA_HEAD(__VA_ARGS__)))), \ + CR_VA_TAIL(__VA_ARGS__) \ + )) + +# define cr_expect_not(...) \ + CR_EXPAND(cr_assert_impl( \ + CR_FAIL_CONTINUES_, \ + !(CR_VA_HEAD(__VA_ARGS__)), \ + dummy, \ + CRITERION_ASSERT_MSG_EXPR_FALSE, \ + (CR_STR(!(CR_VA_HEAD(__VA_ARGS__)))), \ + CR_VA_TAIL(__VA_ARGS__) \ + )) + +// Common binary assertions + +# define cr_assert_op_(Fail, Op, Actual, Expected, ...) \ + CR_EXPAND(cr_assert_impl( \ + Fail, \ + (Actual) Op (Expected), \ + dummy, \ + CRITERION_ASSERT_MSG_EXPR_FALSE, \ + (CR_STR((Actual) Op (Expected))), \ + __VA_ARGS__ \ + )) + +# define cr_assert_op_va_(Fail, Op, ...) \ + CR_EXPAND(cr_assert_op_( \ + Fail, \ + Op, \ + CR_VA_HEAD(__VA_ARGS__), \ + CR_VA_HEAD(CR_VA_TAIL(__VA_ARGS__)), \ + CR_VA_TAIL(CR_VA_TAIL(__VA_ARGS__)) \ + )) + +# define cr_assert_eq(...) CR_EXPAND(cr_assert_op_va_(CR_FAIL_ABORT_, ==, __VA_ARGS__)) +# define cr_expect_eq(...) CR_EXPAND(cr_assert_op_va_(CR_FAIL_CONTINUES_, ==, __VA_ARGS__)) + +# define cr_assert_neq(...) CR_EXPAND(cr_assert_op_va_(CR_FAIL_ABORT_, !=, __VA_ARGS__)) +# define cr_expect_neq(...) CR_EXPAND(cr_assert_op_va_(CR_FAIL_CONTINUES_, !=, __VA_ARGS__)) + +# define cr_assert_lt(...) CR_EXPAND(cr_assert_op_va_(CR_FAIL_ABORT_, <, __VA_ARGS__)) +# define cr_expect_lt(...) CR_EXPAND(cr_assert_op_va_(CR_FAIL_CONTINUES_, <, __VA_ARGS__)) + +# define cr_assert_leq(...) CR_EXPAND(cr_assert_op_va_(CR_FAIL_ABORT_, <=, __VA_ARGS__)) +# define cr_expect_leq(...) CR_EXPAND(cr_assert_op_va_(CR_FAIL_CONTINUES_, <=, __VA_ARGS__)) + +# define cr_assert_gt(...) CR_EXPAND(cr_assert_op_va_(CR_FAIL_ABORT_, >, __VA_ARGS__)) +# define cr_expect_gt(...) CR_EXPAND(cr_assert_op_va_(CR_FAIL_CONTINUES_, >, __VA_ARGS__)) + +# define cr_assert_geq(...) CR_EXPAND(cr_assert_op_va_(CR_FAIL_ABORT_, >=, __VA_ARGS__)) +# define cr_expect_geq(...) CR_EXPAND(cr_assert_op_va_(CR_FAIL_CONTINUES_, >=, __VA_ARGS__)) + +// Common unary assertions + +# define cr_assert_null_op_(Fail, Op, Msg, Value, ...) \ + CR_EXPAND(cr_assert_impl( \ + Fail, \ + (Value) Op NULL, \ + dummy, \ + Msg, \ + (CR_STR(Value)), \ + __VA_ARGS__ \ + )) + +# define cr_assert_null_op_va_(Fail, Op, Msg, ...) \ + CR_EXPAND(cr_assert_null_op_( \ + Fail, \ + Op, \ + Msg, \ + CR_VA_HEAD(__VA_ARGS__), \ + CR_VA_TAIL(__VA_ARGS__) \ + )) + +# define cr_assert_null(...) CR_EXPAND(cr_assert_null_op_va_(CR_FAIL_ABORT_, ==, CRITERION_ASSERT_MSG_IS_NOT_NULL, __VA_ARGS__)) +# define cr_expect_null(...) CR_EXPAND(cr_assert_null_op_va_(CR_FAIL_CONTINUES_, ==, CRITERION_ASSERT_MSG_IS_NOT_NULL, __VA_ARGS__)) + +# define cr_assert_not_null(...) CR_EXPAND(cr_assert_null_op_va_(CR_FAIL_ABORT_, !=, CRITERION_ASSERT_MSG_IS_NULL, __VA_ARGS__)) +# define cr_expect_not_null(...) CR_EXPAND(cr_assert_null_op_va_(CR_FAIL_CONTINUES_, !=, CRITERION_ASSERT_MSG_IS_NULL, __VA_ARGS__)) + +// Floating-point assertions + +# define cr_assert_float_eq_op_(Actual, Expected, Epsilon) \ + (Expected) - (Actual) <= (Epsilon) && (Actual) - (Expected) <= (Epsilon) + +# define cr_assert_float_neq_op_(Actual, Expected, Epsilon) \ + (Expected) - (Actual) > (Epsilon) || (Actual) - (Expected) > (Epsilon) + +# define cr_assert_float_op_(Fail, Op, Actual, Expected, Epsilon, ...) \ + CR_EXPAND(cr_assert_impl( \ + Fail, \ + Op(Actual, Expected, Epsilon), \ + dummy, \ + CRITERION_ASSERT_MSG_EXPR_FALSE, \ + (CR_STR(Op(Actual, Expected, Epsilon))), \ + __VA_ARGS__ \ + )) + +# define cr_assert_float_op_va_(Fail, Op, ...) \ + CR_EXPAND(cr_assert_float_op_( \ + Fail, \ + Op, \ + CR_VA_HEAD(__VA_ARGS__), \ + CR_VA_HEAD(CR_VA_TAIL(__VA_ARGS__)), \ + CR_VA_HEAD(CR_VA_TAIL(CR_VA_TAIL(__VA_ARGS__))), \ + CR_VA_TAIL(CR_VA_TAIL(CR_VA_TAIL(__VA_ARGS__))) \ + )) + +# define cr_assert_float_eq(...) CR_EXPAND(cr_assert_float_op_va_(CR_FAIL_ABORT_, cr_assert_float_eq_op_, __VA_ARGS__)) +# define cr_expect_float_eq(...) CR_EXPAND(cr_assert_float_op_va_(CR_FAIL_CONTINUES_, cr_assert_float_eq_op_, __VA_ARGS__)) + +# define cr_assert_float_neq(...) CR_EXPAND(cr_assert_float_op_va_(CR_FAIL_ABORT_, cr_assert_float_neq_op_, __VA_ARGS__)) +# define cr_expect_float_neq(...) CR_EXPAND(cr_assert_float_op_va_(CR_FAIL_CONTINUES_, cr_assert_float_neq_op_, __VA_ARGS__)) + +// String assertions + +# define cr_assert_str_op_empty_(Fail, Op, Msg, Value, ...) \ + CR_EXPAND(cr_assert_impl( \ + Fail, \ + (Value)[0] Op '\0', \ + dummy, \ + Msg, \ + (CR_STR(Value)), \ + __VA_ARGS__ \ + )) + +# define cr_assert_str_op_empty_va_(Fail, Op, Msg, ...) \ + CR_EXPAND(cr_assert_str_op_empty_( \ + Fail, \ + Op, \ + Msg, \ + CR_VA_HEAD(__VA_ARGS__), \ + CR_VA_TAIL(__VA_ARGS__) \ + )) + +# define cr_assert_str_empty(...) CR_EXPAND(cr_assert_str_op_empty_va_(CR_FAIL_ABORT_, ==, CRITERION_ASSERT_MSG_IS_NOT_EMPTY, __VA_ARGS__)) +# define cr_expect_str_empty(...) CR_EXPAND(cr_assert_str_op_empty_va_(CR_FAIL_CONTINUES_, ==, CRITERION_ASSERT_MSG_IS_NOT_EMPTY, __VA_ARGS__)) + +# define cr_assert_str_not_empty(...) CR_EXPAND(cr_assert_str_op_empty_va_(CR_FAIL_ABORT_, !=, CRITERION_ASSERT_MSG_IS_EMPTY, __VA_ARGS__)) +# define cr_expect_str_not_empty(...) CR_EXPAND(cr_assert_str_op_empty_va_(CR_FAIL_CONTINUES_, !=, CRITERION_ASSERT_MSG_IS_EMPTY, __VA_ARGS__)) + +# define cr_assert_str_op_(Fail, Op, Actual, Expected, ...) \ + CR_EXPAND(cr_assert_impl( \ + Fail, \ + CR_STDN strcmp((Actual), (Expected)) Op 0, \ + dummy, \ + CRITERION_ASSERT_MSG_EXPR_AS_STRINGS_FALSE, \ + (CR_STR((Actual) Op (Expected))), \ + __VA_ARGS__ \ + )) + +# define cr_assert_str_op_va_(Fail, Op, ...) \ + CR_EXPAND(cr_assert_str_op_( \ + Fail, \ + Op, \ + CR_VA_HEAD(__VA_ARGS__), \ + CR_VA_HEAD(CR_VA_TAIL(__VA_ARGS__)), \ + CR_VA_TAIL(CR_VA_TAIL(__VA_ARGS__)) \ + )) + +# define cr_assert_str_eq(...) CR_EXPAND(cr_assert_str_op_va_(CR_FAIL_ABORT_, ==, __VA_ARGS__)) +# define cr_expect_str_eq(...) CR_EXPAND(cr_assert_str_op_va_(CR_FAIL_CONTINUES_, ==, __VA_ARGS__)) + +# define cr_assert_str_neq(...) CR_EXPAND(cr_assert_str_op_va_(CR_FAIL_ABORT_, !=, __VA_ARGS__)) +# define cr_expect_str_neq(...) CR_EXPAND(cr_assert_str_op_va_(CR_FAIL_CONTINUES_, !=, __VA_ARGS__)) + +# define cr_assert_str_lt(...) CR_EXPAND(cr_assert_str_op_va_(CR_FAIL_ABORT_, <, __VA_ARGS__)) +# define cr_expect_str_lt(...) CR_EXPAND(cr_assert_str_op_va_(CR_FAIL_CONTINUES_, <, __VA_ARGS__)) + +# define cr_assert_str_leq(...) CR_EXPAND(cr_assert_str_op_va_(CR_FAIL_ABORT_, <=, __VA_ARGS__)) +# define cr_expect_str_leq(...) CR_EXPAND(cr_assert_str_op_va_(CR_FAIL_CONTINUES_, <=, __VA_ARGS__)) + +# define cr_assert_str_gt(...) CR_EXPAND(cr_assert_str_op_va_(CR_FAIL_ABORT_, >, __VA_ARGS__)) +# define cr_expect_str_gt(...) CR_EXPAND(cr_assert_str_op_va_(CR_FAIL_CONTINUES_, >, __VA_ARGS__)) + +# define cr_assert_str_geq(...) CR_EXPAND(cr_assert_str_op_va_(CR_FAIL_ABORT_, >=, __VA_ARGS__)) +# define cr_expect_str_geq(...) CR_EXPAND(cr_assert_str_op_va_(CR_FAIL_CONTINUES_, >=, __VA_ARGS__)) + +#endif /* !CRITERION_ASSERT_BASE_H_ */ diff --git a/src/core/wrappers/wrap.cc b/src/core/wrappers/wrap.cc index 67eeb93f..cae21933 100644 --- a/src/core/wrappers/wrap.cc +++ b/src/core/wrappers/wrap.cc @@ -22,7 +22,7 @@ * THE SOFTWARE. */ #include -#include "criterion/assert.h" +#include "criterion/assert_base.h" #include "criterion/event.h" extern "C" { From 62b4f2171b51fc4de2f1b9b10a6d33978755b9cc Mon Sep 17 00:00:00 2001 From: Snaipe Date: Mon, 16 Nov 2015 18:35:16 +0100 Subject: [PATCH 148/211] Fixed failing Appveyor MinGW builds due to '_hypot' not being defined. This is caused by a MinGW bug in math.h. See http://ehc.ac/p/mingw/bugs/2250/ for more information. --- CMakeLists.txt | 3 +++ appveyor.yml | 1 + samples/CMakeLists.txt | 4 ++-- test/CMakeLists.txt | 4 ++-- 4 files changed, 8 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 96e093c5..8749ac05 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -40,6 +40,9 @@ set(GettextTranslate_GMO_BINARY 1) add_definitions(-DCRITERION_BUILDING_DLL=1) +set(CMAKE_C_FLAGS_DEFAULT "${CMAKE_C_FLAGS}") +set(CMAKE_CXX_FLAGS_DEFAULT "${CMAKE_CXX_FLAGS}") + if (NOT MSVC) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Werror -g -std=gnu99") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Werror -g -std=c++11") diff --git a/appveyor.yml b/appveyor.yml index 22a8ea99..ba0e7da0 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -15,6 +15,7 @@ environment: matrix: - COMPILER: mingw GENERATOR: "MSYS Makefiles" + CXXFLAGS: -D__NO_INLINE__ - COMPILER: msvc GENERATOR: "Visual Studio 14 2015" CFLAGS: /MP diff --git a/samples/CMakeLists.txt b/samples/CMakeLists.txt index 867cc947..cc3f9ac3 100644 --- a/samples/CMakeLists.txt +++ b/samples/CMakeLists.txt @@ -1,6 +1,6 @@ if (NOT MSVC) - set(CMAKE_C_FLAGS "-std=c99 -Wall -Wextra -pedantic") - set(CMAKE_CXX_FLAGS "-std=c++11 -Wall -Wextra -pedantic") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS_DEFAULT} -std=c99 -Wall -Wextra -pedantic") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS_DEFAULT} -std=c++11 -Wall -Wextra -pedantic") endif () include_directories(../include) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index da638527..4b57f05d 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -1,6 +1,6 @@ if (NOT MSVC) - set(CMAKE_C_FLAGS "-std=gnu99 -Wall -Wextra") - set(CMAKE_CXX_FLAGS "-std=c++11 -Wall -Wextra") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS_DEFAULT} -std=gnu99 -Wall -Wextra") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS_DEFAULT} -std=c++11 -Wall -Wextra") endif () include_directories(../include ../src) From 6917eb4bdac01e65a67a85611cde603eec286e04 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Mon, 16 Nov 2015 20:41:32 +0100 Subject: [PATCH 149/211] [Issue #74] Added __clang__ checks on assert.h __GNUC__ ifdefs for better source searching --- include/criterion/assert.h | 2 +- include/criterion/assert_base.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/criterion/assert.h b/include/criterion/assert.h index 41da0aef..19593108 100644 --- a/include/criterion/assert.h +++ b/include/criterion/assert.h @@ -224,7 +224,7 @@ // Safe array comparison assertions -# if defined(__GNUC__) || defined(__cplusplus) +# if defined(__GNUC__) || defined(__clang__) || defined(__cplusplus) # ifdef __cplusplus # define CR_ARR_COMPARE_(A, B, Size, Cmp, Result) \ diff --git a/include/criterion/assert_base.h b/include/criterion/assert_base.h index 3caa62a2..e3905188 100644 --- a/include/criterion/assert_base.h +++ b/include/criterion/assert_base.h @@ -125,7 +125,7 @@ CR_END_C_API # define CR_FAIL_ABORT_ criterion_abort_test # define CR_FAIL_CONTINUES_ criterion_continue_test -# ifdef __GNUC__ +# if defined(__GNUC__) || defined(__clang__) // We disable the format-zero-length warning because we use the validity of // asprintf(out, "") for empty assertion messages # pragma GCC diagnostic ignored "-Wformat-zero-length" From 7a6bddd63ccec653d1da7c5137249093309a90b7 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Tue, 17 Nov 2015 16:12:16 +0100 Subject: [PATCH 150/211] Removed unimplemented theory functions --- include/criterion/theories.h | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/include/criterion/theories.h b/include/criterion/theories.h index 5a1227e7..1868441d 100644 --- a/include/criterion/theories.h +++ b/include/criterion/theories.h @@ -42,17 +42,6 @@ constexpr size_t criterion_va_num__(const T &...) { CR_BEGIN_C_API -struct criterion_theory_context; - -CR_API struct criterion_theory_context* cr_theory_init(void); -CR_API void cr_theory_push_arg(struct criterion_theory_context *ctx, bool is_float, size_t size, void *ptr); -CR_API void cr_theory_free(struct criterion_theory_context *ctx); -CR_API void cr_theory_abort(void); -CR_API int cr_theory_mark(void); - -CR_API void cr_theory_reset(struct criterion_theory_context *ctx); -CR_API void cr_theory_call(struct criterion_theory_context *ctx, void (*fnptr)(void)); - # define TheoryDataPoints(Category, Name) \ static struct criterion_datapoints CR_IDENTIFIER_(Category, Name, dps)[] From 3eea22fcdae1680849d50112312a936a8757c5be Mon Sep 17 00:00:00 2001 From: Snaipe Date: Tue, 17 Nov 2015 16:14:30 +0100 Subject: [PATCH 151/211] Reverted removal of cr_theory_abort() --- include/criterion/theories.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/criterion/theories.h b/include/criterion/theories.h index 1868441d..3777ef7b 100644 --- a/include/criterion/theories.h +++ b/include/criterion/theories.h @@ -42,6 +42,8 @@ constexpr size_t criterion_va_num__(const T &...) { CR_BEGIN_C_API +CR_API void cr_theory_abort(void); + # define TheoryDataPoints(Category, Name) \ static struct criterion_datapoints CR_IDENTIFIER_(Category, Name, dps)[] From 7fa0b6580b25a8f3623424b2b07663cda51f4ff6 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Tue, 17 Nov 2015 16:30:00 +0100 Subject: [PATCH 152/211] Refactored internal headers into its own subdirectory --- CMakeLists.txt | 10 +++++----- dependencies/valgrind/include/valgrind/valgrind.h | 2 +- include/criterion/abort.h | 2 +- include/criterion/alloc.h | 2 +- include/criterion/assert_base.h | 6 +++--- include/criterion/criterion.h | 4 ++-- include/criterion/event.h | 2 +- include/criterion/hooks.h | 2 +- include/criterion/{ => internal}/asprintf-compat.h | 0 include/criterion/{ => internal}/common.h | 0 .../{ => internal}/designated-initializer-compat.h | 0 include/criterion/{ => internal}/ordered-set.h | 2 +- include/criterion/{ => internal}/preprocess.h | 0 include/criterion/logging.h | 4 ++-- include/criterion/redirect.h | 2 +- include/criterion/types.h | 2 +- src/compat/section.h | 2 +- src/compat/time.c | 2 +- src/core/abort.c | 2 +- src/core/ordered-set.c | 4 ++-- src/core/report.c | 2 +- src/core/runner.c | 4 ++-- src/core/stats.c | 2 +- src/entry/main.c | 2 +- src/io/asprintf.c | 2 +- src/io/event.c | 2 +- src/io/json.c | 2 +- src/io/xml.c | 2 +- src/log/normal.c | 2 +- src/string/extmatch.c | 2 +- src/string/i18n.c | 2 +- test/asprintf.c | 2 +- test/ordered-set.c | 2 +- 33 files changed, 39 insertions(+), 39 deletions(-) rename include/criterion/{ => internal}/asprintf-compat.h (100%) rename include/criterion/{ => internal}/common.h (100%) rename include/criterion/{ => internal}/designated-initializer-compat.h (100%) rename include/criterion/{ => internal}/ordered-set.h (98%) rename include/criterion/{ => internal}/preprocess.h (100%) diff --git a/CMakeLists.txt b/CMakeLists.txt index a1800828..3890768d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -192,23 +192,23 @@ endif () set(INTERFACE_FILES include/criterion/assert.h include/criterion/abort.h - include/criterion/common.h include/criterion/criterion.h include/criterion/event.h include/criterion/hooks.h include/criterion/logging.h include/criterion/types.h include/criterion/options.h - include/criterion/ordered-set.h include/criterion/stats.h include/criterion/theories.h - include/criterion/asprintf-compat.h - include/criterion/designated-initializer-compat.h - include/criterion/preprocess.h include/criterion/alloc.h include/criterion/parameterized.h include/criterion/redirect.h include/criterion/output.h + include/criterion/internal/common.h + include/criterion/internal/ordered-set.h + include/criterion/internal/asprintf-compat.h + include/criterion/internal/designated-initializer-compat.h + include/criterion/internal/preprocess.h ) # Generate the configure file diff --git a/dependencies/valgrind/include/valgrind/valgrind.h b/dependencies/valgrind/include/valgrind/valgrind.h index 9cfb7003..04c73ec8 100644 --- a/dependencies/valgrind/include/valgrind/valgrind.h +++ b/dependencies/valgrind/include/valgrind/valgrind.h @@ -93,7 +93,7 @@ #include -#include +#include /* Nb: this file might be included in a file compiled with -ansi. So we can't use C++ style "//" comments nor the "asm" keyword (instead diff --git a/include/criterion/abort.h b/include/criterion/abort.h index 449c0de4..d6a649e6 100644 --- a/include/criterion/abort.h +++ b/include/criterion/abort.h @@ -24,7 +24,7 @@ #ifndef CRITERION_ABORT_H_ # define CRITERION_ABORT_H_ -# include "common.h" +# include "internal/common.h" CR_BEGIN_C_API diff --git a/include/criterion/alloc.h b/include/criterion/alloc.h index eb687946..71d4ca77 100644 --- a/include/criterion/alloc.h +++ b/include/criterion/alloc.h @@ -31,7 +31,7 @@ using std::size_t; # else # include # endif -# include "common.h" +# include "internal/common.h" CR_BEGIN_C_API diff --git a/include/criterion/assert_base.h b/include/criterion/assert_base.h index e3905188..f5395989 100644 --- a/include/criterion/assert_base.h +++ b/include/criterion/assert_base.h @@ -24,8 +24,8 @@ #ifndef CRITERION_ASSERT_BASE_H_ # define CRITERION_ASSERT_BASE_H_ -# include "preprocess.h" -# include "asprintf-compat.h" +# include "internal/preprocess.h" +# include "internal/asprintf-compat.h" # ifdef __cplusplus # include @@ -35,7 +35,7 @@ # include # include # endif -# include "designated-initializer-compat.h" +# include "internal/designated-initializer-compat.h" # include "types.h" # include "stats.h" # include "hooks.h" diff --git a/include/criterion/criterion.h b/include/criterion/criterion.h index a2f4ae2b..9549223b 100644 --- a/include/criterion/criterion.h +++ b/include/criterion/criterion.h @@ -24,8 +24,8 @@ #ifndef CRITERION_H_ # define CRITERION_H_ -# include "designated-initializer-compat.h" -# include "common.h" +# include "internal/designated-initializer-compat.h" +# include "internal/common.h" # include "types.h" # include "assert.h" # include "alloc.h" diff --git a/include/criterion/event.h b/include/criterion/event.h index 6ccc649d..6d2d3a01 100644 --- a/include/criterion/event.h +++ b/include/criterion/event.h @@ -29,7 +29,7 @@ # else # include # endif -# include "common.h" +# include "internal/common.h" CR_BEGIN_C_API diff --git a/include/criterion/hooks.h b/include/criterion/hooks.h index 497b0476..5f622b2a 100644 --- a/include/criterion/hooks.h +++ b/include/criterion/hooks.h @@ -24,7 +24,7 @@ #ifndef CRITERION_HOOKS_H_ # define CRITERION_HOOKS_H_ -# include "common.h" +# include "internal/common.h" # include "types.h" typedef enum { diff --git a/include/criterion/asprintf-compat.h b/include/criterion/internal/asprintf-compat.h similarity index 100% rename from include/criterion/asprintf-compat.h rename to include/criterion/internal/asprintf-compat.h diff --git a/include/criterion/common.h b/include/criterion/internal/common.h similarity index 100% rename from include/criterion/common.h rename to include/criterion/internal/common.h diff --git a/include/criterion/designated-initializer-compat.h b/include/criterion/internal/designated-initializer-compat.h similarity index 100% rename from include/criterion/designated-initializer-compat.h rename to include/criterion/internal/designated-initializer-compat.h diff --git a/include/criterion/ordered-set.h b/include/criterion/internal/ordered-set.h similarity index 98% rename from include/criterion/ordered-set.h rename to include/criterion/internal/ordered-set.h index 07c5148f..aa93cc15 100644 --- a/include/criterion/ordered-set.h +++ b/include/criterion/internal/ordered-set.h @@ -24,7 +24,7 @@ #ifndef CRITERION_ORDERED_SET_H_ # define CRITERION_ORDERED_SET_H_ -# include "types.h" +# include "../types.h" typedef int (*f_criterion_cmp)(void *, void *); diff --git a/include/criterion/preprocess.h b/include/criterion/internal/preprocess.h similarity index 100% rename from include/criterion/preprocess.h rename to include/criterion/internal/preprocess.h diff --git a/include/criterion/logging.h b/include/criterion/logging.h index 3fbc27c3..ab78034e 100644 --- a/include/criterion/logging.h +++ b/include/criterion/logging.h @@ -31,8 +31,8 @@ using std::va_list; # include # include # endif -# include "common.h" -# include "ordered-set.h" +# include "internal/common.h" +# include "internal/ordered-set.h" # include "stats.h" enum criterion_logging_level { diff --git a/include/criterion/redirect.h b/include/criterion/redirect.h index effb9094..c00f42f9 100644 --- a/include/criterion/redirect.h +++ b/include/criterion/redirect.h @@ -24,7 +24,7 @@ #ifndef CRITERION_REDIRECT_H_ # define CRITERION_REDIRECT_H_ -# include "common.h" +# include "internal/common.h" # include "assert.h" # ifdef __cplusplus diff --git a/include/criterion/types.h b/include/criterion/types.h index c2c40a2c..905b6ac0 100644 --- a/include/criterion/types.h +++ b/include/criterion/types.h @@ -33,7 +33,7 @@ using std::size_t; # include # include # endif -# include "common.h" +# include "internal/common.h" enum criterion_language { CR_LANG_C, diff --git a/src/compat/section.h b/src/compat/section.h index 7ff07555..c461ebfb 100644 --- a/src/compat/section.h +++ b/src/compat/section.h @@ -24,7 +24,7 @@ #ifndef SECTION_H_ # define SECTION_H_ -# include "criterion/common.h" +# include "criterion/internal/common.h" # ifdef _WIN32 void *get_win_section_start(const char *section); diff --git a/src/compat/time.c b/src/compat/time.c index f8c8fee7..2254d50c 100644 --- a/src/compat/time.c +++ b/src/compat/time.c @@ -1,7 +1,7 @@ #include #include #include -#include "criterion/common.h" +#include "criterion/internal/common.h" #include "criterion/options.h" #include "compat/time.h" #include "compat/posix.h" diff --git a/src/core/abort.c b/src/core/abort.c index 0d32188b..3fc35185 100644 --- a/src/core/abort.c +++ b/src/core/abort.c @@ -23,7 +23,7 @@ */ #include #include "abort.h" -#include "criterion/asprintf-compat.h" +#include "criterion/internal/asprintf-compat.h" #include "io/event.h" jmp_buf g_pre_test; diff --git a/src/core/ordered-set.c b/src/core/ordered-set.c index c7c6f38c..dde5d3cb 100644 --- a/src/core/ordered-set.c +++ b/src/core/ordered-set.c @@ -22,8 +22,8 @@ * THE SOFTWARE. */ #include -#include -#include +#include +#include #include #include "common.h" diff --git a/src/core/report.c b/src/core/report.c index c91e7807..f6c2398b 100644 --- a/src/core/report.c +++ b/src/core/report.c @@ -28,7 +28,7 @@ #include "criterion/stats.h" #include "criterion/logging.h" #include "criterion/options.h" -#include "criterion/ordered-set.h" +#include "criterion/internal/ordered-set.h" #include "report.h" #include "config.h" #include "compat/posix.h" diff --git a/src/core/runner.c b/src/core/runner.c index fe20ef5f..38a85fc3 100644 --- a/src/core/runner.c +++ b/src/core/runner.c @@ -29,9 +29,9 @@ #include #include "criterion/criterion.h" #include "criterion/options.h" -#include "criterion/ordered-set.h" +#include "criterion/internal/ordered-set.h" #include "criterion/logging.h" -#include "criterion/preprocess.h" +#include "criterion/internal/preprocess.h" #include "compat/time.h" #include "compat/posix.h" #include "compat/processor.h" diff --git a/src/core/stats.c b/src/core/stats.c index bb10bac9..f8d46cdb 100644 --- a/src/core/stats.c +++ b/src/core/stats.c @@ -23,7 +23,7 @@ */ #include #include -#include "criterion/common.h" +#include "criterion/internal/common.h" #include "stats.h" #include "common.h" diff --git a/src/entry/main.c b/src/entry/main.c index 6e561de7..792ff799 100644 --- a/src/entry/main.c +++ b/src/entry/main.c @@ -28,7 +28,7 @@ #include #include "criterion/criterion.h" #include "criterion/options.h" -#include "criterion/ordered-set.h" +#include "criterion/internal/ordered-set.h" #include "compat/posix.h" #include "compat/strtok.h" #include "core/runner.h" diff --git a/src/io/asprintf.c b/src/io/asprintf.c index c2a4a126..f340b1d0 100644 --- a/src/io/asprintf.c +++ b/src/io/asprintf.c @@ -25,7 +25,7 @@ #include #include #include -#include "criterion/asprintf-compat.h" +#include "criterion/internal/asprintf-compat.h" int cr_asprintf(char **strp, const char *fmt, ...) { va_list ap; diff --git a/src/io/event.c b/src/io/event.c index 97204267..8d45c4b9 100644 --- a/src/io/event.c +++ b/src/io/event.c @@ -26,7 +26,7 @@ #include #include #include "criterion/stats.h" -#include "criterion/common.h" +#include "criterion/internal/common.h" #include "criterion/hooks.h" #include "criterion/logging.h" #include "core/worker.h" diff --git a/src/io/json.c b/src/io/json.c index a893e57e..ea600731 100644 --- a/src/io/json.c +++ b/src/io/json.c @@ -28,7 +28,7 @@ #include "criterion/stats.h" #include "criterion/logging.h" #include "criterion/options.h" -#include "criterion/ordered-set.h" +#include "criterion/internal/ordered-set.h" #include "compat/posix.h" #include "compat/strtok.h" #include "compat/time.h" diff --git a/src/io/xml.c b/src/io/xml.c index 3bce465f..a2cf30f7 100644 --- a/src/io/xml.c +++ b/src/io/xml.c @@ -28,7 +28,7 @@ #include "criterion/stats.h" #include "criterion/logging.h" #include "criterion/options.h" -#include "criterion/ordered-set.h" +#include "criterion/internal/ordered-set.h" #include "compat/posix.h" #include "compat/strtok.h" #include "compat/time.h" diff --git a/src/log/normal.c b/src/log/normal.c index 9789d27e..f6221e09 100644 --- a/src/log/normal.c +++ b/src/log/normal.c @@ -29,7 +29,7 @@ #include "criterion/stats.h" #include "criterion/logging.h" #include "criterion/options.h" -#include "criterion/ordered-set.h" +#include "criterion/internal/ordered-set.h" #include "compat/posix.h" #include "compat/strtok.h" #include "compat/time.h" diff --git a/src/string/extmatch.c b/src/string/extmatch.c index 3af6da9e..de63088e 100644 --- a/src/string/extmatch.c +++ b/src/string/extmatch.c @@ -27,7 +27,7 @@ #include #include -#include "criterion/common.h" +#include "criterion/internal/common.h" #include "common.h" struct context { diff --git a/src/string/i18n.c b/src/string/i18n.c index ecc2e4de..da55950f 100644 --- a/src/string/i18n.c +++ b/src/string/i18n.c @@ -1,6 +1,6 @@ #include "i18n.h" #include "criterion/assert.h" -#include "criterion/asprintf-compat.h" +#include "criterion/internal/asprintf-compat.h" void init_i18n(void) { #if ENABLE_NLS diff --git a/test/asprintf.c b/test/asprintf.c index 0fa34d92..f709bd0f 100644 --- a/test/asprintf.c +++ b/test/asprintf.c @@ -1,6 +1,6 @@ #include "criterion/criterion.h" #include "criterion/theories.h" -#include "criterion/asprintf-compat.h" +#include "criterion/internal/asprintf-compat.h" #include diff --git a/test/ordered-set.c b/test/ordered-set.c index 3ecdbf1b..92a4d28d 100644 --- a/test/ordered-set.c +++ b/test/ordered-set.c @@ -1,7 +1,7 @@ #include #include "criterion/criterion.h" -#include "criterion/ordered-set.h" +#include "criterion/internal/ordered-set.h" int compare_gt(void *a, void *b) { int *ia = a, *ib = b; From 9b993abb936e2b86016f4b8cad455af4c95c060d Mon Sep 17 00:00:00 2001 From: Snaipe Date: Tue, 17 Nov 2015 17:33:44 +0100 Subject: [PATCH 153/211] Refactored tests and assertions implementation to internal/ --- CMakeLists.txt | 2 + include/criterion/assert.h | 274 +--------------- include/criterion/criterion.h | 70 +--- .../{assert_base.h => internal/assert.h} | 307 +++++++++++------- include/criterion/internal/test.h | 97 ++++++ include/criterion/theories.h | 2 +- src/core/wrappers/wrap.cc | 10 +- 7 files changed, 318 insertions(+), 444 deletions(-) rename include/criterion/{assert_base.h => internal/assert.h} (57%) create mode 100644 include/criterion/internal/test.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 3890768d..75cb3fe2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -204,6 +204,8 @@ set(INTERFACE_FILES include/criterion/parameterized.h include/criterion/redirect.h include/criterion/output.h + include/criterion/internal/assert.h + include/criterion/internal/test.h include/criterion/internal/common.h include/criterion/internal/ordered-set.h include/criterion/internal/asprintf-compat.h diff --git a/include/criterion/assert.h b/include/criterion/assert.h index 19593108..3c692830 100644 --- a/include/criterion/assert.h +++ b/include/criterion/assert.h @@ -28,28 +28,26 @@ # include # endif -# include "assert_base.h" +# include "internal/assert.h" -// Common binary assertions +CR_BEGIN_C_API + +CR_API char *cr_translate_assert_msg(int msg_index, ...); + +CR_END_C_API + +// Base assertions + +# define cr_assert_fail(...) CR_EXPAND(cr_fail(CR_FAIL_ABORT_, __VA_ARGS__)) +# define cr_expect_fail(...) CR_EXPAND(cr_fail(CR_FAIL_CONTINUES_, __VA_ARGS__)) + +# define cr_assert(...) CR_EXPAND(cr_assert_(__VA_ARGS__)) +# define cr_expect(...) CR_EXPAND(cr_expect_(__VA_ARGS__)) -# define cr_assert_op_(Fail, Op, Actual, Expected, ...) \ - CR_EXPAND(cr_assert_impl( \ - Fail, \ - (Actual) Op (Expected), \ - dummy, \ - CRITERION_ASSERT_MSG_EXPR_FALSE, \ - (CR_STR((Actual) Op (Expected))), \ - __VA_ARGS__ \ - )) - -# define cr_assert_op_va_(Fail, Op, ...) \ - CR_EXPAND(cr_assert_op_( \ - Fail, \ - Op, \ - CR_VA_HEAD(__VA_ARGS__), \ - CR_VA_HEAD(CR_VA_TAIL(__VA_ARGS__)), \ - CR_VA_TAIL(CR_VA_TAIL(__VA_ARGS__)) \ - )) +# define cr_assert_not(...) CR_EXPAND(cr_assert_not_(__VA_ARGS__)) +# define cr_expect_not(...) CR_EXPAND(cr_expect_not_(__VA_ARGS__)) + +// Common binary assertions # define cr_assert_eq(...) CR_EXPAND(cr_assert_op_va_(CR_FAIL_ABORT_, ==, __VA_ARGS__)) # define cr_expect_eq(...) CR_EXPAND(cr_assert_op_va_(CR_FAIL_CONTINUES_, ==, __VA_ARGS__)) @@ -71,25 +69,6 @@ // Common unary assertions -# define cr_assert_null_op_(Fail, Op, Msg, Value, ...) \ - CR_EXPAND(cr_assert_impl( \ - Fail, \ - (Value) Op NULL, \ - dummy, \ - Msg, \ - (CR_STR(Value)), \ - __VA_ARGS__ \ - )) - -# define cr_assert_null_op_va_(Fail, Op, Msg, ...) \ - CR_EXPAND(cr_assert_null_op_( \ - Fail, \ - Op, \ - Msg, \ - CR_VA_HEAD(__VA_ARGS__), \ - CR_VA_TAIL(__VA_ARGS__) \ - )) - # define cr_assert_null(...) CR_EXPAND(cr_assert_null_op_va_(CR_FAIL_ABORT_, ==, CRITERION_ASSERT_MSG_IS_NOT_NULL, __VA_ARGS__)) # define cr_expect_null(...) CR_EXPAND(cr_assert_null_op_va_(CR_FAIL_CONTINUES_, ==, CRITERION_ASSERT_MSG_IS_NOT_NULL, __VA_ARGS__)) @@ -98,32 +77,6 @@ // Floating-point assertions -# define cr_assert_float_eq_op_(Actual, Expected, Epsilon) \ - (Expected) - (Actual) <= (Epsilon) && (Actual) - (Expected) <= (Epsilon) - -# define cr_assert_float_neq_op_(Actual, Expected, Epsilon) \ - (Expected) - (Actual) > (Epsilon) || (Actual) - (Expected) > (Epsilon) - -# define cr_assert_float_op_(Fail, Op, Actual, Expected, Epsilon, ...) \ - CR_EXPAND(cr_assert_impl( \ - Fail, \ - Op(Actual, Expected, Epsilon), \ - dummy, \ - CRITERION_ASSERT_MSG_EXPR_FALSE, \ - (CR_STR(Op(Actual, Expected, Epsilon))), \ - __VA_ARGS__ \ - )) - -# define cr_assert_float_op_va_(Fail, Op, ...) \ - CR_EXPAND(cr_assert_float_op_( \ - Fail, \ - Op, \ - CR_VA_HEAD(__VA_ARGS__), \ - CR_VA_HEAD(CR_VA_TAIL(__VA_ARGS__)), \ - CR_VA_HEAD(CR_VA_TAIL(CR_VA_TAIL(__VA_ARGS__))), \ - CR_VA_TAIL(CR_VA_TAIL(CR_VA_TAIL(__VA_ARGS__))) \ - )) - # define cr_assert_float_eq(...) CR_EXPAND(cr_assert_float_op_va_(CR_FAIL_ABORT_, cr_assert_float_eq_op_, __VA_ARGS__)) # define cr_expect_float_eq(...) CR_EXPAND(cr_assert_float_op_va_(CR_FAIL_CONTINUES_, cr_assert_float_eq_op_, __VA_ARGS__)) @@ -132,50 +85,12 @@ // String assertions -# define cr_assert_str_op_empty_(Fail, Op, Msg, Value, ...) \ - CR_EXPAND(cr_assert_impl( \ - Fail, \ - (Value)[0] Op '\0', \ - dummy, \ - Msg, \ - (CR_STR(Value)), \ - __VA_ARGS__ \ - )) - -# define cr_assert_str_op_empty_va_(Fail, Op, Msg, ...) \ - CR_EXPAND(cr_assert_str_op_empty_( \ - Fail, \ - Op, \ - Msg, \ - CR_VA_HEAD(__VA_ARGS__), \ - CR_VA_TAIL(__VA_ARGS__) \ - )) - # define cr_assert_str_empty(...) CR_EXPAND(cr_assert_str_op_empty_va_(CR_FAIL_ABORT_, ==, CRITERION_ASSERT_MSG_IS_NOT_EMPTY, __VA_ARGS__)) # define cr_expect_str_empty(...) CR_EXPAND(cr_assert_str_op_empty_va_(CR_FAIL_CONTINUES_, ==, CRITERION_ASSERT_MSG_IS_NOT_EMPTY, __VA_ARGS__)) # define cr_assert_str_not_empty(...) CR_EXPAND(cr_assert_str_op_empty_va_(CR_FAIL_ABORT_, !=, CRITERION_ASSERT_MSG_IS_EMPTY, __VA_ARGS__)) # define cr_expect_str_not_empty(...) CR_EXPAND(cr_assert_str_op_empty_va_(CR_FAIL_CONTINUES_, !=, CRITERION_ASSERT_MSG_IS_EMPTY, __VA_ARGS__)) -# define cr_assert_str_op_(Fail, Op, Actual, Expected, ...) \ - CR_EXPAND(cr_assert_impl( \ - Fail, \ - CR_STDN strcmp((Actual), (Expected)) Op 0, \ - dummy, \ - CRITERION_ASSERT_MSG_EXPR_AS_STRINGS_FALSE, \ - (CR_STR((Actual) Op (Expected))), \ - __VA_ARGS__ \ - )) - -# define cr_assert_str_op_va_(Fail, Op, ...) \ - CR_EXPAND(cr_assert_str_op_( \ - Fail, \ - Op, \ - CR_VA_HEAD(__VA_ARGS__), \ - CR_VA_HEAD(CR_VA_TAIL(__VA_ARGS__)), \ - CR_VA_TAIL(CR_VA_TAIL(__VA_ARGS__)) \ - )) - # define cr_assert_str_eq(...) CR_EXPAND(cr_assert_str_op_va_(CR_FAIL_ABORT_, ==, __VA_ARGS__)) # define cr_expect_str_eq(...) CR_EXPAND(cr_assert_str_op_va_(CR_FAIL_CONTINUES_, ==, __VA_ARGS__)) @@ -196,26 +111,6 @@ // Array assertions -# define cr_assert_mem_op_(Fail, Op, Actual, Expected, Size, ...) \ - CR_EXPAND(cr_assert_impl( \ - Fail, \ - CR_STDN memcmp((Actual), (Expected), (Size)) Op 0, \ - dummy, \ - CRITERION_ASSERT_MSG_EXPR_FALSE, \ - (CR_STR((Actual)[0 .. Size] Op (Expected)[0 .. Size])), \ - __VA_ARGS__ \ - )) - -# define cr_assert_mem_op_va_(Fail, Op, ...) \ - CR_EXPAND(cr_assert_mem_op_( \ - Fail, \ - Op, \ - CR_VA_HEAD(__VA_ARGS__), \ - CR_VA_HEAD(CR_VA_TAIL(__VA_ARGS__)), \ - CR_VA_HEAD(CR_VA_TAIL(CR_VA_TAIL(__VA_ARGS__))), \ - CR_VA_TAIL(CR_VA_TAIL(CR_VA_TAIL(__VA_ARGS__))) \ - )) - # define cr_assert_arr_eq(...) CR_EXPAND(cr_assert_mem_op_va_(CR_FAIL_ABORT_, ==, __VA_ARGS__)) # define cr_expect_arr_eq(...) CR_EXPAND(cr_assert_mem_op_va_(CR_FAIL_CONTINUES_, ==, __VA_ARGS__)) @@ -226,43 +121,6 @@ # if defined(__GNUC__) || defined(__clang__) || defined(__cplusplus) -# ifdef __cplusplus -# define CR_ARR_COMPARE_(A, B, Size, Cmp, Result) \ - int Result = std::lexicographical_compare((A), (A) + Size, (B), (B) + Size, Cmp) -# else -# define CR_ARR_COMPARE_(A, B, Size, Cmp, Result) \ - __typeof__(&(A)[0]) first = (A); \ - __typeof__(&(B)[0]) second = (B); \ - int Result = 0; \ - size_t i, size; \ - for (i = 0, size = (Size); !Result && i < size; ++i) \ - Result = Cmp(first + i, second + i) -# endif - -# define cr_assert_arr_op_cmp_(Fail, Op, Actual, Expected, Size, Cmp, ...) \ - do { \ - CR_ARR_COMPARE_(Actual, Expected, Size, Cmp, order); \ - CR_EXPAND(cr_assert_impl( \ - Fail, \ - order Op 0, \ - dummy, \ - CRITERION_ASSERT_MSG_EXPR_FALSE, \ - (CR_STR((Actual)[0 .. Size] Op (Expected)[0 .. Size])), \ - __VA_ARGS__ \ - )); \ - } while (0) - -# define cr_assert_arr_op_cmp_va_(Fail, Op, ...) \ - CR_EXPAND(cr_assert_arr_op_cmp_( \ - Fail, \ - Op, \ - CR_VA_HEAD(__VA_ARGS__), \ - CR_VA_HEAD(CR_VA_TAIL(__VA_ARGS__)), \ - CR_VA_HEAD(CR_VA_TAIL(CR_VA_TAIL(__VA_ARGS__))), \ - CR_VA_HEAD(CR_VA_TAIL(CR_VA_TAIL(CR_VA_TAIL(__VA_ARGS__)))), \ - CR_VA_TAIL(CR_VA_TAIL(CR_VA_TAIL(CR_VA_TAIL(__VA_ARGS__)))) \ - )) - # define cr_assert_arr_eq_cmp(...) CR_EXPAND(cr_assert_arr_op_cmp_va_(CR_FAIL_ABORT_, ==, __VA_ARGS__)) # define cr_expect_arr_eq_cmp(...) CR_EXPAND(cr_assert_arr_op_cmp_va_(CR_FAIL_CONTINUES_, ==, __VA_ARGS__)) @@ -283,14 +141,6 @@ # else -# define CRITERION_GNUC_WARN__(Msg) \ - _Pragma(#Msg) - -# define CRITERION_GNUC_WARN_(Name) CRITERION_GNUC_WARN__( \ - message \ - "The `" #Name "` macro is only available on GNU C compilers." \ - ) - # define cr_assert_arr_eq_cmp(...) CRITERION_GNUC_WARN_(cr_assert_arr_eq_cmp) CR_NOOP # define cr_expect_arr_eq_cmp(...) CRITERION_GNUC_WARN_(cr_expect_arr_eq_cmp) CR_NOOP @@ -313,103 +163,15 @@ # ifdef __cplusplus -# define cr_assert_throw_abort_(Fail, Msg, MsgArgs, ...) \ - CR_EXPAND(cr_assert_impl( \ - Fail, \ - 0, \ - dummy, \ - Msg, \ - MsgArgs, \ - CR_VA_TAIL(__VA_ARGS__) \ - )) - -# define cr_assert_throw_(Fail, Statement, Exception, ...) \ - try { \ - Statement; \ - } catch (Exception const &) { \ - } catch (...) { \ - CR_EXPAND(cr_assert_throw_abort_( \ - Fail, \ - CRITERION_ASSERT_MSG_NO_THROW, \ - (CR_STR(Statement), CR_STR(Exception)), \ - __VA_ARGS__)); \ - } - -# define cr_assert_throw_va_(...) \ - CR_EXPAND(cr_assert_throw_( \ - CR_VA_HEAD(__VA_ARGS__), \ - CR_VA_HEAD(CR_VA_TAIL(__VA_ARGS__)), \ - CR_VA_HEAD(CR_VA_TAIL(CR_VA_TAIL(__VA_ARGS__))), \ - dummy, \ - CR_VA_TAIL(CR_VA_TAIL(CR_VA_TAIL(__VA_ARGS__))) \ - )) - # define cr_assert_throw(...) CR_EXPAND(cr_assert_throw_va_(CR_FAIL_ABORT_, __VA_ARGS__)) # define cr_expect_throw(...) CR_EXPAND(cr_assert_throw_va_(CR_FAIL_CONTINUES_, __VA_ARGS__)) -# define cr_assert_no_throw_(Fail, Statement, Exception, ...) \ - try { \ - Statement; \ - } catch (Exception const &) { \ - CR_EXPAND(cr_assert_throw_abort_( \ - Fail, \ - CRITERION_ASSERT_MSG_THROW, \ - (CR_STR(Statement), CR_STR(Exception)), \ - __VA_ARGS__)); \ - } - -# define cr_assert_no_throw_va_(...) \ - CR_EXPAND(cr_assert_no_throw_( \ - CR_VA_HEAD(__VA_ARGS__), \ - CR_VA_HEAD(CR_VA_TAIL(__VA_ARGS__)), \ - CR_VA_HEAD(CR_VA_TAIL(CR_VA_TAIL(__VA_ARGS__))), \ - dummy, \ - CR_VA_TAIL(CR_VA_TAIL(CR_VA_TAIL(__VA_ARGS__))) \ - )) - # define cr_assert_no_throw(...) CR_EXPAND(cr_assert_no_throw_va_(CR_FAIL_ABORT_, __VA_ARGS__)) # define cr_expect_no_throw(...) CR_EXPAND(cr_assert_no_throw_va_(CR_FAIL_CONTINUES_, __VA_ARGS__)) -# define cr_assert_any_throw_(Fail, Statement, ...) \ - try { \ - Statement; \ - CR_EXPAND(cr_assert_throw_abort_( \ - Fail, \ - CRITERION_ASSERT_MSG_ANY_THROW, \ - (CR_STR(Statement)), \ - __VA_ARGS__)); \ - } catch (...) {} - -# define cr_assert_any_throw_va_(...) \ - CR_EXPAND(cr_assert_any_throw_( \ - CR_VA_HEAD(__VA_ARGS__), \ - CR_VA_HEAD(CR_VA_TAIL(__VA_ARGS__)), \ - dummy, \ - CR_VA_TAIL(CR_VA_TAIL(__VA_ARGS__)) \ - )) - # define cr_assert_any_throw(...) CR_EXPAND(cr_assert_any_throw_va_(CR_FAIL_ABORT_, __VA_ARGS__)) # define cr_expect_any_throw(...) CR_EXPAND(cr_assert_any_throw_va_(CR_FAIL_CONTINUES_, __VA_ARGS__)) -# define cr_assert_none_throw_(Fail, Statement, ...) \ - try { \ - Statement; \ - } catch (...) { \ - CR_EXPAND(cr_assert_throw_abort_( \ - Fail, \ - CRITERION_ASSERT_MSG_NONE_THROW, \ - (CR_STR(Statement)), \ - __VA_ARGS__)); \ - } - -# define cr_assert_none_throw_va_(...) \ - CR_EXPAND(cr_assert_none_throw_( \ - CR_VA_HEAD(__VA_ARGS__), \ - CR_VA_HEAD(CR_VA_TAIL(__VA_ARGS__)), \ - dummy, \ - CR_VA_TAIL(CR_VA_TAIL(__VA_ARGS__)) \ - )) - # define cr_assert_none_throw(...) CR_EXPAND(cr_assert_none_throw_va_(CR_FAIL_ABORT_, __VA_ARGS__)) # define cr_expect_none_throw(...) CR_EXPAND(cr_assert_none_throw_va_(CR_FAIL_CONTINUES_, __VA_ARGS__)) diff --git a/include/criterion/criterion.h b/include/criterion/criterion.h index 9549223b..c90114e6 100644 --- a/include/criterion/criterion.h +++ b/include/criterion/criterion.h @@ -24,79 +24,15 @@ #ifndef CRITERION_H_ # define CRITERION_H_ -# include "internal/designated-initializer-compat.h" -# include "internal/common.h" # include "types.h" # include "assert.h" # include "alloc.h" -# define CR_IDENTIFIER_(Category, Name, Suffix) \ - Category ## _ ## Name ## _ ## Suffix +# include "internal/test.h" -# ifdef __cplusplus -# ifdef __OBJC__ -# define CR_LANG CR_LANG_OBJCXX -# else -# define CR_LANG CR_LANG_CXX -# endif -# else -# ifdef __OBJC__ -# define CR_LANG CR_LANG_OBJC -# else -# define CR_LANG CR_LANG_C -# endif -# endif +# define Test(...) CR_EXPAND(CR_TEST_BASE(__VA_ARGS__, .sentinel_ = 0)) -# ifdef __cplusplus -# define CR_TEST_PROTOTYPE_(Category, Name) \ - extern "C" void CR_IDENTIFIER_(Category, Name, impl)(void) -# else -# define CR_TEST_PROTOTYPE_(Category, Name) \ - void CR_IDENTIFIER_(Category, Name, impl)(void) -# endif - -# define CR_SUITE_IDENTIFIER_(Name, Suffix) \ - suite_ ## Name ## _ ## Suffix - -# define Test(...) CR_EXPAND(Test_(__VA_ARGS__, .sentinel_ = 0)) -# define Test_(Category, Name, ...) \ - CR_TEST_PROTOTYPE_(Category, Name); \ - struct criterion_test_extra_data CR_IDENTIFIER_(Category, Name, extra) = \ - CR_EXPAND(CRITERION_MAKE_STRUCT(struct criterion_test_extra_data, \ - .lang_ = CR_LANG, \ - .kind_ = CR_TEST_NORMAL, \ - .param_ = (struct criterion_test_params(*)(void)) NULL, \ - .identifier_ = #Category "/" #Name, \ - .file_ = __FILE__, \ - .line_ = __LINE__, \ - __VA_ARGS__ \ - )); \ - struct criterion_test CR_IDENTIFIER_(Category, Name, meta) = { \ - #Name, \ - #Category, \ - CR_IDENTIFIER_(Category, Name, impl), \ - &CR_IDENTIFIER_(Category, Name, extra) \ - }; \ - CR_SECTION_("cr_tst") \ - struct criterion_test *CR_IDENTIFIER_(Category, Name, ptr) \ - = &CR_IDENTIFIER_(Category, Name, meta) CR_SECTION_SUFFIX_; \ - CR_TEST_PROTOTYPE_(Category, Name) - -# define TestSuite(...) CR_EXPAND(TestSuite_(__VA_ARGS__, .sentinel_ = 0)) -# define TestSuite_(Name, ...) \ - struct criterion_test_extra_data CR_SUITE_IDENTIFIER_(Name, extra) = \ - CR_EXPAND(CRITERION_MAKE_STRUCT(struct criterion_test_extra_data, \ - .file_ = __FILE__, \ - .line_ = 0, \ - __VA_ARGS__ \ - )); \ - struct criterion_suite CR_SUITE_IDENTIFIER_(Name, meta) = { \ - #Name, \ - &CR_SUITE_IDENTIFIER_(Name, extra), \ - }; \ - CR_SECTION_("cr_sts") \ - struct criterion_suite *CR_SUITE_IDENTIFIER_(Name, ptr) \ - = &CR_SUITE_IDENTIFIER_(Name, meta) CR_SECTION_SUFFIX_ +# define TestSuite(...) CR_EXPAND(CR_SUITE_BASE(__VA_ARGS__, .sentinel_ = 0)) CR_BEGIN_C_API diff --git a/include/criterion/assert_base.h b/include/criterion/internal/assert.h similarity index 57% rename from include/criterion/assert_base.h rename to include/criterion/internal/assert.h index f5395989..9b234172 100644 --- a/include/criterion/assert_base.h +++ b/include/criterion/internal/assert.h @@ -1,31 +1,10 @@ -/* - * The MIT License (MIT) - * - * Copyright © 2015 Franklin "Snaipe" Mathieu - * - * 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 CRITERION_ASSERT_BASE_H_ -# define CRITERION_ASSERT_BASE_H_ - -# include "internal/preprocess.h" -# include "internal/asprintf-compat.h" +#ifndef CRITERION_INTERNAL_ASSERT_H_ +# define CRITERION_INTERNAL_ASSERT_H_ + +# include "common.h" +# include "preprocess.h" +# include "asprintf-compat.h" +# include "designated-initializer-compat.h" # ifdef __cplusplus # include @@ -35,12 +14,11 @@ # include # include # endif -# include "internal/designated-initializer-compat.h" -# include "types.h" -# include "stats.h" -# include "hooks.h" -# include "event.h" -# include "abort.h" +# include "../types.h" +# include "../stats.h" +# include "../hooks.h" +# include "../event.h" +# include "../abort.h" struct criterion_assert_args { const char *msg; @@ -69,12 +47,6 @@ enum criterion_assert_messages { CRITERION_ASSERT_MSG_NONE_THROW, }; -CR_BEGIN_C_API - -CR_API char *cr_translate_assert_msg(int msg_index, ...); - -CR_END_C_API - # define CR_GET_CONDITION(Condition, ...) Condition # define CR_GET_CONDITION_STR(Condition, ...) #Condition # define CR_VA_SKIP(_, ...) __VA_ARGS__ @@ -151,8 +123,6 @@ CR_END_C_API Fail(); \ } while (0) -// Base assertions - # define cr_fail(Fail, ...) \ CR_EXPAND(cr_assert_impl( \ Fail, \ @@ -163,10 +133,7 @@ CR_END_C_API __VA_ARGS__ \ )) -# define cr_assert_fail(...) CR_EXPAND(cr_fail(CR_FAIL_ABORT_, __VA_ARGS__)) -# define cr_expect_fail(...) CR_EXPAND(cr_fail(CR_FAIL_CONTINUES_, __VA_ARGS__)) - -# define cr_assert(...) \ +# define cr_assert_(...) \ CR_EXPAND(cr_assert_impl( \ CR_FAIL_ABORT_, \ CR_VA_HEAD(__VA_ARGS__), \ @@ -176,7 +143,7 @@ CR_END_C_API CR_VA_TAIL(__VA_ARGS__) \ )) -# define cr_expect(...) \ +# define cr_expect_(...) \ CR_EXPAND(cr_assert_impl( \ CR_FAIL_CONTINUES_, \ CR_VA_HEAD(__VA_ARGS__), \ @@ -186,27 +153,28 @@ CR_END_C_API CR_VA_TAIL(__VA_ARGS__) \ )) -# define cr_assert_not(...) \ - CR_EXPAND(cr_assert_impl( \ - CR_FAIL_ABORT_, \ - !(CR_VA_HEAD(__VA_ARGS__)), \ - dummy, \ - CRITERION_ASSERT_MSG_EXPR_FALSE, \ - (CR_STR(!(CR_VA_HEAD(__VA_ARGS__)))), \ - CR_VA_TAIL(__VA_ARGS__) \ +# define cr_assert_not_(...) \ + CR_EXPAND(cr_assert_impl( \ + CR_FAIL_ABORT_, \ + !(CR_VA_HEAD(__VA_ARGS__)), \ + dummy, \ + CRITERION_ASSERT_MSG_EXPR_FALSE, \ + (CR_STR(!(CR_VA_HEAD(__VA_ARGS__)))), \ + CR_VA_TAIL(__VA_ARGS__) \ )) -# define cr_expect_not(...) \ - CR_EXPAND(cr_assert_impl( \ - CR_FAIL_CONTINUES_, \ - !(CR_VA_HEAD(__VA_ARGS__)), \ - dummy, \ - CRITERION_ASSERT_MSG_EXPR_FALSE, \ - (CR_STR(!(CR_VA_HEAD(__VA_ARGS__)))), \ - CR_VA_TAIL(__VA_ARGS__) \ +# define cr_expect_not_(...) \ + CR_EXPAND(cr_assert_impl( \ + CR_FAIL_CONTINUES_, \ + !(CR_VA_HEAD(__VA_ARGS__)), \ + dummy, \ + CRITERION_ASSERT_MSG_EXPR_FALSE, \ + (CR_STR(!(CR_VA_HEAD(__VA_ARGS__)))), \ + CR_VA_TAIL(__VA_ARGS__) \ )) -// Common binary assertions + +// Binary # define cr_assert_op_(Fail, Op, Actual, Expected, ...) \ CR_EXPAND(cr_assert_impl( \ @@ -227,25 +195,7 @@ CR_END_C_API CR_VA_TAIL(CR_VA_TAIL(__VA_ARGS__)) \ )) -# define cr_assert_eq(...) CR_EXPAND(cr_assert_op_va_(CR_FAIL_ABORT_, ==, __VA_ARGS__)) -# define cr_expect_eq(...) CR_EXPAND(cr_assert_op_va_(CR_FAIL_CONTINUES_, ==, __VA_ARGS__)) - -# define cr_assert_neq(...) CR_EXPAND(cr_assert_op_va_(CR_FAIL_ABORT_, !=, __VA_ARGS__)) -# define cr_expect_neq(...) CR_EXPAND(cr_assert_op_va_(CR_FAIL_CONTINUES_, !=, __VA_ARGS__)) - -# define cr_assert_lt(...) CR_EXPAND(cr_assert_op_va_(CR_FAIL_ABORT_, <, __VA_ARGS__)) -# define cr_expect_lt(...) CR_EXPAND(cr_assert_op_va_(CR_FAIL_CONTINUES_, <, __VA_ARGS__)) - -# define cr_assert_leq(...) CR_EXPAND(cr_assert_op_va_(CR_FAIL_ABORT_, <=, __VA_ARGS__)) -# define cr_expect_leq(...) CR_EXPAND(cr_assert_op_va_(CR_FAIL_CONTINUES_, <=, __VA_ARGS__)) - -# define cr_assert_gt(...) CR_EXPAND(cr_assert_op_va_(CR_FAIL_ABORT_, >, __VA_ARGS__)) -# define cr_expect_gt(...) CR_EXPAND(cr_assert_op_va_(CR_FAIL_CONTINUES_, >, __VA_ARGS__)) - -# define cr_assert_geq(...) CR_EXPAND(cr_assert_op_va_(CR_FAIL_ABORT_, >=, __VA_ARGS__)) -# define cr_expect_geq(...) CR_EXPAND(cr_assert_op_va_(CR_FAIL_CONTINUES_, >=, __VA_ARGS__)) - -// Common unary assertions +// Unary # define cr_assert_null_op_(Fail, Op, Msg, Value, ...) \ CR_EXPAND(cr_assert_impl( \ @@ -266,13 +216,7 @@ CR_END_C_API CR_VA_TAIL(__VA_ARGS__) \ )) -# define cr_assert_null(...) CR_EXPAND(cr_assert_null_op_va_(CR_FAIL_ABORT_, ==, CRITERION_ASSERT_MSG_IS_NOT_NULL, __VA_ARGS__)) -# define cr_expect_null(...) CR_EXPAND(cr_assert_null_op_va_(CR_FAIL_CONTINUES_, ==, CRITERION_ASSERT_MSG_IS_NOT_NULL, __VA_ARGS__)) - -# define cr_assert_not_null(...) CR_EXPAND(cr_assert_null_op_va_(CR_FAIL_ABORT_, !=, CRITERION_ASSERT_MSG_IS_NULL, __VA_ARGS__)) -# define cr_expect_not_null(...) CR_EXPAND(cr_assert_null_op_va_(CR_FAIL_CONTINUES_, !=, CRITERION_ASSERT_MSG_IS_NULL, __VA_ARGS__)) - -// Floating-point assertions +// Floating point # define cr_assert_float_eq_op_(Actual, Expected, Epsilon) \ (Expected) - (Actual) <= (Epsilon) && (Actual) - (Expected) <= (Epsilon) @@ -300,13 +244,7 @@ CR_END_C_API CR_VA_TAIL(CR_VA_TAIL(CR_VA_TAIL(__VA_ARGS__))) \ )) -# define cr_assert_float_eq(...) CR_EXPAND(cr_assert_float_op_va_(CR_FAIL_ABORT_, cr_assert_float_eq_op_, __VA_ARGS__)) -# define cr_expect_float_eq(...) CR_EXPAND(cr_assert_float_op_va_(CR_FAIL_CONTINUES_, cr_assert_float_eq_op_, __VA_ARGS__)) - -# define cr_assert_float_neq(...) CR_EXPAND(cr_assert_float_op_va_(CR_FAIL_ABORT_, cr_assert_float_neq_op_, __VA_ARGS__)) -# define cr_expect_float_neq(...) CR_EXPAND(cr_assert_float_op_va_(CR_FAIL_CONTINUES_, cr_assert_float_neq_op_, __VA_ARGS__)) - -// String assertions +// String # define cr_assert_str_op_empty_(Fail, Op, Msg, Value, ...) \ CR_EXPAND(cr_assert_impl( \ @@ -327,12 +265,6 @@ CR_END_C_API CR_VA_TAIL(__VA_ARGS__) \ )) -# define cr_assert_str_empty(...) CR_EXPAND(cr_assert_str_op_empty_va_(CR_FAIL_ABORT_, ==, CRITERION_ASSERT_MSG_IS_NOT_EMPTY, __VA_ARGS__)) -# define cr_expect_str_empty(...) CR_EXPAND(cr_assert_str_op_empty_va_(CR_FAIL_CONTINUES_, ==, CRITERION_ASSERT_MSG_IS_NOT_EMPTY, __VA_ARGS__)) - -# define cr_assert_str_not_empty(...) CR_EXPAND(cr_assert_str_op_empty_va_(CR_FAIL_ABORT_, !=, CRITERION_ASSERT_MSG_IS_EMPTY, __VA_ARGS__)) -# define cr_expect_str_not_empty(...) CR_EXPAND(cr_assert_str_op_empty_va_(CR_FAIL_CONTINUES_, !=, CRITERION_ASSERT_MSG_IS_EMPTY, __VA_ARGS__)) - # define cr_assert_str_op_(Fail, Op, Actual, Expected, ...) \ CR_EXPAND(cr_assert_impl( \ Fail, \ @@ -352,22 +284,165 @@ CR_END_C_API CR_VA_TAIL(CR_VA_TAIL(__VA_ARGS__)) \ )) -# define cr_assert_str_eq(...) CR_EXPAND(cr_assert_str_op_va_(CR_FAIL_ABORT_, ==, __VA_ARGS__)) -# define cr_expect_str_eq(...) CR_EXPAND(cr_assert_str_op_va_(CR_FAIL_CONTINUES_, ==, __VA_ARGS__)) +// Array + +# define cr_assert_mem_op_(Fail, Op, Actual, Expected, Size, ...) \ + CR_EXPAND(cr_assert_impl( \ + Fail, \ + CR_STDN memcmp((Actual), (Expected), (Size)) Op 0, \ + dummy, \ + CRITERION_ASSERT_MSG_EXPR_FALSE, \ + (CR_STR((Actual)[0 .. Size] Op (Expected)[0 .. Size])), \ + __VA_ARGS__ \ + )) + +# define cr_assert_mem_op_va_(Fail, Op, ...) \ + CR_EXPAND(cr_assert_mem_op_( \ + Fail, \ + Op, \ + CR_VA_HEAD(__VA_ARGS__), \ + CR_VA_HEAD(CR_VA_TAIL(__VA_ARGS__)), \ + CR_VA_HEAD(CR_VA_TAIL(CR_VA_TAIL(__VA_ARGS__))), \ + CR_VA_TAIL(CR_VA_TAIL(CR_VA_TAIL(__VA_ARGS__))) \ + )) -# define cr_assert_str_neq(...) CR_EXPAND(cr_assert_str_op_va_(CR_FAIL_ABORT_, !=, __VA_ARGS__)) -# define cr_expect_str_neq(...) CR_EXPAND(cr_assert_str_op_va_(CR_FAIL_CONTINUES_, !=, __VA_ARGS__)) +// Array comparisons + +# ifdef __cplusplus +# define CR_ARR_COMPARE_(A, B, Size, Cmp, Result) \ + int Result = std::lexicographical_compare((A), (A) + Size, (B), (B) + Size, Cmp) +# else +# define CR_ARR_COMPARE_(A, B, Size, Cmp, Result) \ + __typeof__(&(A)[0]) first = (A); \ + __typeof__(&(B)[0]) second = (B); \ + int Result = 0; \ + size_t i, size; \ + for (i = 0, size = (Size); !Result && i < size; ++i) \ + Result = Cmp(first + i, second + i) +# endif + +# define cr_assert_arr_op_cmp_(Fail, Op, Actual, Expected, Size, Cmp, ...) \ + do { \ + CR_ARR_COMPARE_(Actual, Expected, Size, Cmp, order); \ + CR_EXPAND(cr_assert_impl( \ + Fail, \ + order Op 0, \ + dummy, \ + CRITERION_ASSERT_MSG_EXPR_FALSE, \ + (CR_STR((Actual)[0 .. Size] Op (Expected)[0 .. Size])), \ + __VA_ARGS__ \ + )); \ + } while (0) -# define cr_assert_str_lt(...) CR_EXPAND(cr_assert_str_op_va_(CR_FAIL_ABORT_, <, __VA_ARGS__)) -# define cr_expect_str_lt(...) CR_EXPAND(cr_assert_str_op_va_(CR_FAIL_CONTINUES_, <, __VA_ARGS__)) +# define cr_assert_arr_op_cmp_va_(Fail, Op, ...) \ + CR_EXPAND(cr_assert_arr_op_cmp_( \ + Fail, \ + Op, \ + CR_VA_HEAD(__VA_ARGS__), \ + CR_VA_HEAD(CR_VA_TAIL(__VA_ARGS__)), \ + CR_VA_HEAD(CR_VA_TAIL(CR_VA_TAIL(__VA_ARGS__))), \ + CR_VA_HEAD(CR_VA_TAIL(CR_VA_TAIL(CR_VA_TAIL(__VA_ARGS__)))), \ + CR_VA_TAIL(CR_VA_TAIL(CR_VA_TAIL(CR_VA_TAIL(__VA_ARGS__)))) \ + )) + +// Exceptions + +# define cr_assert_throw_abort_(Fail, Msg, MsgArgs, ...) \ + CR_EXPAND(cr_assert_impl( \ + Fail, \ + 0, \ + dummy, \ + Msg, \ + MsgArgs, \ + CR_VA_TAIL(__VA_ARGS__) \ + )) + +# define cr_assert_throw_(Fail, Statement, Exception, ...) \ + try { \ + Statement; \ + } catch (Exception const &) { \ + } catch (...) { \ + CR_EXPAND(cr_assert_throw_abort_( \ + Fail, \ + CRITERION_ASSERT_MSG_NO_THROW, \ + (CR_STR(Statement), CR_STR(Exception)), \ + __VA_ARGS__)); \ + } + +# define cr_assert_throw_va_(...) \ + CR_EXPAND(cr_assert_throw_( \ + CR_VA_HEAD(__VA_ARGS__), \ + CR_VA_HEAD(CR_VA_TAIL(__VA_ARGS__)), \ + CR_VA_HEAD(CR_VA_TAIL(CR_VA_TAIL(__VA_ARGS__))), \ + dummy, \ + CR_VA_TAIL(CR_VA_TAIL(CR_VA_TAIL(__VA_ARGS__))) \ + )) + +# define cr_assert_no_throw_(Fail, Statement, Exception, ...) \ + try { \ + Statement; \ + } catch (Exception const &) { \ + CR_EXPAND(cr_assert_throw_abort_( \ + Fail, \ + CRITERION_ASSERT_MSG_THROW, \ + (CR_STR(Statement), CR_STR(Exception)), \ + __VA_ARGS__)); \ + } + +# define cr_assert_no_throw_va_(...) \ + CR_EXPAND(cr_assert_no_throw_( \ + CR_VA_HEAD(__VA_ARGS__), \ + CR_VA_HEAD(CR_VA_TAIL(__VA_ARGS__)), \ + CR_VA_HEAD(CR_VA_TAIL(CR_VA_TAIL(__VA_ARGS__))), \ + dummy, \ + CR_VA_TAIL(CR_VA_TAIL(CR_VA_TAIL(__VA_ARGS__))) \ + )) + +# define cr_assert_any_throw_(Fail, Statement, ...) \ + try { \ + Statement; \ + CR_EXPAND(cr_assert_throw_abort_( \ + Fail, \ + CRITERION_ASSERT_MSG_ANY_THROW, \ + (CR_STR(Statement)), \ + __VA_ARGS__)); \ + } catch (...) {} + +# define cr_assert_any_throw_va_(...) \ + CR_EXPAND(cr_assert_any_throw_( \ + CR_VA_HEAD(__VA_ARGS__), \ + CR_VA_HEAD(CR_VA_TAIL(__VA_ARGS__)), \ + dummy, \ + CR_VA_TAIL(CR_VA_TAIL(__VA_ARGS__)) \ + )) + +# define cr_assert_none_throw_(Fail, Statement, ...) \ + try { \ + Statement; \ + } catch (...) { \ + CR_EXPAND(cr_assert_throw_abort_( \ + Fail, \ + CRITERION_ASSERT_MSG_NONE_THROW, \ + (CR_STR(Statement)), \ + __VA_ARGS__)); \ + } + +# define cr_assert_none_throw_va_(...) \ + CR_EXPAND(cr_assert_none_throw_( \ + CR_VA_HEAD(__VA_ARGS__), \ + CR_VA_HEAD(CR_VA_TAIL(__VA_ARGS__)), \ + dummy, \ + CR_VA_TAIL(CR_VA_TAIL(__VA_ARGS__)) \ + )) -# define cr_assert_str_leq(...) CR_EXPAND(cr_assert_str_op_va_(CR_FAIL_ABORT_, <=, __VA_ARGS__)) -# define cr_expect_str_leq(...) CR_EXPAND(cr_assert_str_op_va_(CR_FAIL_CONTINUES_, <=, __VA_ARGS__)) +// Messages -# define cr_assert_str_gt(...) CR_EXPAND(cr_assert_str_op_va_(CR_FAIL_ABORT_, >, __VA_ARGS__)) -# define cr_expect_str_gt(...) CR_EXPAND(cr_assert_str_op_va_(CR_FAIL_CONTINUES_, >, __VA_ARGS__)) +# define CRITERION_GNUC_WARN__(Msg) \ + _Pragma(#Msg) -# define cr_assert_str_geq(...) CR_EXPAND(cr_assert_str_op_va_(CR_FAIL_ABORT_, >=, __VA_ARGS__)) -# define cr_expect_str_geq(...) CR_EXPAND(cr_assert_str_op_va_(CR_FAIL_CONTINUES_, >=, __VA_ARGS__)) +# define CRITERION_GNUC_WARN_(Name) CRITERION_GNUC_WARN__( \ + message \ + "The `" #Name "` macro is only available on GNU C compilers." \ + ) -#endif /* !CRITERION_ASSERT_BASE_H_ */ +#endif /* !CRITERION_INTERNAL_ASSERT_H_ */ diff --git a/include/criterion/internal/test.h b/include/criterion/internal/test.h new file mode 100644 index 00000000..2b4e3d95 --- /dev/null +++ b/include/criterion/internal/test.h @@ -0,0 +1,97 @@ +/* + * The MIT License (MIT) + * + * Copyright © 2015 Franklin "Snaipe" Mathieu + * + * 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 CRITERION_INTERNAL_TEST_H_ +# define CRITERION_INTERNAL_TEST_H_ + +# include "designated-initializer-compat.h" +# include "common.h" + +# define CR_IDENTIFIER_(Category, Name, Suffix) \ + Category ## _ ## Name ## _ ## Suffix + +# ifdef __cplusplus +# ifdef __OBJC__ +# define CR_LANG CR_LANG_OBJCXX +# else +# define CR_LANG CR_LANG_CXX +# endif +# else +# ifdef __OBJC__ +# define CR_LANG CR_LANG_OBJC +# else +# define CR_LANG CR_LANG_C +# endif +# endif + +# ifdef __cplusplus +# define CR_TEST_PROTOTYPE_(Category, Name) \ + extern "C" void CR_IDENTIFIER_(Category, Name, impl)(void) +# else +# define CR_TEST_PROTOTYPE_(Category, Name) \ + void CR_IDENTIFIER_(Category, Name, impl)(void) +# endif + +# define CR_SUITE_IDENTIFIER_(Name, Suffix) \ + suite_ ## Name ## _ ## Suffix + +# define CR_TEST_BASE(Category, Name, ...) \ + CR_TEST_PROTOTYPE_(Category, Name); \ + struct criterion_test_extra_data CR_IDENTIFIER_(Category, Name, extra) = \ + CR_EXPAND(CRITERION_MAKE_STRUCT(struct criterion_test_extra_data, \ + .lang_ = CR_LANG, \ + .kind_ = CR_TEST_NORMAL, \ + .param_ = (struct criterion_test_params(*)(void)) NULL, \ + .identifier_ = #Category "/" #Name, \ + .file_ = __FILE__, \ + .line_ = __LINE__, \ + __VA_ARGS__ \ + )); \ + struct criterion_test CR_IDENTIFIER_(Category, Name, meta) = { \ + #Name, \ + #Category, \ + CR_IDENTIFIER_(Category, Name, impl), \ + &CR_IDENTIFIER_(Category, Name, extra) \ + }; \ + CR_SECTION_("cr_tst") \ + struct criterion_test *CR_IDENTIFIER_(Category, Name, ptr) \ + = &CR_IDENTIFIER_(Category, Name, meta) CR_SECTION_SUFFIX_; \ + CR_TEST_PROTOTYPE_(Category, Name) + +# define CR_SUITE_BASE(Name, ...) \ + struct criterion_test_extra_data CR_SUITE_IDENTIFIER_(Name, extra) = \ + CR_EXPAND(CRITERION_MAKE_STRUCT(struct criterion_test_extra_data, \ + .file_ = __FILE__, \ + .line_ = 0, \ + __VA_ARGS__ \ + )); \ + struct criterion_suite CR_SUITE_IDENTIFIER_(Name, meta) = { \ + #Name, \ + &CR_SUITE_IDENTIFIER_(Name, extra), \ + }; \ + CR_SECTION_("cr_sts") \ + struct criterion_suite *CR_SUITE_IDENTIFIER_(Name, ptr) \ + = &CR_SUITE_IDENTIFIER_(Name, meta) CR_SECTION_SUFFIX_ + + +#endif /* !CRITERION_INTERNAL_TEST_H_ */ diff --git a/include/criterion/theories.h b/include/criterion/theories.h index 3777ef7b..7472760d 100644 --- a/include/criterion/theories.h +++ b/include/criterion/theories.h @@ -122,7 +122,7 @@ CR_API void cr_theory_main(struct criterion_datapoints *dps, size_t datapoints, # define Theory(Args, ...) \ void CR_EXPAND(CR_VAARG_ID(theory, __VA_ARGS__,))Args; \ - CR_EXPAND(Test_(__VA_ARGS__, .sentinel_ = 0)) { \ + CR_EXPAND(CR_TEST_BASE(__VA_ARGS__, .sentinel_ = 0)) { \ cr_theory_main( \ CR_EXPAND(CR_VAARG_ID(dps, __VA_ARGS__,)), \ CR_NB_DATAPOINTS(CR_EXPAND(CR_VAARG_ID(dps, __VA_ARGS__,))), \ diff --git a/src/core/wrappers/wrap.cc b/src/core/wrappers/wrap.cc index e7f716ca..a5bc3eb1 100644 --- a/src/core/wrappers/wrap.cc +++ b/src/core/wrappers/wrap.cc @@ -22,13 +22,13 @@ * THE SOFTWARE. */ #include -#include "criterion/assert_base.h" #include "criterion/event.h" +#include "core/report.h" + extern "C" { #include "core/abort.h" -#include "core/report.h" #include "core/worker.h" #include "compat/time.h" #include "wrap.h" @@ -36,6 +36,10 @@ extern "C" { static INLINE void nothing(void) {} +void cxx_wrap(struct criterion_test *test, struct criterion_suite *suite); + +} + void cxx_wrap(struct criterion_test *test, struct criterion_suite *suite) { criterion_send_event(PRE_INIT, NULL, 0); @@ -86,5 +90,3 @@ void cxx_wrap(struct criterion_test *test, struct criterion_suite *suite) { criterion_send_event(POST_FINI, NULL, 0); } - -} From bbc5edfb340da3a682ba1ded9de74ac9790b30a6 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Tue, 17 Nov 2015 17:49:27 +0100 Subject: [PATCH 154/211] Refactored the implementation of theory macros in internal/ --- include/criterion/internal/theories.h | 71 +++++++++++++++++++++++++++ include/criterion/theories.h | 68 ++++--------------------- 2 files changed, 81 insertions(+), 58 deletions(-) create mode 100644 include/criterion/internal/theories.h diff --git a/include/criterion/internal/theories.h b/include/criterion/internal/theories.h new file mode 100644 index 00000000..a0176c89 --- /dev/null +++ b/include/criterion/internal/theories.h @@ -0,0 +1,71 @@ +#ifndef CRITERION_INTERNAL_THEORIES_H_ +# define CRITERION_INTERNAL_THEORIES_H_ + +# include "test.h" + +# ifdef __cplusplus +# include +using std::size_t; +# else +# include +# endif + +# ifdef __cplusplus +template +constexpr size_t criterion_va_num__(const T &...) { + return sizeof...(T); +} +# endif + +struct criterion_datapoints { + size_t size; + size_t len; + const char *name; + void *arr; +}; + +CR_BEGIN_C_API + +CR_API void cr_theory_main(struct criterion_datapoints *dps, size_t datapoints, void (*fnptr)(void)); + +CR_END_C_API + +# ifdef __cplusplus +# define CR_TH_VA_NUM(Type, ...) criterion_va_num__(__VA_ARGS__) +# define CR_TH_TEMP_ARRAY(Type, ...) []() { static Type arr[] = { __VA_ARGS__ }; return &arr; }() +# else +# define CR_TH_VA_NUM(Type, ...) sizeof ((Type[]) { __VA_ARGS__ }) / sizeof (Type) +# define CR_TH_TEMP_ARRAY(Type, ...) &(Type[]) { __VA_ARGS__ } +# endif + +# define CR_TH_INTERNAL_TDPS(Category, Name) \ + static struct criterion_datapoints CR_IDENTIFIER_(Category, Name, dps)[] + +# define CR_TH_INTERNAL_TDP(Category, Name) \ + (CR_IDENTIFIER_(Category, Name, dps)) + +# define CR_TH_INTERNAL_DP(Type, ...) { \ + sizeof (Type), \ + CR_EXPAND(CR_TH_VA_NUM(Type, __VA_ARGS__)), \ + #Type, \ + CR_EXPAND(CR_TH_TEMP_ARRAY(Type, __VA_ARGS__)), \ + } + +# define CR_NB_DATAPOINTS(Var) \ + (sizeof (Var) / sizeof (struct criterion_datapoints)) + +# define CR_VAARG_ID(Suffix, Category, Name, ...) \ + CR_IDENTIFIER_(Category, Name, Suffix) + +# define CR_THEORY_BASE(Args, ...) \ + void CR_EXPAND(CR_VAARG_ID(theory, __VA_ARGS__,))Args; \ + CR_EXPAND(CR_TEST_BASE(__VA_ARGS__, .sentinel_ = 0)) { \ + cr_theory_main( \ + CR_EXPAND(CR_VAARG_ID(dps, __VA_ARGS__,)), \ + CR_NB_DATAPOINTS(CR_EXPAND(CR_VAARG_ID(dps, __VA_ARGS__,))), \ + (void(*)(void)) CR_EXPAND(CR_VAARG_ID(theory, __VA_ARGS__,)) \ + ); \ + } \ + void CR_EXPAND(CR_VAARG_ID(theory, __VA_ARGS__,))Args + +#endif /* !CRITERION_INTERNAL_THEORIES_H_ */ diff --git a/include/criterion/theories.h b/include/criterion/theories.h index 7472760d..711e7b16 100644 --- a/include/criterion/theories.h +++ b/include/criterion/theories.h @@ -24,62 +24,30 @@ #ifndef CRITERION_THEORIES_H_ # define CRITERION_THEORIES_H_ -# ifdef __cplusplus -# include -using std::size_t; -# else -# include -# endif - # include "criterion.h" - -# ifdef __cplusplus -template -constexpr size_t criterion_va_num__(const T &...) { - return sizeof...(T); -} -# endif +# include "internal/theories.h" CR_BEGIN_C_API CR_API void cr_theory_abort(void); -# define TheoryDataPoints(Category, Name) \ - static struct criterion_datapoints CR_IDENTIFIER_(Category, Name, dps)[] +CR_END_C_API -# define TheoryDataPoint(Category, Name) \ - (CR_IDENTIFIER_(Category, Name, dps)) +// Theory and datapoint macros -# ifdef __cplusplus -# define CR_TH_VA_NUM(Type, ...) criterion_va_num__(__VA_ARGS__) -# define CR_TH_TEMP_ARRAY(Type, ...) []() { static Type arr[] = { __VA_ARGS__ }; return &arr; }() -# else -# define CR_TH_VA_NUM(Type, ...) sizeof ((Type[]) { __VA_ARGS__ }) / sizeof (Type) -# define CR_TH_TEMP_ARRAY(Type, ...) &(Type[]) { __VA_ARGS__ } -# endif +# define Theory(Args, ...) CR_EXPAND(CR_THEORY_BASE(Args, __VA_ARGS__)) -# define DataPoints(Type, ...) { \ - sizeof (Type), \ - CR_EXPAND(CR_TH_VA_NUM(Type, __VA_ARGS__)), \ - #Type, \ - CR_EXPAND(CR_TH_TEMP_ARRAY(Type, __VA_ARGS__)), \ - } +# define TheoryDataPoints(Category, Name) CR_TH_INTERNAL_TDPS(Category, Name) +# define TheoryDataPoint(Category, Name) CR_TH_INTERNAL_TDP(Category, Name) +# define DataPoints(Type, ...) CR_EXPAND(CR_TH_INTERNAL_DP(Type, __VA_ARGS__)) -struct criterion_datapoints { - size_t size; - size_t len; - const char *name; - void *arr; -}; - -# define CR_NB_DATAPOINTS(Var) \ - (sizeof (Var) / sizeof (struct criterion_datapoints)) +// Theory invariants # define cr_assume(Condition) \ do { \ if (!(Condition)) \ cr_theory_abort(); \ - } while (0); + } while (0) # define cr_assume_not(Condition) cr_assume(!(Condition)) @@ -115,23 +83,7 @@ struct criterion_datapoints { # define cr_assume_arr_eq(Actual, Expected, Size) cr_assume(!memcmp((A), (B), (Size))) # define cr_assume_arr_neq(Actual, Expected, Size) cr_assume(memcmp((A), (B), (Size))) -CR_API void cr_theory_main(struct criterion_datapoints *dps, size_t datapoints, void (*fnptr)(void)); - -# define CR_VAARG_ID(Suffix, Category, Name, ...) \ - CR_IDENTIFIER_(Category, Name, Suffix) - -# define Theory(Args, ...) \ - void CR_EXPAND(CR_VAARG_ID(theory, __VA_ARGS__,))Args; \ - CR_EXPAND(CR_TEST_BASE(__VA_ARGS__, .sentinel_ = 0)) { \ - cr_theory_main( \ - CR_EXPAND(CR_VAARG_ID(dps, __VA_ARGS__,)), \ - CR_NB_DATAPOINTS(CR_EXPAND(CR_VAARG_ID(dps, __VA_ARGS__,))), \ - (void(*)(void)) CR_EXPAND(CR_VAARG_ID(theory, __VA_ARGS__,)) \ - ); \ - } \ - void CR_EXPAND(CR_VAARG_ID(theory, __VA_ARGS__,))Args - -CR_END_C_API +// Deprecated # ifndef CRITERION_NO_COMPAT # define cr_assume_strings_eq(...) CRITERION_ASSERT_DEPRECATED_B(cr_assume_strings_eq, cr_assume_str_eq) cr_assume_str_eq(__VA_ARGS__) From 586f29128d305689fff68a66583ed9a81ce0e343 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Tue, 17 Nov 2015 18:24:44 +0100 Subject: [PATCH 155/211] Refactored the implementation of parameterized tests macros to internal/ --- include/criterion/internal/assert.h | 23 +++++++ include/criterion/internal/parameterized.h | 72 +++++++++++++++++++++ include/criterion/internal/theories.h | 23 +++++++ include/criterion/parameterized.h | 74 ++++++++-------------- 4 files changed, 146 insertions(+), 46 deletions(-) create mode 100644 include/criterion/internal/parameterized.h diff --git a/include/criterion/internal/assert.h b/include/criterion/internal/assert.h index 9b234172..426e3aef 100644 --- a/include/criterion/internal/assert.h +++ b/include/criterion/internal/assert.h @@ -1,3 +1,26 @@ +/* + * The MIT License (MIT) + * + * Copyright © 2015 Franklin "Snaipe" Mathieu + * + * 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 CRITERION_INTERNAL_ASSERT_H_ # define CRITERION_INTERNAL_ASSERT_H_ diff --git a/include/criterion/internal/parameterized.h b/include/criterion/internal/parameterized.h new file mode 100644 index 00000000..017a5990 --- /dev/null +++ b/include/criterion/internal/parameterized.h @@ -0,0 +1,72 @@ +/* + * The MIT License (MIT) + * + * Copyright © 2015 Franklin "Snaipe" Mathieu + * + * 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 CRITERION_INTERNAL_PARAMETERIZED_H_ +# define CRITERION_INTERNAL_PARAMETERIZED_H_ + +# include "test.h" +# include "../types.h" + +# ifdef __cplusplus +# define CR_PARAM_TEST_PROTOTYPE_(Param, Category, Name) \ + extern "C" void CR_IDENTIFIER_(Category, Name, impl)(Param) +# else +# define CR_PARAM_TEST_PROTOTYPE_(Param, Category, Name) \ + void CR_IDENTIFIER_(Category, Name, impl)(Param) +# endif + +# define CR_PARAM_TEST_BASE(Param, Category, Name, ...) \ + CR_PARAM_TEST_PROTOTYPE_(Param, Category, Name); \ + struct criterion_test_extra_data CR_IDENTIFIER_(Category, Name, extra) = \ + CR_EXPAND(CRITERION_MAKE_STRUCT(struct criterion_test_extra_data, \ + .lang_ = CR_LANG, \ + .kind_ = CR_TEST_PARAMETERIZED, \ + .param_ = CR_IDENTIFIER_(Category, Name, param), \ + .identifier_ = #Category "/" #Name, \ + .file_ = __FILE__, \ + .line_ = __LINE__, \ + __VA_ARGS__ \ + )); \ + struct criterion_test CR_IDENTIFIER_(Category, Name, meta) = { \ + #Name, \ + #Category, \ + (void(*)(void)) CR_IDENTIFIER_(Category, Name, impl), \ + &CR_IDENTIFIER_(Category, Name, extra) \ + }; \ + CR_SECTION_("cr_tst") \ + struct criterion_test *CR_IDENTIFIER_(Category, Name, ptr) \ + = &CR_IDENTIFIER_(Category, Name, meta) CR_SECTION_SUFFIX_; \ + CR_PARAM_TEST_PROTOTYPE_(Param, Category, Name) + +# define CR_PARAM_TEST_PARAMS(Category, Name) \ + static struct criterion_test_params CR_IDENTIFIER_(Category, Name, param)(void) + +# ifdef __cplusplus +# define cr_make_param_array(Type, Array, ...) \ + criterion_test_params(sizeof (Type), (Array), __VA_ARGS__) +# else +# define cr_make_param_array(Type, Array, ...) \ + (struct criterion_test_params) { .size = sizeof (Type), (void*)(Array), __VA_ARGS__ } +# endif + +#endif /* !CRITERION_INTERNAL_PARAMETERIZED_H_ */ diff --git a/include/criterion/internal/theories.h b/include/criterion/internal/theories.h index a0176c89..172d96df 100644 --- a/include/criterion/internal/theories.h +++ b/include/criterion/internal/theories.h @@ -1,3 +1,26 @@ +/* + * The MIT License (MIT) + * + * Copyright © 2015 Franklin "Snaipe" Mathieu + * + * 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 CRITERION_INTERNAL_THEORIES_H_ # define CRITERION_INTERNAL_THEORIES_H_ diff --git a/include/criterion/parameterized.h b/include/criterion/parameterized.h index 2c6d96ca..7099009a 100644 --- a/include/criterion/parameterized.h +++ b/include/criterion/parameterized.h @@ -1,58 +1,40 @@ +/* + * The MIT License (MIT) + * + * Copyright © 2015 Franklin "Snaipe" Mathieu + * + * 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 CRITERION_PARAMETERIZED_H_ # define CRITERION_PARAMETERIZED_H_ -# include "criterion.h" # include "alloc.h" -# ifdef __cplusplus -# include -# endif - -# ifdef __cplusplus -# define CR_PARAM_TEST_PROTOTYPE_(Param, Category, Name) \ - extern "C" void CR_IDENTIFIER_(Category, Name, impl)(Param) -# else -# define CR_PARAM_TEST_PROTOTYPE_(Param, Category, Name) \ - void CR_IDENTIFIER_(Category, Name, impl)(Param) -# endif - -# define ParameterizedTest(...) \ - CR_EXPAND(ParameterizedTest_(__VA_ARGS__, .sentinel_ = 0)) +# include "assert.h" +# include "internal/parameterized.h" -# define ParameterizedTest_(Param, Category, Name, ...) \ - CR_PARAM_TEST_PROTOTYPE_(Param, Category, Name); \ - struct criterion_test_extra_data CR_IDENTIFIER_(Category, Name, extra) = \ - CR_EXPAND(CRITERION_MAKE_STRUCT(struct criterion_test_extra_data, \ - .lang_ = CR_LANG, \ - .kind_ = CR_TEST_PARAMETERIZED, \ - .param_ = CR_IDENTIFIER_(Category, Name, param), \ - .identifier_ = #Category "/" #Name, \ - .file_ = __FILE__, \ - .line_ = __LINE__, \ - __VA_ARGS__ \ - )); \ - struct criterion_test CR_IDENTIFIER_(Category, Name, meta) = { \ - #Name, \ - #Category, \ - (void(*)(void)) CR_IDENTIFIER_(Category, Name, impl), \ - &CR_IDENTIFIER_(Category, Name, extra) \ - }; \ - CR_SECTION_("cr_tst") \ - struct criterion_test *CR_IDENTIFIER_(Category, Name, ptr) \ - = &CR_IDENTIFIER_(Category, Name, meta) CR_SECTION_SUFFIX_; \ - CR_PARAM_TEST_PROTOTYPE_(Param, Category, Name) +# define ParameterizedTest(...) CR_EXPAND(CR_PARAM_TEST_BASE(__VA_ARGS__, .sentinel_ = 0)) -# define ParameterizedTestParameters(Category, Name) \ - static struct criterion_test_params CR_IDENTIFIER_(Category, Name, param)(void) +# define ParameterizedTestParameters(Category, Name) CR_PARAM_TEST_PARAMS(Category, Name) # ifdef __cplusplus -# define cr_make_param_array(Type, Array, ...) \ - criterion_test_params(sizeof (Type), (Array), __VA_ARGS__) -# else -# define cr_make_param_array(Type, Array, ...) \ - (struct criterion_test_params) { .size = sizeof (Type), (void*)(Array), __VA_ARGS__ } -# endif +# include -# ifdef __cplusplus namespace criterion { template using parameters = std::vector>; From f656fb4279fb944179dd5b1d11086156c2d87175 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Wed, 18 Nov 2015 13:12:51 +0100 Subject: [PATCH 156/211] Added missing header files in cmake install files --- CMakeLists.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 75cb3fe2..21e630e8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -211,6 +211,8 @@ set(INTERFACE_FILES include/criterion/internal/asprintf-compat.h include/criterion/internal/designated-initializer-compat.h include/criterion/internal/preprocess.h + include/criterion/internal/theories.h + include/criterion/internal/parameterized.h ) # Generate the configure file From eb3695902374834dc31bc3ad7eb13d436e9e90da Mon Sep 17 00:00:00 2001 From: Snaipe Date: Wed, 18 Nov 2015 13:20:03 +0100 Subject: [PATCH 157/211] Fixed cmake header file installation flattening include subdirectories --- CMakeLists.txt | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 21e630e8..8c70e05f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -247,7 +247,11 @@ if (COVERALLS) coveralls_setup("${SOURCE_FILES}" ${COVERALLS_UPLOAD}) endif() -install(FILES ${INTERFACE_FILES} DESTINATION include/criterion) +foreach (F ${INTERFACE_FILES}) + get_filename_component(DEST "${F}" DIRECTORY) + install(FILES "${F}" DESTINATION "${DEST}") +endforeach () + install(TARGETS criterion RUNTIME DESTINATION bin LIBRARY DESTINATION lib From 221df82a12b97ce86a30733da8c695b2783fb575 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Wed, 18 Nov 2015 14:00:17 +0100 Subject: [PATCH 158/211] Changed DIRECTORY to PATH in get_filename_component for cmake <2.8.12 compatibility --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 8c70e05f..fdf73aa7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -248,7 +248,7 @@ if (COVERALLS) endif() foreach (F ${INTERFACE_FILES}) - get_filename_component(DEST "${F}" DIRECTORY) + get_filename_component(DEST "${F}" PATH) install(FILES "${F}" DESTINATION "${DEST}") endforeach () From a7d5ecf69c3df4fbff4c1d83d9c525b33e66bb63 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Wed, 18 Nov 2015 16:31:31 +0100 Subject: [PATCH 159/211] Refactored redirections and hooks --- .gitignore | 1 + CMakeLists.txt | 5 + include/criterion/hooks.h | 56 +--- include/criterion/internal/hooks.h | 84 ++++++ include/criterion/internal/redirect.h | 48 ++++ include/criterion/internal/stdio_filebuf.hxx | 138 +++++++++ include/criterion/internal/stream.hxx | 114 ++++++++ include/criterion/redirect.h | 286 +------------------ 8 files changed, 401 insertions(+), 331 deletions(-) create mode 100644 include/criterion/internal/hooks.h create mode 100644 include/criterion/internal/redirect.h create mode 100644 include/criterion/internal/stdio_filebuf.hxx create mode 100644 include/criterion/internal/stream.hxx diff --git a/.gitignore b/.gitignore index 94a86952..007b88d8 100644 --- a/.gitignore +++ b/.gitignore @@ -13,6 +13,7 @@ !*.m !*.cc !*.h +!*.hxx !*.rst !*.po !*.in diff --git a/CMakeLists.txt b/CMakeLists.txt index fdf73aa7..6ea2b7ac 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -213,6 +213,11 @@ set(INTERFACE_FILES include/criterion/internal/preprocess.h include/criterion/internal/theories.h include/criterion/internal/parameterized.h + include/criterion/internal/stdio_filebuf.hxx + include/criterion/internal/stream.hxx + include/criterion/internal/hooks.h + include/criterion/internal/redirect.h + include/criterion/internal/stdio_filebuf.hxx ) # Generate the configure file diff --git a/include/criterion/hooks.h b/include/criterion/hooks.h index 5f622b2a..a7559c60 100644 --- a/include/criterion/hooks.h +++ b/include/criterion/hooks.h @@ -24,8 +24,7 @@ #ifndef CRITERION_HOOKS_H_ # define CRITERION_HOOKS_H_ -# include "internal/common.h" -# include "types.h" +# include "internal/hooks.h" typedef enum { PRE_ALL, @@ -43,57 +42,6 @@ typedef enum { typedef void (*f_report_hook)(); -# define CR_HOOK_IDENTIFIER_(Suffix) CR_HOOK_IDENTIFIER__(__LINE__, Suffix) -# define CR_HOOK_IDENTIFIER__(Line, Suffix) CR_HOOK_IDENTIFIER___(Line, Suffix) -# define CR_HOOK_IDENTIFIER___(Line, Suffix) hook_l ## Line ## _ ## Suffix - -# ifdef __cplusplus -# define CR_HOOK_PROTOTYPE_ \ - extern "C" void CR_HOOK_IDENTIFIER_(impl) -# else -# define CR_HOOK_PROTOTYPE_ \ - void CR_HOOK_IDENTIFIER_(impl) -# endif - -// Section abbreviations -# define CR_HOOK_SECTION_PRE_ALL cr_pra -# define CR_HOOK_SECTION_PRE_SUITE cr_prs -# define CR_HOOK_SECTION_PRE_INIT cr_pri -# define CR_HOOK_SECTION_PRE_TEST cr_prt -# define CR_HOOK_SECTION_ASSERT cr_ast -# define CR_HOOK_SECTION_THEORY_FAIL cr_thf -# define CR_HOOK_SECTION_TEST_CRASH cr_tsc -# define CR_HOOK_SECTION_POST_TEST cr_pot -# define CR_HOOK_SECTION_POST_FINI cr_pof -# define CR_HOOK_SECTION_POST_SUITE cr_pos -# define CR_HOOK_SECTION_POST_ALL cr_poa - -# define CR_HOOK_SECTION(Kind) CR_HOOK_SECTION_ ## Kind - -# define CR_HOOK_SECTION_STRINGIFY__(Sec) #Sec -# define CR_HOOK_SECTION_STRINGIFY_(Sec) CR_HOOK_SECTION_STRINGIFY__(Sec) -# define CR_HOOK_SECTION_STRINGIFY(Kind) CR_HOOK_SECTION_STRINGIFY_(CR_HOOK_SECTION(Kind)) - -# define CR_HOOK_PARAM_TYPE_PRE_ALL struct criterion_test_set * -# define CR_HOOK_PARAM_TYPE_PRE_SUITE struct criterion_suite_set * -# define CR_HOOK_PARAM_TYPE_PRE_INIT struct criterion_test * -# define CR_HOOK_PARAM_TYPE_PRE_TEST struct criterion_test * -# define CR_HOOK_PARAM_TYPE_ASSERT struct criterion_assert_stats * -# define CR_HOOK_PARAM_TYPE_THEORY_FAIL struct criterion_theory_stats * -# define CR_HOOK_PARAM_TYPE_TEST_CRASH struct criterion_test_stats * -# define CR_HOOK_PARAM_TYPE_POST_TEST struct criterion_test_stats * -# define CR_HOOK_PARAM_TYPE_POST_FINI struct criterion_test_stats * -# define CR_HOOK_PARAM_TYPE_POST_SUITE struct criterion_suite_stats * -# define CR_HOOK_PARAM_TYPE_POST_ALL struct criterion_global_stats * - -# define CR_HOOK_PARAM_TYPE(Kind) CR_HOOK_PARAM_TYPE_ ## Kind - -# define ReportHook(Kind) \ - CR_HOOK_PROTOTYPE_(CR_HOOK_PARAM_TYPE(Kind)); \ - CR_SECTION_(CR_HOOK_SECTION_STRINGIFY(Kind)) \ - f_report_hook CR_HOOK_IDENTIFIER_(func) = \ - (f_report_hook) CR_HOOK_IDENTIFIER_(impl) \ - CR_SECTION_SUFFIX_; \ - CR_HOOK_PROTOTYPE_ +# define ReportHook(Kind) CR_REPORT_HOOK_IMPL(Kind) #endif /* !CRITERION_HOOKS_H_ */ diff --git a/include/criterion/internal/hooks.h b/include/criterion/internal/hooks.h new file mode 100644 index 00000000..cf33de53 --- /dev/null +++ b/include/criterion/internal/hooks.h @@ -0,0 +1,84 @@ +/* + * The MIT License (MIT) + * + * Copyright © 2015 Franklin "Snaipe" Mathieu + * + * 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 CRITERION_INTERNAL_HOOKS_H_ +# define CRITERION_INTERNAL_HOOKS_H_ + +# include "common.h" +# include "../types.h" + +# define CR_HOOK_IDENTIFIER_(Suffix) CR_HOOK_IDENTIFIER__(__LINE__, Suffix) +# define CR_HOOK_IDENTIFIER__(Line, Suffix) CR_HOOK_IDENTIFIER___(Line, Suffix) +# define CR_HOOK_IDENTIFIER___(Line, Suffix) hook_l ## Line ## _ ## Suffix + +# ifdef __cplusplus +# define CR_HOOK_PROTOTYPE_ \ + extern "C" void CR_HOOK_IDENTIFIER_(impl) +# else +# define CR_HOOK_PROTOTYPE_ \ + void CR_HOOK_IDENTIFIER_(impl) +# endif + +// Section abbreviations +# define CR_HOOK_SECTION_PRE_ALL cr_pra +# define CR_HOOK_SECTION_PRE_SUITE cr_prs +# define CR_HOOK_SECTION_PRE_INIT cr_pri +# define CR_HOOK_SECTION_PRE_TEST cr_prt +# define CR_HOOK_SECTION_ASSERT cr_ast +# define CR_HOOK_SECTION_THEORY_FAIL cr_thf +# define CR_HOOK_SECTION_TEST_CRASH cr_tsc +# define CR_HOOK_SECTION_POST_TEST cr_pot +# define CR_HOOK_SECTION_POST_FINI cr_pof +# define CR_HOOK_SECTION_POST_SUITE cr_pos +# define CR_HOOK_SECTION_POST_ALL cr_poa + +# define CR_HOOK_SECTION(Kind) CR_HOOK_SECTION_ ## Kind + +# define CR_HOOK_SECTION_STRINGIFY__(Sec) #Sec +# define CR_HOOK_SECTION_STRINGIFY_(Sec) CR_HOOK_SECTION_STRINGIFY__(Sec) +# define CR_HOOK_SECTION_STRINGIFY(Kind) CR_HOOK_SECTION_STRINGIFY_(CR_HOOK_SECTION(Kind)) + +# define CR_HOOK_PARAM_TYPE_PRE_ALL struct criterion_test_set * +# define CR_HOOK_PARAM_TYPE_PRE_SUITE struct criterion_suite_set * +# define CR_HOOK_PARAM_TYPE_PRE_INIT struct criterion_test * +# define CR_HOOK_PARAM_TYPE_PRE_TEST struct criterion_test * +# define CR_HOOK_PARAM_TYPE_ASSERT struct criterion_assert_stats * +# define CR_HOOK_PARAM_TYPE_THEORY_FAIL struct criterion_theory_stats * +# define CR_HOOK_PARAM_TYPE_TEST_CRASH struct criterion_test_stats * +# define CR_HOOK_PARAM_TYPE_POST_TEST struct criterion_test_stats * +# define CR_HOOK_PARAM_TYPE_POST_FINI struct criterion_test_stats * +# define CR_HOOK_PARAM_TYPE_POST_SUITE struct criterion_suite_stats * +# define CR_HOOK_PARAM_TYPE_POST_ALL struct criterion_global_stats * + +# define CR_HOOK_PARAM_TYPE(Kind) CR_HOOK_PARAM_TYPE_ ## Kind + +# define CR_REPORT_HOOK_IMPL(Kind) \ + CR_HOOK_PROTOTYPE_(CR_HOOK_PARAM_TYPE(Kind)); \ + CR_SECTION_(CR_HOOK_SECTION_STRINGIFY(Kind)) \ + f_report_hook CR_HOOK_IDENTIFIER_(func) = \ + (f_report_hook) CR_HOOK_IDENTIFIER_(impl) \ + CR_SECTION_SUFFIX_; \ + CR_HOOK_PROTOTYPE_ + + +#endif /* !CRITERION_INTERNAL_HOOKS_H_ */ diff --git a/include/criterion/internal/redirect.h b/include/criterion/internal/redirect.h new file mode 100644 index 00000000..64c003b7 --- /dev/null +++ b/include/criterion/internal/redirect.h @@ -0,0 +1,48 @@ +#ifndef CRITERION_INTERNAL_REDIRECT_H_ +# define CRITERION_INTERNAL_REDIRECT_H_ + +# include "common.h" +# include "assert.h" + +# define cr_assert_redir_op_(Fail, Fun, Op, File, Str, ...) \ + CR_EXPAND(cr_assert_impl( \ + Fail, \ + !(Fun((File), (Str)) Op 0), \ + dummy, \ + CRITERION_ASSERT_MSG_FILE_STR_MATCH, \ + (CR_STR(File), Str), \ + __VA_ARGS__ \ + )) + +# define cr_assert_redir_op_va_(Fail, Fun, Op, ...) \ + CR_EXPAND(cr_assert_redir_op_( \ + Fail, \ + Fun, \ + Op, \ + CR_VA_HEAD(__VA_ARGS__), \ + CR_VA_HEAD(CR_VA_TAIL(__VA_ARGS__)), \ + CR_VA_TAIL(CR_VA_TAIL(__VA_ARGS__)) \ + )) + +# define cr_assert_redir_f_op_(Fail, Fun, Op, File, Ref, ...) \ + CR_EXPAND(cr_assert_impl( \ + Fail, \ + !(Fun((File), (Ref)) Op 0), \ + dummy, \ + CRITERION_ASSERT_MSG_FILE_MATCH, \ + (CR_STR(File), CR_STR(Ref)), \ + __VA_ARGS__ \ + )) + +# define cr_assert_redir_f_op_va_(Fail, Fun, Op, ...) \ + CR_EXPAND(cr_assert_redir_op_( \ + Fail, \ + Fun, \ + Op, \ + CR_VA_HEAD(__VA_ARGS__), \ + CR_VA_HEAD(CR_VA_TAIL(__VA_ARGS__)), \ + CR_VA_TAIL(CR_VA_TAIL(__VA_ARGS__)) \ + )) + + +#endif /* !CRITERION_INTERNAL_REDIRECT_H_ */ diff --git a/include/criterion/internal/stdio_filebuf.hxx b/include/criterion/internal/stdio_filebuf.hxx new file mode 100644 index 00000000..0cb53d7c --- /dev/null +++ b/include/criterion/internal/stdio_filebuf.hxx @@ -0,0 +1,138 @@ +#ifndef CRITERION_INTERNAL_STDIO_FILEBUF_HXX_ +# define CRITERION_INTERNAL_STDIO_FILEBUF_HXX_ + +# include + +namespace criterion { namespace internal { + + template > + class stdio_sync_filebuf : public std::basic_streambuf { + public: + typedef Traits traits; + typedef std::basic_filebuf super; + typedef typename Traits::int_type int_type; + typedef typename Traits::pos_type pos_type; + typedef typename Traits::off_type off_type; + + stdio_sync_filebuf(std::FILE *file) + : file(file) + , lastchar(Traits::eof()) + {} + + stdio_sync_filebuf(stdio_sync_filebuf&& other) = default; + stdio_sync_filebuf& operator=(stdio_sync_filebuf&& other) = default; + + void swap(stdio_sync_filebuf& other) { + super::swap(other); + std::swap(file, other.file); + std::swap(lastchar, other.lastchar); + } + + protected: + int_type syncgetc(); + int_type syncungetc(int_type); + int_type syncputc(int_type); + + virtual std::streampos seekoff(std::streamoff off, + std::ios_base::seekdir dir, + std::ios_base::openmode = std::ios_base::in | std::ios_base::out) { + + int whence; + if (dir == std::ios_base::beg) + whence = SEEK_SET; + else if (dir == std::ios_base::cur) + whence = SEEK_CUR; + else + whence = SEEK_END; + + if (!fseek(file, off, whence)) + return std::streampos(std::ftell(file)); + return std::streamoff(-1); + } + + virtual std::streampos seekpos(std::streampos pos, + std::ios_base::openmode mode = std::ios_base::in | std::ios_base::out) { + return seekoff(std::streamoff(pos), std::ios_base::beg, mode); + } + + virtual std::streamsize xsgetn(CharT* s, std::streamsize n); + virtual std::streamsize xsputn(const CharT* s, std::streamsize n); + + virtual int sync() { + return std::fflush(file); + } + + virtual int_type underflow() { + int_type c = syncgetc(); + return syncungetc(c); + } + + virtual int_type uflow() { + return lastchar = syncgetc(); + } + + static inline bool is_eof(int_type c) { + static const int_type eof = Traits::eof(); + return Traits::eq_int_type(c, eof); + } + + virtual int_type overflow(int_type c = Traits::eof()) { + int_type ret; + if (is_eof(c)) { + if (std::fflush(file)) + ret = Traits::eof(); + else + ret = Traits::not_eof(c); + } else { + ret = syncputc(c); + } + return ret; + } + + virtual int_type pbackfail(int_type c = Traits::eof()) { + int_type ret = syncungetc(is_eof(c) && !is_eof(lastchar) ? lastchar : c); + lastchar = Traits::eof(); + return ret; + } + + private: + std::FILE *file; + bool file_open; + int_type lastchar; + }; + + template <> + inline stdio_sync_filebuf::int_type + stdio_sync_filebuf::syncgetc() { + return std::getc(file); + } + + template <> + inline stdio_sync_filebuf::int_type + stdio_sync_filebuf::syncungetc(stdio_sync_filebuf::int_type c) { + return std::ungetc(c, file); + } + + template <> + inline stdio_sync_filebuf::int_type + stdio_sync_filebuf::syncputc(stdio_sync_filebuf::int_type c) { + return std::putc(c, file); + } + + template <> + inline std::streamsize + stdio_sync_filebuf::xsgetn(char *s, std::streamsize n) { + std::streamsize res = std::fread(s, 1, n, file); + lastchar = res > 0 ? traits::to_int_type(s[res - 1]) : traits::eof(); + return res; + } + + template <> + inline std::streamsize + stdio_sync_filebuf::xsputn(const char *s, std::streamsize n) { + return std::fwrite(s, 1, n, file); + } + +}} + +#endif /* !CRITERION_INTERNAL_STDIO_FILEBUF_HXX_ */ diff --git a/include/criterion/internal/stream.hxx b/include/criterion/internal/stream.hxx new file mode 100644 index 00000000..d8c5a087 --- /dev/null +++ b/include/criterion/internal/stream.hxx @@ -0,0 +1,114 @@ +#ifndef CRITERION_INTERNAL_STREAM_HXX_ +# define CRITERION_INTERNAL_STREAM_HXX_ + +# include +# include +# include + +# include "stdio_filebuf.hxx" + +namespace criterion { namespace internal { + + template + class stream_mixin : public Super { +public: + stream_mixin(FILE* f) + : Super() + , fbuf(new stdio_sync_filebuf(f)) + , file(f) + { + std::ios::rdbuf(&*fbuf); + } + + stream_mixin(const stream_mixin& other) = delete; + stream_mixin& operator=(const stream_mixin& other) = delete; + + stream_mixin(stream_mixin&& other) : + fbuf(std::move(other.fbuf)), + file(std::move(other.file)) + {} + + stream_mixin& operator=(stream_mixin&& other) { + fbuf = std::move(other.fbuf); + file = std::move(other.file); + } + + void close(void) { + Super::flush(); + Super::close(); + std::fclose(file); + } + + private: + std::shared_ptr> fbuf; + std::FILE* file; + }; + + template + using ofstream_mixin = stream_mixin>; + + template + using ifstream_mixin = stream_mixin>; + + template + using fstream_mixin = stream_mixin>; + + template + class basic_ofstream : public ofstream_mixin { + public: + basic_ofstream(FILE* f) + : ofstream_mixin(f) + {} + + basic_ofstream(basic_ofstream&& other) + : ofstream_mixin(std::move(other)) + {} + }; + + template + class basic_ifstream : public ifstream_mixin { + public: + basic_ifstream(FILE* f) + : ifstream_mixin(f) + {} + + basic_ifstream(basic_ifstream&& other) + : ifstream_mixin(std::move(other)) + {} + }; + + template + class basic_fstream : public fstream_mixin { + public: + basic_fstream(FILE* f) + : fstream_mixin(f) + {} + + basic_fstream(basic_fstream&& other) + : fstream_mixin(std::move(other)) + {} + }; + + struct get_redirected_out_stream_ { + static inline basic_ofstream& call(std::FILE* f) { + static std::unique_ptr> stream; + + if (!stream) + stream.reset(new basic_ofstream(f)); + return *stream; + } + + }; + + struct get_redirected_in_stream_ { + static inline basic_ifstream& call(std::FILE* f) { + static std::unique_ptr> stream; + if (!stream) + stream.reset(new basic_ifstream(f)); + return *stream; + } + }; + +}} + +#endif /* !CRITERION_INTERNAL_STREAM_HXX_ */ diff --git a/include/criterion/redirect.h b/include/criterion/redirect.h index c00f42f9..6fd5f588 100644 --- a/include/criterion/redirect.h +++ b/include/criterion/redirect.h @@ -25,12 +25,10 @@ # define CRITERION_REDIRECT_H_ # include "internal/common.h" -# include "assert.h" +# include "internal/redirect.h" # ifdef __cplusplus # include -# include -# include # else # include # endif @@ -52,46 +50,6 @@ CR_API CR_STDN FILE *cr_mock_file_size(size_t max_size); CR_END_C_API -# define cr_assert_redir_op_(Fail, Fun, Op, File, Str, ...) \ - CR_EXPAND(cr_assert_impl( \ - Fail, \ - !(Fun((File), (Str)) Op 0), \ - dummy, \ - CRITERION_ASSERT_MSG_FILE_STR_MATCH, \ - (CR_STR(File), Str), \ - __VA_ARGS__ \ - )) - -# define cr_assert_redir_op_va_(Fail, Fun, Op, ...) \ - CR_EXPAND(cr_assert_redir_op_( \ - Fail, \ - Fun, \ - Op, \ - CR_VA_HEAD(__VA_ARGS__), \ - CR_VA_HEAD(CR_VA_TAIL(__VA_ARGS__)), \ - CR_VA_TAIL(CR_VA_TAIL(__VA_ARGS__)) \ - )) - -# define cr_assert_redir_f_op_(Fail, Fun, Op, File, Ref, ...) \ - CR_EXPAND(cr_assert_impl( \ - Fail, \ - !(Fun((File), (Ref)) Op 0), \ - dummy, \ - CRITERION_ASSERT_MSG_FILE_MATCH, \ - (CR_STR(File), CR_STR(Ref)), \ - __VA_ARGS__ \ - )) - -# define cr_assert_redir_f_op_va_(Fail, Fun, Op, ...) \ - CR_EXPAND(cr_assert_redir_op_( \ - Fail, \ - Fun, \ - Op, \ - CR_VA_HEAD(__VA_ARGS__), \ - CR_VA_HEAD(CR_VA_TAIL(__VA_ARGS__)), \ - CR_VA_TAIL(CR_VA_TAIL(__VA_ARGS__)) \ - )) - # define cr_assert_file_contents_eq_str(...) CR_EXPAND(cr_assert_redir_op_va_(CR_FAIL_ABORT_, cr_file_match_str, ==, __VA_ARGS__)) # define cr_expect_file_contents_eq_str(...) CR_EXPAND(cr_assert_redir_op_va_(CR_FAIL_CONTINUES_, cr_file_match_str, ==, __VA_ARGS__)) @@ -129,250 +87,24 @@ CR_END_C_API # define cr_expect_stderr_neq(...) CR_EXPAND(cr_assert_redir_f_op_va_(CR_FAIL_CONTINUES_, cr_file_match_file, !=, cr_get_redirected_stderr(), __VA_ARGS__)) # ifdef __cplusplus -namespace criterion { - - template > - class stdio_sync_filebuf : public std::basic_streambuf { - public: - typedef Traits traits; - typedef std::basic_filebuf super; - typedef typename Traits::int_type int_type; - typedef typename Traits::pos_type pos_type; - typedef typename Traits::off_type off_type; - - stdio_sync_filebuf(std::FILE *file) - : file(file) - , lastchar(Traits::eof()) - {} - - stdio_sync_filebuf(stdio_sync_filebuf&& other) = default; - stdio_sync_filebuf& operator=(stdio_sync_filebuf&& other) = default; - - void swap(stdio_sync_filebuf& other) { - super::swap(other); - std::swap(file, other.file); - std::swap(lastchar, other.lastchar); - } - - protected: - int_type syncgetc(); - int_type syncungetc(int_type); - int_type syncputc(int_type); - - virtual std::streampos seekoff(std::streamoff off, - std::ios_base::seekdir dir, - std::ios_base::openmode = std::ios_base::in | std::ios_base::out) { - - int whence; - if (dir == std::ios_base::beg) - whence = SEEK_SET; - else if (dir == std::ios_base::cur) - whence = SEEK_CUR; - else - whence = SEEK_END; - - if (!fseek(file, off, whence)) - return std::streampos(std::ftell(file)); - return std::streamoff(-1); - } - - virtual std::streampos seekpos(std::streampos pos, - std::ios_base::openmode mode = std::ios_base::in | std::ios_base::out) { - return seekoff(std::streamoff(pos), std::ios_base::beg, mode); - } - - virtual std::streamsize xsgetn(CharT* s, std::streamsize n); - virtual std::streamsize xsputn(const CharT* s, std::streamsize n); - - virtual int sync() { - return std::fflush(file); - } - - virtual int_type underflow() { - int_type c = syncgetc(); - return syncungetc(c); - } - - virtual int_type uflow() { - return lastchar = syncgetc(); - } - - static inline bool is_eof(int_type c) { - static const int_type eof = Traits::eof(); - return Traits::eq_int_type(c, eof); - } - - virtual int_type overflow(int_type c = Traits::eof()) { - int_type ret; - if (is_eof(c)) { - if (std::fflush(file)) - ret = Traits::eof(); - else - ret = Traits::not_eof(c); - } else { - ret = syncputc(c); - } - return ret; - } - - virtual int_type pbackfail(int_type c = Traits::eof()) { - int_type ret = syncungetc(is_eof(c) && !is_eof(lastchar) ? lastchar : c); - lastchar = Traits::eof(); - return ret; - } - - private: - std::FILE *file; - bool file_open; - int_type lastchar; - }; - - template <> - inline stdio_sync_filebuf::int_type - stdio_sync_filebuf::syncgetc() { - return std::getc(file); - } - - template <> - inline stdio_sync_filebuf::int_type - stdio_sync_filebuf::syncungetc(stdio_sync_filebuf::int_type c) { - return std::ungetc(c, file); - } +# include "internal/stream.hxx" - template <> - inline stdio_sync_filebuf::int_type - stdio_sync_filebuf::syncputc(stdio_sync_filebuf::int_type c) { - return std::putc(c, file); - } - - template <> - inline std::streamsize - stdio_sync_filebuf::xsgetn(char *s, std::streamsize n) { - std::streamsize res = std::fread(s, 1, n, file); - lastchar = res > 0 ? traits::to_int_type(s[res - 1]) : traits::eof(); - return res; - } - - template <> - inline std::streamsize - stdio_sync_filebuf::xsputn(const char *s, std::streamsize n) { - return std::fwrite(s, 1, n, file); - } - - template - class stream_mixin : public Super { -public: - stream_mixin(FILE* f) - : Super() - , fbuf(new stdio_sync_filebuf(f)) - , file(f) - { - std::ios::rdbuf(&*fbuf); - } - - stream_mixin(const stream_mixin& other) = delete; - stream_mixin& operator=(const stream_mixin& other) = delete; - - stream_mixin(stream_mixin&& other) : - fbuf(std::move(other.fbuf)), - file(std::move(other.file)) - {} - - stream_mixin& operator=(stream_mixin&& other) { - fbuf = std::move(other.fbuf); - file = std::move(other.file); - } - - void close(void) { - Super::flush(); - Super::close(); - std::fclose(file); - } - - private: - std::shared_ptr> fbuf; - std::FILE* file; - }; - - template - using ofstream_mixin = stream_mixin>; - - template - using ifstream_mixin = stream_mixin>; - - template - using fstream_mixin = stream_mixin>; - - template - class basic_ofstream : public ofstream_mixin { - public: - basic_ofstream(FILE* f) - : ofstream_mixin(f) - {} - - basic_ofstream(basic_ofstream&& other) - : ofstream_mixin(std::move(other)) - {} - }; - - template - class basic_ifstream : public ifstream_mixin { - public: - basic_ifstream(FILE* f) - : ifstream_mixin(f) - {} - - basic_ifstream(basic_ifstream&& other) - : ifstream_mixin(std::move(other)) - {} - }; - - template - class basic_fstream : public fstream_mixin { - public: - basic_fstream(FILE* f) - : fstream_mixin(f) - {} - - basic_fstream(basic_fstream&& other) - : fstream_mixin(std::move(other)) - {} - }; - - using ofstream = basic_ofstream; - using ifstream = basic_ifstream; - using fstream = basic_fstream; - - struct get_redirected_out_stream_ { - static inline ofstream& call(std::FILE* f) { - static std::unique_ptr stream; - - if (!stream) - stream.reset(new ofstream(f)); - return *stream; - } - - }; +namespace criterion { - struct get_redirected_in_stream_ { - static inline ifstream& call(std::FILE* f) { - static std::unique_ptr stream; - if (!stream) - stream.reset(new ifstream(f)); - return *stream; - } - }; + using ofstream = internal::basic_ofstream; + using ifstream = internal::basic_ifstream; + using fstream = internal::basic_fstream; static inline ofstream& get_redirected_cin(void) { - return get_redirected_out_stream_::call(cr_get_redirected_stdin()); + return internal::get_redirected_out_stream_::call(cr_get_redirected_stdin()); } static inline ifstream& get_redirected_cout(void) { - return get_redirected_in_stream_::call(cr_get_redirected_stdout()); + return internal::get_redirected_in_stream_::call(cr_get_redirected_stdout()); } static inline ifstream& get_redirected_cerr(void) { - return get_redirected_in_stream_::call(cr_get_redirected_stderr()); + return internal::get_redirected_in_stream_::call(cr_get_redirected_stderr()); } # if __GNUC__ >= 5 From cb9d702f06dbd15e703881ffc1e42cc39d197001 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Thu, 19 Nov 2015 02:13:09 +0100 Subject: [PATCH 160/211] [Issue #77] Fixed msgmerge being called with --lang on versions <=0.17 by cmake. --- .cmake/Modules/GettextTranslate.cmake | 28 +++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/.cmake/Modules/GettextTranslate.cmake b/.cmake/Modules/GettextTranslate.cmake index 553b13d1..02307ff0 100644 --- a/.cmake/Modules/GettextTranslate.cmake +++ b/.cmake/Modules/GettextTranslate.cmake @@ -252,13 +252,29 @@ macro(GettextTranslate) else() - add_custom_target(${PO_TARGET} - COMMAND ${GettextTranslate_MSGMERGE_EXECUTABLE} --lang=${lang} - ${PO_FILE_NAME} ${TEMPLATE_FILE_ABS} - -o ${PO_FILE_NAME}.new - COMMAND mv ${PO_FILE_NAME}.new ${PO_FILE_NAME} - DEPENDS ${TEMPLATE_FILE_ABS} + execute_process( + COMMAND ${GettextTranslate_MSGMERGE_EXECUTABLE} --version + OUTPUT_VARIABLE MSGMERGE_VERSION_MSG ) + string(REGEX MATCH "[0-9]+\\.[0-9]+(\\.[0-9]+)?" MSGMERGE_VERSION "${MSGMERGE_VERSION_MSG}") + + if ("${MSGMERGE_VERSION}" VERSION_GREATER "0.17") + add_custom_target(${PO_TARGET} + COMMAND ${GettextTranslate_MSGMERGE_EXECUTABLE} --lang=${lang} + ${PO_FILE_NAME} ${TEMPLATE_FILE_ABS} + -o ${PO_FILE_NAME}.new + COMMAND mv ${PO_FILE_NAME}.new ${PO_FILE_NAME} + DEPENDS ${TEMPLATE_FILE_ABS} + ) + else () + add_custom_target(${PO_TARGET} + COMMAND ${GettextTranslate_MSGMERGE_EXECUTABLE} + ${PO_FILE_NAME} ${TEMPLATE_FILE_ABS} + -o ${PO_FILE_NAME}.new + COMMAND mv ${PO_FILE_NAME}.new ${PO_FILE_NAME} + DEPENDS ${TEMPLATE_FILE_ABS} + ) + endif () endif() From eeb7ab24f3a87c0a8b9470c7b23c6791c74dbd12 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Thu, 19 Nov 2015 14:32:24 +0100 Subject: [PATCH 161/211] Fixed list formatting for supported compilers in documentation --- doc/setup.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/setup.rst b/doc/setup.rst index b4001e2b..f5f4c2d3 100644 --- a/doc/setup.rst +++ b/doc/setup.rst @@ -7,6 +7,7 @@ Prerequisites The library is supported on Linux, OS X, FreeBSD, and Windows. The following compilers are supported to compile both the library and the tests: + * GCC 4.9+ * Clang 3.4+ * MSVC 14+ (Included in Visual Studio 2015 or later) From 2fbf8e8f1d7b092b77c9de939391644d780c5aa2 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Fri, 20 Nov 2015 18:49:48 +0100 Subject: [PATCH 162/211] Updated libcsptr for icc compilation --- dependencies/libcsptr | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencies/libcsptr b/dependencies/libcsptr index 2762164a..0d52904d 160000 --- a/dependencies/libcsptr +++ b/dependencies/libcsptr @@ -1 +1 @@ -Subproject commit 2762164acfaa712fea7dec6ed760ff88f7d2e026 +Subproject commit 0d52904da5d7bd0a3eac3c47e9f9bb10cd78a26e From 80a45b5eccf1fdacbc823d5e7c75f41612f8203a Mon Sep 17 00:00:00 2001 From: Snaipe Date: Fri, 20 Nov 2015 19:10:35 +0100 Subject: [PATCH 163/211] [Issue #76] Fixed compilation errors for ICC --- src/compat/pipe.h | 1 + src/core/runner_coroutine.c | 17 ++++++++--------- src/entry/main.c | 4 ++-- src/io/redirect.c | 6 +++--- src/string/extmatch.c | 4 ++-- 5 files changed, 16 insertions(+), 16 deletions(-) diff --git a/src/compat/pipe.h b/src/compat/pipe.h index f6a607e8..d0e162d6 100644 --- a/src/compat/pipe.h +++ b/src/compat/pipe.h @@ -47,6 +47,7 @@ enum criterion_std_fd { }; enum pipe_opt { + PIPE_NOOPT = 0, PIPE_DUP = 1 << 0, PIPE_CLOSE = 1 << 1, }; diff --git a/src/core/runner_coroutine.c b/src/core/runner_coroutine.c index 6e557a3d..50f336c6 100644 --- a/src/core/runner_coroutine.c +++ b/src/core/runner_coroutine.c @@ -102,6 +102,7 @@ static int skip_disabled(struct run_next_context *ctx) { struct worker *run_next_test(struct criterion_test_set *p_set, struct criterion_global_stats *p_stats, ccrContParam) { + struct worker *worker = NULL; ccrUseNamedContext(run_next_context, ctx); @@ -122,8 +123,7 @@ struct worker *run_next_test(struct criterion_test_set *p_set, ctx->suite_stats = suite_stats_init(&ctx->suite_set->suite); - struct event ev = { .kind = PRE_SUITE }; - stat_push_event(ctx->stats, ctx->suite_stats, NULL, &ev); + stat_push_event(ctx->stats, ctx->suite_stats, NULL, &(struct event) { .kind = PRE_SUITE }); for (ctx->nt = ctx->suite_set->tests->first; ctx->nt; ctx->nt = ctx->nt->next) { ctx->test = (void*) (ctx->nt + 1); @@ -138,15 +138,14 @@ struct worker *run_next_test(struct criterion_test_set *p_set, for (ctx->i = 0; ctx->i < ctx->params.length; ++ctx->i) { ctx->test_stats = test_stats_init(ctx->test); - struct test_single_param param = { - ctx->params.size, - (char *) ctx->params.params + ctx->i * ctx->params.size - }; - struct worker *worker = run_test(ctx->stats, + worker = run_test(ctx->stats, ctx->suite_stats, ctx->test_stats, - ¶m); + &(struct test_single_param) { + ctx->params.size, + (char *) ctx->params.params + ctx->i * ctx->params.size + }); ccrReturn(cleanup_and_return_worker(ctx, worker)); } @@ -159,7 +158,7 @@ struct worker *run_next_test(struct criterion_test_set *p_set, if (skip_disabled(ctx)) continue; - struct worker *worker = run_test(ctx->stats, + worker = run_test(ctx->stats, ctx->suite_stats, ctx->test_stats, NULL); diff --git a/src/entry/main.c b/src/entry/main.c index 792ff799..1f642434 100644 --- a/src/entry/main.c +++ b/src/entry/main.c @@ -188,7 +188,7 @@ int criterion_handle_args(int argc, char *argv[], bool handle_unknown_arg) { if (env_jobs) opt->jobs = atou(env_jobs); if (env_logging_threshold) - opt->logging_threshold = atou(env_logging_threshold); + opt->logging_threshold = (enum criterion_logging_level) atou(env_logging_threshold); if (env_short_filename) opt->short_filename = !strcmp("1", env_short_filename); @@ -206,7 +206,7 @@ int criterion_handle_args(int argc, char *argv[], bool handle_unknown_arg) { bool quiet = false; for (int c; (c = getopt_long(argc, argv, "hvlfj:SqO:", opts, NULL)) != -1;) { switch (c) { - case 'b': criterion_options.logging_threshold = atou(DEF(optarg, "1")); break; + case 'b': criterion_options.logging_threshold = (enum criterion_logging_level) atou(DEF(optarg, "1")); break; case 'y': criterion_options.always_succeed = true; break; case 'z': criterion_options.no_early_exit = true; break; case 'k': criterion_options.use_ascii = true; break; diff --git a/src/io/redirect.c b/src/io/redirect.c index a9d80d0d..2ee3e196 100644 --- a/src/io/redirect.c +++ b/src/io/redirect.c @@ -49,7 +49,7 @@ void cr_redirect_stdin(void) { FILE* cr_get_redirected_stdout(void) { static FILE *f; if (!f) { - f = pipe_in(stdout_redir, 0); + f = pipe_in(stdout_redir, PIPE_NOOPT); if (!f) cr_assert_fail("Could not get redirected stdout read end."); } @@ -59,7 +59,7 @@ FILE* cr_get_redirected_stdout(void) { FILE* cr_get_redirected_stderr(void) { static FILE *f; if (!f) { - f = pipe_in(stderr_redir, 0); + f = pipe_in(stderr_redir, PIPE_NOOPT); if (!f) cr_assert_fail("Could not get redirected stderr read end."); } @@ -69,7 +69,7 @@ FILE* cr_get_redirected_stderr(void) { FILE* cr_get_redirected_stdin(void) { static FILE *f; if (!f) { - f = pipe_out(stdin_redir, 0); + f = pipe_out(stdin_redir, PIPE_NOOPT); if (!f) cr_assert_fail("Could not get redirected stdin write end."); } diff --git a/src/string/extmatch.c b/src/string/extmatch.c index de63088e..6e9e5504 100644 --- a/src/string/extmatch.c +++ b/src/string/extmatch.c @@ -99,8 +99,8 @@ typedef struct { char *str; } handler_arg; -static int active() { return 1; } -static int inactive() { return 0; } +static int active(struct context *ctx) { return 1; } +static int inactive(struct context *ctx) { return 0; } static int is_eos(struct context *ctx) { return peek_char(ctx) == '\0'; From 5bdccd862a1863ebdfbeecb68449105cd2393fe7 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Sat, 21 Nov 2015 00:07:53 +0100 Subject: [PATCH 164/211] Fixed unused parameter warnings --- src/string/extmatch.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/string/extmatch.c b/src/string/extmatch.c index 6e9e5504..185a2640 100644 --- a/src/string/extmatch.c +++ b/src/string/extmatch.c @@ -99,8 +99,8 @@ typedef struct { char *str; } handler_arg; -static int active(struct context *ctx) { return 1; } -static int inactive(struct context *ctx) { return 0; } +static int active(CR_UNUSED struct context *ctx) { return 1; } +static int inactive(CR_UNUSED struct context *ctx) { return 0; } static int is_eos(struct context *ctx) { return peek_char(ctx) == '\0'; From fa29b3c6dbc9fd23f1c2da0c0d1a65393ebe0b7e Mon Sep 17 00:00:00 2001 From: Snaipe Date: Wed, 25 Nov 2015 20:10:09 +0100 Subject: [PATCH 165/211] Added back GCC 4.6 support --- .travis.yml | 28 +++++++++++++--- CMakeLists.txt | 18 ++++++++++- include/criterion/internal/common.h | 6 +++- .../internal/designated-initializer-compat.h | 10 +++--- include/criterion/internal/parameterized.h | 2 +- include/criterion/internal/stream.hxx | 32 ++++++++----------- include/criterion/internal/test.h | 4 +-- include/criterion/internal/theories.h | 2 +- include/criterion/redirect.h | 6 ++-- samples/CMakeLists.txt | 2 +- test/CMakeLists.txt | 2 +- 11 files changed, 74 insertions(+), 38 deletions(-) diff --git a/.travis.yml b/.travis.yml index 3426f55d..a2ae4f73 100644 --- a/.travis.yml +++ b/.travis.yml @@ -32,6 +32,15 @@ matrix: CONFIGURATION: RelWithDebInfo CMAKE_OPTS: -DLANG_OBJC=ON DEPLOY: true + # Linux Debug, GCC 4.6 + - compiler: gcc + env: CONFIGURATION=Debug TESTS=OFF + # Linux Release, GCC 4.6 + - compiler: gcc + env: CONFIGURATION=Release TESTS=OFF + # Linux RelWithDebInfo, GCC 4.6 + - compiler: gcc + env: CONFIGURATION=RelWithDebInfo TESTS=OFF # OSX Debug, GCC 4.9 - os: osx compiler: gcc-4.9 @@ -67,6 +76,9 @@ matrix: CMAKE_OPTS: -DLANG_OBJC=ON DEPLOY: true + allow_failures: + - compiler: gcc + before_install: - | if [ "$TRAVIS_OS_NAME" = "osx" ] && [ "$CC" = "clang" ]; then @@ -83,14 +95,19 @@ script: - > cmake -Wno-dev - -DCTESTS=ON + -DCTESTS=${TESTS:-ON} -DCOVERALLS=${COVERAGE:-OFF} -DCMAKE_BUILD_TYPE=${CONFIGURATION} -DCMAKE_INSTALL_PREFIX=criterion-${TRAVIS_TAG} ${CMAKE_OPTS} .. - - TERM=dumb cmake --build . --target criterion_tests -- -j4 - - ctest -j4 + - | + if [ "$TESTS" = "ON" ]; then + TERM=dumb cmake --build . --target criterion_tests -- -j4 + ctest -j4 + else + TERM=dumb cmake --build . -- -j4 + fi after_success: - | @@ -100,7 +117,10 @@ after_success: fi after_failure: - - cat Testing/Temporary/LastTest.log samples/*.{out,err} ../samples/tests/*.{out,err} + - | + if [ "$TESTS" = "ON" ]; then + cat Testing/Temporary/LastTest.log samples/*.{out,err} ../samples/tests/*.{out,err} + fi before_deploy: - make install diff --git a/CMakeLists.txt b/CMakeLists.txt index 6ea2b7ac..15b7f398 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -38,6 +38,22 @@ endif () include(Languages) +# Check for C++11 + +if (NOT MSVC AND CMAKE_CXX_COMPILER_WORKS) + include(CheckCXXCompilerFlag) + CHECK_CXX_COMPILER_FLAG("-std=c++11" COMPILER_SUPPORTS_CXX11) + CHECK_CXX_COMPILER_FLAG("-std=c++0x" COMPILER_SUPPORTS_CXX0X) + + if(COMPILER_SUPPORTS_CXX11) + set(CXX11_FLAG "-std=c++11") + elseif(COMPILER_SUPPORTS_CXX0X) + set(CXX11_FLAG "-std=c++0x") + else() + message(FATAL_ERROR "Compiler ${CMAKE_CXX_COMPILER} has no C++11 support.") + endif() +endif() + # Project setup & environment variables set(PROJECT_VERSION "2.1.0") @@ -53,7 +69,7 @@ set(CMAKE_CXX_FLAGS_DEFAULT "${CMAKE_CXX_FLAGS}") if (NOT MSVC) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Werror -g -std=gnu99") if (CMAKE_CXX_COMPILER_WORKS) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Werror -g -std=c++11") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Werror -g ${CXX11_FLAG}") endif () endif () diff --git a/include/criterion/internal/common.h b/include/criterion/internal/common.h index 8b547e5c..f651772e 100644 --- a/include/criterion/internal/common.h +++ b/include/criterion/internal/common.h @@ -42,7 +42,11 @@ # endif # ifdef __cplusplus -# define CR_ATTRIBUTE(Arg) [[gnu::Arg]] +# ifdef __GNUC__ +# define CR_ATTRIBUTE(Arg) __attribute__((Arg)) +# else +# define CR_ATTRIBUTE(Arg) [[gnu::Arg]] +# endif # define CR_BEGIN_C_API extern "C" { # define CR_END_C_API } # else diff --git a/include/criterion/internal/designated-initializer-compat.h b/include/criterion/internal/designated-initializer-compat.h index 9b99d050..e3c59780 100644 --- a/include/criterion/internal/designated-initializer-compat.h +++ b/include/criterion/internal/designated-initializer-compat.h @@ -112,11 +112,11 @@ CR_EXPAND(CRITERION_APPLY(CRITERION_ADD_PREFIX_ONCE, __VA_ARGS__)) # ifdef __cplusplus -# define CRITERION_MAKE_STRUCT(Type, ...) []() { \ - Type t; \ - std::memset(&t, 0, sizeof (t)); \ - CR_EXPAND(CRITERION_ADD_PREFIX(t, __VA_ARGS__)) \ - return t; \ +# define CRITERION_MAKE_STRUCT(Type, ...) []() -> Type { \ + Type t; \ + std::memset(&t, 0, sizeof (t)); \ + CR_EXPAND(CRITERION_ADD_PREFIX(t, __VA_ARGS__)) \ + return t; \ }() # else # define CRITERION_MAKE_STRUCT(Type, ...) { __VA_ARGS__ } diff --git a/include/criterion/internal/parameterized.h b/include/criterion/internal/parameterized.h index 017a5990..c254531d 100644 --- a/include/criterion/internal/parameterized.h +++ b/include/criterion/internal/parameterized.h @@ -38,7 +38,7 @@ # define CR_PARAM_TEST_BASE(Param, Category, Name, ...) \ CR_PARAM_TEST_PROTOTYPE_(Param, Category, Name); \ struct criterion_test_extra_data CR_IDENTIFIER_(Category, Name, extra) = \ - CR_EXPAND(CRITERION_MAKE_STRUCT(struct criterion_test_extra_data, \ + CR_EXPAND(CRITERION_MAKE_STRUCT(criterion_test_extra_data, \ .lang_ = CR_LANG, \ .kind_ = CR_TEST_PARAMETERIZED, \ .param_ = CR_IDENTIFIER_(Category, Name, param), \ diff --git a/include/criterion/internal/stream.hxx b/include/criterion/internal/stream.hxx index d8c5a087..828dbdc4 100644 --- a/include/criterion/internal/stream.hxx +++ b/include/criterion/internal/stream.hxx @@ -20,8 +20,10 @@ public: std::ios::rdbuf(&*fbuf); } +# if __cplusplus > 199711L stream_mixin(const stream_mixin& other) = delete; stream_mixin& operator=(const stream_mixin& other) = delete; +# endif stream_mixin(stream_mixin&& other) : fbuf(std::move(other.fbuf)), @@ -45,47 +47,41 @@ public: }; template - using ofstream_mixin = stream_mixin>; - - template - using ifstream_mixin = stream_mixin>; - - template - using fstream_mixin = stream_mixin>; - - template - class basic_ofstream : public ofstream_mixin { + class basic_ofstream : public stream_mixin> { + typedef stream_mixin> super; public: basic_ofstream(FILE* f) - : ofstream_mixin(f) + : super(f) {} basic_ofstream(basic_ofstream&& other) - : ofstream_mixin(std::move(other)) + : super(std::move(other)) {} }; template - class basic_ifstream : public ifstream_mixin { + class basic_ifstream : public stream_mixin> { + typedef stream_mixin> super; public: basic_ifstream(FILE* f) - : ifstream_mixin(f) + : super(f) {} basic_ifstream(basic_ifstream&& other) - : ifstream_mixin(std::move(other)) + : super(std::move(other)) {} }; template - class basic_fstream : public fstream_mixin { + class basic_fstream : public stream_mixin> { + typedef stream_mixin> super; public: basic_fstream(FILE* f) - : fstream_mixin(f) + : super(f) {} basic_fstream(basic_fstream&& other) - : fstream_mixin(std::move(other)) + : super(std::move(other)) {} }; diff --git a/include/criterion/internal/test.h b/include/criterion/internal/test.h index 2b4e3d95..0772f1f2 100644 --- a/include/criterion/internal/test.h +++ b/include/criterion/internal/test.h @@ -58,7 +58,7 @@ # define CR_TEST_BASE(Category, Name, ...) \ CR_TEST_PROTOTYPE_(Category, Name); \ struct criterion_test_extra_data CR_IDENTIFIER_(Category, Name, extra) = \ - CR_EXPAND(CRITERION_MAKE_STRUCT(struct criterion_test_extra_data, \ + CR_EXPAND(CRITERION_MAKE_STRUCT(criterion_test_extra_data, \ .lang_ = CR_LANG, \ .kind_ = CR_TEST_NORMAL, \ .param_ = (struct criterion_test_params(*)(void)) NULL, \ @@ -80,7 +80,7 @@ # define CR_SUITE_BASE(Name, ...) \ struct criterion_test_extra_data CR_SUITE_IDENTIFIER_(Name, extra) = \ - CR_EXPAND(CRITERION_MAKE_STRUCT(struct criterion_test_extra_data, \ + CR_EXPAND(CRITERION_MAKE_STRUCT(criterion_test_extra_data, \ .file_ = __FILE__, \ .line_ = 0, \ __VA_ARGS__ \ diff --git a/include/criterion/internal/theories.h b/include/criterion/internal/theories.h index 172d96df..798034f0 100644 --- a/include/criterion/internal/theories.h +++ b/include/criterion/internal/theories.h @@ -55,7 +55,7 @@ CR_END_C_API # ifdef __cplusplus # define CR_TH_VA_NUM(Type, ...) criterion_va_num__(__VA_ARGS__) -# define CR_TH_TEMP_ARRAY(Type, ...) []() { static Type arr[] = { __VA_ARGS__ }; return &arr; }() +# define CR_TH_TEMP_ARRAY(Type, ...) []() -> Type* { static Type arr[] = { __VA_ARGS__ }; return reinterpret_cast(&arr); }() # else # define CR_TH_VA_NUM(Type, ...) sizeof ((Type[]) { __VA_ARGS__ }) / sizeof (Type) # define CR_TH_TEMP_ARRAY(Type, ...) &(Type[]) { __VA_ARGS__ } diff --git a/include/criterion/redirect.h b/include/criterion/redirect.h index 6fd5f588..b93f2a6a 100644 --- a/include/criterion/redirect.h +++ b/include/criterion/redirect.h @@ -91,9 +91,9 @@ CR_END_C_API namespace criterion { - using ofstream = internal::basic_ofstream; - using ifstream = internal::basic_ifstream; - using fstream = internal::basic_fstream; + typedef internal::basic_ofstream ofstream; + typedef internal::basic_ifstream ifstream; + typedef internal::basic_fstream fstream; static inline ofstream& get_redirected_cin(void) { return internal::get_redirected_out_stream_::call(cr_get_redirected_stdin()); diff --git a/samples/CMakeLists.txt b/samples/CMakeLists.txt index f8d6bbed..e56eeae5 100644 --- a/samples/CMakeLists.txt +++ b/samples/CMakeLists.txt @@ -1,6 +1,6 @@ if (NOT MSVC) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS_DEFAULT} -std=c99 -Wall -Wextra -pedantic") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS_DEFAULT} -std=c++11 -Wall -Wextra -pedantic") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS_DEFAULT} ${CXX11_FLAG} -Wall -Wextra -pedantic") endif () include_directories(../include) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 96531bec..3e7c7476 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -1,7 +1,7 @@ if (NOT MSVC) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS_DEFAULT} -std=gnu99 -Wall -Wextra") if (CMAKE_CXX_COMPILER_WORKS) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS_DEFAULT} -std=c++11 -Wall -Wextra") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS_DEFAULT} ${CXX11_FLAG} -Wall -Wextra") endif () endif () From 26b25cf1f97d7778db73d1dd54cf3269b66383a3 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Wed, 25 Nov 2015 20:16:26 +0100 Subject: [PATCH 166/211] Updated docs on the required version of GCC --- doc/setup.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/setup.rst b/doc/setup.rst index f5f4c2d3..4083fe66 100644 --- a/doc/setup.rst +++ b/doc/setup.rst @@ -8,7 +8,7 @@ The library is supported on Linux, OS X, FreeBSD, and Windows. The following compilers are supported to compile both the library and the tests: -* GCC 4.9+ +* GCC 4.9+ (Can be relaxed to GCC 4.6+ when not using C++) * Clang 3.4+ * MSVC 14+ (Included in Visual Studio 2015 or later) From 1beccec921b384b2c4e02a38e9fd496cdddc0ff1 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Thu, 26 Nov 2015 00:23:27 +0100 Subject: [PATCH 167/211] Added back CRITERION_ENABLE_TAP and added CRITERION_OUTPUTS environment variable. --- doc/env.rst | 5 +++++ src/entry/main.c | 36 +++++++++++++++++++++++++++++++++++- 2 files changed, 40 insertions(+), 1 deletion(-) diff --git a/doc/env.rst b/doc/env.rst index 234a4966..2205bc51 100644 --- a/doc/env.rst +++ b/doc/env.rst @@ -93,3 +93,8 @@ Environment variables are alternatives to command line switches when set to 1. to its value. (\*nix only) * ``CRITERION_DISABLE_TIME_MEASUREMENTS``: Disables any time measurements on the tests. +* ``CRITERION_OUTPUTS``: Can be set to a comma-separated list of + ``PROVIDER:FILE`` entries. For instance, setting the variable to + ``tap:foo.tap,xml:bar.xml`` has the same effect as specifying ``--tap=foo.tap`` + and ``--xml=bar.xml`` at once. +* ``CRITERION_ENABLE_TAP``: (Deprecated, use CRITERION_OUTPUTS) Same as ``--tap``. diff --git a/src/entry/main.c b/src/entry/main.c index 1f642434..833f6ad0 100644 --- a/src/entry/main.c +++ b/src/entry/main.c @@ -200,10 +200,42 @@ int criterion_handle_args(int argc, char *argv[], bool handle_unknown_arg) { opt->measure_time = !!strcmp("1", DEF(getenv("CRITERION_DISABLE_TIME_MEASUREMENTS"), "0")); + bool quiet = false; + + // CRITERION_ENABLE_TAP backward compatibility. + // The environment variable is otherwise deprecated. + if (!strcmp("1", DEF(getenv("CRITERION_ENABLE_TAP"), "0"))) { + quiet = true; + criterion_add_output("tap", DEF(optarg, "-")); + } + bool do_list_tests = false; bool do_print_version = false; bool do_print_usage = false; - bool quiet = false; + + const char *outputs = getenv("CRITERION_OUTPUTS"); + if (outputs) { + char *out = strdup(outputs); + char *buf = NULL; + strtok_r(out, ",", &buf); + + for (char *s = out; s; s = strtok_r(NULL, ",", &buf)) { + s = strdup(s); + char *buf2 = NULL; + char *provider = strtok_r(s, ":", &buf2); + char *path = strtok_r(NULL, ":", &buf2); + + if (provider == NULL || path == NULL) { + do_print_usage = true; + goto end; + } + + quiet = true; + criterion_add_output(provider, path); + } + free(out); + } + for (int c; (c = getopt_long(argc, argv, "hvlfj:SqO:", opts, NULL)) != -1;) { switch (c) { case 'b': criterion_options.logging_threshold = (enum criterion_logging_level) atou(DEF(optarg, "1")); break; @@ -241,6 +273,8 @@ int criterion_handle_args(int argc, char *argv[], bool handle_unknown_arg) { default : do_print_usage = handle_unknown_arg; break; } } + +end: if (quiet) criterion_options.logging_threshold = CRITERION_LOG_LEVEL_QUIET; From 49abc860662f108ab6d10f84459638134fb19217 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Fri, 27 Nov 2015 00:13:59 +0100 Subject: [PATCH 168/211] [Issue #76] Updated dyncall to latest for icc fix --- dependencies/dyncall | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencies/dyncall b/dependencies/dyncall index 68c57f66..180a5b77 160000 --- a/dependencies/dyncall +++ b/dependencies/dyncall @@ -1 +1 @@ -Subproject commit 68c57f664d4fabbc5b80327fbf5661a3a5a51e06 +Subproject commit 180a5b77ff95a17991afdc6e9be3501eca99ad36 From 6bfdaffea8412ad4591f3deecbc9ee99cef80ec6 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Fri, 27 Nov 2015 00:24:39 +0100 Subject: [PATCH 169/211] Fixed travis build translating 'ON' as 'true' in environment variables. --- .travis.yml | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/.travis.yml b/.travis.yml index a2ae4f73..5481f057 100644 --- a/.travis.yml +++ b/.travis.yml @@ -17,21 +17,21 @@ matrix: # Linux Debug, GCC 4.9 - compiler: gcc-4.9 env: - CONFIGURATION: Debug - GCOV: gcov-4.9 - CMAKE_OPTS: -DLANG_OBJC=ON - COVERAGE: ON + - CONFIGURATION=Debug + - GCOV=gcov-4.9 + - CMAKE_OPTS=-DLANG_OBJC=ON + - COVERAGE=ON # Linux Release, GCC 4.9 - compiler: gcc-4.9 env: - CONFIGURATION: Release - CMAKE_OPTS: -DLANG_OBJC=ON + - CONFIGURATION=Release + - CMAKE_OPTS=-DLANG_OBJC=ON # Linux RelWithDebInfo, GCC 4.9 - compiler: gcc-4.9 env: - CONFIGURATION: RelWithDebInfo - CMAKE_OPTS: -DLANG_OBJC=ON - DEPLOY: true + - CONFIGURATION=RelWithDebInfo + - CMAKE_OPTS=-DLANG_OBJC=ON + - DEPLOY=true # Linux Debug, GCC 4.6 - compiler: gcc env: CONFIGURATION=Debug TESTS=OFF @@ -45,9 +45,9 @@ matrix: - os: osx compiler: gcc-4.9 env: - CONFIGURATION: Debug - GCOV: gcov-4.9 - COVERAGE: ON + - CONFIGURATION=Debug + - GCOV=gcov-4.9 + - COVERAGE=ON # OSX Release, GCC 4.9 - os: osx compiler: gcc-4.9 @@ -60,21 +60,21 @@ matrix: - os: osx compiler: clang env: - CONFIGURATION: Debug - CMAKE_OPTS: -DLANG_OBJC=ON + - CONFIGURATION=Debug + - CMAKE_OPTS=-DLANG_OBJC=ON # OSX Release, Clang - os: osx compiler: clang env: - CONFIGURATION: Release - CMAKE_OPTS: -DLANG_OBJC=ON + - CONFIGURATION=Release + - CMAKE_OPTS=-DLANG_OBJC=ON # OSX RelWithDebInfo, Clang - os: osx compiler: clang env: - CONFIGURATION: RelWithDebInfo - CMAKE_OPTS: -DLANG_OBJC=ON - DEPLOY: true + - CONFIGURATION=RelWithDebInfo + - CMAKE_OPTS=-DLANG_OBJC=ON + - DEPLOY=true allow_failures: - compiler: gcc From a5de951a489502b51bc2df45ffcc4ee3f4b817b9 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Fri, 27 Nov 2015 00:30:08 +0100 Subject: [PATCH 170/211] Fixed travis build not running tests by default --- .travis.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.travis.yml b/.travis.yml index 5481f057..e0c50afa 100644 --- a/.travis.yml +++ b/.travis.yml @@ -12,6 +12,10 @@ addons: - gobjc-4.9 - gnustep-devel +env: + global: + - TESTS=ON + matrix: include: # Linux Debug, GCC 4.9 From 635ddb204feabcd6a296b057c3f3c92b36022f84 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Fri, 27 Nov 2015 00:46:01 +0100 Subject: [PATCH 171/211] Refactored travis config to install gcc 4.9 only on the relevant configurations --- .travis.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index e0c50afa..89729625 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,7 +2,7 @@ language: c sudo: false -addons: +_gcc-4.9-packages: &gcc49-packages apt: sources: - ubuntu-toolchain-r-test @@ -20,6 +20,7 @@ matrix: include: # Linux Debug, GCC 4.9 - compiler: gcc-4.9 + addons: *gcc49-packages env: - CONFIGURATION=Debug - GCOV=gcov-4.9 @@ -27,11 +28,13 @@ matrix: - COVERAGE=ON # Linux Release, GCC 4.9 - compiler: gcc-4.9 + addons: *gcc49-packages env: - CONFIGURATION=Release - CMAKE_OPTS=-DLANG_OBJC=ON # Linux RelWithDebInfo, GCC 4.9 - compiler: gcc-4.9 + addons: *gcc49-packages env: - CONFIGURATION=RelWithDebInfo - CMAKE_OPTS=-DLANG_OBJC=ON From 41d7123b4136e71538134290eaaa72844d157b1f Mon Sep 17 00:00:00 2001 From: Snaipe Date: Fri, 27 Nov 2015 01:11:52 +0100 Subject: [PATCH 172/211] Cleaned up travis config --- .travis.yml | 63 +++++++++++++++++++++++++---------------------------- 1 file changed, 30 insertions(+), 33 deletions(-) diff --git a/.travis.yml b/.travis.yml index 89729625..57fa7592 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,19 +2,16 @@ language: c sudo: false -_gcc-4.9-packages: &gcc49-packages - apt: - sources: - - ubuntu-toolchain-r-test - packages: - - gcc-4.9 - - g++-4.9 - - gobjc-4.9 - - gnustep-devel - -env: - global: - - TESTS=ON +_anchors: + - &gcc49-packages + apt: + sources: + - ubuntu-toolchain-r-test + packages: + - gcc-4.9 + - g++-4.9 + - gobjc-4.9 + - gnustep-devel matrix: include: @@ -22,23 +19,23 @@ matrix: - compiler: gcc-4.9 addons: *gcc49-packages env: - - CONFIGURATION=Debug - - GCOV=gcov-4.9 - - CMAKE_OPTS=-DLANG_OBJC=ON - - COVERAGE=ON + CONFIGURATION: Debug + GCOV: gcov-4.9 + CMAKE_OPTS: -DLANG_OBJC=ON + COVERAGE: "ON" # Linux Release, GCC 4.9 - compiler: gcc-4.9 addons: *gcc49-packages env: - - CONFIGURATION=Release - - CMAKE_OPTS=-DLANG_OBJC=ON + CONFIGURATION: Release + CMAKE_OPTS: -DLANG_OBJC=ON # Linux RelWithDebInfo, GCC 4.9 - compiler: gcc-4.9 addons: *gcc49-packages env: - - CONFIGURATION=RelWithDebInfo - - CMAKE_OPTS=-DLANG_OBJC=ON - - DEPLOY=true + CONFIGURATION: RelWithDebInfo + CMAKE_OPTS: -DLANG_OBJC=ON + DEPLOY: true # Linux Debug, GCC 4.6 - compiler: gcc env: CONFIGURATION=Debug TESTS=OFF @@ -52,9 +49,9 @@ matrix: - os: osx compiler: gcc-4.9 env: - - CONFIGURATION=Debug - - GCOV=gcov-4.9 - - COVERAGE=ON + CONFIGURATION: Debug + GCOV: gcov-4.9 + COVERAGE: "ON" # OSX Release, GCC 4.9 - os: osx compiler: gcc-4.9 @@ -67,21 +64,21 @@ matrix: - os: osx compiler: clang env: - - CONFIGURATION=Debug - - CMAKE_OPTS=-DLANG_OBJC=ON + CONFIGURATION: Debug + CMAKE_OPTS: -DLANG_OBJC=ON # OSX Release, Clang - os: osx compiler: clang env: - - CONFIGURATION=Release - - CMAKE_OPTS=-DLANG_OBJC=ON + CONFIGURATION: Release + CMAKE_OPTS: -DLANG_OBJC=ON # OSX RelWithDebInfo, Clang - os: osx compiler: clang env: - - CONFIGURATION=RelWithDebInfo - - CMAKE_OPTS=-DLANG_OBJC=ON - - DEPLOY=true + CONFIGURATION: RelWithDebInfo + CMAKE_OPTS: -DLANG_OBJC=ON + DEPLOY: true allow_failures: - compiler: gcc @@ -109,7 +106,7 @@ script: ${CMAKE_OPTS} .. - | - if [ "$TESTS" = "ON" ]; then + if [ "${TESTS:-ON}" = "ON" ]; then TERM=dumb cmake --build . --target criterion_tests -- -j4 ctest -j4 else From 56f0abfd49f9002665cc92232b32bede37ea4a8a Mon Sep 17 00:00:00 2001 From: Snaipe Date: Fri, 27 Nov 2015 11:48:52 +0100 Subject: [PATCH 173/211] Added install checks on travis builds --- .travis.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.travis.yml b/.travis.yml index 57fa7592..3e4937b1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -112,6 +112,11 @@ script: else TERM=dumb cmake --build . -- -j4 fi + - | + make DESTDIR=out install + diff <(find ../include/ | sed 's/^..\///g') \ + <(find out/usr/local/include/ | sed 's/out\/usr\/local\///g') \ + || exit 1 after_success: - | From 85095ba7e7fff97a6bfaf000e1462efc726ff84b Mon Sep 17 00:00:00 2001 From: Snaipe Date: Fri, 27 Nov 2015 11:59:39 +0100 Subject: [PATCH 174/211] Disable --quiet when the provider output path is not stderr --- src/entry/main.c | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/src/entry/main.c b/src/entry/main.c index 833f6ad0..5d71a688 100644 --- a/src/entry/main.c +++ b/src/entry/main.c @@ -249,9 +249,19 @@ int criterion_handle_args(int argc, char *argv[], bool handle_unknown_arg) { case 'p': criterion_options.pattern = optarg; break; #endif case 'q': quiet = true; break; - case 't': quiet = true; criterion_add_output("tap", DEF(optarg, "-")); break; - case 'x': quiet = true; criterion_add_output("xml", DEF(optarg, "-")); break; - case 'n': quiet = true; criterion_add_output("json", DEF(optarg, "-")); break; + + { + const char *provider; + case 't': provider = "tap"; goto provider_def; + case 'x': provider = "xml"; goto provider_def; + case 'n': provider = "json"; goto provider_def; + + provider_def: {} + const char *path = DEF(optarg, "-"); + quiet = !strcmp(path, "-"); + criterion_add_output(provider, path); + } break; + case 'l': do_list_tests = true; break; case 'v': do_print_version = true; break; case 'h': do_print_usage = true; break; @@ -266,7 +276,7 @@ int criterion_handle_args(int argc, char *argv[], bool handle_unknown_arg) { break; } - quiet = true; + quiet = !strcmp(path, "-"); criterion_add_output(arg, path); } break; case '?': From 07f109eb6ef602d5f0280d4cf8ccb0df57ef3b94 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Fri, 27 Nov 2015 12:18:38 +0100 Subject: [PATCH 175/211] Added error messages when reporting fails --- po/POTFILES.in | 1 + po/fr.po | 16 +++++++++++++--- src/core/runner.c | 3 +-- src/io/output.c | 21 ++++++++++++++++++++- 4 files changed, 35 insertions(+), 6 deletions(-) diff --git a/po/POTFILES.in b/po/POTFILES.in index 358d39c7..d37bcf23 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -2,3 +2,4 @@ src/log/normal.c src/string/i18n.c src/core/runner.c +src/io/output.c diff --git a/po/fr.po b/po/fr.po index 6e8fe381..25f40f9d 100644 --- a/po/fr.po +++ b/po/fr.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: criterion 2.0.0\n" "Report-Msgid-Bugs-To: franklinmathieu+criterion@gmail.com\n" -"POT-Creation-Date: 2015-11-11 00:24+0100\n" +"POT-Creation-Date: 2015-11-27 12:16+0100\n" "PO-Revision-Date: 2015-04-03 17:58+0200\n" "Last-Translator: \n" "Language-Team: French\n" @@ -185,7 +185,7 @@ msgstr "L'instruction `%1$s` a levé une instance de l'exception `%2$s`." msgid "The statement `%1$s` did not throw an instance of the `%2$s` exception." msgstr "L'instruction `%1$s` n'a pas levé d'instance de l'exception `%2$s`." -#: src/core/runner.c:56 +#: src/core/runner.c:58 #, c-format msgid "" "%1$sWarning! Criterion has detected that it is running under valgrind, but " @@ -196,7 +196,7 @@ msgstr "" "l'option no_early_exit est explicitement désactivée. Les rapports d'erreur " "ne seront pas précis!%2$s\n" -#: src/core/runner.c:60 +#: src/core/runner.c:62 #, c-format msgid "" "%1$sWarning! Criterion has detected that it is running under valgrind, but " @@ -206,3 +206,13 @@ msgstr "" "%1$sAttention! Criterion a détecté qu'il a été lancé avec valgrind, mais le " "nombre de tâches est explicitement défini. Les rapports d'erreur risquent " "d'être déroutants!%2$s\n" + +#: src/io/output.c:12 +#, c-format +msgid "Could not open the file @ `%1$s` for %2$s reporting.\n" +msgstr "Impossible d'ouvrir le fichier `%1$s` pour faire le rapport %2$s.\n" + +#: src/io/output.c:13 +#, c-format +msgid "Writing %1$s report in `%2$s`.\n" +msgstr "Écriture du rapport %1$s dans `%2$s`.\n" diff --git a/src/core/runner.c b/src/core/runner.c index 38a85fc3..d5c6a003 100644 --- a/src/core/runner.c +++ b/src/core/runner.c @@ -462,9 +462,8 @@ static int criterion_run_all_tests_impl(struct criterion_test_set *set) { goto cleanup; report(POST_ALL, stats); - log(post_all, stats); - process_all_output(stats); + log(post_all, stats); cleanup: sfree(g_worker_pipe); diff --git a/src/io/output.c b/src/io/output.c index 25831e42..be5dda10 100644 --- a/src/io/output.c +++ b/src/io/output.c @@ -3,6 +3,18 @@ #include #include #include "criterion/output.h" +#include "criterion/logging.h" +#include "string/i18n.h" + +typedef const char *const msg_t; + +#ifdef ENABLE_NLS +static msg_t msg_err = N_("Could not open the file @ `%1$s` for %2$s reporting.\n"); +static msg_t msg_ok = N_("Writing %1$s report in `%2$s`.\n"); +#else +static msg_t msg_err = "Could not open the file @ `%s` for %s reporting.\n"; +static msg_t msg_ok = "Writing %s report in `%s`.\n"; +#endif typedef kvec_t(const char *) str_vec; @@ -69,7 +81,8 @@ void process_all_output(struct criterion_global_stats *stats) { continue; criterion_reporter *report = kh_value(reporters, k); - khint_t ko = kh_get(ht_path, outputs, kh_key(reporters, k)); + const char *name = kh_key(reporters, k); + khint_t ko = kh_get(ht_path, outputs, name); if (ko == kh_end(outputs)) continue; @@ -83,6 +96,12 @@ void process_all_output(struct criterion_global_stats *stats) { else f = fopen(path, "w"); + if (!f) { + criterion_perror(_(msg_err), path, name); + continue; + } + + criterion_pinfo(CRITERION_PREFIX_DASHES, _(msg_ok), name, path); report(f, stats); } } From 11b84284f783aa89d8b38bf77570e8255896fe59 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Fri, 27 Nov 2015 12:24:42 +0100 Subject: [PATCH 176/211] Print strerror when failing to open a report file --- po/fr.po | 13 +++++++------ src/io/output.c | 8 +++++--- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/po/fr.po b/po/fr.po index 25f40f9d..6056b865 100644 --- a/po/fr.po +++ b/po/fr.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: criterion 2.0.0\n" "Report-Msgid-Bugs-To: franklinmathieu+criterion@gmail.com\n" -"POT-Creation-Date: 2015-11-27 12:16+0100\n" +"POT-Creation-Date: 2015-11-27 12:24+0100\n" "PO-Revision-Date: 2015-04-03 17:58+0200\n" "Last-Translator: \n" "Language-Team: French\n" @@ -207,12 +207,13 @@ msgstr "" "nombre de tâches est explicitement défini. Les rapports d'erreur risquent " "d'être déroutants!%2$s\n" -#: src/io/output.c:12 -#, c-format -msgid "Could not open the file @ `%1$s` for %2$s reporting.\n" -msgstr "Impossible d'ouvrir le fichier `%1$s` pour faire le rapport %2$s.\n" - #: src/io/output.c:13 +#, fuzzy, c-format +msgid "Could not open the file @ `%1$s` for %2$s reporting: %3$s.\n" +msgstr "" +"Impossible d'ouvrir le fichier `%1$s` pour faire le rapport %2$s: %3$s.\n" + +#: src/io/output.c:14 #, c-format msgid "Writing %1$s report in `%2$s`.\n" msgstr "Écriture du rapport %1$s dans `%2$s`.\n" diff --git a/src/io/output.c b/src/io/output.c index be5dda10..d3fd05d1 100644 --- a/src/io/output.c +++ b/src/io/output.c @@ -2,6 +2,7 @@ #include #include #include +#include #include "criterion/output.h" #include "criterion/logging.h" #include "string/i18n.h" @@ -9,10 +10,10 @@ typedef const char *const msg_t; #ifdef ENABLE_NLS -static msg_t msg_err = N_("Could not open the file @ `%1$s` for %2$s reporting.\n"); +static msg_t msg_err = N_("Could not open the file @ `%1$s` for %2$s reporting: %3$s.\n"); static msg_t msg_ok = N_("Writing %1$s report in `%2$s`.\n"); #else -static msg_t msg_err = "Could not open the file @ `%s` for %s reporting.\n"; +static msg_t msg_err = "Could not open the file @ `%s` for %s reporting: %s.\n"; static msg_t msg_ok = "Writing %s report in `%s`.\n"; #endif @@ -97,7 +98,8 @@ void process_all_output(struct criterion_global_stats *stats) { f = fopen(path, "w"); if (!f) { - criterion_perror(_(msg_err), path, name); + int errno2 = errno; + criterion_perror(_(msg_err), path, name, strerror(errno2)); continue; } From 8a0540b5ab6ca084b06d2e93e9e04a40aebeced0 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Fri, 27 Nov 2015 12:26:49 +0100 Subject: [PATCH 177/211] Revert "Added install checks on travis builds" This reverts commit 56f0abfd49f9002665cc92232b32bede37ea4a8a. --- .travis.yml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/.travis.yml b/.travis.yml index 3e4937b1..57fa7592 100644 --- a/.travis.yml +++ b/.travis.yml @@ -112,11 +112,6 @@ script: else TERM=dumb cmake --build . -- -j4 fi - - | - make DESTDIR=out install - diff <(find ../include/ | sed 's/^..\///g') \ - <(find out/usr/local/include/ | sed 's/out\/usr\/local\///g') \ - || exit 1 after_success: - | From 3e489597983b49b183d8746dec24be0df8aed552 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Fri, 27 Nov 2015 12:31:38 +0100 Subject: [PATCH 178/211] Added --quiet implication of having a provider write to stderr in documentation --- doc/env.rst | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/doc/env.rst b/doc/env.rst index 2205bc51..e980f71d 100644 --- a/doc/env.rst +++ b/doc/env.rst @@ -24,19 +24,20 @@ Command line arguments * ``-S or --short-filename``: The filenames are displayed in their short form. * ``--always-succeed``: The process shall exit with a status of ``0``. * ``--tap[=FILE]``: Writes a TAP (Test Anything Protocol) report to FILE. - No file or ``"-"`` means ``stderr``. This option is equivalent to - ``--output=tap:FILE``. + No file or ``"-"`` means ``stderr`` and implies ``--quiet``. This option is + equivalent to ``--output=tap:FILE``. * ``--xml[=FILE]``: Writes JUnit4 XML report to FILE. - No file or ``"-"`` means ``stderr``. This option is equivalent to - ``--output=xml:FILE``. + No file or ``"-"`` means ``stderr`` and implies ``--quiet``. This option is + equivalent to ``--output=tap:FILE``. * ``--json[=FILE]``: Writes a JSON report to FILE. - No file or ``"-"`` means ``stderr``. This option is equivalent to - ``--output=json:FILE``. + No file or ``"-"`` means ``stderr`` and implies ``--quiet``. This option is + equivalent to ``--output=tap:FILE``. * ``--verbose[=level]``: Makes the output verbose. When provided with an integer, sets the verbosity level to that integer. * ``-OPROVIDER:FILE or --output=PROVIDER:FILE``: Write a test report to FILE - using the output provider named by PROVIDER. FILE may be a relative path, or - ``"-"`` to write to ``stderr``. + using the output provider named by PROVIDER. + If FILE is ``"-"``, it implies ``--quiet``, and the report shall be written + to ``stderr``. Shell Wildcard Pattern ---------------------- From d16ce3ae615a0ec0635f3b006def9843e9e8d08c Mon Sep 17 00:00:00 2001 From: Snaipe Date: Fri, 27 Nov 2015 12:52:40 +0100 Subject: [PATCH 179/211] Refactored main.c -> params.c --- CMakeLists.txt | 2 +- src/entry/{main.c => params.c} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename src/entry/{main.c => params.c} (100%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 15b7f398..4c32d647 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -174,7 +174,7 @@ set(SOURCE_FILES src/string/i18n.c src/string/i18n.h src/entry/options.c - src/entry/main.c + src/entry/params.c src/entry/entry.c src/common.h src/config.h diff --git a/src/entry/main.c b/src/entry/params.c similarity index 100% rename from src/entry/main.c rename to src/entry/params.c From 090e8571fe8250d6771faf8686d51244627a098f Mon Sep 17 00:00:00 2001 From: Snaipe Date: Fri, 27 Nov 2015 12:55:24 +0100 Subject: [PATCH 180/211] Added missing license headers --- include/criterion/internal/redirect.h | 23 +++++++++++++++++++++++ src/compat/time.h | 23 +++++++++++++++++++++++ src/entry/entry.c | 23 +++++++++++++++++++++++ src/string/i18n.h | 23 +++++++++++++++++++++++ 4 files changed, 92 insertions(+) diff --git a/include/criterion/internal/redirect.h b/include/criterion/internal/redirect.h index 64c003b7..4d4914d2 100644 --- a/include/criterion/internal/redirect.h +++ b/include/criterion/internal/redirect.h @@ -1,3 +1,26 @@ +/* + * The MIT License (MIT) + * + * Copyright © 2015 Franklin "Snaipe" Mathieu + * + * 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 CRITERION_INTERNAL_REDIRECT_H_ # define CRITERION_INTERNAL_REDIRECT_H_ diff --git a/src/compat/time.h b/src/compat/time.h index 14f301d9..427a137c 100644 --- a/src/compat/time.h +++ b/src/compat/time.h @@ -1,3 +1,26 @@ +/* + * The MIT License (MIT) + * + * Copyright © 2015 Franklin "Snaipe" Mathieu + * + * 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 TIMER_H_ # define TIMER_H_ diff --git a/src/entry/entry.c b/src/entry/entry.c index 71e9b9d0..25301b11 100644 --- a/src/entry/entry.c +++ b/src/entry/entry.c @@ -1,3 +1,26 @@ +/* + * The MIT License (MIT) + * + * Copyright © 2015 Franklin "Snaipe" Mathieu + * + * 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. + */ #include "criterion/criterion.h" CR_API int main(int argc, char *argv[]) { diff --git a/src/string/i18n.h b/src/string/i18n.h index 827dc0a2..8613c9d2 100644 --- a/src/string/i18n.h +++ b/src/string/i18n.h @@ -1,3 +1,26 @@ +/* + * The MIT License (MIT) + * + * Copyright © 2015 Franklin "Snaipe" Mathieu + * + * 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 I18N_H_ # define I18N_H_ From d55869a5e52eadbb39e6980b107711b221543985 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Fri, 27 Nov 2015 13:43:59 +0100 Subject: [PATCH 181/211] Moved criterion_test_params to internal API --- include/criterion/internal/parameterized.h | 42 ++++++++++++++++++++++ include/criterion/types.h | 42 +--------------------- src/core/runner_coroutine.c | 1 + 3 files changed, 44 insertions(+), 41 deletions(-) diff --git a/include/criterion/internal/parameterized.h b/include/criterion/internal/parameterized.h index c254531d..4fbd5117 100644 --- a/include/criterion/internal/parameterized.h +++ b/include/criterion/internal/parameterized.h @@ -27,6 +27,48 @@ # include "test.h" # include "../types.h" +struct criterion_test_params { + size_t size; + void *params; + size_t length; + void (*cleanup)(struct criterion_test_params *); + +# ifdef __cplusplus + constexpr criterion_test_params(size_t size, void *params, size_t length) + : size(size) + , params(params) + , length(length) + , cleanup(nullptr) + {} + + constexpr criterion_test_params(size_t size, void *params, size_t length, + void (*cleanup)(struct criterion_test_params *)) + : size(size) + , params(params) + , length(length) + , cleanup(cleanup) + {} + + template + constexpr criterion_test_params(std::vector>& vec, + void (*cleanup)(criterion_test_params *) = nullptr) + : size(sizeof (T)) + , params(&vec[0]) + , length(vec.size()) + , cleanup(cleanup) + {} + + template + constexpr criterion_test_params(T (&arr)[N], + void (*cleanup)(criterion_test_params *) = nullptr) + : size(sizeof (arr[0])) + , params(static_cast(&arr)) + , length(N) + , cleanup(cleanup) + {} +# endif +}; + # ifdef __cplusplus # define CR_PARAM_TEST_PROTOTYPE_(Param, Category, Name) \ extern "C" void CR_IDENTIFIER_(Category, Name, impl)(Param) diff --git a/include/criterion/types.h b/include/criterion/types.h index 905b6ac0..5c9cc33b 100644 --- a/include/criterion/types.h +++ b/include/criterion/types.h @@ -51,47 +51,7 @@ enum criterion_test_kind { CR_TEST_PARAMETERIZED, }; -struct criterion_test_params { - size_t size; - void *params; - size_t length; - void (*cleanup)(struct criterion_test_params *); - -# ifdef __cplusplus - constexpr criterion_test_params(size_t size, void *params, size_t length) - : size(size) - , params(params) - , length(length) - , cleanup(nullptr) - {} - - constexpr criterion_test_params(size_t size, void *params, size_t length, - void (*cleanup)(struct criterion_test_params *)) - : size(size) - , params(params) - , length(length) - , cleanup(cleanup) - {} - - template - constexpr criterion_test_params(std::vector>& vec, - void (*cleanup)(criterion_test_params *) = nullptr) - : size(sizeof (T)) - , params(&vec[0]) - , length(vec.size()) - , cleanup(cleanup) - {} - - template - constexpr criterion_test_params(T (&arr)[N], - void (*cleanup)(criterion_test_params *) = nullptr) - : size(sizeof (arr[0])) - , params(static_cast(&arr)) - , length(N) - , cleanup(cleanup) - {} -# endif -}; +struct criterion_test_params; struct criterion_test_extra_data { int sentinel_; diff --git a/src/core/runner_coroutine.c b/src/core/runner_coroutine.c index 50f336c6..57a091a5 100644 --- a/src/core/runner_coroutine.c +++ b/src/core/runner_coroutine.c @@ -25,6 +25,7 @@ #include #include #include "criterion/logging.h" +#include "criterion/internal/parameterized.h" #include "runner_coroutine.h" #include "worker.h" #include "stats.h" From 4185058a896594ca78786fd739db9748cd0fb76a Mon Sep 17 00:00:00 2001 From: Snaipe Date: Fri, 27 Nov 2015 13:45:23 +0100 Subject: [PATCH 182/211] Added doxygen-style doc in criterion.h --- include/criterion/criterion.h | 70 +++++++++++++++++++++++++++++++++++ include/criterion/types.h | 17 +++++++-- 2 files changed, 83 insertions(+), 4 deletions(-) diff --git a/include/criterion/criterion.h b/include/criterion/criterion.h index c90114e6..e1ce1581 100644 --- a/include/criterion/criterion.h +++ b/include/criterion/criterion.h @@ -30,16 +30,86 @@ # include "internal/test.h" +/** + * Test(Suite, Name, [Options...]) { Function body } + * + * Defines a new test. + * + * @param Suite The name of the test suite containing this test. + * @param Name The name of the test. + * @param Options An optional sequence of designated initializer key/value + * pairs as described in the `criterion_test_extra_data` structure + * (see criterion/types.h). + * Example: .exit_code = 1 + */ # define Test(...) CR_EXPAND(CR_TEST_BASE(__VA_ARGS__, .sentinel_ = 0)) +/** + * TestSuite(Name, [Options...]); + * + * Explicitely defines a test suite and its options. + * + * @param Name The name of the test suite. + * @param Options An optional sequence of designated initializer key/value + * pairs as described in the `criterion_test_extra_data` structure + * (see criterion/types.h). + * These options will provide the defaults for each test. + */ # define TestSuite(...) CR_EXPAND(CR_SUITE_BASE(__VA_ARGS__, .sentinel_ = 0)) CR_BEGIN_C_API +/** + * Initializes criterion and builds a set of all discovered tests. + * + * Using any of the functions and macros provided by criterion before calling + * this results in undefined behaviour. + * + * @returns the set of tests + */ CR_API struct criterion_test_set *criterion_initialize(void); + +/** + * Release all resources allocated by criterion. + * + * Using any of the functions and macros provided by criterion except + * criterion_initialize after this function is called results in undefined + * behaviour. + */ CR_API void criterion_finalize(struct criterion_test_set *tests); + +/** + * Run all the tests in the test set. + * + * @param[in] tests The set of tests that are to be executed. + * + * @returns 1 if all tests succeeded or criterion_options.always_succeed + * is true, 0 otherwise. + */ CR_API int criterion_run_all_tests(struct criterion_test_set *tests); + +/** + * Handles all default command-line parameters, as documented in: + * , and appropriately + * sets criterion_options. + * + * @param[in] argc The number of arguments in argv. + * @param[in] argv A null-terminated array of strings representing the arguments. + * @param[in] handle_unknown_arg Whether the function should print a message + * and exit when an unknown parameter is encountered. Use false if you want + * to handle additional parameters yourself. + * + * @returns 0 if the process should exit immediately after, for instance after + * printing the help message. + */ CR_API int criterion_handle_args(int argc, char *argv[], bool handle_unknown_arg); + +/** + * Manually registers a new test within the specified test set. + * + * @param[in] tests The set of tests you want to insert the test in. + * @param[in] test The newly created test. + */ CR_API void criterion_register_test(struct criterion_test_set *tests, struct criterion_test *test); diff --git a/include/criterion/types.h b/include/criterion/types.h index 5c9cc33b..2bb4a91d 100644 --- a/include/criterion/types.h +++ b/include/criterion/types.h @@ -36,10 +36,10 @@ using std::size_t; # include "internal/common.h" enum criterion_language { - CR_LANG_C, - CR_LANG_CXX, - CR_LANG_OBJC, - CR_LANG_OBJCXX, + CR_LANG_C, /// C + CR_LANG_CXX, /// C++ + CR_LANG_OBJC, /// Objective-C + CR_LANG_OBJCXX, /// Objective-C++ CR_LANG_SIZE_ // leave this at the end }; @@ -54,6 +54,13 @@ enum criterion_test_kind { struct criterion_test_params; struct criterion_test_extra_data { + // Start of private API + /* + * Warning: the fields below are not meant to be set manually. + * Setting them improperly *will* wreck havock in your tests. + * + * You've been warned. + */ int sentinel_; enum criterion_language lang_; enum criterion_test_kind kind_; @@ -61,6 +68,8 @@ struct criterion_test_extra_data { const char *identifier_; const char *file_; unsigned line_; + // Enf of private API + void (*init)(void); void (*fini)(void); int signal; From 5fddb5a0c8c35cb42f83f2cd4f142fa623db1d8b Mon Sep 17 00:00:00 2001 From: Snaipe Date: Fri, 27 Nov 2015 13:57:38 +0100 Subject: [PATCH 183/211] Added doxygen docs for types.h --- include/criterion/types.h | 35 +++++++++++++++++++++++++++-------- 1 file changed, 27 insertions(+), 8 deletions(-) diff --git a/include/criterion/types.h b/include/criterion/types.h index 2bb4a91d..e2a18d39 100644 --- a/include/criterion/types.h +++ b/include/criterion/types.h @@ -35,6 +35,9 @@ using std::size_t; # endif # include "internal/common.h" +/** + * Enumerates the supported languages for tests + */ enum criterion_language { CR_LANG_C, /// C CR_LANG_CXX, /// C++ @@ -46,13 +49,23 @@ enum criterion_language { extern const char *const cr_language_names[CR_LANG_SIZE_]; +/** + * Enumerates the supported kinds of tests + */ enum criterion_test_kind { CR_TEST_NORMAL, CR_TEST_PARAMETERIZED, }; +/** + * Represents a set of parameters for a parameterized test. + */ struct criterion_test_params; +/** + * Contains all the options that can be set for a test, through + * the Test and TestSuite macros, or other means. + */ struct criterion_test_extra_data { // Start of private API /* @@ -70,16 +83,19 @@ struct criterion_test_extra_data { unsigned line_; // Enf of private API - void (*init)(void); - void (*fini)(void); - int signal; - int exit_code; - bool disabled; - const char *description; - double timeout; - void *data; + void (*init)(void); /// The setup test fixture + void (*fini)(void); /// The setup test fixture + int signal; /// The expected signal raised by the test (or 0 if none) + int exit_code; /// The expected exit code returned by the test + bool disabled; /// Whether the test is disabled or not + const char *description; /// The description of a test + double timeout; /// A timeout for the test in seconds + void *data; /// Extra user data }; +/** + * Represents a test + */ struct criterion_test { const char *name; const char *category; @@ -87,6 +103,9 @@ struct criterion_test { struct criterion_test_extra_data *data; }; +/** + * Represents a test suite + */ struct criterion_suite { const char *name; struct criterion_test_extra_data *data; From d25ea68eb175f488d9df8cdc240dd4443801e84c Mon Sep 17 00:00:00 2001 From: Snaipe Date: Fri, 27 Nov 2015 14:21:50 +0100 Subject: [PATCH 184/211] Removed the worker function pointer typedef from the public API --- include/criterion/types.h | 2 -- src/compat/process.h | 2 ++ 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/criterion/types.h b/include/criterion/types.h index e2a18d39..4734656c 100644 --- a/include/criterion/types.h +++ b/include/criterion/types.h @@ -123,6 +123,4 @@ struct criterion_test_set { size_t tests; }; -typedef void (*cr_worker_func)(struct criterion_test *, struct criterion_suite *); - #endif /* !CRITERION_TYPES_H_ */ diff --git a/src/compat/process.h b/src/compat/process.h index 8b965ab4..1259e7ea 100644 --- a/src/compat/process.h +++ b/src/compat/process.h @@ -27,6 +27,8 @@ # include "criterion/types.h" # include "internal.h" +typedef void (*cr_worker_func)(struct criterion_test *, struct criterion_suite *); + struct proc_handle { #ifdef VANILLA_WIN32 HANDLE handle; From 5101a514a3eaa75a4d9b7f3e0a4925b643551f15 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Fri, 27 Nov 2015 15:42:05 +0100 Subject: [PATCH 185/211] Moved cr_translate_assert_msg out of the public API --- include/criterion/assert.h | 6 ------ include/criterion/internal/assert.h | 6 ++++++ 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/include/criterion/assert.h b/include/criterion/assert.h index 3c692830..fee1d4e8 100644 --- a/include/criterion/assert.h +++ b/include/criterion/assert.h @@ -30,12 +30,6 @@ # include "internal/assert.h" -CR_BEGIN_C_API - -CR_API char *cr_translate_assert_msg(int msg_index, ...); - -CR_END_C_API - // Base assertions # define cr_assert_fail(...) CR_EXPAND(cr_fail(CR_FAIL_ABORT_, __VA_ARGS__)) diff --git a/include/criterion/internal/assert.h b/include/criterion/internal/assert.h index 426e3aef..fd79d793 100644 --- a/include/criterion/internal/assert.h +++ b/include/criterion/internal/assert.h @@ -70,6 +70,12 @@ enum criterion_assert_messages { CRITERION_ASSERT_MSG_NONE_THROW, }; +CR_BEGIN_C_API + +CR_API char *cr_translate_assert_msg(int msg_index, ...); + +CR_END_C_API + # define CR_GET_CONDITION(Condition, ...) Condition # define CR_GET_CONDITION_STR(Condition, ...) #Condition # define CR_VA_SKIP(_, ...) __VA_ARGS__ From c4bc28b7fbf6b5e7d3a9a2c8c83b794db0cdb43a Mon Sep 17 00:00:00 2001 From: Snaipe Date: Fri, 27 Nov 2015 15:53:10 +0100 Subject: [PATCH 186/211] Added THEORIES cmake option --- CMakeLists.txt | 35 +++++++++++++++++++++++++++++------ samples/CMakeLists.txt | 9 +++++++-- samples/tests/CMakeLists.txt | 9 +++++++-- test/CMakeLists.txt | 7 ++++++- 4 files changed, 49 insertions(+), 11 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 4c32d647..21356c0f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -7,6 +7,12 @@ set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${MODULE_DIR}) set(LIBCSPTR_DISABLE_TESTS ON) set(LIBCSPTR_DISABLE_COVERALLS ON) +# Content options + +option(THEORIES "Activate the support for theories" ON) + +# Initialization + include(Submodules) include(Capabilities) @@ -15,7 +21,11 @@ if (MSVC) endif () add_subdirectory(dependencies/libcsptr/ EXCLUDE_FROM_ALL) -add_subdirectory(dependencies/dyncall/ EXCLUDE_FROM_ALL) + +if (THEORIES) + add_subdirectory(dependencies/dyncall/ EXCLUDE_FROM_ALL) + include_directories(dependencies/dyncall/dyncall/) +endif () include_directories(SYSTEM /usr/local/include @@ -24,7 +34,6 @@ include_directories(SYSTEM include_directories( dependencies/libcsptr/include/ - dependencies/dyncall/dyncall/ dependencies/valgrind/include/ dependencies/klib/ ) @@ -140,7 +149,6 @@ set(SOURCE_FILES src/core/stats.c src/core/stats.h src/core/ordered-set.c - src/core/theories.c src/compat/internal.h src/compat/pipe.c src/compat/pipe.h @@ -180,6 +188,12 @@ set(SOURCE_FILES src/config.h ) +if (THEORIES) + set (SOURCE_FILES ${SOURCE_FILES} + src/core/theories.c + ) +endif () + if (PCRE_FOUND) set (SOURCE_FILES ${SOURCE_FILES} src/string/extmatch.c @@ -215,7 +229,6 @@ set(INTERFACE_FILES include/criterion/types.h include/criterion/options.h include/criterion/stats.h - include/criterion/theories.h include/criterion/alloc.h include/criterion/parameterized.h include/criterion/redirect.h @@ -227,7 +240,6 @@ set(INTERFACE_FILES include/criterion/internal/asprintf-compat.h include/criterion/internal/designated-initializer-compat.h include/criterion/internal/preprocess.h - include/criterion/internal/theories.h include/criterion/internal/parameterized.h include/criterion/internal/stdio_filebuf.hxx include/criterion/internal/stream.hxx @@ -236,6 +248,13 @@ set(INTERFACE_FILES include/criterion/internal/stdio_filebuf.hxx ) +if (THEORIES) + set(INTERFACE_FILES ${INTERFACE_FILES} + include/criterion/theories.h + include/criterion/internal/theories.h + ) +endif() + # Generate the configure file configure_file( @@ -245,7 +264,11 @@ configure_file( include_directories(include src) add_library(criterion SHARED ${SOURCE_FILES} ${INTERFACE_FILES}) -target_link_libraries(criterion csptr dyncall_s) +target_link_libraries(criterion csptr) + +if (THEORIES) + target_link_libraries(criterion dyncall_s) +endif () if (MSVC) target_link_libraries(criterion wingetopt) diff --git a/samples/CMakeLists.txt b/samples/CMakeLists.txt index e56eeae5..799a7589 100644 --- a/samples/CMakeLists.txt +++ b/samples/CMakeLists.txt @@ -14,7 +14,6 @@ set(SAMPLES more-suites.c description.c simple.c - theories.c timeout.c redirect.c parameterized.c @@ -31,12 +30,18 @@ if (CMAKE_CXX_COMPILER_WORKS) more-suites.cc description.cc simple.cc - theories.cc redirect.cc parameterized.cc ) endif () +if (THEORIES) + set(SAMPLES ${SAMPLES} theories.c) + if (CMAKE_CXX_COMPILER_WORKS) + set(SAMPLES ${SAMPLES} theories.cc) + endif () +endif () + set(SCRIPTS tap_test xml_test diff --git a/samples/tests/CMakeLists.txt b/samples/tests/CMakeLists.txt index 4a38382e..9432b91e 100644 --- a/samples/tests/CMakeLists.txt +++ b/samples/tests/CMakeLists.txt @@ -3,7 +3,6 @@ set(SAMPLES exit.c long-messages.c other-crashes.c - theories_regression.c ) @@ -13,10 +12,16 @@ if (CMAKE_CXX_COMPILER_WORKS) exit.cc long-messages.cc other-crashes.cc - theories_regression.cc exception.cc ) endif () +if (THEORIES) + set(SAMPLES ${SAMPLES} theories_regression.c) + if (CMAKE_CXX_COMPILER_WORKS) + set(SAMPLES ${SAMPLES} theories_regression.cc) + endif () +endif () + add_samples("${CMAKE_CURRENT_LIST_DIR}" "${SAMPLES}") diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 3e7c7476..f23ac22e 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -9,9 +9,14 @@ include_directories(../include ../src) set(TEST_SOURCES ordered-set.c - asprintf.c ) +if (THEORIES) + set(TEST_SOURCES ${TEST_SOURCES} + asprintf.c + ) +endif () + if (CMAKE_CXX_COMPILER_WORKS) set(TEST_SOURCES ${TEST_SOURCES} redirect.cc From 2ccbdbd578a6c8ef397d6b5c0c827474bd9b271d Mon Sep 17 00:00:00 2001 From: Snaipe Date: Sat, 28 Nov 2015 14:26:08 +0100 Subject: [PATCH 187/211] Added deb generation rules in cmake module --- .cmake/Modules/DebConfig.cmake | 41 +++ .cmake/Modules/DebSourcePPA.cmake | 347 ++++++++++++++++++++++++++ .cmake/Modules/GettextTranslate.cmake | 2 +- .cmake/Modules/PackageConfig.cmake | 79 ++++++ .cmake/copy-source.sh | 11 + .cmake/git-archive-all.sh | 302 ++++++++++++++++++++++ .gitignore | 2 +- CMakeLists.txt | 14 +- 8 files changed, 795 insertions(+), 3 deletions(-) create mode 100644 .cmake/Modules/DebConfig.cmake create mode 100644 .cmake/Modules/DebSourcePPA.cmake create mode 100644 .cmake/Modules/PackageConfig.cmake create mode 100755 .cmake/copy-source.sh create mode 100755 .cmake/git-archive-all.sh diff --git a/.cmake/Modules/DebConfig.cmake b/.cmake/Modules/DebConfig.cmake new file mode 100644 index 00000000..e8a4c73f --- /dev/null +++ b/.cmake/Modules/DebConfig.cmake @@ -0,0 +1,41 @@ +# build a Debian package for Launchpad +set(CPACK_DEBIAN_PACKAGE_NAME "criterion") +set(CPACK_DEBIAN_PACKAGE_PRIORITY "optional") +set(CPACK_DEBIAN_PACKAGE_SECTION "libs") +set(CPACK_DEBIAN_PACKAGE_HOMEPAGE "https://github.com/Snaipe/Criterion") +set(CPACK_DEBIAN_BUILD_DEPENDS + debhelper + cmake + gettext + libpcre3-dev + gcc-4.9 + g++-4.9 + gobjc-4.9 + gnustep-devel +) + +set(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_SOURCE_DIR}/description.txt") + +set(CPACK_DEBIAN_PACKAGE_SOURCE_COPY "${CMAKE_SOURCE_DIR}/.cmake/copy-source.sh") + +set(CPACK_DEBIAN_DISTRIBUTION_NAME ubuntu) +set(CPACK_DEBIAN_DISTRIBUTION_RELEASES precise trusty vivid wily xenial) + +set(DPUT_HOST "snaipewastaken-ppa") +set(DPUT_SNAPSHOT_HOST "snaipewastaken-ppa") +set(CPACK_DEBIAN_PACKAGE_DOCS "") +set(CPACK_DEBIAN_PACKAGE_INSTALL + "/usr/lib/*.so" + "/usr/lib/*.so.*" + "/usr/share/locale/*" +) + +set(CPACK_COMPONENTS_ALL "dev") +set(CPACK_COMPONENT_DEV_DISPLAY_NAME "Criterion library development files") +set(CPACK_COMPONENT_DEV_DESCRIPTION "These are the development files.") +set(CPACK_COMPONENT_DEV_SECTION "devel") + +set(CPACK_COMPONENT_DEV_DOCS "") +set(CPACK_COMPONENT_DEV_INSTALL "/usr/include") + +include (DebSourcePPA) diff --git a/.cmake/Modules/DebSourcePPA.cmake b/.cmake/Modules/DebSourcePPA.cmake new file mode 100644 index 00000000..f948ed5b --- /dev/null +++ b/.cmake/Modules/DebSourcePPA.cmake @@ -0,0 +1,347 @@ +## Debian Source Package Generator +# +# Copyright (c) 2010 Daniel Pfeifer +# Many modifications by Rosen Diankov +# +# Creates source debian files and manages library dependencies +# +# Features: +# +# - Automatically generates symbols and run-time dependencies from the build dependencies +# - Custom copy of source directory via CPACK_DEBIAN_PACKAGE_SOURCE_COPY +# - Simultaneous output of multiple debian source packages for each distribution +# - Can specificy distribution-specific dependencies by suffixing DEPENDS with _${DISTRO_NAME}, for example: CPACK_DEBIAN_PACKAGE_DEPENDS_LUCID, CPACK_COMPONENT_MYCOMP0_DEPENDS_LUCID +# +# Usage: +# +# set(CPACK_DEBIAN_BUILD_DEPENDS debhelper cmake) +# set(CPACK_DEBIAN_PACKAGE_PRIORITY optional) +# set(CPACK_DEBIAN_PACKAGE_SECTION devel) +# set(CPACK_DEBIAN_CMAKE_OPTIONS "-DMYOPTION=myvalue") +# set(CPACK_DEBIAN_PACKAGE_DEPENDS mycomp0 mycomp1 some_ubuntu_package) +# set(CPACK_DEBIAN_PACKAGE_DEPENDS_UBUNTU_LUCID mycomp0 mycomp1 lucid_specific_package) +# set(CPACK_DEBIAN_PACKAGE_NAME mypackage) +# set(CPACK_DEBIAN_PACKAGE_REMOVE_SOURCE_FILES unnecessary_file unnecessary_dir/file0) +# set(CPACK_DEBIAN_PACKAGE_SOURCE_COPY svn export --force) # if using subversion +# set(CPACK_DEBIAN_DISTRIBUTION_NAME ubuntu) +# set(CPACK_DEBIAN_DISTRIBUTION_RELEASES karmic lucid maverick natty) +# set(CPACK_DEBIAN_CHANGELOG " * Extra change log lines") +# set(CPACK_DEBIAN_PACKAGE_SUGGESTS "ipython") +# set(CPACK_COMPONENT_X_RECOMMENDS "recommended-package") +## + +find_program(DEBUILD_EXECUTABLE debuild) +find_program(DPUT_EXECUTABLE dput) + +if(NOT DEBUILD_EXECUTABLE OR NOT DPUT_EXECUTABLE) + return() +endif(NOT DEBUILD_EXECUTABLE OR NOT DPUT_EXECUTABLE) + +# DEBIAN/control +# debian policy enforce lower case for package name +# Package: (mandatory) +IF(NOT CPACK_DEBIAN_PACKAGE_NAME) + STRING(TOLOWER "${CPACK_PACKAGE_NAME}" CPACK_DEBIAN_PACKAGE_NAME) +ENDIF(NOT CPACK_DEBIAN_PACKAGE_NAME) + +# Section: (recommended) +IF(NOT CPACK_DEBIAN_PACKAGE_SECTION) + SET(CPACK_DEBIAN_PACKAGE_SECTION "devel") +ENDIF(NOT CPACK_DEBIAN_PACKAGE_SECTION) + +# Priority: (recommended) +IF(NOT CPACK_DEBIAN_PACKAGE_PRIORITY) + SET(CPACK_DEBIAN_PACKAGE_PRIORITY "optional") +ENDIF(NOT CPACK_DEBIAN_PACKAGE_PRIORITY) + +file(STRINGS ${CPACK_PACKAGE_DESCRIPTION_FILE} DESC_LINES) +foreach(LINE ${DESC_LINES}) + set(DEB_LONG_DESCRIPTION "${DEB_LONG_DESCRIPTION} ${LINE}\n") +endforeach(LINE ${DESC_LINES}) + +file(REMOVE_RECURSE "${CMAKE_BINARY_DIR}/Debian") +file(MAKE_DIRECTORY "${CMAKE_BINARY_DIR}/Debian") +set(DEBIAN_SOURCE_ORIG_DIR "${CMAKE_BINARY_DIR}/Debian/${CPACK_DEBIAN_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}") + +if( CPACK_DEBIAN_PACKAGE_SOURCE_COPY ) + execute_process(COMMAND ${CPACK_DEBIAN_PACKAGE_SOURCE_COPY} "${CMAKE_SOURCE_DIR}" "${DEBIAN_SOURCE_ORIG_DIR}.orig") +else() + execute_process(COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_SOURCE_DIR} "${DEBIAN_SOURCE_ORIG_DIR}.orig") + execute_process(COMMAND ${CMAKE_COMMAND} -E remove_directory "${DEBIAN_SOURCE_ORIG_DIR}.orig/.git") + execute_process(COMMAND ${CMAKE_COMMAND} -E remove_directory "${DEBIAN_SOURCE_ORIG_DIR}.orig/.svn") +endif() + +# remove unnecessary folders +foreach(REMOVE_DIR ${CPACK_DEBIAN_PACKAGE_REMOVE_SOURCE_FILES}) + file(REMOVE_RECURSE ${DEBIAN_SOURCE_ORIG_DIR}.orig/${REMOVE_DIR}) +endforeach() + +# create the original source tar +execute_process(COMMAND ${CMAKE_COMMAND} -E tar czf "${CPACK_DEBIAN_PACKAGE_NAME}_${CPACK_PACKAGE_VERSION}.orig.tar.gz" "${CPACK_DEBIAN_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}.orig" WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/Debian) + +set(DEB_SOURCE_CHANGES) +foreach(RELEASE ${CPACK_DEBIAN_DISTRIBUTION_RELEASES}) + set(DEBIAN_SOURCE_DIR "${DEBIAN_SOURCE_ORIG_DIR}-${CPACK_DEBIAN_DISTRIBUTION_NAME}1~${RELEASE}1") + set(RELEASE_PACKAGE_VERSION "${CPACK_PACKAGE_VERSION}-${CPACK_DEBIAN_DISTRIBUTION_NAME}1~${RELEASE}1") + string(TOUPPER ${RELEASE} RELEASE_UPPER) + string(TOUPPER ${CPACK_DEBIAN_DISTRIBUTION_NAME} DISTRIBUTION_NAME_UPPER) + file(MAKE_DIRECTORY ${DEBIAN_SOURCE_DIR}/debian) + ############################################################################## + # debian/control + set(DEBIAN_CONTROL ${DEBIAN_SOURCE_DIR}/debian/control) + file(WRITE ${DEBIAN_CONTROL} + "Source: ${CPACK_DEBIAN_PACKAGE_NAME}\n" + "Section: ${CPACK_DEBIAN_PACKAGE_SECTION}\n" + "Priority: ${CPACK_DEBIAN_PACKAGE_PRIORITY}\n" + "DM-Upload-Allowed: yes\n" + "Maintainer: ${CPACK_PACKAGE_CONTACT}\n" + "Build-Depends: " + ) + + if( CPACK_DEBIAN_BUILD_DEPENDS_${DISTRIBUTION_NAME_UPPER}_${RELEASE_UPPER} ) + foreach(DEP ${CPACK_DEBIAN_BUILD_DEPENDS_${DISTRIBUTION_NAME_UPPER}_${RELEASE_UPPER}}) + file(APPEND ${DEBIAN_CONTROL} "${DEP}, ") + endforeach(DEP ${CPACK_DEBIAN_BUILD_DEPENDS_${DISTRIBUTION_NAME_UPPER}_${RELEASE_UPPER}}) + else( CPACK_DEBIAN_BUILD_DEPENDS_${DISTRIBUTION_NAME_UPPER}_${RELEASE_UPPER} ) + if( CPACK_DEBIAN_BUILD_DEPENDS_${DISTRIBUTION_NAME_UPPER} ) + foreach(DEP ${CPACK_DEBIAN_BUILD_DEPENDS_${DISTRIBUTION_NAME_UPPER}}) + file(APPEND ${DEBIAN_CONTROL} "${DEP}, ") + endforeach(DEP ${CPACK_DEBIAN_BUILD_DEPENDS_${DISTRIBUTION_NAME_UPPER}}) + else( CPACK_DEBIAN_BUILD_DEPENDS_${DISTRIBUTION_NAME_UPPER} ) + foreach(DEP ${CPACK_DEBIAN_BUILD_DEPENDS}) + file(APPEND ${DEBIAN_CONTROL} "${DEP}, ") + endforeach(DEP ${CPACK_DEBIAN_BUILD_DEPENDS}) + endif( CPACK_DEBIAN_BUILD_DEPENDS_${DISTRIBUTION_NAME_UPPER} ) + endif( CPACK_DEBIAN_BUILD_DEPENDS_${DISTRIBUTION_NAME_UPPER}_${RELEASE_UPPER} ) + + + file(APPEND ${DEBIAN_CONTROL} "\n" + "Standards-Version: 3.8.4\n" + "Homepage: ${CPACK_PACKAGE_VENDOR}\n" + "\n" + "Package: ${CPACK_DEBIAN_PACKAGE_NAME}\n" + "Architecture: any\n" + "Depends: " + ) + + if( CPACK_DEBIAN_PACKAGE_DEPENDS_${DISTRIBUTION_NAME_UPPER}_${RELEASE_UPPER} ) + foreach(DEP ${CPACK_DEBIAN_PACKAGE_DEPENDS_${DISTRIBUTION_NAME_UPPER}_${RELEASE_UPPER}}) + file(APPEND ${DEBIAN_CONTROL} "${DEP}, ") + endforeach(DEP ${CPACK_DEBIAN_PACKAGE_DEPENDS_${DISTRIBUTION_NAME_UPPER}_${RELEASE_UPPER}}) + else( CPACK_DEBIAN_PACKAGE_DEPENDS_${DISTRIBUTION_NAME_UPPER}_${RELEASE_UPPER} ) + if( CPACK_DEBIAN_PACKAGE_DEPENDS_${DISTRIBUTION_NAME_UPPER} ) + foreach(DEP ${CPACK_DEBIAN_PACKAGE_DEPENDS_${DISTRIBUTION_NAME_UPPER}}) + file(APPEND ${DEBIAN_CONTROL} "${DEP}, ") + endforeach(DEP ${CPACK_DEBIAN_PACKAGE_DEPENDS_${DISTRIBUTION_NAME_UPPER}}) + else( CPACK_DEBIAN_PACKAGE_DEPENDS_${DISTRIBUTION_NAME_UPPER} ) + foreach(DEP ${CPACK_DEBIAN_PACKAGE_DEPENDS}) + file(APPEND ${DEBIAN_CONTROL} "${DEP}, ") + endforeach(DEP ${CPACK_DEBIAN_PACKAGE_DEPENDS}) + endif( CPACK_DEBIAN_PACKAGE_DEPENDS_${DISTRIBUTION_NAME_UPPER} ) + endif( CPACK_DEBIAN_PACKAGE_DEPENDS_${DISTRIBUTION_NAME_UPPER}_${RELEASE_UPPER} ) + + file(APPEND ${DEBIAN_CONTROL} "\nRecommends: ") + if( CPACK_DEBIAN_PACKAGE_RECOMMENDS_${DISTRIBUTION_NAME_UPPER}_${RELEASE_UPPER} ) + foreach(DEP ${CPACK_DEBIAN_PACKAGE_RECOMMENDS_${DISTRIBUTION_NAME_UPPER}_${RELEASE_UPPER}}) + file(APPEND ${DEBIAN_CONTROL} "${DEP}, ") + endforeach(DEP ${CPACK_DEBIAN_PACKAGE_RECOMMENDS_${DISTRIBUTION_NAME_UPPER}_${RELEASE_UPPER}}) + else( CPACK_DEBIAN_PACKAGE_RECOMMENDS_${DISTRIBUTION_NAME_UPPER}_${RELEASE_UPPER} ) + if( CPACK_DEBIAN_PACKAGE_RECOMMENDS_${DISTRIBUTION_NAME_UPPER} ) + foreach(DEP ${CPACK_DEBIAN_PACKAGE_RECOMMENDS_${DISTRIBUTION_NAME_UPPER}}) + file(APPEND ${DEBIAN_CONTROL} "${DEP}, ") + endforeach(DEP ${CPACK_DEBIAN_PACKAGE_RECOMMENDS_${DISTRIBUTION_NAME_UPPER}}) + else( CPACK_DEBIAN_PACKAGE_RECOMMENDS_${DISTRIBUTION_NAME_UPPER} ) + foreach(DEP ${CPACK_DEBIAN_PACKAGE_RECOMMENDS}) + file(APPEND ${DEBIAN_CONTROL} "${DEP}, ") + endforeach(DEP ${CPACK_DEBIAN_PACKAGE_RECOMMENDS}) + endif( CPACK_DEBIAN_PACKAGE_RECOMMENDS_${DISTRIBUTION_NAME_UPPER} ) + endif( CPACK_DEBIAN_PACKAGE_RECOMMENDS_${DISTRIBUTION_NAME_UPPER}_${RELEASE_UPPER} ) + + file(APPEND ${DEBIAN_CONTROL} "\nSuggests: ") + if( CPACK_DEBIAN_PACKAGE_SUGGESTS_${DISTRIBUTION_NAME_UPPER}_${RELEASE_UPPER} ) + foreach(DEP ${CPACK_DEBIAN_PACKAGE_SUGGESTS_${DISTRIBUTION_NAME_UPPER}_${RELEASE_UPPER}}) + file(APPEND ${DEBIAN_CONTROL} "${DEP}, ") + endforeach(DEP ${CPACK_DEBIAN_PACKAGE_SUGGESTS_${DISTRIBUTION_NAME_UPPER}_${RELEASE_UPPER}}) + else( CPACK_DEBIAN_PACKAGE_SUGGESTS_${DISTRIBUTION_NAME_UPPER}_${RELEASE_UPPER} ) + if( CPACK_DEBIAN_PACKAGE_SUGGESTS_${DISTRIBUTION_NAME_UPPER} ) + foreach(DEP ${CPACK_DEBIAN_PACKAGE_SUGGESTS_${DISTRIBUTION_NAME_UPPER}}) + file(APPEND ${DEBIAN_CONTROL} "${DEP}, ") + endforeach(DEP ${CPACK_DEBIAN_PACKAGE_SUGGESTS_${DISTRIBUTION_NAME_UPPER}}) + else( CPACK_DEBIAN_PACKAGE_SUGGESTS_${DISTRIBUTION_NAME_UPPER} ) + foreach(DEP ${CPACK_DEBIAN_PACKAGE_SUGGESTS}) + file(APPEND ${DEBIAN_CONTROL} "${DEP}, ") + endforeach(DEP ${CPACK_DEBIAN_PACKAGE_SUGGESTS}) + endif( CPACK_DEBIAN_PACKAGE_SUGGESTS_${DISTRIBUTION_NAME_UPPER} ) + endif( CPACK_DEBIAN_PACKAGE_SUGGESTS_${DISTRIBUTION_NAME_UPPER}_${RELEASE_UPPER} ) + + file(APPEND ${DEBIAN_CONTROL} "\n" + "Description: ${CPACK_PACKAGE_DISPLAY_NAME} ${CPACK_PACKAGE_DESCRIPTION_SUMMARY}\n" + "${DEB_LONG_DESCRIPTION}" + ) + + foreach(COMPONENT ${CPACK_COMPONENTS_ALL}) + string(TOUPPER ${COMPONENT} UPPER_COMPONENT) + set(DEPENDS "\${shlibs:Depends}") + if( CPACK_COMPONENT_${UPPER_COMPONENT}_DEPENDS_${DISTRIBUTION_NAME_UPPER}_${RELEASE_UPPER} ) + foreach(DEP ${CPACK_COMPONENT_${UPPER_COMPONENT}_DEPENDS_${DISTRIBUTION_NAME_UPPER}_${RELEASE_UPPER}}) + set(DEPENDS "${DEPENDS}, ${DEP}") + endforeach(DEP ${CPACK_COMPONENT_${UPPER_COMPONENT}_DEPENDS_${DISTRIBUTION_NAME_UPPER}_${RELEASE_UPPER}}) + else( CPACK_COMPONENT_${UPPER_COMPONENT}_DEPENDS_${DISTRIBUTION_NAME_UPPER}_${RELEASE_UPPER} ) + if( CPACK_COMPONENT_${UPPER_COMPONENT}_DEPENDS_${DISTRIBUTION_NAME_UPPER} ) + foreach(DEP ${CPACK_COMPONENT_${UPPER_COMPONENT}_DEPENDS_${DISTRIBUTION_NAME_UPPER}}) + set(DEPENDS "${DEPENDS}, ${DEP}") + endforeach(DEP ${CPACK_COMPONENT_${UPPER_COMPONENT}_DEPENDS_${DISTRIBUTION_NAME_UPPER}}) + else( CPACK_COMPONENT_${UPPER_COMPONENT}_DEPENDS_${DISTRIBUTION_NAME_UPPER} ) + foreach(DEP ${CPACK_COMPONENT_${UPPER_COMPONENT}_DEPENDS}) + set(DEPENDS "${DEPENDS}, ${DEP}") + endforeach(DEP ${CPACK_COMPONENT_${UPPER_COMPONENT}_DEPENDS}) + endif( CPACK_COMPONENT_${UPPER_COMPONENT}_DEPENDS_${DISTRIBUTION_NAME_UPPER} ) + endif( CPACK_COMPONENT_${UPPER_COMPONENT}_DEPENDS_${DISTRIBUTION_NAME_UPPER}_${RELEASE_UPPER} ) + + set(RECOMMENDS) + if( CPACK_COMPONENT_${UPPER_COMPONENT}_RECOMMENDS_${DISTRIBUTION_NAME_UPPER}_${RELEASE_UPPER} ) + foreach(DEP ${CPACK_COMPONENT_${UPPER_COMPONENT}_RECOMMENDS_${DISTRIBUTION_NAME_UPPER}_${RELEASE_UPPER}}) + set(RECOMMENDS "${RECOMMENDS} ${DEP}, ") + endforeach(DEP ${CPACK_COMPONENT_${UPPER_COMPONENT}_RECOMMENDS_${DISTRIBUTION_NAME_UPPER}_${RELEASE_UPPER}}) + else( CPACK_COMPONENT_${UPPER_COMPONENT}_RECOMMENDS_${DISTRIBUTION_NAME_UPPER}_${RELEASE_UPPER} ) + if( CPACK_COMPONENT_${UPPER_COMPONENT}_RECOMMENDS_${DISTRIBUTION_NAME_UPPER} ) + foreach(DEP ${CPACK_COMPONENT_${UPPER_COMPONENT}_RECOMMENDS_${DISTRIBUTION_NAME_UPPER}}) + set(RECOMMENDS "${RECOMMENDS} ${DEP}, ") + endforeach(DEP ${CPACK_COMPONENT_${UPPER_COMPONENT}_RECOMMENDS_${DISTRIBUTION_NAME_UPPER}}) + else( CPACK_COMPONENT_${UPPER_COMPONENT}_RECOMMENDS_${DISTRIBUTION_NAME_UPPER} ) + foreach(DEP ${CPACK_COMPONENT_${UPPER_COMPONENT}_RECOMMENDS}) + set(RECOMMENDS "${RECOMMENDS} ${DEP}, ") + endforeach(DEP ${CPACK_COMPONENT_${UPPER_COMPONENT}_RECOMMENDS}) + endif( CPACK_COMPONENT_${UPPER_COMPONENT}_RECOMMENDS_${DISTRIBUTION_NAME_UPPER} ) + endif( CPACK_COMPONENT_${UPPER_COMPONENT}_RECOMMENDS_${DISTRIBUTION_NAME_UPPER}_${RELEASE_UPPER} ) + + set(SUGGESTS) + if( CPACK_COMPONENT_${UPPER_COMPONENT}_SUGGESTS_${DISTRIBUTION_NAME_UPPER}_${RELEASE_UPPER} ) + foreach(DEP ${CPACK_COMPONENT_${UPPER_COMPONENT}_SUGGESTS_${DISTRIBUTION_NAME_UPPER}_${RELEASE_UPPER}}) + set(SUGGESTS "${SUGGESTS} ${DEP}, ") + endforeach(DEP ${CPACK_COMPONENT_${UPPER_COMPONENT}_SUGGESTS_${DISTRIBUTION_NAME_UPPER}_${RELEASE_UPPER}}) + else( CPACK_COMPONENT_${UPPER_COMPONENT}_SUGGESTS_${DISTRIBUTION_NAME_UPPER}_${RELEASE_UPPER} ) + if( CPACK_COMPONENT_${UPPER_COMPONENT}_SUGGESTS_${DISTRIBUTION_NAME_UPPER} ) + foreach(DEP ${CPACK_COMPONENT_${UPPER_COMPONENT}_SUGGESTS_${DISTRIBUTION_NAME_UPPER}}) + set(SUGGESTS "${SUGGESTS} ${DEP}, ") + endforeach(DEP ${CPACK_COMPONENT_${UPPER_COMPONENT}_SUGGESTS_${DISTRIBUTION_NAME_UPPER}}) + else( CPACK_COMPONENT_${UPPER_COMPONENT}_SUGGESTS_${DISTRIBUTION_NAME_UPPER} ) + foreach(DEP ${CPACK_COMPONENT_${UPPER_COMPONENT}_SUGGESTS}) + set(SUGGESTS "${SUGGESTS} ${DEP}, ") + endforeach(DEP ${CPACK_COMPONENT_${UPPER_COMPONENT}_SUGGESTS}) + endif( CPACK_COMPONENT_${UPPER_COMPONENT}_SUGGESTS_${DISTRIBUTION_NAME_UPPER} ) + endif( CPACK_COMPONENT_${UPPER_COMPONENT}_SUGGESTS_${DISTRIBUTION_NAME_UPPER}_${RELEASE_UPPER} ) + + file(APPEND ${DEBIAN_CONTROL} "\n" + "Package: ${CPACK_DEBIAN_PACKAGE_NAME}-${COMPONENT}\n" + "Architecture: any\n" + "Depends: ${DEPENDS}\n" + "Recommends: ${RECOMMENDS}\n" + "Suggests: ${SUGGESTS}\n" + "Description: ${CPACK_PACKAGE_DISPLAY_NAME} ${CPACK_COMPONENT_${UPPER_COMPONENT}_DISPLAY_NAME}\n" + "${DEB_LONG_DESCRIPTION}" + " .\n" + " ${CPACK_COMPONENT_${UPPER_COMPONENT}_DESCRIPTION}\n" + ) + endforeach(COMPONENT ${CPACK_COMPONENTS_ALL}) + + ############################################################################## + # debian/copyright + set(DEBIAN_COPYRIGHT ${DEBIAN_SOURCE_DIR}/debian/copyright) + execute_process(COMMAND ${CMAKE_COMMAND} -E + copy ${CPACK_RESOURCE_FILE_LICENSE} ${DEBIAN_COPYRIGHT} + ) + + ############################################################################## + # debian/rules + set(DEBIAN_RULES ${DEBIAN_SOURCE_DIR}/debian/rules) + file(WRITE ${DEBIAN_RULES} + "#!/usr/bin/make -f\n" + "\n" + "BUILDDIR = build_dir\n" + "\n" + "build:\n" + " mkdir $(BUILDDIR)\n" + " cd $(BUILDDIR); cmake -DCMAKE_BUILD_TYPE=Release ${CPACK_DEBIAN_CMAKE_OPTIONS} -DCMAKE_INSTALL_PREFIX=/usr ..\n" + " $(MAKE) -C $(BUILDDIR) preinstall\n" + " touch build\n" + "\n" + "binary: binary-indep binary-arch\n" + "\n" + "binary-indep: build\n" + "\n" + "binary-arch: build\n" + " cd $(BUILDDIR); cmake -DCOMPONENT=Unspecified -DCMAKE_INSTALL_PREFIX=../debian/tmp/usr -P cmake_install.cmake\n" + " mkdir -p debian/tmp/DEBIAN\n" + " dpkg-gensymbols -p${CPACK_DEBIAN_PACKAGE_NAME}\n" + ) + + foreach(COMPONENT ${CPACK_COMPONENTS_ALL}) + set(PATH debian/${COMPONENT}) + file(APPEND ${DEBIAN_RULES} + " cd $(BUILDDIR); cmake -DCOMPONENT=${COMPONENT} -DCMAKE_INSTALL_PREFIX=../${PATH}/usr -P cmake_install.cmake\n" + " mkdir -p ${PATH}/DEBIAN\n" + " dpkg-gensymbols -p${CPACK_DEBIAN_PACKAGE_NAME}-${COMPONENT} -P${PATH}\n" + ) + endforeach(COMPONENT ${CPACK_COMPONENTS_ALL}) + + file(APPEND ${DEBIAN_RULES} + " dh_shlibdeps\n" + " dh_strip\n" # for reducing size + " dpkg-gencontrol -p${CPACK_DEBIAN_PACKAGE_NAME}\n" + " dpkg --build debian/tmp ..\n" + ) + + foreach(COMPONENT ${CPACK_COMPONENTS_ALL}) + set(PATH debian/${COMPONENT}) + file(APPEND ${DEBIAN_RULES} + " dpkg-gencontrol -p${CPACK_DEBIAN_PACKAGE_NAME}-${COMPONENT} -P${PATH} -Tdebian/${COMPONENT}.substvars\n" + " dpkg --build ${PATH} ..\n" + ) + endforeach(COMPONENT ${CPACK_COMPONENTS_ALL}) + + file(APPEND ${DEBIAN_RULES} + "\n" + "clean:\n" + " rm -f build\n" + " rm -rf $(BUILDDIR)\n" + "\n" + ".PHONY: binary binary-arch binary-indep clean\n" + ) + + execute_process(COMMAND chmod +x ${DEBIAN_RULES}) + + ############################################################################## + # debian/compat + file(WRITE ${DEBIAN_SOURCE_DIR}/debian/compat "7") + + ############################################################################## + # debian/source/format + file(WRITE ${DEBIAN_SOURCE_DIR}/debian/source/format "3.0 (quilt)") + + ############################################################################## + # debian/changelog + set(DEBIAN_CHANGELOG ${DEBIAN_SOURCE_DIR}/debian/changelog) + execute_process(COMMAND date -R OUTPUT_VARIABLE DATE_TIME) + file(WRITE ${DEBIAN_CHANGELOG} + "${CPACK_DEBIAN_PACKAGE_NAME} (${RELEASE_PACKAGE_VERSION}) ${RELEASE}; urgency=medium\n\n" + " * Package built with CMake\n\n" + "${CPACK_DEBIAN_CHANGELOG}" + " -- ${CPACK_PACKAGE_CONTACT} ${DATE_TIME}" + ) + + ############################################################################## + # debuild -S + if( DEB_SOURCE_CHANGES ) + set(DEBUILD_OPTIONS "-sd") + else() + set(DEBUILD_OPTIONS "-sa") + endif() + set(SOURCE_CHANGES_FILE "${CPACK_DEBIAN_PACKAGE_NAME}_${RELEASE_PACKAGE_VERSION}_source.changes") + set(DEB_SOURCE_CHANGES ${DEB_SOURCE_CHANGES} "${SOURCE_CHANGES_FILE}") + add_custom_command(OUTPUT "${SOURCE_CHANGES_FILE}" COMMAND ${DEBUILD_EXECUTABLE} -S ${DEBUILD_OPTIONS} WORKING_DIRECTORY ${DEBIAN_SOURCE_DIR}) +endforeach(RELEASE ${CPACK_DEBIAN_DISTRIBUTION_RELEASES}) + +############################################################################## +# dput ppa:your-lp-id/ppa +add_custom_target(dput ${DPUT_EXECUTABLE} ${DPUT_HOST} ${DEB_SOURCE_CHANGES} DEPENDS ${DEB_SOURCE_CHANGES} WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/Debian) diff --git a/.cmake/Modules/GettextTranslate.cmake b/.cmake/Modules/GettextTranslate.cmake index 02307ff0..4c42ef47 100644 --- a/.cmake/Modules/GettextTranslate.cmake +++ b/.cmake/Modules/GettextTranslate.cmake @@ -287,7 +287,7 @@ macro(GettextTranslate) add_dependencies(${PO_TARGET} ${MAKEVAR_DOMAIN}.pot-update) install(FILES ${GMO_FILE_NAME} DESTINATION - ${LOCALEDIR}/${lang}/LC_MESSAGES + ${LOCALEDIR_REL}/${lang}/LC_MESSAGES RENAME ${MAKEVAR_DOMAIN}.mo ) diff --git a/.cmake/Modules/PackageConfig.cmake b/.cmake/Modules/PackageConfig.cmake new file mode 100644 index 00000000..632d9b8a --- /dev/null +++ b/.cmake/Modules/PackageConfig.cmake @@ -0,0 +1,79 @@ + +function(extract_version version major minor patch extra) + string(REGEX MATCH "([0-9]+)\\.([0-9]+)\\.([0-9]+)(.*)?" version_valid ${version}) + if(version_valid) + string(REGEX REPLACE "([0-9]+)\\.([0-9]+)\\.([0-9]+)(.*)?" "\\1;\\2;\\3;\\4" VERSION_MATCHES ${version}) + list(GET VERSION_MATCHES 0 version_major) + set(${major} ${version_major} PARENT_SCOPE) + list(GET VERSION_MATCHES 1 version_minor) + set(${minor} ${version_minor} PARENT_SCOPE) + list(GET VERSION_MATCHES 2 version_patch) + set(${patch} ${version_patch} PARENT_SCOPE) + list(GET VERSION_MATCHES 3 version_extra) + set(${extra} ${version_extra} PARENT_SCOPE) + else(version_valid) + message(AUTHOR_WARNING "Bad version ${version}; falling back to 0 (have you made an initial release?)") + set(${major} "0" PARENT_SCOPE) + set(${minor} "" PARENT_SCOPE) + set(${patch} "" PARENT_SCOPE) + set(${extra} "" PARENT_SCOPE) + endif(version_valid) +endfunction(extract_version) + +if (WIN32) + set(CPACK_GENERATOR "ZIP") + set(CPACK_SOURCE_GENERATOR "ZIP") +else () + set(CPACK_GENERATOR "TGZ") + set(CPACK_SOURCE_GENERATOR "TGZ") +endif () + +set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "A KISS, modern unit testing framework for C and C++.") +set(CPACK_PACKAGE_FILE_NAME "${CMAKE_PROJECT_NAME}-binary-${PROJECT_VERSION}") +set(CPACK_SOURCE_PACKAGE_FILE_NAME "${CMAKE_PROJECT_NAME}-${PROJECT_VERSION}") +set(CPACK_PACKAGE_INSTALL_DIRECTORY "${CMAKE_PROJECT_NAME}-${PROJECT_VERSION}") +set(CPACK_PACKAGE_VENDOR "Franklin \"Snaipe\" Mathieu") +set(CPACK_PACKAGE_CONTACT "Franklin \"Snaipe\" Mathieu ") +set(CPACK_PACKAGE_VERSION "${PROJECT_VERSION}") + +if (WIN32) + # add snapshot specific versioning information + if (CPACK_DEBIAN_PACKAGE_TYPE STREQUAL "snapshot") + execute_process(COMMAND date +%Y%m%d%0k%0M%0S%z OUTPUT_VARIABLE SNAPSHOT_DATE_TIME) + set(CPACK_PACKAGE_VERSION "${PROJECT_VERSION}-snapshot-${SNAPSHOT_DATE_TIME}") + STRING(REPLACE "\n" "" CPACK_PACKAGE_VERSION ${CPACK_PACKAGE_VERSION}) + endif () +endif () + +set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_SOURCE_DIR}/debian.copyright") +extract_version(${PROJECT_VERSION} + CPACK_PACKAGE_VERSION_MAJOR + CPACK_PACKAGE_VERSION_MINOR + CPACK_PACKAGE_VERSION_PATCH + VERSION_EXTRA +) + +set(CPACK_PACKAGE_VERSION ${PROJECT_VERSION}) + +file(GLOB TRASH_FILES "${CMAKE_SOURCE_DIR}/*") +set(KEEP_FILES + "${CMAKE_SOURCE_DIR}/.cmake" + "${CMAKE_SOURCE_DIR}/src" + "${CMAKE_SOURCE_DIR}/include" + "${CMAKE_SOURCE_DIR}/doc" + "${CMAKE_SOURCE_DIR}/dev" + "${CMAKE_SOURCE_DIR}/po" + "${CMAKE_SOURCE_DIR}/dependencies" + "${CMAKE_SOURCE_DIR}/CMakeLists.txt" + "${CMAKE_SOURCE_DIR}/README.md" + "${CMAKE_SOURCE_DIR}/CONTRIBUTING.md" + "${CMAKE_SOURCE_DIR}/LICENSE" + "${CMAKE_SOURCE_DIR}/ChangeLog" + "${CMAKE_SOURCE_DIR}/description.txt" +) +list(REMOVE_ITEM TRASH_FILES ${KEEP_FILES}) +# Escape any '.' characters +string(REPLACE "." "\\\\." TRASH_FILES "${TRASH_FILES}") +set(CPACK_SOURCE_IGNORE_FILES "${TRASH_FILES}") + +include(CPack) diff --git a/.cmake/copy-source.sh b/.cmake/copy-source.sh new file mode 100755 index 00000000..fc562c62 --- /dev/null +++ b/.cmake/copy-source.sh @@ -0,0 +1,11 @@ +#!/bin/sh + +CURDIR=$(dirname $0) +SOURCE_DIR=$1; shift +DEST_DIR=$1; shift + +( + cd "$SOURCE_DIR" + mkdir -p "$DEST_DIR" + "$CURDIR/git-archive-all.sh" --format tar -- - | tar -x -C "$DEST_DIR" +) diff --git a/.cmake/git-archive-all.sh b/.cmake/git-archive-all.sh new file mode 100755 index 00000000..9a17eece --- /dev/null +++ b/.cmake/git-archive-all.sh @@ -0,0 +1,302 @@ +#!/bin/bash - +# +# File: git-archive-all.sh +# +# Description: A utility script that builds an archive file(s) of all +# git repositories and submodules in the current path. +# Useful for creating a single tarfile of a git super- +# project that contains other submodules. +# +# Examples: Use git-archive-all.sh to create archive distributions +# from git repositories. To use, simply do: +# +# cd $GIT_DIR; git-archive-all.sh +# +# where $GIT_DIR is the root of your git superproject. +# +# License: GPL3+ +# +############################################################################### +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# +############################################################################### + +# DEBUGGING +set -e +set -C # noclobber + +# TRAP SIGNALS +trap 'cleanup' QUIT EXIT + +# For security reasons, explicitly set the internal field separator +# to newline, space, tab +OLD_IFS=$IFS +IFS=' + ' + +function cleanup () { + rm -f $TMPFILE + rm -f $TOARCHIVE + IFS="$OLD_IFS" +} + +function usage () { + echo "Usage is as follows:" + echo + echo "$PROGRAM <--version>" + echo " Prints the program version number on a line by itself and exits." + echo + echo "$PROGRAM <--usage|--help|-?>" + echo " Prints this usage output and exits." + echo + echo "$PROGRAM [--format ] [--prefix ] [--verbose|-v] [--separate|-s]" + echo " [--tree-ish|-t ] [output_file]" + echo " Creates an archive for the entire git superproject, and its submodules" + echo " using the passed parameters, described below." + echo + echo " If '--format' is specified, the archive is created with the named" + echo " git archiver backend. Obviously, this must be a backend that git archive" + echo " understands. The format defaults to 'tar' if not specified." + echo + echo " If '--prefix' is specified, the archive's superproject and all submodules" + echo " are created with the prefix named. The default is to not use one." + echo + echo " If '--separate' or '-s' is specified, individual archives will be created" + echo " for each of the superproject itself and its submodules. The default is to" + echo " concatenate individual archives into one larger archive." + echo + echo " If '--tree-ish' is specified, the archive will be created based on whatever" + echo " you define the tree-ish to be. Branch names, commit hash, etc. are acceptable." + echo " Defaults to HEAD if not specified. See git archive's documentation for more" + echo " information on what a tree-ish is." + echo + echo " If 'output_file' is specified, the resulting archive is created as the" + echo " file named. This parameter is essentially a path that must be writeable." + echo " When combined with '--separate' ('-s') this path must refer to a directory." + echo " Without this parameter or when combined with '--separate' the resulting" + echo " archive(s) are named with a dot-separated path of the archived directory and" + echo " a file extension equal to their format (e.g., 'superdir.submodule1dir.tar')." + echo + echo " The special value '-' (single dash) is treated as STDOUT and, when used, the" + echo " --separate option is ignored. Use a double-dash to separate the outfile from" + echo " the value of previous options. For example, to write a .zip file to STDOUT:" + echo + echo " ./$PROGRAM --format zip -- -" + echo + echo " If '--verbose' or '-v' is specified, progress will be printed." +} + +function version () { + echo "$PROGRAM version $VERSION" +} + +# Internal variables and initializations. +readonly PROGRAM=`basename "$0"` +readonly VERSION=0.3 + +SEPARATE=0 +VERBOSE=0 + +TARCMD=`command -v gnutar || command -v tar` +FORMAT=tar +PREFIX= +TREEISH=HEAD + +# RETURN VALUES/EXIT STATUS CODES +readonly E_BAD_OPTION=254 +readonly E_UNKNOWN=255 + +# Process command-line arguments. +while test $# -gt 0; do + if [ x"$1" == x"--" ]; then + # detect argument termination + shift + break + fi + case $1 in + --format ) + shift + FORMAT="$1" + shift + ;; + + --prefix ) + shift + PREFIX="$1" + shift + ;; + + --separate | -s ) + shift + SEPARATE=1 + ;; + + --tree-ish | -t ) + shift + TREEISH="$1" + shift + ;; + + --version ) + version + exit + ;; + + --verbose | -v ) + shift + VERBOSE=1 + ;; + + -? | --usage | --help ) + usage + exit + ;; + + -* ) + echo "Unrecognized option: $1" >&2 + usage + exit $E_BAD_OPTION + ;; + + * ) + break + ;; + esac +done + +OLD_PWD="`pwd`" +TMPDIR=${TMPDIR:-/tmp} +TMPFILE=`mktemp "$TMPDIR/$PROGRAM.XXXXXX"` # Create a place to store our work's progress +TOARCHIVE=`mktemp "$TMPDIR/$PROGRAM.toarchive.XXXXXX"` +OUT_FILE=$OLD_PWD # assume "this directory" without a name change by default + +if [ ! -z "$1" ]; then + OUT_FILE="$1" + if [ "-" == $OUT_FILE ]; then + SEPARATE=0 + fi + shift +fi + +# Validate parameters; error early, error often. +if [ "-" == $OUT_FILE -o $SEPARATE -ne 1 ] && [ "$FORMAT" == "tar" -a `$TARCMD --help | grep -q -- "--concatenate"; echo $?` -ne 0 ]; then + echo "Your 'tar' does not support the '--concatenate' option, which we need" + echo "to produce a single tarfile. Either install a compatible tar (such as" + echo "gnutar), or invoke $PROGRAM with the '--separate' option." + exit +elif [ $SEPARATE -eq 1 -a ! -d $OUT_FILE ]; then + echo "When creating multiple archives, your destination must be a directory." + echo "If it's not, you risk being surprised when your files are overwritten." + exit +elif [ `git config -l | grep -q '^core\.bare=false'; echo $?` -ne 0 ]; then + echo "$PROGRAM must be run from a git working copy (i.e., not a bare repository)." + exit +fi + +# Create the superproject's git-archive +if [ $VERBOSE -eq 1 ]; then + echo -n "creating superproject archive..." +fi +git archive --format=$FORMAT --prefix="$PREFIX" $TREEISH > $TMPDIR/$(basename "$(pwd)").$FORMAT +if [ $VERBOSE -eq 1 ]; then + echo "done" +fi +echo $TMPDIR/$(basename "$(pwd)").$FORMAT >| $TMPFILE # clobber on purpose +superfile=`head -n 1 $TMPFILE` + +if [ $VERBOSE -eq 1 ]; then + echo -n "looking for subprojects..." +fi +# find all '.git' dirs, these show us the remaining to-be-archived dirs +# we only want directories that are below the current directory +find . -mindepth 2 -name '.git' -type d -print | sed -e 's/^\.\///' -e 's/\.git$//' >> $TOARCHIVE +# as of version 1.7.8, git places the submodule .git directories under the superprojects .git dir +# the submodules get a .git file that points to their .git dir. we need to find all of these too +find . -mindepth 2 -name '.git' -type f -print | xargs grep -l "gitdir" | sed -e 's/^\.\///' -e 's/\.git$//' >> $TOARCHIVE +if [ $VERBOSE -eq 1 ]; then + echo "done" + echo " found:" + cat $TOARCHIVE | while read arch + do + echo " $arch" + done +fi + +if [ $VERBOSE -eq 1 ]; then + echo -n "archiving submodules..." +fi +while read path; do + TREEISH=$(git submodule | grep "^ .*${path%/} " | cut -d ' ' -f 2) # git submodule does not list trailing slashes in $path + cd "$path" + git archive --format=$FORMAT --prefix="${PREFIX}$path" ${TREEISH:-HEAD} > "$TMPDIR"/"$(echo "$path" | sed -e 's/\//./g')"$FORMAT + if [ $FORMAT == 'zip' ]; then + # delete the empty directory entry; zipped submodules won't unzip if we don't do this + zip -d "$(tail -n 1 $TMPFILE)" "${PREFIX}${path%/}" >/dev/null # remove trailing '/' + fi + echo "$TMPDIR"/"$(echo "$path" | sed -e 's/\//./g')"$FORMAT >> $TMPFILE + cd "$OLD_PWD" +done < $TOARCHIVE +if [ $VERBOSE -eq 1 ]; then + echo "done" +fi + +if [ $VERBOSE -eq 1 ]; then + echo -n "concatenating archives into single archive..." +fi +# Concatenate archives into a super-archive. +if [ $SEPARATE -eq 0 -o "-" == $OUT_FILE ]; then + if [ $FORMAT == 'tar.gz' ]; then + gunzip $superfile + superfile=${superfile:0: -3} # Remove '.gz' + sed -e '1d' $TMPFILE | while read file; do + gunzip $file + file=${file:0: -3} + $TARCMD --concatenate -f "$superfile" "$file" && rm -f "$file" + done + gzip $superfile + superfile=$superfile.gz + elif [ $FORMAT == 'tar' ]; then + sed -e '1d' $TMPFILE | while read file; do + $TARCMD --concatenate -f "$superfile" "$file" && rm -f "$file" + done + elif [ $FORMAT == 'zip' ]; then + sed -e '1d' $TMPFILE | while read file; do + # zip incorrectly stores the full path, so cd and then grow + cd `dirname "$file"` + zip -g "$superfile" `basename "$file"` && rm -f "$file" + done + cd "$OLD_PWD" + fi + + echo "$superfile" >| $TMPFILE # clobber on purpose +fi +if [ $VERBOSE -eq 1 ]; then + echo "done" +fi + +if [ $VERBOSE -eq 1 ]; then + echo -n "moving archive to $OUT_FILE..." +fi +while read file; do + if [ "-" == $OUT_FILE ]; then + cat "$file" && rm -f "$file" + else + mv "$file" "$OUT_FILE" + fi +done < $TMPFILE +if [ $VERBOSE -eq 1 ]; then + echo "done" +fi diff --git a/.gitignore b/.gitignore index 007b88d8..dc27c604 100644 --- a/.gitignore +++ b/.gitignore @@ -17,7 +17,7 @@ !*.rst !*.po !*.in -!.cmake/*.cmake +!.cmake/Modules/*.cmake !samples/tests/*.sh !samples/**/*.expected diff --git a/CMakeLists.txt b/CMakeLists.txt index 21356c0f..7abd623d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -66,7 +66,8 @@ endif() # Project setup & environment variables set(PROJECT_VERSION "2.1.0") -set(LOCALEDIR ${CMAKE_INSTALL_PREFIX}/share/locale) +set(LOCALEDIR_REL "share/locale") +set(LOCALEDIR "${CMAKE_INSTALL_PREFIX}/${LOCALEDIR_REL}") set(GettextTranslate_ALL 1) set(GettextTranslate_GMO_BINARY 1) @@ -316,3 +317,14 @@ enable_testing() add_subdirectory(samples) add_subdirectory(test) endif () + +# Add toolchain patch number for incremental deb builds +set(PROJECT_VERSION "${PROJECT_VERSION}-4") + +include (PackageConfig) + +option(UPLOAD_DEB "Upload package to launchpad" OFF) + +if (UNIX AND UPLOAD_DEB) + include (DebConfig) +endif () From ba21d658ca117de958e96bbeea0f28c9c179884d Mon Sep 17 00:00:00 2001 From: Snaipe Date: Sat, 28 Nov 2015 14:33:09 +0100 Subject: [PATCH 188/211] Added missing files for ppa builds --- CMakeLists.txt | 2 +- debian.copyright | 25 +++++++++++++++++++++++++ description.txt | 23 +++++++++++++++++++++++ 3 files changed, 49 insertions(+), 1 deletion(-) create mode 100644 debian.copyright create mode 100644 description.txt diff --git a/CMakeLists.txt b/CMakeLists.txt index 7abd623d..af6bc1bb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -319,7 +319,7 @@ add_subdirectory(test) endif () # Add toolchain patch number for incremental deb builds -set(PROJECT_VERSION "${PROJECT_VERSION}-4") +set(PROJECT_VERSION "${PROJECT_VERSION}-5") include (PackageConfig) diff --git a/debian.copyright b/debian.copyright new file mode 100644 index 00000000..6f6dc399 --- /dev/null +++ b/debian.copyright @@ -0,0 +1,25 @@ +Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ +Upstream-Name: Criterion +Upstream-Contact: Franklin "Snaipe" Mathieu +Source: http://github.com/Snaipe/Criterion + +Files: * +Copyright: 2015, Franklin "Snaipe" Mathieu +License: MIT + 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. diff --git a/description.txt b/description.txt new file mode 100644 index 00000000..e249add8 --- /dev/null +++ b/description.txt @@ -0,0 +1,23 @@ +Criterion is a dead-simple, yet extensible, C and C++ unit testing framework. + +Most test frameworks for C require a lot of boilerplate code to +set up tests and test suites -- you need to create a main, +then register new test suites, then register the tests within +these suits, and finally call the right functions. + +This gives the user great control, at the unfortunate cost of simplicity. + +Criterion follows the KISS principle, while keeping the control +the user would have with other frameworks: + +* C99 and C++11 compatible. +* Tests are automatically registered when declared. +* Implements a xUnit framework structure. +* A default entry point is provided, no need to declare a main + unless you want to do special handling. +* Test are isolated in their own process, crashes and signals can be + reported and tested. +* Unified interface between C and C++: include the criterion header and it *just* works. +* Supports parameterized tests and theories. +* Progress and statistics can be followed in real time with report hooks. +* TAP output format can be enabled with an option. From 689eee1545d757cc86057de45d39fccbfd34cc61 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Sat, 28 Nov 2015 14:36:15 +0100 Subject: [PATCH 189/211] Removed unused deb dependencies and activated objective c support on deb builds --- .cmake/Modules/DebConfig.cmake | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/.cmake/Modules/DebConfig.cmake b/.cmake/Modules/DebConfig.cmake index e8a4c73f..83e48a7a 100644 --- a/.cmake/Modules/DebConfig.cmake +++ b/.cmake/Modules/DebConfig.cmake @@ -8,12 +8,14 @@ set(CPACK_DEBIAN_BUILD_DEPENDS cmake gettext libpcre3-dev - gcc-4.9 - g++-4.9 - gobjc-4.9 + gobjc gnustep-devel ) +set(CPACK_DEBIAN_CMAKE_OPTIONS + "-DLANG_OBJC=ON" +) + set(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_SOURCE_DIR}/description.txt") set(CPACK_DEBIAN_PACKAGE_SOURCE_COPY "${CMAKE_SOURCE_DIR}/.cmake/copy-source.sh") From 503f9e28969cb3f0214b6616739b814f9936e2af Mon Sep 17 00:00:00 2001 From: Snaipe Date: Sun, 29 Nov 2015 00:33:58 +0100 Subject: [PATCH 190/211] Properly set up cmake install components --- CMakeLists.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index af6bc1bb..d95bb84f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -294,13 +294,13 @@ endif() foreach (F ${INTERFACE_FILES}) get_filename_component(DEST "${F}" PATH) - install(FILES "${F}" DESTINATION "${DEST}") + install(FILES "${F}" DESTINATION "${DEST}" COMPONENT dev) endforeach () install(TARGETS criterion RUNTIME DESTINATION bin LIBRARY DESTINATION lib - ARCHIVE DESTINATION lib + ARCHIVE DESTINATION lib COMPONENT dev ) add_custom_target(criterion_tests) @@ -319,7 +319,7 @@ add_subdirectory(test) endif () # Add toolchain patch number for incremental deb builds -set(PROJECT_VERSION "${PROJECT_VERSION}-5") +set(PROJECT_VERSION "${PROJECT_VERSION}-6") include (PackageConfig) From 30f2982423b6abd5bedbdec1d40666e304aedc2d Mon Sep 17 00:00:00 2001 From: Snaipe Date: Mon, 30 Nov 2015 10:29:40 +0100 Subject: [PATCH 191/211] Fixed main not cleaning up on special CLI actions --- doc/internal.rst | 7 +++---- src/entry/entry.c | 7 +++---- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/doc/internal.rst b/doc/internal.rst index f1296282..8330590e 100644 --- a/doc/internal.rst +++ b/doc/internal.rst @@ -66,10 +66,9 @@ Example main int main(int argc, char *argv[]) { struct criterion_test_set *tests = criterion_initialize(); - if (!criterion_handle_args(argc, argv, true)) - return 0; - - int result = !criterion_run_all_tests(set); + int result = 0; + if (criterion_handle_args(argc, argv, true)) + result = !criterion_run_all_tests(set); criterion_finalize(set); return result; diff --git a/src/entry/entry.c b/src/entry/entry.c index 25301b11..2e57189f 100644 --- a/src/entry/entry.c +++ b/src/entry/entry.c @@ -26,10 +26,9 @@ CR_API int main(int argc, char *argv[]) { struct criterion_test_set *tests = criterion_initialize(); - if (!criterion_handle_args(argc, argv, true)) - return 0; - - int result = !criterion_run_all_tests(tests); + int result = 0; + if (criterion_handle_args(argc, argv, true)) + result = !criterion_run_all_tests(tests); criterion_finalize(tests); From 214bd95a62aeafa5fc6cc4936004dc1fe450a731 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Fri, 4 Dec 2015 18:44:46 +0100 Subject: [PATCH 192/211] [Issue #83] Added single test execution mode --- src/compat/pipe.c | 22 ++++++++++++++++++++++ src/compat/pipe.h | 2 ++ src/core/runner.c | 21 +++++++++++++++++++++ src/core/runner.h | 2 ++ src/entry/params.c | 2 ++ 5 files changed, 49 insertions(+) diff --git a/src/compat/pipe.c b/src/compat/pipe.c index 30a3ef12..1c05a201 100644 --- a/src/compat/pipe.c +++ b/src/compat/pipe.c @@ -318,3 +318,25 @@ static s_pipe_handle stdin_redir_; s_pipe_handle *stdout_redir = &stdout_redir_; s_pipe_handle *stderr_redir = &stderr_redir_; s_pipe_handle *stdin_redir = &stdin_redir_; + +s_pipe_file_handle *pipe_file_open(const char *path) { + s_pipe_file_handle *h = smalloc( + .size = sizeof (s_pipe_file_handle), + .dtor = close_pipe_file_handle); +#ifdef VANILLA_WIN32 + if (!path) + path = "nul"; + h->fh = CreateFile(path, + GENERIC_READ | GENERIC_WRITE, + 0, + NULL, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, + NULL); +#else + if (!path) + path = "/dev/null"; + h->fd = open(path, O_RDWR); +#endif + return h; +} diff --git a/src/compat/pipe.h b/src/compat/pipe.h index d0e162d6..67999826 100644 --- a/src/compat/pipe.h +++ b/src/compat/pipe.h @@ -79,4 +79,6 @@ extern s_pipe_handle *stdout_redir; extern s_pipe_handle *stderr_redir; extern s_pipe_handle *stdin_redir; +s_pipe_file_handle *pipe_file_open(const char *path); + #endif /* !PIPE_H_ */ diff --git a/src/core/runner.c b/src/core/runner.c index d5c6a003..79dedb33 100644 --- a/src/core/runner.c +++ b/src/core/runner.c @@ -488,3 +488,24 @@ int criterion_run_all_tests(struct criterion_test_set *set) { return criterion_options.always_succeed || res; } + +void run_single_test_by_name(const char *testname) { + struct criterion_test_set *set = criterion_init(); + + g_event_pipe = pipe_file_open(NULL); + + FOREACH_SET(struct criterion_suite_set *s, set->suites) { + size_t tests = s->tests ? s->tests->size : 0; + if (!tests) + continue; + + FOREACH_SET(struct criterion_test *t, s->tests) { + char name[1024]; + snprintf(name, sizeof (name), "%s::%s", s->suite.name, t->name); + if (!strncmp(name, testname, 1024)) + run_test_child(t, &s->suite); + } + } + + sfree(set); +} diff --git a/src/core/runner.h b/src/core/runner.h index 0eafbb78..49039bf2 100644 --- a/src/core/runner.h +++ b/src/core/runner.h @@ -43,4 +43,6 @@ void run_test_child(struct criterion_test *test, struct criterion_suite *suite); Suite < (struct criterion_suite**) GET_SECTION_END(cr_sts); \ ++Suite) +void run_single_test_by_name(const char *testname); + #endif /* !CRITERION_RUNNER_H_ */ diff --git a/src/entry/params.c b/src/entry/params.c index 5d71a688..a6dc8a09 100644 --- a/src/entry/params.c +++ b/src/entry/params.c @@ -149,6 +149,7 @@ int criterion_handle_args(int argc, char *argv[], bool handle_unknown_arg) { {"jobs", required_argument, 0, 'j'}, {"fail-fast", no_argument, 0, 'f'}, {"short-filename", no_argument, 0, 'S'}, + {"single", required_argument, 0, 's'}, #ifdef HAVE_PCRE {"pattern", required_argument, 0, 'p'}, #endif @@ -245,6 +246,7 @@ int criterion_handle_args(int argc, char *argv[], bool handle_unknown_arg) { case 'j': criterion_options.jobs = atou(optarg); break; case 'f': criterion_options.fail_fast = true; break; case 'S': criterion_options.short_filename = true; break; + case 's': run_single_test_by_name(optarg); return 0; #ifdef HAVE_PCRE case 'p': criterion_options.pattern = optarg; break; #endif From 30c3afedda190e4ad39794eafa4b50a3642c04bc Mon Sep 17 00:00:00 2001 From: Snaipe Date: Sat, 5 Dec 2015 01:37:58 +0100 Subject: [PATCH 193/211] Added first tentative to decouple the wrappers from the library --- CMakeLists.txt | 8 --- include/criterion/criterion.h | 3 + include/criterion/internal/test.h | 90 +++++++++++++++++++++++++- src/core/runner.c | 23 ++++--- src/core/{wrappers/wrap.c => test.c} | 33 +++++++--- src/core/wrappers/wrap.cc | 92 -------------------------- src/core/wrappers/wrap.h | 44 ------------- src/core/wrappers/wrap.m | 96 ---------------------------- src/core/wrappers/wrappers.c | 45 ------------- 9 files changed, 126 insertions(+), 308 deletions(-) rename src/core/{wrappers/wrap.c => test.c} (71%) delete mode 100644 src/core/wrappers/wrap.cc delete mode 100644 src/core/wrappers/wrap.h delete mode 100644 src/core/wrappers/wrap.m delete mode 100644 src/core/wrappers/wrappers.c diff --git a/CMakeLists.txt b/CMakeLists.txt index d95bb84f..67dfe4eb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -133,9 +133,6 @@ find_package(PCRE) # List sources and headers set(SOURCE_FILES - src/core/wrappers/wrap.h - src/core/wrappers/wrap.c - src/core/wrappers/wrappers.c src/core/abort.c src/core/abort.h src/core/report.c @@ -203,10 +200,6 @@ if (PCRE_FOUND) set(HAVE_PCRE 1) endif () -if (CMAKE_CXX_COMPILER_WORKS) - set(SOURCE_FILES ${SOURCE_FILES} src/core/wrappers/wrap.cc) -endif () - if (CMAKE_ObjectiveC_COMPILER_WORKS) set(CMAKE_ObjectiveC_FLAGS "${CMAKE_ObjectiveC_FLAGS} ${CMAKE_C_FLAGS} -fobjc-exceptions") if ("${CMAKE_ObjectiveC_COMPILER_ID}" STREQUAL "Clang" AND APPLE) @@ -217,7 +210,6 @@ if (CMAKE_ObjectiveC_COMPILER_WORKS) if (NOT WIN32) set(CMAKE_ObjectiveC_FLAGS "${CMAKE_ObjectiveC_FLAGS} -fPIC") endif () - set(SOURCE_FILES ${SOURCE_FILES} src/core/wrappers/wrap.m) endif () set(INTERFACE_FILES diff --git a/include/criterion/criterion.h b/include/criterion/criterion.h index e1ce1581..a1b183bc 100644 --- a/include/criterion/criterion.h +++ b/include/criterion/criterion.h @@ -113,6 +113,9 @@ CR_API int criterion_handle_args(int argc, char *argv[], bool handle_unknown_arg CR_API void criterion_register_test(struct criterion_test_set *tests, struct criterion_test *test); +extern const struct criterion_test *const criterion_current_test; +extern const struct criterion_suite *const criterion_current_suite; + CR_END_C_API #endif /* !CRITERION_H_ */ diff --git a/include/criterion/internal/test.h b/include/criterion/internal/test.h index 0772f1f2..9a2f526f 100644 --- a/include/criterion/internal/test.h +++ b/include/criterion/internal/test.h @@ -27,6 +27,14 @@ # include "designated-initializer-compat.h" # include "common.h" +# ifdef __OBJC__ +#import +# endif + +# ifdef __cplusplus +# include +# endif + # define CR_IDENTIFIER_(Category, Name, Suffix) \ Category ## _ ## Name ## _ ## Suffix @@ -55,8 +63,88 @@ # define CR_SUITE_IDENTIFIER_(Name, Suffix) \ suite_ ## Name ## _ ## Suffix +CR_BEGIN_C_API + +CR_API void criterion_internal_test_setup(void); +CR_API void criterion_internal_test_main(void (*fn)(void)); +CR_API void criterion_internal_test_teardown(void); + +CR_END_C_API + +static const char *const cr_msg_test_init_std_exception = "Caught an unexpected exception during the test initialization: %s."; +static const char *const cr_msg_test_init_other_exception = "Caught some unexpected exception during the test initialization."; +static const char *const cr_msg_test_main_std_exception = "Caught an unexpected exception during the test execution: %s."; +static const char *const cr_msg_test_main_other_exception = "Caught some unexpected exception during the test execution."; +static const char *const cr_msg_test_fini_std_exception = "Caught an unexpected exception during the test finalization: %s."; +static const char *const cr_msg_test_fini_other_exception = "Caught some unexpected exception during the test finalization."; + +# ifdef __cplusplus +# define CR_TEST_TRAMPOLINE_(Category, Name) \ + static inline void CR_IDENTIFIER_(Category, Name, jmp)(void) { \ + try { \ + criterion_internal_test_setup(); \ + } catch (const std::exception &e) { \ + criterion_test_die(cr_msg_test_init_std_exception, e.what()); \ + } catch (...) { \ + criterion_test_die(cr_msg_test_init_other_exception); \ + } \ + try { \ + criterion_internal_test_main(CR_IDENTIFIER_(Category, Name, impl)); \ + } catch (const std::exception &e) { \ + criterion_test_die(cr_msg_test_main_std_exception, e.what()); \ + } catch (...) { \ + criterion_test_die(cr_msg_test_main_other_exception); \ + } \ + try { \ + criterion_internal_test_teardown(); \ + } catch (const std::exception &e) { \ + criterion_test_die(cr_msg_test_fini_std_exception, e.what()); \ + } catch (...) { \ + criterion_test_die(cr_msg_test_fini_other_exception); \ + } \ + } +# else +# if defined(__OBJC__) && defined(__EXCEPTIONS) +# define CR_TEST_TRAMPOLINE_(Category, Name) \ + static inline void CR_IDENTIFIER_(Category, Name, jmp)(void) { \ + @try { \ + criterion_internal_test_setup(); \ + } @catch (NSException *e) { \ + NSString *reason = [e reason]; \ + criterion_test_die(cr_msg_test_init_std_exception, [reason UTF8String]); \ + } @catch (...) { \ + criterion_test_die(cr_msg_test_init_other_exception); \ + } \ + @try { \ + criterion_internal_test_main(CR_IDENTIFIER_(Category, Name, impl)); \ + } @catch (NSException *e) { \ + NSString *reason = [e reason]; \ + criterion_test_die(cr_msg_test_main_std_exception, [reason UTF8String]); \ + } @catch (...) { \ + criterion_test_die(cr_msg_test_main_other_exception); \ + } \ + @try { \ + criterion_internal_test_teardown(); \ + } @catch (NSException *e) { \ + NSString *reason = [e reason]; \ + criterion_test_die(cr_msg_test_fini_std_exception, [reason UTF8String]); \ + } @catch (...) { \ + criterion_test_die(cr_msg_test_fini_other_exception); \ + } \ + } +# else +# define CR_TEST_TRAMPOLINE_(Category, Name) \ + static inline void CR_IDENTIFIER_(Category, Name, jmp)(void) { \ + criterion_internal_test_setup(); \ + criterion_internal_test_main(CR_IDENTIFIER_(Category, Name, impl)); \ + criterion_internal_test_teardown(); \ + } +# endif +# endif + # define CR_TEST_BASE(Category, Name, ...) \ CR_TEST_PROTOTYPE_(Category, Name); \ + CR_TEST_TRAMPOLINE_(Category, Name) \ struct criterion_test_extra_data CR_IDENTIFIER_(Category, Name, extra) = \ CR_EXPAND(CRITERION_MAKE_STRUCT(criterion_test_extra_data, \ .lang_ = CR_LANG, \ @@ -70,7 +158,7 @@ struct criterion_test CR_IDENTIFIER_(Category, Name, meta) = { \ #Name, \ #Category, \ - CR_IDENTIFIER_(Category, Name, impl), \ + CR_IDENTIFIER_(Category, Name, jmp), \ &CR_IDENTIFIER_(Category, Name, extra) \ }; \ CR_SECTION_("cr_tst") \ diff --git a/src/core/runner.c b/src/core/runner.c index 79dedb33..2caf8448 100644 --- a/src/core/runner.c +++ b/src/core/runner.c @@ -27,7 +27,7 @@ #include #include #include -#include "criterion/criterion.h" +#include "criterion/internal/test.h" #include "criterion/options.h" #include "criterion/internal/ordered-set.h" #include "criterion/logging.h" @@ -35,7 +35,6 @@ #include "compat/time.h" #include "compat/posix.h" #include "compat/processor.h" -#include "wrappers/wrap.h" #include "string/i18n.h" #include "io/event.h" #include "io/output.h" @@ -84,8 +83,8 @@ CR_IMPL_SECTION_LIMITS(struct criterion_test*, cr_tst); CR_IMPL_SECTION_LIMITS(struct criterion_suite*, cr_sts); // This is here to make the test suite & test sections non-empty -TestSuite(); -Test(,) {} +CR_SUITE_BASE(,.sentinel_ = 0); +CR_TEST_BASE(,,.sentinel_ = 0) {} static INLINE void nothing(void) {} @@ -159,6 +158,9 @@ struct criterion_test_set *criterion_init(void) { return set; } +const struct criterion_test *criterion_current_test; +const struct criterion_suite *criterion_current_suite; + void run_test_child(struct criterion_test *test, struct criterion_suite *suite) { @@ -166,19 +168,16 @@ void run_test_child(struct criterion_test *test, VALGRIND_ENABLE_ERROR_REPORTING; #endif + criterion_current_test = test; + criterion_current_suite = suite; + if (suite->data && suite->data->timeout != 0 && test->data->timeout == 0) setup_timeout((uint64_t) (suite->data->timeout * 1e9)); else if (test->data->timeout != 0) setup_timeout((uint64_t) (test->data->timeout * 1e9)); - if (g_wrappers[test->data->lang_]) { - g_wrappers[test->data->lang_](test, suite); - } else { - criterion_test_die( - "The test is compiled in the %s programming language, but the \n" - "criterion runner have been compiled without its language support.", - cr_language_names[test->data->lang_]); - } + if (test->test) + test->test(); } #define push_event(...) \ diff --git a/src/core/wrappers/wrap.c b/src/core/test.c similarity index 71% rename from src/core/wrappers/wrap.c rename to src/core/test.c index 38009a2b..02a4578a 100644 --- a/src/core/wrappers/wrap.c +++ b/src/core/test.c @@ -27,28 +27,35 @@ #include "core/report.h" #include "compat/time.h" #include "io/event.h" -#include "wrap.h" + +extern const struct criterion_test *criterion_current_test; +extern const struct criterion_suite *criterion_current_suite; static INLINE void nothing(void) {} -void c_wrap(struct criterion_test *test, struct criterion_suite *suite) { +void criterion_internal_test_setup(void) { + const struct criterion_suite *suite = criterion_current_suite; + const struct criterion_test *test = criterion_current_test; criterion_send_event(PRE_INIT, NULL, 0); if (suite->data) (suite->data->init ? suite->data->init : nothing)(); (test->data->init ? test->data->init : nothing)(); +} + +void criterion_internal_test_main(void (*fn)(void)) { + const struct criterion_test *test = criterion_current_test; + criterion_send_event(PRE_TEST, NULL, 0); struct timespec_compat ts; if (!setjmp(g_pre_test)) { timer_start(&ts); - if (test->test) { - if (!test->data->param_) { - test->test(); - } else { - void(*param_test_func)(void *) = (void(*)(void*)) test->test; - param_test_func(g_worker_context.param->ptr); - } + if (!test->data->param_) { + fn(); + } else { + void(*param_test_func)(void *) = (void(*)(void*)) fn; + param_test_func(g_worker_context.param->ptr); } } @@ -57,9 +64,15 @@ void c_wrap(struct criterion_test *test, struct criterion_suite *suite) { elapsed_time = -1; criterion_send_event(POST_TEST, &elapsed_time, sizeof(double)); +} + +void criterion_internal_test_teardown(void) { + const struct criterion_suite *suite = criterion_current_suite; + const struct criterion_test *test = criterion_current_test; + (test->data->fini ? test->data->fini : nothing)(); if (suite->data) (suite->data->fini ? suite->data->fini : nothing)(); criterion_send_event(POST_FINI, NULL, 0); - } + diff --git a/src/core/wrappers/wrap.cc b/src/core/wrappers/wrap.cc deleted file mode 100644 index a5bc3eb1..00000000 --- a/src/core/wrappers/wrap.cc +++ /dev/null @@ -1,92 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright © 2015 Franklin "Snaipe" Mathieu - * - * 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. - */ -#include -#include "criterion/event.h" - -#include "core/report.h" - -extern "C" { - -#include "core/abort.h" -#include "core/worker.h" -#include "compat/time.h" -#include "wrap.h" -#include "common.h" - -static INLINE void nothing(void) {} - -void cxx_wrap(struct criterion_test *test, struct criterion_suite *suite); - -} - -void cxx_wrap(struct criterion_test *test, struct criterion_suite *suite) { - - criterion_send_event(PRE_INIT, NULL, 0); - try { - if (suite->data) - (suite->data->init ? suite->data->init : nothing)(); - (test->data->init ? test->data->init : nothing)(); - } catch (const std::exception &e) { - criterion_test_die("Caught an unexpected exception during the test initialization: %s.", e.what()); - } catch (...) { - criterion_test_die("Caught some unexpected exception during the test initialization."); - } - criterion_send_event(PRE_TEST, NULL, 0); - - struct timespec_compat ts; - if (!setjmp(g_pre_test)) { - timer_start(&ts); - if (test->test) { - try { - if (!test->data->param_) { - test->test(); - } else { - void(*param_test_func)(void *) = (void(*)(void*)) test->test; - param_test_func(g_worker_context.param->ptr); - } - } catch (const std::exception &e) { - criterion_test_die("Caught an unexpected exception during the test execution: %s.", e.what()); - } catch (...) { - criterion_test_die("Caught some unexpected exception during the test execution."); - } - } - } - - double elapsed_time; - if (!timer_end(&elapsed_time, &ts)) - elapsed_time = -1; - - criterion_send_event(POST_TEST, &elapsed_time, sizeof(double)); - try { - (test->data->fini ? test->data->fini : nothing)(); - if (suite->data) - (suite->data->fini ? suite->data->fini : nothing)(); - } catch (const std::exception &e) { - criterion_test_die("Caught an unexpected exception during the test finalization: %s.", e.what()); - } catch (...) { - criterion_test_die("Caught some unexpected exception during the test finalization."); - } - criterion_send_event(POST_FINI, NULL, 0); - -} diff --git a/src/core/wrappers/wrap.h b/src/core/wrappers/wrap.h deleted file mode 100644 index 5f20da93..00000000 --- a/src/core/wrappers/wrap.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright © 2015 Franklin "Snaipe" Mathieu - * - * 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 WRAP_H_ -# define WRAP_H_ - -# include "criterion/types.h" -# include "config.h" - -typedef void (f_wrapper)(struct criterion_test *, struct criterion_suite *); - -void c_wrap(struct criterion_test *test, struct criterion_suite *suite); - -# ifdef CXX_BRIDGE -void cxx_wrap(struct criterion_test *test, struct criterion_suite *suite); -# endif - -# ifdef OBJC_BRIDGE -void objc_wrap(struct criterion_test *test, struct criterion_suite *suite); -# endif - -extern f_wrapper *g_wrappers[]; - -#endif /* !WRAP_H_ */ diff --git a/src/core/wrappers/wrap.m b/src/core/wrappers/wrap.m deleted file mode 100644 index db3f75be..00000000 --- a/src/core/wrappers/wrap.m +++ /dev/null @@ -1,96 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright © 2015 Franklin "Snaipe" Mathieu - * - * 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. - */ -#import - -#include "criterion/assert.h" -#include "criterion/event.h" - -#include "core/abort.h" -#include "core/report.h" -#include "core/worker.h" -#include "compat/time.h" -#include "wrap.h" -#include "common.h" - -static INLINE void nothing(void) {} - -void objc_wrap(struct criterion_test *test, struct criterion_suite *suite) { - - criterion_send_event(PRE_INIT, NULL, 0); - @try { - if (suite->data) - (suite->data->init ? suite->data->init : nothing)(); - (test->data->init ? test->data->init : nothing)(); - } - @catch (NSException *e) { - NSString *reason = [e reason]; - criterion_test_die("Caught an unexpected exception during the test initialization: %s.", [reason UTF8String]); - } - @catch (...) { - criterion_test_die("Caught some unexpected exception during the test initialization."); - } - criterion_send_event(PRE_TEST, NULL, 0); - - struct timespec_compat ts; - if (!setjmp(g_pre_test)) { - timer_start(&ts); - if (test->test) { - @try { - if (!test->data->param_) { - test->test(); - } else { - void(*param_test_func)(void *) = (void(*)(void*)) test->test; - param_test_func(g_worker_context.param->ptr); - } - } - @catch (NSException *e) { - NSString *reason = [e reason]; - criterion_test_die("Caught an unexpected exception during the test execution: %s.", [reason UTF8String]); - } - @catch (...) { - criterion_test_die("Caught some unexpected exception during the test execution."); - } - } - } - - double elapsed_time; - if (!timer_end(&elapsed_time, &ts)) - elapsed_time = -1; - - criterion_send_event(POST_TEST, &elapsed_time, sizeof(double)); - @try { - (test->data->fini ? test->data->fini : nothing)(); - if (suite->data) - (suite->data->fini ? suite->data->fini : nothing)(); - } - @catch (NSException *e) { - NSString *reason = [e reason]; - criterion_test_die("Caught an unexpected exception during the test finalization: %s.", [reason UTF8String]); - } - @catch (...) { - criterion_test_die("Caught some unexpected exception during the test finalization."); - } - criterion_send_event(POST_FINI, NULL, 0); - -} diff --git a/src/core/wrappers/wrappers.c b/src/core/wrappers/wrappers.c deleted file mode 100644 index a4094e11..00000000 --- a/src/core/wrappers/wrappers.c +++ /dev/null @@ -1,45 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright © 2015 Franklin "Snaipe" Mathieu - * - * 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. - */ -#include "wrap.h" - -f_wrapper *g_wrappers[CR_LANG_SIZE_] = { - [CR_LANG_C] = c_wrap, - -#ifdef CXX_BRIDGE - [CR_LANG_CXX] = cxx_wrap, -#endif - -#ifdef OBJC_BRIDGE - [CR_LANG_OBJC] = objc_wrap, - [CR_LANG_OBJCXX] = objc_wrap, -#endif -}; - -const char *const cr_language_names[CR_LANG_SIZE_] = { - [CR_LANG_C] = "C", - [CR_LANG_CXX] = "C++", - [CR_LANG_OBJC] = "Objective-C", - [CR_LANG_OBJCXX] = "Objective-C++", -}; - From aaa21d922c750f12f1aa5183cd6e7db0a7af196d Mon Sep 17 00:00:00 2001 From: Snaipe Date: Sat, 5 Dec 2015 14:27:28 +0100 Subject: [PATCH 194/211] Simplified empty tests & suite placeholders in runner --- src/core/runner.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/core/runner.c b/src/core/runner.c index 79dedb33..091a7e43 100644 --- a/src/core/runner.c +++ b/src/core/runner.c @@ -84,8 +84,8 @@ CR_IMPL_SECTION_LIMITS(struct criterion_test*, cr_tst); CR_IMPL_SECTION_LIMITS(struct criterion_suite*, cr_sts); // This is here to make the test suite & test sections non-empty -TestSuite(); -Test(,) {} +CR_SECTION_("cr_sts") struct criterion_suite *dummy_suite = NULL; +CR_SECTION_("cr_tst") struct criterion_test *dummy_test = NULL; static INLINE void nothing(void) {} From 13e7928d0c8fbebbe533ca7d09727718d57dc430 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Sun, 6 Dec 2015 13:28:43 +0100 Subject: [PATCH 195/211] [Issue #82] Fixed deadlocks that were triggered when the event pipe was full and a child needed to be reaped --- src/compat/process.c | 57 ++++++++++++++++++++++++++++++++++---------- src/compat/process.h | 3 +++ src/core/runner.c | 2 ++ 3 files changed, 49 insertions(+), 13 deletions(-) diff --git a/src/compat/process.c b/src/compat/process.c index 08392995..ba7055c4 100644 --- a/src/compat/process.c +++ b/src/compat/process.c @@ -88,6 +88,8 @@ static int get_win_status(HANDLE handle) { } return sig ? sig : exit_code << 8; } +#else +# include #endif struct worker_context g_worker_context = {.test = NULL}; @@ -115,9 +117,7 @@ static struct full_context local_ctx; # error Unsupported compiler. Use GCC or Clang under *nixes. # endif -static void handle_sigchld(CR_UNUSED int sig) { - assert(sig == SIGCHLD); - +static void handle_sigchld_pump(void) { int fd = g_worker_pipe->fds[1]; pid_t pid; int status; @@ -142,8 +142,49 @@ static void handle_sigchld(CR_UNUSED int sig) { } } } + +/* + * This child reaping logic is a dirty hack to prevent deadlocks + * when the pipe is overflowing and a child terminates. + * + * (Windows doesn't have this issue as the waitpid logic is threaded by + * RegisterWaitForSingleObject) + * + * REMOVE WHEN REFACTORING I/O LAYER + */ +static pthread_t child_pump; +static bool child_pump_running; + +static void *chld_pump_thread_main(void *nil) { + child_pump_running = true; + + do { + handle_sigchld_pump(); + usleep(1000); + } while (child_pump_running); + + return nil; +} #endif +void init_proc_compat(void) { +#ifndef VANILLA_WIN32 + pthread_attr_t attr; + int err = pthread_attr_init(&attr) + || pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED) + || pthread_create(&child_pump, &attr, chld_pump_thread_main, NULL) + || pthread_attr_destroy(&attr); + if (err) { + perror(0); + exit(1); + } +#endif +} + +void free_proc_compat(void) { + child_pump_running = false; +} + #ifdef VANILLA_WIN32 struct wait_context { HANDLE wait_handle; @@ -251,16 +292,6 @@ int resume_child(void) { free(param); return 1; #else -# if defined(__unix__) || defined(__APPLE__) - struct sigaction sa; - sa.sa_handler = &handle_sigchld; - sigemptyset(&sa.sa_mask); - sa.sa_flags = SA_RESTART | SA_NOCLDSTOP; - if (sigaction(SIGCHLD, &sa, 0) == -1) { - perror(0); - exit(1); - } -# endif return 0; #endif } diff --git a/src/compat/process.h b/src/compat/process.h index 1259e7ea..193c12b6 100644 --- a/src/compat/process.h +++ b/src/compat/process.h @@ -60,4 +60,7 @@ bool is_current_process(s_proc_handle *proc); unsigned long long get_process_id(void); unsigned long long get_process_id_of(s_proc_handle *proc); +void init_proc_compat(void); +void free_proc_compat(void); + #endif /* !COMPAT_PROCESS_H_ */ diff --git a/src/core/runner.c b/src/core/runner.c index 091a7e43..53238dbd 100644 --- a/src/core/runner.c +++ b/src/core/runner.c @@ -452,6 +452,7 @@ static int criterion_run_all_tests_impl(struct criterion_test_set *set) { strerror(errno)); abort(); } + init_proc_compat(); struct criterion_global_stats *stats = stats_init(); run_tests_async(set, stats); @@ -466,6 +467,7 @@ static int criterion_run_all_tests_impl(struct criterion_test_set *set) { log(post_all, stats); cleanup: + free_proc_compat(); sfree(g_worker_pipe); sfree(stats); return result; From cdcf52e373866330d755a2a6a62ac55599953e8d Mon Sep 17 00:00:00 2001 From: Snaipe Date: Mon, 7 Dec 2015 13:55:55 +0100 Subject: [PATCH 196/211] Fixed conditional windows build broken by 13e7928d0c8fbebbe533ca7d09727718d57dc430 --- src/compat/process.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/compat/process.c b/src/compat/process.c index ba7055c4..6bb6872f 100644 --- a/src/compat/process.c +++ b/src/compat/process.c @@ -182,7 +182,9 @@ void init_proc_compat(void) { } void free_proc_compat(void) { +#ifndef VANILLA_WIN32 child_pump_running = false; +#endif } #ifdef VANILLA_WIN32 From dbe2894b885ff2d122e5bdaf02952f3b4dfd900f Mon Sep 17 00:00:00 2001 From: Snaipe Date: Mon, 7 Dec 2015 13:57:22 +0100 Subject: [PATCH 197/211] [Issue #81] Fixed documentation not mentioning that the assert message is a format string --- doc/assert.rst | 217 +++++++++++++++++++++++++------------------------ 1 file changed, 110 insertions(+), 107 deletions(-) diff --git a/doc/assert.rst b/doc/assert.rst index 46ad0044..20972419 100644 --- a/doc/assert.rst +++ b/doc/assert.rst @@ -9,36 +9,39 @@ As each ``assert`` macros have an ``expect`` counterpart with the exact same number of parameters and name suffix, there is no benefit in adding ``expect`` macros to this list. Hence only ``assert`` macros are represented here. +All ``assert`` macros may take an optional ``printf`` format string and +parameters. + Common Assertions ----------------- -======================================================================= =========================================================================== =========================================== -Macro Passes if and only if Notes -======================================================================= =========================================================================== =========================================== -cr_assert(Condition, [Message, [Args...]]) ``Condition`` is true. ------------------------------------------------------------------------ --------------------------------------------------------------------------- ------------------------------------------- -cr_assert_not(Condition, [Message, [Args...]]) ``Condition`` is false. ------------------------------------------------------------------------ --------------------------------------------------------------------------- ------------------------------------------- -cr_assert_null(Value, [Message, [Args...]]) ``Value`` is ``NULL``. ------------------------------------------------------------------------ --------------------------------------------------------------------------- ------------------------------------------- -cr_assert_not_null(Value, [Message, [Args...]]) ``Value`` is not ``NULL``. ------------------------------------------------------------------------ --------------------------------------------------------------------------- ------------------------------------------- -cr_assert_eq(Actual, Expected, [Message, [Args...]]) ``Actual`` is equal to ``Expected``. Compatible with C++ operator overloading ------------------------------------------------------------------------ --------------------------------------------------------------------------- ------------------------------------------- -cr_assert_neq(Actual, Unexpected, [Message, [Args...]]) ``Actual`` is not equal to ``Unexpected``. Compatible with C++ operator overloading ------------------------------------------------------------------------ --------------------------------------------------------------------------- ------------------------------------------- -cr_assert_lt(Actual, Reference, [Message, [Args...]]) ``Actual`` is less than ``Reference``. Compatible with C++ operator overloading ------------------------------------------------------------------------ --------------------------------------------------------------------------- ------------------------------------------- -cr_assert_leq(Actual, Reference, [Message, [Args...]]) ``Actual`` is less or equal to ``Reference``. Compatible with C++ operator overloading ------------------------------------------------------------------------ --------------------------------------------------------------------------- ------------------------------------------- -cr_assert_gt(Actual, Reference, [Message, [Args...]]) ``Actual`` is greater than ``Reference``. Compatible with C++ operator overloading ------------------------------------------------------------------------ --------------------------------------------------------------------------- ------------------------------------------- -cr_assert_geq(Actual, Reference, [Message, [Args...]]) ``Actual`` is greater or equal to ``Reference``. Compatible with C++ operator overloading ------------------------------------------------------------------------ --------------------------------------------------------------------------- ------------------------------------------- -cr_assert_float_eq(Actual, Expected, Epsilon, [Message, [Args...]]) ``Actual`` is equal to ``Expected`` with a tolerance of ``Epsilon``. Use this to test equality between floats ------------------------------------------------------------------------ --------------------------------------------------------------------------- ------------------------------------------- -cr_assert_float_neq(Actual, Unexpected, Epsilon, [Message, [Args...]]) ``Actual`` is not equal to ``Unexpected`` with a tolerance of ``Epsilon``. Use this to test inequality between floats -======================================================================= =========================================================================== =========================================== +=========================================================================== =========================================================================== =========================================== +Macro Passes if and only if Notes +=========================================================================== =========================================================================== =========================================== +cr_assert(Condition, [FormatString, [Args...]]) ``Condition`` is true. +--------------------------------------------------------------------------- --------------------------------------------------------------------------- ------------------------------------------- +cr_assert_not(Condition, [FormatString, [Args...]]) ``Condition`` is false. +--------------------------------------------------------------------------- --------------------------------------------------------------------------- ------------------------------------------- +cr_assert_null(Value, [FormatString, [Args...]]) ``Value`` is ``NULL``. +--------------------------------------------------------------------------- --------------------------------------------------------------------------- ------------------------------------------- +cr_assert_not_null(Value, [FormatString, [Args...]]) ``Value`` is not ``NULL``. +--------------------------------------------------------------------------- --------------------------------------------------------------------------- ------------------------------------------- +cr_assert_eq(Actual, Expected, [FormatString, [Args...]]) ``Actual`` is equal to ``Expected``. Compatible with C++ operator overloading +--------------------------------------------------------------------------- --------------------------------------------------------------------------- ------------------------------------------- +cr_assert_neq(Actual, Unexpected, [FormatString, [Args...]]) ``Actual`` is not equal to ``Unexpected``. Compatible with C++ operator overloading +--------------------------------------------------------------------------- --------------------------------------------------------------------------- ------------------------------------------- +cr_assert_lt(Actual, Reference, [FormatString, [Args...]]) ``Actual`` is less than ``Reference``. Compatible with C++ operator overloading +--------------------------------------------------------------------------- --------------------------------------------------------------------------- ------------------------------------------- +cr_assert_leq(Actual, Reference, [FormatString, [Args...]]) ``Actual`` is less or equal to ``Reference``. Compatible with C++ operator overloading +--------------------------------------------------------------------------- --------------------------------------------------------------------------- ------------------------------------------- +cr_assert_gt(Actual, Reference, [FormatString, [Args...]]) ``Actual`` is greater than ``Reference``. Compatible with C++ operator overloading +--------------------------------------------------------------------------- --------------------------------------------------------------------------- ------------------------------------------- +cr_assert_geq(Actual, Reference, [FormatString, [Args...]]) ``Actual`` is greater or equal to ``Reference``. Compatible with C++ operator overloading +--------------------------------------------------------------------------- --------------------------------------------------------------------------- ------------------------------------------- +cr_assert_float_eq(Actual, Expected, Epsilon, [FormatString, [Args...]]) ``Actual`` is equal to ``Expected`` with a tolerance of ``Epsilon``. Use this to test equality between floats +--------------------------------------------------------------------------- --------------------------------------------------------------------------- ------------------------------------------- +cr_assert_float_neq(Actual, Unexpected, Epsilon, [FormatString, [Args...]]) ``Actual`` is not equal to ``Unexpected`` with a tolerance of ``Epsilon``. Use this to test inequality between floats +=========================================================================== =========================================================================== =========================================== String Assertions ----------------- @@ -47,98 +50,98 @@ Note: these macros are meant to deal with *native* strings, i.e. char arrays. Most of them won't work on ``std::string`` in C++, with some exceptions -- for ``std::string``, you should use regular comparison assersions, as listed above. -=========================================================== =================================================================== =========================================== -Macro Passes if and only if Notes -=========================================================== =================================================================== =========================================== -cr_assert_str_empty(Value, [Message, [Args...]]) ``Value`` is an empty string. Also works on std::string ------------------------------------------------------------ ------------------------------------------------------------------- ------------------------------------------- -cr_assert_str_not_empty(Value, [Message, [Args...]]) ``Value`` is not an empty string. Also works on std::string ------------------------------------------------------------ ------------------------------------------------------------------- ------------------------------------------- -cr_assert_str_eq(Actual, Expected, [Message, [Args...]]) ``Actual`` is lexicographically equal to ``Expected``. ------------------------------------------------------------ ------------------------------------------------------------------- ------------------------------------------- -cr_assert_str_neq(Actual, Unexpected, [Message, [Args...]]) ``Actual`` is not lexicographically equal to ``Unexpected``. ------------------------------------------------------------ ------------------------------------------------------------------- ------------------------------------------- -cr_assert_str_lt(Actual, Reference, [Message, [Args...]]) ``Actual`` is lexicographically less than ``Reference``. ------------------------------------------------------------ ------------------------------------------------------------------- ------------------------------------------- -cr_assert_str_leq(Actual, Reference, [Message, [Args...]]) ``Actual`` is lexicographically less or equal to ``Reference``. ------------------------------------------------------------ ------------------------------------------------------------------- ------------------------------------------- -cr_assert_str_gt(Actual, Reference, [Message, [Args...]]) ``Actual`` is lexicographically greater than ``Reference``. ------------------------------------------------------------ ------------------------------------------------------------------- ------------------------------------------- -cr_assert_str_geq(Actual, Reference, [Message, [Args...]]) ``Actual`` is lexicographically greater or equal to ``Reference``. -=========================================================== =================================================================== =========================================== +================================================================ =================================================================== =========================================== +Macro Passes if and only if Notes +================================================================ =================================================================== =========================================== +cr_assert_str_empty(Value, [FormatString, [Args...]]) ``Value`` is an empty string. Also works on std::string +---------------------------------------------------------------- ------------------------------------------------------------------- ------------------------------------------- +cr_assert_str_not_empty(Value, [FormatString, [Args...]]) ``Value`` is not an empty string. Also works on std::string +---------------------------------------------------------------- ------------------------------------------------------------------- ------------------------------------------- +cr_assert_str_eq(Actual, Expected, [FormatString, [Args...]]) ``Actual`` is lexicographically equal to ``Expected``. +---------------------------------------------------------------- ------------------------------------------------------------------- ------------------------------------------- +cr_assert_str_neq(Actual, Unexpected, [FormatString, [Args...]]) ``Actual`` is not lexicographically equal to ``Unexpected``. +---------------------------------------------------------------- ------------------------------------------------------------------- ------------------------------------------- +cr_assert_str_lt(Actual, Reference, [FormatString, [Args...]]) ``Actual`` is lexicographically less than ``Reference``. +---------------------------------------------------------------- ------------------------------------------------------------------- ------------------------------------------- +cr_assert_str_leq(Actual, Reference, [FormatString, [Args...]]) ``Actual`` is lexicographically less or equal to ``Reference``. +---------------------------------------------------------------- ------------------------------------------------------------------- ------------------------------------------- +cr_assert_str_gt(Actual, Reference, [FormatString, [Args...]]) ``Actual`` is lexicographically greater than ``Reference``. +---------------------------------------------------------------- ------------------------------------------------------------------- ------------------------------------------- +cr_assert_str_geq(Actual, Reference, [FormatString, [Args...]]) ``Actual`` is lexicographically greater or equal to ``Reference``. +================================================================ =================================================================== =========================================== Array Assertions ----------------- -=========================================================================== =========================================================================== =========================================== -Macro Passes if and only if Notes -=========================================================================== =========================================================================== =========================================== -cr_assert_arr_eq(Actual, Expected, [Message, [Args...]]) ``Actual`` is byte-to-byte equal to ``Expected``. This should not be used on struct arrays, - consider using ``cr_assert_arr_eq_cmp`` - instead. ---------------------------------------------------------------------------- --------------------------------------------------------------------------- ------------------------------------------- -cr_assert_arr_neq(Actual, Unexpected, [Message, [Args...]]) ``Actual`` is not byte-to-byte equal to ``Unexpected``. This should not be used on struct arrays, - consider using ``cr_assert_arr_neq_cmp`` - instead. ---------------------------------------------------------------------------- --------------------------------------------------------------------------- ------------------------------------------- -cr_assert_arr_eq_cmp(Actual, Expected, Size, Cmp, [Message, [Args...]]) ``Actual`` is comparatively equal to ``Expected`` Only available in C++ and GNU C99 ---------------------------------------------------------------------------- --------------------------------------------------------------------------- ------------------------------------------- -cr_assert_arr_neq_cmp(Actual, Unexpected, Size, Cmp, [Message, [Args...]]) ``Actual`` is not comparatively equal to ``Expected`` Only available in C++ and GNU C99 ---------------------------------------------------------------------------- --------------------------------------------------------------------------- ------------------------------------------- -cr_assert_arr_lt_cmp(Actual, Reference, Size, Cmp, [Message, [Args...]]) ``Actual`` is comparatively less than ``Reference`` Only available in C++ and GNU C99 ---------------------------------------------------------------------------- --------------------------------------------------------------------------- ------------------------------------------- -cr_assert_arr_leq_cmp(Actual, Reference, Size, Cmp, [Message, [Args...]]) ``Actual`` is comparatively less or equal to ``Reference`` Only available in C++ and GNU C99 ---------------------------------------------------------------------------- --------------------------------------------------------------------------- ------------------------------------------- -cr_assert_arr_gt_cmp(Actual, Reference, Size, Cmp, [Message, [Args...]]) ``Actual`` is comparatively greater than ``Reference`` Only available in C++ and GNU C99 ---------------------------------------------------------------------------- --------------------------------------------------------------------------- ------------------------------------------- -cr_assert_arr_geq_cmp(Actual, Reference, Size, Cmp, [Message, [Args...]]) ``Actual`` is comparatively greater or equal to ``Reference`` Only available in C++ and GNU C99 -=========================================================================== =========================================================================== =========================================== +=============================================================================== =========================================================================== =========================================== +Macro Passes if and only if Notes +=============================================================================== =========================================================================== =========================================== +cr_assert_arr_eq(Actual, Expected, [FormatString, [Args...]]) ``Actual`` is byte-to-byte equal to ``Expected``. This should not be used on struct arrays, + consider using ``cr_assert_arr_eq_cmp`` + instead. +------------------------------------------------------------------------------- --------------------------------------------------------------------------- ------------------------------------------- +cr_assert_arr_neq(Actual, Unexpected, [FormatString, [Args...]]) ``Actual`` is not byte-to-byte equal to ``Unexpected``. This should not be used on struct arrays, + consider using ``cr_assert_arr_neq_cmp`` + instead. +------------------------------------------------------------------------------- --------------------------------------------------------------------------- ------------------------------------------- +cr_assert_arr_eq_cmp(Actual, Expected, Size, Cmp, [FormatString, [Args...]]) ``Actual`` is comparatively equal to ``Expected`` Only available in C++ and GNU C99 +------------------------------------------------------------------------------- --------------------------------------------------------------------------- ------------------------------------------- +cr_assert_arr_neq_cmp(Actual, Unexpected, Size, Cmp, [FormatString, [Args...]]) ``Actual`` is not comparatively equal to ``Expected`` Only available in C++ and GNU C99 +------------------------------------------------------------------------------- --------------------------------------------------------------------------- ------------------------------------------- +cr_assert_arr_lt_cmp(Actual, Reference, Size, Cmp, [FormatString, [Args...]]) ``Actual`` is comparatively less than ``Reference`` Only available in C++ and GNU C99 +------------------------------------------------------------------------------- --------------------------------------------------------------------------- ------------------------------------------- +cr_assert_arr_leq_cmp(Actual, Reference, Size, Cmp, [FormatString, [Args...]]) ``Actual`` is comparatively less or equal to ``Reference`` Only available in C++ and GNU C99 +------------------------------------------------------------------------------- --------------------------------------------------------------------------- ------------------------------------------- +cr_assert_arr_gt_cmp(Actual, Reference, Size, Cmp, [FormatString, [Args...]]) ``Actual`` is comparatively greater than ``Reference`` Only available in C++ and GNU C99 +------------------------------------------------------------------------------- --------------------------------------------------------------------------- ------------------------------------------- +cr_assert_arr_geq_cmp(Actual, Reference, Size, Cmp, [FormatString, [Args...]]) ``Actual`` is comparatively greater or equal to ``Reference`` Only available in C++ and GNU C99 +=============================================================================== =========================================================================== =========================================== Exception Assertions -------------------- The following assertion macros are only defined for C++. -=========================================================================== =========================================================================== =========================================== -Macro Passes if and only if Notes -=========================================================================== =========================================================================== =========================================== -cr_assert_throw(Statement, Exception, [Message, [Args...]]) ``Statement`` throws an instance of ``Exception``. ---------------------------------------------------------------------------- --------------------------------------------------------------------------- ------------------------------------------- -cr_assert_no_throw(Statement, Exception, [Message, [Args...]]) ``Statement`` does not throws an instance of ``Exception``. ---------------------------------------------------------------------------- --------------------------------------------------------------------------- ------------------------------------------- -cr_assert_any_throw(Statement, [Message, [Args...]]) ``Statement`` throws any kind of exception. ---------------------------------------------------------------------------- --------------------------------------------------------------------------- ------------------------------------------- -cr_assert_none_throw(Statement, [Message, [Args...]]) ``Statement`` does not throw any exception. -=========================================================================== =========================================================================== =========================================== +=============================================================================== =========================================================================== =========================================== +Macro Passes if and only if Notes +=============================================================================== =========================================================================== =========================================== +cr_assert_throw(Statement, Exception, [FormatString, [Args...]]) ``Statement`` throws an instance of ``Exception``. +------------------------------------------------------------------------------- --------------------------------------------------------------------------- ------------------------------------------- +cr_assert_no_throw(Statement, Exception, [FormatString, [Args...]]) ``Statement`` does not throws an instance of ``Exception``. +------------------------------------------------------------------------------- --------------------------------------------------------------------------- ------------------------------------------- +cr_assert_any_throw(Statement, [FormatString, [Args...]]) ``Statement`` throws any kind of exception. +------------------------------------------------------------------------------- --------------------------------------------------------------------------- ------------------------------------------- +cr_assert_none_throw(Statement, [FormatString, [Args...]]) ``Statement`` does not throw any exception. +=============================================================================== =========================================================================== =========================================== File Assertions --------------- -=============================================================================== ============================================================================ =========================================== -Macro Passes if and only if Notes -=============================================================================== ============================================================================ =========================================== -cr_assert_file_contents_eq_str(File, ExpectedContents, [Message, [Args...]]) The contents of ``File`` are equal to the string ``ExpectedContents``. -------------------------------------------------------------------------------- ---------------------------------------------------------------------------- ------------------------------------------- -cr_assert_file_contents_neq_str(File, ExpectedContents, [Message, [Args...]]) The contents of ``File`` are not equal to the string ``ExpectedContents``. -------------------------------------------------------------------------------- ---------------------------------------------------------------------------- ------------------------------------------- -cr_assert_stdout_eq_str(ExpectedContents, [Message, [Args...]]) The contents of ``stdout`` are equal to the string ``ExpectedContents``. -------------------------------------------------------------------------------- ---------------------------------------------------------------------------- ------------------------------------------- -cr_assert_stdout_neq_str(ExpectedContents, [Message, [Args...]]) The contents of ``stdout`` are not equal to the string ``ExpectedContents``. -------------------------------------------------------------------------------- ---------------------------------------------------------------------------- ------------------------------------------- -cr_assert_stderr_eq_str(ExpectedContents, [Message, [Args...]]) The contents of ``stderr`` are equal to the string ``ExpectedContents``. -------------------------------------------------------------------------------- ---------------------------------------------------------------------------- ------------------------------------------- -cr_assert_stderr_neq_str(ExpectedContents, [Message, [Args...]]) The contents of ``stderr`` are not equal to the string ``ExpectedContents``. -------------------------------------------------------------------------------- ---------------------------------------------------------------------------- ------------------------------------------- -cr_assert_file_contents_eq(File, RefFile, [Message, [Args...]]) The contents of ``File`` are equal to the contents of ``RefFile``. -------------------------------------------------------------------------------- ---------------------------------------------------------------------------- ------------------------------------------- -cr_assert_file_contents_neq(File, RefFile, [Message, [Args...]]) The contents of ``File`` are not equal to the contents of ``RefFile``. -------------------------------------------------------------------------------- ---------------------------------------------------------------------------- ------------------------------------------- -cr_assert_stdout_eq(RefFile, [Message, [Args...]]) The contents of ``stdout`` are equal to the contents of ``RefFile``. -------------------------------------------------------------------------------- ---------------------------------------------------------------------------- ------------------------------------------- -cr_assert_stdout_neq(RefFile, [Message, [Args...]]) The contents of ``stdout`` are not equal to the contents of ``RefFile``. -------------------------------------------------------------------------------- ---------------------------------------------------------------------------- ------------------------------------------- -cr_assert_stderr_eq(RefFile, [Message, [Args...]]) The contents of ``stderr`` are equal to the contents of ``RefFile``. -------------------------------------------------------------------------------- ---------------------------------------------------------------------------- ------------------------------------------- -cr_assert_stderr_neq(RefFile, [Message, [Args...]]) The contents of ``stderr`` are not equal to the contents of ``RefFile``. -=============================================================================== ============================================================================ =========================================== +=================================================================================== ============================================================================ =========================================== +Macro Passes if and only if Notes +=================================================================================== ============================================================================ =========================================== +cr_assert_file_contents_eq_str(File, ExpectedContents, [FormatString, [Args...]]) The contents of ``File`` are equal to the string ``ExpectedContents``. +----------------------------------------------------------------------------------- ---------------------------------------------------------------------------- ------------------------------------------- +cr_assert_file_contents_neq_str(File, ExpectedContents, [FormatString, [Args...]]) The contents of ``File`` are not equal to the string ``ExpectedContents``. +----------------------------------------------------------------------------------- ---------------------------------------------------------------------------- ------------------------------------------- +cr_assert_stdout_eq_str(ExpectedContents, [FormatString, [Args...]]) The contents of ``stdout`` are equal to the string ``ExpectedContents``. +----------------------------------------------------------------------------------- ---------------------------------------------------------------------------- ------------------------------------------- +cr_assert_stdout_neq_str(ExpectedContents, [FormatString, [Args...]]) The contents of ``stdout`` are not equal to the string ``ExpectedContents``. +----------------------------------------------------------------------------------- ---------------------------------------------------------------------------- ------------------------------------------- +cr_assert_stderr_eq_str(ExpectedContents, [FormatString, [Args...]]) The contents of ``stderr`` are equal to the string ``ExpectedContents``. +----------------------------------------------------------------------------------- ---------------------------------------------------------------------------- ------------------------------------------- +cr_assert_stderr_neq_str(ExpectedContents, [FormatString, [Args...]]) The contents of ``stderr`` are not equal to the string ``ExpectedContents``. +----------------------------------------------------------------------------------- ---------------------------------------------------------------------------- ------------------------------------------- +cr_assert_file_contents_eq(File, RefFile, [FormatString, [Args...]]) The contents of ``File`` are equal to the contents of ``RefFile``. +----------------------------------------------------------------------------------- ---------------------------------------------------------------------------- ------------------------------------------- +cr_assert_file_contents_neq(File, RefFile, [FormatString, [Args...]]) The contents of ``File`` are not equal to the contents of ``RefFile``. +----------------------------------------------------------------------------------- ---------------------------------------------------------------------------- ------------------------------------------- +cr_assert_stdout_eq(RefFile, [FormatString, [Args...]]) The contents of ``stdout`` are equal to the contents of ``RefFile``. +----------------------------------------------------------------------------------- ---------------------------------------------------------------------------- ------------------------------------------- +cr_assert_stdout_neq(RefFile, [FormatString, [Args...]]) The contents of ``stdout`` are not equal to the contents of ``RefFile``. +----------------------------------------------------------------------------------- ---------------------------------------------------------------------------- ------------------------------------------- +cr_assert_stderr_eq(RefFile, [FormatString, [Args...]]) The contents of ``stderr`` are equal to the contents of ``RefFile``. +----------------------------------------------------------------------------------- ---------------------------------------------------------------------------- ------------------------------------------- +cr_assert_stderr_neq(RefFile, [FormatString, [Args...]]) The contents of ``stderr`` are not equal to the contents of ``RefFile``. +=================================================================================== ============================================================================ =========================================== From 00ca6cfc6742d03fe30776befd9bb9e753a4c507 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Mon, 7 Dec 2015 15:03:27 +0100 Subject: [PATCH 198/211] Added doxygen docs for abort.h --- include/criterion/abort.h | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/include/criterion/abort.h b/include/criterion/abort.h index d6a649e6..77d841ee 100644 --- a/include/criterion/abort.h +++ b/include/criterion/abort.h @@ -28,7 +28,18 @@ CR_BEGIN_C_API +/** + * Aborts the current test, marking it as failed. + * + * This function does not return. + */ CR_API CR_NORETURN void criterion_abort_test(void); + +/** + * Continues the current test. + * + * Used as a counterpart to criterion_abort_test. + */ CR_INLINE static void criterion_continue_test(void) {} CR_END_C_API From 2e5e4af3c721a52c16761455eebbf732ebe8a570 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Mon, 7 Dec 2015 15:03:35 +0100 Subject: [PATCH 199/211] Added doxygen docs for alloc.h --- include/criterion/alloc.h | 116 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 116 insertions(+) diff --git a/include/criterion/alloc.h b/include/criterion/alloc.h index 71d4ca77..555a1dec 100644 --- a/include/criterion/alloc.h +++ b/include/criterion/alloc.h @@ -35,9 +35,55 @@ using std::size_t; CR_BEGIN_C_API +/** + * Allocates a block of memory usable by the test. + * + * It is undefined behaviour to access a pointer returned by malloc(3) + * inside a test or its setup and teardown functions; cr_malloc must + * be use in its place for this purpose. + * + * This function is semantically identical to malloc(3). + * + * @param[in] size The minimal size in bytes of the newly allocated memory. + * @returns The pointer to the start of the allocated memory. + */ CR_API void *cr_malloc(size_t size); + +/** + * Allocates and zero-initialize a block of memory usable by the test. + * + * It is undefined behaviour to access a pointer returned by calloc(3) + * inside a test or its setup and teardown functions; cr_calloc must + * be use in its place for this purpose. + * + * This function is semantically identical to calloc(3). + * + * @param[in] nmemb The number of elements to allocate + * @param[in] size The minimal size of each element. + * @returns The pointer to the start of the allocated memory. + */ CR_API void *cr_calloc(size_t nmemb, size_t size); + +/** + * Reallocates a block of memory usable by the test. + * + * It is undefined behaviour to access a pointer returned by realloc(3) + * inside a test or its setup and teardown functions; cr_realloc must + * be used in its place for this purpose. + * + * This function is semantically identical to realloc(3). + * + * @param[in] ptr A pointer to the memory that needs to be resized. + * @param[in] size The minimal size of the reallocated memory. + * @returns The pointer to the start of the reallocated memory. + */ CR_API void *cr_realloc(void *ptr, size_t size); + +/** + * Free a block of memory allocated by cr_malloc, cr_free or cr_realloc. + * + * @param[in] ptr A pointer to the memory that needs to be freed. + */ CR_API void cr_free(void *ptr); CR_END_C_API @@ -52,6 +98,19 @@ namespace criterion { void *(*const calloc)(size_t, size_t) = cr_calloc; void *(*const realloc)(void *, size_t) = cr_realloc; + /** + * Allocates and construct a new object. + * + * It is undefined behaviour to access a pointer returned by the new + * operator inside a test or its setup and teardown functions; + * new_obj must be used in its place for this purpose. + * + * This function is semantically identical to the new operator. + * + * @tparam T The type of the object to construct + * @param[in] params The constructor parameters of T. + * @returns The pointer to the newly constructed object. + */ template T* new_obj(Params... params) { T* obj = static_cast(cr_malloc(sizeof (T))); @@ -59,6 +118,19 @@ namespace criterion { return obj; } + /** + * Allocates and construct a new array of primitive types + * + * It is undefined behaviour to access a pointer returned by the new[] + * operator inside a test or its setup and teardown functions; + * new_arr must be used in its place for this purpose. + * + * This function is semantically identical to the new[] operator. + * + * @tparam T The compound type of the array to construct + * @param[in] len The length of the array. + * @returns The pointer to the newly constructed array. + */ template typename std::enable_if::value>::type* new_arr(size_t len) { @@ -68,6 +140,19 @@ namespace criterion { return arr; } + /** + * Allocates and construct a new array of object types + * + * It is undefined behaviour to access a pointer returned by the new[] + * operator inside a test or its setup and teardown functions; + * new_arr must be used in its place for this purpose. + * + * This function is semantically identical to the new[] operator. + * + * @tparam T The compound type of the array to construct + * @param[in] len The length of the array. + * @returns The pointer to the newly constructed array. + */ template T* new_arr(size_t len) { void *ptr = cr_malloc(sizeof (size_t) + sizeof (T) * len); @@ -79,17 +164,41 @@ namespace criterion { return arr; } + /** + * Destroys and frees an object allocated by new_obj. + * + * This function is semantically identical to the delete operator. + * + * @tparam T The type of the object to construct + * @param[in] ptr The object to destroy. + */ template void delete_obj(T* ptr) { ptr->~T(); cr_free(ptr); } + /** + * Destroys and frees an array allocated by delete_arr. + * + * This function is semantically identical to the delete[] operator. + * + * @tparam T The type of the object to construct + * @param[in] ptr The object to destroy. + */ template void delete_arr(typename std::enable_if::value>::type* ptr) { cr_free(ptr); } + /** + * Destroys and frees an array allocated by delete_arr. + * + * This function is semantically identical to the delete[] operator. + * + * @tparam T The type of the object to construct + * @param[in] ptr The object to destroy. + */ template void delete_arr(T* ptr) { size_t *ptr_ = reinterpret_cast(ptr); @@ -100,6 +209,13 @@ namespace criterion { cr_free(ptr_ - 1); } + /** + * Allocator for use in the STL. + * + * This internally uses calls to the cr_malloc function family, which + * means that STL collections can be safely used inside tests or + * setup/teardown functions if this allocator is used. + */ template struct allocator { typedef T value_type; From 1b9c13246a4d20db051346fdd186896e61278aa2 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Mon, 7 Dec 2015 15:09:30 +0100 Subject: [PATCH 200/211] Fixed misformed table in assert docs --- doc/assert.rst | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/doc/assert.rst b/doc/assert.rst index 20972419..49d23341 100644 --- a/doc/assert.rst +++ b/doc/assert.rst @@ -118,30 +118,30 @@ File Assertions --------------- =================================================================================== ============================================================================ =========================================== -Macro Passes if and only if Notes +Macro Passes if and only if Notes =================================================================================== ============================================================================ =========================================== -cr_assert_file_contents_eq_str(File, ExpectedContents, [FormatString, [Args...]]) The contents of ``File`` are equal to the string ``ExpectedContents``. +cr_assert_file_contents_eq_str(File, ExpectedContents, [FormatString, [Args...]]) The contents of ``File`` are equal to the string ``ExpectedContents``. ----------------------------------------------------------------------------------- ---------------------------------------------------------------------------- ------------------------------------------- -cr_assert_file_contents_neq_str(File, ExpectedContents, [FormatString, [Args...]]) The contents of ``File`` are not equal to the string ``ExpectedContents``. +cr_assert_file_contents_neq_str(File, ExpectedContents, [FormatString, [Args...]]) The contents of ``File`` are not equal to the string ``ExpectedContents``. ----------------------------------------------------------------------------------- ---------------------------------------------------------------------------- ------------------------------------------- -cr_assert_stdout_eq_str(ExpectedContents, [FormatString, [Args...]]) The contents of ``stdout`` are equal to the string ``ExpectedContents``. +cr_assert_stdout_eq_str(ExpectedContents, [FormatString, [Args...]]) The contents of ``stdout`` are equal to the string ``ExpectedContents``. ----------------------------------------------------------------------------------- ---------------------------------------------------------------------------- ------------------------------------------- -cr_assert_stdout_neq_str(ExpectedContents, [FormatString, [Args...]]) The contents of ``stdout`` are not equal to the string ``ExpectedContents``. +cr_assert_stdout_neq_str(ExpectedContents, [FormatString, [Args...]]) The contents of ``stdout`` are not equal to the string ``ExpectedContents``. ----------------------------------------------------------------------------------- ---------------------------------------------------------------------------- ------------------------------------------- -cr_assert_stderr_eq_str(ExpectedContents, [FormatString, [Args...]]) The contents of ``stderr`` are equal to the string ``ExpectedContents``. +cr_assert_stderr_eq_str(ExpectedContents, [FormatString, [Args...]]) The contents of ``stderr`` are equal to the string ``ExpectedContents``. ----------------------------------------------------------------------------------- ---------------------------------------------------------------------------- ------------------------------------------- -cr_assert_stderr_neq_str(ExpectedContents, [FormatString, [Args...]]) The contents of ``stderr`` are not equal to the string ``ExpectedContents``. +cr_assert_stderr_neq_str(ExpectedContents, [FormatString, [Args...]]) The contents of ``stderr`` are not equal to the string ``ExpectedContents``. ----------------------------------------------------------------------------------- ---------------------------------------------------------------------------- ------------------------------------------- -cr_assert_file_contents_eq(File, RefFile, [FormatString, [Args...]]) The contents of ``File`` are equal to the contents of ``RefFile``. +cr_assert_file_contents_eq(File, RefFile, [FormatString, [Args...]]) The contents of ``File`` are equal to the contents of ``RefFile``. ----------------------------------------------------------------------------------- ---------------------------------------------------------------------------- ------------------------------------------- -cr_assert_file_contents_neq(File, RefFile, [FormatString, [Args...]]) The contents of ``File`` are not equal to the contents of ``RefFile``. +cr_assert_file_contents_neq(File, RefFile, [FormatString, [Args...]]) The contents of ``File`` are not equal to the contents of ``RefFile``. ----------------------------------------------------------------------------------- ---------------------------------------------------------------------------- ------------------------------------------- -cr_assert_stdout_eq(RefFile, [FormatString, [Args...]]) The contents of ``stdout`` are equal to the contents of ``RefFile``. +cr_assert_stdout_eq(RefFile, [FormatString, [Args...]]) The contents of ``stdout`` are equal to the contents of ``RefFile``. ----------------------------------------------------------------------------------- ---------------------------------------------------------------------------- ------------------------------------------- -cr_assert_stdout_neq(RefFile, [FormatString, [Args...]]) The contents of ``stdout`` are not equal to the contents of ``RefFile``. +cr_assert_stdout_neq(RefFile, [FormatString, [Args...]]) The contents of ``stdout`` are not equal to the contents of ``RefFile``. ----------------------------------------------------------------------------------- ---------------------------------------------------------------------------- ------------------------------------------- -cr_assert_stderr_eq(RefFile, [FormatString, [Args...]]) The contents of ``stderr`` are equal to the contents of ``RefFile``. +cr_assert_stderr_eq(RefFile, [FormatString, [Args...]]) The contents of ``stderr`` are equal to the contents of ``RefFile``. ----------------------------------------------------------------------------------- ---------------------------------------------------------------------------- ------------------------------------------- -cr_assert_stderr_neq(RefFile, [FormatString, [Args...]]) The contents of ``stderr`` are not equal to the contents of ``RefFile``. +cr_assert_stderr_neq(RefFile, [FormatString, [Args...]]) The contents of ``stderr`` are not equal to the contents of ``RefFile``. =================================================================================== ============================================================================ =========================================== From 415fc20462e524c5fbc6a69e47be210a07f19834 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Tue, 8 Dec 2015 00:33:55 +0100 Subject: [PATCH 201/211] Added doxygen for hooks.h --- include/criterion/hooks.h | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/include/criterion/hooks.h b/include/criterion/hooks.h index a7559c60..d4e34ee3 100644 --- a/include/criterion/hooks.h +++ b/include/criterion/hooks.h @@ -26,6 +26,9 @@ # include "internal/hooks.h" +/** + * This enum lists all the phases of the runner lifecycle. + */ typedef enum { PRE_ALL, PRE_SUITE, @@ -42,6 +45,24 @@ typedef enum { typedef void (*f_report_hook)(); +/** + * ReportHook(Kind)(Type *param) { Function Body } + * + * Defines a report hook for the phase defined by Kind. + * + * The type of the parameter depends on the phase: + * + * - struct criterion_test_set for PRE_ALL. + * - struct criterion_suite_set for PRE_SUITE. + * - struct criterion_test for PRE_INIT and PRE_TEST. + * - struct criterion_assert_stats for ASSERT. + * - struct criterion_theory_stats for THEORY_FAIL. + * - struct criterion_test_stats for POST_TEST, POST_FINI, and TEST_CRASH. + * - struct criterion_suite_stats for POST_SUITE. + * - struct criterion_global_stats for POST_ALL. + * + * @param Kind The report phase to hook the function onto. + */ # define ReportHook(Kind) CR_REPORT_HOOK_IMPL(Kind) #endif /* !CRITERION_HOOKS_H_ */ From 7c416af673fa755ed60195cce5a764b5828c007e Mon Sep 17 00:00:00 2001 From: Snaipe Date: Tue, 8 Dec 2015 00:34:02 +0100 Subject: [PATCH 202/211] Added doxygen for options.h --- include/criterion/options.h | 70 +++++++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) diff --git a/include/criterion/options.h b/include/criterion/options.h index 220e32c9..fbe90144 100644 --- a/include/criterion/options.h +++ b/include/criterion/options.h @@ -28,20 +28,90 @@ # include "logging.h" struct criterion_options { + + /** + * The current logging threshold. + * + * default: 1 + */ enum criterion_logging_level logging_threshold; + + /** + * The logger that will be used during the execution of the runner. + * + * default: normal logger + */ struct criterion_logger *logger; + + /** + * Don't exit the child immediately after finishing to run the test + * function, and perform a full cleanup. + * + * Useful when tracking memory leaks, and is immediately implied when + * running the process under valgrind. + * + * default: false + */ bool no_early_exit; + + /** + * Always return a success from criterion_run_all_tests. + * + * default: false + */ bool always_succeed; + + /** + * Disable unicode and ansi coloring from the logging system. + * + * default: false + */ bool use_ascii; + + /** + * Exit immediately after the first test failure. + * + * default: false + */ bool fail_fast; + + /** + * Disable all tests not matching this extglob pattern. + * if NULL, don't filter tests. + * + * default: NULL + */ const char *pattern; + + /** + * Only print the base file name compound of the source file containing + * the tests during reporting. + * + * default: false + */ bool short_filename; + + /** + * The maximum number of parallel jobs that the test runner will spawn. + * 0 means that this number shall be the number of cores on your system. + * + * default: 0 + */ size_t jobs; + + /** + * Measure and report times. + * + * default: true + */ bool measure_time; }; CR_BEGIN_C_API +/** + * The runtime options for the test runner. + */ extern struct criterion_options criterion_options; CR_END_C_API From 93199a16511b25c13b15d5e401a498aa7423fcf3 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Tue, 8 Dec 2015 00:34:14 +0100 Subject: [PATCH 203/211] Added doxygen for output.h --- include/criterion/output.h | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/include/criterion/output.h b/include/criterion/output.h index a5a0c666..e6366d16 100644 --- a/include/criterion/output.h +++ b/include/criterion/output.h @@ -28,7 +28,23 @@ typedef void criterion_reporter(FILE *stream, struct criterion_global_stats *); +/** + * Register an output provider. + * + * @param[in] name The name the output provider shall be registered as. + * @param[in] reporter The output reporting function. + * @returns 1 if no output provider is registered at that name, 0 otherwise, + * and -1 on error. + */ int criterion_register_output_provider(const char *name, criterion_reporter *reporter); + +/** + * Use an output provider to write a report in a specific path. + * + * @param[in] provider The name of a registered output provider. + * @param[in] path The path to the file to write the report to. + * @returns -1 on error. + */ int criterion_add_output(const char *provider, const char *path); #endif /* !CRITERION_OUTPUT_H_ */ From c681d2a42e06cc2fe9c5e6a5482a596e8747c571 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Tue, 8 Dec 2015 00:34:38 +0100 Subject: [PATCH 204/211] Added doxygen for parameterized.h --- include/criterion/internal/parameterized.h | 4 +-- include/criterion/parameterized.h | 41 +++++++++++++++++++++- 2 files changed, 42 insertions(+), 3 deletions(-) diff --git a/include/criterion/internal/parameterized.h b/include/criterion/internal/parameterized.h index 4fbd5117..29a79575 100644 --- a/include/criterion/internal/parameterized.h +++ b/include/criterion/internal/parameterized.h @@ -104,10 +104,10 @@ struct criterion_test_params { static struct criterion_test_params CR_IDENTIFIER_(Category, Name, param)(void) # ifdef __cplusplus -# define cr_make_param_array(Type, Array, ...) \ +# define cr_make_param_array_(Type, Array, ...) \ criterion_test_params(sizeof (Type), (Array), __VA_ARGS__) # else -# define cr_make_param_array(Type, Array, ...) \ +# define cr_make_param_array_(Type, Array, ...) \ (struct criterion_test_params) { .size = sizeof (Type), (void*)(Array), __VA_ARGS__ } # endif diff --git a/include/criterion/parameterized.h b/include/criterion/parameterized.h index 7099009a..2a9fafff 100644 --- a/include/criterion/parameterized.h +++ b/include/criterion/parameterized.h @@ -28,9 +28,48 @@ # include "assert.h" # include "internal/parameterized.h" +/** + * ParameterizedTest(Type *param, Suite, Name, [Options...]) { Function Body } + * + * Defines a new parameterized test. + * + * A parameterized test only takes one parameter -- to pass multiple parameters, + * use a structure type. + * + * @param Type The type of the parameter. + * @param Suite The name of the test suite containing this test. + * @param Name The name of the test. + * @param Options An optional sequence of designated initializer key/value + * pairs as described in the `criterion_test_extra_data` structure + * (see criterion/types.h). + * Example: .exit_code = 1 + */ # define ParameterizedTest(...) CR_EXPAND(CR_PARAM_TEST_BASE(__VA_ARGS__, .sentinel_ = 0)) -# define ParameterizedTestParameters(Category, Name) CR_PARAM_TEST_PARAMS(Category, Name) +/** + * ParameterizedTestParameters(Suite, Test) { Function Body } + * + * Defines the parameter generator for the associated parameterized test. + * + * @param Suite The name of the test suite containing the test. + * @param Test The name of the test. + * @returns A constructed instance of criterion::parameters, or the result of + * the cr_make_param_array macro. + */ +# define ParameterizedTestParameters(Suite, Name) CR_PARAM_TEST_PARAMS(Suite, Name) + +/** + * cr_make_param_array(Type, Array, Len, [Cleanup]); + * + * Constructs a parameter list used as a return value for a parameter generator. + * + * @param Type The type of the array subscript. + * @param Array The array of parameters. + * @param Len The length of the array. + * @param Cleanup The optional cleanup function for the array. + * @returns The parameter list. + */ +# define cr_make_param_array(...) CR_EXPAND(cr_make_param_array_(__VA_ARGS__)) # ifdef __cplusplus # include From 046e7abac51ee7a03473756e48df9b7b857069cb Mon Sep 17 00:00:00 2001 From: Snaipe Date: Tue, 8 Dec 2015 00:36:12 +0100 Subject: [PATCH 205/211] Removed objective-c dependency on deb builds & added missing libpcre3 runtime dependency --- .cmake/Modules/DebConfig.cmake | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/.cmake/Modules/DebConfig.cmake b/.cmake/Modules/DebConfig.cmake index 83e48a7a..3bbc3737 100644 --- a/.cmake/Modules/DebConfig.cmake +++ b/.cmake/Modules/DebConfig.cmake @@ -8,14 +8,13 @@ set(CPACK_DEBIAN_BUILD_DEPENDS cmake gettext libpcre3-dev - gobjc - gnustep-devel ) -set(CPACK_DEBIAN_CMAKE_OPTIONS - "-DLANG_OBJC=ON" +set(CPACK_DEBIAN_PACKAGE_DEPENDS + libpcre3 ) +set(CPACK_DEBIAN_CMAKE_OPTIONS) set(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_SOURCE_DIR}/description.txt") set(CPACK_DEBIAN_PACKAGE_SOURCE_COPY "${CMAKE_SOURCE_DIR}/.cmake/copy-source.sh") From 0dfd69b4b95a35c309c5d30a8e937209603f9ea6 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Tue, 8 Dec 2015 01:10:06 +0100 Subject: [PATCH 206/211] Added doxygen for redirect.h --- include/criterion/redirect.h | 50 ++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/include/criterion/redirect.h b/include/criterion/redirect.h index b93f2a6a..3d26d97d 100644 --- a/include/criterion/redirect.h +++ b/include/criterion/redirect.h @@ -35,17 +35,67 @@ CR_BEGIN_C_API +/** + * Redirect stdout for testing. + */ CR_API void cr_redirect_stdout(void); + +/** + * Redirect stderr for testing. + */ CR_API void cr_redirect_stderr(void); + +/** + * Redirect stdin for testing. + * This is implicitely called before each test. + */ CR_API void cr_redirect_stdin(void); +/** + * Get a file handle representing the read-end of the redirected stdout. + * + * @returns the file handle. + */ CR_API CR_STDN FILE* cr_get_redirected_stdout(void); + +/** + * Get a file handle representing the read-end of the redirected stderr. + * + * @returns the file handle. + */ CR_API CR_STDN FILE* cr_get_redirected_stderr(void); + +/** + * Get a file handle representing the write-end of the redirected stdin. + * + * @returns the file handle. + */ CR_API CR_STDN FILE* cr_get_redirected_stdin(void); +/** + * Compare the contents of a file with a string. + * + * @param[in] f The file to compare the contents to. + * @param[in] str The string to compare the contents to. + * @returns 1 if the contents of the file is equal to the string, 0 otherwise. + */ CR_API int cr_file_match_str(CR_STDN FILE* f, const char *str); + +/** + * Compare the contents of a file with the contents of another file. + * + * @param[in] f The first file to compare the contents to. + * @param[in] ref The second file to compare the contents to. + * @returns 1 if the contents of the files are equal, 0 otherwise. + */ CR_API int cr_file_match_file(CR_STDN FILE* f, CR_STDN FILE* ref); +/** + * Create a file mock. + * + * @param[in] max_size The maximum size in bytes of the file mock. + * @returns the file handle representing the mock. + */ CR_API CR_STDN FILE *cr_mock_file_size(size_t max_size); CR_END_C_API From e7234512edc6fa40d9599cb4522110df5a82c251 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Tue, 8 Dec 2015 01:44:42 +0100 Subject: [PATCH 207/211] Added doxygen for theories.h --- include/criterion/theories.h | 43 +++++++++++++++++++++++++++++++++++- 1 file changed, 42 insertions(+), 1 deletion(-) diff --git a/include/criterion/theories.h b/include/criterion/theories.h index 711e7b16..52b61832 100644 --- a/include/criterion/theories.h +++ b/include/criterion/theories.h @@ -29,16 +29,57 @@ CR_BEGIN_C_API +/** + * Aborts the current theory iteration. + * This function does not return. + */ CR_API void cr_theory_abort(void); CR_END_C_API // Theory and datapoint macros +/** + * Theory((Params...), Suite, Name, [Options...]) { Function Body } + * + * Defines a new theory test. + * + * The parameters are selected from a cartesian product defined by a + * TheoryDataPoints macro. + * + * @param Params A list of function parameters. + * @param Suite The name of the test suite containing this test. + * @param Name The name of the test. + * @param Options An optional sequence of designated initializer key/value + * pairs as described in the `criterion_test_extra_data` structure + * (see criterion/types.h). + * Example: .exit_code = 1 + */ # define Theory(Args, ...) CR_EXPAND(CR_THEORY_BASE(Args, __VA_ARGS__)) +/** + * TheoryDataPoints(Suite, Name) = { Datapoints... }; + * + * Defines an array of data points. + * + * The types of the specified data points *must* match the types of the + * associated theory. + * + * Each entry in the array must be the result of the DataPoints macro. + * + * @param Suite The name of the test suite containing this test. + * @param Name The name of the test. + */ # define TheoryDataPoints(Category, Name) CR_TH_INTERNAL_TDPS(Category, Name) -# define TheoryDataPoint(Category, Name) CR_TH_INTERNAL_TDP(Category, Name) + +/** + * DataPoints(Type, Values...) + * + * Defines a new set of data points. + * + * @param Type The type of each data point in the set. + * @param Values The data points in the set. + */ # define DataPoints(Type, ...) CR_EXPAND(CR_TH_INTERNAL_DP(Type, __VA_ARGS__)) // Theory invariants From 6c248da32159dd6b58dc3812b53e2a0c400c5185 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Tue, 8 Dec 2015 01:46:49 +0100 Subject: [PATCH 208/211] Removed Theory data point generation --- samples/tests/theories_regression.c | 17 ----------------- samples/tests/theories_regression.cc | 17 ----------------- samples/theories.c | 17 ----------------- samples/theories.cc | 17 ----------------- 4 files changed, 68 deletions(-) diff --git a/samples/tests/theories_regression.c b/samples/tests/theories_regression.c index 6661f9fd..bcb953e5 100644 --- a/samples/tests/theories_regression.c +++ b/samples/tests/theories_regression.c @@ -33,20 +33,3 @@ Theory((char c, bool b, short s, int i, float f, double d, char *str, const char // abort to see the formatted string of all parameters cr_assert_fail(); } - -// Manually generate datapoints - -TheoryDataPoints(theory, gen) = { - DataPoints(int, 0), // placeholder -}; - -static void generate_datapoints(void) { - static int arr[] = {1, 2, 3, 4, 5}; - TheoryDataPoint(theory, gen)[0].len = 5; - TheoryDataPoint(theory, gen)[0].arr = &arr; -} - -Theory((int i), theory, gen, .init = generate_datapoints) { - (void) i; - cr_assert_fail(); // we fail to display the parameter -} diff --git a/samples/tests/theories_regression.cc b/samples/tests/theories_regression.cc index 608954fe..75fdc0dc 100644 --- a/samples/tests/theories_regression.cc +++ b/samples/tests/theories_regression.cc @@ -35,20 +35,3 @@ Theory((char c, bool b, short s, int i, float f, double d, char *str, const char // abort to see the formatted string of all parameters cr_assert_fail(); } - -// Manually generate datapoints - -TheoryDataPoints(theory, gen) = { - DataPoints(int, 0), // placeholder -}; - -static void generate_datapoints(void) { - static int arr[] = {1, 2, 3, 4, 5}; - TheoryDataPoint(theory, gen)[0].len = 5; - TheoryDataPoint(theory, gen)[0].arr = &arr; -} - -Theory((int i), theory, gen, .init = generate_datapoints) { - (void) i; - cr_assert_fail(); // we fail to display the parameter -} diff --git a/samples/theories.c b/samples/theories.c index c918f4a7..055811f7 100644 --- a/samples/theories.c +++ b/samples/theories.c @@ -105,20 +105,3 @@ Theory((char c, bool b, short s, int i, long l, long long ll, float f, double d, // abort to see the formatted string of all parameters cr_assert_fail(); } - -// Manually generate datapoints - -TheoryDataPoints(theory, gen) = { - DataPoints(int, 0), // placeholder -}; - -static void generate_datapoints(void) { - static int arr[] = {1, 2, 3, 4, 5}; - TheoryDataPoint(theory, gen)[0].len = 5; - TheoryDataPoint(theory, gen)[0].arr = &arr; -} - -Theory((int i), theory, gen, .init = generate_datapoints) { - (void) i; - cr_assert_fail(); // we fail to display the parameter -} diff --git a/samples/theories.cc b/samples/theories.cc index 4ee981bf..b79cb006 100644 --- a/samples/theories.cc +++ b/samples/theories.cc @@ -113,20 +113,3 @@ Theory((char c, bool b, short s, int i, long l, long long ll, float f, double d, // abort to see the formatted string of all parameters cr_assert_fail(); } - -// Manually generate datapoints - -TheoryDataPoints(theory, gen) = { - DataPoints(int, 0), // placeholder -}; - -static void generate_datapoints(void) { - static int arr[] = {1, 2, 3, 4, 5}; - TheoryDataPoint(theory, gen)[0].len = 5; - TheoryDataPoint(theory, gen)[0].arr = &arr; -} - -Theory((int i), theory, gen, .init = generate_datapoints) { - (void) i; - cr_assert_fail(); // we fail to display the parameter -} From df7d47f184cb2ef822597b68d949b0d93440e8fe Mon Sep 17 00:00:00 2001 From: Snaipe Date: Tue, 8 Dec 2015 01:56:01 +0100 Subject: [PATCH 209/211] Fixed theories regression tests --- .../outputs/theories_regression.c.bin.err.expected | 13 +------------ .../outputs/theories_regression.cc.bin.err.expected | 13 +------------ 2 files changed, 2 insertions(+), 24 deletions(-) diff --git a/samples/tests/outputs/theories_regression.c.bin.err.expected b/samples/tests/outputs/theories_regression.c.bin.err.expected index fa88f2bb..1262f800 100644 --- a/samples/tests/outputs/theories_regression.c.bin.err.expected +++ b/samples/tests/outputs/theories_regression.c.bin.err.expected @@ -1,15 +1,4 @@ -[----] theories_regression.c:51: Assertion failed: The conditions for this assertion were not met. -[----] Theory theory::gen failed with the following parameters: (1) -[----] theories_regression.c:51: Assertion failed: The conditions for this assertion were not met. -[----] Theory theory::gen failed with the following parameters: (2) -[----] theories_regression.c:51: Assertion failed: The conditions for this assertion were not met. -[----] Theory theory::gen failed with the following parameters: (3) -[----] theories_regression.c:51: Assertion failed: The conditions for this assertion were not met. -[----] Theory theory::gen failed with the following parameters: (4) -[----] theories_regression.c:51: Assertion failed: The conditions for this assertion were not met. -[----] Theory theory::gen failed with the following parameters: (5) -[FAIL] theory::gen [----] theories_regression.c:34: Assertion failed: The conditions for this assertion were not met. [----] Theory theory::misc failed with the following parameters: ('a', true, 1, 1, 3.14f, 3.14, "test", "other test") [FAIL] theory::misc -[====] Synthesis: Tested: 2 | Passing: 0 | Failing: 2 | Crashing: 0  +[====] Synthesis: Tested: 1 | Passing: 0 | Failing: 1 | Crashing: 0  diff --git a/samples/tests/outputs/theories_regression.cc.bin.err.expected b/samples/tests/outputs/theories_regression.cc.bin.err.expected index 03039376..e149d586 100644 --- a/samples/tests/outputs/theories_regression.cc.bin.err.expected +++ b/samples/tests/outputs/theories_regression.cc.bin.err.expected @@ -1,15 +1,4 @@ -[----] theories_regression.cc:53: Assertion failed: The conditions for this assertion were not met. -[----] Theory theory::gen failed with the following parameters: (1) -[----] theories_regression.cc:53: Assertion failed: The conditions for this assertion were not met. -[----] Theory theory::gen failed with the following parameters: (2) -[----] theories_regression.cc:53: Assertion failed: The conditions for this assertion were not met. -[----] Theory theory::gen failed with the following parameters: (3) -[----] theories_regression.cc:53: Assertion failed: The conditions for this assertion were not met. -[----] Theory theory::gen failed with the following parameters: (4) -[----] theories_regression.cc:53: Assertion failed: The conditions for this assertion were not met. -[----] Theory theory::gen failed with the following parameters: (5) -[FAIL] theory::gen [----] theories_regression.cc:36: Assertion failed: The conditions for this assertion were not met. [----] Theory theory::misc failed with the following parameters: ('a', true, 1, 1, 3.14f, 3.14, "test", "other test") [FAIL] theory::misc -[====] Synthesis: Tested: 2 | Passing: 0 | Failing: 2 | Crashing: 0  +[====] Synthesis: Tested: 1 | Passing: 0 | Failing: 1 | Crashing: 0  From f9139404275e963e3fa18448c9c742ba8073b34f Mon Sep 17 00:00:00 2001 From: Snaipe Date: Tue, 8 Dec 2015 02:36:23 +0100 Subject: [PATCH 210/211] Fixed decoupling for parameterized tests and fixed missing definitions --- CMakeLists.txt | 1 + include/criterion/abort.h | 2 + include/criterion/internal/parameterized.h | 3 +- include/criterion/internal/test.h | 108 ++++++++++----------- src/core/abort.h | 2 - src/core/test.c | 1 + 6 files changed, 60 insertions(+), 57 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 67dfe4eb..830c5d28 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -147,6 +147,7 @@ set(SOURCE_FILES src/core/stats.c src/core/stats.h src/core/ordered-set.c + src/core/test.c src/compat/internal.h src/compat/pipe.c src/compat/pipe.h diff --git a/include/criterion/abort.h b/include/criterion/abort.h index d6a649e6..9cfc9254 100644 --- a/include/criterion/abort.h +++ b/include/criterion/abort.h @@ -31,6 +31,8 @@ CR_BEGIN_C_API CR_API CR_NORETURN void criterion_abort_test(void); CR_INLINE static void criterion_continue_test(void) {} +CR_API void criterion_test_die(const char *msg, ...); + CR_END_C_API #endif /* !CRITERION_ABORT_H_ */ diff --git a/include/criterion/internal/parameterized.h b/include/criterion/internal/parameterized.h index 4fbd5117..c08ee0d1 100644 --- a/include/criterion/internal/parameterized.h +++ b/include/criterion/internal/parameterized.h @@ -79,6 +79,7 @@ struct criterion_test_params { # define CR_PARAM_TEST_BASE(Param, Category, Name, ...) \ CR_PARAM_TEST_PROTOTYPE_(Param, Category, Name); \ + CR_TEST_TRAMPOLINE_(Category, Name) \ struct criterion_test_extra_data CR_IDENTIFIER_(Category, Name, extra) = \ CR_EXPAND(CRITERION_MAKE_STRUCT(criterion_test_extra_data, \ .lang_ = CR_LANG, \ @@ -92,7 +93,7 @@ struct criterion_test_params { struct criterion_test CR_IDENTIFIER_(Category, Name, meta) = { \ #Name, \ #Category, \ - (void(*)(void)) CR_IDENTIFIER_(Category, Name, impl), \ + CR_IDENTIFIER_(Category, Name, jmp), \ &CR_IDENTIFIER_(Category, Name, extra) \ }; \ CR_SECTION_("cr_tst") \ diff --git a/include/criterion/internal/test.h b/include/criterion/internal/test.h index 9a2f526f..35b49ae1 100644 --- a/include/criterion/internal/test.h +++ b/include/criterion/internal/test.h @@ -79,65 +79,65 @@ static const char *const cr_msg_test_fini_std_exception = "Caught an unexpected static const char *const cr_msg_test_fini_other_exception = "Caught some unexpected exception during the test finalization."; # ifdef __cplusplus -# define CR_TEST_TRAMPOLINE_(Category, Name) \ - static inline void CR_IDENTIFIER_(Category, Name, jmp)(void) { \ - try { \ - criterion_internal_test_setup(); \ - } catch (const std::exception &e) { \ - criterion_test_die(cr_msg_test_init_std_exception, e.what()); \ - } catch (...) { \ - criterion_test_die(cr_msg_test_init_other_exception); \ - } \ - try { \ - criterion_internal_test_main(CR_IDENTIFIER_(Category, Name, impl)); \ - } catch (const std::exception &e) { \ - criterion_test_die(cr_msg_test_main_std_exception, e.what()); \ - } catch (...) { \ - criterion_test_die(cr_msg_test_main_other_exception); \ - } \ - try { \ - criterion_internal_test_teardown(); \ - } catch (const std::exception &e) { \ - criterion_test_die(cr_msg_test_fini_std_exception, e.what()); \ - } catch (...) { \ - criterion_test_die(cr_msg_test_fini_other_exception); \ - } \ +# define CR_TEST_TRAMPOLINE_(Category, Name) \ + static inline void CR_IDENTIFIER_(Category, Name, jmp)(void) { \ + try { \ + criterion_internal_test_setup(); \ + } catch (const std::exception &e) { \ + criterion_test_die(cr_msg_test_init_std_exception, e.what()); \ + } catch (...) { \ + criterion_test_die(cr_msg_test_init_other_exception); \ + } \ + try { \ + criterion_internal_test_main((void(*)(void)) CR_IDENTIFIER_(Category, Name, impl)); \ + } catch (const std::exception &e) { \ + criterion_test_die(cr_msg_test_main_std_exception, e.what()); \ + } catch (...) { \ + criterion_test_die(cr_msg_test_main_other_exception); \ + } \ + try { \ + criterion_internal_test_teardown(); \ + } catch (const std::exception &e) { \ + criterion_test_die(cr_msg_test_fini_std_exception, e.what()); \ + } catch (...) { \ + criterion_test_die(cr_msg_test_fini_other_exception); \ + } \ } # else # if defined(__OBJC__) && defined(__EXCEPTIONS) -# define CR_TEST_TRAMPOLINE_(Category, Name) \ - static inline void CR_IDENTIFIER_(Category, Name, jmp)(void) { \ - @try { \ - criterion_internal_test_setup(); \ - } @catch (NSException *e) { \ - NSString *reason = [e reason]; \ - criterion_test_die(cr_msg_test_init_std_exception, [reason UTF8String]); \ - } @catch (...) { \ - criterion_test_die(cr_msg_test_init_other_exception); \ - } \ - @try { \ - criterion_internal_test_main(CR_IDENTIFIER_(Category, Name, impl)); \ - } @catch (NSException *e) { \ - NSString *reason = [e reason]; \ - criterion_test_die(cr_msg_test_main_std_exception, [reason UTF8String]); \ - } @catch (...) { \ - criterion_test_die(cr_msg_test_main_other_exception); \ - } \ - @try { \ - criterion_internal_test_teardown(); \ - } @catch (NSException *e) { \ - NSString *reason = [e reason]; \ - criterion_test_die(cr_msg_test_fini_std_exception, [reason UTF8String]); \ - } @catch (...) { \ - criterion_test_die(cr_msg_test_fini_other_exception); \ - } \ +# define CR_TEST_TRAMPOLINE_(Category, Name) \ + static inline void CR_IDENTIFIER_(Category, Name, jmp)(void) { \ + @try { \ + criterion_internal_test_setup(); \ + } @catch (NSException *e) { \ + NSString *reason = [e reason]; \ + criterion_test_die(cr_msg_test_init_std_exception, [reason UTF8String]); \ + } @catch (...) { \ + criterion_test_die(cr_msg_test_init_other_exception); \ + } \ + @try { \ + criterion_internal_test_main((void(*)(void)) CR_IDENTIFIER_(Category, Name, impl)); \ + } @catch (NSException *e) { \ + NSString *reason = [e reason]; \ + criterion_test_die(cr_msg_test_main_std_exception, [reason UTF8String]); \ + } @catch (...) { \ + criterion_test_die(cr_msg_test_main_other_exception); \ + } \ + @try { \ + criterion_internal_test_teardown(); \ + } @catch (NSException *e) { \ + NSString *reason = [e reason]; \ + criterion_test_die(cr_msg_test_fini_std_exception, [reason UTF8String]); \ + } @catch (...) { \ + criterion_test_die(cr_msg_test_fini_other_exception); \ + } \ } # else -# define CR_TEST_TRAMPOLINE_(Category, Name) \ - static inline void CR_IDENTIFIER_(Category, Name, jmp)(void) { \ - criterion_internal_test_setup(); \ - criterion_internal_test_main(CR_IDENTIFIER_(Category, Name, impl)); \ - criterion_internal_test_teardown(); \ +# define CR_TEST_TRAMPOLINE_(Category, Name) \ + static inline void CR_IDENTIFIER_(Category, Name, jmp)(void) { \ + criterion_internal_test_setup(); \ + criterion_internal_test_main((void(*)(void)) CR_IDENTIFIER_(Category, Name, impl)); \ + criterion_internal_test_teardown(); \ } # endif # endif diff --git a/src/core/abort.h b/src/core/abort.h index 401f09b7..064fe67d 100644 --- a/src/core/abort.h +++ b/src/core/abort.h @@ -29,6 +29,4 @@ extern jmp_buf g_pre_test; -void criterion_test_die(const char *msg, ...); - #endif /* !ABORT_H_ */ diff --git a/src/core/test.c b/src/core/test.c index 02a4578a..4295360d 100644 --- a/src/core/test.c +++ b/src/core/test.c @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ +#include "criterion/internal/test.h" #include "core/abort.h" #include "core/stats.h" #include "core/worker.h" From ac2f5e1bce6b465d15cf26dd130eadace303b388 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Tue, 8 Dec 2015 03:12:05 +0100 Subject: [PATCH 211/211] Removed Objective-C compiler modules --- .../CMakeDetermineObjectiveCCompiler.cmake | 19 -- .../Modules/CMakeObjectiveCCompiler.cmake.in | 10 - .../Modules/CMakeObjectiveCInformation.cmake | 192 ------------------ .../Modules/CMakeTestObjectiveCCompiler.cmake | 64 ------ .cmake/Modules/Languages.cmake | 17 -- CMakeLists.txt | 21 +- src/config.h.in | 7 - 7 files changed, 5 insertions(+), 325 deletions(-) delete mode 100644 .cmake/Modules/CMakeDetermineObjectiveCCompiler.cmake delete mode 100644 .cmake/Modules/CMakeObjectiveCCompiler.cmake.in delete mode 100644 .cmake/Modules/CMakeObjectiveCInformation.cmake delete mode 100644 .cmake/Modules/CMakeTestObjectiveCCompiler.cmake delete mode 100644 .cmake/Modules/Languages.cmake diff --git a/.cmake/Modules/CMakeDetermineObjectiveCCompiler.cmake b/.cmake/Modules/CMakeDetermineObjectiveCCompiler.cmake deleted file mode 100644 index 9a9680a5..00000000 --- a/.cmake/Modules/CMakeDetermineObjectiveCCompiler.cmake +++ /dev/null @@ -1,19 +0,0 @@ -# Copyright (C) 2015 Franklin "Snaipe" Mathieu. -# Redistribution and use of this file is allowed according to the terms of the MIT license. -# For details see the LICENSE file distributed with Criterion. - -# CMake <2.8.10 backward compat -if(NOT CMAKE_PLATFORM_INFO_DIR) - set(CMAKE_PLATFORM_INFO_DIR ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}) -endif(NOT CMAKE_PLATFORM_INFO_DIR) - -set(CMAKE_ObjectiveC_COMPILER_ID ${CMAKE_C_COMPILER_ID}) -set(CMAKE_ObjectiveC_COMPILER ${CMAKE_C_COMPILER}) - -# configure variables set in this file for fast reload later on -configure_file(${CMAKE_CURRENT_LIST_DIR}/CMakeObjectiveCCompiler.cmake.in - ${CMAKE_PLATFORM_INFO_DIR}/CMakeObjectiveCCompiler.cmake - @ONLY - ) - -set(CMAKE_ObjectiveC_COMPILER_ENV_VAR "OBJCC") diff --git a/.cmake/Modules/CMakeObjectiveCCompiler.cmake.in b/.cmake/Modules/CMakeObjectiveCCompiler.cmake.in deleted file mode 100644 index ab197365..00000000 --- a/.cmake/Modules/CMakeObjectiveCCompiler.cmake.in +++ /dev/null @@ -1,10 +0,0 @@ -set(CMAKE_ObjectiveC_COMPILER "@CMAKE_ObjectiveC_COMPILER@") -set(CMAKE_ObjectiveC_COMPILER_ID "@CMAKE_ObjectiveC_COMPILER_ID@") - -set(CMAKE_ObjectiveC_IMPLICIT_LINK_LIBRARIES "@CMAKE_ObjectiveC_IMPLICIT_LINK_LIBRARIES@") - -set(CMAKE_ObjectiveC_COMPILER_LOADED 1) -set(CMAKE_ObjectiveC_COMPILER_WORKS @CMAKE_ObjectiveC_COMPILER_WORKS@) - -set(CMAKE_ObjectiveC_COMPILER_ID_RUN 1) -set(CMAKE_ObjectiveC_SOURCE_FILE_EXTENSIONS m) diff --git a/.cmake/Modules/CMakeObjectiveCInformation.cmake b/.cmake/Modules/CMakeObjectiveCInformation.cmake deleted file mode 100644 index 1a49d7c4..00000000 --- a/.cmake/Modules/CMakeObjectiveCInformation.cmake +++ /dev/null @@ -1,192 +0,0 @@ -if(UNIX) - set(CMAKE_ObjectiveC_OUTPUT_EXTENSION .o) -else() - set(CMAKE_ObjectiveC_OUTPUT_EXTENSION .obj) -endif() - -set(_INCLUDED_FILE 0) -set(_INCLUDED_FILE_2 0) - -# Load compiler-specific information. -if(CMAKE_ObjectiveC_COMPILER_ID) - include(Compiler/${CMAKE_ObjectiveC_COMPILER_ID}-C OPTIONAL) -endif() - -set(CMAKE_BASE_NAME) -get_filename_component(CMAKE_BASE_NAME "${CMAKE_ObjectiveC_COMPILER}" NAME_WE) - -# load a hardware specific file, mostly useful for embedded compilers -if(CMAKE_SYSTEM_PROCESSOR) - if(CMAKE_ObjectiveC_COMPILER_ID) - include(Platform/${CMAKE_SYSTEM_NAME}-${CMAKE_ObjectiveC_COMPILER_ID}-C-${CMAKE_SYSTEM_PROCESSOR} OPTIONAL RESULT_VARIABLE _INCLUDED_FILE) - include(Platform/${CMAKE_SYSTEM_NAME}-${CMAKE_ObjectiveC_COMPILER_ID}-ObjectiveC-${CMAKE_SYSTEM_PROCESSOR} OPTIONAL RESULT_VARIABLE _INCLUDED_FILE_2) - endif() - if (NOT _INCLUDED_FILE AND NOT _INCLUDED_FILE_2) - include(Platform/${CMAKE_SYSTEM_NAME}-${CMAKE_BASE_NAME}-${CMAKE_SYSTEM_PROCESSOR} OPTIONAL) - endif () -endif() - -# load the system- and compiler specific files -if(CMAKE_ObjectiveC_COMPILER_ID) - include(Platform/${CMAKE_SYSTEM_NAME}-${CMAKE_ObjectiveC_COMPILER_ID}-C - OPTIONAL RESULT_VARIABLE _INCLUDED_FILE) - include(Platform/${CMAKE_SYSTEM_NAME}-${CMAKE_ObjectiveC_COMPILER_ID}-ObjectiveC - OPTIONAL RESULT_VARIABLE _INCLUDED_FILE_2) -endif() -if (NOT _INCLUDED_FILE AND _INCLUDED_FILE_2) - include(Platform/${CMAKE_SYSTEM_NAME}-${CMAKE_BASE_NAME} - OPTIONAL RESULT_VARIABLE _INCLUDED_FILE) -endif () - -# We specify the compiler information in the system file for some -# platforms, but this language may not have been enabled when the file -# was first included. Include it again to get the language info. -# Remove this when all compiler info is removed from system files. -if (NOT _INCLUDED_FILE) - include(Platform/${CMAKE_SYSTEM_NAME} OPTIONAL) -endif () - -if(CMAKE_ObjectiveC_COMPILER_LINKS_STATICALLY) - set_property(GLOBAL PROPERTY TARGET_SUPPORTS_SHARED_LIBS FALSE) -endif() - -# This should be included before the _INIT variables are -# used to initialize the cache. Since the rule variables -# have if blocks on them, users can still define them here. -# But, it should still be after the platform file so changes can -# be made to those values. - -if(CMAKE_USER_MAKE_RULES_OVERRIDE) - # Save the full path of the file so try_compile can use it. - include(${CMAKE_USER_MAKE_RULES_OVERRIDE} RESULT_VARIABLE _override) - set(CMAKE_USER_MAKE_RULES_OVERRIDE "${_override}") -endif() - -if(CMAKE_USER_MAKE_RULES_OVERRIDE_ObjectiveC) - # Save the full path of the file so try_compile can use it. - include(${CMAKE_USER_MAKE_RULES_OVERRIDE_ObjectiveC} RESULT_VARIABLE _override) - set(CMAKE_USER_MAKE_RULES_OVERRIDE_ObjectiveC "${_override}") -endif() - - -# for most systems a module is the same as a shared library -# so unless the variable CMAKE_MODULE_EXISTS is set just -# copy the values from the LIBRARY variables -if(NOT CMAKE_MODULE_EXISTS) - set(CMAKE_SHARED_MODULE_ObjectiveC_FLAGS ${CMAKE_SHARED_LIBRARY_ObjectiveC_FLAGS}) - set(CMAKE_SHARED_MODULE_CREATE_ObjectiveC_FLAGS ${CMAKE_SHARED_LIBRARY_CREATE_ObjectiveC_FLAGS}) -endif() - -if(NOT CMAKE_NOT_USING_CONFIG_FLAGS) -# default build type is none - if(NOT CMAKE_NO_BUILD_TYPE) - set (CMAKE_BUILD_TYPE ${CMAKE_BUILD_TYPE_INIT} CACHE STRING - "Choose the type of build, options are: None(CMAKE_CXX_FLAGS or CMAKE_C_FLAGS used) Debug Release RelWithDebInfo MinSizeRel.") - endif() - set (CMAKE_ObjectiveC_FLAGS_DEBUG "${CMAKE_ObjectiveC_FLAGS_DEBUG_INIT}" CACHE STRING - "Flags used by the compiler during debug builds.") - set (CMAKE_ObjectiveC_FLAGS_MINSIZEREL "${CMAKE_ObjectiveC_FLAGS_MINSIZEREL_INIT}" CACHE STRING - "Flags used by the compiler during release builds for minimum size.") - set (CMAKE_ObjectiveC_FLAGS_RELEASE "${CMAKE_ObjectiveC_FLAGS_RELEASE_INIT}" CACHE STRING - "Flags used by the compiler during release builds.") - set (CMAKE_ObjectiveC_FLAGS_RELWITHDEBINFO "${CMAKE_ObjectiveC_FLAGS_RELWITHDEBINFO_INIT}" CACHE STRING - "Flags used by the compiler during release builds with debug info.") -endif() - -if(CMAKE_ObjectiveC_STANDARD_LIBRARIES_INIT) - set(CMAKE_ObjectiveC_STANDARD_LIBRARIES "${CMAKE_C_STANDARD_LIBRARIES_INIT}" - CACHE STRING "Libraries linked by default with all C applications.") - mark_as_advanced(CMAKE_ObjectiveC_STANDARD_LIBRARIES) -endif() - -include(CMakeCommonLanguageInclude) - -# now define the following rule variables - -# CMAKE_ObjectiveC_CREATE_SHARED_LIBRARY -# CMAKE_ObjectiveC_CREATE_SHARED_MODULE -# CMAKE_ObjectiveC_COMPILE_OBJECT -# CMAKE_ObjectiveC_LINK_EXECUTABLE - -# variables supplied by the generator at use time -# -# the target without the suffix -# -# -# -# -# - -# C compiler information -# -# -# -# - -# Static library tools -# -# - - -# create a C shared library -if(NOT CMAKE_ObjectiveC_CREATE_SHARED_LIBRARY) - set(CMAKE_ObjectiveC_CREATE_SHARED_LIBRARY - " -o ") -endif() - -# create a C shared module just copy the shared library rule -if(NOT CMAKE_ObjectiveC_CREATE_SHARED_MODULE) - set(CMAKE_ObjectiveC_CREATE_SHARED_MODULE ${CMAKE_ObjectiveC_CREATE_SHARED_LIBRARY}) -endif() - -# Create a static archive incrementally for large object file counts. -# If CMAKE_ObjectiveC_CREATE_STATIObjectiveC_LIBRARY is set it will override these. -if(NOT DEFINED CMAKE_ObjectiveC_ARCHIVE_CREATE) - set(CMAKE_ObjectiveC_ARCHIVE_CREATE " qc ") -endif() -if(NOT DEFINED CMAKE_ObjectiveC_ARCHIVE_APPEND) - set(CMAKE_ObjectiveC_ARCHIVE_APPEND " q ") -endif() -if(NOT DEFINED CMAKE_ObjectiveC_ARCHIVE_FINISH) - set(CMAKE_ObjectiveC_ARCHIVE_FINISH " ") -endif() - -set(CMAKE_INCLUDE_FLAG_ObjectiveC "-I") -set(CMAKE_ObjectiveC_IMPLICIT_LINK_LIBRARIES objc) - -# compile a C file into an object file -if(NOT CMAKE_ObjectiveC_COMPILE_OBJECT) - if("${CMAKE_VERSION}" VERSION_GREATER 3.3.2) - set(CMAKE_ObjectiveC_COMPILE_OBJECT - " -o -c ") - else () - set(CMAKE_ObjectiveC_COMPILE_OBJECT - " -o -c ") - endif () -endif() - -if(NOT CMAKE_ObjectiveC_LINK_EXECUTABLE) - set(CMAKE_ObjectiveC_LINK_EXECUTABLE - " -o ") -endif() - -if(NOT CMAKE_EXECUTABLE_RUNTIME_ObjectiveC_FLAG) - set(CMAKE_EXECUTABLE_RUNTIME_ObjectiveC_FLAG ${CMAKE_SHARED_LIBRARY_RUNTIME_ObjectiveC_FLAG}) -endif() - -if(NOT CMAKE_EXECUTABLE_RUNTIME_ObjectiveC_FLAG_SEP) - set(CMAKE_EXECUTABLE_RUNTIME_ObjectiveC_FLAG_SEP ${CMAKE_SHARED_LIBRARY_RUNTIME_ObjectiveC_FLAG_SEP}) -endif() - -if(NOT CMAKE_EXECUTABLE_RPATH_LINK_ObjectiveC_FLAG) - set(CMAKE_EXECUTABLE_RPATH_LINK_ObjectiveC_FLAG ${CMAKE_SHARED_LIBRARY_RPATH_LINK_ObjectiveC_FLAG}) -endif() - -mark_as_advanced( - CMAKE_ObjectiveC_FLAGS - CMAKE_ObjectiveC_FLAGS_DEBUG - CMAKE_ObjectiveC_FLAGS_MINSIZEREL - CMAKE_ObjectiveC_FLAGS_RELEASE - CMAKE_ObjectiveC_FLAGS_RELWITHDEBINFO -) -set(CMAKE_ObjectiveC_INFORMATION_LOADED 1) diff --git a/.cmake/Modules/CMakeTestObjectiveCCompiler.cmake b/.cmake/Modules/CMakeTestObjectiveCCompiler.cmake deleted file mode 100644 index a32b33f1..00000000 --- a/.cmake/Modules/CMakeTestObjectiveCCompiler.cmake +++ /dev/null @@ -1,64 +0,0 @@ -if(CMAKE_ObjectiveC_COMPILER_FORCED) - # The compiler configuration was forced by the user. - # Assume the user has configured all compiler information. - set(CMAKE_ObjectiveC_COMPILER_WORKS TRUE) - return() -endif() - -include(CMakeTestCompilerCommon) - -# Remove any cached result from an older CMake version. -# We now store this in CMakeCCompiler.cmake. -unset(CMAKE_ObjectiveC_COMPILER_WORKS CACHE) - -# This file is used by EnableLanguage in cmGlobalGenerator to -# determine that that selected C compiler can actually compile -# and link the most basic of programs. If not, a fatal error -# is set and cmake stops processing commands and will not generate -# any makefiles or projects. -if(NOT CMAKE_ObjectiveC_COMPILER_WORKS) - PrintTestCompilerStatus("ObjectiveC" "") - file(WRITE ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/testObjectiveCCompiler.m - "#ifdef __cplusplus\n" - "# error \"The CMAKE_ObjectiveC_COMPILER is set to an ObjectiveC++ compiler\"\n" - "#endif\n" - "@interface Foo\n" - "@end\n" - "int main(int argc, char* argv[])\n" - "{ (void)argv; return argc-1;}\n") -try_compile(CMAKE_ObjectiveC_COMPILER_WORKS ${CMAKE_BINARY_DIR} - ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/testObjectiveCCompiler.m - OUTPUT_VARIABLE __CMAKE_ObjectiveC_COMPILER_OUTPUT) - # Move result from cache to normal variable. - set(CMAKE_ObjectiveC_COMPILER_WORKS ${CMAKE_ObjectiveC_COMPILER_WORKS}) - unset(CMAKE_ObjectiveC_COMPILER_WORKS CACHE) - set(ObjectiveC_TEST_WAS_RUN 1) -endif() - -if(NOT CMAKE_ObjectiveC_COMPILER_WORKS) - PrintTestCompilerStatus("ObjectiveC" " -- broken") - file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log - "Determining if the ObjectiveC compiler works failed with " - "the following output:\n${__CMAKE_ObjectiveC_COMPILER_OUTPUT}\n\n") -message(FATAL_ERROR "The ObjectiveC compiler \"${CMAKE_ObjectiveC_COMPILER}\" " - "is not able to compile a simple test program.\nIt fails " - "with the following output:\n ${__CMAKE_ObjectiveC_COMPILER_OUTPUT}\n\n" - "CMake will not be able to correctly generate this project.") -else() - if(ObjectiveC_TEST_WAS_RUN) - PrintTestCompilerStatus("ObjectiveC" " -- works") - file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log - "Determining if the ObjectiveC compiler works passed with " - "the following output:\n${__CMAKE_ObjectiveC_COMPILER_OUTPUT}\n\n") - endif() - - # Re-configure file - configure_file( - ${CMAKE_CURRENT_LIST_DIR}/CMakeObjectiveCCompiler.cmake.in - ${CMAKE_PLATFORM_INFO_DIR}/CMakeObjectiveCCompiler.cmake - @ONLY - ) - include(${CMAKE_PLATFORM_INFO_DIR}/CMakeObjectiveCCompiler.cmake) -endif() - -unset(__CMAKE_ObjectiveC_COMPILER_OUTPUT) diff --git a/.cmake/Modules/Languages.cmake b/.cmake/Modules/Languages.cmake deleted file mode 100644 index 615d0670..00000000 --- a/.cmake/Modules/Languages.cmake +++ /dev/null @@ -1,17 +0,0 @@ - -option(LANG_CXX "Turn on C++ support" ON) -option(LANG_OBJC "Turn on Objective-C support" OFF) - -if (LANG_CXX) - enable_language(CXX) - if (CMAKE_CXX_COMPILER_WORKS) - set(CXX_BRIDGE 1) - endif () -endif () - -if (LANG_OBJC) - enable_language(ObjectiveC) - if (CMAKE_ObjectiveC_COMPILER_WORKS) - set(OBJC_BRIDGE 1) - endif () -endif () diff --git a/CMakeLists.txt b/CMakeLists.txt index 830c5d28..ae77f5ed 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -43,12 +43,13 @@ if (MSVC) include_directories(dependencies/wingetopt/src/) endif () -# Language support - -include(Languages) - # Check for C++11 +option(LANG_CXX "Turn on C++ support" ON) +if (LANG_CXX) + enable_language(CXX) +endif () + if (NOT MSVC AND CMAKE_CXX_COMPILER_WORKS) include(CheckCXXCompilerFlag) CHECK_CXX_COMPILER_FLAG("-std=c++11" COMPILER_SUPPORTS_CXX11) @@ -201,18 +202,6 @@ if (PCRE_FOUND) set(HAVE_PCRE 1) endif () -if (CMAKE_ObjectiveC_COMPILER_WORKS) - set(CMAKE_ObjectiveC_FLAGS "${CMAKE_ObjectiveC_FLAGS} ${CMAKE_C_FLAGS} -fobjc-exceptions") - if ("${CMAKE_ObjectiveC_COMPILER_ID}" STREQUAL "Clang" AND APPLE) - set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -framework Foundation") - endif () - add_definitions(-D_NATIVE_OBJC_EXCEPTIONS) - - if (NOT WIN32) - set(CMAKE_ObjectiveC_FLAGS "${CMAKE_ObjectiveC_FLAGS} -fPIC") - endif () -endif () - set(INTERFACE_FILES include/criterion/assert.h include/criterion/abort.h diff --git a/src/config.h.in b/src/config.h.in index fb151cbd..0040dad9 100644 --- a/src/config.h.in +++ b/src/config.h.in @@ -7,13 +7,6 @@ #cmakedefine MINGW_DEFINE_OFF_T @MINGW_DEFINE_OFF_T@ #cmakedefine01 HAVE_STRTOK_S -#cmakedefine CXX_BRIDGE @CXX_BRIDGE@ -#cmakedefine OBJECTIVEC_BRIDGE @OBJECTIVEC_BRIDGE@ - -# ifdef OBJECTIVEC_BRIDGE -# define OBJC_BRIDGE OBJECTIVEC_BRIDGE -# endif - # define LOCALEDIR "${LOCALEDIR}" # define PACKAGE "${PROJECT_NAME}" # define VERSION "${PROJECT_VERSION}"