From 4d114fdd3893d8020b5ed76a4ec054a88852792a Mon Sep 17 00:00:00 2001 From: Snaipe Date: Tue, 8 Sep 2015 18:46:04 +0200 Subject: [PATCH] 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 | 620 +++++++++++++++++----------- 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, 630 insertions(+), 299 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 958a62d..2038e17 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 598b27e..ca981b5 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 0000000..2fc5c1b --- /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 1d67a00..4aeaa9b 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 +// Base assertions -# define cr_abort_test(Message) \ - do { \ - const char *msg = (Message); \ - cr_assert(0, msg ? msg : "The conditions for this test were not met.");\ +# 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 +# define cr_assert_arr_op_cmp_va_(Fail, Op, ...) \ + CR_EXPAND(cr_assert_arr_op_cmp_( \ + Fail, \ + Op, \ + CR_VA_HEAD(__VA_ARGS__), \ + CR_VA_HEAD(CR_VA_TAIL(__VA_ARGS__)), \ + CR_VA_HEAD(CR_VA_TAIL(CR_VA_TAIL(__VA_ARGS__))), \ + CR_VA_HEAD(CR_VA_TAIL(CR_VA_TAIL(CR_VA_TAIL(__VA_ARGS__)))), \ + CR_VA_TAIL(CR_VA_TAIL(CR_VA_TAIL(CR_VA_TAIL(__VA_ARGS__)))) \ + )) + +# define cr_assert_arr_eq_cmp(...) CR_EXPAND(cr_assert_arr_op_cmp_va_(CR_FAIL_ABORT_, ==, __VA_ARGS__)) +# define cr_expect_arr_eq_cmp(...) CR_EXPAND(cr_assert_arr_op_cmp_va_(CR_FAIL_CONTINUES_, ==, __VA_ARGS__)) + +# 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_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_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__)) + +# 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_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__)) + # else -# define CR_SENTINEL .sentinel_ = 0 + +# define CRITERION_GNUC_WARN__(Msg) \ + _Pragma(#Msg) + +# define CRITERION_GNUC_WARN_(Name) CRITERION_GNUC_WARN__( \ + message \ + "The `" #Name "` macro is only available on GNU C compilers." \ + ) + +# define cr_assert_arr_eq_cmp(...) CRITERION_GNUC_WARN_(cr_assert_arr_eq_cmp) CR_NOOP +# define cr_expect_arr_eq_cmp(...) CRITERION_GNUC_WARN_(cr_expect_arr_eq_cmp) CR_NOOP + +# 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_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_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_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_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 + # endif -# define cr_assert(...) CR_EXPAND(cr_assert_(__VA_ARGS__, CR_SENTINEL)) - -# 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__, 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__)) -# define cr_expect_not_(Condition, ...) \ - CR_EXPAND(cr_expect_impl(NORMAL, !(Condition), __VA_ARGS__)) - -// Native asserts - -# 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_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)) - -# 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__, 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__, 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__, 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__, 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_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_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_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) - -# 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) - -# 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__ */ - # 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_assert_throw_(Fail, Statement, Exception, ...) \ + try { \ + Statement; \ + } catch (Exception &ex) { \ + } catch (...) { CR_EXPAND(cr_fail(Fail, CR_VA_TAIL(__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_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__)) -# 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 6d0910a..ae962eb 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 0000000..822e0e3 --- /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 a1d62ed..8d6d4ca 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 0d9daab..2318944 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 c7f5c8f..98cd394 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 6e96a6d..0bbe7cc 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 d0e3dd3..5602754 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 0000000..2eada51 --- /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 83a92e0..ba91d73 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 9f278cf..dedcd5e 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 c58d0fd..76937a0 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