From f7ad1dd01eb9845a5949b6c872e483789d0557ce Mon Sep 17 00:00:00 2001 From: Snaipe Date: Thu, 20 Aug 2015 21:05:56 +0200 Subject: [PATCH 001/174] Revert readme change for x86_64 windows downloads --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index b68c6c16..8be1dc67 100644 --- a/README.md +++ b/README.md @@ -37,7 +37,7 @@ the user would have with other frameworks: * [Linux (x86_64)](https://github.com/Snaipe/Criterion/releases/download/v1.3.1/criterion-1.3.1-linux-x86_64.tar.bz2) * [OS X (x86_64)](https://github.com/Snaipe/Criterion/releases/download/v1.3.1/criterion-1.3.1-osx-x86_64.tar.bz2) -* [Windows (x86)](https://github.com/Snaipe/Criterion/releases/download/v1.3.1/criterion-1.3.1-windows-x86.tar.bz2) +* [Windows (x86_64)](https://github.com/Snaipe/Criterion/releases/download/v1.3.1/criterion-1.3.1-windows-x86_64.tar.bz2) If you have a different platform, you can still [build the library from source](http://criterion.readthedocs.org/en/latest/setup.html#installation) From f354f97cf6fbb6e32fa48a1017478b31475a33ba Mon Sep 17 00:00:00 2001 From: Snaipe Date: Thu, 20 Aug 2015 21:12:58 +0200 Subject: [PATCH 002/174] Fixed download urls --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 8be1dc67..d46b2b1f 100644 --- a/README.md +++ b/README.md @@ -35,9 +35,9 @@ the user would have with other frameworks: ## Downloads -* [Linux (x86_64)](https://github.com/Snaipe/Criterion/releases/download/v1.3.1/criterion-1.3.1-linux-x86_64.tar.bz2) -* [OS X (x86_64)](https://github.com/Snaipe/Criterion/releases/download/v1.3.1/criterion-1.3.1-osx-x86_64.tar.bz2) -* [Windows (x86_64)](https://github.com/Snaipe/Criterion/releases/download/v1.3.1/criterion-1.3.1-windows-x86_64.tar.bz2) +* [Linux (x86_64)](https://github.com/Snaipe/Criterion/releases/download/v1.3.1/criterion-v1.3.1-linux-x86_64.tar.bz2) +* [OS X (x86_64)](https://github.com/Snaipe/Criterion/releases/download/v1.3.1/criterion-v1.3.1-osx-x86_64.tar.bz2) +* [Windows (x86_64)](https://github.com/Snaipe/Criterion/releases/download/v1.3.1/criterion-v1.3.1-windows-x86_64.tar.bz2) If you have a different platform, you can still [build the library from source](http://criterion.readthedocs.org/en/latest/setup.html#installation) From d6888c4ac6c0fca62a7d4829630a90c9088ba700 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Fri, 21 Aug 2015 00:21:48 +0200 Subject: [PATCH 003/174] Fixed comparison tests for scripts --- samples/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/CMakeLists.txt b/samples/CMakeLists.txt index 4f928b2e..f614717e 100644 --- a/samples/CMakeLists.txt +++ b/samples/CMakeLists.txt @@ -49,7 +49,7 @@ foreach(script ${SCRIPTS}) ENVIRONMENT "CRITERION_ALWAYS_SUCCEED=1" ) - add_test(${script}_compare sh ${CMAKE_CURRENT_LIST_DIR}/tests/run_test.sh "${CMAKE_CURRENT_LIST_DIR}" . "${CMAKE_CURRENT_LIST_DIR}" tests/${sample}) + add_test(${script}_compare sh ${CMAKE_CURRENT_LIST_DIR}/tests/run_test.sh "${CMAKE_CURRENT_LIST_DIR}" . "${CMAKE_CURRENT_LIST_DIR}" tests/${script}) set_property(TEST ${script}_compare PROPERTY ENVIRONMENT "LC_ALL=en_US.utf8" ENVIRONMENT "CRITERION_ALWAYS_SUCCEED=1" From 883088e2a515d032325b7b3cba45dd8459c2f1c1 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Fri, 21 Aug 2015 00:26:51 +0200 Subject: [PATCH 004/174] Added conditional pattern test activation --- CMakeLists.txt | 7 ++++--- samples/CMakeLists.txt | 7 ++++--- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 5b8ad202..04fcbfbf 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,9 +4,6 @@ project(Criterion C) # Project setup & environment variables -enable_testing() -add_subdirectory(samples) - set(PROJECT_VERSION "1.3.1") set(LOCALEDIR ${CMAKE_INSTALL_PREFIX}/share/locale) set(GettextTranslate_ALL 1) @@ -133,3 +130,7 @@ install(TARGETS criterion add_custom_target(uninstall "${CMAKE_COMMAND}" -P "${CMAKE_MODULE_PATH}/uninstall.cmake" ) + +enable_testing() +add_subdirectory(samples) + diff --git a/samples/CMakeLists.txt b/samples/CMakeLists.txt index f614717e..17edd703 100644 --- a/samples/CMakeLists.txt +++ b/samples/CMakeLists.txt @@ -1,5 +1,3 @@ -project(criterion_samples) - set(CMAKE_C_FLAGS "-std=c99 -Wall -Wextra -pedantic") include_directories(../include) @@ -22,11 +20,14 @@ set(SCRIPTS early_exit verbose list - pattern fail_fast help ) +if (HAVE_PCRE) + set(SCRIPTS ${SCRIPTS} pattern) +endif () + foreach(sample ${SAMPLES}) add_executable(${sample} ${sample}.c) target_link_libraries(${sample} criterion) From 2e94e558c1006bf9eb3721f37ba98e9e52aa5afb Mon Sep 17 00:00:00 2001 From: Snaipe Date: Fri, 21 Aug 2015 06:30:20 +0200 Subject: [PATCH 005/174] Added tests on ordered-set --- CMakeLists.txt | 1 + test/CMakeLists.txt | 12 ++++++++++++ test/ordered-set.c | 44 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 57 insertions(+) create mode 100644 test/CMakeLists.txt create mode 100644 test/ordered-set.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 04fcbfbf..8dfa0564 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -133,4 +133,5 @@ add_custom_target(uninstall enable_testing() add_subdirectory(samples) +add_subdirectory(test) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt new file mode 100644 index 00000000..e3d47045 --- /dev/null +++ b/test/CMakeLists.txt @@ -0,0 +1,12 @@ +set(CMAKE_C_FLAGS "-std=gnu99 -Wall -Wextra") + +include_directories(../include ../src) + +set(TEST_SOURCES + ordered-set.c +) + +add_executable(test_criterion ${TEST_SOURCES}) +target_link_libraries(test_criterion criterion) + +add_test(test_criterion test_criterion) diff --git a/test/ordered-set.c b/test/ordered-set.c new file mode 100644 index 00000000..c25e638f --- /dev/null +++ b/test/ordered-set.c @@ -0,0 +1,44 @@ +#include + +#include "criterion/criterion.h" +#include "criterion/ordered-set.h" + +int compare_gt(void *a, void *b) { + int *ia = a, *ib = b; + return *ia == *ib ? 0 : (*ia > *ib ? -1 : 1); +} + +int compare_lt(void *a, void *b) { + int *ia = a, *ib = b; + return *ia == *ib ? 0 : (*ia < *ib ? -1 : 1); +} + +Test(ordered_set, contract_lt) { + smart struct criterion_ordered_set *set = new_ordered_set(compare_lt, NULL); + + insert_ordered_set(set, &(int[1]) { 1 }, sizeof (int)); + insert_ordered_set(set, &(int[1]) { 8 }, sizeof (int)); + insert_ordered_set(set, &(int[1]) { 3 }, sizeof (int)); + + int *prev = NULL; + FOREACH_SET(int *e, set) { + if (prev) + cr_assert_lt(*prev, *e); + prev = e; + } +} + +Test(ordered_set, contract_gt) { + smart struct criterion_ordered_set *set = new_ordered_set(compare_gt, NULL); + + insert_ordered_set(set, &(int[1]) { 1 }, sizeof (int)); + insert_ordered_set(set, &(int[1]) { 8 }, sizeof (int)); + insert_ordered_set(set, &(int[1]) { 3 }, sizeof (int)); + + int *prev = NULL; + FOREACH_SET(int *e, set) { + if (prev) + cr_assert_gt(*prev, *e); + prev = e; + } +} From b940ad3790a2b1de1c9c12203e043faea025e065 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Tue, 1 Sep 2015 19:09:11 +0200 Subject: [PATCH 006/174] [Issue #32] Added ability to test the exit status of a test. --- include/criterion/logging.h | 23 ++++++++++++----------- include/criterion/stats.h | 1 + include/criterion/types.h | 1 + po/fr.po | 12 ++++++++++-- samples/CMakeLists.txt | 1 + samples/exit.c | 24 ++++++++++++++++++++++++ samples/exit.err.expected | 4 ++++ samples/exit.out.expected | 0 src/log/normal.c | 9 +++++++++ src/runner.c | 26 ++++++++++++++++++++++++++ src/stats.c | 4 +++- 11 files changed, 91 insertions(+), 14 deletions(-) create mode 100644 samples/exit.c create mode 100644 samples/exit.err.expected create mode 100644 samples/exit.out.expected diff --git a/include/criterion/logging.h b/include/criterion/logging.h index 616dac9e..07309daa 100644 --- a/include/criterion/logging.h +++ b/include/criterion/logging.h @@ -91,17 +91,18 @@ void criterion_log(enum criterion_logging_level level, const char *msg, ...); # define criterion_pimportant(...) criterion_plog(CRITERION_IMPORTANT, __VA_ARGS__) struct criterion_output_provider { - 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); - void (*log_pre_test )(struct criterion_test *test); - void (*log_assert )(struct criterion_assert_stats *stats); - void (*log_test_crash )(struct criterion_test_stats *stats); - void (*log_other_crash)(struct criterion_test_stats *stats); - void (*log_post_test )(struct criterion_test_stats *stats); - void (*log_post_fini )(struct criterion_test_stats *stats); - void (*log_post_suite )(struct criterion_suite_stats *stats); - void (*log_post_all )(struct criterion_global_stats *stats); + 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); + void (*log_pre_test )(struct criterion_test *test); + void (*log_assert )(struct criterion_assert_stats *stats); + void (*log_test_crash )(struct criterion_test_stats *stats); + 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); + void (*log_post_fini )(struct criterion_test_stats *stats); + void (*log_post_suite )(struct criterion_suite_stats *stats); + void (*log_post_all )(struct criterion_global_stats *stats); }; extern struct criterion_output_provider normal_logging; diff --git a/include/criterion/stats.h b/include/criterion/stats.h index 8a1b4e7f..c28d6e99 100644 --- a/include/criterion/stats.h +++ b/include/criterion/stats.h @@ -44,6 +44,7 @@ struct criterion_test_stats { int passed_asserts; int failed_asserts; int signal; + int exit_code; float elapsed_time; unsigned progress; const char *file; diff --git a/include/criterion/types.h b/include/criterion/types.h index f5081746..9acd208e 100644 --- a/include/criterion/types.h +++ b/include/criterion/types.h @@ -36,6 +36,7 @@ struct criterion_test_extra_data { void (*init)(void); void (*fini)(void); int signal; + int exit_code; bool disabled; const char *description; void *data; diff --git a/po/fr.po b/po/fr.po index af25ab87..7c08ad57 100644 --- a/po/fr.po +++ b/po/fr.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: criterion 1.0.0\n" "Report-Msgid-Bugs-To: franklinmathieu+criterion@gmail.com\n" -"POT-Creation-Date: 2015-08-05 11:37+0200\n" +"POT-Creation-Date: 2015-09-01 19:06+0200\n" "PO-Revision-Date: 2015-04-03 17:58+0200\n" "Last-Translator: \n" "Language-Team: French\n" @@ -75,13 +75,21 @@ msgstr "" "sa finalisation.%4$s\n" #: src/log/normal.c:64 +#, fuzzy, c-format +msgid "" +"%1$sWarning! The test `%2$s::%3$s` exited during its setup or teardown.%4$s\n" +msgstr "" +"%1$sAttention! Le test `%2$s::%3$s` a quitté pendant son initialisation ou " +"sa finalisation.%4$s\n" + +#: src/log/normal.c:65 #, 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:66 +#: src/log/normal.c:67 #, c-format msgid "" "%1$sSynthesis: Tested: %2$s%3$lu%4$s | Passing: %5$s%6$lu%7$s | Failing: %8$s" diff --git a/samples/CMakeLists.txt b/samples/CMakeLists.txt index 17edd703..718fda1f 100644 --- a/samples/CMakeLists.txt +++ b/samples/CMakeLists.txt @@ -4,6 +4,7 @@ include_directories(../include) set(SAMPLES signal + exit report suites fixtures diff --git a/samples/exit.c b/samples/exit.c new file mode 100644 index 00000000..f9c95dd6 --- /dev/null +++ b/samples/exit.c @@ -0,0 +1,24 @@ +#include +#include +#include + +Test(exit, normal, .exit_code = 0) { +} + +Test(exit, expected_exit, .exit_code = 42) { + exit(42); +} + +Test(exit, unexpected_exit) { + exit(127); +} + +void do_exit (void) { + exit(127); +} + +Test(exit_with_fixtures, init_exits, .init = do_exit) { +} + +Test(exit_with_fixtures, fini_exits, .fini = do_exit) { +} diff --git a/samples/exit.err.expected b/samples/exit.err.expected new file mode 100644 index 00000000..3ffe51b6 --- /dev/null +++ b/samples/exit.err.expected @@ -0,0 +1,4 @@ +[----] Warning! The test `exit::unexpected_exit` exited during its setup or teardown. +[----] Warning! The test `exit_with_fixtures::fini_exits` exited during its setup or teardown. +[----] Warning! The test `exit_with_fixtures::init_exits` exited during its setup or teardown. +[====] Synthesis: Tested: 5 | Passing: 3 | Failing: 2 | Crashing: 2  diff --git a/samples/exit.out.expected b/samples/exit.out.expected new file mode 100644 index 00000000..e69de29b diff --git a/src/log/normal.c b/src/log/normal.c index 565e763b..edc59621 100644 --- a/src/log/normal.c +++ b/src/log/normal.c @@ -61,6 +61,7 @@ static msg_t msg_assert_fail = N_("%1$s%2$s%3$s:%4$s%5$d%6$s: Assertion failed: 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_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", "Running %1$s%2$lu%3$s tests from %4$s%5$s%6$s:\n"); static msg_t msg_post_all = N_("%1$sSynthesis: Tested: %2$s%3$lu%4$s " @@ -78,6 +79,7 @@ static msg_t msg_assert_fail = "%s%s%s:%s%d%s: Assertion failed: %s\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_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", "Running %s%lu%s tests from %s%s%s:\n" }; static msg_t msg_post_all = "%sSynthesis: Tested: %s%lu%s " @@ -198,6 +200,12 @@ void normal_log_other_crash(UNUSED struct criterion_test_stats *stats) { FG_BOLD, stats->test->category, stats->test->name, RESET); } +void normal_log_abnormal_exit(UNUSED struct criterion_test_stats *stats) { + criterion_pimportant(CRITERION_PREFIX_DASHES, + _(msg_test_abnormal_exit), + FG_BOLD, stats->test->category, stats->test->name, 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), @@ -212,6 +220,7 @@ struct criterion_output_provider normal_logging = { .log_assert = normal_log_assert, .log_test_crash = normal_log_test_crash, .log_other_crash = normal_log_other_crash, + .log_abnormal_exit = normal_log_abnormal_exit, .log_post_test = normal_log_post_test, .log_post_suite = normal_log_post_suite, .log_post_all = normal_log_post_all, diff --git a/src/runner.c b/src/runner.c index c28da672..b5859dbd 100644 --- a/src/runner.c +++ b/src/runner.c @@ -207,6 +207,7 @@ static void run_test(struct criterion_global_stats *stats, bool test_started = false; bool normal_finish = false; + bool cleaned_up = false; struct event *ev; while ((ev = worker_read_event(proc)) != NULL) { stat_push_event(stats, suite_stats, test_stats, ev); @@ -232,6 +233,7 @@ static void run_test(struct criterion_global_stats *stats, case POST_FINI: report(POST_FINI, test_stats); log(post_fini, test_stats); + cleaned_up = true; break; } sfree(ev); @@ -260,6 +262,30 @@ static void run_test(struct criterion_global_stats *stats, push_event(POST_FINI); log(post_fini, test_stats); } + } else { + if ((normal_finish && !cleaned_up) || !test_started) { + log(abnormal_exit, test_stats); + if (!test_started) { + stat_push_event(stats, + suite_stats, + test_stats, + &(struct event) { .kind = TEST_CRASH }); + } + return; + } + test_stats->exit_code = status.status; + if (!normal_finish) { + if (test->data->exit_code == 0) { + push_event(TEST_CRASH); + log(abnormal_exit, test_stats); + } else { + double elapsed_time = 0; + push_event(POST_TEST, .data = &elapsed_time); + log(post_test, test_stats); + push_event(POST_FINI); + log(post_fini, test_stats); + } + } } } diff --git a/src/stats.c b/src/stats.c index e7d60a69..2b40de96 100644 --- a/src/stats.c +++ b/src/stats.c @@ -162,7 +162,9 @@ static void push_post_test(s_glob_stats *stats, s_test_stats *test, double *ptr) { test->elapsed_time = *ptr; - if (test->failed_asserts > 0 || test->signal != test->test->data->signal) { + if (test->failed_asserts > 0 + || test->signal != test->test->data->signal + || test->exit_code != test->test->data->exit_code) { test->failed = 1; ++stats->tests_failed; ++suite->tests_failed; From c9501805b648e3a03246c20464b0ec40c27897ba Mon Sep 17 00:00:00 2001 From: Snaipe Date: Thu, 3 Sep 2015 06:38:44 +0200 Subject: [PATCH 007/174] Added support for theories --- CMakeLists.txt | 4 + include/criterion/theories.h | 79 ++++++++++++++++++++ samples/CMakeLists.txt | 1 + samples/theories.c | 19 +++++ src/theories.c | 137 +++++++++++++++++++++++++++++++++++ 5 files changed, 240 insertions(+) create mode 100644 include/criterion/theories.h create mode 100644 samples/theories.c create mode 100644 src/theories.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 8dfa0564..ba5c8943 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -68,6 +68,7 @@ set(SOURCE_FILES src/i18n.h src/ordered-set.c src/posix-compat.c + src/theories.c src/main.c ) @@ -91,6 +92,7 @@ set(INTERFACE_FILES include/criterion/options.h include/criterion/ordered-set.h include/criterion/stats.h + include/criterion/theories.h ) # Generate the configure file @@ -120,6 +122,8 @@ if (COVERALLS) coveralls_setup("${SOURCE_FILES}" ${COVERALLS_UPLOAD}) endif() +target_link_libraries(criterion dyncall_s) + install(FILES ${INTERFACE_FILES} DESTINATION include/criterion) install(TARGETS criterion RUNTIME DESTINATION bin diff --git a/include/criterion/theories.h b/include/criterion/theories.h new file mode 100644 index 00000000..4da3527c --- /dev/null +++ b/include/criterion/theories.h @@ -0,0 +1,79 @@ +/* + * 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_THEORIES_H_ +# define CRITERION_THEORIES_H_ + +# include +# include "criterion.h" + +struct criterion_theory_context; + +struct criterion_theory_context* cr_theory_init(void); +void cr_theory_push_arg(struct criterion_theory_context *ctx, bool is_float, size_t size, void *ptr); +void cr_theory_free(struct criterion_theory_context *ctx); +void cr_theory_abort(void); +int cr_theory_mark(void); + +void cr_theory_reset(struct criterion_theory_context *ctx); +void cr_theory_call(struct criterion_theory_context *ctx, void (*fnptr)(void)); + +# define TheoryDataPoints(Category, Name) \ + static struct criterion_datapoints IDENTIFIER_(Category, Name, dps)[] + +# define DataPoints(Type, ...) \ + { sizeof (Type), sizeof ((Type[]) { __VA_ARGS__ }) / sizeof (Type), #Type, &(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)) + +# define cr_assume(Condition) \ + do { \ + if (!(Condition)) \ + cr_theory_abort(); \ + } while (0); + +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) + +# define Theory(Args, ...) \ + void CR_VAARG_ID(theory, __VA_ARGS__,)Args; \ + Test_(__VA_ARGS__, .sentinel_ = 0) { \ + cr_theory_main( \ + CR_VAARG_ID(dps, __VA_ARGS__,), \ + CR_NB_DATAPOINTS(CR_VAARG_ID(dps, __VA_ARGS__,)), \ + (void(*)(void)) CR_VAARG_ID(theory, __VA_ARGS__,) \ + ); \ + } \ + void CR_VAARG_ID(theory, __VA_ARGS__,)Args + +#endif /* !CRITERION_THEORIES_H_ */ diff --git a/samples/CMakeLists.txt b/samples/CMakeLists.txt index 17edd703..b33b9b2d 100644 --- a/samples/CMakeLists.txt +++ b/samples/CMakeLists.txt @@ -13,6 +13,7 @@ set(SAMPLES description other-crashes simple + theories ) set(SCRIPTS diff --git a/samples/theories.c b/samples/theories.c new file mode 100644 index 00000000..eb36d666 --- /dev/null +++ b/samples/theories.c @@ -0,0 +1,19 @@ +#include + +TheoryDataPoints(theory, simple) = { + DataPoints(int, 1, 2, 3), + DataPoints(long, 314, 42) +}; + +Theory((int a, long b), theory, simple) { + cr_assume(a == 2); + printf("%d, %ld\n", a, b); +} + +TheoryDataPoints(theory, float) = { + DataPoints(float, 3.14, 42), +}; + +Theory((float a), theory, float) { + printf("%f\n", (double) a); +} diff --git a/src/theories.c b/src/theories.c new file mode 100644 index 00000000..e8465435 --- /dev/null +++ b/src/theories.c @@ -0,0 +1,137 @@ +/* + * 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 +#include +#include "criterion/theories.h" + +struct criterion_theory_context { + DCCallVM* vm; +}; + +void cr_theory_push_arg(struct criterion_theory_context *ctx, bool is_float, size_t size, void *ptr) { + if (is_float) { + if (size == sizeof (float)) { + dcArgFloat(ctx->vm, *(float*)ptr); + } else if (size == sizeof (double)) { + dcArgDouble(ctx->vm, *(double*)ptr); + } else if (size == sizeof (long double)) { + dcArgDouble(ctx->vm, *(long double*)ptr); + } + } else { + if (size == sizeof (char)) { + dcArgChar(ctx->vm, *(char*)ptr); + } else if (size == sizeof (short)) { + dcArgShort(ctx->vm, *(short*)ptr); + } else if (size == sizeof (int)) { + dcArgInt(ctx->vm, *(int*)ptr); + } else if (size == sizeof (bool)) { + dcArgBool(ctx->vm, *(bool*)ptr); + } else if (size == sizeof (long)) { + dcArgLong(ctx->vm, *(long*)ptr); + } else if (size == sizeof (long long)) { + dcArgLongLong(ctx->vm, *(long long*)ptr); + } else if (size == sizeof (void*)) { + dcArgPointer(ctx->vm, *(void**)ptr); + } else { + dcArgPointer(ctx->vm, ptr); + } + } +} + +struct criterion_theory_context* cr_theory_init(void) { + struct criterion_theory_context* ctx = malloc(sizeof (struct criterion_theory_context)); + ctx->vm = dcNewCallVM(4096); + dcMode(ctx->vm, DC_CALL_C_DEFAULT); + return ctx; +} + +void cr_theory_free(struct criterion_theory_context *ctx) { + dcFree(ctx->vm); +} + +static jmp_buf theory_jmp; + +void cr_theory_abort(void) { + longjmp(theory_jmp, 1); +} + +int cr_theory_mark(void) { + return setjmp(theory_jmp); +} + +void cr_theory_reset(struct criterion_theory_context *ctx) { + dcReset(ctx->vm); +} + +void cr_theory_call(struct criterion_theory_context *ctx, void (*fnptr)(void)) { + dcCallVoid(ctx->vm, (DCpointer) fnptr); +} + +static bool contains_word(const char *str, const char *pattern, size_t sz) { + char *res = strstr(str, pattern); + + return res + && (res == str || (res > str && res[-1] == ' ')) + && (!res[sz - 1] || res[sz - 1] == ' '); +} + +void cr_theory_main(struct criterion_datapoints *dps, size_t datapoints, void (*fnptr)(void)) { + struct criterion_theory_context *ctx = cr_theory_init(); + + size_t indices[datapoints]; + memset(indices, 0, datapoints * sizeof (size_t)); + + bool has_next = true; + while (has_next) { + if (!cr_theory_mark()) { + cr_theory_reset(ctx); + for (size_t i = 0; i < datapoints; ++i) { + + bool is_float = contains_word(dps[i].name, "float", sizeof ("float")) + || contains_word(dps[i].name, "double", sizeof ("double")); + + cr_theory_push_arg(ctx, + is_float, + dps[i].size, + ((char*) dps[i].arr) + dps[i].size * indices[i]); + } + cr_theory_call(ctx, fnptr); + } + + for (size_t i = 0; i < datapoints; ++i) { + if (indices[i] == dps[i].len - 1) { + indices[i] = 0; + has_next = i != (datapoints - 1); + } else { + ++indices[i]; + break; + } + } + } + + cr_theory_free(ctx); +} From 029b5e43c3a82217e30a6104c854da226ea759f1 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Thu, 3 Sep 2015 14:29:46 +0200 Subject: [PATCH 008/174] Added better theory sample --- samples/theories.c | 64 ++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 54 insertions(+), 10 deletions(-) diff --git a/samples/theories.c b/samples/theories.c index eb36d666..bd814de4 100644 --- a/samples/theories.c +++ b/samples/theories.c @@ -1,19 +1,63 @@ #include +#include -TheoryDataPoints(theory, simple) = { - DataPoints(int, 1, 2, 3), - DataPoints(long, 314, 42) +# define INT_DATAPOINTS DataPoints(int, 0, 1, 2, -1, -2, INT_MAX, INT_MIN) + +// Let's test the multiplicative properties of 32-bit integers: + +int bad_mul(int a, int b) { + return a * b; +} + +int bad_div(int a, int b) { + return a / b; +} + +TheoryDataPoints(algebra, bad_divide_is_inverse_of_multiply) = { + INT_DATAPOINTS, + INT_DATAPOINTS, }; -Theory((int a, long b), theory, simple) { - cr_assume(a == 2); - printf("%d, %ld\n", a, b); +Theory((int a, int b), algebra, bad_divide_is_inverse_of_multiply) { + cr_assume(b != 0); + cr_assert_eq(a, bad_div(bad_mul(a, b), b)); } -TheoryDataPoints(theory, float) = { - DataPoints(float, 3.14, 42), +// The above implementation of mul & div fails the test because of overflows, +// let's try again: + +long long good_mul(long long a, long long b) { + return a * b; +} + +long long good_div(long long a, long long b) { + return a / b; +} + +TheoryDataPoints(algebra, good_divide_is_inverse_of_multiply) = { + INT_DATAPOINTS, + INT_DATAPOINTS, +}; + +Theory((int a, int b), algebra, good_divide_is_inverse_of_multiply) { + cr_assume(b != 0); + cr_assert_eq(a, good_div(good_mul(a, b), b)); +} + +// For triangulation + +Test(algebra, multiplication_by_integer) { + cr_assert_eq(10, good_mul(5, 2)); +} + +// Another property test + +TheoryDataPoints(algebra, zero_is_absorbing) = { + INT_DATAPOINTS, + INT_DATAPOINTS, }; -Theory((float a), theory, float) { - printf("%f\n", (double) a); +Theory((int a, int b), algebra, zero_is_absorbing) { + cr_assume(a == 0 || b == 0); + cr_assert_eq(0, good_mul(a, b)); } From 1757752dd1bd78307e157eeda24141f3fd393610 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Thu, 3 Sep 2015 17:27:50 +0200 Subject: [PATCH 009/174] Added reporting & logging on theory failure --- doc/hooks.rst | 2 + include/criterion/hooks.h | 2 + include/criterion/logging.h | 1 + include/criterion/stats.h | 5 ++ include/criterion/theories.h | 8 ++- po/fr.po | 16 ++++-- src/abort.c | 3 +- src/abort.h | 3 ++ src/event.c | 20 ++++++++ src/log/normal.c | 11 +++++ src/report.c | 2 + src/report.h | 1 + src/runner.c | 8 +++ src/stats.c | 1 + src/theories.c | 95 +++++++++++++++++++++++++++++++++++- 15 files changed, 168 insertions(+), 10 deletions(-) diff --git a/doc/hooks.rst b/doc/hooks.rst index a9b8bd60..ff334a63 100644 --- a/doc/hooks.rst +++ b/doc/hooks.rst @@ -31,6 +31,7 @@ The flow of the test process goes as follows: #. ``PRE_INIT``: occurs before a test is initialized. #. ``PRE_TEST``: occurs after the test initialization, but before the test is run. #. ``ASSERT``: occurs when an assertion is hit +#. ``THEORY_FAIL``: occurs when a theory iteration fails. #. ``TEST_CRASH``: occurs when a test crashes unexpectedly. #. ``POST_TEST``: occurs after a test ends, but before the test finalization. #. ``POST_FINI``: occurs after a test finalization. @@ -50,6 +51,7 @@ Valid types for each phases are: * ``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``. diff --git a/include/criterion/hooks.h b/include/criterion/hooks.h index c5974677..0c86841d 100644 --- a/include/criterion/hooks.h +++ b/include/criterion/hooks.h @@ -32,6 +32,7 @@ typedef enum { PRE_INIT, PRE_TEST, ASSERT, + THEORY_FAIL, TEST_CRASH, POST_TEST, POST_FINI, @@ -54,6 +55,7 @@ typedef void (*f_report_hook)(); # 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 diff --git a/include/criterion/logging.h b/include/criterion/logging.h index 616dac9e..344b8a7d 100644 --- a/include/criterion/logging.h +++ b/include/criterion/logging.h @@ -96,6 +96,7 @@ struct criterion_output_provider { void (*log_pre_init )(struct criterion_test *test); void (*log_pre_test )(struct criterion_test *test); void (*log_assert )(struct criterion_assert_stats *stats); + void (*log_theory_fail)(struct criterion_theory_stats *stats); void (*log_test_crash )(struct criterion_test_stats *stats); void (*log_other_crash)(struct criterion_test_stats *stats); void (*log_post_test )(struct criterion_test_stats *stats); diff --git a/include/criterion/stats.h b/include/criterion/stats.h index 8a1b4e7f..3effc4d2 100644 --- a/include/criterion/stats.h +++ b/include/criterion/stats.h @@ -51,6 +51,11 @@ struct criterion_test_stats { struct criterion_test_stats *next; }; +struct criterion_theory_stats { + const char *formatted_args; + struct criterion_test_stats *stats; +}; + struct criterion_suite_stats { struct criterion_suite *suite; struct criterion_test_stats *tests; diff --git a/include/criterion/theories.h b/include/criterion/theories.h index 4da3527c..7d233c94 100644 --- a/include/criterion/theories.h +++ b/include/criterion/theories.h @@ -41,8 +41,12 @@ void cr_theory_call(struct criterion_theory_context *ctx, void (*fnptr)(void)); # define TheoryDataPoints(Category, Name) \ static struct criterion_datapoints IDENTIFIER_(Category, Name, dps)[] -# define DataPoints(Type, ...) \ - { sizeof (Type), sizeof ((Type[]) { __VA_ARGS__ }) / sizeof (Type), #Type, &(Type[]) { __VA_ARGS__ } } +# define DataPoints(Type, ...) { \ + sizeof (Type), \ + sizeof ((Type[]) { __VA_ARGS__ }) / sizeof (Type), \ + #Type, \ + &(Type[]) { __VA_ARGS__ }, \ + } struct criterion_datapoints { size_t size; diff --git a/po/fr.po b/po/fr.po index af25ab87..eb73de08 100644 --- a/po/fr.po +++ b/po/fr.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: criterion 1.0.0\n" "Report-Msgid-Bugs-To: franklinmathieu+criterion@gmail.com\n" -"POT-Creation-Date: 2015-08-05 11:37+0200\n" +"POT-Creation-Date: 2015-09-03 17:24+0200\n" "PO-Revision-Date: 2015-04-03 17:58+0200\n" "Last-Translator: \n" "Language-Team: French\n" @@ -54,18 +54,24 @@ 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:61 +#, 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:62 #, 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:62 +#: src/log/normal.c:63 #, c-format msgid "%1$s::%2$s: CRASH!\n" msgstr "%1$s::%2$s: PLANTAGE!\n" -#: src/log/normal.c:63 +#: src/log/normal.c:64 #, fuzzy, c-format msgid "" "%1$sWarning! The test `%2$s::%3$s` crashed during its setup or teardown." @@ -74,14 +80,14 @@ msgstr "" "%1$sAttention! Le test `%2$s::%3$s` a planté pendant son initialisation ou " "sa finalisation.%4$s\n" -#: src/log/normal.c:64 +#: src/log/normal.c:65 #, 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:66 +#: src/log/normal.c:67 #, c-format msgid "" "%1$sSynthesis: Tested: %2$s%3$lu%4$s | Passing: %5$s%6$lu%7$s | Failing: %8$s" diff --git a/src/abort.c b/src/abort.c index ea61bb98..596d9d84 100644 --- a/src/abort.c +++ b/src/abort.c @@ -21,10 +21,9 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -#include #include "abort.h" -static jmp_buf g_pre_test; +jmp_buf g_pre_test; int setup_abort_test(void) { return !setjmp(g_pre_test); diff --git a/src/abort.h b/src/abort.h index 4d85ba3f..9eab3d95 100644 --- a/src/abort.h +++ b/src/abort.h @@ -25,6 +25,9 @@ # define ABORT_H_ # include +# include + +extern jmp_buf g_pre_test; int setup_abort_test(void); diff --git a/src/event.c b/src/event.c index 6146c958..6907c7c7 100644 --- a/src/event.c +++ b/src/event.c @@ -54,6 +54,26 @@ struct event *read_event(FILE *f) { .value = { .kind = kind, .data = buf }, .dtor = destroy_event); } + case THEORY_FAIL: { + size_t *len = malloc(sizeof (size_t)); + if (fread(len, sizeof (size_t), 1, f) == 0) { + free(len); + return NULL; + } + + char *buf = malloc(*len); + if (fread(buf, *len, 1, f) == 0) { + free(len); + free(buf); + return NULL; + } + free(len); + + return unique_ptr(struct event, + .value = { .kind = kind, .data = buf }, + .dtor = destroy_event); + + } case POST_TEST: { double *elapsed_time = malloc(sizeof (double)); if (fread(elapsed_time, sizeof (double), 1, f) == 0) { diff --git a/src/log/normal.c b/src/log/normal.c index 565e763b..560a0f45 100644 --- a/src/log/normal.c +++ b/src/log/normal.c @@ -58,6 +58,7 @@ static msg_t msg_post_test = N_("%1$s::%2$s\n"); static msg_t msg_post_suite_test = N_("%1$s::%2$s: Test is disabled\n"); static msg_t msg_post_suite_suite = N_("%1$s::%2$s: Suite is disabled\n"); static msg_t msg_assert_fail = N_("%1$s%2$s%3$s:%4$s%5$d%6$s: Assertion failed: %7$s\n"); +static msg_t msg_theory_fail = N_(" Theory %1$s::%2$s failed with the following parameters: (%3$s)\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_other_crash = N_("%1$sWarning! The test `%2$s::%3$s` crashed during its setup or teardown.%4$s\n"); @@ -75,6 +76,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_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_other_crash = "%sWarning! The test `%s::%s` crashed during its setup or teardown.%s\n"; @@ -205,11 +207,20 @@ void normal_log_pre_suite(struct criterion_suite_set *set) { FG_GOLD, set->suite.name, RESET); } +void normal_log_theory_fail(struct criterion_theory_stats *stats) { + criterion_pimportant(CRITERION_PREFIX_DASHES, + _(msg_theory_fail), + stats->stats->test->category, + stats->stats->test->name, + stats->formatted_args); +} + struct criterion_output_provider normal_logging = { .log_pre_all = normal_log_pre_all, .log_pre_init = normal_log_pre_init, .log_pre_suite = normal_log_pre_suite, .log_assert = normal_log_assert, + .log_theory_fail = normal_log_theory_fail, .log_test_crash = normal_log_test_crash, .log_other_crash = normal_log_other_crash, .log_post_test = normal_log_post_test, diff --git a/src/report.c b/src/report.c index 64a6861f..b839542b 100644 --- a/src/report.c +++ b/src/report.c @@ -50,6 +50,7 @@ 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); @@ -61,6 +62,7 @@ ReportHook(PRE_SUITE)() {} ReportHook(PRE_INIT)() {} ReportHook(PRE_TEST)() {} ReportHook(ASSERT)() {} +ReportHook(THEORY_FAIL)() {} ReportHook(TEST_CRASH)() {} ReportHook(POST_TEST)() {} ReportHook(POST_FINI)() {} diff --git a/src/report.h b/src/report.h index aab2a103..02aeed95 100644 --- a/src/report.h +++ b/src/report.h @@ -37,6 +37,7 @@ DECL_CALL_REPORT_HOOKS(PRE_SUITE); DECL_CALL_REPORT_HOOKS(PRE_INIT); DECL_CALL_REPORT_HOOKS(PRE_TEST); DECL_CALL_REPORT_HOOKS(ASSERT); +DECL_CALL_REPORT_HOOKS(THEORY_FAIL); DECL_CALL_REPORT_HOOKS(TEST_CRASH); DECL_CALL_REPORT_HOOKS(POST_TEST); DECL_CALL_REPORT_HOOKS(POST_FINI); diff --git a/src/runner.c b/src/runner.c index c28da672..1a22164b 100644 --- a/src/runner.c +++ b/src/runner.c @@ -220,6 +220,14 @@ static void run_test(struct criterion_global_stats *stats, log(pre_test, test); 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); diff --git a/src/stats.c b/src/stats.c index e7d60a69..91b561a1 100644 --- a/src/stats.c +++ b/src/stats.c @@ -91,6 +91,7 @@ void stat_push_event(s_glob_stats *stats, push_pre_init, // PRE_INIT nothing, // PRE_TEST push_assert, // ASSERT + nothing, // THEORY_FAIL push_test_crash, // TEST_CRASH push_post_test, // POST_TEST nothing, // POST_FINI diff --git a/src/theories.c b/src/theories.c index e8465435..ff22ff50 100644 --- a/src/theories.c +++ b/src/theories.c @@ -27,6 +27,7 @@ #include #include #include "criterion/theories.h" +#include "abort.h" struct criterion_theory_context { DCCallVM* vm; @@ -99,6 +100,75 @@ static bool contains_word(const char *str, const char *pattern, size_t sz) { && (!res[sz - 1] || res[sz - 1] == ' '); } +static bool is_string(const char *name) { + return !strcmp(name, "char*") + || !strcmp(name, "char *") + || !strcmp(name, "const char*") + || !strcmp(name, "const char *") + || !strcmp(name, "char const *") + || !strcmp(name, "char const*") + || !strcmp(name, "char[]") + || !strcmp(name, "char []") + || !strcmp(name, "const char[]") + || !strcmp(name, "const char []") + || !strcmp(name, "char const[]") + || !strcmp(name, "char const []"); +} + +static bool is_float(const char *name) { + return contains_word(name, "float", sizeof ("float")) + || contains_word(name, "double", sizeof ("double")); +} + +static bool is_unsigned_int(const char *name) { + return contains_word(name, "unsigned", sizeof ("unsigned")) + || !strncmp(name, "uint", 4); +} + +static void format_arg(char (*arg)[1024], struct criterion_datapoints *dp, void *data) { + if (is_float(dp->name)) { + if (dp->size == sizeof (float)) { + snprintf(*arg, sizeof (*arg) - 1, "%g", *(float*) data); + } else if (dp->size == sizeof (double)) { + snprintf(*arg, sizeof (*arg) - 1, "%g", *(double*) data); + } else if (dp->size == sizeof (long double)) { + snprintf(*arg, sizeof (*arg) - 1, "%g", (double) *(long double*) data); + } + } else { + if (is_string(dp->name)) { + snprintf(*arg, sizeof (*arg) - 1, "%s", *(char**) data); + } else if (dp->size == sizeof (char)) { + snprintf(*arg, sizeof (*arg) - 1, "%c", *(char*) data); + } else if (dp->size == sizeof (short)) { + const char *fmt = is_unsigned_int(dp->name) ? "%hu" : "%hd"; + snprintf(*arg, sizeof (*arg) - 1, fmt, *(short*) data); + } else if (dp->size == sizeof (int)) { + const char *fmt = is_unsigned_int(dp->name) ? "%u" : "%d"; + snprintf(*arg, sizeof (*arg) - 1, fmt, *(int*) data); + } else if (dp->size == sizeof (bool)) { + snprintf(*arg, sizeof (*arg) - 1, "%d", *(bool*) data); + } else if (dp->size == sizeof (long)) { + const char *fmt = is_unsigned_int(dp->name) ? "%lu" : "%ld"; + snprintf(*arg, sizeof (*arg) - 1, fmt, *(long*) data); + } else if (dp->size == sizeof (long long)) { + const char *fmt = is_unsigned_int(dp->name) ? "%llu" : "%lld"; + snprintf(*arg, sizeof (*arg) - 1, fmt, *(long long*) data); + } else if (dp->size == sizeof (void*)) { + snprintf(*arg, sizeof (*arg) - 1, "%p", *(void**) data); + } else { + snprintf(*arg, sizeof (*arg) - 1, "%s", ""); + } + } +} + +static void concat_arg(char (*msg)[4096], struct criterion_datapoints *dps, size_t *indices, size_t i) { + void *data = ((char*) dps[i].arr) + dps[i].size * indices[i]; + + char arg[1024]; + format_arg(&arg, dps + i, data); + strncat(*msg, arg, sizeof (*msg) - 1); +} + void cr_theory_main(struct criterion_datapoints *dps, size_t datapoints, void (*fnptr)(void)) { struct criterion_theory_context *ctx = cr_theory_init(); @@ -119,7 +189,30 @@ void cr_theory_main(struct criterion_datapoints *dps, size_t datapoints, void (* dps[i].size, ((char*) dps[i].arr) + dps[i].size * indices[i]); } - cr_theory_call(ctx, fnptr); + + jmp_buf backup; + memcpy(backup, g_pre_test, sizeof (jmp_buf)); + int abort = 0; + if (!setjmp(g_pre_test)) { + cr_theory_call(ctx, fnptr); + } else { + abort = 1; + struct { + size_t len; + char msg[4096]; + } result; + for (size_t i = 0; i < datapoints - 1; ++i) { + concat_arg(&result.msg, dps, indices, i); + strncat(result.msg, ", ", sizeof (result.msg) - 1); + } + concat_arg(&result.msg, dps, indices, datapoints - 1); + result.len = strlen(result.msg) + 1; + + send_event(THEORY_FAIL, &result, result.len + sizeof (size_t)); + } + memcpy(g_pre_test, backup, sizeof (jmp_buf)); + if (abort) + criterion_abort_test(); } for (size_t i = 0; i < datapoints; ++i) { From 50df60c9624602c2ee2848567b7107a6da17393b Mon Sep 17 00:00:00 2001 From: Snaipe Date: Thu, 3 Sep 2015 17:30:46 +0200 Subject: [PATCH 010/174] Added documentation for .exit_code --- doc/starter.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/doc/starter.rst b/doc/starter.rst index 106c7d19..ed345558 100644 --- a/doc/starter.rst +++ b/doc/starter.rst @@ -194,6 +194,8 @@ Parameter Type Description .disabled bool Disables the test. ------------- --------------- -------------------------------------------------------------- .signal int Expect the test to raise the specified signal. +------------- --------------- -------------------------------------------------------------- +.exit_code int Expect the test to exit with the specified status. ============= =============== ============================================================== Setting up suite-wise configuration From 06e87bf5923cdde8c9821cc5e8c72c4e4853ac9a Mon Sep 17 00:00:00 2001 From: Snaipe Date: Thu, 3 Sep 2015 18:00:37 +0200 Subject: [PATCH 011/174] Added dyncall dependency installation --- .ci/install-dependencies.sh | 4 ++++ .ci/install-dyncall.sh | 12 ++++++++++++ .gitignore | 1 + .travis.yml | 2 +- appveyor.yml | 3 ++- 5 files changed, 20 insertions(+), 2 deletions(-) create mode 100755 .ci/install-dependencies.sh create mode 100755 .ci/install-dyncall.sh diff --git a/.ci/install-dependencies.sh b/.ci/install-dependencies.sh new file mode 100755 index 00000000..20d3273e --- /dev/null +++ b/.ci/install-dependencies.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +./.ci/install-dyncall.sh +./.ci/install-libcsptr.sh diff --git a/.ci/install-dyncall.sh b/.ci/install-dyncall.sh new file mode 100755 index 00000000..142da7d0 --- /dev/null +++ b/.ci/install-dyncall.sh @@ -0,0 +1,12 @@ +#!/bin/bash +repo="https://github.com/Snaipe/dyncall.git" +tag="master" + +mkdir -p dependencies +git clone --branch ${tag} --depth 1 ${repo} dependencies/dyncall && +( + cd dependencies/dyncall && + ./configure --prefix=$LOCAL_INSTALL + make && + make install +) diff --git a/.gitignore b/.gitignore index 8dd4a197..4da1b504 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,7 @@ !.gitignore !.bumpversion.cfg +!.ci/* !*.c !*.h diff --git a/.travis.yml b/.travis.yml index 4df2cb7f..6b8e2e40 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,7 +7,7 @@ compiler: sudo: false before_install: - export LOCAL_INSTALL="$HOME" -- ".ci/install-libcsptr.sh" +- ".ci/install-dependencies.sh" - export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$HOME/lib - export CFLAGS="-g -O0" script: diff --git a/appveyor.yml b/appveyor.yml index 1f74e15f..ee761a26 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -27,7 +27,8 @@ configuration: Release install: # Hack to make git think it is on the tip of the repo branch - 'git checkout -B %APPVEYOR_REPO_BRANCH%' - # Install libcsptr + # Install dependencies + - 'bash -lc "cd $APPVEYOR_BUILD_FOLDER; .ci/install-dyncall.sh; true"' - 'bash -lc "cd $APPVEYOR_BUILD_FOLDER; .ci/install-libcsptr.sh -G \"MSYS Makefiles\"; true"' # We need to manually make since the above command somehow crashes - 'cd dependencies/libcsptr/build && make && make install && cd ../../../' From d8668e3ed8dd8627655bcd6782154ae900df773c Mon Sep 17 00:00:00 2001 From: Snaipe Date: Thu, 3 Sep 2015 18:20:17 +0200 Subject: [PATCH 012/174] Added cmake dyncall dependency search --- .cmake/Modules/FindDyncall.cmake | 31 +++++++++++++++++++++++++++++++ CMakeLists.txt | 7 +++++-- appveyor.yml | 3 ++- 3 files changed, 38 insertions(+), 3 deletions(-) create mode 100644 .cmake/Modules/FindDyncall.cmake diff --git a/.cmake/Modules/FindDyncall.cmake b/.cmake/Modules/FindDyncall.cmake new file mode 100644 index 00000000..83070f6f --- /dev/null +++ b/.cmake/Modules/FindDyncall.cmake @@ -0,0 +1,31 @@ +# 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. + +# - Find dyncall +# Find the native libcsptr headers and libraries. +# +# DYNCALL_INCLUDE_DIRS - where to find smart_ptr.h, etc. +# DYNCALL_LIBRARIES - List of libraries when using libcsptr. +# DYNCALL_FOUND - True if libcsptr has been found. + +# Look for the header file. +FIND_PATH(DYNCALL_INCLUDE_DIR dyncall.h) + +# Look for the library. +FIND_LIBRARY(DYNCALL_LIBRARY NAMES dyncall_s) + +# Handle the QUIETLY and REQUIRED arguments and set DYNCALL_FOUND to TRUE if all listed variables are TRUE. +INCLUDE(FindPackageHandleStandardArgs) +FIND_PACKAGE_HANDLE_STANDARD_ARGS(DYNCALL DEFAULT_MSG DYNCALL_LIBRARY DYNCALL_INCLUDE_DIR) + +# Copy the results to the output variables. +IF(DYNCALL_FOUND) + SET(DYNCALL_LIBRARIES ${DYNCALL_LIBRARY}) + SET(DYNCALL_INCLUDE_DIRS ${DYNCALL_INCLUDE_DIR}) +ELSE(DYNCALL_FOUND) + SET(DYNCALL_LIBRARIES) + SET(DYNCALL_INCLUDE_DIRS) +ENDIF(DYNCALL_FOUND) + +MARK_AS_ADVANCED(DYNCALL_INCLUDE_DIRS DYNCALL_LIBRARIES) diff --git a/CMakeLists.txt b/CMakeLists.txt index ba5c8943..49630d46 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -42,6 +42,7 @@ CHECK_LIBRARY_EXISTS(rt clock_gettime "time.h" HAVE_CLOCK_GETTIME) find_package(PCRE) find_package(Libcsptr REQUIRED) +find_package(Dyncall REQUIRED) # List sources and headers @@ -118,12 +119,14 @@ if (LIBINTL_LIB_FOUND) target_link_libraries(criterion ${LIBINTL_LIBRARIES}) endif() +if (DYNCALL_FOUND) + target_link_libraries(criterion ${DYNCALL_LIBRARIES}) +endif() + if (COVERALLS) coveralls_setup("${SOURCE_FILES}" ${COVERALLS_UPLOAD}) endif() -target_link_libraries(criterion dyncall_s) - install(FILES ${INTERFACE_FILES} DESTINATION include/criterion) install(TARGETS criterion RUNTIME DESTINATION bin diff --git a/appveyor.yml b/appveyor.yml index ee761a26..ca543940 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -28,10 +28,11 @@ install: # Hack to make git think it is on the tip of the repo branch - 'git checkout -B %APPVEYOR_REPO_BRANCH%' # Install dependencies - - 'bash -lc "cd $APPVEYOR_BUILD_FOLDER; .ci/install-dyncall.sh; true"' + - 'bash -lc "cd $APPVEYOR_BUILD_FOLDER; exec 0 Date: Thu, 3 Sep 2015 18:31:24 +0200 Subject: [PATCH 013/174] Trying to fix dyncall installation on windows --- .ci/install-dyncall.bat | 9 +++++++++ .ci/install-dyncall.sh | 4 +++- appveyor.yml | 4 ++-- 3 files changed, 14 insertions(+), 3 deletions(-) create mode 100755 .ci/install-dyncall.bat diff --git a/.ci/install-dyncall.bat b/.ci/install-dyncall.bat new file mode 100755 index 00000000..c983288d --- /dev/null +++ b/.ci/install-dyncall.bat @@ -0,0 +1,9 @@ +set repo="https://github.com/Snaipe/dyncall.git" +set tag="master" + +mkdir dependencies +git clone --branch %tag% --depth 1 %repo% dependencies/dyncall +cd dependencies/dyncall +mkdir build && cd build +cmake -DCMAKE_INSTALL_PREFIX=%LOCAL_INSTALL% -G "NMake Makefiles" .. +nmake diff --git a/.ci/install-dyncall.sh b/.ci/install-dyncall.sh index 142da7d0..b880cbdc 100755 --- a/.ci/install-dyncall.sh +++ b/.ci/install-dyncall.sh @@ -6,7 +6,9 @@ mkdir -p dependencies git clone --branch ${tag} --depth 1 ${repo} dependencies/dyncall && ( cd dependencies/dyncall && - ./configure --prefix=$LOCAL_INSTALL + mkdir build && + cd $_ && + cmake -DCMAKE_INSTALL_PREFIX=$LOCAL_INSTALL "$@" .. && make && make install ) diff --git a/appveyor.yml b/appveyor.yml index ca543940..6e43b3e0 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -28,11 +28,11 @@ install: # Hack to make git think it is on the tip of the repo branch - 'git checkout -B %APPVEYOR_REPO_BRANCH%' # Install dependencies - - 'bash -lc "cd $APPVEYOR_BUILD_FOLDER; exec 0 Date: Thu, 3 Sep 2015 21:44:26 +0200 Subject: [PATCH 014/174] Prevent theories from aborting the whole test & fixed messages being cummulatively concatenated --- src/theories.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/theories.c b/src/theories.c index ff22ff50..3cc818e1 100644 --- a/src/theories.c +++ b/src/theories.c @@ -192,15 +192,13 @@ void cr_theory_main(struct criterion_datapoints *dps, size_t datapoints, void (* jmp_buf backup; memcpy(backup, g_pre_test, sizeof (jmp_buf)); - int abort = 0; if (!setjmp(g_pre_test)) { cr_theory_call(ctx, fnptr); } else { - abort = 1; struct { size_t len; char msg[4096]; - } result; + } result = {0}; for (size_t i = 0; i < datapoints - 1; ++i) { concat_arg(&result.msg, dps, indices, i); strncat(result.msg, ", ", sizeof (result.msg) - 1); @@ -211,8 +209,6 @@ void cr_theory_main(struct criterion_datapoints *dps, size_t datapoints, void (* send_event(THEORY_FAIL, &result, result.len + sizeof (size_t)); } memcpy(g_pre_test, backup, sizeof (jmp_buf)); - if (abort) - criterion_abort_test(); } for (size_t i = 0; i < datapoints; ++i) { From 00783d66ead2abd4fc4aa2b647a2904951147448 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Thu, 3 Sep 2015 23:43:20 +0200 Subject: [PATCH 015/174] Added documentation for theories --- README.md | 1 + doc/index.rst | 1 + doc/starter.rst | 2 + doc/theories.rst | 192 +++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 196 insertions(+) create mode 100644 doc/theories.rst diff --git a/README.md b/README.md index d46b2b1f..bdc4d7dd 100644 --- a/README.md +++ b/README.md @@ -29,6 +29,7 @@ the user would have with other frameworks: unless you want to do special handling. * [x] Test are isolated in their own process, crashes and signals can be reported and tested. +* [x] There is a support for theories alongside tests * [x] Progress and statistics can be followed in real time with report hooks. * [x] TAP output format can be enabled with an option. * [x] Runs on Linux, FreeBSD, Mac OS X, and Windows (Compiling with MinGW GCC). diff --git a/doc/index.rst b/doc/index.rst index dd79dd7e..e9d55c52 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -9,5 +9,6 @@ Criterion starter hooks env + theories internal faq diff --git a/doc/starter.rst b/doc/starter.rst index ed345558..6a9408ee 100644 --- a/doc/starter.rst +++ b/doc/starter.rst @@ -176,6 +176,8 @@ See the `windows exception reference`_ for more details on each exception. .. _windows exception reference: https://msdn.microsoft.com/en-us/library/windows/desktop/ms679356(v=vs.85).aspx +.. _test-config-ref: + Configuration reference ~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/doc/theories.rst b/doc/theories.rst new file mode 100644 index 00000000..7fd95c6e --- /dev/null +++ b/doc/theories.rst @@ -0,0 +1,192 @@ +Using theories +============== + +`Theories`_ are a powerful tool for test-driven development, allowing you +to test a specific behaviour against all permutations of a set of user-defined +parameters known as "data points". + +.. _Theories: http://web.archive.org/web/20110608210825/http://shareandenjoy.saff.net/tdd-specifications.pdf + +Adding theories +--------------- + +Adding theories is done by defining data points and a theory function: + +.. code-block:: c + + #include + + TheoryDataPoints(suite_name, test_name) = { + DataPoints(Type0, val0, val1, val2, ..., valN), + DataPoints(Type1, val0, val1, val2, ..., valN), + ... + DataPoints(TypeN, val0, val1, val2, ..., valN), + } + + Theory((Type0 arg0, Type1 arg1, ..., TypeN argN), suite_name, test_name) { + } + +``suite_name`` and ``test_name`` are the identifiers of the test suite and +the test, respectively. These identifiers must follow the language +identifier format. + +``Type0/arg0`` through ``TypeN/argN`` are the parameter types and names of theory +theory function and are available in the body of the function. + +Datapoints are declared in the same number, type, and order than the parameters +inside the ``TheoryDataPoints`` macro, with the ``DataPoints`` macro. +Beware! It is undefined behaviour to not have a matching number and type of +theory parameters and datatypes. + +Each ``DataPoints`` must then specify the values that will be used for the +theory parameter it is linked to (``val0`` through ``valN``). + +Assertions and invariants +------------------------- + +You can use any ``cr_assert`` or ``cr_expect`` macro functions inside the body of a +theory function. + +Theory invariants are enforced through the ``cr_assume(Condition)`` macro function: +if ``Condition`` is false, then the current theory iteration aborts without +making the test fail. + +Configuring theories +-------------------- + +Theories can optionally recieve configuration parameters to alter the behaviour +of the underlying test; as such, those parameters are the same ones as the ones +of the ``Test`` macro function (c.f. :ref:`test-config-ref`). + +Full sample & purpose of theories +--------------------------------- + +We will illustrate how useful theories are with a simple example using Criterion: + +The basics of theories +~~~~~~~~~~~~~~~~~~~~~~ + +Let us imagine that we want to test if the algebraic properties of integers, +and specifically concerning multiplication, are respected by the C language: + +.. code-block:: c + + int my_mul(int lhs, int rhs) { + return lhs * rhs; + } + +Now, we know that multiplication over integers is commutative, so we first test +that: + +.. code-block:: c + + #include + + Test(algebra, multiplication_is_commutative) { + cr_assert_eq(my_mul(2, 3), my_mul(3, 2)); + } + +However, this test is imperfect, because there is not enough triangulation to +insure that my_mul is indeed commutative. One might be tempted to add more +assertions on other values, but this will never be good enough: commutativity +should work for *any* pair of integers, not just an arbitrary set, but, to be +fair, you cannot just test this behaviour for every integer pair that exists. + +Theories purposely bridge these two issues by introducing the concept of +"data point" and by refactoring the repeating logic into a dedicated function: + +.. code-block:: c + + #include + + TheoryDataPoints(algebra, multiplication_is_commutative) = { + DataPoints(int, [...]), + DataPoints(int, [...]), + }; + + Theory((int lhs, int rhs), algebra, multiplication_is_commutative) { + cr_assert_eq(my_mul(lhs, rhs), my_mul(rhs, lhs)); + } + +As you can see, we refactored the assertion into a theory taking two unspecified +integers. + +We first define some data points in the same order and type the parameters have, +from left to right: the first ``DataPoints(int, ...)`` will define the set of values passed +to the ``int lhs`` parameter, and the second will define the one passed to ``int rhs``. + +Choosing the values of the data point is left to you, but we might as well use +"interesting" values: ``0``, ``-1``, ``1``, ``-2``, ``2``, ``INT_MAX``, and ``INT_MIN``: + +.. code-block:: c + + #include + + TheoryDataPoints(algebra, multiplication_is_commutative) = { + DataPoints(int, 0, -1, 1, -2, 2, INT_MAX, INT_MIN), + DataPoints(int, 0, -1, 1, -2, 2, INT_MAX, INT_MIN), + }; + +Using theory invariants +~~~~~~~~~~~~~~~~~~~~~~~ + +The second thing we can test on multiplication is that it is the inverse function +of division. Then, given the division operation: + +.. code-block:: c + + int my_div(int lhs, int rhs) { + return lhs / rhs; + } + +The associated theory is straight-forward: + +.. code-block:: c + + #include + + TheoryDataPoints(algebra, multiplication_is_inverse_of_division) = { + DataPoints(int, 0, -1, 1, -2, 2, INT_MAX, INT_MIN), + DataPoints(int, 0, -1, 1, -2, 2, INT_MAX, INT_MIN), + }; + + Theory((int lhs, int rhs), algebra, multiplication_is_inverse_of_division) { + cr_assert_eq(lhs, my_div(my_mul(lhs, rhs), rhs)); + } + +However, we do have a problem because you cannot have the theory function divide +by 0. For this purpose, we can ``assume`` than ``rhs`` will never be 0: + +.. code-block:: c + + Theory((int lhs, int rhs), algebra, multiplication_is_inverse_of_division) { + cr_assume(rhs != 0); + cr_assert_eq(lhs, my_div(my_mul(lhs, rhs), rhs)); + } + +``cr_assume`` will abort the current theory iteration if the condition is not +fulfiled. + +Running the test at that point will raise a big problem with the current +implementation of ``my_mul`` and ``my_div``: + +.. code-block:: none + + [----] theories.c:24: Assertion failed: (a) == (bad_div(bad_mul(a, b), b)) + [----] Theory algebra::multiplication_is_inverse_of_division failed with the following parameters: (2147483647, 2) + [----] theories.c:24: Assertion failed: (a) == (bad_div(bad_mul(a, b), b)) + [----] Theory algebra::multiplication_is_inverse_of_division failed with the following parameters: (-2147483648, 2) + [----] theories.c:24: Unexpected signal caught below this line! + [FAIL] algebra::multiplication_is_inverse_of_division: CRASH! + +The theory shows that ``my_div(my_mul(INT_MAX, 2), 2)`` and ``my_div(my_mul(INT_MIN, 2), 2)`` +does not respect the properties for multiplication: it happens that the +behaviour of these two functions is undefined because the operation overflows. + +Similarly, the test crashes at the end; debugging shows that the source of the +crash is the divison of INT_MAX by -1, which is undefined. + +Fixing this is as easy as changing the prototypes of ``my_mul`` and ``my_div`` +to operate on ``long long`` rather than ``int``. + + From ea814f361116af217e99f6534fae3909f7a3fc81 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Fri, 4 Sep 2015 01:09:59 +0200 Subject: [PATCH 016/174] Fixed missing field initializer warning on older GCC versions --- src/theories.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/theories.c b/src/theories.c index 3cc818e1..de3ed184 100644 --- a/src/theories.c +++ b/src/theories.c @@ -198,7 +198,8 @@ void cr_theory_main(struct criterion_datapoints *dps, size_t datapoints, void (* struct { size_t len; char msg[4096]; - } result = {0}; + } result = { .len = 0 }; + for (size_t i = 0; i < datapoints - 1; ++i) { concat_arg(&result.msg, dps, indices, i); strncat(result.msg, ", ", sizeof (result.msg) - 1); From 16aae06e7992a0d60b2b0005c09993d902bbc7cd Mon Sep 17 00:00:00 2001 From: Snaipe Date: Fri, 4 Sep 2015 02:47:06 +0200 Subject: [PATCH 017/174] Made the build system also build the dependencies --- .ci/install-dependencies.bat | 16 ++++++++++++++++ .ci/install-dependencies.sh | 21 +++++++++++++++++++-- .ci/install-dyncall.bat | 9 --------- .ci/install-dyncall.sh | 14 -------------- .ci/install-libcsptr.sh | 14 -------------- .ci/install-pip.sh | 4 ---- .gitmodules | 6 ++++++ CMakeLists.txt | 28 +++++++++++++++++----------- appveyor.yml | 6 +----- dependencies/dyncall | 1 + dependencies/libcsptr | 1 + 11 files changed, 61 insertions(+), 59 deletions(-) create mode 100644 .ci/install-dependencies.bat delete mode 100755 .ci/install-dyncall.bat delete mode 100755 .ci/install-dyncall.sh delete mode 100755 .ci/install-libcsptr.sh delete mode 100755 .ci/install-pip.sh create mode 100644 .gitmodules create mode 160000 dependencies/dyncall create mode 160000 dependencies/libcsptr diff --git a/.ci/install-dependencies.bat b/.ci/install-dependencies.bat new file mode 100644 index 00000000..a48d4b67 --- /dev/null +++ b/.ci/install-dependencies.bat @@ -0,0 +1,16 @@ +git submodule update --init --recursive && + +cd dependencies/dyncall && +mkdir build && cd build && + +cmake -DCMAKE_INSTALL_PREFIX=%LOCAL_INSTALL% %* .. && +make && +make install && +cd ../../../ && + +cd dependencies/libcsptr/ && +mkdir build && cd build && + +cmake -DCMAKE_INSTALL_PREFIX=%LOCAL_INSTALL% %* .. && +make && +make install diff --git a/.ci/install-dependencies.sh b/.ci/install-dependencies.sh index 20d3273e..9ddd12cb 100755 --- a/.ci/install-dependencies.sh +++ b/.ci/install-dependencies.sh @@ -1,4 +1,21 @@ #!/bin/sh -./.ci/install-dyncall.sh -./.ci/install-libcsptr.sh +git submodule update --init --recursive && + +( + cd dependencies/dyncall && + mkdir build && + cd $_ && + cmake -DCMAKE_INSTALL_PREFIX=$LOCAL_INSTALL "$@" .. && + make && + make install +) && + +( + cd dependencies/libcsptr/ && + mkdir build && + cd $_ && + cmake -DCMAKE_INSTALL_PREFIX=$LOCAL_INSTALL "$@" .. && + make && + make install +) diff --git a/.ci/install-dyncall.bat b/.ci/install-dyncall.bat deleted file mode 100755 index c983288d..00000000 --- a/.ci/install-dyncall.bat +++ /dev/null @@ -1,9 +0,0 @@ -set repo="https://github.com/Snaipe/dyncall.git" -set tag="master" - -mkdir dependencies -git clone --branch %tag% --depth 1 %repo% dependencies/dyncall -cd dependencies/dyncall -mkdir build && cd build -cmake -DCMAKE_INSTALL_PREFIX=%LOCAL_INSTALL% -G "NMake Makefiles" .. -nmake diff --git a/.ci/install-dyncall.sh b/.ci/install-dyncall.sh deleted file mode 100755 index b880cbdc..00000000 --- a/.ci/install-dyncall.sh +++ /dev/null @@ -1,14 +0,0 @@ -#!/bin/bash -repo="https://github.com/Snaipe/dyncall.git" -tag="master" - -mkdir -p dependencies -git clone --branch ${tag} --depth 1 ${repo} dependencies/dyncall && -( - cd dependencies/dyncall && - mkdir build && - cd $_ && - cmake -DCMAKE_INSTALL_PREFIX=$LOCAL_INSTALL "$@" .. && - make && - make install -) diff --git a/.ci/install-libcsptr.sh b/.ci/install-libcsptr.sh deleted file mode 100755 index 088f06bb..00000000 --- a/.ci/install-libcsptr.sh +++ /dev/null @@ -1,14 +0,0 @@ -#!/bin/bash -repo="https://github.com/Snaipe/libcsptr.git" -tag="v2.0.4" - -mkdir dependencies -git clone --branch ${tag} --depth 1 ${repo} dependencies/libcsptr && -( - cd dependencies/libcsptr && - mkdir build && - cd $_ && - cmake -DCMAKE_INSTALL_PREFIX=$LOCAL_INSTALL "$@" .. && - make && - make install -) diff --git a/.ci/install-pip.sh b/.ci/install-pip.sh deleted file mode 100755 index 379cfbf1..00000000 --- a/.ci/install-pip.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/sh -curl -O https://bootstrap.pypa.io/get-pip.py -python3 get-pip.py -rm -f get-pip.py diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 00000000..06e28e88 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,6 @@ +[submodule "dependencies/libcsptr"] + path = dependencies/libcsptr + url = https://github.com/Snaipe/libcsptr.git +[submodule "dependencies/dyncall"] + path = dependencies/dyncall + url = https://github.com/Snaipe/dyncall.git diff --git a/CMakeLists.txt b/CMakeLists.txt index 49630d46..6eeca7e1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,15 +2,27 @@ cmake_minimum_required(VERSION 2.8) project(Criterion C) +set(LIBCSPTR_DISABLE_TESTS ON) + +add_subdirectory(dependencies/libcsptr/ EXCLUDE_FROM_ALL) +add_subdirectory(dependencies/dyncall/ EXCLUDE_FROM_ALL) + +include_directories( + dependencies/libcsptr/include/ + dependencies/dyncall/dyncall/ +) + # Project setup & environment variables set(PROJECT_VERSION "1.3.1") set(LOCALEDIR ${CMAKE_INSTALL_PREFIX}/share/locale) set(GettextTranslate_ALL 1) set(GettextTranslate_GMO_BINARY 1) -set(MODULE_DIR "${CMAKE_SOURCE_DIR}/.cmake/Modules") +set(MODULE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/.cmake/Modules") set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${MODULE_DIR}) +set_property(GLOBAL PROPERTY ALLOW_DUPLICATE_CUSTOM_TARGETS ON) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Werror -g -std=gnu99") if (WIN32) @@ -41,8 +53,6 @@ include(CheckLibraryExists) CHECK_LIBRARY_EXISTS(rt clock_gettime "time.h" HAVE_CLOCK_GETTIME) find_package(PCRE) -find_package(Libcsptr REQUIRED) -find_package(Dyncall REQUIRED) # List sources and headers @@ -99,13 +109,13 @@ set(INTERFACE_FILES # Generate the configure file configure_file( - "${CMAKE_SOURCE_DIR}/src/config.h.in" - "${CMAKE_SOURCE_DIR}/src/config.h" + "${CMAKE_CURRENT_SOURCE_DIR}/src/config.h.in" + "${CMAKE_CURRENT_SOURCE_DIR}/src/config.h" ) -include_directories(include src ${CSPTR_INCLUDE_DIRS}) +include_directories(include src) add_library(criterion SHARED ${SOURCE_FILES} ${INTERFACE_FILES}) -target_link_libraries(criterion ${CSPTR_LIBRARIES}) +target_link_libraries(criterion csptr dyncall_s) if (HAVE_CLOCK_GETTIME) target_link_libraries(criterion rt) @@ -119,10 +129,6 @@ if (LIBINTL_LIB_FOUND) target_link_libraries(criterion ${LIBINTL_LIBRARIES}) endif() -if (DYNCALL_FOUND) - target_link_libraries(criterion ${DYNCALL_LIBRARIES}) -endif() - if (COVERALLS) coveralls_setup("${SOURCE_FILES}" ${COVERALLS_UPLOAD}) endif() diff --git a/appveyor.yml b/appveyor.yml index 6e43b3e0..987d728d 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -28,11 +28,7 @@ install: # Hack to make git think it is on the tip of the repo branch - 'git checkout -B %APPVEYOR_REPO_BRANCH%' # Install dependencies - - 'bash -lc "cd $APPVEYOR_BUILD_FOLDER; .ci/install-dyncall.sh -G \"MSYS Makefiles\"; true"' - - 'bash -lc "cd $APPVEYOR_BUILD_FOLDER; .ci/install-libcsptr.sh -G \"MSYS Makefiles\"; true"' - # We need to manually make since the above command somehow crashes - - 'cd dependencies/libcsptr/build && make && make install && cd ../../../' - - 'cd dependencies/dyncall/build && make && make install && cd ../../../' + - '.ci\install-dependencies.bat' # Configure project - 'mkdir build && cd build' - 'cmake -DCMAKE_INSTALL_PREFIX=criterion-%APPVEYOR_REPO_TAG_NAME% -DCMAKE_PREFIX_PATH="%LOCAL_INSTALL%" -DCOVERALLS=ON -DCMAKE_BUILD_TYPE=Debug -G "MSYS Makefiles" ..' diff --git a/dependencies/dyncall b/dependencies/dyncall new file mode 160000 index 00000000..68c57f66 --- /dev/null +++ b/dependencies/dyncall @@ -0,0 +1 @@ +Subproject commit 68c57f664d4fabbc5b80327fbf5661a3a5a51e06 diff --git a/dependencies/libcsptr b/dependencies/libcsptr new file mode 160000 index 00000000..a0c2444c --- /dev/null +++ b/dependencies/libcsptr @@ -0,0 +1 @@ +Subproject commit a0c2444ccc3c589f34894982cd95032a817c9482 From 11bacffc159f248a60441efc80d7ac0c6267723a Mon Sep 17 00:00:00 2001 From: Snaipe Date: Fri, 4 Sep 2015 02:51:00 +0200 Subject: [PATCH 018/174] Fixed install-dependencies scripts --- .ci/install-dependencies.bat | 6 +++--- .ci/install-dependencies.sh | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.ci/install-dependencies.bat b/.ci/install-dependencies.bat index a48d4b67..23358d2b 100644 --- a/.ci/install-dependencies.bat +++ b/.ci/install-dependencies.bat @@ -1,14 +1,14 @@ git submodule update --init --recursive && -cd dependencies/dyncall && +cd dependencies\dyncall && mkdir build && cd build && cmake -DCMAKE_INSTALL_PREFIX=%LOCAL_INSTALL% %* .. && make && make install && -cd ../../../ && +cd ..\..\.. && -cd dependencies/libcsptr/ && +cd dependencies\libcsptr && mkdir build && cd build && cmake -DCMAKE_INSTALL_PREFIX=%LOCAL_INSTALL% %* .. && diff --git a/.ci/install-dependencies.sh b/.ci/install-dependencies.sh index 9ddd12cb..4fefe0c2 100755 --- a/.ci/install-dependencies.sh +++ b/.ci/install-dependencies.sh @@ -5,7 +5,7 @@ git submodule update --init --recursive && ( cd dependencies/dyncall && mkdir build && - cd $_ && + cd build && cmake -DCMAKE_INSTALL_PREFIX=$LOCAL_INSTALL "$@" .. && make && make install @@ -14,7 +14,7 @@ git submodule update --init --recursive && ( cd dependencies/libcsptr/ && mkdir build && - cd $_ && + cd build && cmake -DCMAKE_INSTALL_PREFIX=$LOCAL_INSTALL "$@" .. && make && make install From 164f334ea10c3df87aaa64911e49e4197fbd4ac0 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Fri, 4 Sep 2015 03:03:40 +0200 Subject: [PATCH 019/174] Included submodule update in cmake module --- .ci/install-dependencies.bat | 16 --------- .ci/install-dependencies.sh | 21 ------------ .cmake/Modules/Submodules.cmake | 58 +++++++++++++++++++++++++++++++++ .travis.yml | 1 - CMakeLists.txt | 6 ++-- appveyor.yml | 2 -- 6 files changed, 62 insertions(+), 42 deletions(-) delete mode 100644 .ci/install-dependencies.bat delete mode 100755 .ci/install-dependencies.sh create mode 100644 .cmake/Modules/Submodules.cmake diff --git a/.ci/install-dependencies.bat b/.ci/install-dependencies.bat deleted file mode 100644 index 23358d2b..00000000 --- a/.ci/install-dependencies.bat +++ /dev/null @@ -1,16 +0,0 @@ -git submodule update --init --recursive && - -cd dependencies\dyncall && -mkdir build && cd build && - -cmake -DCMAKE_INSTALL_PREFIX=%LOCAL_INSTALL% %* .. && -make && -make install && -cd ..\..\.. && - -cd dependencies\libcsptr && -mkdir build && cd build && - -cmake -DCMAKE_INSTALL_PREFIX=%LOCAL_INSTALL% %* .. && -make && -make install diff --git a/.ci/install-dependencies.sh b/.ci/install-dependencies.sh deleted file mode 100755 index 4fefe0c2..00000000 --- a/.ci/install-dependencies.sh +++ /dev/null @@ -1,21 +0,0 @@ -#!/bin/sh - -git submodule update --init --recursive && - -( - cd dependencies/dyncall && - mkdir build && - cd build && - cmake -DCMAKE_INSTALL_PREFIX=$LOCAL_INSTALL "$@" .. && - make && - make install -) && - -( - cd dependencies/libcsptr/ && - mkdir build && - cd build && - cmake -DCMAKE_INSTALL_PREFIX=$LOCAL_INSTALL "$@" .. && - make && - make install -) diff --git a/.cmake/Modules/Submodules.cmake b/.cmake/Modules/Submodules.cmake new file mode 100644 index 00000000..2b524e69 --- /dev/null +++ b/.cmake/Modules/Submodules.cmake @@ -0,0 +1,58 @@ +if(EXISTS "${PROJECT_SOURCE_DIR}/.gitmodules") +message(STATUS "Updating submodules to their latest/fixed versions") +message(STATUS "(this can take a while, please be patient)") + +### set the direcory where the submodules live +set(GIT_SUBMODULES_DIRECTORY dependencies) + +### set the directory names of the submodules +set(GIT_SUBMODULES libcsptr dyncall) + +### set each submodules's commit or tag that is to be checked out +### (leave empty if you want master) +set(GIT_SUBMODULE_VERSION_libcsptr a0c2444) +set(GIT_SUBMODULE_VERSION_dyncall 68c57f6) + +### First, get all submodules in +if(${GIT_SUBMODULES_CHECKOUT_QUIET}) + execute_process( + COMMAND git submodule update --init --recursive + WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} + OUTPUT_QUIET + ERROR_QUIET + ) +else() + execute_process( + COMMAND git submodule update --init --recursive + WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} + ) +endif() + +### Then, checkout each submodule to the specified commit +# Note: Execute separate processes here, to make sure each one is run, +# should one crash (because of branch not existing, this, that ... whatever) +foreach(GIT_SUBMODULE ${GIT_SUBMODULES}) + + if( "${GIT_SUBMODULE_VERSION_${GIT_SUBMODULE}}" STREQUAL "" ) + message(STATUS "no specific version given for submodule ${GIT_SUBMODULE}, checking out master") + set(GIT_SUBMODULE_VERSION_${GIT_SUBMODULE} "master") + endif() + + if(${GIT_SUBMODULES_CHECKOUT_QUIET}) + execute_process( + COMMAND git checkout ${GIT_SUBMODULE_VERSION_${GIT_SUBMODULE}} + WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}/${GIT_SUBMODULES_DIRECTORY}/${GIT_SUBMODULE} + OUTPUT_QUIET + ERROR_QUIET + ) + else() + message(STATUS "checking out ${GIT_SUBMODULE}'s commit/tag ${GIT_SUBMODULE_VERSION_${GIT_SUBMODULE}}") + execute_process( + COMMAND git checkout -q ${GIT_SUBMODULE_VERSION_${GIT_SUBMODULE}} + WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}/${GIT_SUBMODULES_DIRECTORY}/${GIT_SUBMODULE} + ) + endif() + +endforeach(${GIT_SUBMODULE}) + +endif() diff --git a/.travis.yml b/.travis.yml index 6b8e2e40..34224653 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,7 +7,6 @@ compiler: sudo: false before_install: - export LOCAL_INSTALL="$HOME" -- ".ci/install-dependencies.sh" - export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$HOME/lib - export CFLAGS="-g -O0" script: diff --git a/CMakeLists.txt b/CMakeLists.txt index 6eeca7e1..ede228e9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,8 +2,12 @@ cmake_minimum_required(VERSION 2.8) project(Criterion C) +set(MODULE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/.cmake/Modules") +set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${MODULE_DIR}) set(LIBCSPTR_DISABLE_TESTS ON) +include(Submodules) + add_subdirectory(dependencies/libcsptr/ EXCLUDE_FROM_ALL) add_subdirectory(dependencies/dyncall/ EXCLUDE_FROM_ALL) @@ -18,8 +22,6 @@ set(PROJECT_VERSION "1.3.1") set(LOCALEDIR ${CMAKE_INSTALL_PREFIX}/share/locale) set(GettextTranslate_ALL 1) set(GettextTranslate_GMO_BINARY 1) -set(MODULE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/.cmake/Modules") -set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${MODULE_DIR}) set_property(GLOBAL PROPERTY ALLOW_DUPLICATE_CUSTOM_TARGETS ON) diff --git a/appveyor.yml b/appveyor.yml index 987d728d..439aa1d1 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -27,8 +27,6 @@ configuration: Release install: # Hack to make git think it is on the tip of the repo branch - 'git checkout -B %APPVEYOR_REPO_BRANCH%' - # Install dependencies - - '.ci\install-dependencies.bat' # Configure project - 'mkdir build && cd build' - 'cmake -DCMAKE_INSTALL_PREFIX=criterion-%APPVEYOR_REPO_TAG_NAME% -DCMAKE_PREFIX_PATH="%LOCAL_INSTALL%" -DCOVERALLS=ON -DCMAKE_BUILD_TYPE=Debug -G "MSYS Makefiles" ..' From dcbf985a003b73de92cb62b57714b16cb74e8bdc Mon Sep 17 00:00:00 2001 From: Snaipe Date: Fri, 4 Sep 2015 03:07:09 +0200 Subject: [PATCH 020/174] Updated libcsptr for -fPIC removal on windows --- .cmake/Modules/Submodules.cmake | 2 +- dependencies/libcsptr | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.cmake/Modules/Submodules.cmake b/.cmake/Modules/Submodules.cmake index 2b524e69..000c367b 100644 --- a/.cmake/Modules/Submodules.cmake +++ b/.cmake/Modules/Submodules.cmake @@ -10,7 +10,7 @@ set(GIT_SUBMODULES libcsptr dyncall) ### set each submodules's commit or tag that is to be checked out ### (leave empty if you want master) -set(GIT_SUBMODULE_VERSION_libcsptr a0c2444) +set(GIT_SUBMODULE_VERSION_libcsptr bacfe99) set(GIT_SUBMODULE_VERSION_dyncall 68c57f6) ### First, get all submodules in diff --git a/dependencies/libcsptr b/dependencies/libcsptr index a0c2444c..bacfe990 160000 --- a/dependencies/libcsptr +++ b/dependencies/libcsptr @@ -1 +1 @@ -Subproject commit a0c2444ccc3c589f34894982cd95032a817c9482 +Subproject commit bacfe990f99e7328ba873e35665a0ff4e57c9df1 From fc64949d9665281e40d3c5d19469a513d40d5ec2 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Fri, 4 Sep 2015 03:11:07 +0200 Subject: [PATCH 021/174] Updated documentation for new build instructions --- doc/setup.rst | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/doc/setup.rst b/doc/setup.rst index 507fc810..1dec23cb 100644 --- a/doc/setup.rst +++ b/doc/setup.rst @@ -6,9 +6,9 @@ Prerequisites Currently, this library only works under \*nix systems. -To compile the static library and its dependencies, GCC 4.6+ is needed. +To compile the shared library and its dependencies, GCC 4.6+ is needed. -To use the static library, any GNU-C compatible compiler will suffice +To use the shared library, any GNU-C compatible compiler will suffice (GCC, Clang/LLVM, ICC, MinGW-GCC, ...). Installation @@ -17,7 +17,6 @@ Installation .. code-block:: bash $ git clone https://github.com/Snaipe/Criterion.git && cd Criterion - $ LOCAL_INSTALL=/usr .ci/install-libcsptr.sh $ mkdir build && cd $_ && cmake -DCMAKE_INSTALL_PATH=/usr .. $ make && sudo make install From 90711d4ae1dfc54e92476be526f276b4643e18d2 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Fri, 4 Sep 2015 03:32:19 +0200 Subject: [PATCH 022/174] Fixed coveralls output to report only criterion --- .cmake/Modules/Submodules.cmake | 2 +- CMakeLists.txt | 1 + dependencies/libcsptr | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.cmake/Modules/Submodules.cmake b/.cmake/Modules/Submodules.cmake index 000c367b..7c251394 100644 --- a/.cmake/Modules/Submodules.cmake +++ b/.cmake/Modules/Submodules.cmake @@ -10,7 +10,7 @@ set(GIT_SUBMODULES libcsptr dyncall) ### set each submodules's commit or tag that is to be checked out ### (leave empty if you want master) -set(GIT_SUBMODULE_VERSION_libcsptr bacfe99) +set(GIT_SUBMODULE_VERSION_libcsptr 04cd477) set(GIT_SUBMODULE_VERSION_dyncall 68c57f6) ### First, get all submodules in diff --git a/CMakeLists.txt b/CMakeLists.txt index ede228e9..a7bf973a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,6 +5,7 @@ project(Criterion C) set(MODULE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/.cmake/Modules") set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${MODULE_DIR}) set(LIBCSPTR_DISABLE_TESTS ON) +set(LIBCSPTR_DISABLE_COVERALLS ON) include(Submodules) diff --git a/dependencies/libcsptr b/dependencies/libcsptr index bacfe990..04cd477d 160000 --- a/dependencies/libcsptr +++ b/dependencies/libcsptr @@ -1 +1 @@ -Subproject commit bacfe990f99e7328ba873e35665a0ff4e57c9df1 +Subproject commit 04cd477d1f213e55d2ddecab2fcd52d1c7865dfa From 5b840e546e74d3d96f3fa35caa591451f2bd0d03 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Fri, 4 Sep 2015 03:33:27 +0200 Subject: [PATCH 023/174] Removed windows coverage until coveralls knows how to merge multiple CI reports --- appveyor.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 439aa1d1..049a0662 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -41,8 +41,8 @@ after_build: test_script: - 'make test || bash -lc "cat $APPVEYOR_BUILD_FOLDER/build/Testing/Temporary/LastTest.log"' -after_test: - - 'make coveralls' +#after_test: +# - 'make coveralls' notifications: From 2bc980a39a97850776e9e434b44e3a042cc973e2 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Fri, 4 Sep 2015 14:59:42 +0200 Subject: [PATCH 024/174] Added better coverage report for theories --- samples/tests/early_exit.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/samples/tests/early_exit.sh b/samples/tests/early_exit.sh index 30f513a5..f25738cc 100755 --- a/samples/tests/early_exit.sh +++ b/samples/tests/early_exit.sh @@ -1,2 +1,3 @@ #!/bin/sh ./simple --no-early-exit --always-succeed +./theories --no-early-exit --always-succeed From e1e332e38b97206f7edcc00ae8de5cbf3e2886ea Mon Sep 17 00:00:00 2001 From: Snaipe Date: Fri, 4 Sep 2015 15:52:54 +0200 Subject: [PATCH 025/174] Added a test for various theory parameters --- samples/theories.c | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/samples/theories.c b/samples/theories.c index bd814de4..8e2e796a 100644 --- a/samples/theories.c +++ b/samples/theories.c @@ -61,3 +61,35 @@ Theory((int a, int b), algebra, zero_is_absorbing) { cr_assume(a == 0 || b == 0); cr_assert_eq(0, good_mul(a, b)); } + +// Testing for various parameters + +struct my_object { + int foo; +}; + +TheoryDataPoints(theory, misc) = { + DataPoints(char, 'a'), + 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"), + DataPoints(struct my_object *, &(struct my_object) {42}), +}; + +Theory((char c, short s, int i, long l, long long ll, float f, double d, char *str, const char *cstr, struct my_object *obj), theory, misc) { + 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_strings_eq(str, "test"); + cr_assert_strings_eq(cstr, "other test"); + cr_assert_eq(obj->foo, 42); +} From eff36eea2d04c67c3ff00ee621575f669a6f97b1 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Fri, 4 Sep 2015 15:53:25 +0200 Subject: [PATCH 026/174] Added 0x prefix for pointer parameters in theories --- src/theories.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/theories.c b/src/theories.c index de3ed184..3d392b95 100644 --- a/src/theories.c +++ b/src/theories.c @@ -154,7 +154,7 @@ static void format_arg(char (*arg)[1024], struct criterion_datapoints *dp, void const char *fmt = is_unsigned_int(dp->name) ? "%llu" : "%lld"; snprintf(*arg, sizeof (*arg) - 1, fmt, *(long long*) data); } else if (dp->size == sizeof (void*)) { - snprintf(*arg, sizeof (*arg) - 1, "%p", *(void**) data); + snprintf(*arg, sizeof (*arg) - 1, "0x%p", *(void**) data); } else { snprintf(*arg, sizeof (*arg) - 1, "%s", ""); } From 9e3196f737717674fa101daff4a6bf03d27068c8 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Fri, 4 Sep 2015 15:57:02 +0200 Subject: [PATCH 027/174] Made the misc theory test fail to test parameter formatting --- samples/theories.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/samples/theories.c b/samples/theories.c index 8e2e796a..920b7862 100644 --- a/samples/theories.c +++ b/samples/theories.c @@ -92,4 +92,7 @@ Theory((char c, short s, int i, long l, long long ll, float f, double d, char *s cr_assert_strings_eq(str, "test"); cr_assert_strings_eq(cstr, "other test"); cr_assert_eq(obj->foo, 42); + + // abort to see the formatted string of all parameters + cr_abort_test(NULL); } From 29befaf779fae974ccf6b9d4dd13b0987ae08e23 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Fri, 4 Sep 2015 16:39:40 +0200 Subject: [PATCH 028/174] Added better parameter formatting for theories & added bool theory parameter to misc sample --- samples/theories.c | 4 +++- src/theories.c | 34 ++++++++++++++++++++++++---------- 2 files changed, 27 insertions(+), 11 deletions(-) diff --git a/samples/theories.c b/samples/theories.c index 920b7862..0493619e 100644 --- a/samples/theories.c +++ b/samples/theories.c @@ -70,6 +70,7 @@ struct my_object { TheoryDataPoints(theory, misc) = { DataPoints(char, 'a'), + DataPoints(bool, true), DataPoints(short, 1), DataPoints(int, 1), DataPoints(long, 1), @@ -81,7 +82,8 @@ TheoryDataPoints(theory, misc) = { DataPoints(struct my_object *, &(struct my_object) {42}), }; -Theory((char c, short s, int i, long l, long long ll, float f, double d, char *str, const char *cstr, struct my_object *obj), 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) { + cr_assert(b); cr_assert_eq(c, 'a'); cr_assert_eq(s, 1); cr_assert_eq(i, 1); diff --git a/src/theories.c b/src/theories.c index 3d392b95..0431c96a 100644 --- a/src/theories.c +++ b/src/theories.c @@ -26,6 +26,7 @@ #include #include #include +#include #include "criterion/theories.h" #include "abort.h" @@ -51,10 +52,14 @@ void cr_theory_push_arg(struct criterion_theory_context *ctx, bool is_float, siz dcArgInt(ctx->vm, *(int*)ptr); } else if (size == sizeof (bool)) { dcArgBool(ctx->vm, *(bool*)ptr); +#if INT_MAX < LONG_MAX } else if (size == sizeof (long)) { dcArgLong(ctx->vm, *(long*)ptr); +#endif +#if LONG_MAX < LLONG_MAX } else if (size == sizeof (long long)) { dcArgLongLong(ctx->vm, *(long long*)ptr); +#endif } else if (size == sizeof (void*)) { dcArgPointer(ctx->vm, *(void**)ptr); } else { @@ -125,36 +130,45 @@ static bool is_unsigned_int(const char *name) { || !strncmp(name, "uint", 4); } +static bool is_bool(const char *name) { + return contains_word(name, "bool", sizeof ("bool")) + || contains_word(name, "_Bool", sizeof ("_Bool")); +} + static void format_arg(char (*arg)[1024], struct criterion_datapoints *dp, void *data) { if (is_float(dp->name)) { if (dp->size == sizeof (float)) { - snprintf(*arg, sizeof (*arg) - 1, "%g", *(float*) data); + snprintf(*arg, sizeof (*arg) - 1, "%gf", *(float*) data); } else if (dp->size == sizeof (double)) { snprintf(*arg, sizeof (*arg) - 1, "%g", *(double*) data); } else if (dp->size == sizeof (long double)) { - snprintf(*arg, sizeof (*arg) - 1, "%g", (double) *(long double*) data); + snprintf(*arg, sizeof (*arg) - 1, "%gl", (double) *(long double*) data); } } else { if (is_string(dp->name)) { - snprintf(*arg, sizeof (*arg) - 1, "%s", *(char**) data); + snprintf(*arg, sizeof (*arg) - 1, "\"%s\"", *(char**) data); + } else if (dp->size == sizeof (bool) && is_bool(dp->name)) { + snprintf(*arg, sizeof (*arg) - 1, "%s", (*(bool*) data) ? "true" : "false"); } else if (dp->size == sizeof (char)) { - snprintf(*arg, sizeof (*arg) - 1, "%c", *(char*) data); + snprintf(*arg, sizeof (*arg) - 1, "'%c'", *(char*) data); } else if (dp->size == sizeof (short)) { const char *fmt = is_unsigned_int(dp->name) ? "%hu" : "%hd"; snprintf(*arg, sizeof (*arg) - 1, fmt, *(short*) data); } else if (dp->size == sizeof (int)) { const char *fmt = is_unsigned_int(dp->name) ? "%u" : "%d"; snprintf(*arg, sizeof (*arg) - 1, fmt, *(int*) data); - } else if (dp->size == sizeof (bool)) { - snprintf(*arg, sizeof (*arg) - 1, "%d", *(bool*) data); + } else if (dp->size == sizeof (void*) && strstr(dp->name, "*")) { + snprintf(*arg, sizeof (*arg) - 1, "%p", *(void**) data); +#if INT_MAX < LONG_MAX } else if (dp->size == sizeof (long)) { - const char *fmt = is_unsigned_int(dp->name) ? "%lu" : "%ld"; + const char *fmt = is_unsigned_int(dp->name) ? "%lulu" : "%ldl"; snprintf(*arg, sizeof (*arg) - 1, fmt, *(long*) data); +#endif +#if LONG_MAX < LLONG_MAX } else if (dp->size == sizeof (long long)) { - const char *fmt = is_unsigned_int(dp->name) ? "%llu" : "%lld"; + const char *fmt = is_unsigned_int(dp->name) ? "%llullu" : "%lldll"; snprintf(*arg, sizeof (*arg) - 1, fmt, *(long long*) data); - } else if (dp->size == sizeof (void*)) { - snprintf(*arg, sizeof (*arg) - 1, "0x%p", *(void**) data); +#endif } else { snprintf(*arg, sizeof (*arg) - 1, "%s", ""); } From d756a2f8585a2059889766a1e555b8418755949a Mon Sep 17 00:00:00 2001 From: Snaipe Date: Sat, 5 Sep 2015 15:28:44 +0200 Subject: [PATCH 029/174] Started to take another try for MSVC compatibility --- include/criterion/common.h | 44 +++++++++++++++++++++++++++++++++-- include/criterion/criterion.h | 8 +++---- 2 files changed, 46 insertions(+), 6 deletions(-) diff --git a/include/criterion/common.h b/include/criterion/common.h index 3a8d3a84..2a1a630a 100644 --- a/include/criterion/common.h +++ b/include/criterion/common.h @@ -24,18 +24,50 @@ #ifndef CRITERION_COMMON_H_ # define CRITERION_COMMON_H_ +# define CR_EXPAND(x) x + +# if defined(_MSC_VER) +# if _MSC_VER < 1900 +# error \ + Your version of MSVC++ is too old, please compile your tests using \ + a c99 compiler, like MinGW or MSVC 14.0+ (Included in visual studio \ + 2015) +# endif +# endif + +# ifndef CR_IS_MSVC +# ifdef _MSC_VER +# define CR_IS_MSVC _MSC_VER +# else +# define CR_IS_MSVC 0 +# endif +# 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) __attribute__((section("__DATA," Name))) +# define 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) \ + __pragma(data_seg(push)) \ + __pragma(section(Name, read)) \ + __declspec(allocate(Name)) +# define 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) __attribute__((section(Name))) +# define SECTION_SUFFIX_ # endif # define MAKE_IDENTIFIER_(Prefix, Id) MAKE_IDENTIFIER__(Prefix, Id) @@ -56,8 +88,16 @@ Type *const SECTION_START(Name) = &SECTION_START_(Name); \ Type *const SECTION_END(Name) = &SECTION_END_(Name) -# define UNUSED __attribute__((unused)) -# define NORETURN __attribute__((noreturn)) +# ifdef __GNUC__ +# define UNUSED __attribute__((unused)) +# define NORETURN __attribute__((noreturn)) +# elif CR_IS_MSVC +# define UNUSED +# define NORETURN __declspec(noreturn) +# else +# define UNUSED +# define NORETURN +# endif # ifdef _WIN32 # define SIZE_T_FORMAT "%Iu" diff --git a/include/criterion/criterion.h b/include/criterion/criterion.h index c26ad266..e68f8412 100644 --- a/include/criterion/criterion.h +++ b/include/criterion/criterion.h @@ -36,7 +36,7 @@ # define SUITE_IDENTIFIER_(Name, Suffix) \ suite_ ## Name ## _ ## Suffix -# define Test(...) Test_(__VA_ARGS__, .sentinel_ = 0) +# 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) = { \ @@ -51,10 +51,10 @@ .category = #Category, \ .test = IDENTIFIER_(Category, Name, impl), \ .data = &IDENTIFIER_(Category, Name, extra) \ - }; \ + } SECTION_SUFFIX_; \ TEST_PROTOTYPE_(Category, Name) -# define TestSuite(...) TestSuite_(__VA_ARGS__, .sentinel_ = 0) +# define TestSuite(...) CR_EXPAND(TestSuite_(__VA_ARGS__, .sentinel_ = 0)) # define TestSuite_(Name, ...) \ struct criterion_test_extra_data SUITE_IDENTIFIER_(Name, extra) = { \ .file_ = __FILE__, \ @@ -65,7 +65,7 @@ const struct criterion_suite SUITE_IDENTIFIER_(Name, meta) = { \ .name = #Name, \ .data = &SUITE_IDENTIFIER_(Name, extra), \ - } + } SECTION_SUFFIX_ int criterion_run_all_tests(void); From 09661568d780cd325f8cb4942cb42a551fbc6d1e Mon Sep 17 00:00:00 2001 From: Snaipe Date: Sat, 5 Sep 2015 17:48:11 +0200 Subject: [PATCH 030/174] Added .def file generation on windows --- CMakeLists.txt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index a7bf973a..3c5f4f7a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -136,6 +136,12 @@ if (COVERALLS) coveralls_setup("${SOURCE_FILES}" ${COVERALLS_UPLOAD}) endif() +if (WIN32) + set_target_properties(criterion PROPERTIES LINK_FLAGS + "-Wl,--output-def,${LIBRARY_OUTPUT_PATH}/libcriterion.def") + install(FILES ${LIBRARY_OUTPUT_PATH}/libcriterion.def DESTINATION lib) +endif () + install(FILES ${INTERFACE_FILES} DESTINATION include/criterion) install(TARGETS criterion RUNTIME DESTINATION bin From 6b3ba2f1bb5db02ec927af09bfac351d80f7bdcf Mon Sep 17 00:00:00 2001 From: Snaipe Date: Sat, 5 Sep 2015 08:58:46 -0700 Subject: [PATCH 031/174] Fixed .def output path --- CMakeLists.txt | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 3c5f4f7a..63388cfd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -44,13 +44,13 @@ 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) -endif () +#find_package(Gettext) +#find_package(Libintl) +#if (GETTEXT_FOUND AND LIBINTL_LIB_FOUND) +# include(GettextTranslate) +# add_subdirectory(po) +# set(ENABLE_NLS 1) +#endif () include(CheckLibraryExists) CHECK_LIBRARY_EXISTS(rt clock_gettime "time.h" HAVE_CLOCK_GETTIME) @@ -138,8 +138,8 @@ endif() if (WIN32) set_target_properties(criterion PROPERTIES LINK_FLAGS - "-Wl,--output-def,${LIBRARY_OUTPUT_PATH}/libcriterion.def") - install(FILES ${LIBRARY_OUTPUT_PATH}/libcriterion.def DESTINATION lib) + "-Wl,--output-def,${CMAKE_CURRENT_BINARY_DIR}/libcriterion.def") + install(FILES ${CMAKE_CURRENT_BINARY_DIR}/libcriterion.def DESTINATION lib) endif () install(FILES ${INTERFACE_FILES} DESTINATION include/criterion) From e8e81a7dd58191a7962f10f253865d84b8842718 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Sat, 5 Sep 2015 10:08:59 -0700 Subject: [PATCH 032/174] Added expansion round on __VA_ARGS__ in assert macros for MSVC compatibility --- include/criterion/assert.h | 136 ++++++++++++++++++------------------- 1 file changed, 68 insertions(+), 68 deletions(-) diff --git a/include/criterion/assert.h b/include/criterion/assert.h index 5e7f6168..6d796b26 100644 --- a/include/criterion/assert.h +++ b/include/criterion/assert.h @@ -72,150 +72,150 @@ struct criterion_assert_args { .msg = (Message) \ ) -# define cr_assert(...) cr_assert_(__VA_ARGS__, .sentinel_ = 0) +# define cr_assert(...) CR_EXPAND(cr_assert_(__VA_ARGS__, .sentinel_ = 0)) -# define cr_expect(...) cr_expect_(__VA_ARGS__, .sentinel_ = 0) +# define cr_expect(...) CR_EXPAND(cr_expect_(__VA_ARGS__, .sentinel_ = 0)) -# define cr_assert_(Condition, ...) cr_assert_impl(FATAL, Condition, __VA_ARGS__) -# define cr_expect_(Condition, ...) cr_assert_impl(NORMAL, Condition, __VA_ARGS__) +# define cr_assert_(Condition, ...) CR_EXPAND(cr_assert_impl(FATAL, Condition, __VA_ARGS__)) +# define cr_expect_(Condition, ...) CR_EXPAND(cr_assert_impl(NORMAL, Condition, __VA_ARGS__)) -# define cr_assert_not(...) cr_assert_not_(__VA_ARGS__, .sentinel_ = 0) -# define cr_expect_not(...) cr_expect_not_(__VA_ARGS__, .sentinel_ = 0) +# define cr_assert_not(...) CR_EXPAND(cr_assert_not_(__VA_ARGS__, .sentinel_ = 0)) +# define cr_expect_not(...) CR_EXPAND(cr_expect_not_(__VA_ARGS__, .sentinel_ = 0)) # define cr_assert_not_(Condition, ...) \ - cr_assert_impl(FATAL, !(Condition), __VA_ARGS__) + CR_EXPAND(cr_assert_impl(FATAL, !(Condition), __VA_ARGS__)) # define cr_expect_not_(Condition, ...) \ - cr_expect_impl(NORMAL, !(Condition), __VA_ARGS__) + CR_EXPAND(cr_expect_impl(NORMAL, !(Condition), __VA_ARGS__)) // Native asserts # define cr_assert_op_(Op, Actual, Expected, ...) \ - cr_assert_impl(FATAL, (Actual) Op (Expected), __VA_ARGS__) + CR_EXPAND(cr_assert_impl(FATAL, (Actual) Op (Expected), __VA_ARGS__)) # define cr_expect_op_(Op, Actual, Expected, ...) \ - cr_assert_impl(NORMAL, (Actual) Op (Expected), __VA_ARGS__) + CR_EXPAND(cr_assert_impl(NORMAL, (Actual) Op (Expected), __VA_ARGS__)) -# define cr_assert_eq(...) cr_assert_op_(==, __VA_ARGS__, .sentinel_ = 0) -# define cr_expect_eq(...) cr_expect_op_(==, __VA_ARGS__, .sentinel_ = 0) +# define cr_assert_eq(...) CR_EXPAND(cr_assert_op_(==, __VA_ARGS__, .sentinel_ = 0)) +# define cr_expect_eq(...) CR_EXPAND(cr_expect_op_(==, __VA_ARGS__, .sentinel_ = 0)) -# define cr_assert_neq(...) cr_assert_op_(!=, __VA_ARGS__, .sentinel_ = 0) -# define cr_expect_neq(...) cr_expect_op_(!=, __VA_ARGS__, .sentinel_ = 0) +# define cr_assert_neq(...) CR_EXPAND(cr_assert_op_(!=, __VA_ARGS__, .sentinel_ = 0)) +# define cr_expect_neq(...) CR_EXPAND(cr_expect_op_(!=, __VA_ARGS__, .sentinel_ = 0)) -# define cr_assert_lt(...) cr_assert_op_(<, __VA_ARGS__, .sentinel_ = 0) -# define cr_expect_lt(...) cr_expect_op_(<, __VA_ARGS__, .sentinel_ = 0) +# define cr_assert_lt(...) CR_EXPAND(cr_assert_op_(<, __VA_ARGS__, .sentinel_ = 0)) +# define cr_expect_lt(...) CR_EXPAND(cr_expect_op_(<, __VA_ARGS__, .sentinel_ = 0)) -# define cr_assert_gt(...) cr_assert_op_(>, __VA_ARGS__, .sentinel_ = 0) -# define cr_expect_gt(...) cr_expect_op_(>, __VA_ARGS__, .sentinel_ = 0) +# define cr_assert_gt(...) CR_EXPAND(cr_assert_op_(>, __VA_ARGS__, .sentinel_ = 0)) +# define cr_expect_gt(...) CR_EXPAND(cr_expect_op_(>, __VA_ARGS__, .sentinel_ = 0)) -# define cr_assert_leq(...) cr_assert_op_(<=, __VA_ARGS__, .sentinel_ = 0) -# define cr_expect_leq(...) cr_expect_op_(<=, __VA_ARGS__, .sentinel_ = 0) +# define cr_assert_leq(...) CR_EXPAND(cr_assert_op_(<=, __VA_ARGS__, .sentinel_ = 0)) +# define cr_expect_leq(...) CR_EXPAND(cr_expect_op_(<=, __VA_ARGS__, .sentinel_ = 0)) -# define cr_assert_geq(...) cr_assert_op_(>=, __VA_ARGS__, .sentinel_ = 0) -# define cr_expect_geq(...) cr_expect_op_(>=, __VA_ARGS__, .sentinel_ = 0) +# define cr_assert_geq(...) CR_EXPAND(cr_assert_op_(>=, __VA_ARGS__, .sentinel_ = 0)) +# define cr_expect_geq(...) CR_EXPAND(cr_expect_op_(>=, __VA_ARGS__, .sentinel_ = 0)) # define cr_assert_null_(Value, ...) \ - cr_assert_impl(FATAL, (Value) == NULL, __VA_ARGS__) + CR_EXPAND(cr_assert_impl(FATAL, (Value) == NULL, __VA_ARGS__)) # define cr_expect_null_(Value, ...) \ - cr_assert_impl(NORMAL, (Value) == NULL, __VA_ARGS__) + CR_EXPAND(cr_assert_impl(NORMAL, (Value) == NULL, __VA_ARGS__)) -# define cr_assert_null(...) cr_assert_null_(__VA_ARGS__, .sentinel_ = 0) -# define cr_expect_null(...) cr_expect_null_(__VA_ARGS__, .sentinel_ = 0) +# define cr_assert_null(...) CR_EXPAND(cr_assert_null_(__VA_ARGS__, .sentinel_ = 0)) +# define cr_expect_null(...) CR_EXPAND(cr_expect_null_(__VA_ARGS__, .sentinel_ = 0)) # define cr_assert_not_null_(Value, ...) \ - cr_assert_impl(FATAL, (Value) != NULL, __VA_ARGS__) + CR_EXPAND(cr_assert_impl(FATAL, (Value) != NULL, __VA_ARGS__)) # define cr_expect_not_null_(Value, ...) \ - cr_assert_impl(NORMAL, (Value) != NULL, __VA_ARGS__) + CR_EXPAND(cr_assert_impl(NORMAL, (Value) != NULL, __VA_ARGS__)) -# define cr_assert_not_null(...) cr_assert_not_null_(__VA_ARGS__, .sentinel_ = 0) -# define cr_expect_not_null(...) cr_expect_not_null_(__VA_ARGS__, .sentinel_ = 0) +# define cr_assert_not_null(...) CR_EXPAND(cr_assert_not_null_(__VA_ARGS__, .sentinel_ = 0)) +# define cr_expect_not_null(...) CR_EXPAND(cr_expect_not_null_(__VA_ARGS__, .sentinel_ = 0)) // Floating-point asserts # define cr_assert_float_eq(...) \ - cr_assert_float_eq_(__VA_ARGS__, .sentinel_ = 0) + CR_EXPAND(cr_assert_float_eq_(__VA_ARGS__, .sentinel_ = 0)) # define cr_expect_float_eq(...) \ - cr_expect_float_eq_(__VA_ARGS__, .sentinel_ = 0) + CR_EXPAND(cr_expect_float_eq_(__VA_ARGS__, .sentinel_ = 0)) # define cr_assert_float_eq_(Actual, Expected, Epsilon, ...) \ - cr_assert_impl(FATAL, (Expected) - (Actual) <= (Epsilon) \ + CR_EXPAND(cr_assert_impl(FATAL, (Expected) - (Actual) <= (Epsilon) \ && (Actual) - (Expected) <= (Epsilon), \ - __VA_ARGS__) + __VA_ARGS__)) # define cr_expect_float_eq_(Actual, Expected, Epsilon, ...) \ - cr_assert_impl(NORMAL, (Expected) - (Actual) <= (Epsilon) \ + CR_EXPAND(cr_assert_impl(NORMAL, (Expected) - (Actual) <= (Epsilon) \ && (Actual) - (Expected) <= (Epsilon), \ - __VA_ARGS__) + __VA_ARGS__)) # define cr_assert_float_neq(...) \ - cr_assert_float_neq_(__VA_ARGS__, .sentinel_ = 0) + CR_EXPAND(cr_assert_float_neq_(__VA_ARGS__, .sentinel_ = 0)) # define cr_expect_float_neq(...) \ - cr_expect_float_neq_(__VA_ARGS__, .sentinel_ = 0) + CR_EXPAND(cr_expect_float_neq_(__VA_ARGS__, .sentinel_ = 0)) # define cr_assert_float_neq_(Actual, Expected, Epsilon, ...) \ - cr_assert_impl(FATAL, (Expected) - (Actual) > (Epsilon) \ + CR_EXPAND(cr_assert_impl(FATAL, (Expected) - (Actual) > (Epsilon) \ || (Actual) - (Expected) > (Epsilon), \ - __VA_ARGS__) + __VA_ARGS__)) # define cr_expect_float_neq_(Actual, Expected, Epsilon, ...) \ - cr_assert_impl(NORMAL, (Expected) - (Actual) > (Epsilon) \ + CR_EXPAND(cr_assert_impl(NORMAL, (Expected) - (Actual) > (Epsilon) \ || (Actual) - (Expected) > (Epsilon), \ - __VA_ARGS__) + __VA_ARGS__)) // String asserts # define cr_assert_strings_(Op, Actual, Expected, ...) \ - cr_assert_impl(FATAL, strcmp((Actual), (Expected)) Op 0, __VA_ARGS__) + CR_EXPAND(cr_assert_impl(FATAL, strcmp((Actual), (Expected)) Op 0, __VA_ARGS__)) # define cr_expect_strings_(Op, Actual, Expected, ...) \ - cr_assert_impl(NORMAL, strcmp((Actual), (Expected)) Op 0, __VA_ARGS__) + CR_EXPAND(cr_assert_impl(NORMAL, strcmp((Actual), (Expected)) Op 0, __VA_ARGS__)) # define cr_assert_strings_eq(...) \ - cr_assert_strings_(==, __VA_ARGS__, .sentinel_ = 0) + CR_EXPAND(cr_assert_strings_(==, __VA_ARGS__, .sentinel_ = 0)) # define cr_expect_strings_eq(...) \ - cr_expect_strings_(==, __VA_ARGS__, .sentinel_ = 0) + CR_EXPAND(cr_expect_strings_(==, __VA_ARGS__, .sentinel_ = 0)) # define cr_assert_strings_neq(...) \ - cr_assert_strings_(!=, __VA_ARGS__, .sentinel_ = 0) + CR_EXPAND(cr_assert_strings_(!=, __VA_ARGS__, .sentinel_ = 0)) # define cr_expect_strings_neq(...) \ - cr_expect_strings_(!=, __VA_ARGS__, .sentinel_ = 0) + CR_EXPAND(cr_expect_strings_(!=, __VA_ARGS__, .sentinel_ = 0)) -# define cr_assert_strings_gt(...) cr_assert_strings_(>, __VA_ARGS__, .sentinel_ = 0) -# define cr_expect_strings_gt(...) cr_expect_strings_(>, __VA_ARGS__, .sentinel_ = 0) +# define cr_assert_strings_gt(...) CR_EXPAND(cr_assert_strings_(>, __VA_ARGS__, .sentinel_ = 0)) +# define cr_expect_strings_gt(...) CR_EXPAND(cr_expect_strings_(>, __VA_ARGS__, .sentinel_ = 0)) -# define cr_assert_strings_lt(...) cr_assert_strings_(<, __VA_ARGS__, .sentinel_ = 0) -# define cr_expect_strings_lt(...) cr_expect_strings_(<, __VA_ARGS__, .sentinel_ = 0) +# define cr_assert_strings_lt(...) CR_EXPAND(cr_assert_strings_(<, __VA_ARGS__, .sentinel_ = 0)) +# define cr_expect_strings_lt(...) CR_EXPAND(cr_expect_strings_(<, __VA_ARGS__, .sentinel_ = 0)) -# define cr_assert_strings_leq(...) cr_assert_strings_(<=, __VA_ARGS__, .sentinel_ = 0) -# define cr_expect_strings_leq(...) cr_expect_strings_(<=, __VA_ARGS__, .sentinel_ = 0) +# define cr_assert_strings_leq(...) CR_EXPAND(cr_assert_strings_(<=, __VA_ARGS__, .sentinel_ = 0)) +# define cr_expect_strings_leq(...) CR_EXPAND(cr_expect_strings_(<=, __VA_ARGS__, .sentinel_ = 0)) -# define cr_assert_strings_geq(...) cr_assert_strings_(>=, __VA_ARGS__, .sentinel_ = 0) -# define cr_expect_strings_geq(...) cr_expect_strings_(>=, __VA_ARGS__, .sentinel_ = 0) +# define cr_assert_strings_geq(...) CR_EXPAND(cr_assert_strings_(>=, __VA_ARGS__, .sentinel_ = 0)) +# define cr_expect_strings_geq(...) CR_EXPAND(cr_expect_strings_(>=, __VA_ARGS__, .sentinel_ = 0)) // Array asserts # define cr_assert_arrays_eq(...) \ - cr_assert_arrays_eq_(__VA_ARGS__, .sentinel_ = 0) + CR_EXPAND(cr_assert_arrays_eq_(__VA_ARGS__, .sentinel_ = 0)) # define cr_expect_arrays_eq(...) \ - cr_expect_arrays_eq_(__VA_ARGS__, .sentinel_ = 0) + CR_EXPAND(cr_expect_arrays_eq_(__VA_ARGS__, .sentinel_ = 0)) # define cr_assert_arrays_neq(...) \ - cr_assert_arrays_neq_(__VA_ARGS__, .sentinel_ = 0) + CR_EXPAND(cr_assert_arrays_neq_(__VA_ARGS__, .sentinel_ = 0)) # define cr_expect_arrays_neq(...) \ - cr_expect_arrays_neq_(__VA_ARGS__, .sentinel_ = 0) + CR_EXPAND(cr_expect_arrays_neq_(__VA_ARGS__, .sentinel_ = 0)) # define cr_assert_arrays_eq_(A, B, Size, ...) \ - cr_assert_impl(FATAL, !memcmp((A), (B), (Size)), \ + CR_EXPAND(cr_assert_impl(FATAL, !memcmp((A), (B), (Size)), \ .default_msg = "Arrays are not equal.", \ - __VA_ARGS__) + __VA_ARGS__)) # define cr_expect_arrays_eq_(A, B, Size, ...) \ - cr_assert_impl(NORMAL, !memcmp((A), (B), (Size)), \ + CR_EXPAND(cr_assert_impl(NORMAL, !memcmp((A), (B), (Size)), \ .default_msg = "Arrays are not equal.", \ - __VA_ARGS__) + __VA_ARGS__)) # define cr_assert_arrays_neq_(A, B, Size, ...) \ - cr_assert_impl(FATAL, memcmp((A), (B), (Size)), \ + CR_EXPAND(cr_assert_impl(FATAL, memcmp((A), (B), (Size)), \ .default_msg = "Arrays are equal", \ - __VA_ARGS__) + __VA_ARGS__)) # define cr_expect_arrays_neq_(A, B, Size, ...) \ - cr_assert_impl(NORMAL, memcmp((A), (B), (Size)), \ + CR_EXPAND(cr_assert_impl(NORMAL, memcmp((A), (B), (Size)), \ .default_msg = "Arrays are equal", \ - __VA_ARGS__) + __VA_ARGS__)) # ifdef __GNUC__ # define CRIT_ARR_COMPARE_(A, B, Size, Cmp, Result) \ From 11eb4a9f103e76ceb4367f57789bef84ed5fb418 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Sat, 5 Sep 2015 10:38:24 -0700 Subject: [PATCH 033/174] Added __VA_ARGS__ macro expansions in theories.h for MSVC compatibility --- include/criterion/theories.h | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/include/criterion/theories.h b/include/criterion/theories.h index 7d233c94..3f7cd800 100644 --- a/include/criterion/theories.h +++ b/include/criterion/theories.h @@ -69,15 +69,15 @@ void cr_theory_main(struct criterion_datapoints *dps, size_t datapoints, void (* # define CR_VAARG_ID(Suffix, Category, Name, ...) \ IDENTIFIER_(Category, Name, Suffix) -# define Theory(Args, ...) \ - void CR_VAARG_ID(theory, __VA_ARGS__,)Args; \ - Test_(__VA_ARGS__, .sentinel_ = 0) { \ - cr_theory_main( \ - CR_VAARG_ID(dps, __VA_ARGS__,), \ - CR_NB_DATAPOINTS(CR_VAARG_ID(dps, __VA_ARGS__,)), \ - (void(*)(void)) CR_VAARG_ID(theory, __VA_ARGS__,) \ - ); \ - } \ - void CR_VAARG_ID(theory, __VA_ARGS__,)Args +# define Theory(Args, ...) \ + void CR_EXPAND(CR_VAARG_ID(theory, __VA_ARGS__,))Args; \ + CR_EXPAND(Test_(__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_THEORIES_H_ */ From b9e3923b7c8e7cfa9bce797c219cac7cc16cc209 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Sat, 5 Sep 2015 20:39:44 +0200 Subject: [PATCH 034/174] Removed any usage of GNU C-only macros from libcsptr, using smalloc & sfree directly instead --- src/event.c | 38 +++++++++++++++++++++------------ src/main.c | 6 ++++-- src/ordered-set.c | 14 ++++++++---- src/posix-compat.c | 24 +++++++++++++++------ src/process.c | 23 ++++++++++++++------ src/runner.c | 53 +++++++++++++++++++++++++++++++++------------- src/stats.c | 40 ++++++++++++++++++++++++---------- 7 files changed, 139 insertions(+), 59 deletions(-) diff --git a/src/event.c b/src/event.c index 6907c7c7..38b25b2d 100644 --- a/src/event.c +++ b/src/event.c @@ -23,7 +23,8 @@ */ #include -#include +#include +#include #include "criterion/stats.h" #include "criterion/common.h" #include "criterion/hooks.h" @@ -50,9 +51,12 @@ struct event *read_event(FILE *f) { return NULL; } - return unique_ptr(struct event, - .value = { .kind = kind, .data = buf }, - .dtor = destroy_event); + struct event *ev = smalloc( + .size = sizeof (struct event), + .dtor = destroy_event + ); + *ev = (struct event) { .kind = kind, .data = buf }; + return ev; } case THEORY_FAIL: { size_t *len = malloc(sizeof (size_t)); @@ -69,10 +73,12 @@ struct event *read_event(FILE *f) { } free(len); - return unique_ptr(struct event, - .value = { .kind = kind, .data = buf }, - .dtor = destroy_event); - + struct event *ev = smalloc( + .size = sizeof (struct event), + .dtor = destroy_event + ); + *ev = (struct event) { .kind = kind, .data = buf }; + return ev; } case POST_TEST: { double *elapsed_time = malloc(sizeof (double)); @@ -81,12 +87,18 @@ struct event *read_event(FILE *f) { return NULL; } - return unique_ptr(struct event, - .value = { .kind = kind, .data = elapsed_time }, - .dtor = destroy_event); + struct event *ev = smalloc( + .size = sizeof (struct event), + .dtor = destroy_event + ); + *ev = (struct event) { .kind = kind, .data = elapsed_time }; + return ev; + } + default: { + struct event *ev = smalloc(sizeof (struct event)); + *ev = (struct event) { .kind = kind, .data = NULL }; + return ev; } - default: - return unique_ptr(struct event, { .kind = kind, .data = NULL }); } } diff --git a/src/main.c b/src/main.c index 1faa4a38..a3ca0ac1 100644 --- a/src/main.c +++ b/src/main.c @@ -28,7 +28,7 @@ #include #include #include -#include +#include #include "runner.h" #include "config.h" @@ -90,7 +90,7 @@ bool is_disabled(struct criterion_suite *s, struct criterion_test *t) { } int list_tests(bool unicode) { - smart struct criterion_test_set *set = criterion_init(); + struct criterion_test_set *set = criterion_init(); const char *node = unicode ? UTF8_TREE_NODE : ASCII_TREE_NODE; const char *join = unicode ? UTF8_TREE_JOIN : ASCII_TREE_JOIN; @@ -114,6 +114,8 @@ int list_tests(bool unicode) { is_disabled(&s->suite, t) ? " (disabled)" : ""); } } + + sfree(set); return 0; } diff --git a/src/ordered-set.c b/src/ordered-set.c index 9386b592..3115ca22 100644 --- a/src/ordered-set.c +++ b/src/ordered-set.c @@ -21,9 +21,10 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ +#include #include #include -#include +#include static void destroy_ordered_set(void *ptr, UNUSED void *meta) { sfree(((struct criterion_ordered_set *) ptr)->first); @@ -42,9 +43,14 @@ static void destroy_ordered_set_node(void *ptr, void *meta) { struct criterion_ordered_set *new_ordered_set(f_criterion_cmp cmp, f_destructor dtor) { - return unique_ptr(struct criterion_ordered_set, - .value = { .cmp = cmp, .dtor = dtor }, - .dtor = destroy_ordered_set); + struct criterion_ordered_set *newset = smalloc( + .size = sizeof (struct criterion_ordered_set), + .dtor = destroy_ordered_set + ); + + struct criterion_ordered_set data = { .cmp = cmp, .dtor = dtor }; + memcpy(newset, &data, sizeof (struct criterion_ordered_set)); + return newset; } void *insert_ordered_set(struct criterion_ordered_set *l, diff --git a/src/posix-compat.c b/src/posix-compat.c index 376cd278..cebca75c 100644 --- a/src/posix-compat.c +++ b/src/posix-compat.c @@ -63,7 +63,7 @@ # include #endif -#include +#include struct proc_handle { #ifdef VANILLA_WIN32 @@ -201,14 +201,19 @@ s_proc_handle *fork_process() { UnmapViewOfFile(ctx); CloseHandle(sharedMem); - return unique_ptr(s_proc_handle, { info.hProcess }); + s_proc_handle *handle = smalloc(sizeof (s_proc_handle)); + *handle = (s_proc_handle) { info.hProcess }; + return handle; #else pid_t pid = fork(); if (pid == -1) return (void *) -1; if (pid == 0) return NULL; - return unique_ptr(s_proc_handle, { pid }); + + s_proc_handle *handle = smalloc(sizeof (s_proc_handle)); + *handle = (s_proc_handle) { pid }; + return handle; #endif } @@ -294,6 +299,7 @@ FILE *pipe_out(s_pipe_handle *p) { } s_pipe_handle *stdpipe() { + s_pipe_handle *handle = smalloc(sizeof (s_pipe_handle)); #ifdef VANILLA_WIN32 HANDLE fhs[2]; SECURITY_ATTRIBUTES attr = { @@ -302,21 +308,25 @@ s_pipe_handle *stdpipe() { }; if (!CreatePipe(fhs, fhs + 1, &attr, 0)) return NULL; - return unique_ptr(s_pipe_handle, {{ fhs[0], fhs[1] }}); + *handle = (s_pipe_handle) {{ fhs[0], fhs[1] }}; + return handle; #else int fds[2] = { -1, -1 }; if (pipe(fds) == -1) return NULL; - return unique_ptr(s_pipe_handle, {{ fds[0], fds[1] }}); + *handle = (s_pipe_handle) {{ fds[0], fds[1] }}; + return handle; #endif } s_proc_handle *get_current_process() { + s_proc_handle *handle = smalloc(sizeof (s_proc_handle)); #ifdef VANILLA_WIN32 - return unique_ptr(s_proc_handle, { GetCurrentProcess() }); + *handle = (s_proc_handle) { GetCurrentProcess() }; #else - return unique_ptr(s_proc_handle, { getpid() }); + *handle = (s_proc_handle) { getpid() }; #endif + return handle; } bool is_current_process(s_proc_handle *proc) { diff --git a/src/process.c b/src/process.c index d3a5f9e9..036b790b 100644 --- a/src/process.c +++ b/src/process.c @@ -23,7 +23,7 @@ */ #include #include -#include +#include #include "criterion/types.h" #include "criterion/options.h" @@ -76,7 +76,7 @@ void run_worker(struct worker_context *ctx) { struct process *spawn_test_worker(struct criterion_test *test, struct criterion_suite *suite, f_worker_func func) { - smart s_pipe_handle *pipe = stdpipe(); + s_pipe_handle *pipe = stdpipe(); if (pipe == NULL) abort(); @@ -86,17 +86,26 @@ struct process *spawn_test_worker(struct criterion_test *test, .func = func, .pipe = pipe }; + + struct process *ptr = NULL; + s_proc_handle *proc = fork_process(); if (proc == (void *) -1) { - return NULL; + goto cleanup; } else if (proc == NULL) { run_worker(&g_worker_context); - return NULL; + goto cleanup; } - return unique_ptr(struct process, - .value = { .proc = proc, .in = pipe_in(pipe) }, - .dtor = close_process); + ptr = smalloc( + .size = sizeof (struct process), + .kind = UNIQUE, + .dtor = close_process); + + *ptr = (struct process) { .proc = proc, .in = pipe_in(pipe) }; +cleanup: + sfree(pipe); + return ptr; } struct process_status wait_proc(struct process *proc) { diff --git a/src/runner.c b/src/runner.c index 1341fa5b..67f3ed8c 100644 --- a/src/runner.c +++ b/src/runner.c @@ -23,7 +23,7 @@ */ #include #include -#include +#include #include "criterion/criterion.h" #include "criterion/options.h" #include "criterion/ordered-set.h" @@ -104,10 +104,17 @@ struct criterion_test_set *criterion_init(void) { ++nb_tests; } - return unique_ptr(struct criterion_test_set, { + struct criterion_test_set *set = smalloc( + .size = sizeof (struct criterion_test_set), + .dtor = dtor_test_set + ); + + *set = (struct criterion_test_set) { suites, nb_tests, - }, dtor_test_set); + }; + + return set; } typedef void (*f_test_run)(struct criterion_global_stats *, @@ -126,7 +133,7 @@ static void map_tests(struct criterion_test_set *set, report(PRE_SUITE, s); log(pre_suite, s); - smart struct criterion_suite_stats *suite_stats = suite_stats_init(&s->suite); + 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); @@ -135,13 +142,18 @@ static void map_tests(struct criterion_test_set *set, fun(stats, suite_stats, t, &s->suite); if (criterion_options.fail_fast && stats->tests_failed > 0) break; - if (!is_runner()) + 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, @@ -191,19 +203,20 @@ static void run_test(struct criterion_global_stats *stats, struct criterion_test *test, struct criterion_suite *suite) { - smart struct criterion_test_stats *test_stats = test_stats_init(test); + 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 }); - return; + goto cleanup; } - smart struct process *proc = spawn_test_worker(test, suite, run_test_child); + proc = spawn_test_worker(test, suite, run_test_child); if (proc == NULL && !is_runner()) - return; + goto cleanup; bool test_started = false; bool normal_finish = false; @@ -257,7 +270,7 @@ static void run_test(struct criterion_global_stats *stats, test_stats, &(struct event) { .kind = TEST_CRASH }); } - return; + goto cleanup; } test_stats->signal = status.status; if (test->data->signal == 0) { @@ -279,7 +292,7 @@ static void run_test(struct criterion_global_stats *stats, test_stats, &(struct event) { .kind = TEST_CRASH }); } - return; + goto cleanup; } test_stats->exit_code = status.status; if (!normal_finish) { @@ -295,6 +308,10 @@ static void run_test(struct criterion_global_stats *stats, } } } + +cleanup: + sfree(test_stats); + sfree(proc); } #ifdef HAVE_PCRE @@ -321,7 +338,7 @@ static int criterion_run_all_tests_impl(void) { if (resume_child()) // (windows only) resume from the fork return -1; - smart struct criterion_test_set *set = criterion_init(); + struct criterion_test_set *set = criterion_init(); #ifdef HAVE_PCRE if (criterion_options.pattern) disable_unmatching(set); @@ -332,15 +349,21 @@ static int criterion_run_all_tests_impl(void) { fflush(NULL); // flush everything before forking - smart struct criterion_global_stats *stats = stats_init(); + struct criterion_global_stats *stats = stats_init(); map_tests(set, stats, run_test); + int result = is_runner() ? stats->tests_failed == 0 : -1; + if (!is_runner()) - return -1; + goto cleanup; report(POST_ALL, stats); log(post_all, stats); - return stats->tests_failed == 0; + +cleanup: + sfree(set); + sfree(stats); + return result; } int criterion_run_all_tests(void) { diff --git a/src/stats.c b/src/stats.c index cd4a83df..f46b957a 100644 --- a/src/stats.c +++ b/src/stats.c @@ -21,7 +21,8 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -#include +#include +#include #include "criterion/common.h" #include "stats.h" @@ -48,7 +49,12 @@ static void destroy_stats(void *ptr, UNUSED void *meta) { } s_glob_stats *stats_init(void) { - return unique_ptr(s_glob_stats, .dtor = destroy_stats); + s_glob_stats *stats = smalloc( + .size = sizeof (s_glob_stats), + .dtor = destroy_stats + ); + *stats = (s_glob_stats) { .suites = NULL }; + return stats; } static void destroy_suite_stats(void *ptr, UNUSED void *meta) { @@ -60,9 +66,13 @@ static void destroy_suite_stats(void *ptr, UNUSED void *meta) { } s_suite_stats *suite_stats_init(struct criterion_suite *s) { - return shared_ptr(s_suite_stats, { - .suite = s, - }, destroy_suite_stats); + s_suite_stats *stats = smalloc( + .size = sizeof (s_suite_stats), + .kind = SHARED, + .dtor = destroy_suite_stats + ); + *stats = (s_suite_stats) { .suite = s }; + return stats; } static void destroy_test_stats(void *ptr, UNUSED void *meta) { @@ -74,11 +84,17 @@ static void destroy_test_stats(void *ptr, UNUSED void *meta) { } s_test_stats *test_stats_init(struct criterion_test *t) { - return shared_ptr(s_test_stats, { - .test = t, - .progress = t->data->line_, - .file = t->data->file_ - }, destroy_test_stats); + s_test_stats *stats = smalloc( + .size = sizeof (s_test_stats), + .kind = SHARED, + .dtor = destroy_test_stats + ); + *stats = (s_test_stats) { + .test = t, + .progress = t->data->line_, + .file = t->data->file_ + }; + return stats; } void stat_push_event(s_glob_stats *stats, @@ -140,7 +156,9 @@ static void push_assert(s_glob_stats *stats, s_suite_stats *suite, s_test_stats *test, s_assert_stats *data) { - s_assert_stats *dup = unique_ptr(s_assert_stats, (*data)); + s_assert_stats *dup = smalloc(sizeof (s_assert_stats)); + memcpy(dup, data, sizeof (s_assert_stats)); + dup->next = test->asserts; test->asserts = dup; From 289731d47d255dc4a2f366ba7add39de52c3fe8b Mon Sep 17 00:00:00 2001 From: Snaipe Date: Sat, 5 Sep 2015 21:02:16 +0200 Subject: [PATCH 035/174] Update libcsptr to allow MSVC compilation --- .cmake/Modules/Submodules.cmake | 2 +- dependencies/libcsptr | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.cmake/Modules/Submodules.cmake b/.cmake/Modules/Submodules.cmake index 7c251394..d5b2cbab 100644 --- a/.cmake/Modules/Submodules.cmake +++ b/.cmake/Modules/Submodules.cmake @@ -10,7 +10,7 @@ set(GIT_SUBMODULES libcsptr dyncall) ### set each submodules's commit or tag that is to be checked out ### (leave empty if you want master) -set(GIT_SUBMODULE_VERSION_libcsptr 04cd477) +set(GIT_SUBMODULE_VERSION_libcsptr a233d68) set(GIT_SUBMODULE_VERSION_dyncall 68c57f6) ### First, get all submodules in diff --git a/dependencies/libcsptr b/dependencies/libcsptr index 04cd477d..a233d686 160000 --- a/dependencies/libcsptr +++ b/dependencies/libcsptr @@ -1 +1 @@ -Subproject commit 04cd477d1f213e55d2ddecab2fcd52d1c7865dfa +Subproject commit a233d686bc6135bc8b96489364fc65ee2a25b297 From 4aa7c0729591d88474de585e4650b1a5e4ba3c22 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Sat, 5 Sep 2015 21:06:18 +0200 Subject: [PATCH 036/174] Made the samples compile with MSVC --- samples/CMakeLists.txt | 4 +++- samples/asserts.c | 8 +++++--- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/samples/CMakeLists.txt b/samples/CMakeLists.txt index 7767a427..5bdb8423 100644 --- a/samples/CMakeLists.txt +++ b/samples/CMakeLists.txt @@ -1,4 +1,6 @@ -set(CMAKE_C_FLAGS "-std=c99 -Wall -Wextra -pedantic") +if (NOT MSVC) + set(CMAKE_C_FLAGS "-std=c99 -Wall -Wextra -pedantic") +endif () include_directories(../include) diff --git a/samples/asserts.c b/samples/asserts.c index 627f7787..6b44cb90 100644 --- a/samples/asserts.c +++ b/samples/asserts.c @@ -64,6 +64,10 @@ Test(asserts, array) { int arr1[] = {1, 2, 3, 4}; int arr2[] = {4, 3, 2, 1}; + cr_assert_arrays_eq(arr1, arr1, 4); + cr_assert_arrays_neq(arr1, arr2, 4); + +#ifdef __GNUC__ struct dummy_struct s1[] = {{4, 2}, {2, 4}}; struct dummy_struct s2[2]; memset(s2, 0xFF, sizeof(s2)); @@ -72,9 +76,7 @@ Test(asserts, array) { s2[1].a = 2; s2[1].b = 4; - cr_assert_arrays_eq(arr1, arr1, 4); - cr_assert_arrays_neq(arr1, arr2, 4); - cr_assert_arrays_neq(s1, s2, 2); cr_assert_arrays_eq_cmp(s1, s2, 2, eq_dummy); +#endif } From c56776b976b0fff331ab5581a55183a1e5ae93db Mon Sep 17 00:00:00 2001 From: Snaipe Date: Sat, 5 Sep 2015 21:25:42 +0200 Subject: [PATCH 037/174] Updated libcsptr to latest --- .cmake/Modules/Submodules.cmake | 2 +- dependencies/libcsptr | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.cmake/Modules/Submodules.cmake b/.cmake/Modules/Submodules.cmake index d5b2cbab..8ab963c8 100644 --- a/.cmake/Modules/Submodules.cmake +++ b/.cmake/Modules/Submodules.cmake @@ -10,7 +10,7 @@ set(GIT_SUBMODULES libcsptr dyncall) ### set each submodules's commit or tag that is to be checked out ### (leave empty if you want master) -set(GIT_SUBMODULE_VERSION_libcsptr a233d68) +set(GIT_SUBMODULE_VERSION_libcsptr 5bf0ad5) set(GIT_SUBMODULE_VERSION_dyncall 68c57f6) ### First, get all submodules in diff --git a/dependencies/libcsptr b/dependencies/libcsptr index a233d686..5bf0ad57 160000 --- a/dependencies/libcsptr +++ b/dependencies/libcsptr @@ -1 +1 @@ -Subproject commit a233d686bc6135bc8b96489364fc65ee2a25b297 +Subproject commit 5bf0ad57051a5b29d12b4daab8b233d1943c1085 From 1e9a635b97c8e69cae8723e64475f00140fe358e Mon Sep 17 00:00:00 2001 From: Snaipe Date: Sat, 5 Sep 2015 21:42:31 +0200 Subject: [PATCH 038/174] Removed commit hashes in Submodule.cmake and updated libcsptr to latest --- .cmake/Modules/Submodules.cmake | 2 -- dependencies/libcsptr | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/.cmake/Modules/Submodules.cmake b/.cmake/Modules/Submodules.cmake index 8ab963c8..5183368e 100644 --- a/.cmake/Modules/Submodules.cmake +++ b/.cmake/Modules/Submodules.cmake @@ -10,8 +10,6 @@ set(GIT_SUBMODULES libcsptr dyncall) ### set each submodules's commit or tag that is to be checked out ### (leave empty if you want master) -set(GIT_SUBMODULE_VERSION_libcsptr 5bf0ad5) -set(GIT_SUBMODULE_VERSION_dyncall 68c57f6) ### First, get all submodules in if(${GIT_SUBMODULES_CHECKOUT_QUIET}) diff --git a/dependencies/libcsptr b/dependencies/libcsptr index 5bf0ad57..530fb9d0 160000 --- a/dependencies/libcsptr +++ b/dependencies/libcsptr @@ -1 +1 @@ -Subproject commit 5bf0ad57051a5b29d12b4daab8b233d1943c1085 +Subproject commit 530fb9d001a4ae9303816f30de6c3bf6b3084c7c From ad6f03bf7a18e5b285d58eb25b56b60518b7dee8 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Sat, 5 Sep 2015 21:58:57 +0200 Subject: [PATCH 039/174] Updated libcsptr to latest --- dependencies/libcsptr | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencies/libcsptr b/dependencies/libcsptr index 530fb9d0..d7be0399 160000 --- a/dependencies/libcsptr +++ b/dependencies/libcsptr @@ -1 +1 @@ -Subproject commit 530fb9d001a4ae9303816f30de6c3bf6b3084c7c +Subproject commit d7be0399f8eed62b73dd8d32a8c0708b1e78059f From 4817fb709f77b7af5525e09eff31bdf1bda33cc9 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Sat, 5 Sep 2015 22:22:08 +0200 Subject: [PATCH 040/174] Updated libcsptr for latest msvc compatibility --- dependencies/libcsptr | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencies/libcsptr b/dependencies/libcsptr index d7be0399..2762164a 160000 --- a/dependencies/libcsptr +++ b/dependencies/libcsptr @@ -1 +1 @@ -Subproject commit d7be0399f8eed62b73dd8d32a8c0708b1e78059f +Subproject commit 2762164acfaa712fea7dec6ed760ff88f7d2e026 From 95539c89adbaaa233a83cd374d23cf1d2acd4451 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Sat, 5 Sep 2015 22:58:45 +0200 Subject: [PATCH 041/174] Removed VLA and ?: GNU extension occurences --- src/common.h | 37 +++++++++++++++++++++++++++++++++++++ src/event.c | 3 ++- src/extmatch.c | 13 +++++++------ src/i18n.c | 5 ++--- src/i18n.h | 2 ++ src/log/normal.c | 6 ++---- src/log/tap.c | 8 ++++---- src/main.c | 19 ++++++++++--------- src/ordered-set.c | 6 +++--- src/report.c | 2 +- src/report.h | 4 +++- src/runner.c | 19 ++++++++++--------- src/stats.c | 4 ++-- 13 files changed, 85 insertions(+), 43 deletions(-) create mode 100644 src/common.h diff --git a/src/common.h b/src/common.h new file mode 100644 index 00000000..b9add0be --- /dev/null +++ b/src/common.h @@ -0,0 +1,37 @@ +/* + * 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 COMMON_H_ +# define COMMON_H_ + +#ifdef __GNUC__ +# define INLINE __attribute__((always_inline)) inline +#elif defined(_MSC_VER) +# define INLINE __forceinline +#else +# define INLINE +#endif + +# define DEF(X, Y) ((X) ? (X) : (Y)) + +#endif /* !COMMON_H_ */ diff --git a/src/event.c b/src/event.c index 38b25b2d..83a92e0d 100644 --- a/src/event.c +++ b/src/event.c @@ -103,9 +103,10 @@ struct event *read_event(FILE *f) { } void send_event(int kind, void *data, size_t size) { - unsigned char buf[sizeof (int) + size]; + unsigned char *buf = malloc(sizeof (int) + size); memcpy(buf, &kind, sizeof (int)); memcpy(buf + sizeof (int), data, size); if (fwrite(buf, sizeof (int) + size, 1, g_event_pipe) == 0) abort(); + free(buf); } diff --git a/src/extmatch.c b/src/extmatch.c index 604d4183..79a7ad30 100644 --- a/src/extmatch.c +++ b/src/extmatch.c @@ -28,6 +28,7 @@ #include #include "criterion/common.h" +#include "common.h" struct context { int depth; @@ -107,20 +108,20 @@ static int is_eos(struct context *ctx) { static inline void handle_special(struct context *ctx, handler_arg strs[5]) { if (peek_char(ctx) == '(') { - if ((strs[0].validator ?: inactive)(ctx)) + if (DEF(strs[0].validator, inactive)(ctx)) copy_str(ctx, strs[0].str); dup_char(ctx); - if ((strs[1].validator ?: inactive)(ctx)) + if (DEF(strs[1].validator, inactive)(ctx)) copy_str(ctx, strs[1].str); transform_rec(ctx); - if ((strs[2].validator ?: inactive)(ctx)) + if (DEF(strs[2].validator, inactive)(ctx)) copy_str(ctx,strs[2].str); copy_char(ctx, ')'); - if ((strs[3].validator ?: inactive)(ctx)) + if (DEF(strs[3].validator, inactive)(ctx)) copy_str(ctx, strs[3].str); - } else if ((strs[4].validator ?: inactive)(ctx)) { + } else if (DEF(strs[4].validator, inactive)(ctx)) { copy_str(ctx, strs[4].str); } } @@ -191,7 +192,7 @@ void transform_impl(struct context *ctx) { if (c == ')' && ctx->depth > 0) return; - (handler ?: copy_char)(ctx, c); + (handler ? handler : copy_char)(ctx, c); if (ctx->eos) return; diff --git a/src/i18n.c b/src/i18n.c index 5b9899b4..7a7c51bb 100644 --- a/src/i18n.c +++ b/src/i18n.c @@ -1,8 +1,7 @@ #include "i18n.h" -#if ENABLE_NLS -__attribute__ ((constructor)) void init_i18n(void) { +#if ENABLE_NLS bindtextdomain (PACKAGE, LOCALEDIR); -} #endif +} diff --git a/src/i18n.h b/src/i18n.h index 74c159ec..2657c1e9 100644 --- a/src/i18n.h +++ b/src/i18n.h @@ -13,4 +13,6 @@ dngettext(PACKAGE, String, Plural, (Quantity)) # endif +void init_i18n(void); + #endif /* !I18N_H_ */ diff --git a/src/log/normal.c b/src/log/normal.c index 81160335..1ce002cb 100644 --- a/src/log/normal.c +++ b/src/log/normal.c @@ -34,8 +34,7 @@ #include "config.h" #include "i18n.h" #include "posix-compat.h" - -#define USED __attribute__ ((used)) +#include "common.h" #ifdef VANILLA_WIN32 // fallback to strtok on windows since strtok_s is not available everywhere @@ -119,8 +118,7 @@ void normal_log_post_test(struct criterion_test_stats *stats) { stats->elapsed_time); } -__attribute__((always_inline)) -static inline bool is_disabled(struct criterion_test *t, +static INLINE bool is_disabled(struct criterion_test *t, struct criterion_suite *s) { return t->data->disabled || (s->data && s->data->disabled); } diff --git a/src/log/tap.c b/src/log/tap.c index 23898f46..b406ba33 100644 --- a/src/log/tap.c +++ b/src/log/tap.c @@ -32,6 +32,7 @@ #include "timer.h" #include "config.h" #include "posix-compat.h" +#include "common.h" void tap_log_pre_all(struct criterion_test_set *set) { size_t enabled_count = 0; @@ -54,8 +55,7 @@ void tap_log_pre_suite(struct criterion_suite_set *set) { set->suite.name); } -__attribute__((always_inline)) -static inline bool is_disabled(struct criterion_test *t, struct criterion_suite *s) { +static INLINE bool is_disabled(struct criterion_test *t, struct criterion_suite *s) { return t->data->disabled || (s->data && s->data->disabled); } @@ -65,7 +65,7 @@ void tap_log_post_suite(struct criterion_suite_stats *stats) { criterion_important("ok - %s::%s %s # SKIP %s is disabled\n", ts->test->category, ts->test->name, - ts->test->data->description ?: "", + DEF(ts->test->data->description, ""), ts->test->data->disabled ? "test" : "suite"); } } @@ -78,7 +78,7 @@ void tap_log_post_test(struct criterion_test_stats *stats) { stats->failed ? "not ok" : "ok", stats->test->category, stats->test->name, - stats->test->data->description ?: "", + DEF(stats->test->data->description, ""), stats->elapsed_time); for (struct criterion_assert_stats *asrt = stats->asserts; asrt; asrt = asrt->next) { if (!asrt->passed) { diff --git a/src/main.c b/src/main.c index a3ca0ac1..7995b346 100644 --- a/src/main.c +++ b/src/main.c @@ -31,6 +31,7 @@ #include #include "runner.h" #include "config.h" +#include "common.h" #if ENABLE_NLS # include @@ -137,8 +138,8 @@ int main(int argc, char *argv[]) { {0, 0, 0, 0 } }; - bool use_ascii = !strcmp("1", getenv("CRITERION_USE_ASCII") ?: "0") - || !strcmp("dumb", getenv("TERM") ?: "dumb"); + bool use_ascii = !strcmp("1", DEF(getenv("CRITERION_USE_ASCII"), "0")) + || !strcmp("dumb", DEF(getenv("TERM"), "dumb")); setlocale(LC_ALL, ""); #if ENABLE_NLS @@ -146,24 +147,24 @@ int main(int argc, char *argv[]) { #endif struct criterion_options *opt = &criterion_options; - opt->always_succeed = !strcmp("1", getenv("CRITERION_ALWAYS_SUCCEED") ?: "0"); - opt->no_early_exit = !strcmp("1", getenv("CRITERION_NO_EARLY_EXIT") ?: "0"); - opt->fail_fast = !strcmp("1", getenv("CRITERION_FAIL_FAST") ?: "0"); + 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->logging_threshold = atoi(getenv("CRITERION_VERBOSITY_LEVEL") ?: "2"); - opt->short_filename = !strcmp("1", getenv("CRITERION_SHORT_FILENAME") ?: "0"); + opt->logging_threshold = atoi(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"); #endif - bool use_tap = !strcmp("1", getenv("CRITERION_ENABLE_TAP") ?: "0"); + bool use_tap = !strcmp("1", DEF(getenv("CRITERION_ENABLE_TAP"), "0")); 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;) { switch (c) { - case 'b': criterion_options.logging_threshold = atoi(optarg ?: "1"); break; + case 'b': criterion_options.logging_threshold = atoi(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/ordered-set.c b/src/ordered-set.c index 3115ca22..cecc87e8 100644 --- a/src/ordered-set.c +++ b/src/ordered-set.c @@ -25,18 +25,18 @@ #include #include #include +#include "common.h" static void destroy_ordered_set(void *ptr, UNUSED void *meta) { sfree(((struct criterion_ordered_set *) ptr)->first); } -__attribute__ ((always_inline)) -static inline void nothing() {} +static INLINE void nothing() {} static void destroy_ordered_set_node(void *ptr, void *meta) { struct criterion_ordered_set *set = *(void **) meta; struct criterion_ordered_set_node *n = ptr; - (set->dtor ?: nothing)(n->data, NULL); + DEF(set->dtor, nothing)(n->data, NULL); sfree(((struct criterion_ordered_set_node *) ptr)->next); } diff --git a/src/report.c b/src/report.c index b839542b..3b709e0a 100644 --- a/src/report.c +++ b/src/report.c @@ -41,7 +41,7 @@ static inline void nothing() {} for (f_report_hook *hook = GET_SECTION_START(HOOK_SECTION(Kind)); \ hook < (f_report_hook*) GET_SECTION_END(HOOK_SECTION(Kind)); \ ++hook) { \ - (*hook ?: nothing)(data); \ + (*hook ? *hook : nothing)(data); \ } \ } diff --git a/src/report.h b/src/report.h index 02aeed95..2322267a 100644 --- a/src/report.h +++ b/src/report.h @@ -45,6 +45,8 @@ DECL_CALL_REPORT_HOOKS(POST_SUITE); DECL_CALL_REPORT_HOOKS(POST_ALL); #define log(Type, Arg) \ - (criterion_options.output_provider->log_ ## Type ?: nothing)(Arg); + log_(criterion_options.output_provider->log_ ## Type, Arg); +#define log_(Log, Arg) \ + (Log ? Log : nothing)(Arg); #endif /* !REPORT_H_ */ diff --git a/src/runner.c b/src/runner.c index 67f3ed8c..37342a3e 100644 --- a/src/runner.c +++ b/src/runner.c @@ -37,6 +37,8 @@ #include "posix-compat.h" #include "abort.h" #include "config.h" +#include "i18n.h" +#include "common.h" #ifdef HAVE_PCRE #include "extmatch.h" @@ -49,8 +51,7 @@ IMPL_SECTION_LIMITS(struct criterion_suite, cr_sts); TestSuite(); Test(,) {}; -__attribute__ ((always_inline)) -static inline void nothing() {} +static INLINE void nothing() {} int cmp_suite(void *a, void *b) { struct criterion_suite *s1 = a, *s2 = b; @@ -161,14 +162,14 @@ static void run_test_child(struct criterion_test *test, send_event(PRE_INIT, NULL, 0); if (suite->data) - (suite->data->init ?: nothing)(); - (test->data->init ?: nothing)(); + (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 (setup_abort_test()) { timer_start(&ts); - (test->test ?: nothing)(); + (test->test ? test->test : nothing)(); } double elapsed_time; @@ -176,14 +177,13 @@ static void run_test_child(struct criterion_test *test, elapsed_time = -1; send_event(POST_TEST, &elapsed_time, sizeof (double)); - (test->data->fini ?: nothing)(); + (test->data->fini ? test->data->fini : nothing)(); if (suite->data) - (suite->data->fini ?: nothing)(); + (suite->data->fini ? suite->data->fini : nothing)(); send_event(POST_FINI, NULL, 0); } -__attribute__((always_inline)) -static inline bool is_disabled(struct criterion_test *t, +static INLINE bool is_disabled(struct criterion_test *t, struct criterion_suite *s) { return t->data->disabled || (s->data && s->data->disabled); @@ -367,6 +367,7 @@ static int criterion_run_all_tests_impl(void) { } int criterion_run_all_tests(void) { + init_i18n(); set_runner_process(); int res = criterion_run_all_tests_impl(); unset_runner_process(); diff --git a/src/stats.c b/src/stats.c index f46b957a..b017c8a4 100644 --- a/src/stats.c +++ b/src/stats.c @@ -25,6 +25,7 @@ #include #include "criterion/common.h" #include "stats.h" +#include "common.h" #include @@ -130,8 +131,7 @@ static void push_pre_suite(s_glob_stats *stats, ++stats->nb_suites; } -__attribute__((always_inline)) -static inline bool is_disabled(struct criterion_test *t, +static INLINE bool is_disabled(struct criterion_test *t, struct criterion_suite *s) { return t->data->disabled || (s->data && s->data->disabled); From f67bed8dba58a686308cccb45eb64eaa56ac5fce Mon Sep 17 00:00:00 2001 From: Snaipe Date: Sat, 5 Sep 2015 23:22:47 +0200 Subject: [PATCH 042/174] Added wingetopt to dependencies --- .gitmodules | 3 +++ CMakeLists.txt | 5 +++++ dependencies/wingetopt | 1 + 3 files changed, 9 insertions(+) create mode 160000 dependencies/wingetopt diff --git a/.gitmodules b/.gitmodules index 06e28e88..7c24be15 100644 --- a/.gitmodules +++ b/.gitmodules @@ -4,3 +4,6 @@ [submodule "dependencies/dyncall"] path = dependencies/dyncall url = https://github.com/Snaipe/dyncall.git +[submodule "dependencies/wingetopt"] + path = dependencies/wingetopt + url = https://github.com/alex85k/wingetopt.git diff --git a/CMakeLists.txt b/CMakeLists.txt index 63388cfd..8ea04d6e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -17,6 +17,11 @@ include_directories( dependencies/dyncall/dyncall/ ) +if (MSVC) + add_subdirectory(dependencies/wingetopt/ EXCLUDE_FROM_ALL) + include_directories(dependencies/wingetopt/src/) +endif () + # Project setup & environment variables set(PROJECT_VERSION "1.3.1") diff --git a/dependencies/wingetopt b/dependencies/wingetopt new file mode 160000 index 00000000..76a5d1ab --- /dev/null +++ b/dependencies/wingetopt @@ -0,0 +1 @@ +Subproject commit 76a5d1ab15f684d4c9479a32624d65b3bd1a726b From 8871ae946bdcc3f791900c8f0f4bccab0340af40 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Sat, 5 Sep 2015 23:23:00 +0200 Subject: [PATCH 043/174] Removed VLA from theories.c --- src/theories.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/theories.c b/src/theories.c index 0431c96a..7cc86d99 100644 --- a/src/theories.c +++ b/src/theories.c @@ -186,7 +186,7 @@ static void concat_arg(char (*msg)[4096], struct criterion_datapoints *dps, size void cr_theory_main(struct criterion_datapoints *dps, size_t datapoints, void (*fnptr)(void)) { struct criterion_theory_context *ctx = cr_theory_init(); - size_t indices[datapoints]; + size_t *indices = malloc(datapoints); memset(indices, 0, datapoints * sizeof (size_t)); bool has_next = true; @@ -237,5 +237,6 @@ void cr_theory_main(struct criterion_datapoints *dps, size_t datapoints, void (* } } + free(indices); cr_theory_free(ctx); } From 030fc1de19b9d99d87e4ae39efbf2ce0933e65f6 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Sat, 5 Sep 2015 23:41:01 +0200 Subject: [PATCH 044/174] Added MSVC glue for missing section symbols --- src/report.c | 14 ++++++++++++++ src/runner.c | 5 +++++ 2 files changed, 19 insertions(+) diff --git a/src/report.c b/src/report.c index 3b709e0a..2f37fa03 100644 --- a/src/report.c +++ b/src/report.c @@ -45,6 +45,20 @@ static inline void nothing() {} } \ } +#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)); +#endif + IMPL_CALL_REPORT_HOOKS(PRE_ALL); IMPL_CALL_REPORT_HOOKS(PRE_SUITE); IMPL_CALL_REPORT_HOOKS(PRE_INIT); diff --git a/src/runner.c b/src/runner.c index 37342a3e..16b0405e 100644 --- a/src/runner.c +++ b/src/runner.c @@ -44,6 +44,11 @@ #include "extmatch.h" #endif +#ifdef _MSC_VER +struct criterion_test SECTION_START_(cr_tst); +struct criterion_suite SECTION_START_(cr_sts); +#endif + IMPL_SECTION_LIMITS(struct criterion_test, cr_tst); IMPL_SECTION_LIMITS(struct criterion_suite, cr_sts); From 4bad96df64f15ab1324cffe696152ecd73b41c39 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Sat, 5 Sep 2015 23:42:22 +0200 Subject: [PATCH 045/174] Added linking to wingetopt --- CMakeLists.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 8ea04d6e..07fe6d16 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -125,6 +125,10 @@ include_directories(include src) add_library(criterion SHARED ${SOURCE_FILES} ${INTERFACE_FILES}) target_link_libraries(criterion csptr dyncall_s) +if (MSVC) + target_link_libraries(criterion wingetopt) +endif () + if (HAVE_CLOCK_GETTIME) target_link_libraries(criterion rt) endif() From 4ccabada4050a5fbbfb3b2c432d15dcfd86cf22e Mon Sep 17 00:00:00 2001 From: Snaipe Date: Sat, 5 Sep 2015 23:46:27 +0200 Subject: [PATCH 046/174] Added missing section stop symbols for MSVC --- src/report.c | 12 ++++++++++++ src/runner.c | 2 ++ 2 files changed, 14 insertions(+) diff --git a/src/report.c b/src/report.c index 2f37fa03..1658d98b 100644 --- a/src/report.c +++ b/src/report.c @@ -57,6 +57,18 @@ 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 SECTION_STOP_(HOOK_SECTION(PRE_ALL)); +f_report_hook SECTION_STOP_(HOOK_SECTION(PRE_SUITE)); +f_report_hook SECTION_STOP_(HOOK_SECTION(PRE_INIT)); +f_report_hook SECTION_STOP_(HOOK_SECTION(PRE_TEST)); +f_report_hook SECTION_STOP_(HOOK_SECTION(ASSERT)); +f_report_hook SECTION_STOP_(HOOK_SECTION(THEORY_FAIL)); +f_report_hook SECTION_STOP_(HOOK_SECTION(TEST_CRASH)); +f_report_hook SECTION_STOP_(HOOK_SECTION(POST_TEST)); +f_report_hook SECTION_STOP_(HOOK_SECTION(POST_FINI)); +f_report_hook SECTION_STOP_(HOOK_SECTION(POST_SUITE)); +f_report_hook SECTION_STOP_(HOOK_SECTION(POST_ALL)); #endif IMPL_CALL_REPORT_HOOKS(PRE_ALL); diff --git a/src/runner.c b/src/runner.c index 16b0405e..2bed26ad 100644 --- a/src/runner.c +++ b/src/runner.c @@ -47,6 +47,8 @@ #ifdef _MSC_VER struct criterion_test SECTION_START_(cr_tst); struct criterion_suite SECTION_START_(cr_sts); +struct criterion_test SECTION_STOP_(cr_tst); +struct criterion_suite SECTION_STOP_(cr_sts); #endif IMPL_SECTION_LIMITS(struct criterion_test, cr_tst); From da4e9ccdfc8279605c7c4077f3fd9ee04f596115 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Sat, 5 Sep 2015 23:48:09 +0200 Subject: [PATCH 047/174] Disabled Safe SEH for MSVC builds --- CMakeLists.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 07fe6d16..7bc0bb2d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -33,6 +33,10 @@ set_property(GLOBAL PROPERTY ALLOW_DUPLICATE_CUSTOM_TARGETS ON) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Werror -g -std=gnu99") +if (MSVC) + set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /SAFESEH:NO") +endif () + if (WIN32) set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,-no-undefined") endif() From 5d119c607efed4c0c69f0a0947dfc3190fcdcdff Mon Sep 17 00:00:00 2001 From: Snaipe Date: Sat, 5 Sep 2015 23:50:55 +0200 Subject: [PATCH 048/174] Fixed SECTION_STOP_ -> SECTION_END_ typo --- src/report.c | 22 +++++++++++----------- src/runner.c | 4 ++-- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/report.c b/src/report.c index 1658d98b..5809bfde 100644 --- a/src/report.c +++ b/src/report.c @@ -58,17 +58,17 @@ 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 SECTION_STOP_(HOOK_SECTION(PRE_ALL)); -f_report_hook SECTION_STOP_(HOOK_SECTION(PRE_SUITE)); -f_report_hook SECTION_STOP_(HOOK_SECTION(PRE_INIT)); -f_report_hook SECTION_STOP_(HOOK_SECTION(PRE_TEST)); -f_report_hook SECTION_STOP_(HOOK_SECTION(ASSERT)); -f_report_hook SECTION_STOP_(HOOK_SECTION(THEORY_FAIL)); -f_report_hook SECTION_STOP_(HOOK_SECTION(TEST_CRASH)); -f_report_hook SECTION_STOP_(HOOK_SECTION(POST_TEST)); -f_report_hook SECTION_STOP_(HOOK_SECTION(POST_FINI)); -f_report_hook SECTION_STOP_(HOOK_SECTION(POST_SUITE)); -f_report_hook SECTION_STOP_(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)); #endif IMPL_CALL_REPORT_HOOKS(PRE_ALL); diff --git a/src/runner.c b/src/runner.c index 2bed26ad..a9dabbac 100644 --- a/src/runner.c +++ b/src/runner.c @@ -47,8 +47,8 @@ #ifdef _MSC_VER struct criterion_test SECTION_START_(cr_tst); struct criterion_suite SECTION_START_(cr_sts); -struct criterion_test SECTION_STOP_(cr_tst); -struct criterion_suite SECTION_STOP_(cr_sts); +struct criterion_test SECTION_END_(cr_tst); +struct criterion_suite SECTION_END_(cr_sts); #endif IMPL_SECTION_LIMITS(struct criterion_test, cr_tst); From 45fc69463943f95a0c053f7f8bc1b788fdc5a651 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Sun, 6 Sep 2015 00:17:03 +0200 Subject: [PATCH 049/174] Marked with dllexport/import API functions --- CMakeLists.txt | 1 + include/criterion/abort.h | 2 +- include/criterion/common.h | 25 +++++++++++++++++++++++++ include/criterion/criterion.h | 2 +- include/criterion/event.h | 3 ++- include/criterion/logging.h | 6 +++--- include/criterion/ordered-set.h | 4 ++-- include/criterion/theories.h | 16 ++++++++-------- 8 files changed, 43 insertions(+), 16 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7bc0bb2d..5378a0a3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -30,6 +30,7 @@ set(GettextTranslate_ALL 1) set(GettextTranslate_GMO_BINARY 1) set_property(GLOBAL PROPERTY ALLOW_DUPLICATE_CUSTOM_TARGETS ON) +add_definitions(-DCRITERION_BUILDING_DLL=1) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Werror -g -std=gnu99") diff --git a/include/criterion/abort.h b/include/criterion/abort.h index f20e3003..1df05c0f 100644 --- a/include/criterion/abort.h +++ b/include/criterion/abort.h @@ -26,6 +26,6 @@ # include "common.h" -NORETURN void criterion_abort_test(void); +CR_API NORETURN void criterion_abort_test(void); #endif /* !CRITERION_ABORT_H_ */ diff --git a/include/criterion/common.h b/include/criterion/common.h index 2a1a630a..238a9c2f 100644 --- a/include/criterion/common.h +++ b/include/criterion/common.h @@ -111,4 +111,29 @@ # define FORMAT(Archetype, Index, Ftc) # endif +# if defined _WIN32 || defined __CYGWIN__ +# ifdef CRITERION_BUILDING_DLL +# ifdef __GNUC__ +# define CR_API __attribute__ ((dllexport)) +# else +# define CR_API __declspec(dllexport) +# endif +# else +# ifdef __GNUC__ +# define CR_API __attribute__ ((dllimport)) +# else +# define CR_API __declspec(dllimport) +# endif +# endif +# define CR_LOCAL +# else +# if __GNUC__ >= 4 +# define CR_API __attribute__ ((visibility ("default"))) +# define CR_LOCAL __attribute__ ((visibility ("hidden"))) +# else +# define CR_API +# define CR_LOCAL +# endif +# endif + #endif /* !CRITERION_COMMON_H_ */ diff --git a/include/criterion/criterion.h b/include/criterion/criterion.h index e68f8412..51c82fd8 100644 --- a/include/criterion/criterion.h +++ b/include/criterion/criterion.h @@ -67,6 +67,6 @@ .data = &SUITE_IDENTIFIER_(Name, extra), \ } SECTION_SUFFIX_ -int criterion_run_all_tests(void); +CR_API int criterion_run_all_tests(void); #endif /* !CRITERION_H_ */ diff --git a/include/criterion/event.h b/include/criterion/event.h index 99c85c86..db6cfe3d 100644 --- a/include/criterion/event.h +++ b/include/criterion/event.h @@ -26,9 +26,10 @@ # include # include +# include "common.h" extern FILE *g_event_pipe; -void send_event(int kind, void *data, size_t size); +CR_API void send_event(int kind, void *data, size_t size); #endif /* !CRITERION_EVENT_H_ */ diff --git a/include/criterion/logging.h b/include/criterion/logging.h index 667bca9e..c5bea186 100644 --- a/include/criterion/logging.h +++ b/include/criterion/logging.h @@ -76,13 +76,13 @@ extern const struct criterion_prefix_data g_criterion_logging_prefixes[]; # define CRITERION_PREFIX_PASS (&g_criterion_logging_prefixes[CRITERION_LOGGING_PREFIX_PASS ]) # define CRITERION_PREFIX_FAIL (&g_criterion_logging_prefixes[CRITERION_LOGGING_PREFIX_FAIL ]) -void criterion_vlog(enum criterion_logging_level level, const char *msg, va_list args); +CR_API void criterion_vlog(enum criterion_logging_level level, const char *msg, va_list args); FORMAT(printf, 3, 4) -void criterion_plog(enum criterion_logging_level level, const struct criterion_prefix_data *prefix, const char *msg, ...); +CR_API void criterion_plog(enum criterion_logging_level level, const struct criterion_prefix_data *prefix, const char *msg, ...); FORMAT(printf, 2, 3) -void criterion_log(enum criterion_logging_level level, const char *msg, ...); +CR_API void criterion_log(enum criterion_logging_level level, const char *msg, ...); # define criterion_info(...) criterion_log(CRITERION_INFO, __VA_ARGS__) # define criterion_important(...) criterion_log(CRITERION_IMPORTANT, __VA_ARGS__) diff --git a/include/criterion/ordered-set.h b/include/criterion/ordered-set.h index 4b71081b..514f601c 100644 --- a/include/criterion/ordered-set.h +++ b/include/criterion/ordered-set.h @@ -50,10 +50,10 @@ struct criterion_test_set { size_t tests; }; -struct criterion_ordered_set *new_ordered_set(f_criterion_cmp cmp, +CR_API struct criterion_ordered_set *new_ordered_set(f_criterion_cmp cmp, void (*dtor)(void *, void *)); -void *insert_ordered_set(struct criterion_ordered_set *l, +CR_API void *insert_ordered_set(struct criterion_ordered_set *l, void *ptr, size_t size); diff --git a/include/criterion/theories.h b/include/criterion/theories.h index 3f7cd800..ab987818 100644 --- a/include/criterion/theories.h +++ b/include/criterion/theories.h @@ -29,14 +29,14 @@ struct criterion_theory_context; -struct criterion_theory_context* cr_theory_init(void); -void cr_theory_push_arg(struct criterion_theory_context *ctx, bool is_float, size_t size, void *ptr); -void cr_theory_free(struct criterion_theory_context *ctx); -void cr_theory_abort(void); -int cr_theory_mark(void); +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); -void cr_theory_reset(struct criterion_theory_context *ctx); -void cr_theory_call(struct criterion_theory_context *ctx, void (*fnptr)(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 IDENTIFIER_(Category, Name, dps)[] @@ -64,7 +64,7 @@ struct criterion_datapoints { cr_theory_abort(); \ } while (0); -void cr_theory_main(struct criterion_datapoints *dps, size_t datapoints, void (*fnptr)(void)); +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) From 933bbefa11c757ab12260355f93b12aa9b4824c6 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Sun, 6 Sep 2015 00:25:29 +0200 Subject: [PATCH 050/174] Fixed wrong allocation size for theory indices --- src/theories.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/theories.c b/src/theories.c index 7cc86d99..3bf0f5b6 100644 --- a/src/theories.c +++ b/src/theories.c @@ -186,7 +186,7 @@ static void concat_arg(char (*msg)[4096], struct criterion_datapoints *dps, size void cr_theory_main(struct criterion_datapoints *dps, size_t datapoints, void (*fnptr)(void)) { struct criterion_theory_context *ctx = cr_theory_init(); - size_t *indices = malloc(datapoints); + size_t *indices = malloc(sizeof (size_t) * datapoints); memset(indices, 0, datapoints * sizeof (size_t)); bool has_next = true; From 785c9e279724ddd20141b24598111cdb30955357 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Sun, 6 Sep 2015 00:32:07 +0200 Subject: [PATCH 051/174] Exported main as API method --- src/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main.c b/src/main.c index 7995b346..50a86d6e 100644 --- a/src/main.c +++ b/src/main.c @@ -120,7 +120,7 @@ int list_tests(bool unicode) { return 0; } -int main(int argc, char *argv[]) { +CR_API int main(int argc, char *argv[]) { static struct option opts[] = { {"verbose", optional_argument, 0, 'b'}, {"version", no_argument, 0, 'v'}, From 211f106cae0de66392b986a4da2679b0c2f97666 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Sun, 6 Sep 2015 00:41:38 +0200 Subject: [PATCH 052/174] Made the tests c99-compliant --- test/ordered-set.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/test/ordered-set.c b/test/ordered-set.c index c25e638f..3ecdbf1b 100644 --- a/test/ordered-set.c +++ b/test/ordered-set.c @@ -1,4 +1,4 @@ -#include +#include #include "criterion/criterion.h" #include "criterion/ordered-set.h" @@ -14,7 +14,7 @@ int compare_lt(void *a, void *b) { } Test(ordered_set, contract_lt) { - smart struct criterion_ordered_set *set = new_ordered_set(compare_lt, NULL); + struct criterion_ordered_set *set = new_ordered_set(compare_lt, NULL); insert_ordered_set(set, &(int[1]) { 1 }, sizeof (int)); insert_ordered_set(set, &(int[1]) { 8 }, sizeof (int)); @@ -26,10 +26,12 @@ Test(ordered_set, contract_lt) { cr_assert_lt(*prev, *e); prev = e; } + + sfree(set); } Test(ordered_set, contract_gt) { - smart struct criterion_ordered_set *set = new_ordered_set(compare_gt, NULL); + struct criterion_ordered_set *set = new_ordered_set(compare_gt, NULL); insert_ordered_set(set, &(int[1]) { 1 }, sizeof (int)); insert_ordered_set(set, &(int[1]) { 8 }, sizeof (int)); @@ -41,4 +43,6 @@ Test(ordered_set, contract_gt) { cr_assert_gt(*prev, *e); prev = e; } + + sfree(set); } From 734dad43906695c2f9d9fd4e0ece2478dcdc5b67 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Sun, 6 Sep 2015 00:44:10 +0200 Subject: [PATCH 053/174] Temporarily removing uninstall goal to support IDEs cmake targets --- CMakeLists.txt | 5 ----- 1 file changed, 5 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 5378a0a3..e7acfdb4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -29,7 +29,6 @@ set(LOCALEDIR ${CMAKE_INSTALL_PREFIX}/share/locale) set(GettextTranslate_ALL 1) set(GettextTranslate_GMO_BINARY 1) -set_property(GLOBAL PROPERTY ALLOW_DUPLICATE_CUSTOM_TARGETS ON) add_definitions(-DCRITERION_BUILDING_DLL=1) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Werror -g -std=gnu99") @@ -163,10 +162,6 @@ install(TARGETS criterion ARCHIVE DESTINATION lib ) -add_custom_target(uninstall - "${CMAKE_COMMAND}" -P "${CMAKE_MODULE_PATH}/uninstall.cmake" -) - enable_testing() add_subdirectory(samples) add_subdirectory(test) From b4b6b611ea38149ff42e87b22dc4a713af8991b5 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Sun, 6 Sep 2015 00:44:45 +0200 Subject: [PATCH 054/174] Restored NLS back --- CMakeLists.txt | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index e7acfdb4..a0fb36c6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -53,13 +53,13 @@ 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) -#endif () +find_package(Gettext) +find_package(Libintl) +if (GETTEXT_FOUND AND LIBINTL_LIB_FOUND) + include(GettextTranslate) + add_subdirectory(po) + set(ENABLE_NLS 1) +endif () include(CheckLibraryExists) CHECK_LIBRARY_EXISTS(rt clock_gettime "time.h" HAVE_CLOCK_GETTIME) From 690c88e0c3053ef4f8425610f028f931195754ad Mon Sep 17 00:00:00 2001 From: Snaipe Date: Sun, 6 Sep 2015 00:45:20 +0200 Subject: [PATCH 055/174] Removed .def file generation --- CMakeLists.txt | 6 ------ 1 file changed, 6 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a0fb36c6..f6005a16 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -149,12 +149,6 @@ if (COVERALLS) coveralls_setup("${SOURCE_FILES}" ${COVERALLS_UPLOAD}) endif() -if (WIN32) - set_target_properties(criterion PROPERTIES LINK_FLAGS - "-Wl,--output-def,${CMAKE_CURRENT_BINARY_DIR}/libcriterion.def") - install(FILES ${CMAKE_CURRENT_BINARY_DIR}/libcriterion.def DESTINATION lib) -endif () - install(FILES ${INTERFACE_FILES} DESTINATION include/criterion) install(TARGETS criterion RUNTIME DESTINATION bin From 9499590ad42e4b38a56b84378653ab65c7443b38 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Sat, 5 Sep 2015 15:47:47 -0700 Subject: [PATCH 056/174] Don't set gcc-specific flags on VC --- CMakeLists.txt | 6 ++++-- test/CMakeLists.txt | 4 +++- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index f6005a16..02c13498 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -31,13 +31,15 @@ set(GettextTranslate_GMO_BINARY 1) add_definitions(-DCRITERION_BUILDING_DLL=1) -set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Werror -g -std=gnu99") +if (NOT MSVC) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Werror -g -std=gnu99") +endif () if (MSVC) set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /SAFESEH:NO") endif () -if (WIN32) +if (WIN32 AND NOT MSVC) set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,-no-undefined") endif() diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index e3d47045..2a575a50 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -1,4 +1,6 @@ -set(CMAKE_C_FLAGS "-std=gnu99 -Wall -Wextra") +if (NOT MSVC) + set(CMAKE_C_FLAGS "-std=gnu99 -Wall -Wextra") +endif () include_directories(../include ../src) From a630645b5ed5521dc4fdf0557493ff3cc0461db3 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Sun, 6 Sep 2015 01:01:48 +0200 Subject: [PATCH 057/174] Trying to clean up appveyor config --- appveyor.yml | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 049a0662..eb11a752 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,6 +1,6 @@ version: 1.3.1_b{build}-{branch} -os: Windows Server 2012 +os: Visual Studio 2015 init: - git config --global core.autocrlf input @@ -13,6 +13,9 @@ environment: CI_JOB_ID: $(APPVEYOR_JOB_ID) LOCAL_INSTALL: $(APPVEYOR_BUILD_FOLDER) GCOV_PREFIX: $(APPVEYOR_BUILD_FOLDER) + matrix: + - COMPILER: msvc + - COMPILER: mingw clone_depth: 5 @@ -29,14 +32,22 @@ install: - 'git checkout -B %APPVEYOR_REPO_BRANCH%' # Configure project - 'mkdir build && cd build' - - 'cmake -DCMAKE_INSTALL_PREFIX=criterion-%APPVEYOR_REPO_TAG_NAME% -DCMAKE_PREFIX_PATH="%LOCAL_INSTALL%" -DCOVERALLS=ON -DCMAKE_BUILD_TYPE=Debug -G "MSYS Makefiles" ..' + - > + cmake + -DCMAKE_INSTALL_PREFIX=criterion-%APPVEYOR_REPO_TAG_NAME% + -DCMAKE_PREFIX_PATH="%LOCAL_INSTALL%" + -DCOVERALLS=ON + -DCMAKE_BUILD_TYPE=Debug + -G "MSYS Makefiles" + .. build_script: - 'make' -after_build: +before_deploy: - 'make install' - 'bash -lc "cd $APPVEYOR_BUILD_FOLDER; tar -cvjf criterion-${APPVEYOR_REPO_BRANCH}-windows-${PLATFORM}.tar.bz2 -C build criterion-${APPVEYOR_REPO_TAG_NAME}"' + - ps: Push-AppveyorArtifact "../criterion-$env:APPVEYOR_REPO_BRANCH-windows-$env:PLATFORM.tar.bz2" test_script: - 'make test || bash -lc "cat $APPVEYOR_BUILD_FOLDER/build/Testing/Temporary/LastTest.log"' @@ -50,9 +61,6 @@ notifications: to: [franklinmathieu@gmail.com] on_build_status_changed: true -artifacts: - - path: '**\*.tar.bz2' - deploy: provider: GitHub auth_token: From 99385e2f38065cfe929cd0368d935cbe53bc5f72 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Sun, 6 Sep 2015 01:22:58 +0200 Subject: [PATCH 058/174] Added msvc builds to appveyor --- appveyor.yml | 42 +++++++++++++++++++++++++++++------------- 1 file changed, 29 insertions(+), 13 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index eb11a752..c1718665 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -32,25 +32,41 @@ install: - 'git checkout -B %APPVEYOR_REPO_BRANCH%' # Configure project - 'mkdir build && cd build' - - > - cmake - -DCMAKE_INSTALL_PREFIX=criterion-%APPVEYOR_REPO_TAG_NAME% - -DCMAKE_PREFIX_PATH="%LOCAL_INSTALL%" - -DCOVERALLS=ON - -DCMAKE_BUILD_TYPE=Debug - -G "MSYS Makefiles" - .. + - ps: | + if ($env:Compiler -eq "mingw") { + $generator = "MSYS Makefiles" + } else { + $generator = "Visual Studio 14 2015" + } + cmake ` + -DCMAKE_INSTALL_PREFIX=criterion-%APPVEYOR_REPO_TAG_NAME% ` + -DCMAKE_PREFIX_PATH="%LOCAL_INSTALL%" ` + -DCOVERALLS=ON ` + -DCMAKE_BUILD_TYPE=Debug ` + -G "$generator" ` + .. build_script: - - 'make' + - ps: | + if ($env:Compiler -eq "mingw") { + make + } else { + msbuild /m:4 /p:Configuration=Debug:Config Criterion.sln + } before_deploy: - - 'make install' - - 'bash -lc "cd $APPVEYOR_BUILD_FOLDER; tar -cvjf criterion-${APPVEYOR_REPO_BRANCH}-windows-${PLATFORM}.tar.bz2 -C build criterion-${APPVEYOR_REPO_TAG_NAME}"' - - ps: Push-AppveyorArtifact "../criterion-$env:APPVEYOR_REPO_BRANCH-windows-$env:PLATFORM.tar.bz2" + - ps: | + if ($env:Compiler -eq "mingw") { + make install + bash -lc "cd $APPVEYOR_BUILD_FOLDER; tar -cvjf criterion-${APPVEYOR_REPO_BRANCH}-windows-${PLATFORM}.tar.bz2 -C build criterion-${APPVEYOR_REPO_TAG_NAME}" + Push-AppveyorArtifact "../criterion-$env:APPVEYOR_REPO_BRANCH-windows-$env:PLATFORM.tar.bz2" + } test_script: - - 'make test || bash -lc "cat $APPVEYOR_BUILD_FOLDER/build/Testing/Temporary/LastTest.log"' + - ps: | + if ($env:Compiler -eq "mingw") { + make test || type Testing/Temporary/LastTest.log + } #after_test: # - 'make coveralls' From c8db617e57e90437738ab972c3b000cbe4e2d7b3 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Sun, 6 Sep 2015 01:24:25 +0200 Subject: [PATCH 059/174] Disabling Coveralls altogether in appveyor builds --- appveyor.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index c1718665..c9c3e18b 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -41,8 +41,6 @@ install: cmake ` -DCMAKE_INSTALL_PREFIX=criterion-%APPVEYOR_REPO_TAG_NAME% ` -DCMAKE_PREFIX_PATH="%LOCAL_INSTALL%" ` - -DCOVERALLS=ON ` - -DCMAKE_BUILD_TYPE=Debug ` -G "$generator" ` .. From e49120792052966e1075c36a36c5b331b161391f Mon Sep 17 00:00:00 2001 From: Snaipe Date: Sun, 6 Sep 2015 01:28:23 +0200 Subject: [PATCH 060/174] Added -Wno-dev warning remover for CI builds --- appveyor.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/appveyor.yml b/appveyor.yml index c9c3e18b..6d3abfa9 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -39,6 +39,7 @@ install: $generator = "Visual Studio 14 2015" } cmake ` + -Wno-dev ` -DCMAKE_INSTALL_PREFIX=criterion-%APPVEYOR_REPO_TAG_NAME% ` -DCMAKE_PREFIX_PATH="%LOCAL_INSTALL%" ` -G "$generator" ` From b3d8ed244ff18e8e336454d5773ba0d5993f51a7 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Sun, 6 Sep 2015 01:33:14 +0200 Subject: [PATCH 061/174] Fixed typo in configuration property in appveyor yml --- appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index 6d3abfa9..677c1d00 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -50,7 +50,7 @@ build_script: if ($env:Compiler -eq "mingw") { make } else { - msbuild /m:4 /p:Configuration=Debug:Config Criterion.sln + msbuild /m:4 /p:Configuration=Debug /p:Platform=Win32 Criterion.sln } before_deploy: From 3f8e179a74813ae8f68e88a81e30ffc0d4a7c4c8 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Sun, 6 Sep 2015 01:45:10 +0200 Subject: [PATCH 062/174] Fixed || not being recognised in powershell script --- appveyor.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index 677c1d00..b77410c3 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -64,7 +64,8 @@ before_deploy: test_script: - ps: | if ($env:Compiler -eq "mingw") { - make test || type Testing/Temporary/LastTest.log + try { make test } + catch { type Testing/Temporary/LastTest.log } } #after_test: From 19ecd3818eaecd2383f798ca3574c98029472bf5 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Sun, 6 Sep 2015 01:54:23 +0200 Subject: [PATCH 063/174] Changed build conditions to use cmake --build --- appveyor.yml | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index b77410c3..10c77f63 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -15,7 +15,13 @@ environment: GCOV_PREFIX: $(APPVEYOR_BUILD_FOLDER) matrix: - COMPILER: msvc + BUILD_TARGET: all_build + TEST_TARGET: run_tests + INSTALL_TARGET: install - COMPILER: mingw + BUILD_TARGET: all + TEST_TARGET: test + INSTALL_TARGET: install clone_depth: 5 @@ -47,26 +53,20 @@ install: build_script: - ps: | - if ($env:Compiler -eq "mingw") { - make - } else { - msbuild /m:4 /p:Configuration=Debug /p:Platform=Win32 Criterion.sln - } + cmake --build . --target $env:BUILD_TARGET before_deploy: - ps: | if ($env:Compiler -eq "mingw") { - make install + cmake --build . --target $env:INSTALL_TARGET bash -lc "cd $APPVEYOR_BUILD_FOLDER; tar -cvjf criterion-${APPVEYOR_REPO_BRANCH}-windows-${PLATFORM}.tar.bz2 -C build criterion-${APPVEYOR_REPO_TAG_NAME}" Push-AppveyorArtifact "../criterion-$env:APPVEYOR_REPO_BRANCH-windows-$env:PLATFORM.tar.bz2" } test_script: - ps: | - if ($env:Compiler -eq "mingw") { - try { make test } - catch { type Testing/Temporary/LastTest.log } - } + try { cmake --build . --target $env:TEST_TARGET } + catch { type Testing/Temporary/LastTest.log } #after_test: # - 'make coveralls' From 507c3183e653f1ac024f3eaee5f72386539f5ccc Mon Sep 17 00:00:00 2001 From: Snaipe Date: Sun, 6 Sep 2015 02:04:06 +0200 Subject: [PATCH 064/174] Run MinGW build before MSVC --- appveyor.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 10c77f63..cd7057bc 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -14,14 +14,14 @@ environment: LOCAL_INSTALL: $(APPVEYOR_BUILD_FOLDER) GCOV_PREFIX: $(APPVEYOR_BUILD_FOLDER) matrix: - - COMPILER: msvc - BUILD_TARGET: all_build - TEST_TARGET: run_tests - INSTALL_TARGET: install - COMPILER: mingw BUILD_TARGET: all TEST_TARGET: test INSTALL_TARGET: install + - COMPILER: msvc + BUILD_TARGET: all_build + TEST_TARGET: run_tests + INSTALL_TARGET: install clone_depth: 5 From 745d6be22982c2f359d4734cda10562b7d63973a Mon Sep 17 00:00:00 2001 From: Snaipe Date: Sun, 6 Sep 2015 02:08:34 +0200 Subject: [PATCH 065/174] Use cmd for build command --- appveyor.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index cd7057bc..b2e4b570 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -52,8 +52,7 @@ install: .. build_script: - - ps: | - cmake --build . --target $env:BUILD_TARGET + - cmake --build . --target %BUILD_TARGET% before_deploy: - ps: | From 44452bc466beff238c01a3a4e34f87fef0cba806 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Sun, 6 Sep 2015 02:18:12 +0200 Subject: [PATCH 066/174] Use 7z rather than tar to package the artifacts --- appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index b2e4b570..12a25028 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -58,7 +58,7 @@ before_deploy: - ps: | if ($env:Compiler -eq "mingw") { cmake --build . --target $env:INSTALL_TARGET - bash -lc "cd $APPVEYOR_BUILD_FOLDER; tar -cvjf criterion-${APPVEYOR_REPO_BRANCH}-windows-${PLATFORM}.tar.bz2 -C build criterion-${APPVEYOR_REPO_TAG_NAME}" + 7z a "../criterion-$env:APPVEYOR_REPO_BRANCH-windows-$env:PLATFORM.tar.bz2" "criterion-$env:APPVEYOR_REPO_TAG_NAME" Push-AppveyorArtifact "../criterion-$env:APPVEYOR_REPO_BRANCH-windows-$env:PLATFORM.tar.bz2" } From c0c80d588875d485d588bf0c0dcb8d080a23e8e6 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Sun, 6 Sep 2015 02:22:23 +0200 Subject: [PATCH 067/174] Fixed environment variables not being expanded in ps script in appveyor config --- appveyor.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 12a25028..35535593 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -46,8 +46,8 @@ install: } cmake ` -Wno-dev ` - -DCMAKE_INSTALL_PREFIX=criterion-%APPVEYOR_REPO_TAG_NAME% ` - -DCMAKE_PREFIX_PATH="%LOCAL_INSTALL%" ` + "-DCMAKE_INSTALL_PREFIX=criterion-$env:APPVEYOR_REPO_TAG_NAME" ` + "-DCMAKE_PREFIX_PATH=$env:LOCAL_INSTALL" ` -G "$generator" ` .. From d65b1c951dad786e033251db77275f44bd1471b7 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Sun, 6 Sep 2015 02:42:38 +0200 Subject: [PATCH 068/174] Copy the missing criterion.dll into the samples & test build directories --- appveyor.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/appveyor.yml b/appveyor.yml index 35535593..d4e52745 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -53,6 +53,12 @@ install: build_script: - cmake --build . --target %BUILD_TARGET% + - ps: | + # HACK: We need to copy criterion.dll into the binary directory + if ($env:Compiler -eq "msvc") { + Copy-Item Debug/criterion.dll samples/Debug/ + Copy-Item Debug/criterion.dll test/Debug/ + } before_deploy: - ps: | From af45e407bb0c1370d6bf12eebd9c159f53001c45 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Sun, 6 Sep 2015 02:45:58 +0200 Subject: [PATCH 069/174] Removed script-based tests when building with visual studio --- samples/CMakeLists.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/samples/CMakeLists.txt b/samples/CMakeLists.txt index 5bdb8423..5934663e 100644 --- a/samples/CMakeLists.txt +++ b/samples/CMakeLists.txt @@ -48,6 +48,8 @@ foreach(sample ${SAMPLES}) ) endforeach() +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) set_property(TEST ${script} PROPERTY @@ -61,3 +63,5 @@ foreach(script ${SCRIPTS}) ENVIRONMENT "CRITERION_SHORT_FILENAME=1" ) endforeach() + +endif() From e42c57fdacb439dda054f9d3b866e983a3c8cac2 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Sun, 6 Sep 2015 02:52:13 +0200 Subject: [PATCH 070/174] Cleaned up appveyor config --- appveyor.yml | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index d4e52745..0d8f165e 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -18,10 +18,12 @@ environment: BUILD_TARGET: all TEST_TARGET: test INSTALL_TARGET: install + GENERATOR: "MSYS Makefiles" - COMPILER: msvc BUILD_TARGET: all_build TEST_TARGET: run_tests INSTALL_TARGET: install + GENERATOR: "Visual Studio 14 2015" clone_depth: 5 @@ -38,18 +40,13 @@ install: - 'git checkout -B %APPVEYOR_REPO_BRANCH%' # Configure project - 'mkdir build && cd build' - - ps: | - if ($env:Compiler -eq "mingw") { - $generator = "MSYS Makefiles" - } else { - $generator = "Visual Studio 14 2015" - } - cmake ` - -Wno-dev ` - "-DCMAKE_INSTALL_PREFIX=criterion-$env:APPVEYOR_REPO_TAG_NAME" ` - "-DCMAKE_PREFIX_PATH=$env:LOCAL_INSTALL" ` - -G "$generator" ` - .. + - > + cmake + -Wno-dev + -DCMAKE_INSTALL_PREFIX="criterion-%APPVEYOR_REPO_TAG_NAME%" + -DCMAKE_PREFIX_PATH="%LOCAL_INSTALL%" + -G "%GENERATOR%" + .. build_script: - cmake --build . --target %BUILD_TARGET% From 2e1ac26f5a349cc59fbfaf0c850e07302c1dc0af Mon Sep 17 00:00:00 2001 From: Snaipe Date: Sun, 6 Sep 2015 03:04:18 +0200 Subject: [PATCH 071/174] Trying to fix the 7z command --- appveyor.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index 0d8f165e..f6258b9e 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -61,7 +61,8 @@ before_deploy: - ps: | if ($env:Compiler -eq "mingw") { cmake --build . --target $env:INSTALL_TARGET - 7z a "../criterion-$env:APPVEYOR_REPO_BRANCH-windows-$env:PLATFORM.tar.bz2" "criterion-$env:APPVEYOR_REPO_TAG_NAME" + 7z a -ttar "criterion-$env:APPVEYOR_REPO_BRANCH-windows-$env:PLATFORM.tar" "criterion-$env:APPVEYOR_REPO_TAG_NAME" + 7z a -tbzip2 "../criterion-$env:APPVEYOR_REPO_BRANCH-windows-$env:PLATFORM.tar.bz2" "criterion-$env:APPVEYOR_REPO_BRANCH-windows-$env:PLATFORM.tar" Push-AppveyorArtifact "../criterion-$env:APPVEYOR_REPO_BRANCH-windows-$env:PLATFORM.tar.bz2" } From 6b91180c9ac9963cbf4b5f25716580a2da928bc0 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Sun, 6 Sep 2015 03:29:41 +0200 Subject: [PATCH 072/174] Disabled comparison tests for MSVC builds --- samples/CMakeLists.txt | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/samples/CMakeLists.txt b/samples/CMakeLists.txt index 5934663e..d8e1d145 100644 --- a/samples/CMakeLists.txt +++ b/samples/CMakeLists.txt @@ -40,12 +40,14 @@ foreach(sample ${SAMPLES}) ENVIRONMENT "CRITERION_ALWAYS_SUCCEED=1" ) - add_test(${sample}_compare sh ${CMAKE_CURRENT_LIST_DIR}/tests/run_test.sh "${CMAKE_CURRENT_LIST_DIR}" . . ${sample}) - set_property(TEST ${sample}_compare PROPERTY - ENVIRONMENT "LC_ALL=en_US.utf8" - ENVIRONMENT "CRITERION_ALWAYS_SUCCEED=1" - ENVIRONMENT "CRITERION_SHORT_FILENAME=1" - ) + if (NOT MSVC) # we disable the scripted tests when building with MSVC + add_test(${sample}_compare sh ${CMAKE_CURRENT_LIST_DIR}/tests/run_test.sh "${CMAKE_CURRENT_LIST_DIR}" . . ${sample}) + set_property(TEST ${sample}_compare PROPERTY + ENVIRONMENT "LC_ALL=en_US.utf8" + ENVIRONMENT "CRITERION_ALWAYS_SUCCEED=1" + ENVIRONMENT "CRITERION_SHORT_FILENAME=1" + ) + endif () endforeach() if (NOT MSVC) # we disable the scripted tests when building with MSVC From 04523d303f49bd0a3d43c20a9513d3f212e9d08d Mon Sep 17 00:00:00 2001 From: Snaipe Date: Sun, 6 Sep 2015 03:35:48 +0200 Subject: [PATCH 073/174] Fixed artifacts being pushed when there is no git tag --- appveyor.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index f6258b9e..ca061d30 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -59,11 +59,11 @@ build_script: before_deploy: - ps: | - if ($env:Compiler -eq "mingw") { + if ($env:Compiler -eq "mingw" -and !$env:APPVEYOR_REPO_TAG_NAME) { cmake --build . --target $env:INSTALL_TARGET 7z a -ttar "criterion-$env:APPVEYOR_REPO_BRANCH-windows-$env:PLATFORM.tar" "criterion-$env:APPVEYOR_REPO_TAG_NAME" - 7z a -tbzip2 "../criterion-$env:APPVEYOR_REPO_BRANCH-windows-$env:PLATFORM.tar.bz2" "criterion-$env:APPVEYOR_REPO_BRANCH-windows-$env:PLATFORM.tar" - Push-AppveyorArtifact "../criterion-$env:APPVEYOR_REPO_BRANCH-windows-$env:PLATFORM.tar.bz2" + 7z a -tbzip2 "../criterion-$env:APPVEYOR_REPO_TAG_NAME-windows-$env:PLATFORM.tar.bz2" "criterion-$env:APPVEYOR_REPO_TAG_NAME-windows-$env:PLATFORM.tar" + Push-AppveyorArtifact "../criterion-$env:APPVEYOR_REPO_TAG_NAME-windows-$env:PLATFORM.tar.bz2" } test_script: From 7577cf8940d66e5042ec03c80cacec4d99a3bc08 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Sun, 6 Sep 2015 07:23:21 -0700 Subject: [PATCH 074/174] Fixed all criterion-related warnings with MSVC --- CMakeLists.txt | 4 +++ include/criterion/logging.h | 12 ++++----- src/log/normal.c | 4 +++ src/log/tap.c | 4 +++ src/ordered-set.c | 2 +- src/report.h | 2 +- src/runner.c | 10 ++++---- src/stats.c | 49 ++++++++++++++++++++++++++++--------- 8 files changed, 63 insertions(+), 24 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 02c13498..42989769 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -9,6 +9,10 @@ set(LIBCSPTR_DISABLE_COVERALLS ON) include(Submodules) +if (MSVC) + add_definitions(-D_CRT_SECURE_NO_WARNINGS=1) +endif () + add_subdirectory(dependencies/libcsptr/ EXCLUDE_FROM_ALL) add_subdirectory(dependencies/dyncall/ EXCLUDE_FROM_ALL) diff --git a/include/criterion/logging.h b/include/criterion/logging.h index c5bea186..7cd74f7e 100644 --- a/include/criterion/logging.h +++ b/include/criterion/logging.h @@ -52,12 +52,12 @@ struct criterion_prefix_data { # ifdef CRITERION_LOGGING_COLORS # define CRIT_COLOR_NORMALIZE(Str) (criterion_options.use_ascii ? "" : Str) -# define CRIT_FG_BOLD "\e[0;1m" -# define CRIT_FG_RED "\e[0;31m" -# define CRIT_FG_GREEN "\e[0;32m" -# define CRIT_FG_GOLD "\e[0;33m" -# define CRIT_FG_BLUE "\e[0;34m" -# define CRIT_RESET "\e[0m" +# define CRIT_FG_BOLD "\33[0;1m" +# define CRIT_FG_RED "\33[0;31m" +# define CRIT_FG_GREEN "\33[0;32m" +# define CRIT_FG_GOLD "\33[0;33m" +# 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) diff --git a/src/log/normal.c b/src/log/normal.c index 1ce002cb..9f278cfc 100644 --- a/src/log/normal.c +++ b/src/log/normal.c @@ -41,6 +41,10 @@ # define strtok_r(str, delim, saveptr) strtok(str, delim) #endif +#ifdef _MSC_VER +# define strdup _strdup +#endif + typedef const char *const msg_t; // Used to mark string for gettext diff --git a/src/log/tap.c b/src/log/tap.c index b406ba33..c58d0fd0 100644 --- a/src/log/tap.c +++ b/src/log/tap.c @@ -34,6 +34,10 @@ #include "posix-compat.h" #include "common.h" +#ifdef _MSC_VER +# 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) { diff --git a/src/ordered-set.c b/src/ordered-set.c index cecc87e8..00630238 100644 --- a/src/ordered-set.c +++ b/src/ordered-set.c @@ -31,7 +31,7 @@ static void destroy_ordered_set(void *ptr, UNUSED void *meta) { sfree(((struct criterion_ordered_set *) ptr)->first); } -static INLINE void nothing() {} +static INLINE void nothing(UNUSED void *ptr, UNUSED void *meta) {} static void destroy_ordered_set_node(void *ptr, void *meta) { struct criterion_ordered_set *set = *(void **) meta; diff --git a/src/report.h b/src/report.h index 2322267a..bc2d166e 100644 --- a/src/report.h +++ b/src/report.h @@ -47,6 +47,6 @@ DECL_CALL_REPORT_HOOKS(POST_ALL); #define log(Type, Arg) \ log_(criterion_options.output_provider->log_ ## Type, Arg); #define log_(Log, Arg) \ - (Log ? Log : nothing)(Arg); + (Log ? Log(Arg) : nothing()); #endif /* !REPORT_H_ */ diff --git a/src/runner.c b/src/runner.c index a9dabbac..c0ec0850 100644 --- a/src/runner.c +++ b/src/runner.c @@ -169,14 +169,14 @@ static void run_test_child(struct criterion_test *test, send_event(PRE_INIT, NULL, 0); if (suite->data) - (suite->data->init ? suite->data->init : nothing)(); - (test->data->init ? test->data->init : nothing)(); + 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 (setup_abort_test()) { timer_start(&ts); - (test->test ? test->test : nothing)(); + test->test ? test->test() : nothing(); } double elapsed_time; @@ -184,9 +184,9 @@ static void run_test_child(struct criterion_test *test, elapsed_time = -1; send_event(POST_TEST, &elapsed_time, sizeof (double)); - (test->data->fini ? test->data->fini : nothing)(); + test->data->fini ? test->data->fini() : nothing(); if (suite->data) - (suite->data->fini ? suite->data->fini : nothing)(); + suite->data->fini ? suite->data->fini() : nothing(); send_event(POST_FINI, NULL, 0); } diff --git a/src/stats.c b/src/stats.c index b017c8a4..04723abb 100644 --- a/src/stats.c +++ b/src/stats.c @@ -29,18 +29,38 @@ #include -static void nothing() {}; -static void push_pre_suite(); -static void push_pre_init(); -static void push_assert(); -static void push_post_test(); -static void push_test_crash(); - typedef struct criterion_global_stats s_glob_stats; typedef struct criterion_suite_stats s_suite_stats; typedef struct criterion_test_stats s_test_stats; typedef struct criterion_assert_stats s_assert_stats; +static void push_pre_suite(s_glob_stats *stats, + s_suite_stats *sstats, + s_test_stats *tstats, + void *data); +static void push_pre_init(s_glob_stats *stats, + s_suite_stats *sstats, + s_test_stats *tstats, + void *data); +static void push_assert(s_glob_stats *stats, + s_suite_stats *sstats, + s_test_stats *tstats, + void *data); +static void push_post_test(s_glob_stats *stats, + s_suite_stats *sstats, + s_test_stats *tstats, + void *data); +static void push_test_crash(s_glob_stats *stats, + s_suite_stats *sstats, + 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 destroy_stats(void *ptr, UNUSED void *meta) { s_glob_stats *stats = ptr; for (s_suite_stats *s = stats->suites, *next; s; s = next) { @@ -98,11 +118,13 @@ s_test_stats *test_stats_init(struct criterion_test *t) { return stats; } +typedef void (*f_handle)(s_glob_stats *, s_suite_stats *, s_test_stats *, void *); + void stat_push_event(s_glob_stats *stats, s_suite_stats *suite, s_test_stats *test, struct event *data) { - static void (*const handles[])(s_glob_stats *, s_suite_stats *, s_test_stats *, void *) = { + static const f_handle handles[] = { nothing, // PRE_ALL push_pre_suite, // PRE_SUITE push_pre_init, // PRE_INIT @@ -155,7 +177,10 @@ static void push_pre_init(s_glob_stats *stats, static void push_assert(s_glob_stats *stats, s_suite_stats *suite, s_test_stats *test, - s_assert_stats *data) { + void *ptr) { + + s_assert_stats *data = ptr; + s_assert_stats *dup = smalloc(sizeof (s_assert_stats)); memcpy(dup, data, sizeof (s_assert_stats)); @@ -179,8 +204,10 @@ static void push_assert(s_glob_stats *stats, static void push_post_test(s_glob_stats *stats, s_suite_stats *suite, s_test_stats *test, - double *ptr) { - test->elapsed_time = *ptr; + void *ptr) { + double *data = ptr; + + test->elapsed_time = (float) *data; if (test->failed_asserts > 0 || test->signal != test->test->data->signal || test->exit_code != test->test->data->exit_code) { From ee1828ff46f28171574e6fc21857b50c362adf58 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Sun, 6 Sep 2015 07:54:20 -0700 Subject: [PATCH 075/174] Fixed UB introduced by the previous commit --- src/runner.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/runner.c b/src/runner.c index c0ec0850..388d0dac 100644 --- a/src/runner.c +++ b/src/runner.c @@ -58,7 +58,7 @@ IMPL_SECTION_LIMITS(struct criterion_suite, cr_sts); TestSuite(); Test(,) {}; -static INLINE void nothing() {} +static INLINE void nothing(void) {} int cmp_suite(void *a, void *b) { struct criterion_suite *s1 = a, *s2 = b; @@ -169,14 +169,14 @@ static void run_test_child(struct criterion_test *test, send_event(PRE_INIT, NULL, 0); if (suite->data) - suite->data->init ? suite->data->init() : nothing(); - test->data->init ? test->data->init() : nothing(); + (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 (setup_abort_test()) { timer_start(&ts); - test->test ? test->test() : nothing(); + (test->test ? test->test : nothing)(); } double elapsed_time; @@ -184,9 +184,9 @@ static void run_test_child(struct criterion_test *test, elapsed_time = -1; send_event(POST_TEST, &elapsed_time, sizeof (double)); - test->data->fini ? test->data->fini() : nothing(); + (test->data->fini ? test->data->fini : nothing)(); if (suite->data) - suite->data->fini ? suite->data->fini() : nothing(); + (suite->data->fini ? suite->data->fini : nothing)(); send_event(POST_FINI, NULL, 0); } From 54ba0135d49168f37bcb0a5e842dbd74ccbdc5f7 Mon Sep 17 00:00:00 2001 From: Adeel Date: Sun, 6 Sep 2015 19:48:15 +0300 Subject: [PATCH 076/174] Repo: Mutes a modifier mismatch warning. * Also added `CMakeFiles/` dir to `.gitignore` and updated README. --- .gitignore | 1 + README.md | 5 +++-- samples/theories.c | 4 ++++ 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index 4da1b504..9e813d93 100644 --- a/.gitignore +++ b/.gitignore @@ -16,6 +16,7 @@ !HEADER !ChangeLog +CMakeFiles/ !CMakeLists.txt !.cmake/* diff --git a/README.md b/README.md index bdc4d7dd..5f46f768 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,8 @@ Criterion Logo ========= -[![Build Status](https://travis-ci.org/Snaipe/Criterion.svg?branch=bleeding)](https://travis-ci.org/Snaipe/Criterion) +[![Unix Build Status](https://travis-ci.org/Snaipe/Criterion.svg?branch=bleeding)](https://travis-ci.org/Snaipe/Criterion) +[![Windows Build Status](https://ci.appveyor.com/api/projects/status/github/Snaipe/Criterion?svg=true)](https://ci.appveyor.com/project/Snaipe/Criterion/branch/bleeding) [![Coverage Status](https://coveralls.io/repos/Snaipe/Criterion/badge.svg?branch=bleeding)](https://coveralls.io/r/Snaipe/Criterion?branch=bleeding) [![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) @@ -32,7 +33,7 @@ the user would have with other frameworks: * [x] There is a support for theories alongside tests * [x] Progress and statistics can be followed in real time with report hooks. * [x] TAP output format can be enabled with an option. -* [x] Runs on Linux, FreeBSD, Mac OS X, and Windows (Compiling with MinGW GCC). +* [x] Runs on Linux, FreeBSD, Mac OS X, and Windows (Compiling with MinGW GCC and Visaul Studio 2015+). ## Downloads diff --git a/samples/theories.c b/samples/theories.c index 0493619e..564297df 100644 --- a/samples/theories.c +++ b/samples/theories.c @@ -1,3 +1,7 @@ +#ifdef _MSC_VER +#pragma warning(disable : 4090) +#endif + #include #include From 89d8b4dbcff61130bd986b9a460ebf7e21d30af2 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Sun, 6 Sep 2015 20:19:06 +0200 Subject: [PATCH 077/174] Fixed typo in readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 5f46f768..4ddc347c 100644 --- a/README.md +++ b/README.md @@ -33,7 +33,7 @@ the user would have with other frameworks: * [x] There is a support for theories alongside tests * [x] Progress and statistics can be followed in real time with report hooks. * [x] TAP output format can be enabled with an option. -* [x] Runs on Linux, FreeBSD, Mac OS X, and Windows (Compiling with MinGW GCC and Visaul Studio 2015+). +* [x] Runs on Linux, FreeBSD, Mac OS X, and Windows (Compiling with MinGW GCC and Visual Studio 2015+). ## Downloads From c03a1495074ee21e2e737c2e9f94bdf4f5165f46 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Sun, 6 Sep 2015 21:59:34 +0200 Subject: [PATCH 078/174] Added common usage `assume` macro functions for theories --- doc/theories.rst | 50 ++++++++++++++++++++++++++++++++++++ include/criterion/theories.h | 34 ++++++++++++++++++++++++ 2 files changed, 84 insertions(+) diff --git a/doc/theories.rst b/doc/theories.rst index 7fd95c6e..9619affe 100644 --- a/doc/theories.rst +++ b/doc/theories.rst @@ -51,6 +51,56 @@ Theory invariants are enforced through the ``cr_assume(Condition)`` macro functi if ``Condition`` is false, then the current theory iteration aborts without making the test fail. +On top of those, more ``assume`` macro functions are available for common operations: + +======================================================= ==================================================== +Macro Description +======================================================= ==================================================== +``cr_assume_not(Condition)`` Assumes Condition is false. +------------------------------------------------------- ---------------------------------------------------- +``cr_assume_null(Ptr)`` Assumes Ptr is NULL. +------------------------------------------------------- ---------------------------------------------------- +``cr_assume_not_null(Ptr)`` Assumes Ptr is not NULL. +------------------------------------------------------- ---------------------------------------------------- +``cr_assume_eq(Actual, Expected)`` Assumes Actual == Expected. +------------------------------------------------------- ---------------------------------------------------- +``cr_assume_neq(Actual, Unexpected)`` Assumes Actual != Expected. +------------------------------------------------------- ---------------------------------------------------- +``cr_assume_lt(Actual, Expected)`` Assumes Actual < Expected. +------------------------------------------------------- ---------------------------------------------------- +``cr_assume_leq(Actual, Expected)`` Assumes Actual <= Expected. +------------------------------------------------------- ---------------------------------------------------- +``cr_assume_gt(Actual, Expected)`` Assumes Actual > Expected. +------------------------------------------------------- ---------------------------------------------------- +``cr_assume_geq(Actual, Expected)`` Assumes Actual >= Expected. +------------------------------------------------------- ---------------------------------------------------- +``cr_assume_float_eq(Actual, Expected, Epsilon)`` Assumes Actual == Expected with an error of Epsilon. +------------------------------------------------------- ---------------------------------------------------- +``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_strings_neq(Actual, Unexpected)`` Assumes Actual and Expected are not the same string. +------------------------------------------------------- ---------------------------------------------------- +``cr_assume_strings_lt(Actual, Expected)`` Assumes Actual is less than Expected + lexicographically. +------------------------------------------------------- ---------------------------------------------------- +``cr_assume_strings_leq(Actual, Expected)`` Assumes Actual is less or equal to Expected + lexicographically. +------------------------------------------------------- ---------------------------------------------------- +``cr_assume_strings_gt(Actual, Expected)`` Assumes Actual is greater than Expected + lexicographically. +------------------------------------------------------- ---------------------------------------------------- +``cr_assume_strings_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) + are equals to those of Expected. +------------------------------------------------------- ---------------------------------------------------- +``cr_assume_arrays_neq(Actual, Unexpected, Size)`` Assumes one or more elements of Actual (from 0 to + Size - 1) differs from their counterpart in Expected. +======================================================= ==================================================== + Configuring theories -------------------- diff --git a/include/criterion/theories.h b/include/criterion/theories.h index ab987818..6e233459 100644 --- a/include/criterion/theories.h +++ b/include/criterion/theories.h @@ -64,6 +64,40 @@ struct criterion_datapoints { cr_theory_abort(); \ } while (0); +# define cr_assume_not(Condition) cr_assume(!(Condition)) + +# define cr_assume_op_(Op, Actual, Expected) cr_assume((Actual) Op (Expected)) +# define cr_assume_eq(Actual, Expected) cr_assume_op_(==, Actual, Expected) +# define cr_assume_neq(Actual, Expected) cr_assume_op_(!=, Actual, Expected) +# define cr_assume_gt(Actual, Expected) cr_assume_op_(>, Actual, Expected) +# define cr_assume_geq(Actual, Expected) cr_assume_op_(>=, Actual, Expected) +# define cr_assume_lt(Actual, Expected) cr_assume_op_(<, Actual, Expected) +# define cr_assume_leq(Actual, Expected) cr_assume_op_(<=, Actual, Expected) + +# define cr_assume_null(Value) cr_assume_eq(Value, NULL) +# define cr_assume_not_null(Value) cr_assume_neq(Value, NULL) + +# define cr_assume_float_eq(Actual, Expected, Epsilon) \ + cr_assume((Expected) - (Actual) <= (Epsilon) \ + && (Actual) - (Expected) <= (Epsilon)) + +# define cr_assume_float_neq(Actual, Expected, Epsilon) \ + cr_assume((Expected) - (Actual) > (Epsilon) \ + || (Actual) - (Expected) > (Epsilon)) + +# define cr_assume_strings_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_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))) + CR_API void cr_theory_main(struct criterion_datapoints *dps, size_t datapoints, void (*fnptr)(void)); # define CR_VAARG_ID(Suffix, Category, Name, ...) \ From 416b034fe138d515931b747dc60722845e2103f8 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Mon, 7 Sep 2015 01:15:31 +0200 Subject: [PATCH 079/174] Made the interface C++11-compatible --- CMakeLists.txt | 2 +- include/criterion/abort.h | 4 + include/criterion/assert.h | 169 +++++++++--------- include/criterion/common.h | 28 ++- include/criterion/criterion.h | 51 ++++-- .../criterion/designated-initializer-compat.h | 124 +++++++++++++ include/criterion/event.h | 13 +- include/criterion/hooks.h | 26 ++- include/criterion/logging.h | 13 +- include/criterion/options.h | 4 + include/criterion/ordered-set.h | 12 +- include/criterion/theories.h | 4 + include/criterion/types.h | 21 ++- samples/CMakeLists.txt | 8 + samples/asserts.c | 2 - samples/report.c | 6 +- src/report.c | 22 +-- 17 files changed, 364 insertions(+), 145 deletions(-) create mode 100644 include/criterion/designated-initializer-compat.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 42989769..d2222684 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,6 @@ cmake_minimum_required(VERSION 2.8) -project(Criterion C) +project(Criterion C CXX) set(MODULE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/.cmake/Modules") set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${MODULE_DIR}) diff --git a/include/criterion/abort.h b/include/criterion/abort.h index 1df05c0f..598b27ef 100644 --- a/include/criterion/abort.h +++ b/include/criterion/abort.h @@ -26,6 +26,10 @@ # include "common.h" +CR_BEGIN_C_API + CR_API NORETURN void criterion_abort_test(void); +CR_END_C_API + #endif /* !CRITERION_ABORT_H_ */ diff --git a/include/criterion/assert.h b/include/criterion/assert.h index 6d796b26..23b42569 100644 --- a/include/criterion/assert.h +++ b/include/criterion/assert.h @@ -24,9 +24,17 @@ #ifndef CRITERION_ASSERT_H_ # define CRITERION_ASSERT_H_ -# include -# include -# include +# ifdef __cplusplus +# include +# include +using std::strcmp; +using std::memcmp; +# else +# include +# include +# include +# endif +# include "designated-initializer-compat.h" # include "types.h" # include "stats.h" # include "hooks.h" @@ -40,47 +48,50 @@ enum criterion_assert_kind { struct criterion_assert_args { const char *msg; - const char *default_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 }; -# define cr_assert_impl(Kind, Condition, ...) \ - do { \ - struct criterion_assert_args args = { \ - __VA_ARGS__ \ - }; \ - int passed = !!(Condition); \ - struct criterion_assert_stats stat = { \ - .kind = (Kind), \ - .condition = #Condition, \ - .message = args.msg ? args.msg \ - : (args.default_msg ? args.default_msg : ""), \ - .passed = passed, \ - .file = __FILE__, \ - .line = __LINE__, \ - }; \ - send_event(ASSERT, &stat, sizeof (stat)); \ - if (!passed && (Kind) == FATAL) \ - criterion_abort_test(); \ +# define CR_GET_CONDITION(Condition, ...) Condition +# define CR_GET_CONDITION_STR(Condition, ...) #Condition +# define CR_VA_SKIP(_, ...) __VA_ARGS__ + +# define cr_assert_impl(Kind, ...) \ + do { \ + struct criterion_assert_args args = { \ + CR_EXPAND(CR_VA_SKIP(__VA_ARGS__)) \ + }; \ + int passed = !!(CR_EXPAND(CR_GET_CONDITION(__VA_ARGS__))); \ + struct criterion_assert_stats stat; \ + stat.kind = (Kind); \ + stat.condition = CR_EXPAND(CR_GET_CONDITION_STR(__VA_ARGS__)); \ + stat.message = args.msg ? args.msg : ""; \ + stat.passed = passed; \ + stat.file = __FILE__; \ + stat.line = __LINE__; \ + send_event(ASSERT, &stat, sizeof (stat)); \ + if (!passed && (Kind) == FATAL) \ + criterion_abort_test(); \ } while (0) // Common asserts -# define cr_abort_test(Message) \ - cr_assert(0, \ - .default_msg = "The conditions for this test were not met.", \ - .msg = (Message) \ - ) +# define cr_abort_test(Message) \ + cr_assert(0, (Message)) -# define cr_assert(...) CR_EXPAND(cr_assert_(__VA_ARGS__, .sentinel_ = 0)) +# define cr_assert(...) CR_EXPAND(cr_assert_(__VA_ARGS__, 0)) -# define cr_expect(...) CR_EXPAND(cr_expect_(__VA_ARGS__, .sentinel_ = 0)) +# define cr_expect(...) CR_EXPAND(cr_expect_(__VA_ARGS__, 0)) # define cr_assert_(Condition, ...) CR_EXPAND(cr_assert_impl(FATAL, Condition, __VA_ARGS__)) # define cr_expect_(Condition, ...) CR_EXPAND(cr_assert_impl(NORMAL, Condition, __VA_ARGS__)) -# define cr_assert_not(...) CR_EXPAND(cr_assert_not_(__VA_ARGS__, .sentinel_ = 0)) -# define cr_expect_not(...) CR_EXPAND(cr_expect_not_(__VA_ARGS__, .sentinel_ = 0)) +# define cr_assert_not(...) CR_EXPAND(cr_assert_not_(__VA_ARGS__, 0)) +# define cr_expect_not(...) CR_EXPAND(cr_expect_not_(__VA_ARGS__, 0)) # define cr_assert_not_(Condition, ...) \ CR_EXPAND(cr_assert_impl(FATAL, !(Condition), __VA_ARGS__)) @@ -94,46 +105,46 @@ struct criterion_assert_args { # define cr_expect_op_(Op, Actual, Expected, ...) \ CR_EXPAND(cr_assert_impl(NORMAL, (Actual) Op (Expected), __VA_ARGS__)) -# define cr_assert_eq(...) CR_EXPAND(cr_assert_op_(==, __VA_ARGS__, .sentinel_ = 0)) -# define cr_expect_eq(...) CR_EXPAND(cr_expect_op_(==, __VA_ARGS__, .sentinel_ = 0)) +# define cr_assert_eq(...) CR_EXPAND(cr_assert_op_(==, __VA_ARGS__, 0)) +# define cr_expect_eq(...) CR_EXPAND(cr_expect_op_(==, __VA_ARGS__, 0)) -# define cr_assert_neq(...) CR_EXPAND(cr_assert_op_(!=, __VA_ARGS__, .sentinel_ = 0)) -# define cr_expect_neq(...) CR_EXPAND(cr_expect_op_(!=, __VA_ARGS__, .sentinel_ = 0)) +# define cr_assert_neq(...) CR_EXPAND(cr_assert_op_(!=, __VA_ARGS__, 0)) +# define cr_expect_neq(...) CR_EXPAND(cr_expect_op_(!=, __VA_ARGS__, 0)) -# define cr_assert_lt(...) CR_EXPAND(cr_assert_op_(<, __VA_ARGS__, .sentinel_ = 0)) -# define cr_expect_lt(...) CR_EXPAND(cr_expect_op_(<, __VA_ARGS__, .sentinel_ = 0)) +# define cr_assert_lt(...) CR_EXPAND(cr_assert_op_(<, __VA_ARGS__, 0)) +# define cr_expect_lt(...) CR_EXPAND(cr_expect_op_(<, __VA_ARGS__, 0)) -# define cr_assert_gt(...) CR_EXPAND(cr_assert_op_(>, __VA_ARGS__, .sentinel_ = 0)) -# define cr_expect_gt(...) CR_EXPAND(cr_expect_op_(>, __VA_ARGS__, .sentinel_ = 0)) +# define cr_assert_gt(...) CR_EXPAND(cr_assert_op_(>, __VA_ARGS__, 0)) +# define cr_expect_gt(...) CR_EXPAND(cr_expect_op_(>, __VA_ARGS__, 0)) -# define cr_assert_leq(...) CR_EXPAND(cr_assert_op_(<=, __VA_ARGS__, .sentinel_ = 0)) -# define cr_expect_leq(...) CR_EXPAND(cr_expect_op_(<=, __VA_ARGS__, .sentinel_ = 0)) +# define cr_assert_leq(...) CR_EXPAND(cr_assert_op_(<=, __VA_ARGS__, 0)) +# define cr_expect_leq(...) CR_EXPAND(cr_expect_op_(<=, __VA_ARGS__, 0)) -# define cr_assert_geq(...) CR_EXPAND(cr_assert_op_(>=, __VA_ARGS__, .sentinel_ = 0)) -# define cr_expect_geq(...) CR_EXPAND(cr_expect_op_(>=, __VA_ARGS__, .sentinel_ = 0)) +# define cr_assert_geq(...) CR_EXPAND(cr_assert_op_(>=, __VA_ARGS__, 0)) +# define cr_expect_geq(...) CR_EXPAND(cr_expect_op_(>=, __VA_ARGS__, 0)) # define cr_assert_null_(Value, ...) \ CR_EXPAND(cr_assert_impl(FATAL, (Value) == NULL, __VA_ARGS__)) # define cr_expect_null_(Value, ...) \ CR_EXPAND(cr_assert_impl(NORMAL, (Value) == NULL, __VA_ARGS__)) -# define cr_assert_null(...) CR_EXPAND(cr_assert_null_(__VA_ARGS__, .sentinel_ = 0)) -# define cr_expect_null(...) CR_EXPAND(cr_expect_null_(__VA_ARGS__, .sentinel_ = 0)) +# define cr_assert_null(...) CR_EXPAND(cr_assert_null_(__VA_ARGS__, 0)) +# define cr_expect_null(...) CR_EXPAND(cr_expect_null_(__VA_ARGS__, 0)) # define cr_assert_not_null_(Value, ...) \ CR_EXPAND(cr_assert_impl(FATAL, (Value) != NULL, __VA_ARGS__)) # define cr_expect_not_null_(Value, ...) \ CR_EXPAND(cr_assert_impl(NORMAL, (Value) != NULL, __VA_ARGS__)) -# define cr_assert_not_null(...) CR_EXPAND(cr_assert_not_null_(__VA_ARGS__, .sentinel_ = 0)) -# define cr_expect_not_null(...) CR_EXPAND(cr_expect_not_null_(__VA_ARGS__, .sentinel_ = 0)) +# define cr_assert_not_null(...) CR_EXPAND(cr_assert_not_null_(__VA_ARGS__, 0)) +# define cr_expect_not_null(...) CR_EXPAND(cr_expect_not_null_(__VA_ARGS__, 0)) // Floating-point asserts # define cr_assert_float_eq(...) \ - CR_EXPAND(cr_assert_float_eq_(__VA_ARGS__, .sentinel_ = 0)) + CR_EXPAND(cr_assert_float_eq_(__VA_ARGS__, 0)) # define cr_expect_float_eq(...) \ - CR_EXPAND(cr_expect_float_eq_(__VA_ARGS__, .sentinel_ = 0)) + CR_EXPAND(cr_expect_float_eq_(__VA_ARGS__, 0)) # define cr_assert_float_eq_(Actual, Expected, Epsilon, ...) \ CR_EXPAND(cr_assert_impl(FATAL, (Expected) - (Actual) <= (Epsilon) \ @@ -145,9 +156,9 @@ struct criterion_assert_args { __VA_ARGS__)) # define cr_assert_float_neq(...) \ - CR_EXPAND(cr_assert_float_neq_(__VA_ARGS__, .sentinel_ = 0)) + CR_EXPAND(cr_assert_float_neq_(__VA_ARGS__, 0)) # define cr_expect_float_neq(...) \ - CR_EXPAND(cr_expect_float_neq_(__VA_ARGS__, .sentinel_ = 0)) + CR_EXPAND(cr_expect_float_neq_(__VA_ARGS__, 0)) # define cr_assert_float_neq_(Actual, Expected, Epsilon, ...) \ CR_EXPAND(cr_assert_impl(FATAL, (Expected) - (Actual) > (Epsilon) \ @@ -166,55 +177,51 @@ struct criterion_assert_args { CR_EXPAND(cr_assert_impl(NORMAL, strcmp((Actual), (Expected)) Op 0, __VA_ARGS__)) # define cr_assert_strings_eq(...) \ - CR_EXPAND(cr_assert_strings_(==, __VA_ARGS__, .sentinel_ = 0)) + CR_EXPAND(cr_assert_strings_(==, __VA_ARGS__, 0)) # define cr_expect_strings_eq(...) \ - CR_EXPAND(cr_expect_strings_(==, __VA_ARGS__, .sentinel_ = 0)) + CR_EXPAND(cr_expect_strings_(==, __VA_ARGS__, 0)) # define cr_assert_strings_neq(...) \ - CR_EXPAND(cr_assert_strings_(!=, __VA_ARGS__, .sentinel_ = 0)) + CR_EXPAND(cr_assert_strings_(!=, __VA_ARGS__, 0)) # define cr_expect_strings_neq(...) \ - CR_EXPAND(cr_expect_strings_(!=, __VA_ARGS__, .sentinel_ = 0)) + CR_EXPAND(cr_expect_strings_(!=, __VA_ARGS__, 0)) -# define cr_assert_strings_gt(...) CR_EXPAND(cr_assert_strings_(>, __VA_ARGS__, .sentinel_ = 0)) -# define cr_expect_strings_gt(...) CR_EXPAND(cr_expect_strings_(>, __VA_ARGS__, .sentinel_ = 0)) +# define cr_assert_strings_gt(...) CR_EXPAND(cr_assert_strings_(>, __VA_ARGS__, 0)) +# define cr_expect_strings_gt(...) CR_EXPAND(cr_expect_strings_(>, __VA_ARGS__, 0)) -# define cr_assert_strings_lt(...) CR_EXPAND(cr_assert_strings_(<, __VA_ARGS__, .sentinel_ = 0)) -# define cr_expect_strings_lt(...) CR_EXPAND(cr_expect_strings_(<, __VA_ARGS__, .sentinel_ = 0)) +# define cr_assert_strings_lt(...) CR_EXPAND(cr_assert_strings_(<, __VA_ARGS__, 0)) +# define cr_expect_strings_lt(...) CR_EXPAND(cr_expect_strings_(<, __VA_ARGS__, 0)) -# define cr_assert_strings_leq(...) CR_EXPAND(cr_assert_strings_(<=, __VA_ARGS__, .sentinel_ = 0)) -# define cr_expect_strings_leq(...) CR_EXPAND(cr_expect_strings_(<=, __VA_ARGS__, .sentinel_ = 0)) +# define cr_assert_strings_leq(...) CR_EXPAND(cr_assert_strings_(<=, __VA_ARGS__, 0)) +# define cr_expect_strings_leq(...) CR_EXPAND(cr_expect_strings_(<=, __VA_ARGS__, 0)) -# define cr_assert_strings_geq(...) CR_EXPAND(cr_assert_strings_(>=, __VA_ARGS__, .sentinel_ = 0)) -# define cr_expect_strings_geq(...) CR_EXPAND(cr_expect_strings_(>=, __VA_ARGS__, .sentinel_ = 0)) +# define cr_assert_strings_geq(...) CR_EXPAND(cr_assert_strings_(>=, __VA_ARGS__, 0)) +# define cr_expect_strings_geq(...) CR_EXPAND(cr_expect_strings_(>=, __VA_ARGS__, 0)) // Array asserts # define cr_assert_arrays_eq(...) \ - CR_EXPAND(cr_assert_arrays_eq_(__VA_ARGS__, .sentinel_ = 0)) + CR_EXPAND(cr_assert_arrays_eq_(__VA_ARGS__, 0)) # define cr_expect_arrays_eq(...) \ - CR_EXPAND(cr_expect_arrays_eq_(__VA_ARGS__, .sentinel_ = 0)) + CR_EXPAND(cr_expect_arrays_eq_(__VA_ARGS__, 0)) # define cr_assert_arrays_neq(...) \ - CR_EXPAND(cr_assert_arrays_neq_(__VA_ARGS__, .sentinel_ = 0)) + CR_EXPAND(cr_assert_arrays_neq_(__VA_ARGS__, 0)) # define cr_expect_arrays_neq(...) \ - CR_EXPAND(cr_expect_arrays_neq_(__VA_ARGS__, .sentinel_ = 0)) + CR_EXPAND(cr_expect_arrays_neq_(__VA_ARGS__, 0)) -# define cr_assert_arrays_eq_(A, B, Size, ...) \ +# define cr_assert_arrays_eq_(A, B, Size, ...) \ CR_EXPAND(cr_assert_impl(FATAL, !memcmp((A), (B), (Size)), \ - .default_msg = "Arrays are not equal.", \ __VA_ARGS__)) -# define cr_expect_arrays_eq_(A, B, Size, ...) \ +# define cr_expect_arrays_eq_(A, B, Size, ...) \ CR_EXPAND(cr_assert_impl(NORMAL, !memcmp((A), (B), (Size)), \ - .default_msg = "Arrays are not equal.", \ __VA_ARGS__)) -# define cr_assert_arrays_neq_(A, B, Size, ...) \ +# define cr_assert_arrays_neq_(A, B, Size, ...) \ CR_EXPAND(cr_assert_impl(FATAL, memcmp((A), (B), (Size)), \ - .default_msg = "Arrays are equal", \ __VA_ARGS__)) -# define cr_expect_arrays_neq_(A, B, Size, ...) \ +# define cr_expect_arrays_neq_(A, B, Size, ...) \ CR_EXPAND(cr_assert_impl(NORMAL, memcmp((A), (B), (Size)), \ - .default_msg = "Arrays are equal", \ __VA_ARGS__)) # ifdef __GNUC__ @@ -230,7 +237,6 @@ struct criterion_assert_args { do { \ CRIT_ARR_COMPARE_(A, B, Size, Cmp, equals); \ cr_assert_impl(FATAL, equals, \ - .default_msg = "Arrays are not equal", \ __VA_ARGS__); \ } while (0) @@ -238,20 +244,18 @@ struct criterion_assert_args { do { \ CRIT_ARR_COMPARE_(A, B, Size, Cmp, equals); \ cr_assert_impl(NORMAL, equals, \ - .default_msg = "Arrays are not equal", \ __VA_ARGS__); \ } while (0) # define cr_assert_arrays_eq_cmp(...) \ - cr_assert_arrays_eq_cmp_(__VA_ARGS__, .sentinel_ = 0) + cr_assert_arrays_eq_cmp_(__VA_ARGS__, 0) # define cr_expect_arrays_eq_cmp(...) \ - cr_expect_arrays_eq_cmp_(__VA_ARGS__, .sentinel_ = 0) + cr_expect_arrays_eq_cmp_(__VA_ARGS__, 0) # define cr_assert_arrays_neq_cmp_(A, B, Size, Cmp, ...) \ do { \ CRIT_ARR_COMPARE_(A, B, Size, Cmp, equals); \ cr_assert_impl(FATAL, !equals, \ - .default_msg = "Arrays not equal", \ __VA_ARGS__); \ } while (0) @@ -259,14 +263,13 @@ struct criterion_assert_args { do { \ CRIT_ARR_COMPARE_(A, B, Size, Cmp, equals); \ cr_assert_impl(NORMAL, equals, \ - .default_msg = "Arrays not equal", \ __VA_ARGS__); \ } while (0) # define cr_assert_arrays_neq_cmp(...) \ - cr_assert_arrays_eq_cmp_(__VA_ARGS__, .sentinel_ = 0) + cr_assert_arrays_eq_cmp_(__VA_ARGS__, 0) # define cr_expect_arrays_neq_cmp(...) \ - cr_expect_arrays_eq_cmp_(__VA_ARGS__, .sentinel_ = 0) + cr_expect_arrays_eq_cmp_(__VA_ARGS__, 0) # endif /* !__GNUC__ */ // The section below is here for backward compatibility purposes. diff --git a/include/criterion/common.h b/include/criterion/common.h index 238a9c2f..5ee86a92 100644 --- a/include/criterion/common.h +++ b/include/criterion/common.h @@ -43,12 +43,22 @@ # endif # endif +# ifdef __cplusplus +# define CR_ATTRIBUTE(Arg) [[gnu::Arg]] +# define CR_BEGIN_C_API extern "C" { +# define CR_END_C_API } +# else +# define CR_ATTRIBUTE(Arg) __attribute__((Arg)) +# define CR_BEGIN_C_API +# define CR_END_C_API +# 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) __attribute__((section("__DATA," Name))) +# define SECTION_(Name) CR_ATTRIBUTE(section("__DATA," Name) # define SECTION_SUFFIX_ # elif CR_IS_MSVC # define SECTION_START_PREFIX __start @@ -66,7 +76,7 @@ # define SECTION_END_PREFIX __stop # define SECTION_START_SUFFIX(Name) # define SECTION_END_SUFFIX(Name) -# define SECTION_(Name) __attribute__((section(Name))) +# define SECTION_(Name) CR_ATTRIBUTE(section(Name)) # define SECTION_SUFFIX_ # endif @@ -89,8 +99,8 @@ Type *const SECTION_END(Name) = &SECTION_END_(Name) # ifdef __GNUC__ -# define UNUSED __attribute__((unused)) -# define NORETURN __attribute__((noreturn)) +# define UNUSED CR_ATTRIBUTE(unused) +# define NORETURN CR_ATTRIBUTE(noreturn) # elif CR_IS_MSVC # define UNUSED # define NORETURN __declspec(noreturn) @@ -106,7 +116,7 @@ # endif # ifdef __GNUC__ -# define FORMAT(Archetype, Index, Ftc) __attribute__((format(Archetype, Index, Ftc))) +# define FORMAT(Archetype, Index, Ftc) CR_ATTRIBUTE(format(Archetype, Index, Ftc)) # else # define FORMAT(Archetype, Index, Ftc) # endif @@ -114,13 +124,13 @@ # if defined _WIN32 || defined __CYGWIN__ # ifdef CRITERION_BUILDING_DLL # ifdef __GNUC__ -# define CR_API __attribute__ ((dllexport)) +# define CR_API CR_ATTRIBUTE(dllexport) # else # define CR_API __declspec(dllexport) # endif # else # ifdef __GNUC__ -# define CR_API __attribute__ ((dllimport)) +# define CR_API CR_ATTRIBUTE(dllimport) # else # define CR_API __declspec(dllimport) # endif @@ -128,8 +138,8 @@ # define CR_LOCAL # else # if __GNUC__ >= 4 -# define CR_API __attribute__ ((visibility ("default"))) -# define CR_LOCAL __attribute__ ((visibility ("hidden"))) +# define CR_API CR_ATTRIBUTE(visibility("default")) +# define CR_LOCAL CR_ATTRIBUTE(visibility("hidden")) # else # define CR_API # define CR_LOCAL diff --git a/include/criterion/criterion.h b/include/criterion/criterion.h index 51c82fd8..bc82cccc 100644 --- a/include/criterion/criterion.h +++ b/include/criterion/criterion.h @@ -24,14 +24,21 @@ #ifndef CRITERION_H_ # define CRITERION_H_ +# include "designated-initializer-compat.h" # include "common.h" -# include "assert.h" # include "types.h" +# include "assert.h" # define IDENTIFIER_(Category, Name, Suffix) \ Category ## _ ## Name ## _ ## Suffix -# define TEST_PROTOTYPE_(Category, Name) \ + +# ifdef __cplusplus +# define TEST_PROTOTYPE_(Category, Name) \ + extern "C" void IDENTIFIER_(Category, Name, impl)(void) +# else +# define TEST_PROTOTYPE_(Category, Name) \ void IDENTIFIER_(Category, Name, impl)(void) +# endif # define SUITE_IDENTIFIER_(Name, Suffix) \ suite_ ## Name ## _ ## Suffix @@ -39,34 +46,40 @@ # 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) = { \ - .identifier_ = #Category "/" #Name, \ - .file_ = __FILE__, \ - .line_ = __LINE__, \ - __VA_ARGS__ \ - }; \ + struct criterion_test_extra_data IDENTIFIER_(Category, Name, extra) = \ + CR_EXPAND(CRITERION_MAKE_STRUCT(struct criterion_test_extra_data, \ + .identifier_ = #Category "/" #Name, \ + .file_ = __FILE__, \ + .line_ = __LINE__, \ + __VA_ARGS__ \ + )); \ SECTION_("cr_tst") \ const struct criterion_test IDENTIFIER_(Category, Name, meta) = { \ - .name = #Name, \ - .category = #Category, \ - .test = IDENTIFIER_(Category, Name, impl), \ - .data = &IDENTIFIER_(Category, Name, extra) \ + #Name, \ + #Category, \ + IDENTIFIER_(Category, Name, impl), \ + &IDENTIFIER_(Category, Name, extra) \ } SECTION_SUFFIX_; \ 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) = { \ - .file_ = __FILE__, \ - .line_ = 0, \ - __VA_ARGS__ \ - }; \ + struct criterion_test_extra_data SUITE_IDENTIFIER_(Name, extra) = \ + CR_EXPAND(CRITERION_MAKE_STRUCT(struct criterion_test_extra_data, \ + .file_ = __FILE__, \ + .line_ = 0, \ + __VA_ARGS__ \ + )); \ SECTION_("cr_sts") \ const struct criterion_suite SUITE_IDENTIFIER_(Name, meta) = { \ - .name = #Name, \ - .data = &SUITE_IDENTIFIER_(Name, extra), \ + #Name, \ + &SUITE_IDENTIFIER_(Name, extra), \ } SECTION_SUFFIX_ +CR_BEGIN_C_API + CR_API int criterion_run_all_tests(void); +CR_END_C_API + #endif /* !CRITERION_H_ */ diff --git a/include/criterion/designated-initializer-compat.h b/include/criterion/designated-initializer-compat.h new file mode 100644 index 00000000..910952b1 --- /dev/null +++ b/include/criterion/designated-initializer-compat.h @@ -0,0 +1,124 @@ +/* + * 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_DESIGNATED_INITIALIZER_COMPAT_HH_ +# define CRITERION_DESIGNATED_INITIALIZER_COMPAT_HH_ + +# include "common.h" + +# define CRITERION_ARG_LENGTH(...) CR_EXPAND(CRITERION_ARG_LENGTH_(__VA_ARGS__,\ + 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45,\ + 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26,\ + 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6,\ + 5, 4, 3, 2, 1, 0)) +# define CRITERION_ARG_LENGTH_(_63, _62, _61, _60, _59, _58, _57, _56, _55, _54, _53, \ + _52, _51, _50, _49, _48, _47, _46, _45, _44, _43, _42, _41, _40, _39, _38, \ + _37, _36, _35, _34, _33, _32, _31, _30, _29, _28, _27, _26, _25, _24, _23, \ + _22, _21, _20, _19, _18, _17, _16, _15, _14, _13, _12, _11, _10, _9, _8, \ + _7, _6, _5, _4, _3, _2, _1, count, ...) count + +# define CRITERION_APPLY_1(Macro, ...) +# define CRITERION_APPLY_2(Macro, Prefix, Head, ...) Macro(Prefix, Head) CR_EXPAND(CRITERION_APPLY_1(Macro, Prefix, __VA_ARGS__)) +# define CRITERION_APPLY_3(Macro, Prefix, Head, ...) Macro(Prefix, Head) CR_EXPAND(CRITERION_APPLY_2(Macro, Prefix, __VA_ARGS__)) +# define CRITERION_APPLY_4(Macro, Prefix, Head, ...) Macro(Prefix, Head) CR_EXPAND(CRITERION_APPLY_3(Macro, Prefix, __VA_ARGS__)) +# define CRITERION_APPLY_5(Macro, Prefix, Head, ...) Macro(Prefix, Head) CR_EXPAND(CRITERION_APPLY_4(Macro, Prefix, __VA_ARGS__)) +# define CRITERION_APPLY_6(Macro, Prefix, Head, ...) Macro(Prefix, Head) CR_EXPAND(CRITERION_APPLY_5(Macro, Prefix, __VA_ARGS__)) +# define CRITERION_APPLY_7(Macro, Prefix, Head, ...) Macro(Prefix, Head) CR_EXPAND(CRITERION_APPLY_6(Macro, Prefix, __VA_ARGS__)) +# define CRITERION_APPLY_8(Macro, Prefix, Head, ...) Macro(Prefix, Head) CR_EXPAND(CRITERION_APPLY_7(Macro, Prefix, __VA_ARGS__)) +# define CRITERION_APPLY_9(Macro, Prefix, Head, ...) Macro(Prefix, Head) CR_EXPAND(CRITERION_APPLY_8(Macro, Prefix, __VA_ARGS__)) +# define CRITERION_APPLY_10(Macro, Prefix, Head, ...) Macro(Prefix, Head) CR_EXPAND(CRITERION_APPLY_9(Macro, Prefix, __VA_ARGS__)) +# define CRITERION_APPLY_11(Macro, Prefix, Head, ...) Macro(Prefix, Head) CR_EXPAND(CRITERION_APPLY_10(Macro, Prefix, __VA_ARGS__)) +# define CRITERION_APPLY_12(Macro, Prefix, Head, ...) Macro(Prefix, Head) CR_EXPAND(CRITERION_APPLY_11(Macro, Prefix, __VA_ARGS__)) +# define CRITERION_APPLY_13(Macro, Prefix, Head, ...) Macro(Prefix, Head) CR_EXPAND(CRITERION_APPLY_12(Macro, Prefix, __VA_ARGS__)) +# define CRITERION_APPLY_14(Macro, Prefix, Head, ...) Macro(Prefix, Head) CR_EXPAND(CRITERION_APPLY_13(Macro, Prefix, __VA_ARGS__)) +# define CRITERION_APPLY_15(Macro, Prefix, Head, ...) Macro(Prefix, Head) CR_EXPAND(CRITERION_APPLY_14(Macro, Prefix, __VA_ARGS__)) +# define CRITERION_APPLY_16(Macro, Prefix, Head, ...) Macro(Prefix, Head) CR_EXPAND(CRITERION_APPLY_15(Macro, Prefix, __VA_ARGS__)) +# define CRITERION_APPLY_17(Macro, Prefix, Head, ...) Macro(Prefix, Head) CR_EXPAND(CRITERION_APPLY_16(Macro, Prefix, __VA_ARGS__)) +# define CRITERION_APPLY_18(Macro, Prefix, Head, ...) Macro(Prefix, Head) CR_EXPAND(CRITERION_APPLY_17(Macro, Prefix, __VA_ARGS__)) +# define CRITERION_APPLY_19(Macro, Prefix, Head, ...) Macro(Prefix, Head) CR_EXPAND(CRITERION_APPLY_18(Macro, Prefix, __VA_ARGS__)) +# define CRITERION_APPLY_20(Macro, Prefix, Head, ...) Macro(Prefix, Head) CR_EXPAND(CRITERION_APPLY_19(Macro, Prefix, __VA_ARGS__)) +# define CRITERION_APPLY_21(Macro, Prefix, Head, ...) Macro(Prefix, Head) CR_EXPAND(CRITERION_APPLY_20(Macro, Prefix, __VA_ARGS__)) +# define CRITERION_APPLY_22(Macro, Prefix, Head, ...) Macro(Prefix, Head) CR_EXPAND(CRITERION_APPLY_21(Macro, Prefix, __VA_ARGS__)) +# define CRITERION_APPLY_23(Macro, Prefix, Head, ...) Macro(Prefix, Head) CR_EXPAND(CRITERION_APPLY_22(Macro, Prefix, __VA_ARGS__)) +# define CRITERION_APPLY_24(Macro, Prefix, Head, ...) Macro(Prefix, Head) CR_EXPAND(CRITERION_APPLY_23(Macro, Prefix, __VA_ARGS__)) +# define CRITERION_APPLY_25(Macro, Prefix, Head, ...) Macro(Prefix, Head) CR_EXPAND(CRITERION_APPLY_24(Macro, Prefix, __VA_ARGS__)) +# define CRITERION_APPLY_26(Macro, Prefix, Head, ...) Macro(Prefix, Head) CR_EXPAND(CRITERION_APPLY_25(Macro, Prefix, __VA_ARGS__)) +# define CRITERION_APPLY_27(Macro, Prefix, Head, ...) Macro(Prefix, Head) CR_EXPAND(CRITERION_APPLY_26(Macro, Prefix, __VA_ARGS__)) +# define CRITERION_APPLY_28(Macro, Prefix, Head, ...) Macro(Prefix, Head) CR_EXPAND(CRITERION_APPLY_27(Macro, Prefix, __VA_ARGS__)) +# define CRITERION_APPLY_29(Macro, Prefix, Head, ...) Macro(Prefix, Head) CR_EXPAND(CRITERION_APPLY_28(Macro, Prefix, __VA_ARGS__)) +# define CRITERION_APPLY_30(Macro, Prefix, Head, ...) Macro(Prefix, Head) CR_EXPAND(CRITERION_APPLY_29(Macro, Prefix, __VA_ARGS__)) +# define CRITERION_APPLY_31(Macro, Prefix, Head, ...) Macro(Prefix, Head) CR_EXPAND(CRITERION_APPLY_30(Macro, Prefix, __VA_ARGS__)) +# define CRITERION_APPLY_32(Macro, Prefix, Head, ...) Macro(Prefix, Head) CR_EXPAND(CRITERION_APPLY_31(Macro, Prefix, __VA_ARGS__)) +# define CRITERION_APPLY_33(Macro, Prefix, Head, ...) Macro(Prefix, Head) CR_EXPAND(CRITERION_APPLY_32(Macro, Prefix, __VA_ARGS__)) +# define CRITERION_APPLY_34(Macro, Prefix, Head, ...) Macro(Prefix, Head) CR_EXPAND(CRITERION_APPLY_33(Macro, Prefix, __VA_ARGS__)) +# define CRITERION_APPLY_35(Macro, Prefix, Head, ...) Macro(Prefix, Head) CR_EXPAND(CRITERION_APPLY_34(Macro, Prefix, __VA_ARGS__)) +# define CRITERION_APPLY_36(Macro, Prefix, Head, ...) Macro(Prefix, Head) CR_EXPAND(CRITERION_APPLY_35(Macro, Prefix, __VA_ARGS__)) +# define CRITERION_APPLY_37(Macro, Prefix, Head, ...) Macro(Prefix, Head) CR_EXPAND(CRITERION_APPLY_36(Macro, Prefix, __VA_ARGS__)) +# define CRITERION_APPLY_38(Macro, Prefix, Head, ...) Macro(Prefix, Head) CR_EXPAND(CRITERION_APPLY_37(Macro, Prefix, __VA_ARGS__)) +# define CRITERION_APPLY_39(Macro, Prefix, Head, ...) Macro(Prefix, Head) CR_EXPAND(CRITERION_APPLY_38(Macro, Prefix, __VA_ARGS__)) +# define CRITERION_APPLY_40(Macro, Prefix, Head, ...) Macro(Prefix, Head) CR_EXPAND(CRITERION_APPLY_39(Macro, Prefix, __VA_ARGS__)) +# define CRITERION_APPLY_41(Macro, Prefix, Head, ...) Macro(Prefix, Head) CR_EXPAND(CRITERION_APPLY_40(Macro, Prefix, __VA_ARGS__)) +# define CRITERION_APPLY_42(Macro, Prefix, Head, ...) Macro(Prefix, Head) CR_EXPAND(CRITERION_APPLY_41(Macro, Prefix, __VA_ARGS__)) +# define CRITERION_APPLY_43(Macro, Prefix, Head, ...) Macro(Prefix, Head) CR_EXPAND(CRITERION_APPLY_42(Macro, Prefix, __VA_ARGS__)) +# define CRITERION_APPLY_44(Macro, Prefix, Head, ...) Macro(Prefix, Head) CR_EXPAND(CRITERION_APPLY_43(Macro, Prefix, __VA_ARGS__)) +# define CRITERION_APPLY_45(Macro, Prefix, Head, ...) Macro(Prefix, Head) CR_EXPAND(CRITERION_APPLY_44(Macro, Prefix, __VA_ARGS__)) +# define CRITERION_APPLY_46(Macro, Prefix, Head, ...) Macro(Prefix, Head) CR_EXPAND(CRITERION_APPLY_45(Macro, Prefix, __VA_ARGS__)) +# define CRITERION_APPLY_47(Macro, Prefix, Head, ...) Macro(Prefix, Head) CR_EXPAND(CRITERION_APPLY_46(Macro, Prefix, __VA_ARGS__)) +# define CRITERION_APPLY_48(Macro, Prefix, Head, ...) Macro(Prefix, Head) CR_EXPAND(CRITERION_APPLY_47(Macro, Prefix, __VA_ARGS__)) +# define CRITERION_APPLY_49(Macro, Prefix, Head, ...) Macro(Prefix, Head) CR_EXPAND(CRITERION_APPLY_48(Macro, Prefix, __VA_ARGS__)) +# define CRITERION_APPLY_50(Macro, Prefix, Head, ...) Macro(Prefix, Head) CR_EXPAND(CRITERION_APPLY_49(Macro, Prefix, __VA_ARGS__)) +# define CRITERION_APPLY_51(Macro, Prefix, Head, ...) Macro(Prefix, Head) CR_EXPAND(CRITERION_APPLY_50(Macro, Prefix, __VA_ARGS__)) +# define CRITERION_APPLY_52(Macro, Prefix, Head, ...) Macro(Prefix, Head) CR_EXPAND(CRITERION_APPLY_51(Macro, Prefix, __VA_ARGS__)) +# define CRITERION_APPLY_53(Macro, Prefix, Head, ...) Macro(Prefix, Head) CR_EXPAND(CRITERION_APPLY_52(Macro, Prefix, __VA_ARGS__)) +# define CRITERION_APPLY_54(Macro, Prefix, Head, ...) Macro(Prefix, Head) CR_EXPAND(CRITERION_APPLY_53(Macro, Prefix, __VA_ARGS__)) +# define CRITERION_APPLY_55(Macro, Prefix, Head, ...) Macro(Prefix, Head) CR_EXPAND(CRITERION_APPLY_54(Macro, Prefix, __VA_ARGS__)) +# define CRITERION_APPLY_56(Macro, Prefix, Head, ...) Macro(Prefix, Head) CR_EXPAND(CRITERION_APPLY_55(Macro, Prefix, __VA_ARGS__)) +# define CRITERION_APPLY_57(Macro, Prefix, Head, ...) Macro(Prefix, Head) CR_EXPAND(CRITERION_APPLY_56(Macro, Prefix, __VA_ARGS__)) +# define CRITERION_APPLY_58(Macro, Prefix, Head, ...) Macro(Prefix, Head) CR_EXPAND(CRITERION_APPLY_57(Macro, Prefix, __VA_ARGS__)) +# define CRITERION_APPLY_59(Macro, Prefix, Head, ...) Macro(Prefix, Head) CR_EXPAND(CRITERION_APPLY_58(Macro, Prefix, __VA_ARGS__)) +# define CRITERION_APPLY_60(Macro, Prefix, Head, ...) Macro(Prefix, Head) CR_EXPAND(CRITERION_APPLY_59(Macro, Prefix, __VA_ARGS__)) +# define CRITERION_APPLY_61(Macro, Prefix, Head, ...) Macro(Prefix, Head) CR_EXPAND(CRITERION_APPLY_60(Macro, Prefix, __VA_ARGS__)) +# define CRITERION_APPLY_62(Macro, Prefix, Head, ...) Macro(Prefix, Head) CR_EXPAND(CRITERION_APPLY_61(Macro, Prefix, __VA_ARGS__)) +# define CRITERION_APPLY_63(Macro, Prefix, Head, ...) Macro(Prefix, Head) CR_EXPAND(CRITERION_APPLY_62(Macro, Prefix, __VA_ARGS__)) +# define CRITERION_APPLY_64(Macro, Prefix, Head, ...) Macro(Prefix, Head) CR_EXPAND(CRITERION_APPLY_63(Macro, Prefix, __VA_ARGS__)) +# define CRITERION_APPLY_65(Macro, Prefix, Head, ...) Macro(Prefix, Head) CR_EXPAND(CRITERION_APPLY_64(Macro, Prefix, __VA_ARGS__)) + +# define CRITERION_APPLY__(Macro, Prefix, n, ...) CR_EXPAND(CRITERION_APPLY_##n(Macro, Prefix, __VA_ARGS__)) +# define CRITERION_APPLY_(Macro, n, Prefix, ...) CR_EXPAND(CRITERION_APPLY__(Macro, Prefix, n, __VA_ARGS__)) +# define CRITERION_APPLY(Macro, ...) CR_EXPAND(CRITERION_APPLY_(Macro, CRITERION_ARG_LENGTH(__VA_ARGS__), __VA_ARGS__)) + +# define CRITERION_ADD_PREFIX_ONCE(Prefix, Field, ...) Prefix Field; +# define CRITERION_ADD_PREFIX(...) \ + CR_EXPAND(CRITERION_APPLY(CRITERION_ADD_PREFIX_ONCE, __VA_ARGS__)) + +# ifdef __cplusplus +# define CRITERION_MAKE_STRUCT(Type, ...) [&]() { \ + Type t; \ + CR_EXPAND(CRITERION_ADD_PREFIX(t, __VA_ARGS__)) \ + return t; \ + }() +# else +# define CRITERION_MAKE_STRUCT(Type, ...) { __VA_ARGS__ } +# endif + +#endif /* !CRITERION_DESIGNATED_INITIALIZER_COMPAT_HH_ */ diff --git a/include/criterion/event.h b/include/criterion/event.h index db6cfe3d..37881db3 100644 --- a/include/criterion/event.h +++ b/include/criterion/event.h @@ -24,12 +24,21 @@ #ifndef CRITERION_EVENT_H_ # define CRITERION_EVENT_H_ -# include -# include +# ifdef __cplusplus +# include +# include +# else +# include +# include +# endif # include "common.h" +CR_BEGIN_C_API + extern FILE *g_event_pipe; CR_API void send_event(int kind, void *data, size_t size); +CR_END_C_API + #endif /* !CRITERION_EVENT_H_ */ diff --git a/include/criterion/hooks.h b/include/criterion/hooks.h index 0c86841d..098790a9 100644 --- a/include/criterion/hooks.h +++ b/include/criterion/hooks.h @@ -25,6 +25,7 @@ # define CRITERION_HOOKS_H_ # include "common.h" +# include "types.h" typedef enum { PRE_ALL, @@ -46,8 +47,13 @@ typedef void (*f_report_hook)(); # define HOOK_IDENTIFIER__(Line, Suffix) HOOK_IDENTIFIER___(Line, Suffix) # define HOOK_IDENTIFIER___(Line, Suffix) hook_l ## Line ## _ ## Suffix -# define HOOK_PROTOTYPE_ \ +# ifdef __cplusplus +# define HOOK_PROTOTYPE_ \ + extern "C" void HOOK_IDENTIFIER_(impl) +# else +# define HOOK_PROTOTYPE_ \ void HOOK_IDENTIFIER_(impl) +# endif // Section abbreviations # define HOOK_SECTION_PRE_ALL cr_pra @@ -68,10 +74,24 @@ typedef void (*f_report_hook)(); # define HOOK_SECTION_STRINGIFY_(Sec) HOOK_SECTION_STRINGIFY__(Sec) # define HOOK_SECTION_STRINGIFY(Kind) HOOK_SECTION_STRINGIFY_(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 HOOK_PARAM_TYPE(Kind) HOOK_PARAM_TYPE_ ## Kind + # define ReportHook(Kind) \ - HOOK_PROTOTYPE_(); \ + HOOK_PROTOTYPE_(HOOK_PARAM_TYPE(Kind)); \ SECTION_(HOOK_SECTION_STRINGIFY(Kind)) \ - const f_report_hook HOOK_IDENTIFIER_(func) = HOOK_IDENTIFIER_(impl); \ + const f_report_hook HOOK_IDENTIFIER_(func) = (f_report_hook) HOOK_IDENTIFIER_(impl); \ HOOK_PROTOTYPE_ #endif /* !CRITERION_HOOKS_H_ */ diff --git a/include/criterion/logging.h b/include/criterion/logging.h index 7cd74f7e..c8c02052 100644 --- a/include/criterion/logging.h +++ b/include/criterion/logging.h @@ -24,8 +24,13 @@ #ifndef CRITERION_LOGGING_H_ # define CRITERION_LOGGING_H_ -# include -# include +# ifdef __cplusplus +# include +using std::va_list; +# else +# include +# include +# endif # include "common.h" # include "ordered-set.h" # include "stats.h" @@ -67,6 +72,8 @@ struct criterion_prefix_data { # define RESET CRIT_COLOR_NORMALIZE(CRIT_RESET) # endif +CR_BEGIN_C_API + extern const struct criterion_prefix_data g_criterion_logging_prefixes[]; # define CRITERION_PREFIX_DASHES (&g_criterion_logging_prefixes[CRITERION_LOGGING_PREFIX_DASHES]) @@ -109,6 +116,8 @@ struct criterion_output_provider { extern struct criterion_output_provider normal_logging; extern struct criterion_output_provider tap_logging; +CR_END_C_API + #define NORMAL_LOGGING (&normal_logging) #define TAP_LOGGING (&tap_logging) diff --git a/include/criterion/options.h b/include/criterion/options.h index 31b90d2c..0bdcdeef 100644 --- a/include/criterion/options.h +++ b/include/criterion/options.h @@ -38,6 +38,10 @@ struct criterion_options { bool short_filename; }; +CR_BEGIN_C_API + extern struct criterion_options criterion_options; +CR_END_C_API + #endif /*!CRITERION_OPTIONS_H_ */ diff --git a/include/criterion/ordered-set.h b/include/criterion/ordered-set.h index 514f601c..24044f81 100644 --- a/include/criterion/ordered-set.h +++ b/include/criterion/ordered-set.h @@ -40,15 +40,7 @@ struct criterion_ordered_set_node { char data[0]; }; -struct criterion_suite_set { - struct criterion_suite suite; - struct criterion_ordered_set *tests; -}; - -struct criterion_test_set { - struct criterion_ordered_set *suites; - size_t tests; -}; +CR_BEGIN_C_API CR_API struct criterion_ordered_set *new_ordered_set(f_criterion_cmp cmp, void (*dtor)(void *, void *)); @@ -57,6 +49,8 @@ CR_API void *insert_ordered_set(struct criterion_ordered_set *l, void *ptr, size_t size); +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;) \ diff --git a/include/criterion/theories.h b/include/criterion/theories.h index 6e233459..f23c2236 100644 --- a/include/criterion/theories.h +++ b/include/criterion/theories.h @@ -27,6 +27,8 @@ # include # include "criterion.h" +CR_BEGIN_C_API + struct criterion_theory_context; CR_API struct criterion_theory_context* cr_theory_init(void); @@ -114,4 +116,6 @@ CR_API void cr_theory_main(struct criterion_datapoints *dps, size_t datapoints, } \ void CR_EXPAND(CR_VAARG_ID(theory, __VA_ARGS__,))Args +CR_END_C_API + #endif /* !CRITERION_THEORIES_H_ */ diff --git a/include/criterion/types.h b/include/criterion/types.h index 9acd208e..aa05e034 100644 --- a/include/criterion/types.h +++ b/include/criterion/types.h @@ -24,8 +24,13 @@ #ifndef CRITERION_TYPES_H_ # define CRITERION_TYPES_H_ -# include -# include +# ifdef __cplusplus +# include +using std::size_t; +# else +# include +# include +# endif # include "common.h" struct criterion_test_extra_data { @@ -54,6 +59,18 @@ struct criterion_suite { struct criterion_test_extra_data *data; }; +struct criterion_ordered_set; + +struct criterion_suite_set { + struct criterion_suite suite; + struct criterion_ordered_set *tests; +}; + +struct criterion_test_set { + struct criterion_ordered_set *suites; + size_t tests; +}; + typedef void (*f_worker_func)(struct criterion_test *, struct criterion_suite *); #endif /* !CRITERION_TYPES_H_ */ diff --git a/samples/CMakeLists.txt b/samples/CMakeLists.txt index d8e1d145..386710a8 100644 --- a/samples/CMakeLists.txt +++ b/samples/CMakeLists.txt @@ -1,5 +1,6 @@ if (NOT MSVC) set(CMAKE_C_FLAGS "-std=c99 -Wall -Wextra -pedantic") + set(CMAKE_CXX_FLAGS "-std=c++11 -Wall -Wextra -pedantic") endif () include_directories(../include) @@ -40,6 +41,13 @@ foreach(sample ${SAMPLES}) ENVIRONMENT "CRITERION_ALWAYS_SUCCEED=1" ) + add_executable(${sample}_cpp ${sample}.cc) + target_link_libraries(${sample}_cpp criterion) + add_test(${sample}_cpp ${sample}_cpp) + set_property(TEST ${sample} PROPERTY + ENVIRONMENT "CRITERION_ALWAYS_SUCCEED=1" + ) + if (NOT MSVC) # we disable the scripted tests when building with MSVC add_test(${sample}_compare sh ${CMAKE_CURRENT_LIST_DIR}/tests/run_test.sh "${CMAKE_CURRENT_LIST_DIR}" . . ${sample}) set_property(TEST ${sample}_compare PROPERTY diff --git a/samples/asserts.c b/samples/asserts.c index 6b44cb90..ef5bc985 100644 --- a/samples/asserts.c +++ b/samples/asserts.c @@ -6,8 +6,6 @@ Test(asserts, base) { cr_assert(true, "Assertions may take failure messages"); - cr_assert(true, .msg = "You can use explicit named arguments"); - cr_expect(false, "assert is fatal, expect isn't"); cr_assert(false, "This assert runs"); cr_assert(false, "This does not"); diff --git a/samples/report.c b/samples/report.c index 4c7a8499..8c9ace8a 100644 --- a/samples/report.c +++ b/samples/report.c @@ -15,10 +15,12 @@ ReportHook(POST_TEST)(struct criterion_test_stats *stats) { stats->passed_asserts, stats->failed_asserts, stats->passed_asserts + stats->failed_asserts); } -ReportHook(PRE_ALL)() { +ReportHook(PRE_ALL)(struct criterion_test_set *tests) { + (void) tests; puts("criterion_init"); } -ReportHook(POST_ALL)() { +ReportHook(POST_ALL)(struct criterion_global_stats *stats) { + (void) stats; puts("criterion_fini"); } diff --git a/src/report.c b/src/report.c index 5809bfde..9a6f80ec 100644 --- a/src/report.c +++ b/src/report.c @@ -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)() {} -ReportHook(PRE_SUITE)() {} -ReportHook(PRE_INIT)() {} -ReportHook(PRE_TEST)() {} -ReportHook(ASSERT)() {} -ReportHook(THEORY_FAIL)() {} -ReportHook(TEST_CRASH)() {} -ReportHook(POST_TEST)() {} -ReportHook(POST_FINI)() {} -ReportHook(POST_SUITE)() {} -ReportHook(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) {} From 496710164ed74e46cab80a8e42a35d43e2f4af92 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Mon, 7 Sep 2015 01:42:15 +0200 Subject: [PATCH 080/174] Refactored samples for cmake compilation --- samples/CMakeLists.txt | 51 ++++++++++--------- ...rr.expected => asserts.c.bin.err.expected} | 6 +-- ...ut.expected => asserts.c.bin.out.expected} | 0 samples/asserts.cc.bin.err.expected | 6 +++ ...t.expected => asserts.cc.bin.out.expected} | 0 ...xpected => description.c.bin.err.expected} | 0 ...xpected => description.c.bin.out.expected} | 0 samples/description.cc.bin.err.expected | 3 ++ ...pected => description.cc.bin.out.expected} | 0 ...t.err.expected => exit.c.bin.err.expected} | 0 ...s.out.expected => exit.c.bin.out.expected} | 0 samples/exit.cc.bin.err.expected | 4 ++ ....out.expected => exit.cc.bin.out.expected} | 0 ...r.expected => fixtures.c.bin.err.expected} | 0 ...t.expected => fixtures.c.bin.out.expected} | 0 samples/fixtures.cc.bin.err.expected | 1 + samples/fixtures.cc.bin.out.expected | 2 + ...ected => long-messages.c.bin.err.expected} | 0 ...ected => long-messages.c.bin.out.expected} | 0 samples/long-messages.cc.bin.err.expected | 6 +++ ...cted => long-messages.cc.bin.out.expected} | 0 ...xpected => more-suites.c.bin.err.expected} | 0 ...xpected => more-suites.c.bin.out.expected} | 0 ...pected => more-suites.cc.bin.err.expected} | 0 samples/more-suites.cc.bin.out.expected | 0 ...ected => other-crashes.c.bin.err.expected} | 0 samples/other-crashes.c.bin.out.expected | 0 samples/other-crashes.cc.bin.err.expected | 3 ++ samples/other-crashes.cc.bin.out.expected | 0 ...err.expected => report.c.bin.err.expected} | 0 ...out.expected => report.c.bin.out.expected} | 0 samples/report.cc.bin.err.expected | 3 ++ samples/report.cc.bin.out.expected | 4 ++ ...err.expected => signal.c.bin.err.expected} | 0 samples/signal.c.bin.out.expected | 0 samples/signal.cc.bin.err.expected | 4 ++ samples/signal.cc.bin.out.expected | 0 ...err.expected => simple.c.bin.err.expected} | 0 samples/simple.c.bin.out.expected | 0 samples/simple.cc.bin.err.expected | 3 ++ samples/simple.cc.bin.out.expected | 0 samples/suites.c.bin.err.expected | 1 + samples/suites.c.bin.out.expected | 0 samples/suites.cc.bin.err.expected | 1 + samples/suites.cc.bin.out.expected | 0 samples/tests/early_exit.sh | 4 +- samples/tests/fail_fast.sh | 2 +- samples/tests/help.sh | 4 +- samples/tests/list.sh | 4 +- samples/tests/pattern.sh | 18 +++---- samples/tests/tap_test.sh | 12 ++--- samples/tests/verbose.sh | 2 +- 52 files changed, 95 insertions(+), 49 deletions(-) rename samples/{asserts.err.expected => asserts.c.bin.err.expected} (57%) rename samples/{asserts.out.expected => asserts.c.bin.out.expected} (100%) create mode 100644 samples/asserts.cc.bin.err.expected rename samples/{description.out.expected => asserts.cc.bin.out.expected} (100%) rename samples/{description.err.expected => description.c.bin.err.expected} (100%) rename samples/{exit.out.expected => description.c.bin.out.expected} (100%) create mode 100644 samples/description.cc.bin.err.expected rename samples/{long-messages.out.expected => description.cc.bin.out.expected} (100%) rename samples/{exit.err.expected => exit.c.bin.err.expected} (100%) rename samples/{more-suites.out.expected => exit.c.bin.out.expected} (100%) create mode 100644 samples/exit.cc.bin.err.expected rename samples/{other-crashes.out.expected => exit.cc.bin.out.expected} (100%) rename samples/{fixtures.err.expected => fixtures.c.bin.err.expected} (100%) rename samples/{fixtures.out.expected => fixtures.c.bin.out.expected} (100%) create mode 100644 samples/fixtures.cc.bin.err.expected create mode 100644 samples/fixtures.cc.bin.out.expected rename samples/{long-messages.err.expected => long-messages.c.bin.err.expected} (100%) rename samples/{signal.out.expected => long-messages.c.bin.out.expected} (100%) create mode 100644 samples/long-messages.cc.bin.err.expected rename samples/{simple.out.expected => long-messages.cc.bin.out.expected} (100%) rename samples/{more-suites.err.expected => more-suites.c.bin.err.expected} (100%) rename samples/{suites.out.expected => more-suites.c.bin.out.expected} (100%) rename samples/{suites.err.expected => more-suites.cc.bin.err.expected} (100%) create mode 100644 samples/more-suites.cc.bin.out.expected rename samples/{other-crashes.err.expected => other-crashes.c.bin.err.expected} (100%) create mode 100644 samples/other-crashes.c.bin.out.expected create mode 100644 samples/other-crashes.cc.bin.err.expected create mode 100644 samples/other-crashes.cc.bin.out.expected rename samples/{report.err.expected => report.c.bin.err.expected} (100%) rename samples/{report.out.expected => report.c.bin.out.expected} (100%) create mode 100644 samples/report.cc.bin.err.expected create mode 100644 samples/report.cc.bin.out.expected rename samples/{signal.err.expected => signal.c.bin.err.expected} (100%) create mode 100644 samples/signal.c.bin.out.expected create mode 100644 samples/signal.cc.bin.err.expected create mode 100644 samples/signal.cc.bin.out.expected rename samples/{simple.err.expected => simple.c.bin.err.expected} (100%) create mode 100644 samples/simple.c.bin.out.expected create mode 100644 samples/simple.cc.bin.err.expected create mode 100644 samples/simple.cc.bin.out.expected create mode 100644 samples/suites.c.bin.err.expected create mode 100644 samples/suites.c.bin.out.expected create mode 100644 samples/suites.cc.bin.err.expected create mode 100644 samples/suites.cc.bin.out.expected diff --git a/samples/CMakeLists.txt b/samples/CMakeLists.txt index 386710a8..889f39f7 100644 --- a/samples/CMakeLists.txt +++ b/samples/CMakeLists.txt @@ -6,18 +6,30 @@ endif () include_directories(../include) set(SAMPLES - signal - exit - report - suites - fixtures - asserts - more-suites - long-messages - description - other-crashes - simple - theories + signal.c + exit.c + report.c + suites.c + fixtures.c + asserts.c + more-suites.c + long-messages.c + description.c + other-crashes.c + simple.c + theories.c + + signal.cc + exit.cc + report.cc + suites.cc + fixtures.cc + asserts.cc + more-suites.cc + long-messages.cc + description.cc + other-crashes.cc + simple.cc ) set(SCRIPTS @@ -34,22 +46,15 @@ if (HAVE_PCRE) endif () foreach(sample ${SAMPLES}) - add_executable(${sample} ${sample}.c) - target_link_libraries(${sample} criterion) - add_test(${sample} ${sample}) - set_property(TEST ${sample} PROPERTY - ENVIRONMENT "CRITERION_ALWAYS_SUCCEED=1" - ) - - add_executable(${sample}_cpp ${sample}.cc) - target_link_libraries(${sample}_cpp criterion) - add_test(${sample}_cpp ${sample}_cpp) + add_executable(${sample}.bin ${sample}) + target_link_libraries(${sample}.bin criterion) + add_test(${sample} ${sample}.bin) set_property(TEST ${sample} PROPERTY ENVIRONMENT "CRITERION_ALWAYS_SUCCEED=1" ) if (NOT MSVC) # we disable the scripted tests when building with MSVC - add_test(${sample}_compare sh ${CMAKE_CURRENT_LIST_DIR}/tests/run_test.sh "${CMAKE_CURRENT_LIST_DIR}" . . ${sample}) + add_test(${sample}_compare sh ${CMAKE_CURRENT_LIST_DIR}/tests/run_test.sh "${CMAKE_CURRENT_LIST_DIR}" . . ${sample}.bin) set_property(TEST ${sample}_compare PROPERTY ENVIRONMENT "LC_ALL=en_US.utf8" ENVIRONMENT "CRITERION_ALWAYS_SUCCEED=1" diff --git a/samples/asserts.err.expected b/samples/asserts.c.bin.err.expected similarity index 57% rename from samples/asserts.err.expected rename to samples/asserts.c.bin.err.expected index 644a4407..0f81d723 100644 --- a/samples/asserts.err.expected +++ b/samples/asserts.c.bin.err.expected @@ -1,6 +1,6 @@ -[----] asserts.c:11: Assertion failed: assert is fatal, expect isn't -[----] asserts.c:12: Assertion failed: This assert runs +[----] asserts.c:9: Assertion failed: assert is fatal, expect isn't +[----] asserts.c:10: Assertion failed: This assert runs [FAIL] asserts::base: (0.00s) -[----] asserts.c:20: Assertion failed: The conditions for this test were not met. +[----] asserts.c:18: Assertion failed: The conditions for this test were not met. [FAIL] asserts::old_school: (0.00s) [====] Synthesis: Tested: 6 | Passing: 4 | Failing: 2 | Crashing: 0  diff --git a/samples/asserts.out.expected b/samples/asserts.c.bin.out.expected similarity index 100% rename from samples/asserts.out.expected rename to samples/asserts.c.bin.out.expected diff --git a/samples/asserts.cc.bin.err.expected b/samples/asserts.cc.bin.err.expected new file mode 100644 index 00000000..3b7d7aef --- /dev/null +++ b/samples/asserts.cc.bin.err.expected @@ -0,0 +1,6 @@ +[----] asserts.cc:9: Assertion failed: assert is fatal, expect isn't +[----] asserts.cc:10: Assertion failed: This assert runs +[FAIL] asserts::base: (0.00s) +[----] asserts.cc:18: Assertion failed: The conditions for this test were not met. +[FAIL] asserts::old_school: (0.00s) +[====] Synthesis: Tested: 6 | Passing: 4 | Failing: 2 | Crashing: 0  diff --git a/samples/description.out.expected b/samples/asserts.cc.bin.out.expected similarity index 100% rename from samples/description.out.expected rename to samples/asserts.cc.bin.out.expected diff --git a/samples/description.err.expected b/samples/description.c.bin.err.expected similarity index 100% rename from samples/description.err.expected rename to samples/description.c.bin.err.expected diff --git a/samples/exit.out.expected b/samples/description.c.bin.out.expected similarity index 100% rename from samples/exit.out.expected rename to samples/description.c.bin.out.expected diff --git a/samples/description.cc.bin.err.expected b/samples/description.cc.bin.err.expected new file mode 100644 index 00000000..730b527f --- /dev/null +++ b/samples/description.cc.bin.err.expected @@ -0,0 +1,3 @@ +[----] description.cc:4: Assertion failed: 0 +[FAIL] misc::failing: (0.00s) +[====] Synthesis: Tested: 1 | Passing: 0 | Failing: 1 | Crashing: 0  diff --git a/samples/long-messages.out.expected b/samples/description.cc.bin.out.expected similarity index 100% rename from samples/long-messages.out.expected rename to samples/description.cc.bin.out.expected diff --git a/samples/exit.err.expected b/samples/exit.c.bin.err.expected similarity index 100% rename from samples/exit.err.expected rename to samples/exit.c.bin.err.expected diff --git a/samples/more-suites.out.expected b/samples/exit.c.bin.out.expected similarity index 100% rename from samples/more-suites.out.expected rename to samples/exit.c.bin.out.expected diff --git a/samples/exit.cc.bin.err.expected b/samples/exit.cc.bin.err.expected new file mode 100644 index 00000000..3ffe51b6 --- /dev/null +++ b/samples/exit.cc.bin.err.expected @@ -0,0 +1,4 @@ +[----] Warning! The test `exit::unexpected_exit` exited during its setup or teardown. +[----] Warning! The test `exit_with_fixtures::fini_exits` exited during its setup or teardown. +[----] Warning! The test `exit_with_fixtures::init_exits` exited during its setup or teardown. +[====] Synthesis: Tested: 5 | Passing: 3 | Failing: 2 | Crashing: 2  diff --git a/samples/other-crashes.out.expected b/samples/exit.cc.bin.out.expected similarity index 100% rename from samples/other-crashes.out.expected rename to samples/exit.cc.bin.out.expected diff --git a/samples/fixtures.err.expected b/samples/fixtures.c.bin.err.expected similarity index 100% rename from samples/fixtures.err.expected rename to samples/fixtures.c.bin.err.expected diff --git a/samples/fixtures.out.expected b/samples/fixtures.c.bin.out.expected similarity index 100% rename from samples/fixtures.out.expected rename to samples/fixtures.c.bin.out.expected diff --git a/samples/fixtures.cc.bin.err.expected b/samples/fixtures.cc.bin.err.expected new file mode 100644 index 00000000..a34f221b --- /dev/null +++ b/samples/fixtures.cc.bin.err.expected @@ -0,0 +1 @@ +[====] Synthesis: Tested: 1 | Passing: 1 | Failing: 0 | Crashing: 0  diff --git a/samples/fixtures.cc.bin.out.expected b/samples/fixtures.cc.bin.out.expected new file mode 100644 index 00000000..a74afed9 --- /dev/null +++ b/samples/fixtures.cc.bin.out.expected @@ -0,0 +1,2 @@ +Runs before the test +Runs after the test diff --git a/samples/long-messages.err.expected b/samples/long-messages.c.bin.err.expected similarity index 100% rename from samples/long-messages.err.expected rename to samples/long-messages.c.bin.err.expected diff --git a/samples/signal.out.expected b/samples/long-messages.c.bin.out.expected similarity index 100% rename from samples/signal.out.expected rename to samples/long-messages.c.bin.out.expected diff --git a/samples/long-messages.cc.bin.err.expected b/samples/long-messages.cc.bin.err.expected new file mode 100644 index 00000000..fa56cf28 --- /dev/null +++ b/samples/long-messages.cc.bin.err.expected @@ -0,0 +1,6 @@ +[----] long-messages.cc:4: Assertion failed: This is +[----] A long message +[----] Spawning multiple lines. +[----] Formatting is respected. +[FAIL] sample::long_msg: (0.00s) +[====] Synthesis: Tested: 1 | Passing: 0 | Failing: 1 | Crashing: 0  diff --git a/samples/simple.out.expected b/samples/long-messages.cc.bin.out.expected similarity index 100% rename from samples/simple.out.expected rename to samples/long-messages.cc.bin.out.expected diff --git a/samples/more-suites.err.expected b/samples/more-suites.c.bin.err.expected similarity index 100% rename from samples/more-suites.err.expected rename to samples/more-suites.c.bin.err.expected diff --git a/samples/suites.out.expected b/samples/more-suites.c.bin.out.expected similarity index 100% rename from samples/suites.out.expected rename to samples/more-suites.c.bin.out.expected diff --git a/samples/suites.err.expected b/samples/more-suites.cc.bin.err.expected similarity index 100% rename from samples/suites.err.expected rename to samples/more-suites.cc.bin.err.expected diff --git a/samples/more-suites.cc.bin.out.expected b/samples/more-suites.cc.bin.out.expected new file mode 100644 index 00000000..e69de29b diff --git a/samples/other-crashes.err.expected b/samples/other-crashes.c.bin.err.expected similarity index 100% rename from samples/other-crashes.err.expected rename to samples/other-crashes.c.bin.err.expected diff --git a/samples/other-crashes.c.bin.out.expected b/samples/other-crashes.c.bin.out.expected new file mode 100644 index 00000000..e69de29b diff --git a/samples/other-crashes.cc.bin.err.expected b/samples/other-crashes.cc.bin.err.expected new file mode 100644 index 00000000..41d3cb89 --- /dev/null +++ b/samples/other-crashes.cc.bin.err.expected @@ -0,0 +1,3 @@ +[----] Warning! The test `misc::setup_crash` crashed during its setup or teardown. +[----] Warning! The test `misc::teardown_crash` crashed during its setup or teardown. +[====] Synthesis: Tested: 2 | Passing: 1 | Failing: 1 | Crashing: 1  diff --git a/samples/other-crashes.cc.bin.out.expected b/samples/other-crashes.cc.bin.out.expected new file mode 100644 index 00000000..e69de29b diff --git a/samples/report.err.expected b/samples/report.c.bin.err.expected similarity index 100% rename from samples/report.err.expected rename to samples/report.c.bin.err.expected diff --git a/samples/report.out.expected b/samples/report.c.bin.out.expected similarity index 100% rename from samples/report.out.expected rename to samples/report.c.bin.out.expected diff --git a/samples/report.cc.bin.err.expected b/samples/report.cc.bin.err.expected new file mode 100644 index 00000000..d81ba267 --- /dev/null +++ b/samples/report.cc.bin.err.expected @@ -0,0 +1,3 @@ +[----] report.cc:5: Assertion failed: 0 +[FAIL] sample::test: (0.00s) +[====] Synthesis: Tested: 1 | Passing: 0 | Failing: 1 | Crashing: 0  diff --git a/samples/report.cc.bin.out.expected b/samples/report.cc.bin.out.expected new file mode 100644 index 00000000..d560277c --- /dev/null +++ b/samples/report.cc.bin.out.expected @@ -0,0 +1,4 @@ +criterion_init +testing test in category sample +Asserts: [1 passed, 1 failed, 2 total] +criterion_fini diff --git a/samples/signal.err.expected b/samples/signal.c.bin.err.expected similarity index 100% rename from samples/signal.err.expected rename to samples/signal.c.bin.err.expected diff --git a/samples/signal.c.bin.out.expected b/samples/signal.c.bin.out.expected new file mode 100644 index 00000000..e69de29b diff --git a/samples/signal.cc.bin.err.expected b/samples/signal.cc.bin.err.expected new file mode 100644 index 00000000..8ac44c18 --- /dev/null +++ b/samples/signal.cc.bin.err.expected @@ -0,0 +1,4 @@ +[----] signal.cc:16: Unexpected signal caught below this line! +[FAIL] simple::uncaught: CRASH! +[FAIL] simple::wrong_signal: (0.00s) +[====] Synthesis: Tested: 3 | Passing: 1 | Failing: 2 | Crashing: 1  diff --git a/samples/signal.cc.bin.out.expected b/samples/signal.cc.bin.out.expected new file mode 100644 index 00000000..e69de29b diff --git a/samples/simple.err.expected b/samples/simple.c.bin.err.expected similarity index 100% rename from samples/simple.err.expected rename to samples/simple.c.bin.err.expected diff --git a/samples/simple.c.bin.out.expected b/samples/simple.c.bin.out.expected new file mode 100644 index 00000000..e69de29b diff --git a/samples/simple.cc.bin.err.expected b/samples/simple.cc.bin.err.expected new file mode 100644 index 00000000..c52de64f --- /dev/null +++ b/samples/simple.cc.bin.err.expected @@ -0,0 +1,3 @@ +[----] simple.cc:4: Assertion failed: 0 +[FAIL] misc::failing: (0.00s) +[====] Synthesis: Tested: 2 | Passing: 1 | Failing: 1 | Crashing: 0  diff --git a/samples/simple.cc.bin.out.expected b/samples/simple.cc.bin.out.expected new file mode 100644 index 00000000..e69de29b diff --git a/samples/suites.c.bin.err.expected b/samples/suites.c.bin.err.expected new file mode 100644 index 00000000..09eb50f6 --- /dev/null +++ b/samples/suites.c.bin.err.expected @@ -0,0 +1 @@ +[====] Synthesis: Tested: 2 | Passing: 2 | Failing: 0 | Crashing: 0  diff --git a/samples/suites.c.bin.out.expected b/samples/suites.c.bin.out.expected new file mode 100644 index 00000000..e69de29b diff --git a/samples/suites.cc.bin.err.expected b/samples/suites.cc.bin.err.expected new file mode 100644 index 00000000..09eb50f6 --- /dev/null +++ b/samples/suites.cc.bin.err.expected @@ -0,0 +1 @@ +[====] Synthesis: Tested: 2 | Passing: 2 | Failing: 0 | Crashing: 0  diff --git a/samples/suites.cc.bin.out.expected b/samples/suites.cc.bin.out.expected new file mode 100644 index 00000000..e69de29b diff --git a/samples/tests/early_exit.sh b/samples/tests/early_exit.sh index f25738cc..71bb31d1 100755 --- a/samples/tests/early_exit.sh +++ b/samples/tests/early_exit.sh @@ -1,3 +1,3 @@ #!/bin/sh -./simple --no-early-exit --always-succeed -./theories --no-early-exit --always-succeed +./simple.c.bin --no-early-exit --always-succeed +./theories.c.bin --no-early-exit --always-succeed diff --git a/samples/tests/fail_fast.sh b/samples/tests/fail_fast.sh index 3fecfd8c..fcc02e17 100755 --- a/samples/tests/fail_fast.sh +++ b/samples/tests/fail_fast.sh @@ -1,2 +1,2 @@ #!/bin/sh -./simple --fail-fast --always-succeed +./simple.c.bin --fail-fast --always-succeed diff --git a/samples/tests/help.sh b/samples/tests/help.sh index 6b60bb51..6752cc60 100755 --- a/samples/tests/help.sh +++ b/samples/tests/help.sh @@ -1,3 +1,3 @@ #!/bin/sh -./simple --help -./simple --version +./simple.c.bin --help +./simple.c.bin --version diff --git a/samples/tests/list.sh b/samples/tests/list.sh index 2040e540..6ab72bf3 100755 --- a/samples/tests/list.sh +++ b/samples/tests/list.sh @@ -1,3 +1,3 @@ #!/bin/sh -./simple --list -./simple --list --ascii +./simple.c.bin --list +./simple.c.bin --list --ascii diff --git a/samples/tests/pattern.sh b/samples/tests/pattern.sh index 09996f13..c1b10a9f 100755 --- a/samples/tests/pattern.sh +++ b/samples/tests/pattern.sh @@ -1,10 +1,10 @@ #!/bin/sh -e -./simple --pattern '*/passing' -./simple --pattern '!(*/passing)' -./simple --pattern '[pf]a@(ss|il)ing' -./simple --pattern '@(+(nest)ed))' -./simple --pattern '?(*(a|b))' -! ./simple --pattern '?(malformed' -./simple --pattern '[!azerty]assing' -./simple --pattern '|pipe' -./simple --pattern '\!(escaped' +./simple.c.bin --pattern '*/passing' +./simple.c.bin --pattern '!(*/passing)' +./simple.c.bin --pattern '[pf]a@(ss|il)ing' +./simple.c.bin --pattern '@(+(nest)ed))' +./simple.c.bin --pattern '?(*(a|b))' +! ./simple.c.bin --pattern '?(malformed' +./simple.c.bin --pattern '[!azerty]assing' +./simple.c.bin --pattern '|pipe' +./simple.c.bin --pattern '\!(escaped' diff --git a/samples/tests/tap_test.sh b/samples/tests/tap_test.sh index 38c0ac30..5e81fbf6 100755 --- a/samples/tests/tap_test.sh +++ b/samples/tests/tap_test.sh @@ -1,7 +1,7 @@ #!/bin/sh -./simple --tap --always-succeed -./signal --tap --always-succeed -./asserts --tap --always-succeed -./more-suites --tap --always-succeed -./long-messages --tap --always-succeed -./description --tap --always-succeed +./simple.c.bin --tap --always-succeed +./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 +./description.c.bin --tap --always-succeed diff --git a/samples/tests/verbose.sh b/samples/tests/verbose.sh index 73410b8c..6bb1ef28 100755 --- a/samples/tests/verbose.sh +++ b/samples/tests/verbose.sh @@ -1,2 +1,2 @@ #!/bin/sh -./simple --verbose --always-succeed +./simple.c.bin --verbose --always-succeed From 8e66ff173f2fe0b91a3cad37687dae5c89240ad4 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Mon, 7 Sep 2015 01:57:05 +0200 Subject: [PATCH 081/174] Restored cr_abort_test default message --- include/criterion/assert.h | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/include/criterion/assert.h b/include/criterion/assert.h index 23b42569..ea3e0ccb 100644 --- a/include/criterion/assert.h +++ b/include/criterion/assert.h @@ -80,8 +80,11 @@ struct criterion_assert_args { // Common asserts -# define cr_abort_test(Message) \ - cr_assert(0, (Message)) +# define cr_abort_test(Message) \ + do { \ + const char *msg = (Message); \ + cr_assert(0, msg ? msg : "The conditions for this test were not met.");\ + } while (0) # define cr_assert(...) CR_EXPAND(cr_assert_(__VA_ARGS__, 0)) From b9292bb42d397caa755d324f6b1fbc7ff6fcf5c6 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Mon, 7 Sep 2015 01:58:15 +0200 Subject: [PATCH 082/174] Temporarily removed -pedantic from c++ samples --- samples/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/CMakeLists.txt b/samples/CMakeLists.txt index 889f39f7..5ab40fb5 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_CXX_FLAGS "-std=c++11 -Wall -Wextra") endif () include_directories(../include) From fd9cf1755afa1e3ea955ca6a36350be962331570 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Mon, 7 Sep 2015 02:00:03 +0200 Subject: [PATCH 083/174] Added missing .cc samples --- .gitignore | 1 + samples/asserts.cc | 80 ++++++++++++++++++++++++++++++++++++++++ samples/description.cc | 8 ++++ samples/exit.cc | 24 ++++++++++++ samples/fixtures.cc | 14 +++++++ samples/long-messages.cc | 5 +++ samples/more-suites.cc | 21 +++++++++++ samples/other-crashes.cc | 14 +++++++ samples/report.cc | 26 +++++++++++++ samples/signal.cc | 19 ++++++++++ samples/simple.cc | 9 +++++ samples/suites.cc | 9 +++++ 12 files changed, 230 insertions(+) create mode 100644 samples/asserts.cc create mode 100644 samples/description.cc create mode 100644 samples/exit.cc create mode 100644 samples/fixtures.cc create mode 100644 samples/long-messages.cc create mode 100644 samples/more-suites.cc create mode 100644 samples/other-crashes.cc create mode 100644 samples/report.cc create mode 100644 samples/signal.cc create mode 100644 samples/simple.cc create mode 100644 samples/suites.cc diff --git a/.gitignore b/.gitignore index 9e813d93..fdaf4999 100644 --- a/.gitignore +++ b/.gitignore @@ -6,6 +6,7 @@ !.ci/* !*.c +!*.cc !*.h !*.rst !samples/tests/*.sh diff --git a/samples/asserts.cc b/samples/asserts.cc new file mode 100644 index 00000000..ef5bc985 --- /dev/null +++ b/samples/asserts.cc @@ -0,0 +1,80 @@ +#include + +Test(asserts, base) { + cr_assert(true); + cr_expect(true); + + cr_assert(true, "Assertions may take failure messages"); + + cr_expect(false, "assert is fatal, expect isn't"); + cr_assert(false, "This assert runs"); + cr_assert(false, "This does not"); +} + +Test(asserts, old_school) { + if (false) + cr_abort_test("You can abort the test with a message from anywhere"); + + cr_abort_test(NULL); // or without a message +} + +Test(asserts, string) { + cr_assert_strings_eq("hello", "hello"); + cr_assert_strings_neq("hello", "olleh"); + + cr_assert_strings_gt("hello", "hell"); + cr_assert_strings_geq("hello", "hell"); + cr_assert_strings_geq("hello", "hello"); + + cr_assert_strings_lt("hell", "hello"); + cr_assert_strings_leq("hell", "hello"); + cr_assert_strings_leq("hello", "hello"); +} + +Test(asserts, native) { + cr_assert_eq(1, 1); + cr_assert_neq(1, 2); + + cr_assert_lt(1, 2); + cr_assert_leq(1, 2); + cr_assert_leq(2, 2); + + cr_assert_gt(2, 1); + cr_assert_geq(2, 1); + cr_assert_geq(2, 2); +} + +Test(asserts, float) { + cr_assert_neq(0.1 * 0.1, 0.01); + cr_assert_float_eq(0.1 * 0.1, 0.01, 0.001); +} + +struct dummy_struct { + char a; + size_t b; +}; + +int eq_dummy(struct dummy_struct *a, struct dummy_struct *b) { + return a->a != b->a || a->b != b->b; +} + +Test(asserts, array) { + int arr1[] = {1, 2, 3, 4}; + int arr2[] = {4, 3, 2, 1}; + + cr_assert_arrays_eq(arr1, arr1, 4); + cr_assert_arrays_neq(arr1, arr2, 4); + +#ifdef __GNUC__ + struct dummy_struct s1[] = {{4, 2}, {2, 4}}; + struct dummy_struct s2[2]; + memset(s2, 0xFF, sizeof(s2)); + s2[0].a = 4; + s2[0].b = 2; + s2[1].a = 2; + s2[1].b = 4; + + cr_assert_arrays_neq(s1, s2, 2); + cr_assert_arrays_eq_cmp(s1, s2, 2, eq_dummy); +#endif +} diff --git a/samples/description.cc b/samples/description.cc new file mode 100644 index 00000000..55b7b49c --- /dev/null +++ b/samples/description.cc @@ -0,0 +1,8 @@ +#include + +Test(misc, failing, .description = "Just a failing test") { + cr_assert(0); +} + +Test(misc, skipped, .description = "This one is skipped", .disabled = true) { +} diff --git a/samples/exit.cc b/samples/exit.cc new file mode 100644 index 00000000..f9c95dd6 --- /dev/null +++ b/samples/exit.cc @@ -0,0 +1,24 @@ +#include +#include +#include + +Test(exit, normal, .exit_code = 0) { +} + +Test(exit, expected_exit, .exit_code = 42) { + exit(42); +} + +Test(exit, unexpected_exit) { + exit(127); +} + +void do_exit (void) { + exit(127); +} + +Test(exit_with_fixtures, init_exits, .init = do_exit) { +} + +Test(exit_with_fixtures, fini_exits, .fini = do_exit) { +} diff --git a/samples/fixtures.cc b/samples/fixtures.cc new file mode 100644 index 00000000..1f7851c4 --- /dev/null +++ b/samples/fixtures.cc @@ -0,0 +1,14 @@ +#include +#include + +void setup(void) { + puts("Runs before the test"); +} + +void teardown(void) { + puts("Runs after the test"); +} + +Test(simple, fixtures, .init = setup, .fini = teardown) { + cr_assert(1); +} diff --git a/samples/long-messages.cc b/samples/long-messages.cc new file mode 100644 index 00000000..02472e1b --- /dev/null +++ b/samples/long-messages.cc @@ -0,0 +1,5 @@ +#include + +Test(sample, long_msg) { + cr_assert(0, "This is\nA long message\nSpawning multiple lines.\n\nFormatting is respected."); +} diff --git a/samples/more-suites.cc b/samples/more-suites.cc new file mode 100644 index 00000000..95d70393 --- /dev/null +++ b/samples/more-suites.cc @@ -0,0 +1,21 @@ +#include + +void setup_suite(void) { +} + +void teardown_suite(void) { +} + +TestSuite(suite1, .init = setup_suite, .fini = teardown_suite); + +Test(suite1, test) { + cr_assert(1); +} + +Test(suite2, test) { + cr_assert(1); +} + +TestSuite(disabled, .disabled = true); + +Test(disabled, test) {} diff --git a/samples/other-crashes.cc b/samples/other-crashes.cc new file mode 100644 index 00000000..ab689bb2 --- /dev/null +++ b/samples/other-crashes.cc @@ -0,0 +1,14 @@ +#include + +void crash(void) { + int *i = NULL; + *i = 42; +} + +Test(misc, setup_crash, .init = crash) { + cr_assert(true); +} + +Test(misc, teardown_crash, .fini = crash) { + cr_assert(true); +} diff --git a/samples/report.cc b/samples/report.cc new file mode 100644 index 00000000..8c9ace8a --- /dev/null +++ b/samples/report.cc @@ -0,0 +1,26 @@ +#include +#include + +Test(sample, test) { + cr_expect(0); + cr_assert(1); +} + +ReportHook(PRE_INIT)(struct criterion_test *test) { + printf("testing %s in category %s\n", test->name, test->category); +} + +ReportHook(POST_TEST)(struct criterion_test_stats *stats) { + printf("Asserts: [%d passed, %d failed, %d total]\n", + stats->passed_asserts, stats->failed_asserts, stats->passed_asserts + stats->failed_asserts); +} + +ReportHook(PRE_ALL)(struct criterion_test_set *tests) { + (void) tests; + puts("criterion_init"); +} + +ReportHook(POST_ALL)(struct criterion_global_stats *stats) { + (void) stats; + puts("criterion_fini"); +} diff --git a/samples/signal.cc b/samples/signal.cc new file mode 100644 index 00000000..9dcc99d3 --- /dev/null +++ b/samples/signal.cc @@ -0,0 +1,19 @@ +#include +#include +#include +#include + +Test(simple, caught, .signal = SIGSEGV) { + int *i = NULL; + *i = 42; +} + +Test(simple, wrong_signal, .signal = SIGINT) { + int *i = NULL; + *i = 42; +} + +Test(simple, uncaught) { + int *i = NULL; + *i = 42; +} diff --git a/samples/simple.cc b/samples/simple.cc new file mode 100644 index 00000000..d5916f5a --- /dev/null +++ b/samples/simple.cc @@ -0,0 +1,9 @@ +#include + +Test(misc, failing) { + cr_assert(0); +} + +Test(misc, passing) { + cr_assert(1); +} diff --git a/samples/suites.cc b/samples/suites.cc new file mode 100644 index 00000000..d19d7b2d --- /dev/null +++ b/samples/suites.cc @@ -0,0 +1,9 @@ +#include + +Test(first_suite, test) { + cr_assert(1); +} + +Test(second_suite, test) { + cr_assert(1); +} From ba051b8869712f546d333e7293f2d5f78677d676 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Mon, 7 Sep 2015 02:20:18 +0200 Subject: [PATCH 084/174] Fixed missing initializer for C samples on assert substitution --- include/criterion/assert.h | 94 ++++++++++++++++++++------------------ 1 file changed, 50 insertions(+), 44 deletions(-) diff --git a/include/criterion/assert.h b/include/criterion/assert.h index ea3e0ccb..21114091 100644 --- a/include/criterion/assert.h +++ b/include/criterion/assert.h @@ -86,15 +86,21 @@ struct criterion_assert_args { cr_assert(0, msg ? msg : "The conditions for this test were not met.");\ } while (0) -# define cr_assert(...) CR_EXPAND(cr_assert_(__VA_ARGS__, 0)) +# ifdef __cplusplus +# define CR_SENTINEL 0 +# else +# define CR_SENTINEL .sentinel_ = 0 +# endif + +# define cr_assert(...) CR_EXPAND(cr_assert_(__VA_ARGS__, CR_SENTINEL)) -# define cr_expect(...) CR_EXPAND(cr_expect_(__VA_ARGS__, 0)) +# define cr_expect(...) CR_EXPAND(cr_expect_(__VA_ARGS__, CR_SENTINEL)) # define cr_assert_(Condition, ...) CR_EXPAND(cr_assert_impl(FATAL, Condition, __VA_ARGS__)) # define cr_expect_(Condition, ...) CR_EXPAND(cr_assert_impl(NORMAL, Condition, __VA_ARGS__)) -# define cr_assert_not(...) CR_EXPAND(cr_assert_not_(__VA_ARGS__, 0)) -# define cr_expect_not(...) CR_EXPAND(cr_expect_not_(__VA_ARGS__, 0)) +# define cr_assert_not(...) CR_EXPAND(cr_assert_not_(__VA_ARGS__, CR_SENTINEL)) +# define cr_expect_not(...) CR_EXPAND(cr_expect_not_(__VA_ARGS__, CR_SENTINEL)) # define cr_assert_not_(Condition, ...) \ CR_EXPAND(cr_assert_impl(FATAL, !(Condition), __VA_ARGS__)) @@ -108,46 +114,46 @@ struct criterion_assert_args { # define cr_expect_op_(Op, Actual, Expected, ...) \ CR_EXPAND(cr_assert_impl(NORMAL, (Actual) Op (Expected), __VA_ARGS__)) -# define cr_assert_eq(...) CR_EXPAND(cr_assert_op_(==, __VA_ARGS__, 0)) -# define cr_expect_eq(...) CR_EXPAND(cr_expect_op_(==, __VA_ARGS__, 0)) +# define cr_assert_eq(...) CR_EXPAND(cr_assert_op_(==, __VA_ARGS__, CR_SENTINEL)) +# define cr_expect_eq(...) CR_EXPAND(cr_expect_op_(==, __VA_ARGS__, CR_SENTINEL)) -# define cr_assert_neq(...) CR_EXPAND(cr_assert_op_(!=, __VA_ARGS__, 0)) -# define cr_expect_neq(...) CR_EXPAND(cr_expect_op_(!=, __VA_ARGS__, 0)) +# define cr_assert_neq(...) CR_EXPAND(cr_assert_op_(!=, __VA_ARGS__, CR_SENTINEL)) +# define cr_expect_neq(...) CR_EXPAND(cr_expect_op_(!=, __VA_ARGS__, CR_SENTINEL)) -# define cr_assert_lt(...) CR_EXPAND(cr_assert_op_(<, __VA_ARGS__, 0)) -# define cr_expect_lt(...) CR_EXPAND(cr_expect_op_(<, __VA_ARGS__, 0)) +# define cr_assert_lt(...) CR_EXPAND(cr_assert_op_(<, __VA_ARGS__, CR_SENTINEL)) +# define cr_expect_lt(...) CR_EXPAND(cr_expect_op_(<, __VA_ARGS__, CR_SENTINEL)) -# define cr_assert_gt(...) CR_EXPAND(cr_assert_op_(>, __VA_ARGS__, 0)) -# define cr_expect_gt(...) CR_EXPAND(cr_expect_op_(>, __VA_ARGS__, 0)) +# define cr_assert_gt(...) CR_EXPAND(cr_assert_op_(>, __VA_ARGS__, CR_SENTINEL)) +# define cr_expect_gt(...) CR_EXPAND(cr_expect_op_(>, __VA_ARGS__, CR_SENTINEL)) -# define cr_assert_leq(...) CR_EXPAND(cr_assert_op_(<=, __VA_ARGS__, 0)) -# define cr_expect_leq(...) CR_EXPAND(cr_expect_op_(<=, __VA_ARGS__, 0)) +# define cr_assert_leq(...) CR_EXPAND(cr_assert_op_(<=, __VA_ARGS__, CR_SENTINEL)) +# define cr_expect_leq(...) CR_EXPAND(cr_expect_op_(<=, __VA_ARGS__, CR_SENTINEL)) -# define cr_assert_geq(...) CR_EXPAND(cr_assert_op_(>=, __VA_ARGS__, 0)) -# define cr_expect_geq(...) CR_EXPAND(cr_expect_op_(>=, __VA_ARGS__, 0)) +# define cr_assert_geq(...) CR_EXPAND(cr_assert_op_(>=, __VA_ARGS__, CR_SENTINEL)) +# define cr_expect_geq(...) CR_EXPAND(cr_expect_op_(>=, __VA_ARGS__, CR_SENTINEL)) # define cr_assert_null_(Value, ...) \ CR_EXPAND(cr_assert_impl(FATAL, (Value) == NULL, __VA_ARGS__)) # define cr_expect_null_(Value, ...) \ CR_EXPAND(cr_assert_impl(NORMAL, (Value) == NULL, __VA_ARGS__)) -# define cr_assert_null(...) CR_EXPAND(cr_assert_null_(__VA_ARGS__, 0)) -# define cr_expect_null(...) CR_EXPAND(cr_expect_null_(__VA_ARGS__, 0)) +# define cr_assert_null(...) CR_EXPAND(cr_assert_null_(__VA_ARGS__, CR_SENTINEL)) +# define cr_expect_null(...) CR_EXPAND(cr_expect_null_(__VA_ARGS__, CR_SENTINEL)) # define cr_assert_not_null_(Value, ...) \ CR_EXPAND(cr_assert_impl(FATAL, (Value) != NULL, __VA_ARGS__)) # define cr_expect_not_null_(Value, ...) \ CR_EXPAND(cr_assert_impl(NORMAL, (Value) != NULL, __VA_ARGS__)) -# define cr_assert_not_null(...) CR_EXPAND(cr_assert_not_null_(__VA_ARGS__, 0)) -# define cr_expect_not_null(...) CR_EXPAND(cr_expect_not_null_(__VA_ARGS__, 0)) +# define cr_assert_not_null(...) CR_EXPAND(cr_assert_not_null_(__VA_ARGS__, CR_SENTINEL)) +# define cr_expect_not_null(...) CR_EXPAND(cr_expect_not_null_(__VA_ARGS__, CR_SENTINEL)) // Floating-point asserts # define cr_assert_float_eq(...) \ - CR_EXPAND(cr_assert_float_eq_(__VA_ARGS__, 0)) + CR_EXPAND(cr_assert_float_eq_(__VA_ARGS__, CR_SENTINEL)) # define cr_expect_float_eq(...) \ - CR_EXPAND(cr_expect_float_eq_(__VA_ARGS__, 0)) + CR_EXPAND(cr_expect_float_eq_(__VA_ARGS__, CR_SENTINEL)) # define cr_assert_float_eq_(Actual, Expected, Epsilon, ...) \ CR_EXPAND(cr_assert_impl(FATAL, (Expected) - (Actual) <= (Epsilon) \ @@ -159,9 +165,9 @@ struct criterion_assert_args { __VA_ARGS__)) # define cr_assert_float_neq(...) \ - CR_EXPAND(cr_assert_float_neq_(__VA_ARGS__, 0)) + CR_EXPAND(cr_assert_float_neq_(__VA_ARGS__, CR_SENTINEL)) # define cr_expect_float_neq(...) \ - CR_EXPAND(cr_expect_float_neq_(__VA_ARGS__, 0)) + CR_EXPAND(cr_expect_float_neq_(__VA_ARGS__, CR_SENTINEL)) # define cr_assert_float_neq_(Actual, Expected, Epsilon, ...) \ CR_EXPAND(cr_assert_impl(FATAL, (Expected) - (Actual) > (Epsilon) \ @@ -180,38 +186,38 @@ struct criterion_assert_args { CR_EXPAND(cr_assert_impl(NORMAL, strcmp((Actual), (Expected)) Op 0, __VA_ARGS__)) # define cr_assert_strings_eq(...) \ - CR_EXPAND(cr_assert_strings_(==, __VA_ARGS__, 0)) + CR_EXPAND(cr_assert_strings_(==, __VA_ARGS__, CR_SENTINEL)) # define cr_expect_strings_eq(...) \ - CR_EXPAND(cr_expect_strings_(==, __VA_ARGS__, 0)) + CR_EXPAND(cr_expect_strings_(==, __VA_ARGS__, CR_SENTINEL)) # define cr_assert_strings_neq(...) \ - CR_EXPAND(cr_assert_strings_(!=, __VA_ARGS__, 0)) + CR_EXPAND(cr_assert_strings_(!=, __VA_ARGS__, CR_SENTINEL)) # define cr_expect_strings_neq(...) \ - CR_EXPAND(cr_expect_strings_(!=, __VA_ARGS__, 0)) + CR_EXPAND(cr_expect_strings_(!=, __VA_ARGS__, CR_SENTINEL)) -# define cr_assert_strings_gt(...) CR_EXPAND(cr_assert_strings_(>, __VA_ARGS__, 0)) -# define cr_expect_strings_gt(...) CR_EXPAND(cr_expect_strings_(>, __VA_ARGS__, 0)) +# define cr_assert_strings_gt(...) CR_EXPAND(cr_assert_strings_(>, __VA_ARGS__, CR_SENTINEL)) +# define cr_expect_strings_gt(...) CR_EXPAND(cr_expect_strings_(>, __VA_ARGS__, CR_SENTINEL)) -# define cr_assert_strings_lt(...) CR_EXPAND(cr_assert_strings_(<, __VA_ARGS__, 0)) -# define cr_expect_strings_lt(...) CR_EXPAND(cr_expect_strings_(<, __VA_ARGS__, 0)) +# define cr_assert_strings_lt(...) CR_EXPAND(cr_assert_strings_(<, __VA_ARGS__, CR_SENTINEL)) +# define cr_expect_strings_lt(...) CR_EXPAND(cr_expect_strings_(<, __VA_ARGS__, CR_SENTINEL)) -# define cr_assert_strings_leq(...) CR_EXPAND(cr_assert_strings_(<=, __VA_ARGS__, 0)) -# define cr_expect_strings_leq(...) CR_EXPAND(cr_expect_strings_(<=, __VA_ARGS__, 0)) +# define cr_assert_strings_leq(...) CR_EXPAND(cr_assert_strings_(<=, __VA_ARGS__, CR_SENTINEL)) +# define cr_expect_strings_leq(...) CR_EXPAND(cr_expect_strings_(<=, __VA_ARGS__, CR_SENTINEL)) -# define cr_assert_strings_geq(...) CR_EXPAND(cr_assert_strings_(>=, __VA_ARGS__, 0)) -# define cr_expect_strings_geq(...) CR_EXPAND(cr_expect_strings_(>=, __VA_ARGS__, 0)) +# define cr_assert_strings_geq(...) CR_EXPAND(cr_assert_strings_(>=, __VA_ARGS__, CR_SENTINEL)) +# define cr_expect_strings_geq(...) CR_EXPAND(cr_expect_strings_(>=, __VA_ARGS__, CR_SENTINEL)) // Array asserts # define cr_assert_arrays_eq(...) \ - CR_EXPAND(cr_assert_arrays_eq_(__VA_ARGS__, 0)) + CR_EXPAND(cr_assert_arrays_eq_(__VA_ARGS__, CR_SENTINEL)) # define cr_expect_arrays_eq(...) \ - CR_EXPAND(cr_expect_arrays_eq_(__VA_ARGS__, 0)) + CR_EXPAND(cr_expect_arrays_eq_(__VA_ARGS__, CR_SENTINEL)) # define cr_assert_arrays_neq(...) \ - CR_EXPAND(cr_assert_arrays_neq_(__VA_ARGS__, 0)) + CR_EXPAND(cr_assert_arrays_neq_(__VA_ARGS__, CR_SENTINEL)) # define cr_expect_arrays_neq(...) \ - CR_EXPAND(cr_expect_arrays_neq_(__VA_ARGS__, 0)) + CR_EXPAND(cr_expect_arrays_neq_(__VA_ARGS__, CR_SENTINEL)) # define cr_assert_arrays_eq_(A, B, Size, ...) \ CR_EXPAND(cr_assert_impl(FATAL, !memcmp((A), (B), (Size)), \ @@ -251,9 +257,9 @@ struct criterion_assert_args { } while (0) # define cr_assert_arrays_eq_cmp(...) \ - cr_assert_arrays_eq_cmp_(__VA_ARGS__, 0) + cr_assert_arrays_eq_cmp_(__VA_ARGS__, CR_SENTINEL) # define cr_expect_arrays_eq_cmp(...) \ - cr_expect_arrays_eq_cmp_(__VA_ARGS__, 0) + cr_expect_arrays_eq_cmp_(__VA_ARGS__, CR_SENTINEL) # define cr_assert_arrays_neq_cmp_(A, B, Size, Cmp, ...) \ do { \ @@ -270,9 +276,9 @@ struct criterion_assert_args { } while (0) # define cr_assert_arrays_neq_cmp(...) \ - cr_assert_arrays_eq_cmp_(__VA_ARGS__, 0) + cr_assert_arrays_eq_cmp_(__VA_ARGS__, CR_SENTINEL) # define cr_expect_arrays_neq_cmp(...) \ - cr_expect_arrays_eq_cmp_(__VA_ARGS__, 0) + cr_expect_arrays_eq_cmp_(__VA_ARGS__, CR_SENTINEL) # endif /* !__GNUC__ */ // The section below is here for backward compatibility purposes. From c94fef2837ecdfe7478bf326376b5a875b87c6f6 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Mon, 7 Sep 2015 02:28:06 +0200 Subject: [PATCH 085/174] Switched compiler to use gcc 4.9 --- .travis.yml | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 34224653..4c31586f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,13 +2,25 @@ language: c os: - linux - osx + compiler: -- gcc +- gcc-4.9 + sudo: false + +addons: + apt: + sources: + - ubuntu-toolchain-r-test + packages: + - gcc-4.9 + - g++-4.9 + before_install: - export LOCAL_INSTALL="$HOME" - export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$HOME/lib - export CFLAGS="-g -O0" +- export CXX="g++-4.9" script: - mkdir -p build - cd build From dc0f871d0e8cba2bdf33add56c2a23e3c264fc09 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Mon, 7 Sep 2015 02:59:29 +0200 Subject: [PATCH 086/174] Fixed mismatching parenthesis in section attribute on OS X --- include/criterion/common.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/criterion/common.h b/include/criterion/common.h index 5ee86a92..6d0910a7 100644 --- a/include/criterion/common.h +++ b/include/criterion/common.h @@ -58,7 +58,7 @@ # 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_(Name) CR_ATTRIBUTE(section("__DATA," Name)) # define SECTION_SUFFIX_ # elif CR_IS_MSVC # define SECTION_START_PREFIX __start From b594f5cf8abbd61276c535cd8377fde0697339d5 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Mon, 7 Sep 2015 03:02:41 +0200 Subject: [PATCH 087/174] Added missing section suffix on report hooks on Windows VC builds --- include/criterion/hooks.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/include/criterion/hooks.h b/include/criterion/hooks.h index 098790a9..d6ceed22 100644 --- a/include/criterion/hooks.h +++ b/include/criterion/hooks.h @@ -91,7 +91,9 @@ typedef void (*f_report_hook)(); # define ReportHook(Kind) \ HOOK_PROTOTYPE_(HOOK_PARAM_TYPE(Kind)); \ SECTION_(HOOK_SECTION_STRINGIFY(Kind)) \ - const f_report_hook HOOK_IDENTIFIER_(func) = (f_report_hook) HOOK_IDENTIFIER_(impl); \ + const f_report_hook HOOK_IDENTIFIER_(func) = \ + (f_report_hook) HOOK_IDENTIFIER_(impl) \ + SECTION_SUFFIX_; \ HOOK_PROTOTYPE_ #endif /* !CRITERION_HOOKS_H_ */ From a411b22ea3de8dc1957352d0328f3bb8383286fa Mon Sep 17 00:00:00 2001 From: Snaipe Date: Mon, 7 Sep 2015 03:48:20 +0200 Subject: [PATCH 088/174] Switched appveyor badge link to display the bleeding status --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 4ddc347c..6d8427a0 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ ========= [![Unix Build Status](https://travis-ci.org/Snaipe/Criterion.svg?branch=bleeding)](https://travis-ci.org/Snaipe/Criterion) -[![Windows Build Status](https://ci.appveyor.com/api/projects/status/github/Snaipe/Criterion?svg=true)](https://ci.appveyor.com/project/Snaipe/Criterion/branch/bleeding) +[![Windows Build Status](https://ci.appveyor.com/api/projects/status/github/Snaipe/Criterion?svg=true&branch=bleeding)](https://ci.appveyor.com/project/Snaipe/Criterion/branch/bleeding) [![Coverage Status](https://coveralls.io/repos/Snaipe/Criterion/badge.svg?branch=bleeding)](https://coveralls.io/r/Snaipe/Criterion?branch=bleeding) [![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) From 20d5f6fe59791478524686221263067360f904dc Mon Sep 17 00:00:00 2001 From: Snaipe Date: Mon, 7 Sep 2015 03:57:00 +0200 Subject: [PATCH 089/174] Removed report.cc from MinGW build on appveyor --- samples/CMakeLists.txt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/samples/CMakeLists.txt b/samples/CMakeLists.txt index 5ab40fb5..1512ae8d 100644 --- a/samples/CMakeLists.txt +++ b/samples/CMakeLists.txt @@ -21,7 +21,6 @@ set(SAMPLES signal.cc exit.cc - report.cc suites.cc fixtures.cc asserts.cc @@ -32,6 +31,10 @@ set(SAMPLES simple.cc ) +if (NOT WIN32 OR MSVC) + set(SAMPLES ${SAMPLES} report.cc) +endif () + set(SCRIPTS tap_test early_exit From 63f47f170ac62ce2fb0d3801e67a75e37b187d24 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Mon, 7 Sep 2015 05:08:56 +0200 Subject: [PATCH 090/174] Added zero-filling code for assert stats before sending them to the monitoring process --- include/criterion/assert.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/include/criterion/assert.h b/include/criterion/assert.h index 21114091..bf9e7fe8 100644 --- a/include/criterion/assert.h +++ b/include/criterion/assert.h @@ -60,6 +60,12 @@ struct criterion_assert_args { # define CR_GET_CONDITION_STR(Condition, ...) #Condition # define CR_VA_SKIP(_, ...) __VA_ARGS__ +# ifndef __cplusplus +# define CR_ZERO_FILL(Arg) memset(&(Arg), 0, sizeof (Arg)) +# else +# define CR_ZERO_FILL(Arg) std::memset(&(Arg), 0, sizeof (Arg)) +# endif + # define cr_assert_impl(Kind, ...) \ do { \ struct criterion_assert_args args = { \ @@ -67,6 +73,7 @@ struct criterion_assert_args { }; \ int passed = !!(CR_EXPAND(CR_GET_CONDITION(__VA_ARGS__))); \ struct criterion_assert_stats stat; \ + CR_ZERO_FILL(stat); \ stat.kind = (Kind); \ stat.condition = CR_EXPAND(CR_GET_CONDITION_STR(__VA_ARGS__)); \ stat.message = args.msg ? args.msg : ""; \ From 7fca89739f1abf46123d53b24613e0f708cffed7 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Mon, 7 Sep 2015 05:17:27 +0200 Subject: [PATCH 091/174] Removed fast-fail flag for appveyor builds --- appveyor.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index ca061d30..692534d1 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -27,9 +27,6 @@ environment: clone_depth: 5 -matrix: - fast_finish: true # set this flag to immediately finish build once one of the jobs fails. - platform: - x86_64 From 4b2fb35d31c577d7d84fc8caf388aa738801a85c Mon Sep 17 00:00:00 2001 From: Snaipe Date: Mon, 7 Sep 2015 05:27:00 +0200 Subject: [PATCH 092/174] Added RDP details for Appveyor VM debugging. --- appveyor.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/appveyor.yml b/appveyor.yml index 692534d1..45385c41 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -3,6 +3,7 @@ version: 1.3.1_b{build}-{branch} os: Visual Studio 2015 init: + - ps: iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1')) - git config --global core.autocrlf input - 'SET PATH=%PATH%;C:\MinGW\msys\1.0\bin;C:\MinGW\bin;%APPVEYOR_BUILD_FOLDER%\bin;%APPVEYOR_BUILD_FOLDER%\build' From 91200ed8dd59c2ebaf4229db9e47caf1e7637327 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Mon, 7 Sep 2015 05:35:32 +0200 Subject: [PATCH 093/174] Changed path ordering to include C:\MinGW\bin before anything else --- appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index 45385c41..5d22cd96 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -5,7 +5,7 @@ os: Visual Studio 2015 init: - ps: iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1')) - git config --global core.autocrlf input - - 'SET PATH=%PATH%;C:\MinGW\msys\1.0\bin;C:\MinGW\bin;%APPVEYOR_BUILD_FOLDER%\bin;%APPVEYOR_BUILD_FOLDER%\build' + - 'SET PATH=C:\MinGW\bin;%PATH%;C:\MinGW\msys\1.0\bin;%APPVEYOR_BUILD_FOLDER%\bin;%APPVEYOR_BUILD_FOLDER%\build' environment: COVERALLS_REPO_TOKEN: From 18f218f4df9a62fa7132ad82cd23cfa6431ec22b Mon Sep 17 00:00:00 2001 From: Snaipe Date: Mon, 7 Sep 2015 05:42:25 +0200 Subject: [PATCH 094/174] Revert "Removed report.cc from MinGW build on appveyor" This reverts commit 20d5f6fe59791478524686221263067360f904dc. --- samples/CMakeLists.txt | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/samples/CMakeLists.txt b/samples/CMakeLists.txt index 1512ae8d..5ab40fb5 100644 --- a/samples/CMakeLists.txt +++ b/samples/CMakeLists.txt @@ -21,6 +21,7 @@ set(SAMPLES signal.cc exit.cc + report.cc suites.cc fixtures.cc asserts.cc @@ -31,10 +32,6 @@ set(SAMPLES simple.cc ) -if (NOT WIN32 OR MSVC) - set(SAMPLES ${SAMPLES} report.cc) -endif () - set(SCRIPTS tap_test early_exit From ffd6c5a5e7628a8c82631763263a30b445e63900 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Mon, 7 Sep 2015 05:42:29 +0200 Subject: [PATCH 095/174] Revert "Added RDP details for Appveyor VM debugging." This reverts commit 4b2fb35d31c577d7d84fc8caf388aa738801a85c. --- appveyor.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index 5d22cd96..26f267de 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -3,7 +3,6 @@ version: 1.3.1_b{build}-{branch} os: Visual Studio 2015 init: - - ps: iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1')) - git config --global core.autocrlf input - 'SET PATH=C:\MinGW\bin;%PATH%;C:\MinGW\msys\1.0\bin;%APPVEYOR_BUILD_FOLDER%\bin;%APPVEYOR_BUILD_FOLDER%\build' From f35bc3d21c4d3d3339bb410e68581a19d883b7b3 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Mon, 7 Sep 2015 07:26:53 +0200 Subject: [PATCH 096/174] Fixed VC++ not registering any sections and internal crashes due to test data not being zero-filled --- include/criterion/criterion.h | 4 ++-- include/criterion/designated-initializer-compat.h | 1 + include/criterion/hooks.h | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/include/criterion/criterion.h b/include/criterion/criterion.h index bc82cccc..172c5850 100644 --- a/include/criterion/criterion.h +++ b/include/criterion/criterion.h @@ -54,7 +54,7 @@ __VA_ARGS__ \ )); \ SECTION_("cr_tst") \ - const struct criterion_test IDENTIFIER_(Category, Name, meta) = { \ + struct criterion_test IDENTIFIER_(Category, Name, meta) = { \ #Name, \ #Category, \ IDENTIFIER_(Category, Name, impl), \ @@ -71,7 +71,7 @@ __VA_ARGS__ \ )); \ SECTION_("cr_sts") \ - const struct criterion_suite SUITE_IDENTIFIER_(Name, meta) = { \ + struct criterion_suite SUITE_IDENTIFIER_(Name, meta) = { \ #Name, \ &SUITE_IDENTIFIER_(Name, extra), \ } SECTION_SUFFIX_ diff --git a/include/criterion/designated-initializer-compat.h b/include/criterion/designated-initializer-compat.h index 910952b1..bda193b4 100644 --- a/include/criterion/designated-initializer-compat.h +++ b/include/criterion/designated-initializer-compat.h @@ -114,6 +114,7 @@ # 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; \ }() diff --git a/include/criterion/hooks.h b/include/criterion/hooks.h index d6ceed22..62ab4834 100644 --- a/include/criterion/hooks.h +++ b/include/criterion/hooks.h @@ -91,7 +91,7 @@ typedef void (*f_report_hook)(); # define ReportHook(Kind) \ HOOK_PROTOTYPE_(HOOK_PARAM_TYPE(Kind)); \ SECTION_(HOOK_SECTION_STRINGIFY(Kind)) \ - const f_report_hook HOOK_IDENTIFIER_(func) = \ + f_report_hook HOOK_IDENTIFIER_(func) = \ (f_report_hook) HOOK_IDENTIFIER_(impl) \ SECTION_SUFFIX_; \ HOOK_PROTOTYPE_ From 47d12933039f279563cbc5eaef0c77d1141dacee Mon Sep 17 00:00:00 2001 From: Snaipe Date: Mon, 7 Sep 2015 08:22:02 +0200 Subject: [PATCH 097/174] Made the theory interface C++11-compatible --- include/criterion/theories.h | 27 ++++++++- samples/CMakeLists.txt | 1 + samples/theories.cc | 112 +++++++++++++++++++++++++++++++++++ 3 files changed, 137 insertions(+), 3 deletions(-) create mode 100644 samples/theories.cc diff --git a/include/criterion/theories.h b/include/criterion/theories.h index f23c2236..be9bf8b5 100644 --- a/include/criterion/theories.h +++ b/include/criterion/theories.h @@ -24,9 +24,22 @@ #ifndef CRITERION_THEORIES_H_ # define CRITERION_THEORIES_H_ -# include +# 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 + CR_BEGIN_C_API struct criterion_theory_context; @@ -43,11 +56,19 @@ CR_API void cr_theory_call(struct criterion_theory_context *ctx, void (*fnptr)(v # define TheoryDataPoints(Category, Name) \ static struct criterion_datapoints IDENTIFIER_(Category, Name, dps)[] +# 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 DataPoints(Type, ...) { \ sizeof (Type), \ - sizeof ((Type[]) { __VA_ARGS__ }) / sizeof (Type), \ + CR_EXPAND(CR_TH_VA_NUM(Type, __VA_ARGS__)), \ #Type, \ - &(Type[]) { __VA_ARGS__ }, \ + CR_EXPAND(CR_TH_TEMP_ARRAY(Type, __VA_ARGS__)), \ } struct criterion_datapoints { diff --git a/samples/CMakeLists.txt b/samples/CMakeLists.txt index 5ab40fb5..efbef5e5 100644 --- a/samples/CMakeLists.txt +++ b/samples/CMakeLists.txt @@ -30,6 +30,7 @@ set(SAMPLES description.cc other-crashes.cc simple.cc + theories.cc ) set(SCRIPTS diff --git a/samples/theories.cc b/samples/theories.cc new file mode 100644 index 00000000..62f8b91c --- /dev/null +++ b/samples/theories.cc @@ -0,0 +1,112 @@ +#ifdef _MSC_VER +#pragma warning(disable : 4090) +#endif + +#include +#ifdef __cplusplus +# include +#else +# include +#endif + +# define INT_DATAPOINTS DataPoints(int, 0, 1, 2, -1, -2, INT_MAX, INT_MIN) + +// Let's test the multiplicative properties of 32-bit integers: + +int bad_mul(int a, int b) { + return a * b; +} + +int bad_div(int a, int b) { + return a / b; +} + +TheoryDataPoints(algebra, bad_divide_is_inverse_of_multiply) = { + INT_DATAPOINTS, + INT_DATAPOINTS, +}; + +Theory((int a, int b), algebra, bad_divide_is_inverse_of_multiply) { + cr_assume(b != 0); + cr_assert_eq(a, bad_div(bad_mul(a, b), b)); +} + +// The above implementation of mul & div fails the test because of overflows, +// let's try again: + +long long good_mul(long long a, long long b) { + return a * b; +} + +long long good_div(long long a, long long b) { + return a / b; +} + +TheoryDataPoints(algebra, good_divide_is_inverse_of_multiply) = { + INT_DATAPOINTS, + INT_DATAPOINTS, +}; + +Theory((int a, int b), algebra, good_divide_is_inverse_of_multiply) { + cr_assume(b != 0); + cr_assert_eq(a, good_div(good_mul(a, b), b)); +} + +// For triangulation + +Test(algebra, multiplication_by_integer) { + cr_assert_eq(10, good_mul(5, 2)); +} + +// Another property test + +TheoryDataPoints(algebra, zero_is_absorbing) = { + INT_DATAPOINTS, + INT_DATAPOINTS, +}; + +Theory((int a, int b), algebra, zero_is_absorbing) { + cr_assume(a == 0 || b == 0); + cr_assert_eq(0, good_mul(a, b)); +} + +// Testing for various parameters + +struct my_object { + int foo; +}; + +struct my_object o = {42}; + +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"), + DataPoints(struct my_object *, &o), +}; + +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) { + 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_strings_eq(str, "test"); + cr_assert_strings_eq(cstr, "other test"); + cr_assert_eq(obj->foo, 42); + + // abort to see the formatted string of all parameters + cr_abort_test(NULL); +} From 59e91f9404c7383c50d15dbdfd9e806fde9ad990 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Mon, 7 Sep 2015 08:24:52 +0200 Subject: [PATCH 098/174] Removed extra semicolon --- include/criterion/theories.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/criterion/theories.h b/include/criterion/theories.h index be9bf8b5..3dc42c51 100644 --- a/include/criterion/theories.h +++ b/include/criterion/theories.h @@ -37,7 +37,7 @@ using std::size_t; template constexpr size_t criterion_va_num__(const T &...) { return sizeof...(T); -}; +} # endif CR_BEGIN_C_API From a9f325874a61585d4f334a8d5ab0c36833edbd8e Mon Sep 17 00:00:00 2001 From: Snaipe Date: Mon, 7 Sep 2015 08:37:28 +0200 Subject: [PATCH 099/174] Switched type of 'passed' to bool instead of int --- include/criterion/assert.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/criterion/assert.h b/include/criterion/assert.h index bf9e7fe8..539393d0 100644 --- a/include/criterion/assert.h +++ b/include/criterion/assert.h @@ -71,7 +71,7 @@ struct criterion_assert_args { struct criterion_assert_args args = { \ CR_EXPAND(CR_VA_SKIP(__VA_ARGS__)) \ }; \ - int passed = !!(CR_EXPAND(CR_GET_CONDITION(__VA_ARGS__))); \ + bool passed = !!(CR_EXPAND(CR_GET_CONDITION(__VA_ARGS__))); \ struct criterion_assert_stats stat; \ CR_ZERO_FILL(stat); \ stat.kind = (Kind); \ From 17cd3c6509bafff4874d520a6feba5da71616796 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Mon, 7 Sep 2015 08:45:38 +0200 Subject: [PATCH 100/174] Removed bogus assert in asserts.{c,cc} samples --- samples/asserts.c | 2 +- samples/asserts.cc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/samples/asserts.c b/samples/asserts.c index ef5bc985..0d9daab5 100644 --- a/samples/asserts.c +++ b/samples/asserts.c @@ -74,7 +74,7 @@ Test(asserts, array) { s2[1].a = 2; s2[1].b = 4; - cr_assert_arrays_neq(s1, s2, 2); + // cr_assert_arrays_eq(s1, s2, 2); not guaranteed to work on structs. cr_assert_arrays_eq_cmp(s1, s2, 2, eq_dummy); #endif } diff --git a/samples/asserts.cc b/samples/asserts.cc index ef5bc985..0d9daab5 100644 --- a/samples/asserts.cc +++ b/samples/asserts.cc @@ -74,7 +74,7 @@ Test(asserts, array) { s2[1].a = 2; s2[1].b = 4; - cr_assert_arrays_neq(s1, s2, 2); + // cr_assert_arrays_eq(s1, s2, 2); not guaranteed to work on structs. cr_assert_arrays_eq_cmp(s1, s2, 2, eq_dummy); #endif } From 60760092b403f5f67a4d8e98ea3bdf93469068be Mon Sep 17 00:00:00 2001 From: Snaipe Date: Mon, 7 Sep 2015 10:22:37 +0200 Subject: [PATCH 101/174] Fixed __VA_ARG__ warnings & added -pedantic to c++ samples --- include/criterion/designated-initializer-compat.h | 4 ++-- samples/CMakeLists.txt | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/include/criterion/designated-initializer-compat.h b/include/criterion/designated-initializer-compat.h index bda193b4..3b2a7ba2 100644 --- a/include/criterion/designated-initializer-compat.h +++ b/include/criterion/designated-initializer-compat.h @@ -103,11 +103,11 @@ # define CRITERION_APPLY_64(Macro, Prefix, Head, ...) Macro(Prefix, Head) CR_EXPAND(CRITERION_APPLY_63(Macro, Prefix, __VA_ARGS__)) # define CRITERION_APPLY_65(Macro, Prefix, Head, ...) Macro(Prefix, Head) CR_EXPAND(CRITERION_APPLY_64(Macro, Prefix, __VA_ARGS__)) -# define CRITERION_APPLY__(Macro, Prefix, n, ...) CR_EXPAND(CRITERION_APPLY_##n(Macro, Prefix, __VA_ARGS__)) +# define CRITERION_APPLY__(Macro, Prefix, n, ...) CR_EXPAND(CRITERION_APPLY_##n(Macro, Prefix, __VA_ARGS__,)) # define CRITERION_APPLY_(Macro, n, Prefix, ...) CR_EXPAND(CRITERION_APPLY__(Macro, Prefix, n, __VA_ARGS__)) # define CRITERION_APPLY(Macro, ...) CR_EXPAND(CRITERION_APPLY_(Macro, CRITERION_ARG_LENGTH(__VA_ARGS__), __VA_ARGS__)) -# define CRITERION_ADD_PREFIX_ONCE(Prefix, Field, ...) Prefix Field; +# define CRITERION_ADD_PREFIX_ONCE(Prefix, Field) Prefix Field; # define CRITERION_ADD_PREFIX(...) \ CR_EXPAND(CRITERION_APPLY(CRITERION_ADD_PREFIX_ONCE, __VA_ARGS__)) diff --git a/samples/CMakeLists.txt b/samples/CMakeLists.txt index efbef5e5..f95f2558 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") + set(CMAKE_CXX_FLAGS "-std=c++11 -Wall -Wextra -pedantic") endif () include_directories(../include) From 7e1bdc54f83af27be912813ce7adc637cf422a43 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Mon, 7 Sep 2015 10:35:17 +0200 Subject: [PATCH 102/174] Updated README with C++ mentions --- README.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 4ddc347c..3c93776d 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ [![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) -A dead-simple, yet extensible, C unit testing framework. +A dead-simple, yet extensible, C and C++ unit testing framework. ![Screencast](./doc/screencast.gif) @@ -24,12 +24,14 @@ 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: +* [x] C99 and C++11 compatible. * [x] Tests are automatically registered when declared. * [x] Implements a xUnit framework structure. * [x] A default entry point is provided, no need to declare a main unless you want to do special handling. * [x] Test are isolated in their own process, crashes and signals can be reported and tested. +* [x] Unified interface between C and C++: include the criterion header and it *just* works. * [x] There is a support for theories alongside tests * [x] Progress and statistics can be followed in real time with report hooks. * [x] TAP output format can be enabled with an option. @@ -89,7 +91,7 @@ be merged. ## F.A.Q. -**Q. What's wrong with other test frameworks?** +**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 From f2f87cdc1a0d31d86392e308e0f4f4750188fd56 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Mon, 7 Sep 2015 11:00:52 +0200 Subject: [PATCH 103/174] Updated Setup steps in documentation --- doc/setup.rst | 36 ++++++++++++++++++++++++------------ 1 file changed, 24 insertions(+), 12 deletions(-) diff --git a/doc/setup.rst b/doc/setup.rst index 1dec23cb..b4001e2b 100644 --- a/doc/setup.rst +++ b/doc/setup.rst @@ -4,27 +4,39 @@ Setup Prerequisites ------------- -Currently, this library only works under \*nix systems. +The library is supported on Linux, OS X, FreeBSD, and Windows. -To compile the shared library and its dependencies, GCC 4.6+ is needed. +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) -To use the shared library, any GNU-C compatible compiler will suffice -(GCC, Clang/LLVM, ICC, MinGW-GCC, ...). +Building from source +-------------------- -Installation ------------- +.. code-block:: bash + + $ mkdir build + $ cd build + $ cmake .. + $ cmake --build . + +Installing the library and language files (Linux, OS X, FreeBSD) +---------------------------------------------------------------- + +From the build directory created above, run with an elevated shell: .. code-block:: bash - $ git clone https://github.com/Snaipe/Criterion.git && cd Criterion - $ mkdir build && cd $_ && cmake -DCMAKE_INSTALL_PATH=/usr .. - $ make && sudo make install + $ make install Usage ----- -Given a test file named test.c, compile it with `-lcriterion`: +To compile your tests with Criterion, you need to make sure to: -.. code-block:: bash +1. Add the include directory to the header search path +2. Install the library to your library search path +3. Link Criterion to your executable. - $ gcc -o test test.c -lcriterion +This should be all you need. From f31a7b90d56c1c3d011de3a2268650719c9b3330 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Mon, 7 Sep 2015 11:04:33 +0200 Subject: [PATCH 104/174] Cleaned up appveyor config --- appveyor.yml | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 26f267de..ea56e78a 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -4,7 +4,7 @@ os: Visual Studio 2015 init: - git config --global core.autocrlf input - - 'SET PATH=C:\MinGW\bin;%PATH%;C:\MinGW\msys\1.0\bin;%APPVEYOR_BUILD_FOLDER%\bin;%APPVEYOR_BUILD_FOLDER%\build' + - 'SET PATH=C:\MinGW\bin;%PATH%;C:\MinGW\msys\1.0\bin;%APPVEYOR_BUILD_FOLDER%\build' environment: COVERALLS_REPO_TOKEN: @@ -15,14 +15,8 @@ environment: GCOV_PREFIX: $(APPVEYOR_BUILD_FOLDER) matrix: - COMPILER: mingw - BUILD_TARGET: all - TEST_TARGET: test - INSTALL_TARGET: install GENERATOR: "MSYS Makefiles" - COMPILER: msvc - BUILD_TARGET: all_build - TEST_TARGET: run_tests - INSTALL_TARGET: install GENERATOR: "Visual Studio 14 2015" clone_depth: 5 @@ -46,7 +40,7 @@ install: .. build_script: - - cmake --build . --target %BUILD_TARGET% + - cmake --build . - ps: | # HACK: We need to copy criterion.dll into the binary directory if ($env:Compiler -eq "msvc") { @@ -57,16 +51,14 @@ build_script: before_deploy: - ps: | if ($env:Compiler -eq "mingw" -and !$env:APPVEYOR_REPO_TAG_NAME) { - cmake --build . --target $env:INSTALL_TARGET + cmake --build . --target install 7z a -ttar "criterion-$env:APPVEYOR_REPO_BRANCH-windows-$env:PLATFORM.tar" "criterion-$env:APPVEYOR_REPO_TAG_NAME" 7z a -tbzip2 "../criterion-$env:APPVEYOR_REPO_TAG_NAME-windows-$env:PLATFORM.tar.bz2" "criterion-$env:APPVEYOR_REPO_TAG_NAME-windows-$env:PLATFORM.tar" Push-AppveyorArtifact "../criterion-$env:APPVEYOR_REPO_TAG_NAME-windows-$env:PLATFORM.tar.bz2" } test_script: - - ps: | - try { cmake --build . --target $env:TEST_TARGET } - catch { type Testing/Temporary/LastTest.log } + - ps: try { ctest } catch { type Testing/Temporary/LastTest.log } #after_test: # - 'make coveralls' From 1658c4ed72821dbe4bfbce529ae0f7c6f2e651f8 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Mon, 7 Sep 2015 11:16:31 +0200 Subject: [PATCH 105/174] Fixed artifacts releases on appveyor --- appveyor.yml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index ea56e78a..4c16dd55 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -27,6 +27,7 @@ platform: configuration: Release install: + - ps: $env:RELEASE_NAME = $env:APPVEYOR_REPO_BRANCH -replace "/", "-" # Hack to make git think it is on the tip of the repo branch - 'git checkout -B %APPVEYOR_REPO_BRANCH%' # Configure project @@ -34,7 +35,7 @@ install: - > cmake -Wno-dev - -DCMAKE_INSTALL_PREFIX="criterion-%APPVEYOR_REPO_TAG_NAME%" + -DCMAKE_INSTALL_PREFIX="criterion-%RELEASE_NAME%" -DCMAKE_PREFIX_PATH="%LOCAL_INSTALL%" -G "%GENERATOR%" .. @@ -50,12 +51,11 @@ build_script: before_deploy: - ps: | - if ($env:Compiler -eq "mingw" -and !$env:APPVEYOR_REPO_TAG_NAME) { - cmake --build . --target install - 7z a -ttar "criterion-$env:APPVEYOR_REPO_BRANCH-windows-$env:PLATFORM.tar" "criterion-$env:APPVEYOR_REPO_TAG_NAME" - 7z a -tbzip2 "../criterion-$env:APPVEYOR_REPO_TAG_NAME-windows-$env:PLATFORM.tar.bz2" "criterion-$env:APPVEYOR_REPO_TAG_NAME-windows-$env:PLATFORM.tar" - Push-AppveyorArtifact "../criterion-$env:APPVEYOR_REPO_TAG_NAME-windows-$env:PLATFORM.tar.bz2" - } + $archive = "criterion-$env:RELEASE_NAME-windows-$env:COMPILER-$env:PLATFORM" + cmake --build . --target install + 7z a -ttar "$archive.tar" "criterion-$env:RELEASE_NAME" + 7z a -tbzip2 "../$archive.tar.bz2" "$archive.tar" + Push-AppveyorArtifact "../$archive.tar.bz2" test_script: - ps: try { ctest } catch { type Testing/Temporary/LastTest.log } @@ -73,7 +73,7 @@ deploy: provider: GitHub auth_token: secure: MnZZQeoxBVnpV9GSSvVok5Je0/N2d/fzG4+ITw95/tYSgZ8rleBV23a5sCwAea3r - artifact: 'criterion-$(APPVEYOR_REPO_TAG_NAME)-windows-$(PLATFORM).tar.bz2' + artifact: 'criterion-$(RELEASE_NAME)-windows-$(COMPILER)-$(PLATFORM).tar.bz2' draft: false prerelease: false on: From 3028af859d33ad9a2cd6987630c6f5815101e3be Mon Sep 17 00:00:00 2001 From: Snaipe Date: Mon, 7 Sep 2015 11:28:39 +0200 Subject: [PATCH 106/174] Switched gcov to gcov 4.9 in travis config --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 4c31586f..25cd6d28 100644 --- a/.travis.yml +++ b/.travis.yml @@ -17,6 +17,7 @@ addons: - g++-4.9 before_install: +- export GCOV="gcov-4.9" - export LOCAL_INSTALL="$HOME" - export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$HOME/lib - export CFLAGS="-g -O0" From aca092b9d6ed033f0c63235a0453734ef8af6b96 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Mon, 7 Sep 2015 15:27:15 +0200 Subject: [PATCH 107/174] Refactored CLI parameter handling in its own function for reusability --- CMakeLists.txt | 1 + doc/internal.rst | 23 +++++++++++++++++++++++ include/criterion/criterion.h | 1 + src/entry.c | 8 ++++++++ src/main.c | 14 +++++++------- 5 files changed, 40 insertions(+), 7 deletions(-) create mode 100644 src/entry.c diff --git a/CMakeLists.txt b/CMakeLists.txt index d2222684..958a62dc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -99,6 +99,7 @@ set(SOURCE_FILES src/posix-compat.c src/theories.c src/main.c + src/entry.c ) if (PCRE_FOUND) diff --git a/doc/internal.rst b/doc/internal.rst index 8c942376..873d6be1 100644 --- a/doc/internal.rst +++ b/doc/internal.rst @@ -34,12 +34,35 @@ fail_fast bool True iff the test runner pattern const char * The pattern of the tests that should be executed =================== ================================== ============================================================== +if you want criterion to provide its own default CLI parameters and environment +variables handling, you can also call ``criterion_initialize(int argc, char *argv[], bool handle_unknown_arg)`` +with the proper ``argc/argv``. ``handle_unknown_arg``, if set to true, is here +to tell criterion to print its usage when an unknown CLI parameter is encountered. +If you want to add your own parameters, you should set it to false. + +The function returns 0 if the main should exit immediately, and 1 if it should +continue. + Starting the test runner ~~~~~~~~~~~~~~~~~~~~~~~~ The test runner can be called with ``criterion_run_all_tests``. The function returns 0 if one test or more failed, 1 otherwise. +Example main +~~~~~~~~~~~~ + +.. code-block:: c + + #include + + int main(int argc, char *argv[]) { + if (!criterion_initialize(argc, argv, true)) + return 0; + + return !criterion_run_all_tests(); + } + Implementing your own output provider ------------------------------------- diff --git a/include/criterion/criterion.h b/include/criterion/criterion.h index 172c5850..ba8185a3 100644 --- a/include/criterion/criterion.h +++ b/include/criterion/criterion.h @@ -79,6 +79,7 @@ CR_BEGIN_C_API CR_API int criterion_run_all_tests(void); +CR_API int criterion_initialize(int argc, char *argv[], bool handle_unknown_arg); CR_END_C_API diff --git a/src/entry.c b/src/entry.c new file mode 100644 index 00000000..b5700b08 --- /dev/null +++ b/src/entry.c @@ -0,0 +1,8 @@ +#include "criterion/criterion.h" + +CR_API int main(int argc, char *argv[]) { + if (!criterion_initialize(argc, argv, true)) + return 0; + + return !criterion_run_all_tests(); +} diff --git a/src/main.c b/src/main.c index 50a86d6e..86d49fac 100644 --- a/src/main.c +++ b/src/main.c @@ -22,13 +22,13 @@ * THE SOFTWARE. */ #define _GNU_SOURCE -#include -#include -#include #include #include #include #include +#include "criterion/criterion.h" +#include "criterion/options.h" +#include "criterion/ordered-set.h" #include "runner.h" #include "config.h" #include "common.h" @@ -120,7 +120,7 @@ int list_tests(bool unicode) { return 0; } -CR_API int main(int argc, char *argv[]) { +CR_API int criterion_initialize(int argc, char *argv[], bool handle_unknown_arg) { static struct option opts[] = { {"verbose", optional_argument, 0, 'b'}, {"version", no_argument, 0, 'v'}, @@ -176,8 +176,8 @@ CR_API int main(int argc, char *argv[]) { case 't': use_tap = true; break; case 'l': do_list_tests = true; break; case 'v': do_print_version = true; break; - case 'h': - default : do_print_usage = true; break; + case 'h': do_print_usage = true; break; + default : do_print_usage = handle_unknown_arg; break; } } if (use_tap) @@ -189,5 +189,5 @@ CR_API int main(int argc, char *argv[]) { if (do_list_tests) return list_tests(!criterion_options.use_ascii); - return !criterion_run_all_tests(); + return 1; } From d7466dc0e57126820fea202939695caa1d1c6bc9 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Mon, 7 Sep 2015 15:55:36 +0200 Subject: [PATCH 108/174] Refactored the default main to allow dynamic test registration --- doc/internal.rst | 18 +++++++-- include/criterion/criterion.h | 8 +++- src/entry.c | 10 ++++- src/main.c | 2 +- src/runner.c | 73 ++++++++++++++++++++--------------- 5 files changed, 72 insertions(+), 39 deletions(-) diff --git a/doc/internal.rst b/doc/internal.rst index 873d6be1..69b5f0ad 100644 --- a/doc/internal.rst +++ b/doc/internal.rst @@ -10,6 +10,13 @@ can define your own main function. Configuring the test runner ~~~~~~~~~~~~~~~~~~~~~~~~~~~ +First and foremost, you need to generate the test set; this is done by calling +``criterion_initialize()``. The function returns a ``struct criterion_test_set *``, +that you need to pass to ``criterion_run_all_tests`` later on. + +At the very end of your main, you also need to call ``criterion_finalize`` with +the test set as parameter to free any ressources initialized by criterion earlier. + You'd usually want to configure the test runner before calling it. Configuration is done by setting fields in a global variable named ``criterion_options`` (include criterion/options.h). @@ -35,7 +42,7 @@ pattern const char * The pattern of the tests =================== ================================== ============================================================== if you want criterion to provide its own default CLI parameters and environment -variables handling, you can also call ``criterion_initialize(int argc, char *argv[], bool handle_unknown_arg)`` +variables handling, you can also call ``criterion_handle_args(int argc, char *argv[], bool handle_unknown_arg)`` with the proper ``argc/argv``. ``handle_unknown_arg``, if set to true, is here to tell criterion to print its usage when an unknown CLI parameter is encountered. If you want to add your own parameters, you should set it to false. @@ -57,10 +64,15 @@ Example main #include int main(int argc, char *argv[]) { - if (!criterion_initialize(argc, argv, true)) + struct criterion_test_set *tests = criterion_initialize(); + + if (!criterion_handle_args(argc, argv, true)) return 0; - return !criterion_run_all_tests(); + int result = !criterion_run_all_tests(set); + + criterion_finalize(set); + return result; } Implementing your own output provider diff --git a/include/criterion/criterion.h b/include/criterion/criterion.h index ba8185a3..82dab63d 100644 --- a/include/criterion/criterion.h +++ b/include/criterion/criterion.h @@ -78,8 +78,12 @@ CR_BEGIN_C_API -CR_API int criterion_run_all_tests(void); -CR_API int criterion_initialize(int argc, char *argv[], bool handle_unknown_arg); +CR_API struct criterion_test_set *criterion_initialize(void); +CR_API void criterion_finalize(struct criterion_test_set *tests); +CR_API int criterion_run_all_tests(struct criterion_test_set *tests); +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); CR_END_C_API diff --git a/src/entry.c b/src/entry.c index b5700b08..71e9b9d0 100644 --- a/src/entry.c +++ b/src/entry.c @@ -1,8 +1,14 @@ #include "criterion/criterion.h" CR_API int main(int argc, char *argv[]) { - if (!criterion_initialize(argc, argv, true)) + struct criterion_test_set *tests = criterion_initialize(); + + if (!criterion_handle_args(argc, argv, true)) return 0; - return !criterion_run_all_tests(); + int result = !criterion_run_all_tests(tests); + + criterion_finalize(tests); + + return result; } diff --git a/src/main.c b/src/main.c index 86d49fac..3aa95841 100644 --- a/src/main.c +++ b/src/main.c @@ -120,7 +120,7 @@ int list_tests(bool unicode) { return 0; } -CR_API int criterion_initialize(int argc, char *argv[], bool handle_unknown_arg) { +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'}, diff --git a/src/runner.c b/src/runner.c index 388d0dac..ed053152 100644 --- a/src/runner.c +++ b/src/runner.c @@ -80,6 +80,20 @@ static void dtor_test_set(void *ptr, UNUSED void *meta) { sfree(t->suites); } +void criterion_register_test(struct criterion_test_set *set, + struct criterion_test *test) { + + struct criterion_suite_set css = { + .suite = { .name = test->category }, + }; + struct criterion_suite_set *s = insert_ordered_set(set->suites, &css, sizeof (css)); + if (!s->tests) + s->tests = new_ordered_set(cmp_test, NULL); + + insert_ordered_set(s->tests, test, sizeof(*test)); + ++set->tests; +} + struct criterion_test_set *criterion_init(void) { struct criterion_ordered_set *suites = new_ordered_set(cmp_suite, dtor_suite_set); @@ -93,25 +107,6 @@ struct criterion_test_set *criterion_init(void) { insert_ordered_set(suites, &css, sizeof (css)); } - size_t nb_tests = 0; - FOREACH_TEST_SEC(test) { - if (!test->category) - break; - - if (!*test->category) - continue; - - struct criterion_suite_set css = { - .suite = { .name = test->category }, - }; - struct criterion_suite_set *s = insert_ordered_set(suites, &css, sizeof (css)); - if (!s->tests) - s->tests = new_ordered_set(cmp_test, NULL); - - insert_ordered_set(s->tests, test, sizeof(*test)); - ++nb_tests; - } - struct criterion_test_set *set = smalloc( .size = sizeof (struct criterion_test_set), .dtor = dtor_test_set @@ -119,9 +114,19 @@ struct criterion_test_set *criterion_init(void) { *set = (struct criterion_test_set) { suites, - nb_tests, + 0, }; + FOREACH_TEST_SEC(test) { + if (!test->category) + break; + + if (!*test->category) + continue; + + criterion_register_test(set, test); + } + return set; } @@ -341,16 +346,27 @@ void disable_unmatching(struct criterion_test_set *set) { } #endif -static int criterion_run_all_tests_impl(void) { +struct criterion_test_set *criterion_initialize(void) { + init_i18n(); + if (resume_child()) // (windows only) resume from the fork - return -1; + exit(0); struct criterion_test_set *set = criterion_init(); -#ifdef HAVE_PCRE + + #ifdef HAVE_PCRE if (criterion_options.pattern) disable_unmatching(set); -#endif + #endif + return set; +} + +void criterion_finalize(struct criterion_test_set *set) { + sfree(set); +} + +static int criterion_run_all_tests_impl(struct criterion_test_set *set) { report(PRE_ALL, set); log(pre_all, set); @@ -368,19 +384,14 @@ static int criterion_run_all_tests_impl(void) { log(post_all, stats); cleanup: - sfree(set); sfree(stats); return result; } -int criterion_run_all_tests(void) { - init_i18n(); +int criterion_run_all_tests(struct criterion_test_set *set) { set_runner_process(); - int res = criterion_run_all_tests_impl(); + int res = criterion_run_all_tests_impl(set); unset_runner_process(); - if (res == -1) // if this is the test worker terminating - exit(0); - return criterion_options.always_succeed || res; } From f6b6139607f8b66b7d8166398d0283da8ea5cb52 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Mon, 7 Sep 2015 16:17:16 +0200 Subject: [PATCH 109/174] Fixed regression on --pattern handling --- src/runner.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/src/runner.c b/src/runner.c index ed053152..5e078eab 100644 --- a/src/runner.c +++ b/src/runner.c @@ -352,14 +352,7 @@ struct criterion_test_set *criterion_initialize(void) { if (resume_child()) // (windows only) resume from the fork exit(0); - struct criterion_test_set *set = criterion_init(); - - #ifdef HAVE_PCRE - if (criterion_options.pattern) - disable_unmatching(set); - #endif - - return set; + return criterion_init(); } void criterion_finalize(struct criterion_test_set *set) { @@ -389,6 +382,11 @@ static int criterion_run_all_tests_impl(struct criterion_test_set *set) { } int criterion_run_all_tests(struct criterion_test_set *set) { + #ifdef HAVE_PCRE + if (criterion_options.pattern) + disable_unmatching(set); + #endif + set_runner_process(); int res = criterion_run_all_tests_impl(set); unset_runner_process(); From afad78c433174af6f8c03c85fb6b5bda573ae6be Mon Sep 17 00:00:00 2001 From: Snaipe Date: Mon, 7 Sep 2015 18:03:05 +0200 Subject: [PATCH 110/174] Added generated datapoints theory sample --- include/criterion/theories.h | 3 +++ samples/theories.c | 17 +++++++++++++++++ samples/theories.cc | 17 +++++++++++++++++ 3 files changed, 37 insertions(+) diff --git a/include/criterion/theories.h b/include/criterion/theories.h index 3dc42c51..29055b53 100644 --- a/include/criterion/theories.h +++ b/include/criterion/theories.h @@ -56,6 +56,9 @@ CR_API void cr_theory_call(struct criterion_theory_context *ctx, void (*fnptr)(v # define TheoryDataPoints(Category, Name) \ static struct criterion_datapoints IDENTIFIER_(Category, Name, dps)[] +# define TheoryDataPoint(Category, Name) \ + (IDENTIFIER_(Category, Name, dps)) + # 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; }() diff --git a/samples/theories.c b/samples/theories.c index 564297df..6e96a6dd 100644 --- a/samples/theories.c +++ b/samples/theories.c @@ -102,3 +102,20 @@ 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_abort_test(NULL); } + +// 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_abort_test(NULL); // we fail to display the parameter +} diff --git a/samples/theories.cc b/samples/theories.cc index 62f8b91c..d0e3dd37 100644 --- a/samples/theories.cc +++ b/samples/theories.cc @@ -110,3 +110,20 @@ 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_abort_test(NULL); } + +// 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_abort_test(NULL); // we fail to display the parameter +} From b8374bca163387207cea60dc43486a895754c564 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Mon, 7 Sep 2015 20:07:59 +0200 Subject: [PATCH 111/174] [Issue #36] Added throw assertions --- include/criterion/assert.h | 28 ++++++++++++++++++++++++++++ samples/asserts.cc | 7 +++++++ samples/asserts.cc.bin.err.expected | 10 ++++++---- 3 files changed, 41 insertions(+), 4 deletions(-) diff --git a/include/criterion/assert.h b/include/criterion/assert.h index 539393d0..1d67a00d 100644 --- a/include/criterion/assert.h +++ b/include/criterion/assert.h @@ -288,6 +288,34 @@ struct criterion_assert_args { cr_expect_arrays_eq_cmp_(__VA_ARGS__, CR_SENTINEL) # endif /* !__GNUC__ */ +# ifdef __cplusplus +# define cr_assert_throw(...) CR_EXPAND(cr_assert_throw_(__VA_ARGS__, CR_SENTINEL)) +# define cr_assert_throw_(Statement, Exception, ...) \ + try { \ + Statement; \ + } catch (Exception &ex) { \ + } catch (...) { CR_EXPAND(cr_assert_impl(FATAL, 0, __VA_ARGS__)); } + +# define cr_assert_no_throw(...) CR_EXPAND(cr_assert_not_throw_(__VA_ARGS__, CR_SENTINEL)) +# define cr_assert_no_throw_(Statement, Exception, ...) \ + try { \ + Statement; \ + } catch (Exception &ex) { CR_EXPAND(cr_assert_impl(FATAL, 0, __VA_ARGS__)); } + +# define cr_expect_throw(...) CR_EXPAND(cr_expect_throw_(__VA_ARGS__, CR_SENTINEL)) +# define cr_expect_throw_(Statement, Exception, ...) \ + try { \ + Statement; \ + } catch (Exception &ex) { \ + } catch (...) { CR_EXPAND(cr_assert_impl(NORMAL, 0, __VA_ARGS__)); } + +# define cr_expect_no_throw(...) CR_EXPAND(cr_expect_not_throw_(__VA_ARGS__, CR_SENTINEL)) +# define cr_expect_no_throw_(Statement, Exception, ...) \ + try { \ + Statement; \ + } catch (Exception &ex) { CR_EXPAND(cr_assert_impl(NORMAL, 0, __VA_ARGS__)); } +# endif + // The section below is here for backward compatibility purposes. // It shall be removed in the text major version of Criterion # ifndef CRITERION_NO_COMPAT diff --git a/samples/asserts.cc b/samples/asserts.cc index 0d9daab5..c7f5c8f0 100644 --- a/samples/asserts.cc +++ b/samples/asserts.cc @@ -1,4 +1,6 @@ #include +#include +#include Test(asserts, base) { cr_assert(true); @@ -78,3 +80,8 @@ Test(asserts, array) { cr_assert_arrays_eq_cmp(s1, s2, 2, eq_dummy); #endif } + +Test(asserts, exception) { + cr_assert_throw(throw std::exception(), std::exception); + cr_assert_throw(throw std::exception(), std::bad_alloc); +} diff --git a/samples/asserts.cc.bin.err.expected b/samples/asserts.cc.bin.err.expected index 3b7d7aef..8b27dddf 100644 --- a/samples/asserts.cc.bin.err.expected +++ b/samples/asserts.cc.bin.err.expected @@ -1,6 +1,8 @@ -[----] asserts.cc:9: Assertion failed: assert is fatal, expect isn't -[----] asserts.cc:10: Assertion failed: This assert runs +[----] asserts.cc:11: Assertion failed: assert is fatal, expect isn't +[----] asserts.cc:12: Assertion failed: This assert runs [FAIL] asserts::base: (0.00s) -[----] asserts.cc:18: Assertion failed: The conditions for this test were not met. +[----] asserts.cc:86: Assertion failed: 0 +[FAIL] asserts::exception: (0.00s) +[----] asserts.cc:20: Assertion failed: The conditions for this test were not met. [FAIL] asserts::old_school: (0.00s) -[====] Synthesis: Tested: 6 | Passing: 4 | Failing: 2 | Crashing: 0  +[====] Synthesis: Tested: 7 | Passing: 4 | Failing: 3 | Crashing: 0  From 4d114fdd3893d8020b5ed76a4ec054a88852792a Mon Sep 17 00:00:00 2001 From: Snaipe Date: Tue, 8 Sep 2015 18:46:04 +0200 Subject: [PATCH 112/174] Changed the assert interface to accept a format string --- CMakeLists.txt | 7 + include/criterion/abort.h | 1 + include/criterion/asprintf-compat.h | 43 ++ include/criterion/assert.h | 598 +++++++++++++++++----------- include/criterion/common.h | 5 +- include/criterion/preprocess.h | 72 ++++ include/criterion/stats.h | 2 - samples/asserts.c | 30 +- samples/asserts.cc | 30 +- samples/theories.c | 8 +- samples/theories.cc | 8 +- src/asprintf.c | 62 +++ src/event.c | 36 +- src/log/normal.c | 3 +- src/log/tap.c | 2 +- 15 files changed, 619 insertions(+), 288 deletions(-) create mode 100644 include/criterion/asprintf-compat.h create mode 100644 include/criterion/preprocess.h create mode 100644 src/asprintf.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 958a62dc..2038e171 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -110,6 +110,12 @@ if (PCRE_FOUND) set(HAVE_PCRE 1) endif () +if ("${CMAKE_SYSTEM_NAME}" EQUAL "Linux") + set (SOURCE_FILES ${SOURCE_FILES} + src/asprintf.c + ) +endif () + set(INTERFACE_FILES include/criterion/assert.h include/criterion/abort.h @@ -123,6 +129,7 @@ set(INTERFACE_FILES include/criterion/ordered-set.h include/criterion/stats.h include/criterion/theories.h + include/criterion/asprintf-compat.h ) # Generate the configure file diff --git a/include/criterion/abort.h b/include/criterion/abort.h index 598b27ef..ca981b51 100644 --- a/include/criterion/abort.h +++ b/include/criterion/abort.h @@ -29,6 +29,7 @@ CR_BEGIN_C_API CR_API NORETURN void criterion_abort_test(void); +CR_API CR_INLINE void criterion_continue_test(void) {} CR_END_C_API diff --git a/include/criterion/asprintf-compat.h b/include/criterion/asprintf-compat.h new file mode 100644 index 00000000..2fc5c1bf --- /dev/null +++ b/include/criterion/asprintf-compat.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 CRITERION_ASPRINTF_COMPAT_H_ +# define CRITERION_ASPRINTF_COMPAT_H_ + +# ifdef __cplusplus +# include +# else +# include +# endif + +# include "common.h" + +CR_BEGIN_C_API + +FORMAT(printf, 2, 3) +CR_API int asprintf(char **strp, const char *fmt, ...) CR_NOTHROW; +CR_API int vasprintf(char **strp, const char *fmt, va_list ap) CR_NOTHROW; + +CR_END_C_API + +#endif /* !CRITERION_ASPRINTF_COMPAT_H_ */ diff --git a/include/criterion/assert.h b/include/criterion/assert.h index 1d67a00d..4aeaa9b9 100644 --- a/include/criterion/assert.h +++ b/include/criterion/assert.h @@ -24,11 +24,13 @@ #ifndef CRITERION_ASSERT_H_ # define CRITERION_ASSERT_H_ +# include "preprocess.h" +# include "asprintf-compat.h" + # ifdef __cplusplus # include # include -using std::strcmp; -using std::memcmp; +# include # else # include # include @@ -41,11 +43,6 @@ using std::memcmp; # include "event.h" # include "abort.h" -enum criterion_assert_kind { - NORMAL, - FATAL -}; - struct criterion_assert_args { const char *msg; int sentinel_; @@ -60,264 +57,372 @@ struct criterion_assert_args { # define CR_GET_CONDITION_STR(Condition, ...) #Condition # define CR_VA_SKIP(_, ...) __VA_ARGS__ -# ifndef __cplusplus -# define CR_ZERO_FILL(Arg) memset(&(Arg), 0, sizeof (Arg)) +# ifdef __cplusplus +# define CR_STDN std:: # else -# define CR_ZERO_FILL(Arg) std::memset(&(Arg), 0, sizeof (Arg)) +# define CR_STDN # endif -# define cr_assert_impl(Kind, ...) \ +# define CR_INIT_STATS_(BufSize, MsgVar, ...) CR_EXPAND( \ do { \ - struct criterion_assert_args args = { \ - CR_EXPAND(CR_VA_SKIP(__VA_ARGS__)) \ - }; \ - bool passed = !!(CR_EXPAND(CR_GET_CONDITION(__VA_ARGS__))); \ - struct criterion_assert_stats stat; \ - CR_ZERO_FILL(stat); \ - stat.kind = (Kind); \ - stat.condition = CR_EXPAND(CR_GET_CONDITION_STR(__VA_ARGS__)); \ - stat.message = args.msg ? args.msg : ""; \ - stat.passed = passed; \ - stat.file = __FILE__; \ - stat.line = __LINE__; \ - send_event(ASSERT, &stat, sizeof (stat)); \ - if (!passed && (Kind) == FATAL) \ - criterion_abort_test(); \ + const char *default_msg = "" CR_VA_HEAD(__VA_ARGS__); \ + char *formatted_msg = NULL; \ + int msglen = asprintf(&formatted_msg, "" CR_VA_TAIL(__VA_ARGS__)); \ + MsgVar = formatted_msg ? formatted_msg : default_msg; \ + \ + if (!formatted_msg) \ + msglen = strlen(default_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; \ + buf += sizeof (size_t); \ + CR_STDN strcpy(buf, MsgVar); \ + CR_STDN free(formatted_msg); \ + } while (0)) + +# define CR_FAIL_ABORT_ criterion_abort_test +# define CR_FAIL_CONTINUES_ criterion_continue_test + +# define cr_assert_impl(Fail, Condition, ...) \ + do { \ + bool passed = !!(Condition); \ + \ + const char *msg = NULL; \ + size_t bufsize; \ + \ + _Pragma("GCC diagnostic ignored \"-Wformat-zero-length\"") \ + 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__; \ + \ + send_event(ASSERT, stat, bufsize); \ + CR_STDN free(stat); \ + \ + if (!passed) \ + Fail(); \ } while (0) -// Common asserts - -# define cr_abort_test(Message) \ - do { \ - const char *msg = (Message); \ - cr_assert(0, msg ? msg : "The conditions for this test were not met.");\ +// Base assertions + +# define cr_fail(Fail, ...) \ + CR_EXPAND(cr_assert_impl( \ + Fail, \ + 0, \ + dummy, \ + "The condition for this assertion were not met.", \ + __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, \ + 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, \ + 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, \ + 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, \ + 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, \ + 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(...) CR_EXPAND(cr_assert_eq(CR_VA_HEAD(__VA_ARGS__), NULL, CR_VA_TAIL(__VA_ARGS__))) +# define cr_expect_null(...) CR_EXPAND(cr_expect_eq(CR_VA_HEAD(__VA_ARGS__), NULL, CR_VA_TAIL(__VA_ARGS__))) + +# define cr_assert_not_null(...) CR_EXPAND(cr_assert_neq(CR_VA_HEAD(__VA_ARGS__), NULL, CR_VA_TAIL(__VA_ARGS__))) +# define cr_expect_not_null(...) CR_EXPAND(cr_expect_neq(CR_VA_HEAD(__VA_ARGS__), NULL, CR_VA_TAIL(__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, \ + 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_(Fail, Op, Actual, Expected, ...) \ + CR_EXPAND(cr_assert_impl( \ + Fail, \ + CR_STDN strcmp((Actual), (Expected)) Op 0, \ + dummy, \ + CR_STR((as strings) (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__)) + +// 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, \ + 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__)) + +# define cr_assert_arr_neq(...) CR_EXPAND(cr_assert_mem_op_va_(CR_FAIL_ABORT_, !=, __VA_ARGS__)) +# define cr_expect_arr_neq(...) CR_EXPAND(cr_assert_mem_op_va_(CR_FAIL_CONTINUES_, !=, __VA_ARGS__)) + +// Safe array comparison assertions + +# if defined(__GNUC__) || 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, \ + CR_STR((Actual)[0 .. Size] Op (Expected)[0 .. Size]), \ + __VA_ARGS__ \ + )); \ } while (0) -# ifdef __cplusplus -# define CR_SENTINEL 0 -# else -# define CR_SENTINEL .sentinel_ = 0 -# endif - -# define cr_assert(...) CR_EXPAND(cr_assert_(__VA_ARGS__, CR_SENTINEL)) +# 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_expect(...) CR_EXPAND(cr_expect_(__VA_ARGS__, CR_SENTINEL)) +# 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__)) -# define cr_assert_(Condition, ...) CR_EXPAND(cr_assert_impl(FATAL, Condition, __VA_ARGS__)) -# define cr_expect_(Condition, ...) CR_EXPAND(cr_assert_impl(NORMAL, Condition, __VA_ARGS__)) +# define cr_assert_arr_neq_cmp(...) CR_EXPAND(cr_assert_arr_op_cmp_va_(CR_FAIL_ABORT_, !=, __VA_ARGS__)) +# define cr_expect_arr_neq_cmp(...) CR_EXPAND(cr_assert_arr_op_cmp_va_(CR_FAIL_CONTINUES_, !=, __VA_ARGS__)) -# define cr_assert_not(...) CR_EXPAND(cr_assert_not_(__VA_ARGS__, CR_SENTINEL)) -# define cr_expect_not(...) CR_EXPAND(cr_expect_not_(__VA_ARGS__, CR_SENTINEL)) +# define cr_assert_arr_lt_cmp(...) CR_EXPAND(cr_assert_arr_op_cmp_va_(CR_FAIL_ABORT_, <, __VA_ARGS__)) +# define cr_expect_arr_lt_cmp(...) CR_EXPAND(cr_assert_arr_op_cmp_va_(CR_FAIL_CONTINUES_, <, __VA_ARGS__)) -# define cr_assert_not_(Condition, ...) \ - CR_EXPAND(cr_assert_impl(FATAL, !(Condition), __VA_ARGS__)) -# define cr_expect_not_(Condition, ...) \ - CR_EXPAND(cr_expect_impl(NORMAL, !(Condition), __VA_ARGS__)) +# define cr_assert_arr_leq_cmp(...) CR_EXPAND(cr_assert_arr_op_cmp_va_(CR_FAIL_ABORT_, <=, __VA_ARGS__)) +# define cr_expect_arr_leq_cmp(...) CR_EXPAND(cr_assert_arr_op_cmp_va_(CR_FAIL_CONTINUES_, <=, __VA_ARGS__)) -// Native asserts +# define cr_assert_arr_gt_cmp(...) CR_EXPAND(cr_assert_arr_op_cmp_va_(CR_FAIL_ABORT_, >, __VA_ARGS__)) +# define cr_expect_arr_gt_cmp(...) CR_EXPAND(cr_assert_arr_op_cmp_va_(CR_FAIL_CONTINUES_, >, __VA_ARGS__)) -# define cr_assert_op_(Op, Actual, Expected, ...) \ - CR_EXPAND(cr_assert_impl(FATAL, (Actual) Op (Expected), __VA_ARGS__)) -# define cr_expect_op_(Op, Actual, Expected, ...) \ - CR_EXPAND(cr_assert_impl(NORMAL, (Actual) Op (Expected), __VA_ARGS__)) +# define cr_assert_arr_geq_cmp(...) CR_EXPAND(cr_assert_arr_op_cmp_va_(CR_FAIL_ABORT_, >=, __VA_ARGS__)) +# define cr_expect_arr_geq_cmp(...) CR_EXPAND(cr_assert_arr_op_cmp_va_(CR_FAIL_CONTINUES_, >=, __VA_ARGS__)) -# define cr_assert_eq(...) CR_EXPAND(cr_assert_op_(==, __VA_ARGS__, CR_SENTINEL)) -# define cr_expect_eq(...) CR_EXPAND(cr_expect_op_(==, __VA_ARGS__, CR_SENTINEL)) - -# define cr_assert_neq(...) CR_EXPAND(cr_assert_op_(!=, __VA_ARGS__, CR_SENTINEL)) -# define cr_expect_neq(...) CR_EXPAND(cr_expect_op_(!=, __VA_ARGS__, CR_SENTINEL)) +# else -# define cr_assert_lt(...) CR_EXPAND(cr_assert_op_(<, __VA_ARGS__, CR_SENTINEL)) -# define cr_expect_lt(...) CR_EXPAND(cr_expect_op_(<, __VA_ARGS__, CR_SENTINEL)) +# define CRITERION_GNUC_WARN__(Msg) \ + _Pragma(#Msg) -# define cr_assert_gt(...) CR_EXPAND(cr_assert_op_(>, __VA_ARGS__, CR_SENTINEL)) -# define cr_expect_gt(...) CR_EXPAND(cr_expect_op_(>, __VA_ARGS__, CR_SENTINEL)) +# define CRITERION_GNUC_WARN_(Name) CRITERION_GNUC_WARN__( \ + message \ + "The `" #Name "` macro is only available on GNU C compilers." \ + ) -# define cr_assert_leq(...) CR_EXPAND(cr_assert_op_(<=, __VA_ARGS__, CR_SENTINEL)) -# define cr_expect_leq(...) CR_EXPAND(cr_expect_op_(<=, __VA_ARGS__, CR_SENTINEL)) +# 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 -# define cr_assert_geq(...) CR_EXPAND(cr_assert_op_(>=, __VA_ARGS__, CR_SENTINEL)) -# define cr_expect_geq(...) CR_EXPAND(cr_expect_op_(>=, __VA_ARGS__, CR_SENTINEL)) +# define cr_assert_arr_neq_cmp(...) CRITERION_GNUC_WARN_(cr_assert_arr_neq_cmp) CR_NOOP +# define cr_expect_arr_neq_cmp(...) CRITERION_GNUC_WARN_(cr_expect_arr_neq_cmp) CR_NOOP -# define cr_assert_null_(Value, ...) \ - CR_EXPAND(cr_assert_impl(FATAL, (Value) == NULL, __VA_ARGS__)) -# define cr_expect_null_(Value, ...) \ - CR_EXPAND(cr_assert_impl(NORMAL, (Value) == NULL, __VA_ARGS__)) +# define cr_assert_arr_lt_cmp(...) CRITERION_GNUC_WARN_(cr_assert_arr_lt_cmp) CR_NOOP +# define cr_expect_arr_lt_cmp(...) CRITERION_GNUC_WARN_(cr_expect_arr_lt_cmp) CR_NOOP -# define cr_assert_null(...) CR_EXPAND(cr_assert_null_(__VA_ARGS__, CR_SENTINEL)) -# define cr_expect_null(...) CR_EXPAND(cr_expect_null_(__VA_ARGS__, CR_SENTINEL)) - -# define cr_assert_not_null_(Value, ...) \ - CR_EXPAND(cr_assert_impl(FATAL, (Value) != NULL, __VA_ARGS__)) -# define cr_expect_not_null_(Value, ...) \ - CR_EXPAND(cr_assert_impl(NORMAL, (Value) != NULL, __VA_ARGS__)) - -# define cr_assert_not_null(...) CR_EXPAND(cr_assert_not_null_(__VA_ARGS__, CR_SENTINEL)) -# define cr_expect_not_null(...) CR_EXPAND(cr_expect_not_null_(__VA_ARGS__, CR_SENTINEL)) - -// Floating-point asserts - -# define cr_assert_float_eq(...) \ - CR_EXPAND(cr_assert_float_eq_(__VA_ARGS__, CR_SENTINEL)) -# define cr_expect_float_eq(...) \ - CR_EXPAND(cr_expect_float_eq_(__VA_ARGS__, CR_SENTINEL)) - -# define cr_assert_float_eq_(Actual, Expected, Epsilon, ...) \ - CR_EXPAND(cr_assert_impl(FATAL, (Expected) - (Actual) <= (Epsilon) \ - && (Actual) - (Expected) <= (Epsilon), \ - __VA_ARGS__)) -# define cr_expect_float_eq_(Actual, Expected, Epsilon, ...) \ - CR_EXPAND(cr_assert_impl(NORMAL, (Expected) - (Actual) <= (Epsilon) \ - && (Actual) - (Expected) <= (Epsilon), \ - __VA_ARGS__)) - -# define cr_assert_float_neq(...) \ - CR_EXPAND(cr_assert_float_neq_(__VA_ARGS__, CR_SENTINEL)) -# define cr_expect_float_neq(...) \ - CR_EXPAND(cr_expect_float_neq_(__VA_ARGS__, CR_SENTINEL)) - -# define cr_assert_float_neq_(Actual, Expected, Epsilon, ...) \ - CR_EXPAND(cr_assert_impl(FATAL, (Expected) - (Actual) > (Epsilon) \ - || (Actual) - (Expected) > (Epsilon), \ - __VA_ARGS__)) -# define cr_expect_float_neq_(Actual, Expected, Epsilon, ...) \ - CR_EXPAND(cr_assert_impl(NORMAL, (Expected) - (Actual) > (Epsilon) \ - || (Actual) - (Expected) > (Epsilon), \ - __VA_ARGS__)) - -// String asserts - -# define cr_assert_strings_(Op, Actual, Expected, ...) \ - CR_EXPAND(cr_assert_impl(FATAL, strcmp((Actual), (Expected)) Op 0, __VA_ARGS__)) -# define cr_expect_strings_(Op, Actual, Expected, ...) \ - CR_EXPAND(cr_assert_impl(NORMAL, strcmp((Actual), (Expected)) Op 0, __VA_ARGS__)) - -# define cr_assert_strings_eq(...) \ - CR_EXPAND(cr_assert_strings_(==, __VA_ARGS__, CR_SENTINEL)) -# define cr_expect_strings_eq(...) \ - CR_EXPAND(cr_expect_strings_(==, __VA_ARGS__, CR_SENTINEL)) - -# define cr_assert_strings_neq(...) \ - CR_EXPAND(cr_assert_strings_(!=, __VA_ARGS__, CR_SENTINEL)) -# define cr_expect_strings_neq(...) \ - CR_EXPAND(cr_expect_strings_(!=, __VA_ARGS__, CR_SENTINEL)) - -# define cr_assert_strings_gt(...) CR_EXPAND(cr_assert_strings_(>, __VA_ARGS__, CR_SENTINEL)) -# define cr_expect_strings_gt(...) CR_EXPAND(cr_expect_strings_(>, __VA_ARGS__, CR_SENTINEL)) - -# define cr_assert_strings_lt(...) CR_EXPAND(cr_assert_strings_(<, __VA_ARGS__, CR_SENTINEL)) -# define cr_expect_strings_lt(...) CR_EXPAND(cr_expect_strings_(<, __VA_ARGS__, CR_SENTINEL)) - -# define cr_assert_strings_leq(...) CR_EXPAND(cr_assert_strings_(<=, __VA_ARGS__, CR_SENTINEL)) -# define cr_expect_strings_leq(...) CR_EXPAND(cr_expect_strings_(<=, __VA_ARGS__, CR_SENTINEL)) - -# define cr_assert_strings_geq(...) CR_EXPAND(cr_assert_strings_(>=, __VA_ARGS__, CR_SENTINEL)) -# define cr_expect_strings_geq(...) CR_EXPAND(cr_expect_strings_(>=, __VA_ARGS__, CR_SENTINEL)) - -// Array asserts - -# define cr_assert_arrays_eq(...) \ - CR_EXPAND(cr_assert_arrays_eq_(__VA_ARGS__, CR_SENTINEL)) -# define cr_expect_arrays_eq(...) \ - CR_EXPAND(cr_expect_arrays_eq_(__VA_ARGS__, CR_SENTINEL)) - -# define cr_assert_arrays_neq(...) \ - CR_EXPAND(cr_assert_arrays_neq_(__VA_ARGS__, CR_SENTINEL)) -# define cr_expect_arrays_neq(...) \ - CR_EXPAND(cr_expect_arrays_neq_(__VA_ARGS__, CR_SENTINEL)) - -# define cr_assert_arrays_eq_(A, B, Size, ...) \ - CR_EXPAND(cr_assert_impl(FATAL, !memcmp((A), (B), (Size)), \ - __VA_ARGS__)) -# define cr_expect_arrays_eq_(A, B, Size, ...) \ - CR_EXPAND(cr_assert_impl(NORMAL, !memcmp((A), (B), (Size)), \ - __VA_ARGS__)) - -# define cr_assert_arrays_neq_(A, B, Size, ...) \ - CR_EXPAND(cr_assert_impl(FATAL, memcmp((A), (B), (Size)), \ - __VA_ARGS__)) -# define cr_expect_arrays_neq_(A, B, Size, ...) \ - CR_EXPAND(cr_assert_impl(NORMAL, memcmp((A), (B), (Size)), \ - __VA_ARGS__)) - -# ifdef __GNUC__ -# define CRIT_ARR_COMPARE_(A, B, Size, Cmp, Result) \ - __typeof__(&(A)[0]) first = (A); \ - __typeof__(&(B)[0]) second = (B); \ - int equals = 1; \ - size_t i, size; \ - for (i = 0, size = (Size); equals && i < size; ++i) \ - equals = equals && !Cmp(first + i, second + i) - -# define cr_assert_arrays_eq_cmp_(A, B, Size, Cmp, ...) \ - do { \ - CRIT_ARR_COMPARE_(A, B, Size, Cmp, equals); \ - cr_assert_impl(FATAL, equals, \ - __VA_ARGS__); \ - } while (0) +# define cr_assert_arr_leq_cmp(...) CRITERION_GNUC_WARN_(cr_assert_arr_leq_cmp) CR_NOOP +# define cr_expect_arr_leq_cmp(...) CRITERION_GNUC_WARN_(cr_expect_arr_leq_cmp) CR_NOOP -# define cr_expect_arrays_eq_cmp_(A, B, Size, Cmp, ...) \ - do { \ - CRIT_ARR_COMPARE_(A, B, Size, Cmp, equals); \ - cr_assert_impl(NORMAL, equals, \ - __VA_ARGS__); \ - } while (0) +# define cr_assert_arr_gt_cmp(...) CRITERION_GNUC_WARN_(cr_assert_arr_gt_cmp) CR_NOOP +# define cr_expect_arr_gt_cmp(...) CRITERION_GNUC_WARN_(cr_expect_arr_gt_cmp) CR_NOOP -# define cr_assert_arrays_eq_cmp(...) \ - cr_assert_arrays_eq_cmp_(__VA_ARGS__, CR_SENTINEL) -# define cr_expect_arrays_eq_cmp(...) \ - cr_expect_arrays_eq_cmp_(__VA_ARGS__, CR_SENTINEL) +# define cr_assert_arr_geq_cmp(...) CRITERION_GNUC_WARN_(cr_assert_arr_geq_cmp) CR_NOOP +# define cr_expect_arr_geq_cmp(...) CRITERION_GNUC_WARN_(cr_expect_arr_geq_cmp) CR_NOOP -# define cr_assert_arrays_neq_cmp_(A, B, Size, Cmp, ...) \ - do { \ - CRIT_ARR_COMPARE_(A, B, Size, Cmp, equals); \ - cr_assert_impl(FATAL, !equals, \ - __VA_ARGS__); \ - } while (0) +# endif -# define cr_expect_arrays_neq_cmp_(A, B, Size, Cmp, ...) \ - do { \ - CRIT_ARR_COMPARE_(A, B, Size, Cmp, equals); \ - cr_assert_impl(NORMAL, equals, \ - __VA_ARGS__); \ - } while (0) +# ifdef __cplusplus -# define cr_assert_arrays_neq_cmp(...) \ - cr_assert_arrays_eq_cmp_(__VA_ARGS__, CR_SENTINEL) -# define cr_expect_arrays_neq_cmp(...) \ - cr_expect_arrays_eq_cmp_(__VA_ARGS__, CR_SENTINEL) -# endif /* !__GNUC__ */ +# define cr_assert_throw_(Fail, Statement, Exception, ...) \ + try { \ + Statement; \ + } catch (Exception &ex) { \ + } catch (...) { CR_EXPAND(cr_fail(Fail, CR_VA_TAIL(__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 &ex) { CR_EXPAND(cr_fail(Fail, CR_VA_TAIL(__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__)) -# ifdef __cplusplus -# define cr_assert_throw(...) CR_EXPAND(cr_assert_throw_(__VA_ARGS__, CR_SENTINEL)) -# define cr_assert_throw_(Statement, Exception, ...) \ - try { \ - Statement; \ - } catch (Exception &ex) { \ - } catch (...) { CR_EXPAND(cr_assert_impl(FATAL, 0, __VA_ARGS__)); } - -# define cr_assert_no_throw(...) CR_EXPAND(cr_assert_not_throw_(__VA_ARGS__, CR_SENTINEL)) -# define cr_assert_no_throw_(Statement, Exception, ...) \ - try { \ - Statement; \ - } catch (Exception &ex) { CR_EXPAND(cr_assert_impl(FATAL, 0, __VA_ARGS__)); } - -# define cr_expect_throw(...) CR_EXPAND(cr_expect_throw_(__VA_ARGS__, CR_SENTINEL)) -# define cr_expect_throw_(Statement, Exception, ...) \ - try { \ - Statement; \ - } catch (Exception &ex) { \ - } catch (...) { CR_EXPAND(cr_assert_impl(NORMAL, 0, __VA_ARGS__)); } - -# define cr_expect_no_throw(...) CR_EXPAND(cr_expect_not_throw_(__VA_ARGS__, CR_SENTINEL)) -# define cr_expect_no_throw_(Statement, Exception, ...) \ - try { \ - Statement; \ - } catch (Exception &ex) { CR_EXPAND(cr_assert_impl(NORMAL, 0, __VA_ARGS__)); } # endif // The section below is here for backward compatibility purposes. -// It shall be removed in the text major version of Criterion +// It shall be removed in the next major version of Criterion # ifndef CRITERION_NO_COMPAT # define CRITERION_ASSERT_DEPRECATED_(Name) CRITERION_ASSERT_DEPRECATED__( \ @@ -326,6 +431,13 @@ struct criterion_assert_args { "please use `cr_" #Name "` instead." \ ) +# define CRITERION_ASSERT_DEPRECATED_B(Name, Newname) \ + CRITERION_ASSERT_DEPRECATED__( \ + message \ + "The `" #Name "` macro is deprecated, " \ + "please use `" #Newname "` instead." \ + ) + # define CRITERION_ASSERT_DEPRECATED__(Msg) \ _Pragma(#Msg) @@ -339,6 +451,22 @@ struct criterion_assert_args { # 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__) +# define cr_assert_strings_neq(...) CRITERION_ASSERT_DEPRECATED_B(cr_assert_strings_neq, cr_assert_str_neq) cr_assert_str_neq(__VA_ARGS__) +# define cr_assert_strings_lt(...) CRITERION_ASSERT_DEPRECATED_B(cr_assert_strings_lt, cr_assert_str_lt) cr_assert_str_lt(__VA_ARGS__) +# define cr_assert_strings_leq(...) CRITERION_ASSERT_DEPRECATED_B(cr_assert_strings_leq, cr_assert_str_leq) cr_assert_str_leq(__VA_ARGS__) +# define cr_assert_strings_gt(...) CRITERION_ASSERT_DEPRECATED_B(cr_assert_strings_gt, cr_assert_str_gt) cr_assert_str_gt(__VA_ARGS__) +# define cr_assert_strings_geq(...) CRITERION_ASSERT_DEPRECATED_B(cr_assert_strings_geq, cr_assert_str_geq) cr_assert_str_geq(__VA_ARGS__) + +# define cr_assert_arrays_eq(...) CRITERION_ASSERT_DEPRECATED_B(cr_assert_arrays_eq, cr_assert_arr_eq) cr_assert_arr_eq(__VA_ARGS__) +# define cr_assert_arrays_neq(...) CRITERION_ASSERT_DEPRECATED_B(cr_assert_arrays_neq, cr_assert_arr_neq) cr_assert_arr_neq(__VA_ARGS__) + +# 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__) diff --git a/include/criterion/common.h b/include/criterion/common.h index 6d0910a7..ae962eb7 100644 --- a/include/criterion/common.h +++ b/include/criterion/common.h @@ -24,8 +24,6 @@ #ifndef CRITERION_COMMON_H_ # define CRITERION_COMMON_H_ -# define CR_EXPAND(x) x - # if defined(_MSC_VER) # if _MSC_VER < 1900 # error \ @@ -101,12 +99,15 @@ # ifdef __GNUC__ # define UNUSED CR_ATTRIBUTE(unused) # define NORETURN CR_ATTRIBUTE(noreturn) +# define CR_INLINE CR_ATTRIBUTE(always_inline) inline # elif CR_IS_MSVC # define UNUSED # define NORETURN __declspec(noreturn) +# define CR_INLINE __forceinline # else # define UNUSED # define NORETURN +# define CR_INLINE inline # endif # ifdef _WIN32 diff --git a/include/criterion/preprocess.h b/include/criterion/preprocess.h new file mode 100644 index 00000000..822e0e34 --- /dev/null +++ b/include/criterion/preprocess.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_PREPROCESS_H_ +# define CRITERION_PREPROCESS_H_ + +# define CR_NOOP do {} while(0) + +# ifdef __cplusplus +# define CR_NOTHROW throw() +# else +# define CR_NOTHROW +# endif + +# define CR_EXPAND(x) x + +# define CR_STR(x) CR_EXPAND(CR_STR_(x)) +# define CR_STR_(x) #x + +# define CR_VA_TAIL(...) CR_EXPAND(CR_VA_TAIL_HELPER(CR_VA_TAIL_SELECT(__VA_ARGS__), __VA_ARGS__)) + +# define CR_VA_TAIL_HELPER(N, ...) CR_EXPAND(CR_VA_TAIL_HELPER_(N, __VA_ARGS__)) +# define CR_VA_TAIL_HELPER_(N, ...) CR_EXPAND(CR_VA_TAIL_HELPER_##N(__VA_ARGS__)) +# define CR_VA_TAIL_HELPER_1(Head) +# define CR_VA_TAIL_HELPER_2(Head, ...) __VA_ARGS__ + +# define CR_VA_HEAD(...) CR_EXPAND(CR_VA_HEAD_HELPER(CR_VA_TAIL_SELECT(__VA_ARGS__), __VA_ARGS__)) + +# define CR_VA_HEAD_HELPER(N, ...) CR_EXPAND(CR_VA_HEAD_HELPER_(N, __VA_ARGS__)) +# define CR_VA_HEAD_HELPER_(N, ...) CR_EXPAND(CR_VA_HEAD_HELPER_##N(__VA_ARGS__)) +# define CR_VA_HEAD_HELPER_1(Head) Head +# define CR_VA_HEAD_HELPER_2(Head, ...) Head + +# define CR_VA_TAIL_SELECT(...) CR_EXPAND(CR_VA_TAIL_SELECT64(__VA_ARGS__, \ + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, \ + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, \ + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, \ + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, \ + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, \ + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, \ + 2, 2, 1, _)) + +# define CR_VA_TAIL_SELECT64( \ + _01, _02, _03, _04, _05, _06, _07, _08, _09, _10, \ + _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, \ + _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, \ + _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, \ + _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, \ + _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, \ + _61, _62, _63, X, ...) X + +#endif /* !CRITERION_PREPROCESS_H_ */ diff --git a/include/criterion/stats.h b/include/criterion/stats.h index a1d62ed0..8d6d4ca0 100644 --- a/include/criterion/stats.h +++ b/include/criterion/stats.h @@ -27,8 +27,6 @@ # include "types.h" struct criterion_assert_stats { - int kind; - const char *condition; const char *message; bool passed; unsigned line; diff --git a/samples/asserts.c b/samples/asserts.c index 0d9daab5..23189442 100644 --- a/samples/asserts.c +++ b/samples/asserts.c @@ -12,23 +12,21 @@ Test(asserts, base) { } Test(asserts, old_school) { - if (false) - cr_abort_test("You can abort the test with a message from anywhere"); - - cr_abort_test(NULL); // or without a message + cr_expect_fail("You can fail an assertion with a message from anywhere"); + cr_assert_fail(); // or without a message } Test(asserts, string) { - cr_assert_strings_eq("hello", "hello"); - cr_assert_strings_neq("hello", "olleh"); + cr_assert_str_eq("hello", "hello"); + cr_assert_str_neq("hello", "olleh"); - cr_assert_strings_gt("hello", "hell"); - cr_assert_strings_geq("hello", "hell"); - cr_assert_strings_geq("hello", "hello"); + cr_assert_str_gt("hello", "hell"); + cr_assert_str_geq("hello", "hell"); + cr_assert_str_geq("hello", "hello"); - cr_assert_strings_lt("hell", "hello"); - cr_assert_strings_leq("hell", "hello"); - cr_assert_strings_leq("hello", "hello"); + cr_assert_str_lt("hell", "hello"); + cr_assert_str_leq("hell", "hello"); + cr_assert_str_leq("hello", "hello"); } Test(asserts, native) { @@ -62,8 +60,8 @@ Test(asserts, array) { int arr1[] = {1, 2, 3, 4}; int arr2[] = {4, 3, 2, 1}; - cr_assert_arrays_eq(arr1, arr1, 4); - cr_assert_arrays_neq(arr1, arr2, 4); + cr_assert_arr_eq(arr1, arr1, 4); + cr_assert_arr_neq(arr1, arr2, 4); #ifdef __GNUC__ struct dummy_struct s1[] = {{4, 2}, {2, 4}}; @@ -74,7 +72,7 @@ Test(asserts, array) { s2[1].a = 2; s2[1].b = 4; - // cr_assert_arrays_eq(s1, s2, 2); not guaranteed to work on structs. - cr_assert_arrays_eq_cmp(s1, s2, 2, eq_dummy); + // cr_assert_arr_eq(s1, s2, 2); not guaranteed to work on structs. + cr_assert_arr_eq_cmp(s1, s2, 2, eq_dummy); #endif } diff --git a/samples/asserts.cc b/samples/asserts.cc index c7f5c8f0..98cd3941 100644 --- a/samples/asserts.cc +++ b/samples/asserts.cc @@ -14,23 +14,21 @@ Test(asserts, base) { } Test(asserts, old_school) { - if (false) - cr_abort_test("You can abort the test with a message from anywhere"); - - cr_abort_test(NULL); // or without a message + cr_expect_fail("You can fail an assertion with a message from anywhere"); + cr_assert_fail(); // or without a message } Test(asserts, string) { - cr_assert_strings_eq("hello", "hello"); - cr_assert_strings_neq("hello", "olleh"); + cr_assert_str_eq("hello", "hello"); + cr_assert_str_neq("hello", "olleh"); - cr_assert_strings_gt("hello", "hell"); - cr_assert_strings_geq("hello", "hell"); - cr_assert_strings_geq("hello", "hello"); + cr_assert_str_gt("hello", "hell"); + cr_assert_str_geq("hello", "hell"); + cr_assert_str_geq("hello", "hello"); - cr_assert_strings_lt("hell", "hello"); - cr_assert_strings_leq("hell", "hello"); - cr_assert_strings_leq("hello", "hello"); + cr_assert_str_lt("hell", "hello"); + cr_assert_str_leq("hell", "hello"); + cr_assert_str_leq("hello", "hello"); } Test(asserts, native) { @@ -64,8 +62,8 @@ Test(asserts, array) { int arr1[] = {1, 2, 3, 4}; int arr2[] = {4, 3, 2, 1}; - cr_assert_arrays_eq(arr1, arr1, 4); - cr_assert_arrays_neq(arr1, arr2, 4); + cr_assert_arr_eq(arr1, arr1, 4); + cr_assert_arr_neq(arr1, arr2, 4); #ifdef __GNUC__ struct dummy_struct s1[] = {{4, 2}, {2, 4}}; @@ -76,8 +74,8 @@ Test(asserts, array) { s2[1].a = 2; s2[1].b = 4; - // cr_assert_arrays_eq(s1, s2, 2); not guaranteed to work on structs. - cr_assert_arrays_eq_cmp(s1, s2, 2, eq_dummy); + // cr_assert_arrays_eq(&s1, &s2, 2); not guaranteed to work on structs. + cr_assert_arr_eq_cmp(&s1, &s2, 2, eq_dummy); #endif } diff --git a/samples/theories.c b/samples/theories.c index 6e96a6dd..0bbe7cc2 100644 --- a/samples/theories.c +++ b/samples/theories.c @@ -95,12 +95,12 @@ Theory((char c, bool b, short s, int i, long l, long long ll, float f, double d, cr_assert_eq(ll, 1); cr_assert_eq(f, 3.14f); cr_assert_eq(d, 3.14); - cr_assert_strings_eq(str, "test"); - cr_assert_strings_eq(cstr, "other test"); + 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_abort_test(NULL); + cr_assert_fail(); } // Manually generate datapoints @@ -117,5 +117,5 @@ static void generate_datapoints(void) { Theory((int i), theory, gen, .init = generate_datapoints) { (void) i; - cr_abort_test(NULL); // we fail to display the parameter + cr_assert_fail(); // we fail to display the parameter } diff --git a/samples/theories.cc b/samples/theories.cc index d0e3dd37..56027542 100644 --- a/samples/theories.cc +++ b/samples/theories.cc @@ -103,12 +103,12 @@ Theory((char c, bool b, short s, int i, long l, long long ll, float f, double d, cr_assert_eq(ll, 1); cr_assert_eq(f, 3.14f); cr_assert_eq(d, 3.14); - cr_assert_strings_eq(str, "test"); - cr_assert_strings_eq(cstr, "other test"); + 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_abort_test(NULL); + cr_assert_fail(); } // Manually generate datapoints @@ -125,5 +125,5 @@ static void generate_datapoints(void) { Theory((int i), theory, gen, .init = generate_datapoints) { (void) i; - cr_abort_test(NULL); // we fail to display the parameter + cr_assert_fail(); // we fail to display the parameter } diff --git a/src/asprintf.c b/src/asprintf.c new file mode 100644 index 00000000..2eada51e --- /dev/null +++ b/src/asprintf.c @@ -0,0 +1,62 @@ +/* + * 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 "criterion/asprintf-compat.h" + +int asprintf(char **strp, const char *fmt, ...) { + va_list ap; + va_start(ap, fmt); + int res = vasprintf(strp, fmt, ap); + va_end(ap); + return res; +} + +int vasprintf(char **strp, const char *fmt, va_list ap) { + va_list vl; + va_copy(vl, ap); + + int size = vsnprintf(0, 0, fmt, vl); + int res = -1; + + if (size < 0 || size >= INT_MAX) { + goto cleanup; + } + + char *str = malloc(size + 1); + if (str) { + int res2 = vsnprintf(str, size + 1, fmt, ap); + if (res2 < 0 || res2 > size) { + free(str); + goto cleanup; + } + *strp = str; + res = res2; + } + +cleanup: + va_end(vl); + return res; +} diff --git a/src/event.c b/src/event.c index 83a92e0d..ba91d730 100644 --- a/src/event.c +++ b/src/event.c @@ -37,6 +37,12 @@ void destroy_event(void *ptr, UNUSED void *meta) { free(ev->data); } +void destroy_assert_event(void *ptr, UNUSED void *meta) { + struct event *ev = ptr; + free((void*) ((struct criterion_assert_stats *) ev)->message); + free(ev->data); +} + struct event *read_event(FILE *f) { unsigned kind; if (fread(&kind, sizeof (unsigned), 1, f) == 0) @@ -45,18 +51,36 @@ struct event *read_event(FILE *f) { switch (kind) { case ASSERT: { const size_t assert_size = sizeof (struct criterion_assert_stats); - unsigned char *buf = malloc(assert_size); - if (fread(buf, assert_size, 1, f) == 0) { - free(buf); - return NULL; - } + struct criterion_assert_stats *buf = NULL; + size_t *len = NULL; + char *msg = NULL; + + buf = malloc(assert_size); + if (fread(buf, assert_size, 1, f) == 0) + goto fail_assert; + + len = malloc(sizeof (size_t)); + if (fread(len, sizeof (size_t), 1, f) == 0) + goto fail_assert; + + msg = malloc(*len); + if (fread(buf, *len, 1, f) == 0) + goto fail_assert; + + buf->message = msg; struct event *ev = smalloc( .size = sizeof (struct event), - .dtor = destroy_event + .dtor = destroy_assert_event ); *ev = (struct event) { .kind = kind, .data = buf }; return ev; + +fail_assert: + free(len); + free(buf); + free(msg); + return NULL; } case THEORY_FAIL: { size_t *len = malloc(sizeof (size_t)); diff --git a/src/log/normal.c b/src/log/normal.c index 9f278cfc..dedcd5e7 100644 --- a/src/log/normal.c +++ b/src/log/normal.c @@ -160,8 +160,7 @@ 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 - : stats->condition); + char *dup = strdup(*stats->message ? stats->message : ""); #ifdef VANILLA_WIN32 char *line = strtok(dup, "\n"); diff --git a/src/log/tap.c b/src/log/tap.c index c58d0fd0..76937a0e 100644 --- a/src/log/tap.c +++ b/src/log/tap.c @@ -86,7 +86,7 @@ void tap_log_post_test(struct criterion_test_stats *stats) { stats->elapsed_time); for (struct criterion_assert_stats *asrt = stats->asserts; asrt; asrt = asrt->next) { if (!asrt->passed) { - char *dup = strdup(*asrt->message ? asrt->message : asrt->condition); + char *dup = strdup(*asrt->message ? asrt->message : ""); #ifdef VANILLA_WIN32 char *line = strtok(dup, "\n"); #else From 01831b2ed58bf1e87fa34186fd7a0e44b8725550 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Tue, 8 Sep 2015 19:21:53 +0200 Subject: [PATCH 113/174] Fixed crashes introduced by the API change --- include/criterion/assert.h | 8 ++++---- src/event.c | 24 +++++++++--------------- 2 files changed, 13 insertions(+), 19 deletions(-) diff --git a/include/criterion/assert.h b/include/criterion/assert.h index 4aeaa9b9..092f7a1d 100644 --- a/include/criterion/assert.h +++ b/include/criterion/assert.h @@ -68,9 +68,10 @@ struct criterion_assert_args { const char *default_msg = "" CR_VA_HEAD(__VA_ARGS__); \ char *formatted_msg = NULL; \ int msglen = asprintf(&formatted_msg, "" CR_VA_TAIL(__VA_ARGS__)); \ - MsgVar = formatted_msg ? formatted_msg : default_msg; \ + MsgVar = formatted_msg && *formatted_msg ? \ + formatted_msg : default_msg; \ \ - if (!formatted_msg) \ + if (!formatted_msg || !*formatted_msg) \ msglen = strlen(default_msg); \ \ BufSize = sizeof(struct criterion_assert_stats) \ @@ -78,10 +79,9 @@ struct criterion_assert_args { \ 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; \ + *((size_t*) buf) = msglen + 1; \ buf += sizeof (size_t); \ CR_STDN strcpy(buf, MsgVar); \ CR_STDN free(formatted_msg); \ diff --git a/src/event.c b/src/event.c index ba91d730..abb85a6c 100644 --- a/src/event.c +++ b/src/event.c @@ -39,7 +39,7 @@ void destroy_event(void *ptr, UNUSED void *meta) { void destroy_assert_event(void *ptr, UNUSED void *meta) { struct event *ev = ptr; - free((void*) ((struct criterion_assert_stats *) ev)->message); + free((void*) ((struct criterion_assert_stats *) ev->data)->message); free(ev->data); } @@ -52,19 +52,18 @@ struct event *read_event(FILE *f) { case ASSERT: { const size_t assert_size = sizeof (struct criterion_assert_stats); struct criterion_assert_stats *buf = NULL; - size_t *len = NULL; char *msg = NULL; buf = malloc(assert_size); if (fread(buf, assert_size, 1, f) == 0) goto fail_assert; - len = malloc(sizeof (size_t)); - if (fread(len, sizeof (size_t), 1, f) == 0) + size_t len = 0; + if (fread(&len, sizeof (size_t), 1, f) == 0) goto fail_assert; - msg = malloc(*len); - if (fread(buf, *len, 1, f) == 0) + msg = malloc(len); + if (fread(msg, len, 1, f) == 0) goto fail_assert; buf->message = msg; @@ -77,25 +76,20 @@ struct event *read_event(FILE *f) { return ev; fail_assert: - free(len); free(buf); free(msg); return NULL; } case THEORY_FAIL: { - size_t *len = malloc(sizeof (size_t)); - if (fread(len, sizeof (size_t), 1, f) == 0) { - free(len); + size_t len = 0; + if (fread(&len, sizeof (size_t), 1, f) == 0) return NULL; - } - char *buf = malloc(*len); - if (fread(buf, *len, 1, f) == 0) { - free(len); + char *buf = malloc(len); + if (fread(buf, len, 1, f) == 0) { free(buf); return NULL; } - free(len); struct event *ev = smalloc( .size = sizeof (struct event), From ae429f9bd2a9bde4d2ebfde17d85fd8fbb862fc8 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Tue, 8 Sep 2015 19:22:28 +0200 Subject: [PATCH 114/174] Fixed comparison tests to reflect the API change --- samples/asserts.c.bin.err.expected | 3 ++- samples/asserts.cc.bin.err.expected | 9 ++++++--- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/samples/asserts.c.bin.err.expected b/samples/asserts.c.bin.err.expected index 0f81d723..5ee803cc 100644 --- a/samples/asserts.c.bin.err.expected +++ b/samples/asserts.c.bin.err.expected @@ -1,6 +1,7 @@ [----] asserts.c:9: Assertion failed: assert is fatal, expect isn't [----] asserts.c:10: Assertion failed: This assert runs [FAIL] asserts::base: (0.00s) -[----] asserts.c:18: Assertion failed: The conditions for this test were not met. +[----] asserts.c:15: Assertion failed: You can fail an assertion with a message from anywhere +[----] asserts.c:16: Assertion failed: The condition for this assertion were not met. [FAIL] asserts::old_school: (0.00s) [====] Synthesis: Tested: 6 | Passing: 4 | Failing: 2 | Crashing: 0  diff --git a/samples/asserts.cc.bin.err.expected b/samples/asserts.cc.bin.err.expected index 8b27dddf..d18db61d 100644 --- a/samples/asserts.cc.bin.err.expected +++ b/samples/asserts.cc.bin.err.expected @@ -1,8 +1,11 @@ +[----] asserts.cc:78: Assertion failed: (&s1)[0 .. 2] == (&s2)[0 .. 2] +[FAIL] asserts::array: (0.00s) [----] asserts.cc:11: Assertion failed: assert is fatal, expect isn't [----] asserts.cc:12: Assertion failed: This assert runs [FAIL] asserts::base: (0.00s) -[----] asserts.cc:86: Assertion failed: 0 +[----] asserts.cc:84: Assertion failed: The condition for this assertion were not met. [FAIL] asserts::exception: (0.00s) -[----] asserts.cc:20: Assertion failed: The conditions for this test were not met. +[----] asserts.cc:17: Assertion failed: You can fail an assertion with a message from anywhere +[----] asserts.cc:18: Assertion failed: The condition for this assertion were not met. [FAIL] asserts::old_school: (0.00s) -[====] Synthesis: Tested: 7 | Passing: 4 | Failing: 3 | Crashing: 0  +[====] Synthesis: Tested: 7 | Passing: 3 | Failing: 4 | Crashing: 0  From 9c58e8d1e13d4a26dc75b8ca5ea46ba87b5e6a42 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Tue, 8 Sep 2015 20:25:22 +0200 Subject: [PATCH 115/174] Added empty string assertions --- include/criterion/assert.h | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/include/criterion/assert.h b/include/criterion/assert.h index 092f7a1d..ab577677 100644 --- a/include/criterion/assert.h +++ b/include/criterion/assert.h @@ -231,6 +231,29 @@ struct criterion_assert_args { // String assertions +# define cr_assert_str_op_empty_(Fail, Op, Value, ...) \ + CR_EXPAND(cr_assert_impl( \ + Fail, \ + (Value)[0] Op '\0', \ + dummy, \ + CR_STR(Value is empty.), \ + __VA_ARGS__ \ + )) + +# define cr_assert_str_op_empty_va_(Fail, Op, ...) \ + CR_EXPAND(cr_assert_str_op_empty_( \ + Fail, \ + Op, \ + 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_, ==, __VA_ARGS__)) +# define cr_expect_str_empty(...) CR_EXPAND(cr_assert_str_op_empty_va_(CR_FAIL_ABORT_, ==, __VA_ARGS__)) + +# define cr_assert_str_not_empty(...) CR_EXPAND(cr_assert_str_op_empty_va_(CR_FAIL_ABORT_, !=, __VA_ARGS__)) +# define cr_expect_str_not_empty(...) CR_EXPAND(cr_assert_str_op_empty_va_(CR_FAIL_ABORT_, !=, __VA_ARGS__)) + # define cr_assert_str_op_(Fail, Op, Actual, Expected, ...) \ CR_EXPAND(cr_assert_impl( \ Fail, \ From 9969604915321e1d1adcb6af30694a8bb047d7e1 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Tue, 8 Sep 2015 20:33:42 +0200 Subject: [PATCH 116/174] Moved the pipe definition out of the API, and use the system asprintf declaration when available --- include/criterion/asprintf-compat.h | 12 +++++++++++- include/criterion/event.h | 4 ---- src/event.h | 3 +++ src/theories.c | 1 + 4 files changed, 15 insertions(+), 5 deletions(-) diff --git a/include/criterion/asprintf-compat.h b/include/criterion/asprintf-compat.h index 2fc5c1bf..35997baa 100644 --- a/include/criterion/asprintf-compat.h +++ b/include/criterion/asprintf-compat.h @@ -24,13 +24,21 @@ #ifndef CRITERION_ASPRINTF_COMPAT_H_ # define CRITERION_ASPRINTF_COMPAT_H_ +# ifdef __UNIX__ +# define _GNU_SOURCE 1 +# endif + # ifdef __cplusplus # include # else # include # endif -# include "common.h" +# ifdef __UNIX__ +# include +# else + +# include "common.h" CR_BEGIN_C_API @@ -40,4 +48,6 @@ CR_API int vasprintf(char **strp, const char *fmt, va_list ap) CR_NOTHROW; CR_END_C_API +# endif + #endif /* !CRITERION_ASPRINTF_COMPAT_H_ */ diff --git a/include/criterion/event.h b/include/criterion/event.h index 37881db3..51389018 100644 --- a/include/criterion/event.h +++ b/include/criterion/event.h @@ -26,17 +26,13 @@ # ifdef __cplusplus # include -# include # else # include -# include # endif # include "common.h" CR_BEGIN_C_API -extern FILE *g_event_pipe; - CR_API void send_event(int kind, void *data, size_t size); CR_END_C_API diff --git a/src/event.h b/src/event.h index fc8ce4fb..21d9b210 100644 --- a/src/event.h +++ b/src/event.h @@ -25,6 +25,9 @@ # define EVENT_H_ # include "criterion/event.h" +# include + +extern FILE *g_event_pipe; struct event { int kind; diff --git a/src/theories.c b/src/theories.c index 3bf0f5b6..9e440ff5 100644 --- a/src/theories.c +++ b/src/theories.c @@ -23,6 +23,7 @@ */ #include #include +#include #include #include #include From 29860d46be3fc06220bb29879dc12ef18df285b4 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Tue, 8 Sep 2015 20:48:30 +0200 Subject: [PATCH 117/174] Made criterion_continue_test static --- include/criterion/abort.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/criterion/abort.h b/include/criterion/abort.h index ca981b51..026289f2 100644 --- a/include/criterion/abort.h +++ b/include/criterion/abort.h @@ -29,7 +29,7 @@ CR_BEGIN_C_API CR_API NORETURN void criterion_abort_test(void); -CR_API CR_INLINE void criterion_continue_test(void) {} +CR_INLINE static void criterion_continue_test(void) {} CR_END_C_API From 5247808140360bc76b00445d9cf490bca981aa64 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Tue, 8 Sep 2015 22:12:22 +0200 Subject: [PATCH 118/174] Renamed asprintf to cr_asprintf for compatibility --- CMakeLists.txt | 7 +------ include/criterion/asprintf-compat.h | 16 +++------------- include/criterion/assert.h | 2 +- src/asprintf.c | 7 ++++--- 4 files changed, 9 insertions(+), 23 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 2038e171..37e02d36 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -98,6 +98,7 @@ set(SOURCE_FILES src/ordered-set.c src/posix-compat.c src/theories.c + src/asprintf.c src/main.c src/entry.c ) @@ -110,12 +111,6 @@ if (PCRE_FOUND) set(HAVE_PCRE 1) endif () -if ("${CMAKE_SYSTEM_NAME}" EQUAL "Linux") - set (SOURCE_FILES ${SOURCE_FILES} - src/asprintf.c - ) -endif () - set(INTERFACE_FILES include/criterion/assert.h include/criterion/abort.h diff --git a/include/criterion/asprintf-compat.h b/include/criterion/asprintf-compat.h index 35997baa..6f78efdd 100644 --- a/include/criterion/asprintf-compat.h +++ b/include/criterion/asprintf-compat.h @@ -24,30 +24,20 @@ #ifndef CRITERION_ASPRINTF_COMPAT_H_ # define CRITERION_ASPRINTF_COMPAT_H_ -# ifdef __UNIX__ -# define _GNU_SOURCE 1 -# endif - # ifdef __cplusplus # include # else # include # endif -# ifdef __UNIX__ -# include -# else - -# include "common.h" +# include "common.h" CR_BEGIN_C_API FORMAT(printf, 2, 3) -CR_API int asprintf(char **strp, const char *fmt, ...) CR_NOTHROW; -CR_API int vasprintf(char **strp, const char *fmt, va_list ap) CR_NOTHROW; +CR_API int cr_asprintf(char **strp, const char *fmt, ...); +CR_API int cr_vasprintf(char **strp, const char *fmt, va_list ap); CR_END_C_API -# endif - #endif /* !CRITERION_ASPRINTF_COMPAT_H_ */ diff --git a/include/criterion/assert.h b/include/criterion/assert.h index ab577677..8c28e304 100644 --- a/include/criterion/assert.h +++ b/include/criterion/assert.h @@ -67,7 +67,7 @@ struct criterion_assert_args { do { \ const char *default_msg = "" CR_VA_HEAD(__VA_ARGS__); \ char *formatted_msg = NULL; \ - int msglen = asprintf(&formatted_msg, "" CR_VA_TAIL(__VA_ARGS__)); \ + int msglen = cr_asprintf(&formatted_msg, "" CR_VA_TAIL(__VA_ARGS__));\ MsgVar = formatted_msg && *formatted_msg ? \ formatted_msg : default_msg; \ \ diff --git a/src/asprintf.c b/src/asprintf.c index 2eada51e..c2a4a126 100644 --- a/src/asprintf.c +++ b/src/asprintf.c @@ -24,17 +24,18 @@ #include #include +#include #include "criterion/asprintf-compat.h" -int asprintf(char **strp, const char *fmt, ...) { +int cr_asprintf(char **strp, const char *fmt, ...) { va_list ap; va_start(ap, fmt); - int res = vasprintf(strp, fmt, ap); + int res = cr_vasprintf(strp, fmt, ap); va_end(ap); return res; } -int vasprintf(char **strp, const char *fmt, va_list ap) { +int cr_vasprintf(char **strp, const char *fmt, va_list ap) { va_list vl; va_copy(vl, ap); From 3ba88bb314f6ba4824388917c3870ef9aa02e5b8 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Tue, 8 Sep 2015 22:41:50 +0200 Subject: [PATCH 119/174] Extracted GCC-specific pragma from the assert macro --- include/criterion/assert.h | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/include/criterion/assert.h b/include/criterion/assert.h index 8c28e304..82216e86 100644 --- a/include/criterion/assert.h +++ b/include/criterion/assert.h @@ -90,6 +90,12 @@ struct criterion_assert_args { # 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); \ @@ -97,7 +103,6 @@ struct criterion_assert_args { const char *msg = NULL; \ size_t bufsize; \ \ - _Pragma("GCC diagnostic ignored \"-Wformat-zero-length\"") \ struct criterion_assert_stats *stat; \ CR_EXPAND(CR_INIT_STATS_(bufsize, msg, CR_VA_TAIL(__VA_ARGS__))); \ stat->passed = passed; \ From 8628b5fbea4363d280870fc74616f052f4eda156 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Tue, 8 Sep 2015 22:48:06 +0200 Subject: [PATCH 120/174] Removed unused exception variable name from throw assersions --- include/criterion/assert.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/criterion/assert.h b/include/criterion/assert.h index 82216e86..97e5648b 100644 --- a/include/criterion/assert.h +++ b/include/criterion/assert.h @@ -415,7 +415,7 @@ struct criterion_assert_args { # define cr_assert_throw_(Fail, Statement, Exception, ...) \ try { \ Statement; \ - } catch (Exception &ex) { \ + } catch (Exception const &) { \ } catch (...) { CR_EXPAND(cr_fail(Fail, CR_VA_TAIL(__VA_ARGS__))); } # define cr_assert_throw_va_(...) \ @@ -433,7 +433,7 @@ struct criterion_assert_args { # define cr_assert_no_throw_(Fail, Statement, Exception, ...) \ try { \ Statement; \ - } catch (Exception &ex) { CR_EXPAND(cr_fail(Fail, CR_VA_TAIL(__VA_ARGS__))); } + } catch (Exception const &) { CR_EXPAND(cr_fail(Fail, CR_VA_TAIL(__VA_ARGS__))); } # define cr_assert_no_throw_va_(...) \ CR_EXPAND(cr_assert_no_throw_( \ From d1fce372a49a6fb4a3fc89a9cdd3ab95674bab18 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Tue, 8 Sep 2015 23:07:45 +0200 Subject: [PATCH 121/174] Reformatted criterion/assert.h --- include/criterion/assert.h | 255 +++++++++++++++++++------------------ 1 file changed, 133 insertions(+), 122 deletions(-) diff --git a/include/criterion/assert.h b/include/criterion/assert.h index 97e5648b..d3ebbffc 100644 --- a/include/criterion/assert.h +++ b/include/criterion/assert.h @@ -63,28 +63,28 @@ struct criterion_assert_args { # define CR_STDN # endif -# define CR_INIT_STATS_(BufSize, MsgVar, ...) CR_EXPAND( \ - do { \ - const char *default_msg = "" CR_VA_HEAD(__VA_ARGS__); \ - char *formatted_msg = NULL; \ - int msglen = cr_asprintf(&formatted_msg, "" CR_VA_TAIL(__VA_ARGS__));\ - MsgVar = formatted_msg && *formatted_msg ? \ - formatted_msg : default_msg; \ - \ - if (!formatted_msg || !*formatted_msg) \ - msglen = strlen(default_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(formatted_msg); \ +# define CR_INIT_STATS_(BufSize, MsgVar, ...) CR_EXPAND( \ + do { \ + const char *default_msg = "" CR_VA_HEAD(__VA_ARGS__); \ + char *formatted_msg = NULL; \ + int msglen = cr_asprintf(&formatted_msg, "" CR_VA_TAIL(__VA_ARGS__)); \ + MsgVar = formatted_msg && *formatted_msg ? \ + formatted_msg : default_msg; \ + \ + if (!formatted_msg || !*formatted_msg) \ + msglen = strlen(default_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(formatted_msg); \ } while (0)) # define CR_FAIL_ABORT_ criterion_abort_test @@ -130,50 +130,61 @@ struct criterion_assert_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, \ - 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, \ - 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, \ - 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, \ - CR_STR(!(CR_VA_HEAD(__VA_ARGS__))), \ - CR_VA_TAIL(__VA_ARGS__))) +# define cr_assert(...) \ + CR_EXPAND(cr_assert_impl( \ + CR_FAIL_ABORT_, \ + CR_VA_HEAD(__VA_ARGS__), \ + dummy, \ + 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, \ + 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, \ + 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, \ + 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, \ - 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_op_(Fail, Op, Actual, Expected, ...) \ + CR_EXPAND(cr_assert_impl( \ + Fail, \ + (Actual) Op (Expected), \ + dummy, \ + 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__)) @@ -209,23 +220,23 @@ struct criterion_assert_args { # 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, \ - CR_STR(Op(Actual, Expected, Epsilon)), \ - __VA_ARGS__ \ +# define cr_assert_float_op_(Fail, Op, Actual, Expected, Epsilon, ...) \ + CR_EXPAND(cr_assert_impl( \ + Fail, \ + Op(Actual, Expected, Epsilon), \ + dummy, \ + 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_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__)) @@ -236,21 +247,21 @@ struct criterion_assert_args { // String assertions -# define cr_assert_str_op_empty_(Fail, Op, Value, ...) \ - CR_EXPAND(cr_assert_impl( \ - Fail, \ - (Value)[0] Op '\0', \ - dummy, \ - CR_STR(Value is empty.), \ - __VA_ARGS__ \ +# define cr_assert_str_op_empty_(Fail, Op, Value, ...) \ + CR_EXPAND(cr_assert_impl( \ + Fail, \ + (Value)[0] Op '\0', \ + dummy, \ + CR_STR(Value is empty.), \ + __VA_ARGS__ \ )) -# define cr_assert_str_op_empty_va_(Fail, Op, ...) \ - CR_EXPAND(cr_assert_str_op_empty_( \ - Fail, \ - Op, \ - CR_VA_HEAD(__VA_ARGS__), \ - CR_VA_TAIL(__VA_ARGS__) \ +# define cr_assert_str_op_empty_va_(Fail, Op, ...) \ + CR_EXPAND(cr_assert_str_op_empty_( \ + Fail, \ + Op, \ + 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_, ==, __VA_ARGS__)) @@ -260,21 +271,21 @@ struct criterion_assert_args { # define cr_expect_str_not_empty(...) CR_EXPAND(cr_assert_str_op_empty_va_(CR_FAIL_ABORT_, !=, __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, \ - CR_STR((as strings) (Actual) Op (Expected)), \ - __VA_ARGS__ \ + CR_EXPAND(cr_assert_impl( \ + Fail, \ + CR_STDN strcmp((Actual), (Expected)) Op 0, \ + dummy, \ + CR_STR((as strings) (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_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__)) @@ -300,20 +311,20 @@ struct criterion_assert_args { # define cr_assert_mem_op_(Fail, Op, Actual, Expected, Size, ...) \ CR_EXPAND(cr_assert_impl( \ Fail, \ - CR_STDN memcmp((Actual), (Expected), (Size)) Op 0, \ + CR_STDN memcmp((Actual), (Expected), (Size)) Op 0, \ dummy, \ 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_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__)) @@ -351,15 +362,15 @@ struct criterion_assert_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_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__)) From 565ed9a6722ed06e1b49718b8e54ff4e25fa454e Mon Sep 17 00:00:00 2001 From: Snaipe Date: Tue, 8 Sep 2015 23:08:27 +0200 Subject: [PATCH 122/174] Made the deprecation message work with MSVC --- include/criterion/assert.h | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/include/criterion/assert.h b/include/criterion/assert.h index d3ebbffc..4deab347 100644 --- a/include/criterion/assert.h +++ b/include/criterion/assert.h @@ -464,21 +464,26 @@ struct criterion_assert_args { // 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_(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 \ - "The `" #Name "` macro is deprecated, " \ - "please use `" #Newname "` instead." \ + ("The `" #Name "` macro is deprecated, " \ + "please use `" #Newname "` instead.") \ ) +# ifdef _MSC_VER +# define CRITERION_ASSERT_DEPRECATED__(Msg) \ + __pragma(Msg) +# else # define CRITERION_ASSERT_DEPRECATED__(Msg) \ _Pragma(#Msg) +# endif # ifndef assert # define assert(...) CRITERION_ASSERT_DEPRECATED_(assert) cr_assert(__VA_ARGS__) From 8ac4911f19573683d3ae731d4baa09d549830125 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Tue, 8 Sep 2015 23:49:35 +0200 Subject: [PATCH 123/174] Added assertion reference in documentation --- doc/assert.rst | 96 +++++++++++++++++++++++++++++++++++++++++++++++++ doc/index.rst | 1 + doc/starter.rst | 41 ++------------------- 3 files changed, 99 insertions(+), 39 deletions(-) create mode 100644 doc/assert.rst diff --git a/doc/assert.rst b/doc/assert.rst new file mode 100644 index 00000000..720bcaf2 --- /dev/null +++ b/doc/assert.rst @@ -0,0 +1,96 @@ +.. _assertions-ref: + +Assertion reference +=================== + +This is an exhaustive list of all assertion macros that Criterion provides. + +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. + +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 +======================================================================= =========================================================================== =========================================== + +String Assertions +----------------- + +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``. +=========================================================== =================================================================== =========================================== + +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 +=========================================================================== =========================================================================== =========================================== + diff --git a/doc/index.rst b/doc/index.rst index e9d55c52..56fbdf45 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -7,6 +7,7 @@ Criterion intro setup starter + assert hooks env theories diff --git a/doc/starter.rst b/doc/starter.rst index 6a9408ee..4e329122 100644 --- a/doc/starter.rst +++ b/doc/starter.rst @@ -48,45 +48,8 @@ parameter, and an optional failure message: cr_assert(strlen("") == 0); } -On top of those, more assertions are available for common operations: - -* ``cr_assert_null(Ptr, [Message])``: passes if Ptr is NULL. -* ``cr_assert_eq(Actual, Expected, [Message])``: passes if Actual == Expected. -* ``cr_assert_lt(Actual, Expected, [Message])``: passes if Actual < Expected. -* ``cr_assert_leq(Actual, Expected, [Message])``: passes if Actual <= Expected. -* ``cr_assert_gt(Actual, Expected, [Message])``: passes if Actual > Expected. -* ``cr_assert_geq(Actual, Expected, [Message])``: passes if Actual >= Expected. -* ``cr_assert_float_eq(Actual, Expected, Epsilon, [Message])``: - passes if Actual == Expected with an error of Epsilon. -* ``cr_assert_arrays_eq(Actual, Expected, Size, [Message])``: - passes if all elements of Actual (from 0 to Size - 1) are equals to those - of Expected. -* ``cr_assert_arrays_eq_cmp(Actual, Expected, Size, Cmp, [Message])``: - Same as ``arrays_eq`` but equality is defined by the result of the binary - Cmp function. - -Equality and lexical comparison assertions are also available for strings: - -* ``cr_assert_strings_eq(Actual, Expected, [Message])`` -* ``cr_assert_strings_lt(Actual, Expected, [Message])`` -* ``cr_assert_strings_leq(Actual, Expected, [Message])`` -* ``cr_assert_strings_gt(Actual, Expected, [Message])`` -* ``cr_assert_strings_geq(Actual, Expected, [Message])`` - -And some assertions have a logical negative counterpart: - -* ``cr_assert_not(Condition, [Message])`` -* ``cr_assert_not_null(Ptr, [Message])`` -* ``cr_assert_neq(Actual, Unexpected, [Message])`` -* ``cr_assert_float_neq(Actual, Unexpected, Epsilon, [Message])`` -* ``cr_assert_strings_neq(Actual, Unexpected, [Message])`` -* ``cr_assert_arrays_neq(Actual, Unexpected, Size, [Message])`` -* ``cr_assert_arrays_neq_cmp(Actual, Unexpected, Size, Cmp, [Message])`` - -Of course, every ``assert`` has an ``expect`` counterpart. - -Please note that ``arrays_(n)eq`` assertions should not be used on padded -structures -- please use ``arrays_(n)eq_cmp`` instead. +On top of those, more assertions are available for common operations. See +:ref:`assertions-ref` for a complete list. Configuring tests ----------------- From a8ecd27427740ccef9c2419d4f314b3e39dd8262 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Tue, 8 Sep 2015 23:55:11 +0200 Subject: [PATCH 124/174] Updated asserts sample --- samples/asserts.c | 5 +++++ samples/asserts.c.bin.err.expected | 8 ++++---- samples/asserts.cc | 5 +++++ samples/asserts.cc.bin.err.expected | 12 ++++++------ 4 files changed, 20 insertions(+), 10 deletions(-) diff --git a/samples/asserts.c b/samples/asserts.c index 23189442..1d5d83e3 100644 --- a/samples/asserts.c +++ b/samples/asserts.c @@ -6,6 +6,8 @@ Test(asserts, base) { cr_assert(true, "Assertions may take failure messages"); + cr_assert(true, "Or even %d format string %s", 1, "with parameters"); + cr_expect(false, "assert is fatal, expect isn't"); cr_assert(false, "This assert runs"); cr_assert(false, "This does not"); @@ -17,6 +19,9 @@ Test(asserts, old_school) { } Test(asserts, string) { + cr_assert_str_empty(""); + cr_assert_str_not_empty("foo"); + cr_assert_str_eq("hello", "hello"); cr_assert_str_neq("hello", "olleh"); diff --git a/samples/asserts.c.bin.err.expected b/samples/asserts.c.bin.err.expected index 5ee803cc..2488aa8d 100644 --- a/samples/asserts.c.bin.err.expected +++ b/samples/asserts.c.bin.err.expected @@ -1,7 +1,7 @@ -[----] asserts.c:9: Assertion failed: assert is fatal, expect isn't -[----] asserts.c:10: Assertion failed: This assert runs +[----] asserts.c:11: Assertion failed: assert is fatal, expect isn't +[----] asserts.c:12: Assertion failed: This assert runs [FAIL] asserts::base: (0.00s) -[----] asserts.c:15: Assertion failed: You can fail an assertion with a message from anywhere -[----] asserts.c:16: Assertion failed: The condition for this assertion were not met. +[----] asserts.c:17: Assertion failed: You can fail an assertion with a message from anywhere +[----] asserts.c:18: Assertion failed: The condition for this assertion were not met. [FAIL] asserts::old_school: (0.00s) [====] Synthesis: Tested: 6 | Passing: 4 | Failing: 2 | Crashing: 0  diff --git a/samples/asserts.cc b/samples/asserts.cc index 98cd3941..46c22afe 100644 --- a/samples/asserts.cc +++ b/samples/asserts.cc @@ -8,6 +8,8 @@ Test(asserts, base) { cr_assert(true, "Assertions may take failure messages"); + cr_assert(true, "Or even %d format string %s", 1, "with parameters"); + cr_expect(false, "assert is fatal, expect isn't"); cr_assert(false, "This assert runs"); cr_assert(false, "This does not"); @@ -19,6 +21,9 @@ Test(asserts, old_school) { } Test(asserts, string) { + cr_assert_str_empty(""); + cr_assert_str_not_empty("foo"); + cr_assert_str_eq("hello", "hello"); cr_assert_str_neq("hello", "olleh"); diff --git a/samples/asserts.cc.bin.err.expected b/samples/asserts.cc.bin.err.expected index d18db61d..3ef16473 100644 --- a/samples/asserts.cc.bin.err.expected +++ b/samples/asserts.cc.bin.err.expected @@ -1,11 +1,11 @@ -[----] asserts.cc:78: Assertion failed: (&s1)[0 .. 2] == (&s2)[0 .. 2] +[----] asserts.cc:83: Assertion failed: (&s1)[0 .. 2] == (&s2)[0 .. 2] [FAIL] asserts::array: (0.00s) -[----] asserts.cc:11: Assertion failed: assert is fatal, expect isn't -[----] asserts.cc:12: Assertion failed: This assert runs +[----] asserts.cc:13: Assertion failed: assert is fatal, expect isn't +[----] asserts.cc:14: Assertion failed: This assert runs [FAIL] asserts::base: (0.00s) -[----] asserts.cc:84: Assertion failed: The condition for this assertion were not met. +[----] asserts.cc:89: Assertion failed: The condition for this assertion were not met. [FAIL] asserts::exception: (0.00s) -[----] asserts.cc:17: Assertion failed: You can fail an assertion with a message from anywhere -[----] asserts.cc:18: Assertion failed: The condition for this assertion were not met. +[----] asserts.cc:19: Assertion failed: You can fail an assertion with a message from anywhere +[----] asserts.cc:20: Assertion failed: The condition for this assertion were not met. [FAIL] asserts::old_school: (0.00s) [====] Synthesis: Tested: 7 | Passing: 3 | Failing: 4 | Crashing: 0  From d6ef9f61ad89ee74f09a1bdf4a3caaf3e4933090 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Wed, 9 Sep 2015 01:25:26 +0200 Subject: [PATCH 125/174] Improved assert messages --- include/criterion/assert.h | 182 ++++++++++++++---------- samples/asserts.c.bin.err.expected | 2 +- samples/asserts.cc.bin.err.expected | 6 +- samples/description.c.bin.err.expected | 2 +- samples/description.cc.bin.err.expected | 2 +- samples/report.c.bin.err.expected | 2 +- samples/report.cc.bin.err.expected | 2 +- samples/simple.c.bin.err.expected | 2 +- samples/simple.cc.bin.err.expected | 2 +- 9 files changed, 113 insertions(+), 89 deletions(-) diff --git a/include/criterion/assert.h b/include/criterion/assert.h index 4deab347..9a42e55c 100644 --- a/include/criterion/assert.h +++ b/include/criterion/assert.h @@ -123,67 +123,67 @@ struct criterion_assert_args { Fail, \ 0, \ dummy, \ - "The condition for this assertion were not met.", \ + "The conditions for this assertion were not met.", \ __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, \ - CR_STR(CR_VA_HEAD(__VA_ARGS__)), \ - CR_VA_TAIL(__VA_ARGS__) \ +# define cr_assert(...) \ + CR_EXPAND(cr_assert_impl( \ + CR_FAIL_ABORT_, \ + CR_VA_HEAD(__VA_ARGS__), \ + dummy, \ + "The expression " CR_STR(CR_VA_HEAD(__VA_ARGS__)) " is false.", \ + CR_VA_TAIL(__VA_ARGS__) \ )) -# define cr_expect(...) \ - CR_EXPAND(cr_assert_impl( \ - CR_FAIL_CONTINUES_, \ - CR_VA_HEAD(__VA_ARGS__), \ - dummy, \ - 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, \ + "The expression " CR_STR(CR_VA_HEAD(__VA_ARGS__)) " is false.", \ + CR_VA_TAIL(__VA_ARGS__) \ )) -# define cr_assert_not(...) \ - CR_EXPAND(cr_assert_impl( \ - CR_FAIL_ABORT_, \ - !(CR_VA_HEAD(__VA_ARGS__)), \ - dummy, \ - 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, \ + "The expression " CR_STR(!(CR_VA_HEAD(__VA_ARGS__))) " is false.", \ + CR_VA_TAIL(__VA_ARGS__) \ )) -# define cr_expect_not(...) \ - CR_EXPAND(cr_assert_impl( \ - CR_FAIL_CONTINUES_, \ - !(CR_VA_HEAD(__VA_ARGS__)), \ - dummy, \ - 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, \ + "The expression " CR_STR(!(CR_VA_HEAD(__VA_ARGS__))) " is false.", \ + 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, \ - CR_STR((Actual) Op (Expected)), \ - __VA_ARGS__ \ +# define cr_assert_op_(Fail, Op, Actual, Expected, ...) \ + CR_EXPAND(cr_assert_impl( \ + Fail, \ + (Actual) Op (Expected), \ + dummy, \ + "The expression " CR_STR((Actual) Op (Expected)) " is false.", \ + __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_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__)) @@ -206,11 +206,29 @@ struct criterion_assert_args { // Common unary assertions -# define cr_assert_null(...) CR_EXPAND(cr_assert_eq(CR_VA_HEAD(__VA_ARGS__), NULL, CR_VA_TAIL(__VA_ARGS__))) -# define cr_expect_null(...) CR_EXPAND(cr_expect_eq(CR_VA_HEAD(__VA_ARGS__), NULL, CR_VA_TAIL(__VA_ARGS__))) +# define cr_assert_null_op_(Fail, Op, Not, Value, ...) \ + CR_EXPAND(cr_assert_impl( \ + Fail, \ + (Value) Op NULL, \ + dummy, \ + CR_STR(Value) " is" Not " null.", \ + __VA_ARGS__ \ + )) + +# define cr_assert_null_op_va_(Fail, Op, Not, ...) \ + CR_EXPAND(cr_assert_null_op_( \ + Fail, \ + Op, \ + Not, \ + CR_VA_HEAD(__VA_ARGS__), \ + CR_VA_TAIL(__VA_ARGS__) \ + )) + +# define cr_assert_null(...) CR_EXPAND(cr_assert_null_op_va_(CR_FAIL_ABORT_, ==, " not", __VA_ARGS__)) +# define cr_expect_null(...) CR_EXPAND(cr_assert_null_op_va_(CR_FAIL_CONTINUES_, ==, " not", __VA_ARGS__)) -# define cr_assert_not_null(...) CR_EXPAND(cr_assert_neq(CR_VA_HEAD(__VA_ARGS__), NULL, CR_VA_TAIL(__VA_ARGS__))) -# define cr_expect_not_null(...) CR_EXPAND(cr_expect_neq(CR_VA_HEAD(__VA_ARGS__), NULL, CR_VA_TAIL(__VA_ARGS__))) +# define cr_assert_not_null(...) CR_EXPAND(cr_assert_null_op_va_(CR_FAIL_ABORT_, !=, "", __VA_ARGS__)) +# define cr_expect_not_null(...) CR_EXPAND(cr_assert_null_op_va_(CR_FAIL_CONTINUES_, !=, "", __VA_ARGS__)) // Floating-point assertions @@ -220,13 +238,13 @@ struct criterion_assert_args { # 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, \ - CR_STR(Op(Actual, Expected, Epsilon)), \ - __VA_ARGS__ \ +# define cr_assert_float_op_(Fail, Op, Actual, Expected, Epsilon, ...) \ + CR_EXPAND(cr_assert_impl( \ + Fail, \ + Op(Actual, Expected, Epsilon), \ + dummy, \ + "The expression " CR_STR(Op(Actual, Expected, Epsilon)) " is false.", \ + __VA_ARGS__ \ )) # define cr_assert_float_op_va_(Fail, Op, ...) \ @@ -247,35 +265,37 @@ struct criterion_assert_args { // String assertions -# define cr_assert_str_op_empty_(Fail, Op, Value, ...) \ - CR_EXPAND(cr_assert_impl( \ - Fail, \ - (Value)[0] Op '\0', \ - dummy, \ - CR_STR(Value is empty.), \ - __VA_ARGS__ \ +# define cr_assert_str_op_empty_(Fail, Op, Not, Value, ...) \ + CR_EXPAND(cr_assert_impl( \ + Fail, \ + (Value)[0] Op '\0', \ + dummy, \ + CR_STR(Value) " is" Not " empty.", \ + __VA_ARGS__ \ )) -# define cr_assert_str_op_empty_va_(Fail, Op, ...) \ +# define cr_assert_str_op_empty_va_(Fail, Op, Not, ...) \ CR_EXPAND(cr_assert_str_op_empty_( \ Fail, \ Op, \ + Not, \ 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_, ==, __VA_ARGS__)) -# define cr_expect_str_empty(...) CR_EXPAND(cr_assert_str_op_empty_va_(CR_FAIL_ABORT_, ==, __VA_ARGS__)) +# define cr_assert_str_empty(...) CR_EXPAND(cr_assert_str_op_empty_va_(CR_FAIL_ABORT_, ==, " not", __VA_ARGS__)) +# define cr_expect_str_empty(...) CR_EXPAND(cr_assert_str_op_empty_va_(CR_FAIL_CONTINUES_, ==, " not", __VA_ARGS__)) -# define cr_assert_str_not_empty(...) CR_EXPAND(cr_assert_str_op_empty_va_(CR_FAIL_ABORT_, !=, __VA_ARGS__)) -# define cr_expect_str_not_empty(...) CR_EXPAND(cr_assert_str_op_empty_va_(CR_FAIL_ABORT_, !=, __VA_ARGS__)) +# define cr_assert_str_not_empty(...) CR_EXPAND(cr_assert_str_op_empty_va_(CR_FAIL_ABORT_, !=, "", __VA_ARGS__)) +# define cr_expect_str_not_empty(...) CR_EXPAND(cr_assert_str_op_empty_va_(CR_FAIL_CONTINUES_, !=, "", __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, \ - CR_STR((as strings) (Actual) Op (Expected)), \ + "The expression (as strings) " \ + CR_STR((Actual) Op (Expected)) " is false", \ __VA_ARGS__ \ )) @@ -308,13 +328,15 @@ struct criterion_assert_args { // 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, \ - CR_STR((Actual)[0 .. Size] Op (Expected)[0 .. Size]), \ - __VA_ARGS__ \ +# 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, \ + "The expression " \ + CR_STR((Actual)[0 .. Size] Op (Expected)[0 .. Size]) \ + "is false.", \ + __VA_ARGS__ \ )) # define cr_assert_mem_op_va_(Fail, Op, ...) \ @@ -357,7 +379,9 @@ struct criterion_assert_args { Fail, \ order Op 0, \ dummy, \ - CR_STR((Actual)[0 .. Size] Op (Expected)[0 .. Size]), \ + "The expression " \ + CR_STR((Actual)[0 .. Size] Op (Expected)[0 .. Size]) \ + " is false.", \ __VA_ARGS__ \ )); \ } while (0) @@ -446,10 +470,10 @@ struct criterion_assert_args { Statement; \ } catch (Exception const &) { CR_EXPAND(cr_fail(Fail, CR_VA_TAIL(__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__)), \ +# 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__))) \ diff --git a/samples/asserts.c.bin.err.expected b/samples/asserts.c.bin.err.expected index 2488aa8d..95d9a944 100644 --- a/samples/asserts.c.bin.err.expected +++ b/samples/asserts.c.bin.err.expected @@ -2,6 +2,6 @@ [----] asserts.c:12: Assertion failed: This assert runs [FAIL] asserts::base: (0.00s) [----] asserts.c:17: Assertion failed: You can fail an assertion with a message from anywhere -[----] asserts.c:18: Assertion failed: The condition for this assertion were not met. +[----] asserts.c:18: Assertion failed: The conditions for this assertion were not met. [FAIL] asserts::old_school: (0.00s) [====] Synthesis: Tested: 6 | Passing: 4 | Failing: 2 | Crashing: 0  diff --git a/samples/asserts.cc.bin.err.expected b/samples/asserts.cc.bin.err.expected index 3ef16473..ac5d5222 100644 --- a/samples/asserts.cc.bin.err.expected +++ b/samples/asserts.cc.bin.err.expected @@ -1,11 +1,11 @@ -[----] asserts.cc:83: Assertion failed: (&s1)[0 .. 2] == (&s2)[0 .. 2] +[----] asserts.cc:83: Assertion failed: The expression (&s1)[0 .. 2] == (&s2)[0 .. 2] is false. [FAIL] asserts::array: (0.00s) [----] asserts.cc:13: Assertion failed: assert is fatal, expect isn't [----] asserts.cc:14: Assertion failed: This assert runs [FAIL] asserts::base: (0.00s) -[----] asserts.cc:89: Assertion failed: The condition for this assertion were not met. +[----] asserts.cc:89: Assertion failed: The conditions for this assertion were not met. [FAIL] asserts::exception: (0.00s) [----] asserts.cc:19: Assertion failed: You can fail an assertion with a message from anywhere -[----] asserts.cc:20: Assertion failed: The condition for this assertion were not met. +[----] asserts.cc:20: Assertion failed: The conditions for this assertion were not met. [FAIL] asserts::old_school: (0.00s) [====] Synthesis: Tested: 7 | Passing: 3 | Failing: 4 | Crashing: 0  diff --git a/samples/description.c.bin.err.expected b/samples/description.c.bin.err.expected index 64ffe215..2cc0d104 100644 --- a/samples/description.c.bin.err.expected +++ b/samples/description.c.bin.err.expected @@ -1,3 +1,3 @@ -[----] description.c:4: Assertion failed: 0 +[----] description.c:4: Assertion failed: The expression 0 is false. [FAIL] misc::failing: (0.00s) [====] Synthesis: Tested: 1 | Passing: 0 | Failing: 1 | Crashing: 0  diff --git a/samples/description.cc.bin.err.expected b/samples/description.cc.bin.err.expected index 730b527f..b9cebe4b 100644 --- a/samples/description.cc.bin.err.expected +++ b/samples/description.cc.bin.err.expected @@ -1,3 +1,3 @@ -[----] description.cc:4: Assertion failed: 0 +[----] description.cc:4: Assertion failed: The expression 0 is false. [FAIL] misc::failing: (0.00s) [====] Synthesis: Tested: 1 | Passing: 0 | Failing: 1 | Crashing: 0  diff --git a/samples/report.c.bin.err.expected b/samples/report.c.bin.err.expected index 5b8f140b..f08bf9aa 100644 --- a/samples/report.c.bin.err.expected +++ b/samples/report.c.bin.err.expected @@ -1,3 +1,3 @@ -[----] report.c:5: Assertion failed: 0 +[----] report.c:5: Assertion failed: The expression 0 is false. [FAIL] sample::test: (0.00s) [====] Synthesis: Tested: 1 | Passing: 0 | Failing: 1 | Crashing: 0  diff --git a/samples/report.cc.bin.err.expected b/samples/report.cc.bin.err.expected index d81ba267..72c59aa4 100644 --- a/samples/report.cc.bin.err.expected +++ b/samples/report.cc.bin.err.expected @@ -1,3 +1,3 @@ -[----] report.cc:5: Assertion failed: 0 +[----] report.cc:5: Assertion failed: The expression 0 is false. [FAIL] sample::test: (0.00s) [====] Synthesis: Tested: 1 | Passing: 0 | Failing: 1 | Crashing: 0  diff --git a/samples/simple.c.bin.err.expected b/samples/simple.c.bin.err.expected index ef375ca7..a6878985 100644 --- a/samples/simple.c.bin.err.expected +++ b/samples/simple.c.bin.err.expected @@ -1,3 +1,3 @@ -[----] simple.c:4: Assertion failed: 0 +[----] simple.c:4: Assertion failed: The expression 0 is false. [FAIL] misc::failing: (0.00s) [====] Synthesis: Tested: 2 | Passing: 1 | Failing: 1 | Crashing: 0  diff --git a/samples/simple.cc.bin.err.expected b/samples/simple.cc.bin.err.expected index c52de64f..816d6cd4 100644 --- a/samples/simple.cc.bin.err.expected +++ b/samples/simple.cc.bin.err.expected @@ -1,3 +1,3 @@ -[----] simple.cc:4: Assertion failed: 0 +[----] simple.cc:4: Assertion failed: The expression 0 is false. [FAIL] misc::failing: (0.00s) [====] Synthesis: Tested: 2 | Passing: 1 | Failing: 1 | Crashing: 0  From f0201193198cdede0dc30509ba807aeabd2ebdaf Mon Sep 17 00:00:00 2001 From: Snaipe Date: Wed, 9 Sep 2015 01:31:33 +0200 Subject: [PATCH 126/174] Added comparison test for all failure messages --- samples/CMakeLists.txt | 1 + samples/tests/failmessages.c | 49 +++++++++++++++++++ samples/tests/failmessages.c.bin.err.expected | 41 ++++++++++++++++ samples/tests/failmessages.c.bin.out.expected | 0 4 files changed, 91 insertions(+) create mode 100644 samples/tests/failmessages.c create mode 100644 samples/tests/failmessages.c.bin.err.expected create mode 100644 samples/tests/failmessages.c.bin.out.expected diff --git a/samples/CMakeLists.txt b/samples/CMakeLists.txt index f95f2558..60eaacac 100644 --- a/samples/CMakeLists.txt +++ b/samples/CMakeLists.txt @@ -18,6 +18,7 @@ set(SAMPLES other-crashes.c simple.c theories.c + tests/failmessages.c signal.cc exit.cc diff --git a/samples/tests/failmessages.c b/samples/tests/failmessages.c new file mode 100644 index 00000000..e2bc221b --- /dev/null +++ b/samples/tests/failmessages.c @@ -0,0 +1,49 @@ +#include + +Test(messages, default) { + cr_expect(0); + cr_expect_eq(0, 1); + cr_expect_neq(1, 1); + cr_expect_lt(2, 1); + cr_expect_leq(2, 1); + cr_expect_gt(1, 2); + cr_expect_geq(1, 2); + cr_expect_null(""); + cr_expect_not_null(NULL); + + cr_expect_float_eq(1, 2, 0.1); + cr_expect_float_neq(2, 2, 0.1); + + cr_expect_str_empty("foo"); + cr_expect_str_not_empty(""); + cr_expect_str_eq("abc", "abd"); + cr_expect_str_neq("abc", "abc"); + cr_expect_str_lt("abc", "aba"); + cr_expect_str_leq("abc", "aba"); + cr_expect_str_gt("abc", "abd"); + cr_expect_str_geq("abc", "abd"); +} + +Test(messages, user) { + cr_expect(0, "foo %s", "bar"); + cr_expect_eq(0, 1, "foo %s", "bar"); + cr_expect_neq(1, 1, "foo %s", "bar"); + cr_expect_lt(2, 1, "foo %s", "bar"); + cr_expect_leq(2, 1, "foo %s", "bar"); + cr_expect_gt(1, 2, "foo %s", "bar"); + cr_expect_geq(1, 2, "foo %s", "bar"); + cr_expect_null("", "foo %s", "bar"); + cr_expect_not_null(NULL, "foo %s", "bar"); + + cr_expect_float_eq(1, 2, 0.1, "foo %s", "bar"); + cr_expect_float_neq(2, 2, 0.1, "foo %s", "bar"); + + cr_expect_str_empty("foo", "foo %s", "bar"); + cr_expect_str_not_empty("", "foo %s", "bar"); + cr_expect_str_eq("abc", "abd", "foo %s", "bar"); + cr_expect_str_neq("abc", "abc", "foo %s", "bar"); + cr_expect_str_lt("abc", "aba", "foo %s", "bar"); + cr_expect_str_leq("abc", "aba", "foo %s", "bar"); + cr_expect_str_gt("abc", "abd", "foo %s", "bar"); + cr_expect_str_geq("abc", "abd", "foo %s", "bar"); +} diff --git a/samples/tests/failmessages.c.bin.err.expected b/samples/tests/failmessages.c.bin.err.expected new file mode 100644 index 00000000..b6af5a9d --- /dev/null +++ b/samples/tests/failmessages.c.bin.err.expected @@ -0,0 +1,41 @@ +[----] failmessages.c:4: Assertion failed: The expression 0 is false. +[----] failmessages.c:5: Assertion failed: The expression (0) == (1) is false. +[----] failmessages.c:6: Assertion failed: The expression (1) != (1) is false. +[----] failmessages.c:7: Assertion failed: The expression (2) < (1) is false. +[----] failmessages.c:8: Assertion failed: The expression (2) <= (1) is false. +[----] failmessages.c:9: Assertion failed: The expression (1) > (2) is false. +[----] failmessages.c:10: Assertion failed: The expression (1) >= (2) is false. +[----] failmessages.c:11: Assertion failed: "" is not null. +[----] failmessages.c:12: Assertion failed: ((void *)0) is null. +[----] failmessages.c:14: Assertion failed: The expression (2) - (1) <= (0.1) && (1) - (2) <= (0.1) is false. +[----] failmessages.c:15: Assertion failed: The expression (2) - (2) > (0.1) || (2) - (2) > (0.1) is false. +[----] failmessages.c:17: Assertion failed: "foo" is not empty. +[----] failmessages.c:18: Assertion failed: "" is empty. +[----] failmessages.c:19: Assertion failed: The expression (as strings) ("abc") == ("abd") is false +[----] failmessages.c:20: Assertion failed: The expression (as strings) ("abc") != ("abc") is false +[----] failmessages.c:21: Assertion failed: The expression (as strings) ("abc") < ("aba") is false +[----] 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) +[----] failmessages.c:28: Assertion failed: foo bar +[----] failmessages.c:29: Assertion failed: foo bar +[----] failmessages.c:30: Assertion failed: foo bar +[----] failmessages.c:31: Assertion failed: foo bar +[----] failmessages.c:32: Assertion failed: foo bar +[----] failmessages.c:33: Assertion failed: foo bar +[----] failmessages.c:34: Assertion failed: foo bar +[----] failmessages.c:35: Assertion failed: foo bar +[----] failmessages.c:36: Assertion failed: foo bar +[----] failmessages.c:38: Assertion failed: foo bar +[----] failmessages.c:39: Assertion failed: foo bar +[----] failmessages.c:41: Assertion failed: foo bar +[----] failmessages.c:42: Assertion failed: foo bar +[----] failmessages.c:43: Assertion failed: foo bar +[----] failmessages.c:44: Assertion failed: foo bar +[----] failmessages.c:45: Assertion failed: foo bar +[----] 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) +[====] Synthesis: Tested: 2 | Passing: 0 | Failing: 2 | Crashing: 0  diff --git a/samples/tests/failmessages.c.bin.out.expected b/samples/tests/failmessages.c.bin.out.expected new file mode 100644 index 00000000..e69de29b From df8035e484c140b5c041911b4c09359732398d5b Mon Sep 17 00:00:00 2001 From: Snaipe Date: Wed, 9 Sep 2015 01:47:10 +0200 Subject: [PATCH 127/174] Refactored sample CMakeLists --- samples/CMakeLists.txt | 37 ++++++++++++++++++++---------------- samples/tests/CMakeLists.txt | 5 +++++ 2 files changed, 26 insertions(+), 16 deletions(-) create mode 100644 samples/tests/CMakeLists.txt diff --git a/samples/CMakeLists.txt b/samples/CMakeLists.txt index 60eaacac..a3a05ee0 100644 --- a/samples/CMakeLists.txt +++ b/samples/CMakeLists.txt @@ -18,7 +18,6 @@ set(SAMPLES other-crashes.c simple.c theories.c - tests/failmessages.c signal.cc exit.cc @@ -47,23 +46,27 @@ if (HAVE_PCRE) set(SCRIPTS ${SCRIPTS} pattern) endif () -foreach(sample ${SAMPLES}) - add_executable(${sample}.bin ${sample}) - target_link_libraries(${sample}.bin criterion) - add_test(${sample} ${sample}.bin) - set_property(TEST ${sample} PROPERTY - ENVIRONMENT "CRITERION_ALWAYS_SUCCEED=1" - ) - - if (NOT MSVC) # we disable the scripted tests when building with MSVC - add_test(${sample}_compare sh ${CMAKE_CURRENT_LIST_DIR}/tests/run_test.sh "${CMAKE_CURRENT_LIST_DIR}" . . ${sample}.bin) - set_property(TEST ${sample}_compare PROPERTY - ENVIRONMENT "LC_ALL=en_US.utf8" +macro(add_samples DIR_ SAMPLES_) + foreach(sample ${SAMPLES_}) + add_executable(${sample}.bin ${sample}) + target_link_libraries(${sample}.bin criterion) + add_test(${sample} ${sample}.bin) + set_property(TEST ${sample} PROPERTY ENVIRONMENT "CRITERION_ALWAYS_SUCCEED=1" - ENVIRONMENT "CRITERION_SHORT_FILENAME=1" ) - endif () -endforeach() + + if (NOT MSVC) # we disable the scripted tests when building with MSVC + add_test(${sample}_compare sh ${DIR_}/run_test.sh "${CMAKE_CURRENT_LIST_DIR}" . . ${sample}.bin) + set_property(TEST ${sample}_compare PROPERTY + ENVIRONMENT "LC_ALL=en_US.utf8" + ENVIRONMENT "CRITERION_ALWAYS_SUCCEED=1" + ENVIRONMENT "CRITERION_SHORT_FILENAME=1" + ) + endif () + endforeach() +endmacro() + +add_samples("${CMAKE_CURRENT_LIST_DIR}/tests" "${SAMPLES}") if (NOT MSVC) # we disable the scripted tests when building with MSVC @@ -82,3 +85,5 @@ foreach(script ${SCRIPTS}) endforeach() endif() + +add_subdirectory(tests) diff --git a/samples/tests/CMakeLists.txt b/samples/tests/CMakeLists.txt new file mode 100644 index 00000000..6399df5c --- /dev/null +++ b/samples/tests/CMakeLists.txt @@ -0,0 +1,5 @@ +set(SAMPLES + failmessages.c +) + +add_samples("${CMAKE_CURRENT_LIST_DIR}" "${SAMPLES}") From 5e4c9beaa8b78c3b8625c7169e079c8a6e226124 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Wed, 9 Sep 2015 02:15:13 +0200 Subject: [PATCH 128/174] Added Debug directory to path for appveyor builds --- appveyor.yml | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 4c16dd55..96d4291f 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -4,7 +4,7 @@ os: Visual Studio 2015 init: - git config --global core.autocrlf input - - 'SET PATH=C:\MinGW\bin;%PATH%;C:\MinGW\msys\1.0\bin;%APPVEYOR_BUILD_FOLDER%\build' + - 'SET PATH=C:\MinGW\bin;%PATH%;C:\MinGW\msys\1.0\bin;%APPVEYOR_BUILD_FOLDER%\build;%APPVEYOR_BUILD_FOLDER%\build\Debug' environment: COVERALLS_REPO_TOKEN: @@ -42,12 +42,6 @@ install: build_script: - cmake --build . - - ps: | - # HACK: We need to copy criterion.dll into the binary directory - if ($env:Compiler -eq "msvc") { - Copy-Item Debug/criterion.dll samples/Debug/ - Copy-Item Debug/criterion.dll test/Debug/ - } before_deploy: - ps: | From 788803d0ddb918cb2fd76a0640a2062416dc1dda Mon Sep 17 00:00:00 2001 From: Snaipe Date: Wed, 9 Sep 2015 02:30:48 +0200 Subject: [PATCH 129/174] Refactored CONTRIBUTING.md out of README.md --- CONTRIBUTING.md | 42 ++++++++++++++++++++++++++++++++++++++++++ README.md | 28 ---------------------------- 2 files changed, 42 insertions(+), 28 deletions(-) create mode 100644 CONTRIBUTING.md diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 00000000..bae87cd7 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,42 @@ +# Contributing + +Contributions are welcomed, but must follow a simple set of rules in order to +be merged. + +**Please follow these conventions if you want your pull request(s) accepted.** + +## General + +* Use 4 (four) spaces for indentation. +* No trailing whitespaces. +* 80 chars column limit. +* No trash files. Trash files are by-products of the compilation process, or + generated files that does not need to be under version control. +* Pull requests must compile and work properly. +* Pull requests must pass all tests. +* Pull requests must be mergeable automatically. +* Number of commits in a pull request should be kept to one commit and all + additional commits must be squashed. +* You may have more than one commit in a pull request if the commits are + separate changes, otherwise squash them. + +## Translations + +* You can contribute new translation files for output messages, on the + condition that you are fluent with the language itself. +* Each correction on existing translations must be followed by a + rationale ("why would the translation be better if the change is applied?") + +## Roadmap + + . + |- .cmake/: CMake modules + |- dependencies/: dependencies for building libcriterion + |- doc/: Sphinx documentation files + |- include/criterion/: Public API + |- src/: Sources for libcriterion + | `- log/: Output providers, all the output logic in general + |- po/: Translation files, i18n stuff + |- test/: Unit tests for libcriterion + `- samples/: Sample files + `- tests/: Internal regression tests diff --git a/README.md b/README.md index f41bd944..b4e692b8 100644 --- a/README.md +++ b/README.md @@ -61,34 +61,6 @@ Sample tests can be found in the [sample directory][samples]. * [Tests with signals][sample-signal] * [Using report hooks][sample-report] -## Contributing - -Contributions are welcomed, but must follow a simple set of rules in order to -be merged. - -**Please follow these conventions if you want your pull request(s) accepted.** - -### General - -* Use 4 (four) spaces for indentation. -* No trailing whitespaces. -* 80 chars column limit. -* No trash files. Trash files are by-products of the compilation process, or - generated files that does not need to be under version control. -* Pull requests must compile and work properly. -* Pull requests must be mergeable automatically. -* Number of commits in a pull request should be kept to one commit and all - additional commits must be squashed. -* You may have more than one commit in a pull request if the commits are - separate changes, otherwise squash them. - -### Translations - -* You can contribute new translation files for output messages, on the - condition that you are fluent with the language itself. -* Each correction on existing translations must be followed by a - rationale ("why would the translation be better if the change is applied?") - ## F.A.Q. **Q. What's wrong with other C test frameworks?** From d9af4fc6148d180ab3ee10d59f98b0ade5533569 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Wed, 9 Sep 2015 02:42:00 +0200 Subject: [PATCH 130/174] Removed legacy Makefile.am --- samples/Makefile.am | 39 --------------------------------------- 1 file changed, 39 deletions(-) delete mode 100644 samples/Makefile.am diff --git a/samples/Makefile.am b/samples/Makefile.am deleted file mode 100644 index 7ed5f121..00000000 --- a/samples/Makefile.am +++ /dev/null @@ -1,39 +0,0 @@ -BIN_TESTS = \ - signal \ - report \ - suites \ - fixtures \ - asserts \ - more-suites \ - long-messages \ - description \ - other-crashes \ - simple - -TESTS_ENVIRONMENT = CRITERION_ALWAYS_SUCCEED=1 - -check_PROGRAMS := $(BIN_TESTS) -CFLAGS = -I$(top_srcdir)/include/ -std=c99 -Wall -Wextra -pedantic -LDADD = -L$(top_srcdir)/ -lcriterion - -if ENABLE_RT_TESTS -BIN_TESTS += with-time -with_time_LDADD = $(LDADD) -lrt -endif - -SCRIPT_TESTS = tests/tap_test.sh \ - tests/early_exit.sh \ - tests/verbose.sh \ - tests/list.sh \ - tests/pattern.sh \ - tests/fail_fast.sh \ - tests/help.sh - -EXTRA_DIST = $(SCRIPT_TESTS) - -tests/tap_test.sh: simple signal asserts -tests/early_exit.sh: simple -tests/verbose.sh: simple -tests/help.sh: simple - -TESTS = $(BIN_TESTS) $(SCRIPT_TESTS) From f7d4d7616ac9621c41e28a44a7dcd18f55a4b5bd Mon Sep 17 00:00:00 2001 From: Snaipe Date: Wed, 9 Sep 2015 02:43:01 +0200 Subject: [PATCH 131/174] Cleaned up sample directory --- CONTRIBUTING.md | 2 ++ samples/CMakeLists.txt | 8 +------- samples/{ => outputs}/asserts.c.bin.err.expected | 0 samples/{ => outputs}/asserts.c.bin.out.expected | 0 samples/{ => outputs}/asserts.cc.bin.err.expected | 0 samples/{ => outputs}/asserts.cc.bin.out.expected | 0 samples/{ => outputs}/description.c.bin.err.expected | 0 samples/{ => outputs}/description.c.bin.out.expected | 0 samples/{ => outputs}/description.cc.bin.err.expected | 0 samples/{ => outputs}/description.cc.bin.out.expected | 0 samples/{ => outputs}/fixtures.c.bin.err.expected | 0 samples/{ => outputs}/fixtures.c.bin.out.expected | 0 samples/{ => outputs}/fixtures.cc.bin.err.expected | 0 samples/{ => outputs}/fixtures.cc.bin.out.expected | 0 samples/{ => outputs}/more-suites.c.bin.err.expected | 0 samples/{ => outputs}/more-suites.c.bin.out.expected | 0 samples/{ => outputs}/more-suites.cc.bin.err.expected | 0 samples/{ => outputs}/more-suites.cc.bin.out.expected | 0 samples/{ => outputs}/other-crashes.c.bin.err.expected | 0 samples/{ => outputs}/other-crashes.c.bin.out.expected | 0 samples/{ => outputs}/other-crashes.cc.bin.err.expected | 0 samples/{ => outputs}/other-crashes.cc.bin.out.expected | 0 samples/{ => outputs}/report.c.bin.err.expected | 0 samples/{ => outputs}/report.c.bin.out.expected | 0 samples/{ => outputs}/report.cc.bin.err.expected | 0 samples/{ => outputs}/report.cc.bin.out.expected | 0 samples/{ => outputs}/signal.c.bin.err.expected | 0 samples/{ => outputs}/signal.c.bin.out.expected | 0 samples/{ => outputs}/signal.cc.bin.err.expected | 0 samples/{ => outputs}/signal.cc.bin.out.expected | 0 samples/{ => outputs}/simple.c.bin.err.expected | 0 samples/{ => outputs}/simple.c.bin.out.expected | 0 samples/{ => outputs}/simple.cc.bin.err.expected | 0 samples/{ => outputs}/simple.cc.bin.out.expected | 0 samples/{ => outputs}/suites.c.bin.err.expected | 0 samples/{ => outputs}/suites.c.bin.out.expected | 0 samples/{ => outputs}/suites.cc.bin.err.expected | 0 samples/{ => outputs}/suites.cc.bin.out.expected | 0 samples/tests/CMakeLists.txt | 7 +++++++ samples/{ => tests}/exit.c | 0 samples/{ => tests}/exit.cc | 0 samples/{ => tests}/long-messages.c | 0 samples/{ => tests}/long-messages.cc | 0 samples/{ => tests}/other-crashes.c | 0 samples/{ => tests}/other-crashes.cc | 0 samples/{ => tests/outputs}/exit.c.bin.err.expected | 0 samples/{ => tests/outputs}/exit.c.bin.out.expected | 0 samples/{ => tests/outputs}/exit.cc.bin.err.expected | 0 samples/{ => tests/outputs}/exit.cc.bin.out.expected | 0 .../tests/{ => outputs}/failmessages.c.bin.err.expected | 0 .../tests/{ => outputs}/failmessages.c.bin.out.expected | 0 .../{ => tests/outputs}/long-messages.c.bin.err.expected | 0 .../{ => tests/outputs}/long-messages.c.bin.out.expected | 0 .../{ => tests/outputs}/long-messages.cc.bin.err.expected | 0 .../{ => tests/outputs}/long-messages.cc.bin.out.expected | 0 samples/{ => tests}/with-time.c | 0 56 files changed, 10 insertions(+), 7 deletions(-) rename samples/{ => outputs}/asserts.c.bin.err.expected (100%) rename samples/{ => outputs}/asserts.c.bin.out.expected (100%) rename samples/{ => outputs}/asserts.cc.bin.err.expected (100%) rename samples/{ => outputs}/asserts.cc.bin.out.expected (100%) rename samples/{ => outputs}/description.c.bin.err.expected (100%) rename samples/{ => outputs}/description.c.bin.out.expected (100%) rename samples/{ => outputs}/description.cc.bin.err.expected (100%) rename samples/{ => outputs}/description.cc.bin.out.expected (100%) rename samples/{ => outputs}/fixtures.c.bin.err.expected (100%) rename samples/{ => outputs}/fixtures.c.bin.out.expected (100%) rename samples/{ => outputs}/fixtures.cc.bin.err.expected (100%) rename samples/{ => outputs}/fixtures.cc.bin.out.expected (100%) rename samples/{ => outputs}/more-suites.c.bin.err.expected (100%) rename samples/{ => outputs}/more-suites.c.bin.out.expected (100%) rename samples/{ => outputs}/more-suites.cc.bin.err.expected (100%) rename samples/{ => outputs}/more-suites.cc.bin.out.expected (100%) rename samples/{ => outputs}/other-crashes.c.bin.err.expected (100%) rename samples/{ => outputs}/other-crashes.c.bin.out.expected (100%) rename samples/{ => outputs}/other-crashes.cc.bin.err.expected (100%) rename samples/{ => outputs}/other-crashes.cc.bin.out.expected (100%) rename samples/{ => outputs}/report.c.bin.err.expected (100%) rename samples/{ => outputs}/report.c.bin.out.expected (100%) rename samples/{ => outputs}/report.cc.bin.err.expected (100%) rename samples/{ => outputs}/report.cc.bin.out.expected (100%) rename samples/{ => outputs}/signal.c.bin.err.expected (100%) rename samples/{ => outputs}/signal.c.bin.out.expected (100%) rename samples/{ => outputs}/signal.cc.bin.err.expected (100%) rename samples/{ => outputs}/signal.cc.bin.out.expected (100%) rename samples/{ => outputs}/simple.c.bin.err.expected (100%) rename samples/{ => outputs}/simple.c.bin.out.expected (100%) rename samples/{ => outputs}/simple.cc.bin.err.expected (100%) rename samples/{ => outputs}/simple.cc.bin.out.expected (100%) rename samples/{ => outputs}/suites.c.bin.err.expected (100%) rename samples/{ => outputs}/suites.c.bin.out.expected (100%) rename samples/{ => outputs}/suites.cc.bin.err.expected (100%) rename samples/{ => outputs}/suites.cc.bin.out.expected (100%) rename samples/{ => tests}/exit.c (100%) rename samples/{ => tests}/exit.cc (100%) rename samples/{ => tests}/long-messages.c (100%) rename samples/{ => tests}/long-messages.cc (100%) rename samples/{ => tests}/other-crashes.c (100%) rename samples/{ => tests}/other-crashes.cc (100%) rename samples/{ => tests/outputs}/exit.c.bin.err.expected (100%) rename samples/{ => tests/outputs}/exit.c.bin.out.expected (100%) rename samples/{ => tests/outputs}/exit.cc.bin.err.expected (100%) rename samples/{ => tests/outputs}/exit.cc.bin.out.expected (100%) rename samples/tests/{ => outputs}/failmessages.c.bin.err.expected (100%) rename samples/tests/{ => outputs}/failmessages.c.bin.out.expected (100%) rename samples/{ => tests/outputs}/long-messages.c.bin.err.expected (100%) rename samples/{ => tests/outputs}/long-messages.c.bin.out.expected (100%) rename samples/{ => tests/outputs}/long-messages.cc.bin.err.expected (100%) rename samples/{ => tests/outputs}/long-messages.cc.bin.out.expected (100%) rename samples/{ => tests}/with-time.c (100%) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index bae87cd7..670555eb 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -39,4 +39,6 @@ be merged. |- po/: Translation files, i18n stuff |- test/: Unit tests for libcriterion `- samples/: Sample files + |- outputs/: Expected output files for the current samples `- tests/: Internal regression tests + `- outputs/: Expected output files for the regression tests diff --git a/samples/CMakeLists.txt b/samples/CMakeLists.txt index a3a05ee0..1dfbacaf 100644 --- a/samples/CMakeLists.txt +++ b/samples/CMakeLists.txt @@ -7,28 +7,22 @@ include_directories(../include) set(SAMPLES signal.c - exit.c report.c suites.c fixtures.c asserts.c more-suites.c - long-messages.c description.c - other-crashes.c simple.c theories.c signal.cc - exit.cc report.cc suites.cc fixtures.cc asserts.cc more-suites.cc - long-messages.cc description.cc - other-crashes.cc simple.cc theories.cc ) @@ -56,7 +50,7 @@ macro(add_samples DIR_ SAMPLES_) ) if (NOT MSVC) # we disable the scripted tests when building with MSVC - add_test(${sample}_compare sh ${DIR_}/run_test.sh "${CMAKE_CURRENT_LIST_DIR}" . . ${sample}.bin) + add_test(${sample}_compare sh ${DIR_}/run_test.sh "${CMAKE_CURRENT_LIST_DIR}/out_dir" . . ${sample}.bin) set_property(TEST ${sample}_compare PROPERTY ENVIRONMENT "LC_ALL=en_US.utf8" ENVIRONMENT "CRITERION_ALWAYS_SUCCEED=1" diff --git a/samples/asserts.c.bin.err.expected b/samples/outputs/asserts.c.bin.err.expected similarity index 100% rename from samples/asserts.c.bin.err.expected rename to samples/outputs/asserts.c.bin.err.expected diff --git a/samples/asserts.c.bin.out.expected b/samples/outputs/asserts.c.bin.out.expected similarity index 100% rename from samples/asserts.c.bin.out.expected rename to samples/outputs/asserts.c.bin.out.expected diff --git a/samples/asserts.cc.bin.err.expected b/samples/outputs/asserts.cc.bin.err.expected similarity index 100% rename from samples/asserts.cc.bin.err.expected rename to samples/outputs/asserts.cc.bin.err.expected diff --git a/samples/asserts.cc.bin.out.expected b/samples/outputs/asserts.cc.bin.out.expected similarity index 100% rename from samples/asserts.cc.bin.out.expected rename to samples/outputs/asserts.cc.bin.out.expected diff --git a/samples/description.c.bin.err.expected b/samples/outputs/description.c.bin.err.expected similarity index 100% rename from samples/description.c.bin.err.expected rename to samples/outputs/description.c.bin.err.expected diff --git a/samples/description.c.bin.out.expected b/samples/outputs/description.c.bin.out.expected similarity index 100% rename from samples/description.c.bin.out.expected rename to samples/outputs/description.c.bin.out.expected diff --git a/samples/description.cc.bin.err.expected b/samples/outputs/description.cc.bin.err.expected similarity index 100% rename from samples/description.cc.bin.err.expected rename to samples/outputs/description.cc.bin.err.expected diff --git a/samples/description.cc.bin.out.expected b/samples/outputs/description.cc.bin.out.expected similarity index 100% rename from samples/description.cc.bin.out.expected rename to samples/outputs/description.cc.bin.out.expected diff --git a/samples/fixtures.c.bin.err.expected b/samples/outputs/fixtures.c.bin.err.expected similarity index 100% rename from samples/fixtures.c.bin.err.expected rename to samples/outputs/fixtures.c.bin.err.expected diff --git a/samples/fixtures.c.bin.out.expected b/samples/outputs/fixtures.c.bin.out.expected similarity index 100% rename from samples/fixtures.c.bin.out.expected rename to samples/outputs/fixtures.c.bin.out.expected diff --git a/samples/fixtures.cc.bin.err.expected b/samples/outputs/fixtures.cc.bin.err.expected similarity index 100% rename from samples/fixtures.cc.bin.err.expected rename to samples/outputs/fixtures.cc.bin.err.expected diff --git a/samples/fixtures.cc.bin.out.expected b/samples/outputs/fixtures.cc.bin.out.expected similarity index 100% rename from samples/fixtures.cc.bin.out.expected rename to samples/outputs/fixtures.cc.bin.out.expected diff --git a/samples/more-suites.c.bin.err.expected b/samples/outputs/more-suites.c.bin.err.expected similarity index 100% rename from samples/more-suites.c.bin.err.expected rename to samples/outputs/more-suites.c.bin.err.expected diff --git a/samples/more-suites.c.bin.out.expected b/samples/outputs/more-suites.c.bin.out.expected similarity index 100% rename from samples/more-suites.c.bin.out.expected rename to samples/outputs/more-suites.c.bin.out.expected diff --git a/samples/more-suites.cc.bin.err.expected b/samples/outputs/more-suites.cc.bin.err.expected similarity index 100% rename from samples/more-suites.cc.bin.err.expected rename to samples/outputs/more-suites.cc.bin.err.expected diff --git a/samples/more-suites.cc.bin.out.expected b/samples/outputs/more-suites.cc.bin.out.expected similarity index 100% rename from samples/more-suites.cc.bin.out.expected rename to samples/outputs/more-suites.cc.bin.out.expected diff --git a/samples/other-crashes.c.bin.err.expected b/samples/outputs/other-crashes.c.bin.err.expected similarity index 100% rename from samples/other-crashes.c.bin.err.expected rename to samples/outputs/other-crashes.c.bin.err.expected diff --git a/samples/other-crashes.c.bin.out.expected b/samples/outputs/other-crashes.c.bin.out.expected similarity index 100% rename from samples/other-crashes.c.bin.out.expected rename to samples/outputs/other-crashes.c.bin.out.expected diff --git a/samples/other-crashes.cc.bin.err.expected b/samples/outputs/other-crashes.cc.bin.err.expected similarity index 100% rename from samples/other-crashes.cc.bin.err.expected rename to samples/outputs/other-crashes.cc.bin.err.expected diff --git a/samples/other-crashes.cc.bin.out.expected b/samples/outputs/other-crashes.cc.bin.out.expected similarity index 100% rename from samples/other-crashes.cc.bin.out.expected rename to samples/outputs/other-crashes.cc.bin.out.expected diff --git a/samples/report.c.bin.err.expected b/samples/outputs/report.c.bin.err.expected similarity index 100% rename from samples/report.c.bin.err.expected rename to samples/outputs/report.c.bin.err.expected diff --git a/samples/report.c.bin.out.expected b/samples/outputs/report.c.bin.out.expected similarity index 100% rename from samples/report.c.bin.out.expected rename to samples/outputs/report.c.bin.out.expected diff --git a/samples/report.cc.bin.err.expected b/samples/outputs/report.cc.bin.err.expected similarity index 100% rename from samples/report.cc.bin.err.expected rename to samples/outputs/report.cc.bin.err.expected diff --git a/samples/report.cc.bin.out.expected b/samples/outputs/report.cc.bin.out.expected similarity index 100% rename from samples/report.cc.bin.out.expected rename to samples/outputs/report.cc.bin.out.expected diff --git a/samples/signal.c.bin.err.expected b/samples/outputs/signal.c.bin.err.expected similarity index 100% rename from samples/signal.c.bin.err.expected rename to samples/outputs/signal.c.bin.err.expected diff --git a/samples/signal.c.bin.out.expected b/samples/outputs/signal.c.bin.out.expected similarity index 100% rename from samples/signal.c.bin.out.expected rename to samples/outputs/signal.c.bin.out.expected diff --git a/samples/signal.cc.bin.err.expected b/samples/outputs/signal.cc.bin.err.expected similarity index 100% rename from samples/signal.cc.bin.err.expected rename to samples/outputs/signal.cc.bin.err.expected diff --git a/samples/signal.cc.bin.out.expected b/samples/outputs/signal.cc.bin.out.expected similarity index 100% rename from samples/signal.cc.bin.out.expected rename to samples/outputs/signal.cc.bin.out.expected diff --git a/samples/simple.c.bin.err.expected b/samples/outputs/simple.c.bin.err.expected similarity index 100% rename from samples/simple.c.bin.err.expected rename to samples/outputs/simple.c.bin.err.expected diff --git a/samples/simple.c.bin.out.expected b/samples/outputs/simple.c.bin.out.expected similarity index 100% rename from samples/simple.c.bin.out.expected rename to samples/outputs/simple.c.bin.out.expected diff --git a/samples/simple.cc.bin.err.expected b/samples/outputs/simple.cc.bin.err.expected similarity index 100% rename from samples/simple.cc.bin.err.expected rename to samples/outputs/simple.cc.bin.err.expected diff --git a/samples/simple.cc.bin.out.expected b/samples/outputs/simple.cc.bin.out.expected similarity index 100% rename from samples/simple.cc.bin.out.expected rename to samples/outputs/simple.cc.bin.out.expected diff --git a/samples/suites.c.bin.err.expected b/samples/outputs/suites.c.bin.err.expected similarity index 100% rename from samples/suites.c.bin.err.expected rename to samples/outputs/suites.c.bin.err.expected diff --git a/samples/suites.c.bin.out.expected b/samples/outputs/suites.c.bin.out.expected similarity index 100% rename from samples/suites.c.bin.out.expected rename to samples/outputs/suites.c.bin.out.expected diff --git a/samples/suites.cc.bin.err.expected b/samples/outputs/suites.cc.bin.err.expected similarity index 100% rename from samples/suites.cc.bin.err.expected rename to samples/outputs/suites.cc.bin.err.expected diff --git a/samples/suites.cc.bin.out.expected b/samples/outputs/suites.cc.bin.out.expected similarity index 100% rename from samples/suites.cc.bin.out.expected rename to samples/outputs/suites.cc.bin.out.expected diff --git a/samples/tests/CMakeLists.txt b/samples/tests/CMakeLists.txt index 6399df5c..d5b4da53 100644 --- a/samples/tests/CMakeLists.txt +++ b/samples/tests/CMakeLists.txt @@ -1,5 +1,12 @@ set(SAMPLES failmessages.c + exit.c + long-messages.c + other-crashes.c + + exit.cc + long-messages.cc + other-crashes.cc ) add_samples("${CMAKE_CURRENT_LIST_DIR}" "${SAMPLES}") diff --git a/samples/exit.c b/samples/tests/exit.c similarity index 100% rename from samples/exit.c rename to samples/tests/exit.c diff --git a/samples/exit.cc b/samples/tests/exit.cc similarity index 100% rename from samples/exit.cc rename to samples/tests/exit.cc diff --git a/samples/long-messages.c b/samples/tests/long-messages.c similarity index 100% rename from samples/long-messages.c rename to samples/tests/long-messages.c diff --git a/samples/long-messages.cc b/samples/tests/long-messages.cc similarity index 100% rename from samples/long-messages.cc rename to samples/tests/long-messages.cc diff --git a/samples/other-crashes.c b/samples/tests/other-crashes.c similarity index 100% rename from samples/other-crashes.c rename to samples/tests/other-crashes.c diff --git a/samples/other-crashes.cc b/samples/tests/other-crashes.cc similarity index 100% rename from samples/other-crashes.cc rename to samples/tests/other-crashes.cc diff --git a/samples/exit.c.bin.err.expected b/samples/tests/outputs/exit.c.bin.err.expected similarity index 100% rename from samples/exit.c.bin.err.expected rename to samples/tests/outputs/exit.c.bin.err.expected diff --git a/samples/exit.c.bin.out.expected b/samples/tests/outputs/exit.c.bin.out.expected similarity index 100% rename from samples/exit.c.bin.out.expected rename to samples/tests/outputs/exit.c.bin.out.expected diff --git a/samples/exit.cc.bin.err.expected b/samples/tests/outputs/exit.cc.bin.err.expected similarity index 100% rename from samples/exit.cc.bin.err.expected rename to samples/tests/outputs/exit.cc.bin.err.expected diff --git a/samples/exit.cc.bin.out.expected b/samples/tests/outputs/exit.cc.bin.out.expected similarity index 100% rename from samples/exit.cc.bin.out.expected rename to samples/tests/outputs/exit.cc.bin.out.expected diff --git a/samples/tests/failmessages.c.bin.err.expected b/samples/tests/outputs/failmessages.c.bin.err.expected similarity index 100% rename from samples/tests/failmessages.c.bin.err.expected rename to samples/tests/outputs/failmessages.c.bin.err.expected diff --git a/samples/tests/failmessages.c.bin.out.expected b/samples/tests/outputs/failmessages.c.bin.out.expected similarity index 100% rename from samples/tests/failmessages.c.bin.out.expected rename to samples/tests/outputs/failmessages.c.bin.out.expected diff --git a/samples/long-messages.c.bin.err.expected b/samples/tests/outputs/long-messages.c.bin.err.expected similarity index 100% rename from samples/long-messages.c.bin.err.expected rename to samples/tests/outputs/long-messages.c.bin.err.expected diff --git a/samples/long-messages.c.bin.out.expected b/samples/tests/outputs/long-messages.c.bin.out.expected similarity index 100% rename from samples/long-messages.c.bin.out.expected rename to samples/tests/outputs/long-messages.c.bin.out.expected diff --git a/samples/long-messages.cc.bin.err.expected b/samples/tests/outputs/long-messages.cc.bin.err.expected similarity index 100% rename from samples/long-messages.cc.bin.err.expected rename to samples/tests/outputs/long-messages.cc.bin.err.expected diff --git a/samples/long-messages.cc.bin.out.expected b/samples/tests/outputs/long-messages.cc.bin.out.expected similarity index 100% rename from samples/long-messages.cc.bin.out.expected rename to samples/tests/outputs/long-messages.cc.bin.out.expected diff --git a/samples/with-time.c b/samples/tests/with-time.c similarity index 100% rename from samples/with-time.c rename to samples/tests/with-time.c From 9896377a470b310d401c9d9eb50b33c8cf9a6726 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Wed, 9 Sep 2015 02:56:54 +0200 Subject: [PATCH 132/174] Added clarification to the proof of the extmatch length heuristic --- src/extmatch.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/extmatch.c b/src/extmatch.c index 79a7ad30..5673191d 100644 --- a/src/extmatch.c +++ b/src/extmatch.c @@ -248,21 +248,21 @@ static int transform(const char *pattern, char *result, const char **errmsg) { * We must now find the maximal length L such as ∀s, L >= length(T(s)) * * It is immediately apparent that the largest string will depend on the number - * of occurrences of '!()'. Hence, let u be a string that is a repeating - * sequence of '!()' padded by '.' to a multiple of 3, + * of occurrences of '!()'. Hence, ∀s, let u(s) be a string that is a repeating + * sequence of '!()' padded by at most two '.', such as length(u(s)) == length(s), * - * let N = floor(length(u) / 3), - * let Q = length(u) mod 3, + * let N = floor(length(u(s)) / 3), + * let Q = length(u(s)) mod 3, * hence num('!()') = N. * - * ∀s | lenght(s) = length(u), - * length(T(s)) <= length(T(u)) - * <= length(u) | the original length + * ∀s | lenght(s) = length(u(s)), + * length(T(s)) <= length(T(u(s))) + * <= length(u(s)) | the original length * + 4 * N | the expansion of all '!()' * + Q * diff('.') | the expansion of Q '.' * <= 3 * N + Q + 4 * N + Q * <= 7 * N + 4 - * <= 7 * floor(length(u) / 3) + 4 + * <= 7 * floor(length(u(s)) / 3) + 4 * <= 7 * floor(length(s) / 3) + 4 * */ From 352123b2d5ed3eae86ceff4fd6ea7547b828c27f Mon Sep 17 00:00:00 2001 From: Snaipe Date: Wed, 9 Sep 2015 03:00:49 +0200 Subject: [PATCH 133/174] Fixed rare worst-case out-of-bounds access in extmatch algorithm --- src/extmatch.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/extmatch.c b/src/extmatch.c index 5673191d..e6c75fc0 100644 --- a/src/extmatch.c +++ b/src/extmatch.c @@ -271,7 +271,7 @@ static inline size_t max_length(size_t len) { } int extmatch(const char *pattern, const char *string, const char **errmsg) { - char regex[max_length(strlen(pattern))]; + char regex[max_length(strlen(pattern)) + 1]; if (transform(pattern, regex, errmsg) != -1) { int erroffset; pcre *preg = pcre_compile(regex, 0, errmsg, &erroffset, NULL); From 099e30a4a5e8c2f38929b9e0bd14a7004b947b0f Mon Sep 17 00:00:00 2001 From: Snaipe Date: Wed, 9 Sep 2015 03:07:14 +0200 Subject: [PATCH 134/174] Prevent bumpversion from creating a commit --- .bumpversion.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.bumpversion.cfg b/.bumpversion.cfg index a3c3c426..77c74087 100644 --- a/.bumpversion.cfg +++ b/.bumpversion.cfg @@ -1,6 +1,6 @@ [bumpversion] current_version = 1.3.1 -commit = True +commit = False [bumpversion:file:CMakeLists.txt] From e6138cd8601cc03e96731df561884130bd8f0d3a Mon Sep 17 00:00:00 2001 From: Snaipe Date: Wed, 9 Sep 2015 03:07:43 +0200 Subject: [PATCH 135/174] Updated line numbers in pot files --- po/fr.po | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/po/fr.po b/po/fr.po index c7e25add..38453318 100644 --- a/po/fr.po +++ b/po/fr.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: criterion 1.0.0\n" "Report-Msgid-Bugs-To: franklinmathieu+criterion@gmail.com\n" -"POT-Creation-Date: 2015-09-03 18:58+0200\n" +"POT-Creation-Date: 2015-09-09 02:59+0200\n" "PO-Revision-Date: 2015-04-03 17:58+0200\n" "Last-Translator: \n" "Language-Team: French\n" @@ -18,60 +18,60 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n" -#: src/log/normal.c:51 +#: src/log/normal.c:54 #, c-format msgid "Criterion v%s\n" msgstr "Criterion v%s\n" -#: src/log/normal.c:52 +#: src/log/normal.c:55 #, c-format msgid " %s\n" msgstr " %s\n" -#: src/log/normal.c:55 src/log/normal.c:57 +#: src/log/normal.c:58 src/log/normal.c:60 #, c-format msgid "%1$s::%2$s\n" msgstr "%1$s::%2$s\n" -#: src/log/normal.c:56 +#: src/log/normal.c:59 #, 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:58 +#: src/log/normal.c:61 #, 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:59 +#: src/log/normal.c:62 #, 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:60 +#: src/log/normal.c:63 #, 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:61 +#: src/log/normal.c:64 #, 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:62 +#: src/log/normal.c:65 #, 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:66 #, 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:67 #, fuzzy, c-format msgid "" "%1$sWarning! The test `%2$s::%3$s` crashed during its setup or teardown." @@ -80,7 +80,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:68 #, fuzzy, c-format msgid "" "%1$sWarning! The test `%2$s::%3$s` exited during its setup or teardown.%4$s\n" @@ -88,14 +88,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:69 #, 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:71 #, c-format msgid "" "%1$sSynthesis: Tested: %2$s%3$lu%4$s | Passing: %5$s%6$lu%7$s | Failing: %8$s" From 151824d96e024395dd850dbb626bd60c6d68748f Mon Sep 17 00:00:00 2001 From: Snaipe Date: Wed, 9 Sep 2015 03:36:41 +0200 Subject: [PATCH 136/174] Added missing headers in install rule --- CMakeLists.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 37e02d36..8165f2e6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -125,6 +125,8 @@ set(INTERFACE_FILES include/criterion/stats.h include/criterion/theories.h include/criterion/asprintf-compat.h + include/criterion/designated-initializer-compat.h + include/criterion/preprocess.h ) # Generate the configure file From e1122855d9b1dbeb23e8110071c463448fd05e2e Mon Sep 17 00:00:00 2001 From: Snaipe Date: Wed, 9 Sep 2015 04:25:19 +0200 Subject: [PATCH 137/174] Added gitter chat room & refactored a bit the readme [ci skip] --- README.md | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index b4e692b8..27863f0d 100644 --- a/README.md +++ b/README.md @@ -45,12 +45,14 @@ the user would have with other frameworks: If you have a different platform, you can still [build the library from source](http://criterion.readthedocs.org/en/latest/setup.html#installation) -## Documentation +## Developer Resources + +### Documentation An online documentation is available on [ReadTheDocs][online-docs] ([PDF][pdf-docs] | [Zip][zip-docs] | [Epub][epub-docs]) -## Samples +### Samples Sample tests can be found in the [sample directory][samples]. @@ -61,6 +63,10 @@ Sample tests can be found in the [sample directory][samples]. * [Tests with signals][sample-signal] * [Using report hooks][sample-report] +### 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) + ## F.A.Q. **Q. What's wrong with other C test frameworks?** From 2d7456fd762f950519aecf805671b03b8830481e Mon Sep 17 00:00:00 2001 From: Snaipe Date: Wed, 9 Sep 2015 16:20:49 +0200 Subject: [PATCH 138/174] Prevent optimizations from zero-summing the wait condition on forked processes on windows --- src/posix-compat.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/posix-compat.c b/src/posix-compat.c index cebca75c..291a727c 100644 --- a/src/posix-compat.c +++ b/src/posix-compat.c @@ -91,7 +91,7 @@ struct full_context { struct criterion_test_extra_data suite_data; f_worker_func func; struct pipe_handle pipe; - int resumed; + volatile int resumed; }; static TCHAR g_mapping_name[] = TEXT("WinCriterionWorker"); From eb80cb914aee58053518fef336736038d30eeee8 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Wed, 9 Sep 2015 17:12:42 +0200 Subject: [PATCH 139/174] Gave the gitignore some love. --- .gitignore | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/.gitignore b/.gitignore index fdaf4999..e28ebbfa 100644 --- a/.gitignore +++ b/.gitignore @@ -4,13 +4,18 @@ !.gitignore !.bumpversion.cfg !.ci/* +!.cmake/* + +!dev/* +!doc/* !*.c !*.cc !*.h !*.rst -!samples/tests/*.sh !*.po +!*.in +!samples/tests/*.sh !samples/*.expected !LICENSE @@ -19,11 +24,10 @@ CMakeFiles/ !CMakeLists.txt -!.cmake/* -!src/config.h.in src/config.h - build + *~ *.swp +.*.swp From e5ec792907dee2d14f5eac300bc32b978a712370 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Wed, 9 Sep 2015 17:14:45 +0200 Subject: [PATCH 140/174] Added find module for criterion --- README.md | 6 ++++++ dev/FindCriterion.cmake | 27 +++++++++++++++++++++++++++ 2 files changed, 33 insertions(+) create mode 100644 dev/FindCriterion.cmake diff --git a/README.md b/README.md index 27863f0d..a1b09629 100644 --- a/README.md +++ b/README.md @@ -67,6 +67,10 @@ Sample tests can be found in the [sample directory][samples]. 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) +### Misc + +* [CMake find module for Criterion][find-module] + ## F.A.Q. **Q. What's wrong with other C test frameworks?** @@ -98,3 +102,5 @@ Logo done by [Greehm](http://www.cargocollective.com/pbouigue) [sample-fixtures]: ./samples/fixtures.c [sample-signal]: ./samples/signal.c [sample-report]: ./samples/report.c + +[find-module]: ./dev/FindCriterion.cmake diff --git a/dev/FindCriterion.cmake b/dev/FindCriterion.cmake new file mode 100644 index 00000000..1ca96d90 --- /dev/null +++ b/dev/FindCriterion.cmake @@ -0,0 +1,27 @@ +# This file is licensed under the WTFPL version 2 -- you can see the full +# license over at http://www.wtfpl.net/txt/copying/ +# +# - Try to find Criterion +# +# Once done this will define +# CRITERION_FOUND - System has LibXml2 +# CRITERION_INCLUDE_DIRS - The LibXml2 include directories +# CRITERION_LIBRARIES - The libraries needed to use LibXml2 + +find_package(PkgConfig) + +find_path(CRITERION_INCLUDE_DIR criterion/criterion.h + PATH_SUFFIXES criterion) + +find_library(CRITERION_LIBRARY NAMES criterion libcriterion) + +set(CRITERION_LIBRARIES ${CRITERION_LIBRARY}) +set(CRITERION_INCLUDE_DIRS ${CRITERION_INCLUDE_DIR}) + +include(FindPackageHandleStandardArgs) +# handle the QUIETLY and REQUIRED arguments and set CRITERION_FOUND to TRUE +# if all listed variables are TRUE +find_package_handle_standard_args(LibXml2 DEFAULT_MSG + CRITERION_LIBRARY CRITERION_INCLUDE_DIR) + +mark_as_advanced(CRITERION_INCLUDE_DIR CRITERION_LIBRARY) From 343678a02015c7f47d18cb49396bf889463d11ef Mon Sep 17 00:00:00 2001 From: Snaipe Date: Wed, 9 Sep 2015 19:19:58 +0200 Subject: [PATCH 141/174] Removed samples building from 'all' target --- .travis.yml | 1 + CMakeLists.txt | 3 ++- appveyor.yml | 1 + samples/CMakeLists.txt | 6 +++++- test/CMakeLists.txt | 8 +++++--- 5 files changed, 14 insertions(+), 5 deletions(-) diff --git a/.travis.yml b/.travis.yml index 25cd6d28..dd3282b9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -27,6 +27,7 @@ script: - cd build - cmake -DCOVERALLS=ON -DCMAKE_BUILD_TYPE=Debug -DCMAKE_PREFIX_PATH=$HOME -DCMAKE_INSTALL_PREFIX=criterion-${TRAVIS_TAG} .. - make +- make criterion_tests - make test after_success: - make coveralls diff --git a/CMakeLists.txt b/CMakeLists.txt index 8165f2e6..f82d4fec 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -167,7 +167,8 @@ install(TARGETS criterion ARCHIVE DESTINATION lib ) +add_custom_target(criterion_tests) + enable_testing() add_subdirectory(samples) add_subdirectory(test) - diff --git a/appveyor.yml b/appveyor.yml index 96d4291f..66c09d8a 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -52,6 +52,7 @@ before_deploy: Push-AppveyorArtifact "../$archive.tar.bz2" test_script: + - cmake --build . --target criterion_tests - ps: try { ctest } catch { type Testing/Temporary/LastTest.log } #after_test: diff --git a/samples/CMakeLists.txt b/samples/CMakeLists.txt index 1dfbacaf..038f8c2a 100644 --- a/samples/CMakeLists.txt +++ b/samples/CMakeLists.txt @@ -40,9 +40,13 @@ if (HAVE_PCRE) set(SCRIPTS ${SCRIPTS} pattern) endif () +add_custom_target(criterion_samples) +add_dependencies(criterion_tests criterion_samples) + macro(add_samples DIR_ SAMPLES_) foreach(sample ${SAMPLES_}) - add_executable(${sample}.bin ${sample}) + add_executable(${sample}.bin EXCLUDE_FROM_ALL ${sample}) + add_dependencies(criterion_samples ${sample}.bin) target_link_libraries(${sample}.bin criterion) add_test(${sample} ${sample}.bin) set_property(TEST ${sample} PROPERTY diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 2a575a50..d9122f24 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -8,7 +8,9 @@ set(TEST_SOURCES ordered-set.c ) -add_executable(test_criterion ${TEST_SOURCES}) -target_link_libraries(test_criterion criterion) +add_executable(criterion_unit_tests EXCLUDE_FROM_ALL ${TEST_SOURCES}) +target_link_libraries(criterion_unit_tests criterion) -add_test(test_criterion test_criterion) +add_dependencies(criterion_tests criterion_unit_tests) + +add_test(criterion_unit_tests criterion_unit_tests) From e2a3a51e3c3d9faef6eed29e947d0339feb4b771 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Thu, 10 Sep 2015 03:40:50 +0200 Subject: [PATCH 142/174] [Issue #37] Added assert message localization & french translation --- include/criterion/assert.h | 107 ++++++++++++++++++++++++------------- po/POTFILES.in | 1 + po/fr.po | 64 ++++++++++++++++------ src/i18n.c | 22 ++++++++ src/i18n.h | 4 ++ src/log/normal.c | 4 -- 6 files changed, 146 insertions(+), 56 deletions(-) diff --git a/include/criterion/assert.h b/include/criterion/assert.h index 9a42e55c..62c578c8 100644 --- a/include/criterion/assert.h +++ b/include/criterion/assert.h @@ -53,6 +53,22 @@ struct criterion_assert_args { #endif }; +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, +}; + +CR_BEGIN_C_API + +CR_API char *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__ @@ -63,16 +79,26 @@ struct criterion_assert_args { # define CR_STDN # endif +# define CR_TRANSLATE_DEF_MSG__(Arg) \ + CR_EXPAND Arg + +# define CR_TRANSLATE_DEF_MSG_(...) \ + CR_EXPAND(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 { \ - const char *default_msg = "" CR_VA_HEAD(__VA_ARGS__); \ + char *def_msg = CR_EXPAND(CR_TRANSLATE_DEF_MSG_(__VA_ARGS__)); \ char *formatted_msg = NULL; \ - int msglen = cr_asprintf(&formatted_msg, "" CR_VA_TAIL(__VA_ARGS__)); \ + int msglen = cr_asprintf(&formatted_msg, \ + "" CR_VA_TAIL(CR_VA_TAIL(__VA_ARGS__))); \ MsgVar = formatted_msg && *formatted_msg ? \ - formatted_msg : default_msg; \ + formatted_msg : def_msg; \ \ if (!formatted_msg || !*formatted_msg) \ - msglen = strlen(default_msg); \ + msglen = strlen(def_msg); \ \ BufSize = sizeof(struct criterion_assert_stats) \ + sizeof (size_t) + msglen + 1; \ @@ -84,7 +110,7 @@ struct criterion_assert_args { *((size_t*) buf) = msglen + 1; \ buf += sizeof (size_t); \ CR_STDN strcpy(buf, MsgVar); \ - CR_STDN free(formatted_msg); \ + CR_STDN free(MsgVar); \ } while (0)) # define CR_FAIL_ABORT_ criterion_abort_test @@ -100,7 +126,7 @@ struct criterion_assert_args { do { \ bool passed = !!(Condition); \ \ - const char *msg = NULL; \ + char *msg = NULL; \ size_t bufsize; \ \ struct criterion_assert_stats *stat; \ @@ -123,7 +149,8 @@ struct criterion_assert_args { Fail, \ 0, \ dummy, \ - "The conditions for this assertion were not met.", \ + CRITERION_ASSERT_MSG_FAIL, \ + (), \ __VA_ARGS__ \ )) @@ -135,7 +162,8 @@ struct criterion_assert_args { CR_FAIL_ABORT_, \ CR_VA_HEAD(__VA_ARGS__), \ dummy, \ - "The expression " CR_STR(CR_VA_HEAD(__VA_ARGS__)) " is false.", \ + CRITERION_ASSERT_MSG_EXPR_FALSE, \ + (CR_STR(CR_VA_HEAD(__VA_ARGS__))), \ CR_VA_TAIL(__VA_ARGS__) \ )) @@ -144,7 +172,8 @@ struct criterion_assert_args { CR_FAIL_CONTINUES_, \ CR_VA_HEAD(__VA_ARGS__), \ dummy, \ - "The expression " CR_STR(CR_VA_HEAD(__VA_ARGS__)) " is false.", \ + CRITERION_ASSERT_MSG_EXPR_FALSE, \ + (CR_STR(CR_VA_HEAD(__VA_ARGS__))), \ CR_VA_TAIL(__VA_ARGS__) \ )) @@ -153,7 +182,8 @@ struct criterion_assert_args { CR_FAIL_ABORT_, \ !(CR_VA_HEAD(__VA_ARGS__)), \ dummy, \ - "The expression " CR_STR(!(CR_VA_HEAD(__VA_ARGS__))) " is false.", \ + CRITERION_ASSERT_MSG_EXPR_FALSE, \ + (CR_STR(!(CR_VA_HEAD(__VA_ARGS__)))), \ CR_VA_TAIL(__VA_ARGS__) \ )) @@ -162,7 +192,8 @@ struct criterion_assert_args { CR_FAIL_CONTINUES_, \ !(CR_VA_HEAD(__VA_ARGS__)), \ dummy, \ - "The expression " CR_STR(!(CR_VA_HEAD(__VA_ARGS__))) " is false.", \ + CRITERION_ASSERT_MSG_EXPR_FALSE, \ + (CR_STR(!(CR_VA_HEAD(__VA_ARGS__)))), \ CR_VA_TAIL(__VA_ARGS__) \ )) @@ -173,7 +204,8 @@ struct criterion_assert_args { Fail, \ (Actual) Op (Expected), \ dummy, \ - "The expression " CR_STR((Actual) Op (Expected)) " is false.", \ + CRITERION_ASSERT_MSG_EXPR_FALSE, \ + (CR_STR((Actual) Op (Expected))), \ __VA_ARGS__ \ )) @@ -206,29 +238,30 @@ struct criterion_assert_args { // Common unary assertions -# define cr_assert_null_op_(Fail, Op, Not, Value, ...) \ +# define cr_assert_null_op_(Fail, Op, Msg, Value, ...) \ CR_EXPAND(cr_assert_impl( \ Fail, \ (Value) Op NULL, \ dummy, \ - CR_STR(Value) " is" Not " null.", \ + Msg, \ + (CR_STR(Value)), \ __VA_ARGS__ \ )) -# define cr_assert_null_op_va_(Fail, Op, Not, ...) \ +# define cr_assert_null_op_va_(Fail, Op, Msg, ...) \ CR_EXPAND(cr_assert_null_op_( \ Fail, \ Op, \ - Not, \ + 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_, ==, " not", __VA_ARGS__)) -# define cr_expect_null(...) CR_EXPAND(cr_assert_null_op_va_(CR_FAIL_CONTINUES_, ==, " not", __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_, !=, "", __VA_ARGS__)) -# define cr_expect_not_null(...) CR_EXPAND(cr_assert_null_op_va_(CR_FAIL_CONTINUES_, !=, "", __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 @@ -243,7 +276,8 @@ struct criterion_assert_args { Fail, \ Op(Actual, Expected, Epsilon), \ dummy, \ - "The expression " CR_STR(Op(Actual, Expected, Epsilon)) " is false.", \ + CRITERION_ASSERT_MSG_EXPR_FALSE, \ + (CR_STR(Op(Actual, Expected, Epsilon))), \ __VA_ARGS__ \ )) @@ -265,37 +299,38 @@ struct criterion_assert_args { // String assertions -# define cr_assert_str_op_empty_(Fail, Op, Not, Value, ...) \ +# define cr_assert_str_op_empty_(Fail, Op, Msg, Value, ...) \ CR_EXPAND(cr_assert_impl( \ Fail, \ (Value)[0] Op '\0', \ dummy, \ - CR_STR(Value) " is" Not " empty.", \ + Msg, \ + (CR_STR(Value)), \ __VA_ARGS__ \ )) -# define cr_assert_str_op_empty_va_(Fail, Op, Not, ...) \ +# define cr_assert_str_op_empty_va_(Fail, Op, Msg, ...) \ CR_EXPAND(cr_assert_str_op_empty_( \ Fail, \ Op, \ - Not, \ + 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_, ==, " not", __VA_ARGS__)) -# define cr_expect_str_empty(...) CR_EXPAND(cr_assert_str_op_empty_va_(CR_FAIL_CONTINUES_, ==, " not", __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_, !=, "", __VA_ARGS__)) -# define cr_expect_str_not_empty(...) CR_EXPAND(cr_assert_str_op_empty_va_(CR_FAIL_CONTINUES_, !=, "", __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, \ - "The expression (as strings) " \ - CR_STR((Actual) Op (Expected)) " is false", \ + CRITERION_ASSERT_MSG_EXPR_AS_STRINGS_FALSE, \ + (CR_STR((Actual) Op (Expected))), \ __VA_ARGS__ \ )) @@ -333,9 +368,8 @@ struct criterion_assert_args { Fail, \ CR_STDN memcmp((Actual), (Expected), (Size)) Op 0, \ dummy, \ - "The expression " \ - CR_STR((Actual)[0 .. Size] Op (Expected)[0 .. Size]) \ - "is false.", \ + CRITERION_ASSERT_MSG_EXPR_FALSE, \ + (CR_STR((Actual)[0 .. Size] Op (Expected)[0 .. Size])), \ __VA_ARGS__ \ )) @@ -379,9 +413,8 @@ struct criterion_assert_args { Fail, \ order Op 0, \ dummy, \ - "The expression " \ - CR_STR((Actual)[0 .. Size] Op (Expected)[0 .. Size]) \ - " is false.", \ + CRITERION_ASSERT_MSG_EXPR_FALSE, \ + (CR_STR((Actual)[0 .. Size] Op (Expected)[0 .. Size])), \ __VA_ARGS__ \ )); \ } while (0) diff --git a/po/POTFILES.in b/po/POTFILES.in index d9d2b168..e93e6cdf 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -1,2 +1,3 @@ # List of source files which contain translatable strings. src/log/normal.c +src/i18n.c diff --git a/po/fr.po b/po/fr.po index 38453318..8e0b48e5 100644 --- a/po/fr.po +++ b/po/fr.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: criterion 1.0.0\n" "Report-Msgid-Bugs-To: franklinmathieu+criterion@gmail.com\n" -"POT-Creation-Date: 2015-09-09 02:59+0200\n" +"POT-Creation-Date: 2015-09-10 03:35+0200\n" "PO-Revision-Date: 2015-04-03 17:58+0200\n" "Last-Translator: \n" "Language-Team: French\n" @@ -18,60 +18,60 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n" -#: src/log/normal.c:54 +#: src/log/normal.c:50 #, c-format msgid "Criterion v%s\n" msgstr "Criterion v%s\n" -#: src/log/normal.c:55 +#: src/log/normal.c:51 #, c-format msgid " %s\n" msgstr " %s\n" -#: src/log/normal.c:58 src/log/normal.c:60 +#: src/log/normal.c:54 src/log/normal.c:56 #, c-format msgid "%1$s::%2$s\n" msgstr "%1$s::%2$s\n" -#: src/log/normal.c:59 +#: src/log/normal.c:55 #, 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:61 +#: src/log/normal.c:57 #, 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:62 +#: src/log/normal.c:58 #, 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:63 +#: src/log/normal.c:59 #, 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:64 +#: src/log/normal.c:60 #, 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:65 +#: src/log/normal.c:61 #, 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:66 +#: src/log/normal.c:62 #, c-format msgid "%1$s::%2$s: CRASH!\n" msgstr "%1$s::%2$s: PLANTAGE!\n" -#: src/log/normal.c:67 +#: src/log/normal.c:63 #, fuzzy, c-format msgid "" "%1$sWarning! The test `%2$s::%3$s` crashed during its setup or teardown." @@ -80,7 +80,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:68 +#: src/log/normal.c:64 #, fuzzy, c-format msgid "" "%1$sWarning! The test `%2$s::%3$s` exited during its setup or teardown.%4$s\n" @@ -88,14 +88,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:69 +#: src/log/normal.c:65 #, 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:71 +#: src/log/normal.c:67 #, c-format msgid "" "%1$sSynthesis: Tested: %2$s%3$lu%4$s | Passing: %5$s%6$lu%7$s | Failing: %8$s" @@ -103,3 +103,37 @@ msgid "" 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/i18n.c:13 +msgid "The conditions for this assertion were not met." +msgstr "Les conditions de cette assertions n'ont pas été remplies." + +#: src/i18n.c:14 +#, c-format +msgid "The expression %s is false." +msgstr "L'expression %s est fausse." + +#: src/i18n.c:15 +#, c-format +msgid "The expression (as strings) %s is false." +msgstr "L'expression (en tant que chaînes de caractères) %s est fausse." + +#: src/i18n.c:16 +#, c-format +msgid "%s is null." +msgstr "%s est nul." + +#: src/i18n.c:17 +#, c-format +msgid "%s is not null." +msgstr "%s n'est pas nul." + +#: src/i18n.c:18 +#, c-format +msgid "%s is empty." +msgstr "%s est vide." + +#: src/i18n.c:19 +#, c-format +msgid "%s is not empty." +msgstr "%s n'est pas vide." diff --git a/src/i18n.c b/src/i18n.c index 7a7c51bb..b6003993 100644 --- a/src/i18n.c +++ b/src/i18n.c @@ -1,7 +1,29 @@ #include "i18n.h" +#include "criterion/assert.h" +#include "criterion/asprintf-compat.h" void init_i18n(void) { #if ENABLE_NLS bindtextdomain (PACKAGE, LOCALEDIR); #endif } + +char *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."), + [CRITERION_ASSERT_MSG_EXPR_AS_STRINGS_FALSE] = N_("The expression (as strings) %s is false."), + [CRITERION_ASSERT_MSG_IS_NULL] = N_("%s is null."), + [CRITERION_ASSERT_MSG_IS_NOT_NULL] = N_("%s is not null."), + [CRITERION_ASSERT_MSG_IS_EMPTY] = N_("%s is empty."), + [CRITERION_ASSERT_MSG_IS_NOT_EMPTY] = N_("%s is not empty."), + }; + + va_list vl; + va_start(vl, msg_index); + char *out; + cr_vasprintf(&out, _(messages[msg_index]), vl); + va_end(vl); + + return out; +} diff --git a/src/i18n.h b/src/i18n.h index 2657c1e9..827dc0a2 100644 --- a/src/i18n.h +++ b/src/i18n.h @@ -13,6 +13,10 @@ dngettext(PACKAGE, String, Plural, (Quantity)) # endif +// Used to mark string for gettext +# define N_(Str) Str +# define N_s(Str, Pl) {Str, Pl} + void init_i18n(void); #endif /* !I18N_H_ */ diff --git a/src/log/normal.c b/src/log/normal.c index dedcd5e7..fc5c7f0c 100644 --- a/src/log/normal.c +++ b/src/log/normal.c @@ -47,10 +47,6 @@ typedef const char *const msg_t; -// Used to mark string for gettext -# define N_(Str) Str -# define N_s(Str, Pl) {Str, Pl} - static msg_t msg_pre_all = N_("Criterion v%s\n"); static msg_t msg_desc = N_(" %s\n"); From 7038b2dcb5dfd0c59c9d764cdbf7bf02cfdee917 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Thu, 10 Sep 2015 05:32:26 +0200 Subject: [PATCH 143/174] Fixed typo in french translation --- po/fr.po | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/po/fr.po b/po/fr.po index 8e0b48e5..79c850db 100644 --- a/po/fr.po +++ b/po/fr.po @@ -106,7 +106,7 @@ msgstr "" #: src/i18n.c:13 msgid "The conditions for this assertion were not met." -msgstr "Les conditions de cette assertions n'ont pas été remplies." +msgstr "Les conditions de cette assertion n'ont pas été remplies." #: src/i18n.c:14 #, c-format From 53c9edc23eaedcab3b9b730b452c99809c945aac Mon Sep 17 00:00:00 2001 From: Snaipe Date: Thu, 10 Sep 2015 05:33:35 +0200 Subject: [PATCH 144/174] Added redirection functions --- include/criterion/redirect.h | 41 +++++++++++ src/posix-compat.c | 130 +++++++++++++++++++++++++++++++---- src/posix-compat.h | 4 +- src/process.c | 4 +- 4 files changed, 162 insertions(+), 17 deletions(-) create mode 100644 include/criterion/redirect.h diff --git a/include/criterion/redirect.h b/include/criterion/redirect.h new file mode 100644 index 00000000..bb5bc6c8 --- /dev/null +++ b/include/criterion/redirect.h @@ -0,0 +1,41 @@ +/* + * 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_REDIRECT_H_ +# define CRITERION_REDIRECT_H_ + +# include "common.h" + +CR_BEGIN_C_API + +CR_API void cr_redirect_stdout(void); +CR_API void cr_redirect_stderr(void); +CR_API void cr_redirect_stdin(void); + +CR_API FILE* cr_get_redirected_stdout(void); +CR_API FILE* cr_get_redirected_stderr(void); +CR_API FILE* cr_get_redirected_stdin(void); + +CR_END_C_API + +#endif /* !CRITERION_REDIRECT_H_ */ diff --git a/src/posix-compat.c b/src/posix-compat.c index 291a727c..d7894b77 100644 --- a/src/posix-compat.c +++ b/src/posix-compat.c @@ -24,6 +24,7 @@ #include #include "posix-compat.h" #include "process.h" +#include "criterion/assert.h" #ifdef VANILLA_WIN32 # define VC_EXTRALEAN @@ -262,15 +263,17 @@ void wait_process(s_proc_handle *handle, int *status) { #endif } -FILE *pipe_in(s_pipe_handle *p) { +FILE *pipe_in(s_pipe_handle *p, int do_close) { #ifdef VANILLA_WIN32 - CloseHandle(p->fhs[1]); + if (do_close) + CloseHandle(p->fhs[1]); int fd = _open_osfhandle((intptr_t) p->fhs[0], _O_RDONLY); if (fd == -1) return NULL; FILE *in = _fdopen(fd, "r"); #else - close(p->fds[1]); + if (do_close) + close(p->fds[1]); FILE *in = fdopen(p->fds[0], "r"); #endif if (!in) @@ -280,15 +283,17 @@ FILE *pipe_in(s_pipe_handle *p) { return in; } -FILE *pipe_out(s_pipe_handle *p) { +FILE *pipe_out(s_pipe_handle *p, int do_close) { #ifdef VANILLA_WIN32 - CloseHandle(p->fhs[0]); + if (do_close) + CloseHandle(p->fhs[0]); int fd = _open_osfhandle((intptr_t) p->fhs[1], _O_WRONLY); if (fd == -1) return NULL; FILE *out = _fdopen(fd, "w"); #else - close(p->fds[0]); + if (do_close) + close(p->fds[0]); FILE *out = fdopen(p->fds[1], "w"); #endif if (!out) @@ -298,8 +303,7 @@ FILE *pipe_out(s_pipe_handle *p) { return out; } -s_pipe_handle *stdpipe() { - s_pipe_handle *handle = smalloc(sizeof (s_pipe_handle)); +int stdpipe_stack(s_pipe_handle *out) { #ifdef VANILLA_WIN32 HANDLE fhs[2]; SECURITY_ATTRIBUTES attr = { @@ -307,16 +311,22 @@ s_pipe_handle *stdpipe() { .bInheritHandle = TRUE }; if (!CreatePipe(fhs, fhs + 1, &attr, 0)) - return NULL; - *handle = (s_pipe_handle) {{ fhs[0], fhs[1] }}; - return handle; + return -1; + *out = (s_pipe_handle) {{ fhs[0], fhs[1] }}; #else int fds[2] = { -1, -1 }; if (pipe(fds) == -1) + return -1; + *out = (s_pipe_handle) {{ fds[0], fds[1] }}; +#endif + return 0; +} + +s_pipe_handle *stdpipe() { + s_pipe_handle *handle = smalloc(sizeof (s_pipe_handle)); + if (stdpipe_stack(handle) < 0) return NULL; - *handle = (s_pipe_handle) {{ fds[0], fds[1] }}; return handle; -#endif } s_proc_handle *get_current_process() { @@ -405,3 +415,97 @@ const char *basename_compat(const char *str) { start = c + 1; return start; } + +#ifdef VANILLA_WIN32 +typedef DWORD cr_std_fd; +#else +typedef int cr_std_fd; +#endif + +static s_pipe_handle stdout_redir; +static s_pipe_handle stderr_redir; +static s_pipe_handle stdin_redir; + +enum criterion_std_fd { + CR_STDIN, + CR_STDOUT, + CR_STDERR +}; + +enum criterion_pipe_end { + PIPE_READ = 0, + PIPE_WRITE = 1, +}; + +cr_std_fd get_std_fd(int fd_kind) { + static int kinds[] = { +#ifdef VANILLA_WIN32 + [CR_STDIN] = STD_INPUT_HANDLE, + [CR_STDOUT] = STD_OUTPUT_HANDLE, + [CR_STDERR] = STD_ERROR_HANDLE, +#else + [CR_STDIN] = STDIN_FILENO, + [CR_STDOUT] = STDOUT_FILENO, + [CR_STDERR] = STDERR_FILENO, +#endif + }; + + return kinds[fd_kind]; +} + +void cr_redirect(int fd_kind, s_pipe_handle *pipe, int fd_index) { + if (stdpipe_stack(pipe) < 0) + cr_assert_fail("Could not redirect standard file descriptor."); + + cr_std_fd fd = get_std_fd(fd_kind); +#ifdef VANILLA_WIN32 + CloseHandle(GetStdHandle(fd)); + SetStdHandle(fd, pipe->fds[fd_index]); +#else + close(fd); + dup2(fd, pipe->fds[fd_index]); + close(pipe->fds[fd_index]); +#endif +} + +void cr_redirect_stdout(void) { + cr_redirect(CR_STDOUT, &stdout_redir, PIPE_WRITE); +} + +void cr_redirect_stderr(void) { + cr_redirect(CR_STDERR, &stderr_redir, PIPE_WRITE); +} + +void cr_redirect_stdin(void) { + cr_redirect(CR_STDIN, &stdin_redir, PIPE_READ); +} + +FILE* cr_get_redirected_stdout(void) { + static FILE *f; + if (!f) { + f = pipe_in(&stdout_redir, 0); + if (!f) + cr_assert_fail("Could not get redirected stdout read end."); + } + return f; +} + +FILE* cr_get_redirected_stderr(void) { + static FILE *f; + if (!f) { + f = pipe_in(&stderr_redir, 0); + if (!f) + cr_assert_fail("Could not get redirected stderr read end."); + } + return f; +} + +FILE* cr_get_redirected_stdin(void) { + static FILE *f; + if (!f) { + f = pipe_out(&stdin_redir, 0); + if (!f) + cr_assert_fail("Could not get redirected stdin write end."); + } + return f; +} diff --git a/src/posix-compat.h b/src/posix-compat.h index 9f938dbe..8ad38f35 100644 --- a/src/posix-compat.h +++ b/src/posix-compat.h @@ -67,8 +67,8 @@ extern struct worker_context g_worker_context; int resume_child(void); s_pipe_handle *stdpipe(); -FILE *pipe_in(s_pipe_handle *p); -FILE *pipe_out(s_pipe_handle *p); +FILE *pipe_in(s_pipe_handle *p, int do_close); +FILE *pipe_out(s_pipe_handle *p, int do_close); s_proc_handle *fork_process(); void wait_process(s_proc_handle *handle, int *status); diff --git a/src/process.c b/src/process.c index 036b790b..dd0a0c71 100644 --- a/src/process.c +++ b/src/process.c @@ -62,7 +62,7 @@ struct event *worker_read_event(struct process *proc) { void run_worker(struct worker_context *ctx) { fclose(stdin); - g_event_pipe = pipe_out(ctx->pipe); + g_event_pipe = pipe_out(ctx->pipe, 1); ctx->func(ctx->test, ctx->suite); fclose(g_event_pipe); @@ -102,7 +102,7 @@ struct process *spawn_test_worker(struct criterion_test *test, .kind = UNIQUE, .dtor = close_process); - *ptr = (struct process) { .proc = proc, .in = pipe_in(pipe) }; + *ptr = (struct process) { .proc = proc, .in = pipe_in(pipe, 1) }; cleanup: sfree(pipe); return ptr; From 3744d67b0c460c78d3b37c6ba2c59ecd1af7983d Mon Sep 17 00:00:00 2001 From: Snaipe Date: Thu, 10 Sep 2015 05:36:03 +0200 Subject: [PATCH 145/174] Fixed typo in cr_redirect in windows-specific code --- src/posix-compat.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/posix-compat.c b/src/posix-compat.c index d7894b77..55a506f9 100644 --- a/src/posix-compat.c +++ b/src/posix-compat.c @@ -460,7 +460,7 @@ void cr_redirect(int fd_kind, s_pipe_handle *pipe, int fd_index) { cr_std_fd fd = get_std_fd(fd_kind); #ifdef VANILLA_WIN32 CloseHandle(GetStdHandle(fd)); - SetStdHandle(fd, pipe->fds[fd_index]); + SetStdHandle(fd, pipe->fhs[fd_index]); #else close(fd); dup2(fd, pipe->fds[fd_index]); From 3dc9d47c0b57ab3317dbf9cb129b008739ae7c34 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Fri, 11 Sep 2015 00:21:31 +0200 Subject: [PATCH 146/174] Added file assertions for redirection --- include/criterion/assert.h | 3 +- include/criterion/preprocess.h | 1 + include/criterion/redirect.h | 41 +++++++++++++- samples/CMakeLists.txt | 1 + src/i18n.c | 6 ++ src/posix-compat.c | 100 +++++++++++++++++++++++++++++++-- src/process.c | 3 +- 7 files changed, 144 insertions(+), 11 deletions(-) diff --git a/include/criterion/assert.h b/include/criterion/assert.h index 62c578c8..6d50a1c9 100644 --- a/include/criterion/assert.h +++ b/include/criterion/assert.h @@ -61,6 +61,7 @@ enum criterion_assert_messages { CRITERION_ASSERT_MSG_IS_NOT_NULL, CRITERION_ASSERT_MSG_IS_EMPTY, CRITERION_ASSERT_MSG_IS_NOT_EMPTY, + CRITERION_ASSERT_MSG_FILE_STR_MATCH, }; CR_BEGIN_C_API @@ -80,7 +81,7 @@ CR_END_C_API # endif # define CR_TRANSLATE_DEF_MSG__(Arg) \ - CR_EXPAND Arg + CR_IDENTITY Arg # define CR_TRANSLATE_DEF_MSG_(...) \ CR_EXPAND(translate_assert_msg( \ diff --git a/include/criterion/preprocess.h b/include/criterion/preprocess.h index 822e0e34..aee370a3 100644 --- a/include/criterion/preprocess.h +++ b/include/criterion/preprocess.h @@ -33,6 +33,7 @@ # endif # define CR_EXPAND(x) x +# define CR_IDENTITY(...) __VA_ARGS__ # define CR_STR(x) CR_EXPAND(CR_STR_(x)) # define CR_STR_(x) #x diff --git a/include/criterion/redirect.h b/include/criterion/redirect.h index bb5bc6c8..cf1efcf5 100644 --- a/include/criterion/redirect.h +++ b/include/criterion/redirect.h @@ -25,6 +25,13 @@ # define CRITERION_REDIRECT_H_ # include "common.h" +# include "assert.h" + +# ifdef __cplusplus +# include +# else +# include +# endif CR_BEGIN_C_API @@ -32,10 +39,38 @@ CR_API void cr_redirect_stdout(void); CR_API void cr_redirect_stderr(void); CR_API void cr_redirect_stdin(void); -CR_API FILE* cr_get_redirected_stdout(void); -CR_API FILE* cr_get_redirected_stderr(void); -CR_API FILE* cr_get_redirected_stdin(void); +CR_API CR_STDN FILE* cr_get_redirected_stdout(void); +CR_API CR_STDN FILE* cr_get_redirected_stderr(void); +CR_API CR_STDN FILE* cr_get_redirected_stdin(void); + +CR_API int cr_file_match_str(CR_STDN FILE* f, const char *str); 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_file_contents_match_str(...) CR_EXPAND(cr_assert_redir_op_va_(CR_FAIL_ABORT_, cr_file_match_str, ==, __VA_ARGS__)) +# define cr_expect_file_contents_match_str(...) CR_EXPAND(cr_assert_redir_op_va_(CR_FAIL_CONTINUES_, cr_file_match_str, ==, __VA_ARGS__)) + +# define cr_assert_file_contents_not_match_str(...) CR_EXPAND(cr_assert_redir_op_va_(CR_FAIL_ABORT_, cr_file_match_str, !=, __VA_ARGS__)) +# define cr_expect_file_contents_not_match_str(...) CR_EXPAND(cr_assert_redir_op_va_(CR_FAIL_CONTINUES_, cr_file_match_str, !=, __VA_ARGS__)) + #endif /* !CRITERION_REDIRECT_H_ */ diff --git a/samples/CMakeLists.txt b/samples/CMakeLists.txt index 038f8c2a..f792c1d0 100644 --- a/samples/CMakeLists.txt +++ b/samples/CMakeLists.txt @@ -15,6 +15,7 @@ set(SAMPLES description.c simple.c theories.c + redirect.c signal.cc report.cc diff --git a/src/i18n.c b/src/i18n.c index b6003993..fb6e7d75 100644 --- a/src/i18n.c +++ b/src/i18n.c @@ -17,6 +17,12 @@ char *translate_assert_msg(int msg_index, ...) { [CRITERION_ASSERT_MSG_IS_NOT_NULL] = N_("%s is not null."), [CRITERION_ASSERT_MSG_IS_EMPTY] = N_("%s is empty."), [CRITERION_ASSERT_MSG_IS_NOT_EMPTY] = N_("%s is not empty."), + +#ifdef ENABLE_NLS + [CRITERION_ASSERT_MSG_FILE_STR_MATCH] = N_("The file contents of %1$s does not match the string \"%2$s\"."), +#else + [CRITERION_ASSERT_MSG_FILE_STR_MATCH] = "The file contents of %s does not match the string \"%s\".", +#endif }; va_list vl; diff --git a/src/posix-compat.c b/src/posix-compat.c index 55a506f9..45cf897c 100644 --- a/src/posix-compat.c +++ b/src/posix-compat.c @@ -453,8 +453,72 @@ cr_std_fd get_std_fd(int fd_kind) { return kinds[fd_kind]; } -void cr_redirect(int fd_kind, s_pipe_handle *pipe, int fd_index) { - if (stdpipe_stack(pipe) < 0) +FILE* get_std_file(int fd_kind) { + switch (fd_kind) { + case CR_STDIN: return stdin; + case CR_STDOUT: return stdout; + case CR_STDERR: return stderr; + } + return NULL; +} + +int make_redirect_pipe(s_pipe_handle *handle, int noblock) { +#ifdef VANILLA_WIN32 + static char pipe_name[256] = {0}; + + HANDLE fhs[2]; + SECURITY_ATTRIBUTES attr = { + .nLength = sizeof (SECURITY_ATTRIBUTES), + .bInheritHandle = TRUE + }; + if (!pipe_name[0]) { + snprintf(pipe_name, sizeof (pipe_name), + "\\\\.\\pipe\\criterion_%d", GetCurrentProcessId()); + } + fhs[0] = CreateNamedPipe(pipe_name, + PIPE_ACCESS_DUPLEX, + PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE + | (noblock ? PIPE_NOWAIT : PIPE_WAIT), + PIPE_UNLIMITED_INSTANCES + 4096 * 4, + 4096 * 4, + 0, + attr); + + if (fds[0] == INVALID_HANDLE_VALUE) + return 0; + + fhs[1] = CreateFile(pipe_name, + GENERIC_READ | GENERIC_WRITE, + 0, + attr, + OPEN_EXISTING, + 0, + NULL); + + if (fds[1] == INVALID_HANDLE_VALUE) { + CloseHandle(fds[0]); + return 0; + } + + *handle = (s_pipe_handle) {{ fhs[0], fhs[1] }}; +#else + int fds[2] = { -1, -1 }; + if (pipe(fds) == -1) + return 0; + + if (noblock) + for (int i = 0; i < 2; ++i) + fcntl(fds[i], F_SETFL, fcntl(fds[i], F_GETFL) | O_NONBLOCK); + + *handle = (s_pipe_handle) {{ fds[0], fds[1] }}; +#endif + return 1; +} + +void cr_redirect(int fd_kind, s_pipe_handle *pipe, int fd_index, int noblock) { + fflush(get_std_file(fd_kind)); + if (make_redirect_pipe(pipe, noblock) < 0) cr_assert_fail("Could not redirect standard file descriptor."); cr_std_fd fd = get_std_fd(fd_kind); @@ -463,21 +527,21 @@ void cr_redirect(int fd_kind, s_pipe_handle *pipe, int fd_index) { SetStdHandle(fd, pipe->fhs[fd_index]); #else close(fd); - dup2(fd, pipe->fds[fd_index]); + dup2(pipe->fds[fd_index], fd); close(pipe->fds[fd_index]); #endif } void cr_redirect_stdout(void) { - cr_redirect(CR_STDOUT, &stdout_redir, PIPE_WRITE); + cr_redirect(CR_STDOUT, &stdout_redir, PIPE_WRITE, 1); } void cr_redirect_stderr(void) { - cr_redirect(CR_STDERR, &stderr_redir, PIPE_WRITE); + cr_redirect(CR_STDERR, &stderr_redir, PIPE_WRITE, 1); } void cr_redirect_stdin(void) { - cr_redirect(CR_STDIN, &stdin_redir, PIPE_READ); + cr_redirect(CR_STDIN, &stdin_redir, PIPE_READ, 0); } FILE* cr_get_redirected_stdout(void) { @@ -509,3 +573,27 @@ FILE* cr_get_redirected_stdin(void) { } return f; } + +int cr_file_match_str(FILE* f, const char *str) { + size_t len = strlen(str); + + fputs(str, stderr); + char buf[512]; + size_t read; + int matches = 0; + while ((read = fread(buf, 1, sizeof (buf), f)) > 0) { + matches = !strncmp(buf, str, read); + if (!matches || read > len) { + matches = 0; + break; + } + + len -= read; + str += read; + } + + // consume the rest of what's available + while (fread(buf, 1, sizeof (buf), f) > 0); + + return matches; +} diff --git a/src/process.c b/src/process.c index dd0a0c71..561665c2 100644 --- a/src/process.c +++ b/src/process.c @@ -27,6 +27,7 @@ #include "criterion/types.h" #include "criterion/options.h" +#include "criterion/redirect.h" #include "process.h" #include "event.h" #include "posix-compat.h" @@ -61,7 +62,7 @@ struct event *worker_read_event(struct process *proc) { } void run_worker(struct worker_context *ctx) { - fclose(stdin); + cr_redirect_stdin(); g_event_pipe = pipe_out(ctx->pipe, 1); ctx->func(ctx->test, ctx->suite); From ec1095c96628bd932be9e4e27ac92251503b6ea5 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Fri, 11 Sep 2015 02:16:54 +0200 Subject: [PATCH 147/174] Added redirect.c sample --- samples/redirect.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 samples/redirect.c diff --git a/samples/redirect.c b/samples/redirect.c new file mode 100644 index 00000000..fdeeb785 --- /dev/null +++ b/samples/redirect.c @@ -0,0 +1,15 @@ +#include +#include + +#include + +Test(redirect, stdout) { + cr_redirect_stdout(); + + fprintf(stdout, "foo"); + fflush(stdout); + + FILE* stdout_in = cr_get_redirected_stdout(); + + cr_assert_file_contents_match_str(stdout_in, "foo"); +} From 9444d4f0a13cc1126854819c3654175a2e53fae5 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Fri, 11 Sep 2015 02:24:10 +0200 Subject: [PATCH 148/174] Fixed windows redirect pipe code --- src/posix-compat.c | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/src/posix-compat.c b/src/posix-compat.c index 45cf897c..f809a1dd 100644 --- a/src/posix-compat.c +++ b/src/posix-compat.c @@ -462,7 +462,7 @@ FILE* get_std_file(int fd_kind) { return NULL; } -int make_redirect_pipe(s_pipe_handle *handle, int noblock) { +int make_redirect_pipe(s_pipe_handle *handle, int id, int noblock) { #ifdef VANILLA_WIN32 static char pipe_name[256] = {0}; @@ -473,36 +473,38 @@ int make_redirect_pipe(s_pipe_handle *handle, int noblock) { }; if (!pipe_name[0]) { snprintf(pipe_name, sizeof (pipe_name), - "\\\\.\\pipe\\criterion_%d", GetCurrentProcessId()); + "\\\\.\\pipe\\criterion_%lu_%d", GetCurrentProcessId(), id); } fhs[0] = CreateNamedPipe(pipe_name, PIPE_ACCESS_DUPLEX, PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | (noblock ? PIPE_NOWAIT : PIPE_WAIT), - PIPE_UNLIMITED_INSTANCES + PIPE_UNLIMITED_INSTANCES, 4096 * 4, 4096 * 4, 0, - attr); + &attr); - if (fds[0] == INVALID_HANDLE_VALUE) + if (fhs[0] == INVALID_HANDLE_VALUE) return 0; fhs[1] = CreateFile(pipe_name, GENERIC_READ | GENERIC_WRITE, 0, - attr, + &attr, OPEN_EXISTING, 0, NULL); - if (fds[1] == INVALID_HANDLE_VALUE) { - CloseHandle(fds[0]); + if (fhs[1] == INVALID_HANDLE_VALUE) { + CloseHandle(fhs[0]); return 0; } *handle = (s_pipe_handle) {{ fhs[0], fhs[1] }}; #else + (void) id; + int fds[2] = { -1, -1 }; if (pipe(fds) == -1) return 0; @@ -518,7 +520,7 @@ int make_redirect_pipe(s_pipe_handle *handle, int noblock) { void cr_redirect(int fd_kind, s_pipe_handle *pipe, int fd_index, int noblock) { fflush(get_std_file(fd_kind)); - if (make_redirect_pipe(pipe, noblock) < 0) + if (make_redirect_pipe(pipe, fd_kind, noblock) < 0) cr_assert_fail("Could not redirect standard file descriptor."); cr_std_fd fd = get_std_fd(fd_kind); From 73255382a385032554ea5fb51d7551e9b98c0bd5 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Fri, 11 Sep 2015 02:34:25 +0200 Subject: [PATCH 149/174] Fixed stdout being macro-substitued in test name --- samples/redirect.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/redirect.c b/samples/redirect.c index fdeeb785..f32c0c8c 100644 --- a/samples/redirect.c +++ b/samples/redirect.c @@ -3,7 +3,7 @@ #include -Test(redirect, stdout) { +Test(redirect, test_stdout) { cr_redirect_stdout(); fprintf(stdout, "foo"); From 2642c420f4f491888f7341f955959e21921f1ea1 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Fri, 11 Sep 2015 02:38:10 +0200 Subject: [PATCH 150/174] Added missing header to posix-compat.c --- src/posix-compat.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/posix-compat.c b/src/posix-compat.c index f809a1dd..85ff1ceb 100644 --- a/src/posix-compat.c +++ b/src/posix-compat.c @@ -25,6 +25,7 @@ #include "posix-compat.h" #include "process.h" #include "criterion/assert.h" +#include "criterion/redirect.h" #ifdef VANILLA_WIN32 # define VC_EXTRALEAN From d1861db6d0fb41c0604d65500e15cc297ced71e7 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Fri, 11 Sep 2015 02:50:17 +0200 Subject: [PATCH 151/174] Removed debug code --- src/posix-compat.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/posix-compat.c b/src/posix-compat.c index 85ff1ceb..b8a88da0 100644 --- a/src/posix-compat.c +++ b/src/posix-compat.c @@ -580,7 +580,6 @@ FILE* cr_get_redirected_stdin(void) { int cr_file_match_str(FILE* f, const char *str) { size_t len = strlen(str); - fputs(str, stderr); char buf[512]; size_t read; int matches = 0; From 1d06689aa044dd91239279e0f8726f7d156a49b0 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Fri, 11 Sep 2015 03:16:50 +0200 Subject: [PATCH 152/174] Enhanced redirect sample --- samples/redirect.c | 48 +++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 45 insertions(+), 3 deletions(-) diff --git a/samples/redirect.c b/samples/redirect.c index f32c0c8c..895eb568 100644 --- a/samples/redirect.c +++ b/samples/redirect.c @@ -2,14 +2,56 @@ #include #include +#include -Test(redirect, test_stdout) { +// Testing stdout/stderr + +void redirect_all_std(void) { cr_redirect_stdout(); + cr_redirect_stderr(); +} + +Test(redirect, test_outputs, .init = redirect_all_std) { + FILE* f_stdout = cr_get_redirected_stdout(); fprintf(stdout, "foo"); fflush(stdout); - FILE* stdout_in = cr_get_redirected_stdout(); + cr_assert_file_contents_match_str(f_stdout, "foo"); + + FILE* f_stderr = cr_get_redirected_stderr(); + + fprintf(stderr, "bar"); + fflush(stderr); + + cr_assert_file_contents_match_str(f_stderr, "bar"); +} + +// Testing general I/O with sample command-line rot13 + +char rot13_char(char c) { + return isalpha(c) ? (c - 'a' + 13) % 26 + 'a' : c; +} + +void rot13_io(void) { + char buf[512]; + + size_t read; + while ((read = fread(buf, 1, sizeof (buf), stdin)) > 0) { + for (size_t i = 0; i < read; ++i) + buf[i] = rot13_char(buf[i]); + fwrite(buf, 1, read, stdout); + } + fflush(stdout); +} + +Test(redirect, rot13, .init = cr_redirect_stdout) { + FILE* f_stdin = cr_get_redirected_stdin(); + fprintf(f_stdin, "the quick brown fox jumps over the lazy dog"); + fclose(f_stdin); + + rot13_io(); - cr_assert_file_contents_match_str(stdout_in, "foo"); + FILE* f_stdout = cr_get_redirected_stdout(); + cr_assert_file_contents_match_str(f_stdout, "gur dhvpx oebja sbk whzcf bire gur ynml qbt"); } From e29d5a13cf73454703828460570b23624aca67fe Mon Sep 17 00:00:00 2001 From: Snaipe Date: Fri, 11 Sep 2015 16:56:40 +0200 Subject: [PATCH 153/174] Added timeout code for tests --- include/criterion/logging.h | 1 + include/criterion/stats.h | 1 + include/criterion/types.h | 1 + po/fr.po | 17 ++++++---- samples/CMakeLists.txt | 1 + samples/timeout.c | 12 +++++++ src/log/normal.c | 10 ++++++ src/log/tap.c | 17 +++++++--- src/posix-compat.c | 5 +-- src/posix-compat.h | 3 ++ src/runner.c | 16 ++++++++++ src/stats.c | 5 +++ src/timer.c | 64 +++++++++++++++++++++++++++++++++++++ src/timer.h | 2 ++ 14 files changed, 140 insertions(+), 15 deletions(-) create mode 100644 samples/timeout.c diff --git a/include/criterion/logging.h b/include/criterion/logging.h index c8c02052..17baf4b5 100644 --- a/include/criterion/logging.h +++ b/include/criterion/logging.h @@ -104,6 +104,7 @@ struct criterion_output_provider { void (*log_pre_test )(struct criterion_test *test); void (*log_assert )(struct criterion_assert_stats *stats); 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_other_crash )(struct criterion_test_stats *stats); void (*log_abnormal_exit)(struct criterion_test_stats *stats); diff --git a/include/criterion/stats.h b/include/criterion/stats.h index 8d6d4ca0..ec80c2ff 100644 --- a/include/criterion/stats.h +++ b/include/criterion/stats.h @@ -44,6 +44,7 @@ struct criterion_test_stats { int signal; int exit_code; float elapsed_time; + bool timed_out; unsigned progress; const char *file; diff --git a/include/criterion/types.h b/include/criterion/types.h index aa05e034..e9e948fd 100644 --- a/include/criterion/types.h +++ b/include/criterion/types.h @@ -44,6 +44,7 @@ struct criterion_test_extra_data { int exit_code; bool disabled; const char *description; + float timeout; void *data; }; diff --git a/po/fr.po b/po/fr.po index 79c850db..0ca50cfe 100644 --- a/po/fr.po +++ b/po/fr.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: criterion 1.0.0\n" "Report-Msgid-Bugs-To: franklinmathieu+criterion@gmail.com\n" -"POT-Creation-Date: 2015-09-10 03:35+0200\n" +"POT-Creation-Date: 2015-09-11 16:47+0200\n" "PO-Revision-Date: 2015-04-03 17:58+0200\n" "Last-Translator: \n" "Language-Team: French\n" @@ -60,18 +60,23 @@ msgstr "" " La théorie %1$s::%2$s a échoué avec les paramètres suivants: (%3$s)\n" #: src/log/normal.c:61 +#, fuzzy, c-format +msgid "%1$s::%2$s: Timed out.\n" +msgstr "%1$s::%2$s: Délai expiré.\n" + +#: src/log/normal.c:62 #, 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:62 +#: src/log/normal.c:63 #, c-format msgid "%1$s::%2$s: CRASH!\n" msgstr "%1$s::%2$s: PLANTAGE!\n" -#: src/log/normal.c:63 +#: src/log/normal.c:64 #, fuzzy, c-format msgid "" "%1$sWarning! The test `%2$s::%3$s` crashed during its setup or teardown." @@ -80,7 +85,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:64 +#: src/log/normal.c:65 #, fuzzy, c-format msgid "" "%1$sWarning! The test `%2$s::%3$s` exited during its setup or teardown.%4$s\n" @@ -88,14 +93,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:65 +#: src/log/normal.c:66 #, 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:67 +#: src/log/normal.c:68 #, c-format msgid "" "%1$sSynthesis: Tested: %2$s%3$lu%4$s | Passing: %5$s%6$lu%7$s | Failing: %8$s" diff --git a/samples/CMakeLists.txt b/samples/CMakeLists.txt index 038f8c2a..00b2e546 100644 --- a/samples/CMakeLists.txt +++ b/samples/CMakeLists.txt @@ -15,6 +15,7 @@ set(SAMPLES description.c simple.c theories.c + timeout.c signal.cc report.cc diff --git a/samples/timeout.c b/samples/timeout.c new file mode 100644 index 00000000..db37bf04 --- /dev/null +++ b/samples/timeout.c @@ -0,0 +1,12 @@ +#include + +#ifdef _WIN32 +# include +# define sleep(x) Sleep(x * 1000) +#else +# include +#endif + +Test(timeout, simple, .timeout = 1.) { + sleep(10); +} diff --git a/src/log/normal.c b/src/log/normal.c index fc5c7f0c..5bae2efc 100644 --- a/src/log/normal.c +++ b/src/log/normal.c @@ -58,6 +58,7 @@ static msg_t msg_post_suite_test = N_("%1$s::%2$s: Test is disabled\n"); static msg_t msg_post_suite_suite = N_("%1$s::%2$s: Suite is disabled\n"); static msg_t msg_assert_fail = N_("%1$s%2$s%3$s:%4$s%5$d%6$s: Assertion failed: %7$s\n"); static msg_t msg_theory_fail = N_(" Theory %1$s::%2$s failed with the following parameters: (%3$s)\n"); +static msg_t msg_test_timeout = N_("%1$s::%2$s: Timed out.\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_other_crash = N_("%1$sWarning! The test `%2$s::%3$s` crashed during its setup or teardown.%4$s\n"); @@ -77,6 +78,7 @@ 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_test_timeout = "%s::%s: timed out.\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_other_crash = "%sWarning! The test `%s::%s` crashed during its setup or teardown.%s\n"; @@ -220,12 +222,20 @@ void normal_log_theory_fail(struct criterion_theory_stats *stats) { stats->formatted_args); } +void normal_log_test_timeout(UNUSED struct criterion_test_stats *stats) { + criterion_pimportant(CRITERION_PREFIX_FAIL, + _(msg_test_timeout), + stats->test->category, + stats->test->name); +} + struct criterion_output_provider normal_logging = { .log_pre_all = normal_log_pre_all, .log_pre_init = normal_log_pre_init, .log_pre_suite = normal_log_pre_suite, .log_assert = normal_log_assert, .log_theory_fail = normal_log_theory_fail, + .log_test_timeout = normal_log_test_timeout, .log_test_crash = normal_log_test_crash, .log_other_crash = normal_log_other_crash, .log_abnormal_exit = normal_log_abnormal_exit, diff --git a/src/log/tap.c b/src/log/tap.c index 76937a0e..b3180b51 100644 --- a/src/log/tap.c +++ b/src/log/tap.c @@ -118,10 +118,17 @@ void tap_log_test_crash(struct criterion_test_stats *stats) { stats->progress); } +void tap_log_test_timeout(struct criterion_test_stats *stats) { + criterion_important("not ok - %s::%s timed out\n", + stats->test->category, + stats->test->name); +} + 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_post_test = tap_log_post_test, - .log_post_suite = tap_log_post_suite, + .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, }; diff --git a/src/posix-compat.c b/src/posix-compat.c index 291a727c..28089165 100644 --- a/src/posix-compat.c +++ b/src/posix-compat.c @@ -52,9 +52,6 @@ WriteProcessMemory(Proc, &What, &What, Size, NULL); # include -# ifndef SIGALRM -# define SIGALRM 14 -# endif #else # include @@ -240,7 +237,7 @@ void wait_process(s_proc_handle *handle, int *status) { case STATUS_PRIVILEGED_INSTRUCTION: case STATUS_NONCONTINUABLE_EXCEPTION: sig = SIGILL; break; - case STATUS_TIMEOUT: sig = SIGALRM; break; + case CR_EXCEPTION_TIMEOUT: sig = SIGPROF; break; case STATUS_ACCESS_VIOLATION: case STATUS_DATATYPE_MISALIGNMENT: diff --git a/src/posix-compat.h b/src/posix-compat.h index 9f938dbe..c51ab1bc 100644 --- a/src/posix-compat.h +++ b/src/posix-compat.h @@ -43,6 +43,9 @@ # define WTERMSIG(Status) ((Status) & 0x7F) # define WIFEXITED(Status) (WTERMSIG(Status) == 0) # define WIFSIGNALED(Status) (((signed char) (WTERMSIG(Status) + 1) >> 1) > 0) + +# define SIGPROF 27 +# define CR_EXCEPTION_TIMEOUT 0xC0001042 # else # include # endif diff --git a/src/runner.c b/src/runner.c index 5e078eab..c752d86a 100644 --- a/src/runner.c +++ b/src/runner.c @@ -172,6 +172,11 @@ static void map_tests(struct criterion_test_set *set, static 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)); + 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)(); @@ -274,6 +279,17 @@ static void run_test(struct criterion_global_stats *stats, struct process_status status = wait_proc(proc); if (status.kind == SIGNAL) { + if (status.status == SIGPROF) { + test_stats->timed_out = true; + double elapsed_time = test->data->timeout; + if (elapsed_time == 0 && suite->data) + elapsed_time = suite->data->timeout; + push_event(POST_TEST, .data = &elapsed_time); + push_event(POST_FINI); + log(test_timeout, test_stats); + goto cleanup; + } + if (normal_finish || !test_started) { log(other_crash, test_stats); if (!test_started) { diff --git a/src/stats.c b/src/stats.c index 04723abb..a9dbe95c 100644 --- a/src/stats.c +++ b/src/stats.c @@ -209,15 +209,20 @@ static void push_post_test(s_glob_stats *stats, test->elapsed_time = (float) *data; if (test->failed_asserts > 0 + || test->timed_out || test->signal != test->test->data->signal || test->exit_code != test->test->data->exit_code) { test->failed = 1; + } + + if (test->failed) { ++stats->tests_failed; ++suite->tests_failed; } else { ++stats->tests_passed; ++suite->tests_passed; } + } static void push_test_crash(s_glob_stats *stats, diff --git a/src/timer.c b/src/timer.c index edb181e5..7efb70ce 100644 --- a/src/timer.c +++ b/src/timer.c @@ -1,6 +1,9 @@ #include #include +#include #include "timer.h" +#include "criterion/common.h" +#include "posix-compat.h" #define GIGA 1000000000 @@ -17,6 +20,7 @@ extern __attribute__ ((weak)) int clock_gettime(clockid_t, struct timespec *); #elif defined(__APPLE__) # include # include +# include #elif defined(_WIN32) || defined(__CYGWIN__) # define VC_EXTRALEAN # define WIN32_LEAN_AND_MEAN @@ -81,3 +85,63 @@ int timer_end(double *time, struct timespec_compat *state) { *time = (last.tv_sec - state->tv_sec) + (last.tv_nsec - state->tv_nsec) / (double) GIGA; return 1; } + +#if defined(_WIN32) || defined(__CYGWIN__) +void win_raise_timeout(UNUSED HWND hwnd, + UNUSED UINT uMsg, + UNUSED UINT_PTR idEvent, + UNUSED DWORD dwTime) { + RaiseException(CR_EXCEPTION_TIMEOUT, EXCEPTION_NONCONTINUABLE, 0, NULL); +} +#endif + +#if defined(__APPLE__) +void *wait_and_raise(void *ptr) { + uint64_t *nanos = ptr; + struct timespec elapsed = { + .tv_sec = *nanos / GIGA, + .tv_nsec = *nanos % GIGA, + }; + free(nanos); + if (!nanosleep(&elapsed, NULL)) + raise(SIGPROF); + return NULL; +} +#endif + +int setup_timeout(uint64_t nanos) { +#if defined(__APPLE__) + uint64_t *nanos_copy = malloc(sizeof (uint64_t)); + *nanos_copy = nanos; + + pthread_t thread; + int res = pthread_create(&thread, NULL, wait_and_raise, nanos_copy); + + return res ? -1 : 0; +#elif defined(_WIN32) || defined(__CYGWIN__) + return SetTimer(NULL, 0, nanos / 1000000, (TIMERPROC) win_raise_timeout) ? 0 : -1; +#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, + .sigev_signo = SIGPROF, + }, &timer); + + if (res == -1) + return res; + + struct itimerspec schedule = { + .it_value = { .tv_sec = nanos / GIGA, .tv_nsec = (nanos % GIGA) } + }; + + return timer_settime(timer, 0, &schedule, NULL); +#else + errno = ENOTSUP; + return -1; +#endif +} diff --git a/src/timer.h b/src/timer.h index 2d334cbf..14f301d9 100644 --- a/src/timer.h +++ b/src/timer.h @@ -1,6 +1,7 @@ #ifndef TIMER_H_ # define TIMER_H_ +# include # include # include # include @@ -13,5 +14,6 @@ struct timespec_compat { bool can_measure_time(void); int timer_start(struct timespec_compat *state); int timer_end(double *time, struct timespec_compat *state); +int setup_timeout(uint64_t nanos); #endif /* !TIMER_H_ */ From 7bc54daaad30620a634f0f850f73ea1aebeedc6e Mon Sep 17 00:00:00 2001 From: Snaipe Date: Sat, 12 Sep 2015 14:12:31 +0200 Subject: [PATCH 154/174] Switched windows timer code to a thread-based implementation --- src/timer.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/src/timer.c b/src/timer.c index 7efb70ce..8007afa2 100644 --- a/src/timer.c +++ b/src/timer.c @@ -87,11 +87,11 @@ int timer_end(double *time, struct timespec_compat *state) { } #if defined(_WIN32) || defined(__CYGWIN__) -void win_raise_timeout(UNUSED HWND hwnd, - UNUSED UINT uMsg, - UNUSED UINT_PTR idEvent, - UNUSED DWORD dwTime) { - RaiseException(CR_EXCEPTION_TIMEOUT, EXCEPTION_NONCONTINUABLE, 0, NULL); +DWORD WINAPI win_raise_timeout(LPVOID ptr) { + uint64_t *nanos = (uint64_t*) ptr; + Sleep(*nanos / 1000000); + TerminateProcess(GetCurrentProcess(), CR_EXCEPTION_TIMEOUT); + return 0; } #endif @@ -119,7 +119,14 @@ int setup_timeout(uint64_t nanos) { return res ? -1 : 0; #elif defined(_WIN32) || defined(__CYGWIN__) - return SetTimer(NULL, 0, nanos / 1000000, (TIMERPROC) win_raise_timeout) ? 0 : -1; + uint64_t *nanos_copy = malloc(sizeof (uint64_t)); + *nanos_copy = nanos; + + HANDLE thread = CreateThread(NULL, 0, win_raise_timeout, nanos_copy, 0, NULL); + if (thread == NULL) + return -1; + CloseHandle(thread); + return 0; #elif defined(__unix__) if (!can_measure_time()) { errno = ENOTSUP; From 30e71b42eb822e5ffb4778b219e12d502875605c Mon Sep 17 00:00:00 2001 From: Snaipe Date: Sat, 12 Sep 2015 08:52:03 -0700 Subject: [PATCH 155/174] Corrected the windows redirect code for pipe initialization --- src/posix-compat.c | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/src/posix-compat.c b/src/posix-compat.c index b8a88da0..eb2ba3db 100644 --- a/src/posix-compat.c +++ b/src/posix-compat.c @@ -465,22 +465,19 @@ FILE* get_std_file(int fd_kind) { int make_redirect_pipe(s_pipe_handle *handle, int id, int noblock) { #ifdef VANILLA_WIN32 - static char pipe_name[256] = {0}; - HANDLE fhs[2]; SECURITY_ATTRIBUTES attr = { .nLength = sizeof (SECURITY_ATTRIBUTES), .bInheritHandle = TRUE }; - if (!pipe_name[0]) { - snprintf(pipe_name, sizeof (pipe_name), - "\\\\.\\pipe\\criterion_%lu_%d", GetCurrentProcessId(), id); - } + char pipe_name[256] = {0}; + snprintf(pipe_name, sizeof (pipe_name), + "\\\\.\\pipe\\criterion_%lu_%d", GetCurrentProcessId(), id); fhs[0] = CreateNamedPipe(pipe_name, - PIPE_ACCESS_DUPLEX, - PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE - | (noblock ? PIPE_NOWAIT : PIPE_WAIT), - PIPE_UNLIMITED_INSTANCES, + PIPE_ACCESS_INBOUND, + PIPE_TYPE_BYTE | PIPE_READMODE_BYTE + | (noblock ? PIPE_NOWAIT : PIPE_WAIT), + 1, 4096 * 4, 4096 * 4, 0, @@ -490,7 +487,7 @@ int make_redirect_pipe(s_pipe_handle *handle, int id, int noblock) { return 0; fhs[1] = CreateFile(pipe_name, - GENERIC_READ | GENERIC_WRITE, + GENERIC_WRITE, 0, &attr, OPEN_EXISTING, @@ -521,7 +518,7 @@ int make_redirect_pipe(s_pipe_handle *handle, int id, int noblock) { void cr_redirect(int fd_kind, s_pipe_handle *pipe, int fd_index, int noblock) { fflush(get_std_file(fd_kind)); - if (make_redirect_pipe(pipe, fd_kind, noblock) < 0) + if (!make_redirect_pipe(pipe, fd_kind, noblock)) cr_assert_fail("Could not redirect standard file descriptor."); cr_std_fd fd = get_std_fd(fd_kind); From 6c35c644568eaabd57a7d7b950ed1ff72bd16a26 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Sat, 12 Sep 2015 09:33:55 -0700 Subject: [PATCH 156/174] Fixed windows redirection not replacing standard file pointers --- src/posix-compat.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/posix-compat.c b/src/posix-compat.c index eb2ba3db..2b0c6a7d 100644 --- a/src/posix-compat.c +++ b/src/posix-compat.c @@ -524,7 +524,14 @@ void cr_redirect(int fd_kind, s_pipe_handle *pipe, int fd_index, int noblock) { cr_std_fd fd = get_std_fd(fd_kind); #ifdef VANILLA_WIN32 CloseHandle(GetStdHandle(fd)); + _close(fd_kind); SetStdHandle(fd, pipe->fhs[fd_index]); + + fflush(NULL); + FILE *stdf = fd_kind == 0 ? pipe_in(pipe, 0) : pipe_out(pipe, 0); + if (stdf == NULL) + cr_assert_fail("Could not redirect standard file descriptor."); + _dup2(_fileno(stdf), fd_kind); #else close(fd); dup2(pipe->fds[fd_index], fd); From 17a609ba8898835aae813d35a4c906df24eda84d Mon Sep 17 00:00:00 2001 From: Snaipe Date: Sat, 12 Sep 2015 10:22:14 -0700 Subject: [PATCH 157/174] Fixed windows redirect code not working for stderr --- src/posix-compat.c | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/src/posix-compat.c b/src/posix-compat.c index 2b0c6a7d..2e46ca60 100644 --- a/src/posix-compat.c +++ b/src/posix-compat.c @@ -428,9 +428,9 @@ static s_pipe_handle stderr_redir; static s_pipe_handle stdin_redir; enum criterion_std_fd { - CR_STDIN, - CR_STDOUT, - CR_STDERR + CR_STDIN = 0, + CR_STDOUT = 1, + CR_STDERR = 2, }; enum criterion_pipe_end { @@ -523,15 +523,19 @@ void cr_redirect(int fd_kind, s_pipe_handle *pipe, int fd_index, int noblock) { cr_std_fd fd = get_std_fd(fd_kind); #ifdef VANILLA_WIN32 - CloseHandle(GetStdHandle(fd)); + int stdfd = _open_osfhandle((intptr_t) pipe->fhs[fd_index], fd_kind == 0 ? _O_RDONLY : _O_WRONLY); + if (stdfd == -1) + cr_assert_fail("Could not redirect standard file descriptor."); + + fflush(get_std_file(fd_kind)); + _close(fd_kind); SetStdHandle(fd, pipe->fhs[fd_index]); - fflush(NULL); - FILE *stdf = fd_kind == 0 ? pipe_in(pipe, 0) : pipe_out(pipe, 0); - if (stdf == NULL) - cr_assert_fail("Could not redirect standard file descriptor."); - _dup2(_fileno(stdf), fd_kind); + _dup2(stdfd, fd_kind); + _close(stdfd); + + setvbuf(get_std_file(fd_kind), NULL, _IONBF, 0); #else close(fd); dup2(pipe->fds[fd_index], fd); From 2be4bfd24151794223efa631211bc9ba9122870a Mon Sep 17 00:00:00 2001 From: Snaipe Date: Sat, 12 Sep 2015 10:24:00 -0700 Subject: [PATCH 158/174] Added C++ redirect sample --- samples/CMakeLists.txt | 1 + samples/redirect.cc | 56 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+) create mode 100644 samples/redirect.cc diff --git a/samples/CMakeLists.txt b/samples/CMakeLists.txt index f792c1d0..b7b13cc7 100644 --- a/samples/CMakeLists.txt +++ b/samples/CMakeLists.txt @@ -26,6 +26,7 @@ set(SAMPLES description.cc simple.cc theories.cc + redirect.cc ) set(SCRIPTS diff --git a/samples/redirect.cc b/samples/redirect.cc new file mode 100644 index 00000000..f4eae63a --- /dev/null +++ b/samples/redirect.cc @@ -0,0 +1,56 @@ +#include +#include + +#include +#include +#include +#include + +// Testing stdout/stderr + +void redirect_all_std(void) { + cr_redirect_stdout(); + cr_redirect_stderr(); +} + +Test(redirect, test_outputs, .init = redirect_all_std) { + std::FILE* f_stdout = cr_get_redirected_stdout(); + + std::cout << "foo" << std::flush; + + cr_assert_file_contents_match_str(f_stdout, "foo"); + + std::FILE* f_stderr = cr_get_redirected_stderr(); + + std::cerr << "bar" << std::flush; + + cr_assert_file_contents_match_str(f_stderr, "bar"); +} + +// Testing general I/O with sample command-line rot13 + +char rot13_char(char c) { + return std::isalpha(c) ? (c - 'a' + 13) % 26 + 'a' : c; +} + +void rot13_io(void) { + std::string s; + + std::cin >> s; + for (size_t i = 0; i < s.length(); ++i) + s[i] = rot13_char(s[i]); + std::cout << s << std::flush; +} + +Test(redirect, rot13, .init = cr_redirect_stdout) { + std::FILE* f_stdin = cr_get_redirected_stdin(); + std::ofstream f_cin(f_stdin); + + f_cin << "the quick brown fox jumps over the lazy dog"; + f_cin.close(); + + rot13_io(); + + std::FILE* f_stdout = cr_get_redirected_stdout(); + cr_assert_file_contents_match_str(f_stdout, "gur dhvpx oebja sbk whzcf bire gur ynml qbt"); +} From ac6415d465ab12c269629c1139f47c0cae7cc80a Mon Sep 17 00:00:00 2001 From: Snaipe Date: Sun, 13 Sep 2015 13:11:11 +0200 Subject: [PATCH 159/174] Added C++ stream interface for redirection functions --- include/criterion/redirect.h | 104 +++++++++++++++++++++++++++++++++++ samples/redirect.cc | 14 ++--- 2 files changed, 111 insertions(+), 7 deletions(-) diff --git a/include/criterion/redirect.h b/include/criterion/redirect.h index cf1efcf5..eacd0bb5 100644 --- a/include/criterion/redirect.h +++ b/include/criterion/redirect.h @@ -29,6 +29,12 @@ # ifdef __cplusplus # include +# include +# include + +# ifdef __GNUC__ +# include +# endif # else # include # endif @@ -73,4 +79,102 @@ CR_END_C_API # define cr_assert_file_contents_not_match_str(...) CR_EXPAND(cr_assert_redir_op_va_(CR_FAIL_ABORT_, cr_file_match_str, !=, __VA_ARGS__)) # define cr_expect_file_contents_not_match_str(...) CR_EXPAND(cr_assert_redir_op_va_(CR_FAIL_CONTINUES_, cr_file_match_str, !=, __VA_ARGS__)) +# ifdef __cplusplus +namespace criterion { + + template + class basic_ofstream : public std::basic_ofstream { + public: + basic_ofstream(FILE* f) +# ifdef __GNUC__ + : std::ofstream() + , fbuf(new ::__gnu_cxx::stdio_filebuf(f, std::ios::out)) +# else + : std::ofstream(f) +# endif + , file(f) + { + std::ios::rdbuf(&*fbuf); + } + + void close(void) { + std::basic_ofstream::flush(); + std::basic_ofstream::close(); + std::fclose(file); + } + + private: +# ifdef __GNUC__ + std::unique_ptr<::__gnu_cxx::stdio_filebuf> fbuf; +# endif + std::FILE* file; + }; + + template + class basic_ifstream : public std::basic_ifstream { + public: + basic_ifstream(FILE* f) +# ifdef __GNUC__ + : std::ifstream() + , fbuf(new ::__gnu_cxx::stdio_filebuf(f, std::ios::in)) +# else + : std::ifstream(f) +# endif + , file(f) + { + std::ios::rdbuf(&*fbuf); + } + + void close(void) { + std::basic_ifstream::flush(); + std::basic_ifstream::close(); + std::fclose(file); + } + + private: +# ifdef __GNUC__ + std::unique_ptr<::__gnu_cxx::stdio_filebuf> fbuf; +# endif + std::FILE* file; + }; + + template + 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; + } + + }; + + template + 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; + } + }; + + using ofstream = basic_ofstream; + using ifstream = basic_ifstream; + + static inline ofstream& get_redirected_cin(void) { + return 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()); + } + + static inline ifstream& get_redirected_cerr(void) { + return get_redirected_in_stream_::call(cr_get_redirected_stderr()); + } +} +# endif + #endif /* !CRITERION_REDIRECT_H_ */ diff --git a/samples/redirect.cc b/samples/redirect.cc index f4eae63a..29ee036c 100644 --- a/samples/redirect.cc +++ b/samples/redirect.cc @@ -6,6 +6,10 @@ #include #include +#ifdef __GNUC__ +# include +#endif + // Testing stdout/stderr void redirect_all_std(void) { @@ -14,16 +18,13 @@ void redirect_all_std(void) { } Test(redirect, test_outputs, .init = redirect_all_std) { - std::FILE* f_stdout = cr_get_redirected_stdout(); - std::cout << "foo" << std::flush; + std::cerr << "bar" << std::flush; + std::FILE* f_stdout = cr_get_redirected_stdout(); cr_assert_file_contents_match_str(f_stdout, "foo"); std::FILE* f_stderr = cr_get_redirected_stderr(); - - std::cerr << "bar" << std::flush; - cr_assert_file_contents_match_str(f_stderr, "bar"); } @@ -43,8 +44,7 @@ void rot13_io(void) { } Test(redirect, rot13, .init = cr_redirect_stdout) { - std::FILE* f_stdin = cr_get_redirected_stdin(); - std::ofstream f_cin(f_stdin); + auto& f_cin = criterion::get_redirected_cin(); f_cin << "the quick brown fox jumps over the lazy dog"; f_cin.close(); From 8232862d599a9e3ebdd4ef27c6afc900432de535 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Sun, 13 Sep 2015 13:11:41 +0200 Subject: [PATCH 160/174] Added french translation message for mismatching file contents --- po/fr.po | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/po/fr.po b/po/fr.po index 79c850db..17d25ae8 100644 --- a/po/fr.po +++ b/po/fr.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: criterion 1.0.0\n" "Report-Msgid-Bugs-To: franklinmathieu+criterion@gmail.com\n" -"POT-Creation-Date: 2015-09-10 03:35+0200\n" +"POT-Creation-Date: 2015-09-13 13:10+0200\n" "PO-Revision-Date: 2015-04-03 17:58+0200\n" "Last-Translator: \n" "Language-Team: French\n" @@ -137,3 +137,10 @@ msgstr "%s est vide." #, c-format msgid "%s is not empty." msgstr "%s n'est pas vide." + +#: src/i18n.c:22 +#, c-format +msgid "The file contents of %1$s does not match the string \"%2$s\"." +msgstr "" +"Le contenu du fichier %1$s ne correspond pas à la chaine de caractères \"%2$s" +"\"." From 9882f987cf0a39cde7ad3a4a3b7328f5725554dc Mon Sep 17 00:00:00 2001 From: Snaipe Date: Sun, 13 Sep 2015 13:12:16 +0200 Subject: [PATCH 161/174] Fixed memory leak on cr_assert() --- include/criterion/assert.h | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/include/criterion/assert.h b/include/criterion/assert.h index 62c578c8..b3434a5f 100644 --- a/include/criterion/assert.h +++ b/include/criterion/assert.h @@ -94,11 +94,14 @@ CR_END_C_API char *formatted_msg = NULL; \ int msglen = cr_asprintf(&formatted_msg, \ "" CR_VA_TAIL(CR_VA_TAIL(__VA_ARGS__))); \ - MsgVar = formatted_msg && *formatted_msg ? \ - formatted_msg : def_msg; \ - \ - if (!formatted_msg || !*formatted_msg) \ + 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; \ From 20c93d86dea0b90129a3ea768c1a17a8c2c525d1 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Sun, 13 Sep 2015 13:45:10 +0200 Subject: [PATCH 162/174] Fixed GCC-specific code being visible to MSVC --- include/criterion/redirect.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/include/criterion/redirect.h b/include/criterion/redirect.h index eacd0bb5..e037691e 100644 --- a/include/criterion/redirect.h +++ b/include/criterion/redirect.h @@ -94,7 +94,9 @@ namespace criterion { # endif , file(f) { +# ifdef __GNUC__ std::ios::rdbuf(&*fbuf); +# endif } void close(void) { @@ -122,7 +124,9 @@ namespace criterion { # endif , file(f) { +# ifdef __GNUC__ std::ios::rdbuf(&*fbuf); +# endif } void close(void) { From dd3f5344046790ab9e59aa41e641ca3e28b8d6af Mon Sep 17 00:00:00 2001 From: Snaipe Date: Sun, 13 Sep 2015 13:52:02 +0200 Subject: [PATCH 163/174] Added regression tests for redirect.{c,cc} --- samples/outputs/redirect.c.bin.err.expected | 1 + samples/outputs/redirect.c.bin.out.expected | 0 samples/outputs/redirect.cc.bin.err.expected | 1 + samples/outputs/redirect.cc.bin.out.expected | 0 4 files changed, 2 insertions(+) create mode 100644 samples/outputs/redirect.c.bin.err.expected create mode 100644 samples/outputs/redirect.c.bin.out.expected create mode 100644 samples/outputs/redirect.cc.bin.err.expected create mode 100644 samples/outputs/redirect.cc.bin.out.expected diff --git a/samples/outputs/redirect.c.bin.err.expected b/samples/outputs/redirect.c.bin.err.expected new file mode 100644 index 00000000..09eb50f6 --- /dev/null +++ b/samples/outputs/redirect.c.bin.err.expected @@ -0,0 +1 @@ +[====] Synthesis: Tested: 2 | Passing: 2 | Failing: 0 | Crashing: 0  diff --git a/samples/outputs/redirect.c.bin.out.expected b/samples/outputs/redirect.c.bin.out.expected new file mode 100644 index 00000000..e69de29b diff --git a/samples/outputs/redirect.cc.bin.err.expected b/samples/outputs/redirect.cc.bin.err.expected new file mode 100644 index 00000000..09eb50f6 --- /dev/null +++ b/samples/outputs/redirect.cc.bin.err.expected @@ -0,0 +1 @@ +[====] Synthesis: Tested: 2 | Passing: 2 | Failing: 0 | Crashing: 0  diff --git a/samples/outputs/redirect.cc.bin.out.expected b/samples/outputs/redirect.cc.bin.out.expected new file mode 100644 index 00000000..e69de29b From 98eb5e45a67c65a6cb14d593eedc8bab8a309023 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Sun, 13 Sep 2015 15:02:13 +0200 Subject: [PATCH 164/174] Added elapsed time on time out --- po/fr.po | 6 +++--- src/log/normal.c | 7 ++++--- src/log/tap.c | 5 +++-- 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/po/fr.po b/po/fr.po index 84b22a67..a59b0661 100644 --- a/po/fr.po +++ b/po/fr.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: criterion 1.0.0\n" "Report-Msgid-Bugs-To: franklinmathieu+criterion@gmail.com\n" -"POT-Creation-Date: 2015-09-13 13:10+0200\n" +"POT-Creation-Date: 2015-09-13 14:51+0200\n" "PO-Revision-Date: 2015-04-03 17:58+0200\n" "Last-Translator: \n" "Language-Team: French\n" @@ -61,8 +61,8 @@ msgstr "" #: src/log/normal.c:61 #, fuzzy, c-format -msgid "%1$s::%2$s: Timed out.\n" -msgstr "%1$s::%2$s: Délai expiré.\n" +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 #, c-format diff --git a/src/log/normal.c b/src/log/normal.c index 5bae2efc..6e3b1dbd 100644 --- a/src/log/normal.c +++ b/src/log/normal.c @@ -58,7 +58,7 @@ static msg_t msg_post_suite_test = N_("%1$s::%2$s: Test is disabled\n"); static msg_t msg_post_suite_suite = N_("%1$s::%2$s: Suite is disabled\n"); static msg_t msg_assert_fail = N_("%1$s%2$s%3$s:%4$s%5$d%6$s: Assertion failed: %7$s\n"); static msg_t msg_theory_fail = N_(" Theory %1$s::%2$s failed with the following parameters: (%3$s)\n"); -static msg_t msg_test_timeout = N_("%1$s::%2$s: Timed out.\n"); +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_other_crash = N_("%1$sWarning! The test `%2$s::%3$s` crashed during its setup or teardown.%4$s\n"); @@ -78,7 +78,7 @@ 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_test_timeout = "%s::%s: timed out.\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"; static msg_t msg_test_other_crash = "%sWarning! The test `%s::%s` crashed during its setup or teardown.%s\n"; @@ -226,7 +226,8 @@ void normal_log_test_timeout(UNUSED struct criterion_test_stats *stats) { criterion_pimportant(CRITERION_PREFIX_FAIL, _(msg_test_timeout), stats->test->category, - stats->test->name); + stats->test->name, + stats->elapsed_time); } struct criterion_output_provider normal_logging = { diff --git a/src/log/tap.c b/src/log/tap.c index b3180b51..9a87b78d 100644 --- a/src/log/tap.c +++ b/src/log/tap.c @@ -119,9 +119,10 @@ void tap_log_test_crash(struct criterion_test_stats *stats) { } void tap_log_test_timeout(struct criterion_test_stats *stats) { - criterion_important("not ok - %s::%s timed out\n", + criterion_important("not ok - %s::%s timed out (%3.2fs)\n", stats->test->category, - stats->test->name); + stats->test->name, + stats->elapsed_time); } struct criterion_output_provider tap_logging = { From b893b9aba116453eeee7f5afc34b4debe4f92853 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Mon, 14 Sep 2015 01:39:47 +0200 Subject: [PATCH 165/174] Fixed output directory of comparison tests --- samples/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/CMakeLists.txt b/samples/CMakeLists.txt index 9967e2e0..54990fe3 100644 --- a/samples/CMakeLists.txt +++ b/samples/CMakeLists.txt @@ -57,7 +57,7 @@ macro(add_samples DIR_ SAMPLES_) ) if (NOT MSVC) # we disable the scripted tests when building with MSVC - add_test(${sample}_compare sh ${DIR_}/run_test.sh "${CMAKE_CURRENT_LIST_DIR}/out_dir" . . ${sample}.bin) + add_test(${sample}_compare sh ${DIR_}/run_test.sh "${CMAKE_CURRENT_LIST_DIR}/outputs" . . ${sample}.bin) set_property(TEST ${sample}_compare PROPERTY ENVIRONMENT "LC_ALL=en_US.utf8" ENVIRONMENT "CRITERION_ALWAYS_SUCCEED=1" From 28144765ba5b838db8f38533e3e50e1794cdafcd Mon Sep 17 00:00:00 2001 From: Snaipe Date: Mon, 14 Sep 2015 01:47:00 +0200 Subject: [PATCH 166/174] Fixed comparison tests for failmessages --- .../tests/outputs/failmessages.c.bin.err.expected | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/samples/tests/outputs/failmessages.c.bin.err.expected b/samples/tests/outputs/failmessages.c.bin.err.expected index b6af5a9d..3a6b0e7a 100644 --- a/samples/tests/outputs/failmessages.c.bin.err.expected +++ b/samples/tests/outputs/failmessages.c.bin.err.expected @@ -11,12 +11,12 @@ [----] failmessages.c:15: Assertion failed: The expression (2) - (2) > (0.1) || (2) - (2) > (0.1) is false. [----] failmessages.c:17: Assertion failed: "foo" is not empty. [----] failmessages.c:18: Assertion failed: "" is empty. -[----] failmessages.c:19: Assertion failed: The expression (as strings) ("abc") == ("abd") is false -[----] failmessages.c:20: Assertion failed: The expression (as strings) ("abc") != ("abc") is false -[----] failmessages.c:21: Assertion failed: The expression (as strings) ("abc") < ("aba") is false -[----] 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 +[----] failmessages.c:19: Assertion failed: The expression (as strings) ("abc") == ("abd") is false. +[----] failmessages.c:20: Assertion failed: The expression (as strings) ("abc") != ("abc") is false. +[----] failmessages.c:21: Assertion failed: The expression (as strings) ("abc") < ("aba") is false. +[----] 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) [----] failmessages.c:28: Assertion failed: foo bar [----] failmessages.c:29: Assertion failed: foo bar From d4271865bc7485a6936a2a1cb9b44188f5e66d7b Mon Sep 17 00:00:00 2001 From: Snaipe Date: Mon, 14 Sep 2015 02:14:46 +0200 Subject: [PATCH 167/174] Added default message for throw assertions --- include/criterion/assert.h | 75 ++++++++++++++++++++++++----------- po/fr.po | 14 ++++++- samples/tests/CMakeLists.txt | 1 + samples/tests/failmessages.cc | 56 ++++++++++++++++++++++++++ src/i18n.c | 6 ++- 5 files changed, 125 insertions(+), 27 deletions(-) create mode 100644 samples/tests/failmessages.cc diff --git a/include/criterion/assert.h b/include/criterion/assert.h index f88842b7..c3e02508 100644 --- a/include/criterion/assert.h +++ b/include/criterion/assert.h @@ -53,6 +53,7 @@ struct criterion_assert_args { #endif }; +// Do NOT reorder unless you want to break the ABI enum criterion_assert_messages { CRITERION_ASSERT_MSG_FAIL, CRITERION_ASSERT_MSG_EXPR_FALSE, @@ -62,6 +63,8 @@ enum criterion_assert_messages { CRITERION_ASSERT_MSG_IS_EMPTY, CRITERION_ASSERT_MSG_IS_NOT_EMPTY, CRITERION_ASSERT_MSG_FILE_STR_MATCH, + CRITERION_ASSERT_MSG_THROW, + CRITERION_ASSERT_MSG_NO_THROW, }; CR_BEGIN_C_API @@ -484,36 +487,60 @@ CR_END_C_API # ifdef __cplusplus -# define cr_assert_throw_(Fail, Statement, Exception, ...) \ - try { \ - Statement; \ - } catch (Exception const &) { \ - } catch (...) { CR_EXPAND(cr_fail(Fail, CR_VA_TAIL(__VA_ARGS__))); } +# define cr_assert_throw_abort_(Fail, Msg, Statement, Exception, ...) \ + CR_EXPAND(cr_assert_impl( \ + Fail, \ + 0, \ + dummy, \ + Msg, \ + (CR_STR(Statement), CR_STR(Exception)), \ + CR_VA_TAIL(__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_(Fail, Statement, Exception, ...) \ + try { \ + Statement; \ + } catch (Exception const &) { \ + } catch (...) { \ + CR_EXPAND(cr_assert_throw_abort_( \ + Fail, \ + CRITERION_ASSERT_MSG_THROW, \ + Statement, \ + 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_fail(Fail, CR_VA_TAIL(__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_(Fail, Statement, Exception, ...) \ + try { \ + Statement; \ + } catch (Exception const &) { \ + CR_EXPAND(cr_assert_throw_abort_( \ + Fail, \ + CRITERION_ASSERT_MSG_NO_THROW, \ + Statement, \ + 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__)) diff --git a/po/fr.po b/po/fr.po index a59b0661..3df7e374 100644 --- a/po/fr.po +++ b/po/fr.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: criterion 1.0.0\n" "Report-Msgid-Bugs-To: franklinmathieu+criterion@gmail.com\n" -"POT-Creation-Date: 2015-09-13 14:51+0200\n" +"POT-Creation-Date: 2015-09-14 02:01+0200\n" "PO-Revision-Date: 2015-04-03 17:58+0200\n" "Last-Translator: \n" "Language-Team: French\n" @@ -143,9 +143,19 @@ msgstr "%s est vide." msgid "%s is not empty." msgstr "%s n'est pas vide." -#: src/i18n.c:22 +#: src/i18n.c:21 #, c-format msgid "The file contents of %1$s does not match the string \"%2$s\"." msgstr "" "Le contenu du fichier %1$s ne correspond pas à la chaine de caractères \"%2$s" "\"." + +#: src/i18n.c:22 +#, c-format +msgid "The statement `%1$s` did throw an instance of the `%2$s` exception." +msgstr "L'instruction `%1$s` a levé une instance de l'exception `%2$s`." + +#: src/i18n.c:23 +#, 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`." diff --git a/samples/tests/CMakeLists.txt b/samples/tests/CMakeLists.txt index d5b4da53..463d4da7 100644 --- a/samples/tests/CMakeLists.txt +++ b/samples/tests/CMakeLists.txt @@ -4,6 +4,7 @@ set(SAMPLES long-messages.c other-crashes.c + failmessages.cc exit.cc long-messages.cc other-crashes.cc diff --git a/samples/tests/failmessages.cc b/samples/tests/failmessages.cc new file mode 100644 index 00000000..c39a769f --- /dev/null +++ b/samples/tests/failmessages.cc @@ -0,0 +1,56 @@ +#include +#include + +Test(messages, default) { + cr_expect(0); + cr_expect_eq(0, 1); + cr_expect_neq(1, 1); + cr_expect_lt(2, 1); + cr_expect_leq(2, 1); + cr_expect_gt(1, 2); + cr_expect_geq(1, 2); + cr_expect_null(""); + cr_expect_not_null(NULL); + + cr_expect_float_eq(1, 2, 0.1); + cr_expect_float_neq(2, 2, 0.1); + + cr_expect_str_empty("foo"); + cr_expect_str_not_empty(""); + cr_expect_str_eq("abc", "abd"); + cr_expect_str_neq("abc", "abc"); + cr_expect_str_lt("abc", "aba"); + cr_expect_str_leq("abc", "aba"); + cr_expect_str_gt("abc", "abd"); + cr_expect_str_geq("abc", "abd"); + + cr_expect_throw(throw std::exception(), std::bad_alloc); + cr_expect_no_throw(throw std::exception(), std::exception); +} + +Test(messages, user) { + cr_expect(0, "foo %s", "bar"); + cr_expect_eq(0, 1, "foo %s", "bar"); + cr_expect_neq(1, 1, "foo %s", "bar"); + cr_expect_lt(2, 1, "foo %s", "bar"); + cr_expect_leq(2, 1, "foo %s", "bar"); + cr_expect_gt(1, 2, "foo %s", "bar"); + cr_expect_geq(1, 2, "foo %s", "bar"); + cr_expect_null("", "foo %s", "bar"); + cr_expect_not_null(NULL, "foo %s", "bar"); + + cr_expect_float_eq(1, 2, 0.1, "foo %s", "bar"); + cr_expect_float_neq(2, 2, 0.1, "foo %s", "bar"); + + cr_expect_str_empty("foo", "foo %s", "bar"); + cr_expect_str_not_empty("", "foo %s", "bar"); + cr_expect_str_eq("abc", "abd", "foo %s", "bar"); + cr_expect_str_neq("abc", "abc", "foo %s", "bar"); + cr_expect_str_lt("abc", "aba", "foo %s", "bar"); + cr_expect_str_leq("abc", "aba", "foo %s", "bar"); + cr_expect_str_gt("abc", "abd", "foo %s", "bar"); + cr_expect_str_geq("abc", "abd", "foo %s", "bar"); + + cr_expect_throw(throw std::exception(), std::bad_alloc, "foo %s", "bar"); + cr_expect_no_throw(throw std::exception(), std::exception, "foo %s", "bar"); +} diff --git a/src/i18n.c b/src/i18n.c index fb6e7d75..31780642 100644 --- a/src/i18n.c +++ b/src/i18n.c @@ -17,12 +17,16 @@ char *translate_assert_msg(int msg_index, ...) { [CRITERION_ASSERT_MSG_IS_NOT_NULL] = N_("%s is not null."), [CRITERION_ASSERT_MSG_IS_EMPTY] = N_("%s is empty."), [CRITERION_ASSERT_MSG_IS_NOT_EMPTY] = N_("%s is not empty."), - #ifdef ENABLE_NLS [CRITERION_ASSERT_MSG_FILE_STR_MATCH] = N_("The file contents of %1$s does not match the string \"%2$s\"."), + [CRITERION_ASSERT_MSG_THROW] = N_("The statement `%1$s` did throw an instance of the `%2$s` exception."), + [CRITERION_ASSERT_MSG_NO_THROW] = N_("The statement `%1$s` did not throw an instance of the `%2$s` exception."), #else [CRITERION_ASSERT_MSG_FILE_STR_MATCH] = "The file contents of %s does not match the string \"%s\".", + [CRITERION_ASSERT_MSG_THROW] = "The statement `%s` did throw an instance of the `%s` exception.", + [CRITERION_ASSERT_MSG_NO_THROW] = "The statement `%s` did not throw an instance of the `%s` exception.", #endif + }; va_list vl; From 5e8491af90cc8b4c1b0555682f7683d1265ad6aa Mon Sep 17 00:00:00 2001 From: Snaipe Date: Mon, 14 Sep 2015 02:35:09 +0200 Subject: [PATCH 168/174] Added any_throw and none_throw assertions --- include/criterion/assert.h | 59 ++++++++++++++++--- po/fr.po | 16 ++++- samples/outputs/asserts.cc.bin.err.expected | 2 +- samples/tests/failmessages.cc | 4 ++ .../outputs/failmessages.cc.bin.err.expected | 49 +++++++++++++++ .../outputs/failmessages.cc.bin.out.expected | 0 src/i18n.c | 3 + 7 files changed, 121 insertions(+), 12 deletions(-) create mode 100644 samples/tests/outputs/failmessages.cc.bin.err.expected create mode 100644 samples/tests/outputs/failmessages.cc.bin.out.expected diff --git a/include/criterion/assert.h b/include/criterion/assert.h index c3e02508..018a0c1a 100644 --- a/include/criterion/assert.h +++ b/include/criterion/assert.h @@ -65,6 +65,8 @@ enum criterion_assert_messages { CRITERION_ASSERT_MSG_FILE_STR_MATCH, CRITERION_ASSERT_MSG_THROW, CRITERION_ASSERT_MSG_NO_THROW, + CRITERION_ASSERT_MSG_ANY_THROW, + CRITERION_ASSERT_MSG_NONE_THROW, }; CR_BEGIN_C_API @@ -487,13 +489,13 @@ CR_END_C_API # ifdef __cplusplus -# define cr_assert_throw_abort_(Fail, Msg, Statement, Exception, ...) \ +# define cr_assert_throw_abort_(Fail, Msg, MsgArgs, ...) \ CR_EXPAND(cr_assert_impl( \ Fail, \ 0, \ dummy, \ Msg, \ - (CR_STR(Statement), CR_STR(Exception)), \ + MsgArgs, \ CR_VA_TAIL(__VA_ARGS__) \ )) @@ -504,9 +506,8 @@ CR_END_C_API } catch (...) { \ CR_EXPAND(cr_assert_throw_abort_( \ Fail, \ - CRITERION_ASSERT_MSG_THROW, \ - Statement, \ - Exception, \ + CRITERION_ASSERT_MSG_NO_THROW, \ + (CR_STR(Statement), CR_STR(Exception)), \ __VA_ARGS__)); \ } @@ -528,9 +529,8 @@ CR_END_C_API } catch (Exception const &) { \ CR_EXPAND(cr_assert_throw_abort_( \ Fail, \ - CRITERION_ASSERT_MSG_NO_THROW, \ - Statement, \ - Exception, \ + CRITERION_ASSERT_MSG_THROW, \ + (CR_STR(Statement), CR_STR(Exception)), \ __VA_ARGS__)); \ } @@ -546,6 +546,49 @@ CR_END_C_API # 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__)) + # endif // The section below is here for backward compatibility purposes. diff --git a/po/fr.po b/po/fr.po index 3df7e374..aa39d31a 100644 --- a/po/fr.po +++ b/po/fr.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: criterion 1.0.0\n" "Report-Msgid-Bugs-To: franklinmathieu+criterion@gmail.com\n" -"POT-Creation-Date: 2015-09-14 02:01+0200\n" +"POT-Creation-Date: 2015-09-14 02:33+0200\n" "PO-Revision-Date: 2015-04-03 17:58+0200\n" "Last-Translator: \n" "Language-Team: French\n" @@ -143,19 +143,29 @@ msgstr "%s est vide." msgid "%s is not empty." msgstr "%s n'est pas vide." +#: src/i18n.c:20 +#, fuzzy, c-format +msgid "The statement `%s` did not throw any exception." +msgstr "L'instruction `%s` n'a pas levé d'exception." + #: src/i18n.c:21 +#, fuzzy, c-format +msgid "The statement `%s` threw some exception." +msgstr "L'instruction `%1$s` a levé une exception." + +#: src/i18n.c:24 #, c-format msgid "The file contents of %1$s does not match the string \"%2$s\"." msgstr "" "Le contenu du fichier %1$s ne correspond pas à la chaine de caractères \"%2$s" "\"." -#: src/i18n.c:22 +#: src/i18n.c:25 #, c-format msgid "The statement `%1$s` did throw an instance of the `%2$s` exception." msgstr "L'instruction `%1$s` a levé une instance de l'exception `%2$s`." -#: src/i18n.c:23 +#: src/i18n.c:26 #, 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`." diff --git a/samples/outputs/asserts.cc.bin.err.expected b/samples/outputs/asserts.cc.bin.err.expected index ac5d5222..1b10420c 100644 --- a/samples/outputs/asserts.cc.bin.err.expected +++ b/samples/outputs/asserts.cc.bin.err.expected @@ -3,7 +3,7 @@ [----] asserts.cc:13: Assertion failed: assert is fatal, expect isn't [----] asserts.cc:14: Assertion failed: This assert runs [FAIL] asserts::base: (0.00s) -[----] asserts.cc:89: Assertion failed: The conditions for this assertion were not met. +[----] asserts.cc:89: Assertion failed: The statement `throw std::exception()` did throw an instance of the `std::bad_alloc` exception. [FAIL] asserts::exception: (0.00s) [----] 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. diff --git a/samples/tests/failmessages.cc b/samples/tests/failmessages.cc index c39a769f..6e57b648 100644 --- a/samples/tests/failmessages.cc +++ b/samples/tests/failmessages.cc @@ -26,6 +26,8 @@ Test(messages, default) { cr_expect_throw(throw std::exception(), std::bad_alloc); cr_expect_no_throw(throw std::exception(), std::exception); + cr_expect_any_throw({}); + cr_expect_none_throw(throw std::exception()); } Test(messages, user) { @@ -53,4 +55,6 @@ Test(messages, user) { cr_expect_throw(throw std::exception(), std::bad_alloc, "foo %s", "bar"); cr_expect_no_throw(throw std::exception(), std::exception, "foo %s", "bar"); + cr_expect_any_throw({}, "foo %s", "bar"); + cr_expect_none_throw(throw std::exception(), "foo %s", "bar"); } diff --git a/samples/tests/outputs/failmessages.cc.bin.err.expected b/samples/tests/outputs/failmessages.cc.bin.err.expected new file mode 100644 index 00000000..f060bace --- /dev/null +++ b/samples/tests/outputs/failmessages.cc.bin.err.expected @@ -0,0 +1,49 @@ +[----] failmessages.cc:5: Assertion failed: The expression 0 is false. +[----] failmessages.cc:6: Assertion failed: The expression (0) == (1) is false. +[----] failmessages.cc:7: Assertion failed: The expression (1) != (1) is false. +[----] failmessages.cc:8: Assertion failed: The expression (2) < (1) is false. +[----] failmessages.cc:9: Assertion failed: The expression (2) <= (1) is false. +[----] failmessages.cc:10: Assertion failed: The expression (1) > (2) is false. +[----] failmessages.cc:11: Assertion failed: The expression (1) >= (2) is false. +[----] failmessages.cc:12: Assertion failed: "" is not null. +[----] failmessages.cc:13: Assertion failed: __null is null. +[----] failmessages.cc:15: Assertion failed: The expression (2) - (1) <= (0.1) && (1) - (2) <= (0.1) is false. +[----] failmessages.cc:16: Assertion failed: The expression (2) - (2) > (0.1) || (2) - (2) > (0.1) is false. +[----] failmessages.cc:18: Assertion failed: "foo" is not empty. +[----] failmessages.cc:19: Assertion failed: "" is empty. +[----] failmessages.cc:20: Assertion failed: The expression (as strings) ("abc") == ("abd") is false. +[----] failmessages.cc:21: Assertion failed: The expression (as strings) ("abc") != ("abc") is false. +[----] failmessages.cc:22: Assertion failed: The expression (as strings) ("abc") < ("aba") is false. +[----] failmessages.cc:23: Assertion failed: The expression (as strings) ("abc") <= ("aba") is false. +[----] failmessages.cc:24: Assertion failed: The expression (as strings) ("abc") > ("abd") is false. +[----] failmessages.cc:25: Assertion failed: The expression (as strings) ("abc") >= ("abd") is false. +[----] failmessages.cc:27: Assertion failed: The statement `throw std::exception()` did not throw an instance of the `std::bad_alloc` exception. +[----] 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) +[----] failmessages.cc:34: Assertion failed: foo bar +[----] failmessages.cc:35: Assertion failed: foo bar +[----] failmessages.cc:36: Assertion failed: foo bar +[----] failmessages.cc:37: Assertion failed: foo bar +[----] failmessages.cc:38: Assertion failed: foo bar +[----] failmessages.cc:39: Assertion failed: foo bar +[----] failmessages.cc:40: Assertion failed: foo bar +[----] failmessages.cc:41: Assertion failed: foo bar +[----] failmessages.cc:42: Assertion failed: foo bar +[----] failmessages.cc:44: Assertion failed: foo bar +[----] failmessages.cc:45: Assertion failed: foo bar +[----] failmessages.cc:47: Assertion failed: foo bar +[----] failmessages.cc:48: Assertion failed: foo bar +[----] failmessages.cc:49: Assertion failed: foo bar +[----] failmessages.cc:50: Assertion failed: foo bar +[----] failmessages.cc:51: Assertion failed: foo bar +[----] failmessages.cc:52: Assertion failed: foo bar +[----] failmessages.cc:53: Assertion failed: foo bar +[----] failmessages.cc:54: Assertion failed: foo bar +[----] failmessages.cc:56: Assertion failed: foo bar +[----] 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) +[====] Synthesis: Tested: 2 | Passing: 0 | Failing: 2 | Crashing: 0  diff --git a/samples/tests/outputs/failmessages.cc.bin.out.expected b/samples/tests/outputs/failmessages.cc.bin.out.expected new file mode 100644 index 00000000..e69de29b diff --git a/src/i18n.c b/src/i18n.c index 31780642..6df4ccb5 100644 --- a/src/i18n.c +++ b/src/i18n.c @@ -17,6 +17,9 @@ char *translate_assert_msg(int msg_index, ...) { [CRITERION_ASSERT_MSG_IS_NOT_NULL] = N_("%s is not null."), [CRITERION_ASSERT_MSG_IS_EMPTY] = N_("%s is empty."), [CRITERION_ASSERT_MSG_IS_NOT_EMPTY] = N_("%s is not empty."), + [CRITERION_ASSERT_MSG_ANY_THROW] = N_("The statement `%s` did not throw any exception."), + [CRITERION_ASSERT_MSG_NONE_THROW] = N_("The statement `%s` threw some exception."), + #ifdef ENABLE_NLS [CRITERION_ASSERT_MSG_FILE_STR_MATCH] = N_("The file contents of %1$s does not match the string \"%2$s\"."), [CRITERION_ASSERT_MSG_THROW] = N_("The statement `%1$s` did throw an instance of the `%2$s` exception."), From 0e2203df43e3fe0938765080fe844b707d66adc9 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Mon, 14 Sep 2015 03:32:33 +0200 Subject: [PATCH 169/174] Renamed file assertion macros for consistency --- include/criterion/redirect.h | 8 ++++---- samples/redirect.c | 6 +++--- samples/redirect.cc | 6 +++--- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/include/criterion/redirect.h b/include/criterion/redirect.h index e037691e..b8a80c5a 100644 --- a/include/criterion/redirect.h +++ b/include/criterion/redirect.h @@ -73,11 +73,11 @@ CR_END_C_API CR_VA_TAIL(CR_VA_TAIL(__VA_ARGS__)) \ )) -# define cr_assert_file_contents_match_str(...) CR_EXPAND(cr_assert_redir_op_va_(CR_FAIL_ABORT_, cr_file_match_str, ==, __VA_ARGS__)) -# define cr_expect_file_contents_match_str(...) CR_EXPAND(cr_assert_redir_op_va_(CR_FAIL_CONTINUES_, cr_file_match_str, ==, __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__)) -# define cr_assert_file_contents_not_match_str(...) CR_EXPAND(cr_assert_redir_op_va_(CR_FAIL_ABORT_, cr_file_match_str, !=, __VA_ARGS__)) -# define cr_expect_file_contents_not_match_str(...) CR_EXPAND(cr_assert_redir_op_va_(CR_FAIL_CONTINUES_, cr_file_match_str, !=, __VA_ARGS__)) +# define cr_assert_file_contents_neq_str(...) CR_EXPAND(cr_assert_redir_op_va_(CR_FAIL_ABORT_, cr_file_match_str, !=, __VA_ARGS__)) +# define cr_expect_file_contents_neq_str(...) CR_EXPAND(cr_assert_redir_op_va_(CR_FAIL_CONTINUES_, cr_file_match_str, !=, __VA_ARGS__)) # ifdef __cplusplus namespace criterion { diff --git a/samples/redirect.c b/samples/redirect.c index 895eb568..f7ee089b 100644 --- a/samples/redirect.c +++ b/samples/redirect.c @@ -17,14 +17,14 @@ Test(redirect, test_outputs, .init = redirect_all_std) { fprintf(stdout, "foo"); fflush(stdout); - cr_assert_file_contents_match_str(f_stdout, "foo"); + cr_assert_file_contents_eq_str(f_stdout, "foo"); FILE* f_stderr = cr_get_redirected_stderr(); fprintf(stderr, "bar"); fflush(stderr); - cr_assert_file_contents_match_str(f_stderr, "bar"); + cr_assert_file_contents_eq_str(f_stderr, "bar"); } // Testing general I/O with sample command-line rot13 @@ -53,5 +53,5 @@ Test(redirect, rot13, .init = cr_redirect_stdout) { rot13_io(); FILE* f_stdout = cr_get_redirected_stdout(); - cr_assert_file_contents_match_str(f_stdout, "gur dhvpx oebja sbk whzcf bire gur ynml qbt"); + cr_assert_file_contents_eq_str(f_stdout, "gur dhvpx oebja sbk whzcf bire gur ynml qbt"); } diff --git a/samples/redirect.cc b/samples/redirect.cc index 29ee036c..f87dfb83 100644 --- a/samples/redirect.cc +++ b/samples/redirect.cc @@ -22,10 +22,10 @@ Test(redirect, test_outputs, .init = redirect_all_std) { std::cerr << "bar" << std::flush; std::FILE* f_stdout = cr_get_redirected_stdout(); - cr_assert_file_contents_match_str(f_stdout, "foo"); + cr_assert_file_contents_eq_str(f_stdout, "foo"); std::FILE* f_stderr = cr_get_redirected_stderr(); - cr_assert_file_contents_match_str(f_stderr, "bar"); + cr_assert_file_contents_eq_str(f_stderr, "bar"); } // Testing general I/O with sample command-line rot13 @@ -52,5 +52,5 @@ Test(redirect, rot13, .init = cr_redirect_stdout) { rot13_io(); std::FILE* f_stdout = cr_get_redirected_stdout(); - cr_assert_file_contents_match_str(f_stdout, "gur dhvpx oebja sbk whzcf bire gur ynml qbt"); + cr_assert_file_contents_eq_str(f_stdout, "gur dhvpx oebja sbk whzcf bire gur ynml qbt"); } From 779fbca56e070f27e53f927c8184323d8d2008ad Mon Sep 17 00:00:00 2001 From: Snaipe Date: Mon, 14 Sep 2015 03:39:52 +0200 Subject: [PATCH 170/174] Added redirection assertion shortcuts for std{out,err} --- include/criterion/redirect.h | 12 ++++++++++++ samples/redirect.c | 11 +++-------- samples/redirect.cc | 10 +++------- 3 files changed, 18 insertions(+), 15 deletions(-) diff --git a/include/criterion/redirect.h b/include/criterion/redirect.h index b8a80c5a..e88fc89f 100644 --- a/include/criterion/redirect.h +++ b/include/criterion/redirect.h @@ -79,6 +79,18 @@ CR_END_C_API # define cr_assert_file_contents_neq_str(...) CR_EXPAND(cr_assert_redir_op_va_(CR_FAIL_ABORT_, cr_file_match_str, !=, __VA_ARGS__)) # define cr_expect_file_contents_neq_str(...) CR_EXPAND(cr_assert_redir_op_va_(CR_FAIL_CONTINUES_, cr_file_match_str, !=, __VA_ARGS__)) +# define cr_assert_stdout_eq_str(...) CR_EXPAND(cr_assert_redir_op_va_(CR_FAIL_ABORT_, cr_file_match_str, ==, cr_get_redirected_stdout(), __VA_ARGS__)) +# define cr_expect_stdout_eq_str(...) CR_EXPAND(cr_assert_redir_op_va_(CR_FAIL_CONTINUES_, cr_file_match_str, ==, cr_get_redirected_stdout(), __VA_ARGS__)) + +# define cr_assert_stdout_neq_str(...) CR_EXPAND(cr_assert_redir_op_va_(CR_FAIL_ABORT_, cr_file_match_str, !=, cr_get_redirected_stdout(), __VA_ARGS__)) +# define cr_expect_stdout_neq_str(...) CR_EXPAND(cr_assert_redir_op_va_(CR_FAIL_CONTINUES_, cr_file_match_str, !=, cr_get_redirected_stdout(), __VA_ARGS__)) + +# define cr_assert_stderr_eq_str(...) CR_EXPAND(cr_assert_redir_op_va_(CR_FAIL_ABORT_, cr_file_match_str, ==, cr_get_redirected_stderr(), __VA_ARGS__)) +# define cr_expect_stderr_eq_str(...) CR_EXPAND(cr_assert_redir_op_va_(CR_FAIL_CONTINUES_, cr_file_match_str, ==, cr_get_redirected_stderr(), __VA_ARGS__)) + +# define cr_assert_stderr_neq_str(...) CR_EXPAND(cr_assert_redir_op_va_(CR_FAIL_ABORT_, cr_file_match_str, !=, cr_get_redirected_stderr(), __VA_ARGS__)) +# define cr_expect_stderr_neq_str(...) CR_EXPAND(cr_assert_redir_op_va_(CR_FAIL_CONTINUES_, cr_file_match_str, !=, cr_get_redirected_stderr(), __VA_ARGS__)) + # ifdef __cplusplus namespace criterion { diff --git a/samples/redirect.c b/samples/redirect.c index f7ee089b..9a0db123 100644 --- a/samples/redirect.c +++ b/samples/redirect.c @@ -12,19 +12,15 @@ void redirect_all_std(void) { } Test(redirect, test_outputs, .init = redirect_all_std) { - FILE* f_stdout = cr_get_redirected_stdout(); - fprintf(stdout, "foo"); fflush(stdout); - cr_assert_file_contents_eq_str(f_stdout, "foo"); - - FILE* f_stderr = cr_get_redirected_stderr(); + cr_assert_stdout_eq_str("foo"); fprintf(stderr, "bar"); fflush(stderr); - cr_assert_file_contents_eq_str(f_stderr, "bar"); + cr_assert_stderr_eq_str("bar"); } // Testing general I/O with sample command-line rot13 @@ -52,6 +48,5 @@ Test(redirect, rot13, .init = cr_redirect_stdout) { rot13_io(); - FILE* f_stdout = cr_get_redirected_stdout(); - cr_assert_file_contents_eq_str(f_stdout, "gur dhvpx oebja sbk whzcf bire gur ynml qbt"); + cr_assert_stdout_eq_str("gur dhvpx oebja sbk whzcf bire gur ynml qbt"); } diff --git a/samples/redirect.cc b/samples/redirect.cc index f87dfb83..87a25da0 100644 --- a/samples/redirect.cc +++ b/samples/redirect.cc @@ -21,11 +21,8 @@ Test(redirect, test_outputs, .init = redirect_all_std) { std::cout << "foo" << std::flush; std::cerr << "bar" << std::flush; - std::FILE* f_stdout = cr_get_redirected_stdout(); - cr_assert_file_contents_eq_str(f_stdout, "foo"); - - std::FILE* f_stderr = cr_get_redirected_stderr(); - cr_assert_file_contents_eq_str(f_stderr, "bar"); + cr_assert_stdout_eq_str("foo"); + cr_assert_stderr_eq_str("bar"); } // Testing general I/O with sample command-line rot13 @@ -51,6 +48,5 @@ Test(redirect, rot13, .init = cr_redirect_stdout) { rot13_io(); - std::FILE* f_stdout = cr_get_redirected_stdout(); - cr_assert_file_contents_eq_str(f_stdout, "gur dhvpx oebja sbk whzcf bire gur ynml qbt"); + cr_assert_stdout_eq_str("gur dhvpx oebja sbk whzcf bire gur ynml qbt"); } From 9f850ef6fe31f8ed835aadca8ce031547250f19d Mon Sep 17 00:00:00 2001 From: Snaipe Date: Mon, 14 Sep 2015 03:42:20 +0200 Subject: [PATCH 171/174] Fixed regression test for assert --- samples/outputs/asserts.cc.bin.err.expected | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/outputs/asserts.cc.bin.err.expected b/samples/outputs/asserts.cc.bin.err.expected index 1b10420c..ebeb3553 100644 --- a/samples/outputs/asserts.cc.bin.err.expected +++ b/samples/outputs/asserts.cc.bin.err.expected @@ -3,7 +3,7 @@ [----] asserts.cc:13: Assertion failed: assert is fatal, expect isn't [----] asserts.cc:14: Assertion failed: This assert runs [FAIL] asserts::base: (0.00s) -[----] asserts.cc:89: Assertion failed: The statement `throw std::exception()` did throw an instance of the `std::bad_alloc` exception. +[----] 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) [----] 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. From b0869165affce34b8b778134cea329eb20e6b815 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Mon, 14 Sep 2015 03:58:25 +0200 Subject: [PATCH 172/174] Added more file assertions and file comparison function --- CMakeLists.txt | 1 + include/criterion/redirect.h | 19 +++++++++++++ src/file.c | 53 ++++++++++++++++++++++++++++++++++++ src/posix-compat.c | 23 ---------------- 4 files changed, 73 insertions(+), 23 deletions(-) create mode 100644 src/file.c diff --git a/CMakeLists.txt b/CMakeLists.txt index f82d4fec..ef4b09e3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -99,6 +99,7 @@ set(SOURCE_FILES src/posix-compat.c src/theories.c src/asprintf.c + src/file.c src/main.c src/entry.c ) diff --git a/include/criterion/redirect.h b/include/criterion/redirect.h index e88fc89f..2b8492fc 100644 --- a/include/criterion/redirect.h +++ b/include/criterion/redirect.h @@ -50,6 +50,7 @@ CR_API CR_STDN FILE* cr_get_redirected_stderr(void); CR_API CR_STDN FILE* cr_get_redirected_stdin(void); CR_API int cr_file_match_str(CR_STDN FILE* f, const char *str); +CR_API int cr_file_match_file(CR_STDN FILE* f, CR_STDN FILE* ref); CR_END_C_API @@ -79,6 +80,12 @@ CR_END_C_API # define cr_assert_file_contents_neq_str(...) CR_EXPAND(cr_assert_redir_op_va_(CR_FAIL_ABORT_, cr_file_match_str, !=, __VA_ARGS__)) # define cr_expect_file_contents_neq_str(...) CR_EXPAND(cr_assert_redir_op_va_(CR_FAIL_CONTINUES_, cr_file_match_str, !=, __VA_ARGS__)) +# define cr_assert_file_contents_eq(...) CR_EXPAND(cr_assert_redir_op_va_(CR_FAIL_ABORT_, cr_file_match_file, ==, __VA_ARGS__)) +# define cr_expect_file_contents_eq(...) CR_EXPAND(cr_assert_redir_op_va_(CR_FAIL_CONTINUES_, cr_file_match_file, ==, __VA_ARGS__)) + +# define cr_assert_file_contents_neq(...) CR_EXPAND(cr_assert_redir_op_va_(CR_FAIL_ABORT_, cr_file_match_file, !=, __VA_ARGS__)) +# define cr_expect_file_contents_neq(...) CR_EXPAND(cr_assert_redir_op_va_(CR_FAIL_CONTINUES_, cr_file_match_file, !=, __VA_ARGS__)) + # define cr_assert_stdout_eq_str(...) CR_EXPAND(cr_assert_redir_op_va_(CR_FAIL_ABORT_, cr_file_match_str, ==, cr_get_redirected_stdout(), __VA_ARGS__)) # define cr_expect_stdout_eq_str(...) CR_EXPAND(cr_assert_redir_op_va_(CR_FAIL_CONTINUES_, cr_file_match_str, ==, cr_get_redirected_stdout(), __VA_ARGS__)) @@ -91,6 +98,18 @@ CR_END_C_API # define cr_assert_stderr_neq_str(...) CR_EXPAND(cr_assert_redir_op_va_(CR_FAIL_ABORT_, cr_file_match_str, !=, cr_get_redirected_stderr(), __VA_ARGS__)) # define cr_expect_stderr_neq_str(...) CR_EXPAND(cr_assert_redir_op_va_(CR_FAIL_CONTINUES_, cr_file_match_str, !=, cr_get_redirected_stderr(), __VA_ARGS__)) +# define cr_assert_stdout_eq(...) CR_EXPAND(cr_assert_redir_op_va_(CR_FAIL_ABORT_, cr_file_match_file, ==, cr_get_redirected_stdout(), __VA_ARGS__)) +# define cr_expect_stdout_eq(...) CR_EXPAND(cr_assert_redir_op_va_(CR_FAIL_CONTINUES_, cr_file_match_file, ==, cr_get_redirected_stdout(), __VA_ARGS__)) + +# define cr_assert_stdout_neq(...) CR_EXPAND(cr_assert_redir_op_va_(CR_FAIL_ABORT_, cr_file_match_file, !=, cr_get_redirected_stdout(), __VA_ARGS__)) +# define cr_expect_stdout_neq(...) CR_EXPAND(cr_assert_redir_op_va_(CR_FAIL_CONTINUES_, cr_file_match_file, !=, cr_get_redirected_stdout(), __VA_ARGS__)) + +# define cr_assert_stderr_eq(...) CR_EXPAND(cr_assert_redir_op_va_(CR_FAIL_ABORT_, cr_file_match_file, ==, cr_get_redirected_stderr(), __VA_ARGS__)) +# define cr_expect_stderr_eq(...) CR_EXPAND(cr_assert_redir_op_va_(CR_FAIL_CONTINUES_, cr_file_match_file, ==, cr_get_redirected_stderr(), __VA_ARGS__)) + +# define cr_assert_stderr_neq(...) CR_EXPAND(cr_assert_redir_op_va_(CR_FAIL_ABORT_, cr_file_match_file, !=, cr_get_redirected_stderr(), __VA_ARGS__)) +# define cr_expect_stderr_neq(...) CR_EXPAND(cr_assert_redir_op_va_(CR_FAIL_CONTINUES_, cr_file_match_file, !=, cr_get_redirected_stderr(), __VA_ARGS__)) + # ifdef __cplusplus namespace criterion { diff --git a/src/file.c b/src/file.c new file mode 100644 index 00000000..e48e183f --- /dev/null +++ b/src/file.c @@ -0,0 +1,53 @@ +#include + +int cr_file_match_str(FILE* f, const char *str) { + size_t len = strlen(str); + + char buf[512]; + size_t read; + int matches = 0; + while ((read = fread(buf, 1, sizeof (buf), f)) > 0) { + matches = !strncmp(buf, str, read); + if (!matches || read > len) { + matches = 0; + break; + } + + len -= read; + str += read; + } + + // consume the rest of what's available + while (fread(buf, 1, sizeof (buf), f) > 0); + + return matches; +} + +int cr_file_match_file(FILE* f, FILE* ref) { + char buf1[512]; + char buf2[512]; + + fpos_t orig_pos; + fgetpos(ref, &orig_pos); + rewind(ref); + + size_t read1 = 1, read2 = 1; + int matches = 0; + while ((read1 = fread(buf1, 1, sizeof (buf1), f)) > 0 + && (read2 = fread(buf2, 1, sizeof (buf2), ref)) > 0) { + + if (read1 != read2) { + matches = 0; + break; + } + + matches = !memcmp(buf1, buf2, read1); + } + + // consume the rest of what's available + while (fread(buf1, 1, sizeof (buf1), f) > 0); + + fsetpos(ref, &orig_pos); + + return matches; +} diff --git a/src/posix-compat.c b/src/posix-compat.c index 21c2c33a..72dd6db0 100644 --- a/src/posix-compat.c +++ b/src/posix-compat.c @@ -581,26 +581,3 @@ FILE* cr_get_redirected_stdin(void) { } return f; } - -int cr_file_match_str(FILE* f, const char *str) { - size_t len = strlen(str); - - char buf[512]; - size_t read; - int matches = 0; - while ((read = fread(buf, 1, sizeof (buf), f)) > 0) { - matches = !strncmp(buf, str, read); - if (!matches || read > len) { - matches = 0; - break; - } - - len -= read; - str += read; - } - - // consume the rest of what's available - while (fread(buf, 1, sizeof (buf), f) > 0); - - return matches; -} From 8986414138fdc21a3174fff800bbfab0d4fb53dd Mon Sep 17 00:00:00 2001 From: Snaipe Date: Mon, 14 Sep 2015 04:15:48 +0200 Subject: [PATCH 173/174] Added default message to file asserts --- include/criterion/assert.h | 1 + include/criterion/redirect.h | 44 ++++++++++++++++++++++++++---------- po/fr.po | 9 ++++++-- src/i18n.c | 2 ++ 4 files changed, 42 insertions(+), 14 deletions(-) diff --git a/include/criterion/assert.h b/include/criterion/assert.h index 018a0c1a..f29860ed 100644 --- a/include/criterion/assert.h +++ b/include/criterion/assert.h @@ -63,6 +63,7 @@ enum criterion_assert_messages { 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, diff --git a/include/criterion/redirect.h b/include/criterion/redirect.h index 2b8492fc..7adaf9b3 100644 --- a/include/criterion/redirect.h +++ b/include/criterion/redirect.h @@ -74,17 +74,37 @@ CR_END_C_API 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__)) # define cr_assert_file_contents_neq_str(...) CR_EXPAND(cr_assert_redir_op_va_(CR_FAIL_ABORT_, cr_file_match_str, !=, __VA_ARGS__)) # define cr_expect_file_contents_neq_str(...) CR_EXPAND(cr_assert_redir_op_va_(CR_FAIL_CONTINUES_, cr_file_match_str, !=, __VA_ARGS__)) -# define cr_assert_file_contents_eq(...) CR_EXPAND(cr_assert_redir_op_va_(CR_FAIL_ABORT_, cr_file_match_file, ==, __VA_ARGS__)) -# define cr_expect_file_contents_eq(...) CR_EXPAND(cr_assert_redir_op_va_(CR_FAIL_CONTINUES_, cr_file_match_file, ==, __VA_ARGS__)) +# define cr_assert_file_contents_eq(...) CR_EXPAND(cr_assert_redir_f_op_va_(CR_FAIL_ABORT_, cr_file_match_file, ==, __VA_ARGS__)) +# define cr_expect_file_contents_eq(...) CR_EXPAND(cr_assert_redir_f_op_va_(CR_FAIL_CONTINUES_, cr_file_match_file, ==, __VA_ARGS__)) -# define cr_assert_file_contents_neq(...) CR_EXPAND(cr_assert_redir_op_va_(CR_FAIL_ABORT_, cr_file_match_file, !=, __VA_ARGS__)) -# define cr_expect_file_contents_neq(...) CR_EXPAND(cr_assert_redir_op_va_(CR_FAIL_CONTINUES_, cr_file_match_file, !=, __VA_ARGS__)) +# define cr_assert_file_contents_neq(...) CR_EXPAND(cr_assert_redir_f_op_va_(CR_FAIL_ABORT_, cr_file_match_file, !=, __VA_ARGS__)) +# define cr_expect_file_contents_neq(...) CR_EXPAND(cr_assert_redir_f_op_va_(CR_FAIL_CONTINUES_, cr_file_match_file, !=, __VA_ARGS__)) # define cr_assert_stdout_eq_str(...) CR_EXPAND(cr_assert_redir_op_va_(CR_FAIL_ABORT_, cr_file_match_str, ==, cr_get_redirected_stdout(), __VA_ARGS__)) # define cr_expect_stdout_eq_str(...) CR_EXPAND(cr_assert_redir_op_va_(CR_FAIL_CONTINUES_, cr_file_match_str, ==, cr_get_redirected_stdout(), __VA_ARGS__)) @@ -98,17 +118,17 @@ CR_END_C_API # define cr_assert_stderr_neq_str(...) CR_EXPAND(cr_assert_redir_op_va_(CR_FAIL_ABORT_, cr_file_match_str, !=, cr_get_redirected_stderr(), __VA_ARGS__)) # define cr_expect_stderr_neq_str(...) CR_EXPAND(cr_assert_redir_op_va_(CR_FAIL_CONTINUES_, cr_file_match_str, !=, cr_get_redirected_stderr(), __VA_ARGS__)) -# define cr_assert_stdout_eq(...) CR_EXPAND(cr_assert_redir_op_va_(CR_FAIL_ABORT_, cr_file_match_file, ==, cr_get_redirected_stdout(), __VA_ARGS__)) -# define cr_expect_stdout_eq(...) CR_EXPAND(cr_assert_redir_op_va_(CR_FAIL_CONTINUES_, cr_file_match_file, ==, cr_get_redirected_stdout(), __VA_ARGS__)) +# define cr_assert_stdout_eq(...) CR_EXPAND(cr_assert_redir_f_op_va_(CR_FAIL_ABORT_, cr_file_match_file, ==, cr_get_redirected_stdout(), __VA_ARGS__)) +# define cr_expect_stdout_eq(...) CR_EXPAND(cr_assert_redir_f_op_va_(CR_FAIL_CONTINUES_, cr_file_match_file, ==, cr_get_redirected_stdout(), __VA_ARGS__)) -# define cr_assert_stdout_neq(...) CR_EXPAND(cr_assert_redir_op_va_(CR_FAIL_ABORT_, cr_file_match_file, !=, cr_get_redirected_stdout(), __VA_ARGS__)) -# define cr_expect_stdout_neq(...) CR_EXPAND(cr_assert_redir_op_va_(CR_FAIL_CONTINUES_, cr_file_match_file, !=, cr_get_redirected_stdout(), __VA_ARGS__)) +# define cr_assert_stdout_neq(...) CR_EXPAND(cr_assert_redir_f_op_va_(CR_FAIL_ABORT_, cr_file_match_file, !=, cr_get_redirected_stdout(), __VA_ARGS__)) +# define cr_expect_stdout_neq(...) CR_EXPAND(cr_assert_redir_f_op_va_(CR_FAIL_CONTINUES_, cr_file_match_file, !=, cr_get_redirected_stdout(), __VA_ARGS__)) -# define cr_assert_stderr_eq(...) CR_EXPAND(cr_assert_redir_op_va_(CR_FAIL_ABORT_, cr_file_match_file, ==, cr_get_redirected_stderr(), __VA_ARGS__)) -# define cr_expect_stderr_eq(...) CR_EXPAND(cr_assert_redir_op_va_(CR_FAIL_CONTINUES_, cr_file_match_file, ==, cr_get_redirected_stderr(), __VA_ARGS__)) +# define cr_assert_stderr_eq(...) CR_EXPAND(cr_assert_redir_f_op_va_(CR_FAIL_ABORT_, cr_file_match_file, ==, cr_get_redirected_stderr(), __VA_ARGS__)) +# define cr_expect_stderr_eq(...) CR_EXPAND(cr_assert_redir_f_op_va_(CR_FAIL_CONTINUES_, cr_file_match_file, ==, cr_get_redirected_stderr(), __VA_ARGS__)) -# define cr_assert_stderr_neq(...) CR_EXPAND(cr_assert_redir_op_va_(CR_FAIL_ABORT_, cr_file_match_file, !=, cr_get_redirected_stderr(), __VA_ARGS__)) -# define cr_expect_stderr_neq(...) CR_EXPAND(cr_assert_redir_op_va_(CR_FAIL_CONTINUES_, cr_file_match_file, !=, cr_get_redirected_stderr(), __VA_ARGS__)) +# define cr_assert_stderr_neq(...) CR_EXPAND(cr_assert_redir_f_op_va_(CR_FAIL_ABORT_, cr_file_match_file, !=, cr_get_redirected_stderr(), __VA_ARGS__)) +# 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 { diff --git a/po/fr.po b/po/fr.po index aa39d31a..5b3eb93a 100644 --- a/po/fr.po +++ b/po/fr.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: criterion 1.0.0\n" "Report-Msgid-Bugs-To: franklinmathieu+criterion@gmail.com\n" -"POT-Creation-Date: 2015-09-14 02:33+0200\n" +"POT-Creation-Date: 2015-09-14 04:12+0200\n" "PO-Revision-Date: 2015-04-03 17:58+0200\n" "Last-Translator: \n" "Language-Team: French\n" @@ -161,11 +161,16 @@ msgstr "" "\"." #: src/i18n.c:25 +#, fuzzy, c-format +msgid "The file contents of %1$s does not match the contents of %2$s." +msgstr "Le contenu du fichier %1$s ne correspond pas au contenu de %2$s." + +#: src/i18n.c:26 #, c-format msgid "The statement `%1$s` did throw an instance of the `%2$s` exception." msgstr "L'instruction `%1$s` a levé une instance de l'exception `%2$s`." -#: src/i18n.c:26 +#: src/i18n.c:27 #, 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`." diff --git a/src/i18n.c b/src/i18n.c index 6df4ccb5..c83a119c 100644 --- a/src/i18n.c +++ b/src/i18n.c @@ -22,10 +22,12 @@ char *translate_assert_msg(int msg_index, ...) { #ifdef ENABLE_NLS [CRITERION_ASSERT_MSG_FILE_STR_MATCH] = N_("The file contents of %1$s does not match the string \"%2$s\"."), + [CRITERION_ASSERT_MSG_FILE_MATCH] = N_("The file contents of %1$s does not match the contents of %2$s."), [CRITERION_ASSERT_MSG_THROW] = N_("The statement `%1$s` did throw an instance of the `%2$s` exception."), [CRITERION_ASSERT_MSG_NO_THROW] = N_("The statement `%1$s` did not throw an instance of the `%2$s` exception."), #else [CRITERION_ASSERT_MSG_FILE_STR_MATCH] = "The file contents of %s does not match the string \"%s\".", + [CRITERION_ASSERT_MSG_FILE_MATCH] = "The file contents of %s does not match the contents of %s.", [CRITERION_ASSERT_MSG_THROW] = "The statement `%s` did throw an instance of the `%s` exception.", [CRITERION_ASSERT_MSG_NO_THROW] = "The statement `%s` did not throw an instance of the `%s` exception.", #endif From 5e275da558ca70b671e3ff0548bb836b7382b9a5 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Mon, 14 Sep 2015 04:16:03 +0200 Subject: [PATCH 174/174] Updated documentation on asserts --- doc/assert.rst | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/doc/assert.rst b/doc/assert.rst index 720bcaf2..46ad0044 100644 --- a/doc/assert.rst +++ b/doc/assert.rst @@ -94,3 +94,51 @@ cr_assert_arr_gt_cmp(Actual, Reference, Size, Cmp, [Message, [Args...]]) ``Ac 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 =========================================================================== =========================================================================== =========================================== +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. +=========================================================================== =========================================================================== =========================================== + +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``. +=============================================================================== ============================================================================ =========================================== +