diff --git a/.gitignore b/.gitignore index 94a8695..007b88d 100644 --- a/.gitignore +++ b/.gitignore @@ -13,6 +13,7 @@ !*.m !*.cc !*.h +!*.hxx !*.rst !*.po !*.in diff --git a/CMakeLists.txt b/CMakeLists.txt index 3890768..6ea2b7a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -204,11 +204,20 @@ set(INTERFACE_FILES include/criterion/parameterized.h include/criterion/redirect.h include/criterion/output.h + include/criterion/internal/assert.h + include/criterion/internal/test.h include/criterion/internal/common.h include/criterion/internal/ordered-set.h include/criterion/internal/asprintf-compat.h include/criterion/internal/designated-initializer-compat.h include/criterion/internal/preprocess.h + include/criterion/internal/theories.h + include/criterion/internal/parameterized.h + include/criterion/internal/stdio_filebuf.hxx + include/criterion/internal/stream.hxx + include/criterion/internal/hooks.h + include/criterion/internal/redirect.h + include/criterion/internal/stdio_filebuf.hxx ) # Generate the configure file @@ -243,7 +252,11 @@ if (COVERALLS) coveralls_setup("${SOURCE_FILES}" ${COVERALLS_UPLOAD}) endif() -install(FILES ${INTERFACE_FILES} DESTINATION include/criterion) +foreach (F ${INTERFACE_FILES}) + get_filename_component(DEST "${F}" PATH) + install(FILES "${F}" DESTINATION "${DEST}") +endforeach () + install(TARGETS criterion RUNTIME DESTINATION bin LIBRARY DESTINATION lib diff --git a/include/criterion/assert.h b/include/criterion/assert.h index 1959310..3c69283 100644 --- a/include/criterion/assert.h +++ b/include/criterion/assert.h @@ -28,29 +28,27 @@ # include # endif -# include "assert_base.h" +# include "internal/assert.h" + +CR_BEGIN_C_API + +CR_API char *cr_translate_assert_msg(int msg_index, ...); + +CR_END_C_API + +// Base assertions + +# define cr_assert_fail(...) CR_EXPAND(cr_fail(CR_FAIL_ABORT_, __VA_ARGS__)) +# define cr_expect_fail(...) CR_EXPAND(cr_fail(CR_FAIL_CONTINUES_, __VA_ARGS__)) + +# define cr_assert(...) CR_EXPAND(cr_assert_(__VA_ARGS__)) +# define cr_expect(...) CR_EXPAND(cr_expect_(__VA_ARGS__)) + +# define cr_assert_not(...) CR_EXPAND(cr_assert_not_(__VA_ARGS__)) +# define cr_expect_not(...) CR_EXPAND(cr_expect_not_(__VA_ARGS__)) // Common binary assertions -# define cr_assert_op_(Fail, Op, Actual, Expected, ...) \ - CR_EXPAND(cr_assert_impl( \ - Fail, \ - (Actual) Op (Expected), \ - dummy, \ - CRITERION_ASSERT_MSG_EXPR_FALSE, \ - (CR_STR((Actual) Op (Expected))), \ - __VA_ARGS__ \ - )) - -# define cr_assert_op_va_(Fail, Op, ...) \ - CR_EXPAND(cr_assert_op_( \ - Fail, \ - Op, \ - CR_VA_HEAD(__VA_ARGS__), \ - CR_VA_HEAD(CR_VA_TAIL(__VA_ARGS__)), \ - CR_VA_TAIL(CR_VA_TAIL(__VA_ARGS__)) \ - )) - # define cr_assert_eq(...) CR_EXPAND(cr_assert_op_va_(CR_FAIL_ABORT_, ==, __VA_ARGS__)) # define cr_expect_eq(...) CR_EXPAND(cr_assert_op_va_(CR_FAIL_CONTINUES_, ==, __VA_ARGS__)) @@ -71,25 +69,6 @@ // Common unary assertions -# define cr_assert_null_op_(Fail, Op, Msg, Value, ...) \ - CR_EXPAND(cr_assert_impl( \ - Fail, \ - (Value) Op NULL, \ - dummy, \ - Msg, \ - (CR_STR(Value)), \ - __VA_ARGS__ \ - )) - -# define cr_assert_null_op_va_(Fail, Op, Msg, ...) \ - CR_EXPAND(cr_assert_null_op_( \ - Fail, \ - Op, \ - Msg, \ - CR_VA_HEAD(__VA_ARGS__), \ - CR_VA_TAIL(__VA_ARGS__) \ - )) - # define cr_assert_null(...) CR_EXPAND(cr_assert_null_op_va_(CR_FAIL_ABORT_, ==, CRITERION_ASSERT_MSG_IS_NOT_NULL, __VA_ARGS__)) # define cr_expect_null(...) CR_EXPAND(cr_assert_null_op_va_(CR_FAIL_CONTINUES_, ==, CRITERION_ASSERT_MSG_IS_NOT_NULL, __VA_ARGS__)) @@ -98,32 +77,6 @@ // Floating-point assertions -# define cr_assert_float_eq_op_(Actual, Expected, Epsilon) \ - (Expected) - (Actual) <= (Epsilon) && (Actual) - (Expected) <= (Epsilon) - -# define cr_assert_float_neq_op_(Actual, Expected, Epsilon) \ - (Expected) - (Actual) > (Epsilon) || (Actual) - (Expected) > (Epsilon) - -# define cr_assert_float_op_(Fail, Op, Actual, Expected, Epsilon, ...) \ - CR_EXPAND(cr_assert_impl( \ - Fail, \ - Op(Actual, Expected, Epsilon), \ - dummy, \ - CRITERION_ASSERT_MSG_EXPR_FALSE, \ - (CR_STR(Op(Actual, Expected, Epsilon))), \ - __VA_ARGS__ \ - )) - -# define cr_assert_float_op_va_(Fail, Op, ...) \ - CR_EXPAND(cr_assert_float_op_( \ - Fail, \ - Op, \ - CR_VA_HEAD(__VA_ARGS__), \ - CR_VA_HEAD(CR_VA_TAIL(__VA_ARGS__)), \ - CR_VA_HEAD(CR_VA_TAIL(CR_VA_TAIL(__VA_ARGS__))), \ - CR_VA_TAIL(CR_VA_TAIL(CR_VA_TAIL(__VA_ARGS__))) \ - )) - # define cr_assert_float_eq(...) CR_EXPAND(cr_assert_float_op_va_(CR_FAIL_ABORT_, cr_assert_float_eq_op_, __VA_ARGS__)) # define cr_expect_float_eq(...) CR_EXPAND(cr_assert_float_op_va_(CR_FAIL_CONTINUES_, cr_assert_float_eq_op_, __VA_ARGS__)) @@ -132,50 +85,12 @@ // String assertions -# define cr_assert_str_op_empty_(Fail, Op, Msg, Value, ...) \ - CR_EXPAND(cr_assert_impl( \ - Fail, \ - (Value)[0] Op '\0', \ - dummy, \ - Msg, \ - (CR_STR(Value)), \ - __VA_ARGS__ \ - )) - -# define cr_assert_str_op_empty_va_(Fail, Op, Msg, ...) \ - CR_EXPAND(cr_assert_str_op_empty_( \ - Fail, \ - Op, \ - Msg, \ - CR_VA_HEAD(__VA_ARGS__), \ - CR_VA_TAIL(__VA_ARGS__) \ - )) - # define cr_assert_str_empty(...) CR_EXPAND(cr_assert_str_op_empty_va_(CR_FAIL_ABORT_, ==, CRITERION_ASSERT_MSG_IS_NOT_EMPTY, __VA_ARGS__)) # define cr_expect_str_empty(...) CR_EXPAND(cr_assert_str_op_empty_va_(CR_FAIL_CONTINUES_, ==, CRITERION_ASSERT_MSG_IS_NOT_EMPTY, __VA_ARGS__)) # define cr_assert_str_not_empty(...) CR_EXPAND(cr_assert_str_op_empty_va_(CR_FAIL_ABORT_, !=, CRITERION_ASSERT_MSG_IS_EMPTY, __VA_ARGS__)) # define cr_expect_str_not_empty(...) CR_EXPAND(cr_assert_str_op_empty_va_(CR_FAIL_CONTINUES_, !=, CRITERION_ASSERT_MSG_IS_EMPTY, __VA_ARGS__)) -# define cr_assert_str_op_(Fail, Op, Actual, Expected, ...) \ - CR_EXPAND(cr_assert_impl( \ - Fail, \ - CR_STDN strcmp((Actual), (Expected)) Op 0, \ - dummy, \ - CRITERION_ASSERT_MSG_EXPR_AS_STRINGS_FALSE, \ - (CR_STR((Actual) Op (Expected))), \ - __VA_ARGS__ \ - )) - -# define cr_assert_str_op_va_(Fail, Op, ...) \ - CR_EXPAND(cr_assert_str_op_( \ - Fail, \ - Op, \ - CR_VA_HEAD(__VA_ARGS__), \ - CR_VA_HEAD(CR_VA_TAIL(__VA_ARGS__)), \ - CR_VA_TAIL(CR_VA_TAIL(__VA_ARGS__)) \ - )) - # define cr_assert_str_eq(...) CR_EXPAND(cr_assert_str_op_va_(CR_FAIL_ABORT_, ==, __VA_ARGS__)) # define cr_expect_str_eq(...) CR_EXPAND(cr_assert_str_op_va_(CR_FAIL_CONTINUES_, ==, __VA_ARGS__)) @@ -196,26 +111,6 @@ // Array assertions -# define cr_assert_mem_op_(Fail, Op, Actual, Expected, Size, ...) \ - CR_EXPAND(cr_assert_impl( \ - Fail, \ - CR_STDN memcmp((Actual), (Expected), (Size)) Op 0, \ - dummy, \ - CRITERION_ASSERT_MSG_EXPR_FALSE, \ - (CR_STR((Actual)[0 .. Size] Op (Expected)[0 .. Size])), \ - __VA_ARGS__ \ - )) - -# define cr_assert_mem_op_va_(Fail, Op, ...) \ - CR_EXPAND(cr_assert_mem_op_( \ - Fail, \ - Op, \ - CR_VA_HEAD(__VA_ARGS__), \ - CR_VA_HEAD(CR_VA_TAIL(__VA_ARGS__)), \ - CR_VA_HEAD(CR_VA_TAIL(CR_VA_TAIL(__VA_ARGS__))), \ - CR_VA_TAIL(CR_VA_TAIL(CR_VA_TAIL(__VA_ARGS__))) \ - )) - # define cr_assert_arr_eq(...) CR_EXPAND(cr_assert_mem_op_va_(CR_FAIL_ABORT_, ==, __VA_ARGS__)) # define cr_expect_arr_eq(...) CR_EXPAND(cr_assert_mem_op_va_(CR_FAIL_CONTINUES_, ==, __VA_ARGS__)) @@ -226,43 +121,6 @@ # if defined(__GNUC__) || defined(__clang__) || defined(__cplusplus) -# ifdef __cplusplus -# define CR_ARR_COMPARE_(A, B, Size, Cmp, Result) \ - int Result = std::lexicographical_compare((A), (A) + Size, (B), (B) + Size, Cmp) -# else -# define CR_ARR_COMPARE_(A, B, Size, Cmp, Result) \ - __typeof__(&(A)[0]) first = (A); \ - __typeof__(&(B)[0]) second = (B); \ - int Result = 0; \ - size_t i, size; \ - for (i = 0, size = (Size); !Result && i < size; ++i) \ - Result = Cmp(first + i, second + i) -# endif - -# define cr_assert_arr_op_cmp_(Fail, Op, Actual, Expected, Size, Cmp, ...) \ - do { \ - CR_ARR_COMPARE_(Actual, Expected, Size, Cmp, order); \ - CR_EXPAND(cr_assert_impl( \ - Fail, \ - order Op 0, \ - dummy, \ - CRITERION_ASSERT_MSG_EXPR_FALSE, \ - (CR_STR((Actual)[0 .. Size] Op (Expected)[0 .. Size])), \ - __VA_ARGS__ \ - )); \ - } while (0) - -# define cr_assert_arr_op_cmp_va_(Fail, Op, ...) \ - CR_EXPAND(cr_assert_arr_op_cmp_( \ - Fail, \ - Op, \ - CR_VA_HEAD(__VA_ARGS__), \ - CR_VA_HEAD(CR_VA_TAIL(__VA_ARGS__)), \ - CR_VA_HEAD(CR_VA_TAIL(CR_VA_TAIL(__VA_ARGS__))), \ - CR_VA_HEAD(CR_VA_TAIL(CR_VA_TAIL(CR_VA_TAIL(__VA_ARGS__)))), \ - CR_VA_TAIL(CR_VA_TAIL(CR_VA_TAIL(CR_VA_TAIL(__VA_ARGS__)))) \ - )) - # define cr_assert_arr_eq_cmp(...) CR_EXPAND(cr_assert_arr_op_cmp_va_(CR_FAIL_ABORT_, ==, __VA_ARGS__)) # define cr_expect_arr_eq_cmp(...) CR_EXPAND(cr_assert_arr_op_cmp_va_(CR_FAIL_CONTINUES_, ==, __VA_ARGS__)) @@ -283,14 +141,6 @@ # else -# define CRITERION_GNUC_WARN__(Msg) \ - _Pragma(#Msg) - -# define CRITERION_GNUC_WARN_(Name) CRITERION_GNUC_WARN__( \ - message \ - "The `" #Name "` macro is only available on GNU C compilers." \ - ) - # define cr_assert_arr_eq_cmp(...) CRITERION_GNUC_WARN_(cr_assert_arr_eq_cmp) CR_NOOP # define cr_expect_arr_eq_cmp(...) CRITERION_GNUC_WARN_(cr_expect_arr_eq_cmp) CR_NOOP @@ -313,103 +163,15 @@ # ifdef __cplusplus -# define cr_assert_throw_abort_(Fail, Msg, MsgArgs, ...) \ - CR_EXPAND(cr_assert_impl( \ - Fail, \ - 0, \ - dummy, \ - Msg, \ - MsgArgs, \ - CR_VA_TAIL(__VA_ARGS__) \ - )) - -# define cr_assert_throw_(Fail, Statement, Exception, ...) \ - try { \ - Statement; \ - } catch (Exception const &) { \ - } catch (...) { \ - CR_EXPAND(cr_assert_throw_abort_( \ - Fail, \ - CRITERION_ASSERT_MSG_NO_THROW, \ - (CR_STR(Statement), CR_STR(Exception)), \ - __VA_ARGS__)); \ - } - -# define cr_assert_throw_va_(...) \ - CR_EXPAND(cr_assert_throw_( \ - CR_VA_HEAD(__VA_ARGS__), \ - CR_VA_HEAD(CR_VA_TAIL(__VA_ARGS__)), \ - CR_VA_HEAD(CR_VA_TAIL(CR_VA_TAIL(__VA_ARGS__))), \ - dummy, \ - CR_VA_TAIL(CR_VA_TAIL(CR_VA_TAIL(__VA_ARGS__))) \ - )) - # define cr_assert_throw(...) CR_EXPAND(cr_assert_throw_va_(CR_FAIL_ABORT_, __VA_ARGS__)) # define cr_expect_throw(...) CR_EXPAND(cr_assert_throw_va_(CR_FAIL_CONTINUES_, __VA_ARGS__)) -# define cr_assert_no_throw_(Fail, Statement, Exception, ...) \ - try { \ - Statement; \ - } catch (Exception const &) { \ - CR_EXPAND(cr_assert_throw_abort_( \ - Fail, \ - CRITERION_ASSERT_MSG_THROW, \ - (CR_STR(Statement), CR_STR(Exception)), \ - __VA_ARGS__)); \ - } - -# define cr_assert_no_throw_va_(...) \ - CR_EXPAND(cr_assert_no_throw_( \ - CR_VA_HEAD(__VA_ARGS__), \ - CR_VA_HEAD(CR_VA_TAIL(__VA_ARGS__)), \ - CR_VA_HEAD(CR_VA_TAIL(CR_VA_TAIL(__VA_ARGS__))), \ - dummy, \ - CR_VA_TAIL(CR_VA_TAIL(CR_VA_TAIL(__VA_ARGS__))) \ - )) - # define cr_assert_no_throw(...) CR_EXPAND(cr_assert_no_throw_va_(CR_FAIL_ABORT_, __VA_ARGS__)) # define cr_expect_no_throw(...) CR_EXPAND(cr_assert_no_throw_va_(CR_FAIL_CONTINUES_, __VA_ARGS__)) -# define cr_assert_any_throw_(Fail, Statement, ...) \ - try { \ - Statement; \ - CR_EXPAND(cr_assert_throw_abort_( \ - Fail, \ - CRITERION_ASSERT_MSG_ANY_THROW, \ - (CR_STR(Statement)), \ - __VA_ARGS__)); \ - } catch (...) {} - -# define cr_assert_any_throw_va_(...) \ - CR_EXPAND(cr_assert_any_throw_( \ - CR_VA_HEAD(__VA_ARGS__), \ - CR_VA_HEAD(CR_VA_TAIL(__VA_ARGS__)), \ - dummy, \ - CR_VA_TAIL(CR_VA_TAIL(__VA_ARGS__)) \ - )) - # define cr_assert_any_throw(...) CR_EXPAND(cr_assert_any_throw_va_(CR_FAIL_ABORT_, __VA_ARGS__)) # define cr_expect_any_throw(...) CR_EXPAND(cr_assert_any_throw_va_(CR_FAIL_CONTINUES_, __VA_ARGS__)) -# define cr_assert_none_throw_(Fail, Statement, ...) \ - try { \ - Statement; \ - } catch (...) { \ - CR_EXPAND(cr_assert_throw_abort_( \ - Fail, \ - CRITERION_ASSERT_MSG_NONE_THROW, \ - (CR_STR(Statement)), \ - __VA_ARGS__)); \ - } - -# define cr_assert_none_throw_va_(...) \ - CR_EXPAND(cr_assert_none_throw_( \ - CR_VA_HEAD(__VA_ARGS__), \ - CR_VA_HEAD(CR_VA_TAIL(__VA_ARGS__)), \ - dummy, \ - CR_VA_TAIL(CR_VA_TAIL(__VA_ARGS__)) \ - )) - # define cr_assert_none_throw(...) CR_EXPAND(cr_assert_none_throw_va_(CR_FAIL_ABORT_, __VA_ARGS__)) # define cr_expect_none_throw(...) CR_EXPAND(cr_assert_none_throw_va_(CR_FAIL_CONTINUES_, __VA_ARGS__)) diff --git a/include/criterion/criterion.h b/include/criterion/criterion.h index 9549223..c90114e 100644 --- a/include/criterion/criterion.h +++ b/include/criterion/criterion.h @@ -24,79 +24,15 @@ #ifndef CRITERION_H_ # define CRITERION_H_ -# include "internal/designated-initializer-compat.h" -# include "internal/common.h" # include "types.h" # include "assert.h" # include "alloc.h" -# define CR_IDENTIFIER_(Category, Name, Suffix) \ - Category ## _ ## Name ## _ ## Suffix +# include "internal/test.h" -# ifdef __cplusplus -# ifdef __OBJC__ -# define CR_LANG CR_LANG_OBJCXX -# else -# define CR_LANG CR_LANG_CXX -# endif -# else -# ifdef __OBJC__ -# define CR_LANG CR_LANG_OBJC -# else -# define CR_LANG CR_LANG_C -# endif -# endif +# define Test(...) CR_EXPAND(CR_TEST_BASE(__VA_ARGS__, .sentinel_ = 0)) -# ifdef __cplusplus -# define CR_TEST_PROTOTYPE_(Category, Name) \ - extern "C" void CR_IDENTIFIER_(Category, Name, impl)(void) -# else -# define CR_TEST_PROTOTYPE_(Category, Name) \ - void CR_IDENTIFIER_(Category, Name, impl)(void) -# endif - -# define CR_SUITE_IDENTIFIER_(Name, Suffix) \ - suite_ ## Name ## _ ## Suffix - -# define Test(...) CR_EXPAND(Test_(__VA_ARGS__, .sentinel_ = 0)) -# define Test_(Category, Name, ...) \ - CR_TEST_PROTOTYPE_(Category, Name); \ - struct criterion_test_extra_data CR_IDENTIFIER_(Category, Name, extra) = \ - CR_EXPAND(CRITERION_MAKE_STRUCT(struct criterion_test_extra_data, \ - .lang_ = CR_LANG, \ - .kind_ = CR_TEST_NORMAL, \ - .param_ = (struct criterion_test_params(*)(void)) NULL, \ - .identifier_ = #Category "/" #Name, \ - .file_ = __FILE__, \ - .line_ = __LINE__, \ - __VA_ARGS__ \ - )); \ - struct criterion_test CR_IDENTIFIER_(Category, Name, meta) = { \ - #Name, \ - #Category, \ - CR_IDENTIFIER_(Category, Name, impl), \ - &CR_IDENTIFIER_(Category, Name, extra) \ - }; \ - CR_SECTION_("cr_tst") \ - struct criterion_test *CR_IDENTIFIER_(Category, Name, ptr) \ - = &CR_IDENTIFIER_(Category, Name, meta) CR_SECTION_SUFFIX_; \ - CR_TEST_PROTOTYPE_(Category, Name) - -# define TestSuite(...) CR_EXPAND(TestSuite_(__VA_ARGS__, .sentinel_ = 0)) -# define TestSuite_(Name, ...) \ - struct criterion_test_extra_data CR_SUITE_IDENTIFIER_(Name, extra) = \ - CR_EXPAND(CRITERION_MAKE_STRUCT(struct criterion_test_extra_data, \ - .file_ = __FILE__, \ - .line_ = 0, \ - __VA_ARGS__ \ - )); \ - struct criterion_suite CR_SUITE_IDENTIFIER_(Name, meta) = { \ - #Name, \ - &CR_SUITE_IDENTIFIER_(Name, extra), \ - }; \ - CR_SECTION_("cr_sts") \ - struct criterion_suite *CR_SUITE_IDENTIFIER_(Name, ptr) \ - = &CR_SUITE_IDENTIFIER_(Name, meta) CR_SECTION_SUFFIX_ +# define TestSuite(...) CR_EXPAND(CR_SUITE_BASE(__VA_ARGS__, .sentinel_ = 0)) CR_BEGIN_C_API diff --git a/include/criterion/hooks.h b/include/criterion/hooks.h index 5f622b2..a7559c6 100644 --- a/include/criterion/hooks.h +++ b/include/criterion/hooks.h @@ -24,8 +24,7 @@ #ifndef CRITERION_HOOKS_H_ # define CRITERION_HOOKS_H_ -# include "internal/common.h" -# include "types.h" +# include "internal/hooks.h" typedef enum { PRE_ALL, @@ -43,57 +42,6 @@ typedef enum { typedef void (*f_report_hook)(); -# define CR_HOOK_IDENTIFIER_(Suffix) CR_HOOK_IDENTIFIER__(__LINE__, Suffix) -# define CR_HOOK_IDENTIFIER__(Line, Suffix) CR_HOOK_IDENTIFIER___(Line, Suffix) -# define CR_HOOK_IDENTIFIER___(Line, Suffix) hook_l ## Line ## _ ## Suffix - -# ifdef __cplusplus -# define CR_HOOK_PROTOTYPE_ \ - extern "C" void CR_HOOK_IDENTIFIER_(impl) -# else -# define CR_HOOK_PROTOTYPE_ \ - void CR_HOOK_IDENTIFIER_(impl) -# endif - -// Section abbreviations -# define CR_HOOK_SECTION_PRE_ALL cr_pra -# define CR_HOOK_SECTION_PRE_SUITE cr_prs -# define CR_HOOK_SECTION_PRE_INIT cr_pri -# define CR_HOOK_SECTION_PRE_TEST cr_prt -# define CR_HOOK_SECTION_ASSERT cr_ast -# define CR_HOOK_SECTION_THEORY_FAIL cr_thf -# define CR_HOOK_SECTION_TEST_CRASH cr_tsc -# define CR_HOOK_SECTION_POST_TEST cr_pot -# define CR_HOOK_SECTION_POST_FINI cr_pof -# define CR_HOOK_SECTION_POST_SUITE cr_pos -# define CR_HOOK_SECTION_POST_ALL cr_poa - -# define CR_HOOK_SECTION(Kind) CR_HOOK_SECTION_ ## Kind - -# define CR_HOOK_SECTION_STRINGIFY__(Sec) #Sec -# define CR_HOOK_SECTION_STRINGIFY_(Sec) CR_HOOK_SECTION_STRINGIFY__(Sec) -# define CR_HOOK_SECTION_STRINGIFY(Kind) CR_HOOK_SECTION_STRINGIFY_(CR_HOOK_SECTION(Kind)) - -# define CR_HOOK_PARAM_TYPE_PRE_ALL struct criterion_test_set * -# define CR_HOOK_PARAM_TYPE_PRE_SUITE struct criterion_suite_set * -# define CR_HOOK_PARAM_TYPE_PRE_INIT struct criterion_test * -# define CR_HOOK_PARAM_TYPE_PRE_TEST struct criterion_test * -# define CR_HOOK_PARAM_TYPE_ASSERT struct criterion_assert_stats * -# define CR_HOOK_PARAM_TYPE_THEORY_FAIL struct criterion_theory_stats * -# define CR_HOOK_PARAM_TYPE_TEST_CRASH struct criterion_test_stats * -# define CR_HOOK_PARAM_TYPE_POST_TEST struct criterion_test_stats * -# define CR_HOOK_PARAM_TYPE_POST_FINI struct criterion_test_stats * -# define CR_HOOK_PARAM_TYPE_POST_SUITE struct criterion_suite_stats * -# define CR_HOOK_PARAM_TYPE_POST_ALL struct criterion_global_stats * - -# define CR_HOOK_PARAM_TYPE(Kind) CR_HOOK_PARAM_TYPE_ ## Kind - -# define ReportHook(Kind) \ - CR_HOOK_PROTOTYPE_(CR_HOOK_PARAM_TYPE(Kind)); \ - CR_SECTION_(CR_HOOK_SECTION_STRINGIFY(Kind)) \ - f_report_hook CR_HOOK_IDENTIFIER_(func) = \ - (f_report_hook) CR_HOOK_IDENTIFIER_(impl) \ - CR_SECTION_SUFFIX_; \ - CR_HOOK_PROTOTYPE_ +# define ReportHook(Kind) CR_REPORT_HOOK_IMPL(Kind) #endif /* !CRITERION_HOOKS_H_ */ diff --git a/include/criterion/assert_base.h b/include/criterion/internal/assert.h similarity index 59% rename from include/criterion/assert_base.h rename to include/criterion/internal/assert.h index f539598..426e3ae 100644 --- a/include/criterion/assert_base.h +++ b/include/criterion/internal/assert.h @@ -21,11 +21,13 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -#ifndef CRITERION_ASSERT_BASE_H_ -# define CRITERION_ASSERT_BASE_H_ +#ifndef CRITERION_INTERNAL_ASSERT_H_ +# define CRITERION_INTERNAL_ASSERT_H_ -# include "internal/preprocess.h" -# include "internal/asprintf-compat.h" +# include "common.h" +# include "preprocess.h" +# include "asprintf-compat.h" +# include "designated-initializer-compat.h" # ifdef __cplusplus # include @@ -35,12 +37,11 @@ # include # include # endif -# include "internal/designated-initializer-compat.h" -# include "types.h" -# include "stats.h" -# include "hooks.h" -# include "event.h" -# include "abort.h" +# include "../types.h" +# include "../stats.h" +# include "../hooks.h" +# include "../event.h" +# include "../abort.h" struct criterion_assert_args { const char *msg; @@ -69,12 +70,6 @@ enum criterion_assert_messages { CRITERION_ASSERT_MSG_NONE_THROW, }; -CR_BEGIN_C_API - -CR_API char *cr_translate_assert_msg(int msg_index, ...); - -CR_END_C_API - # define CR_GET_CONDITION(Condition, ...) Condition # define CR_GET_CONDITION_STR(Condition, ...) #Condition # define CR_VA_SKIP(_, ...) __VA_ARGS__ @@ -151,8 +146,6 @@ CR_END_C_API Fail(); \ } while (0) -// Base assertions - # define cr_fail(Fail, ...) \ CR_EXPAND(cr_assert_impl( \ Fail, \ @@ -163,10 +156,7 @@ CR_END_C_API __VA_ARGS__ \ )) -# define cr_assert_fail(...) CR_EXPAND(cr_fail(CR_FAIL_ABORT_, __VA_ARGS__)) -# define cr_expect_fail(...) CR_EXPAND(cr_fail(CR_FAIL_CONTINUES_, __VA_ARGS__)) - -# define cr_assert(...) \ +# define cr_assert_(...) \ CR_EXPAND(cr_assert_impl( \ CR_FAIL_ABORT_, \ CR_VA_HEAD(__VA_ARGS__), \ @@ -176,7 +166,7 @@ CR_END_C_API CR_VA_TAIL(__VA_ARGS__) \ )) -# define cr_expect(...) \ +# define cr_expect_(...) \ CR_EXPAND(cr_assert_impl( \ CR_FAIL_CONTINUES_, \ CR_VA_HEAD(__VA_ARGS__), \ @@ -186,27 +176,28 @@ CR_END_C_API CR_VA_TAIL(__VA_ARGS__) \ )) -# define cr_assert_not(...) \ - CR_EXPAND(cr_assert_impl( \ - CR_FAIL_ABORT_, \ - !(CR_VA_HEAD(__VA_ARGS__)), \ - dummy, \ - CRITERION_ASSERT_MSG_EXPR_FALSE, \ - (CR_STR(!(CR_VA_HEAD(__VA_ARGS__)))), \ - CR_VA_TAIL(__VA_ARGS__) \ +# define cr_assert_not_(...) \ + CR_EXPAND(cr_assert_impl( \ + CR_FAIL_ABORT_, \ + !(CR_VA_HEAD(__VA_ARGS__)), \ + dummy, \ + CRITERION_ASSERT_MSG_EXPR_FALSE, \ + (CR_STR(!(CR_VA_HEAD(__VA_ARGS__)))), \ + CR_VA_TAIL(__VA_ARGS__) \ )) -# define cr_expect_not(...) \ - CR_EXPAND(cr_assert_impl( \ - CR_FAIL_CONTINUES_, \ - !(CR_VA_HEAD(__VA_ARGS__)), \ - dummy, \ - CRITERION_ASSERT_MSG_EXPR_FALSE, \ - (CR_STR(!(CR_VA_HEAD(__VA_ARGS__)))), \ - CR_VA_TAIL(__VA_ARGS__) \ +# define cr_expect_not_(...) \ + CR_EXPAND(cr_assert_impl( \ + CR_FAIL_CONTINUES_, \ + !(CR_VA_HEAD(__VA_ARGS__)), \ + dummy, \ + CRITERION_ASSERT_MSG_EXPR_FALSE, \ + (CR_STR(!(CR_VA_HEAD(__VA_ARGS__)))), \ + CR_VA_TAIL(__VA_ARGS__) \ )) -// Common binary assertions + +// Binary # define cr_assert_op_(Fail, Op, Actual, Expected, ...) \ CR_EXPAND(cr_assert_impl( \ @@ -227,25 +218,7 @@ CR_END_C_API CR_VA_TAIL(CR_VA_TAIL(__VA_ARGS__)) \ )) -# define cr_assert_eq(...) CR_EXPAND(cr_assert_op_va_(CR_FAIL_ABORT_, ==, __VA_ARGS__)) -# define cr_expect_eq(...) CR_EXPAND(cr_assert_op_va_(CR_FAIL_CONTINUES_, ==, __VA_ARGS__)) - -# define cr_assert_neq(...) CR_EXPAND(cr_assert_op_va_(CR_FAIL_ABORT_, !=, __VA_ARGS__)) -# define cr_expect_neq(...) CR_EXPAND(cr_assert_op_va_(CR_FAIL_CONTINUES_, !=, __VA_ARGS__)) - -# define cr_assert_lt(...) CR_EXPAND(cr_assert_op_va_(CR_FAIL_ABORT_, <, __VA_ARGS__)) -# define cr_expect_lt(...) CR_EXPAND(cr_assert_op_va_(CR_FAIL_CONTINUES_, <, __VA_ARGS__)) - -# define cr_assert_leq(...) CR_EXPAND(cr_assert_op_va_(CR_FAIL_ABORT_, <=, __VA_ARGS__)) -# define cr_expect_leq(...) CR_EXPAND(cr_assert_op_va_(CR_FAIL_CONTINUES_, <=, __VA_ARGS__)) - -# define cr_assert_gt(...) CR_EXPAND(cr_assert_op_va_(CR_FAIL_ABORT_, >, __VA_ARGS__)) -# define cr_expect_gt(...) CR_EXPAND(cr_assert_op_va_(CR_FAIL_CONTINUES_, >, __VA_ARGS__)) - -# define cr_assert_geq(...) CR_EXPAND(cr_assert_op_va_(CR_FAIL_ABORT_, >=, __VA_ARGS__)) -# define cr_expect_geq(...) CR_EXPAND(cr_assert_op_va_(CR_FAIL_CONTINUES_, >=, __VA_ARGS__)) - -// Common unary assertions +// Unary # define cr_assert_null_op_(Fail, Op, Msg, Value, ...) \ CR_EXPAND(cr_assert_impl( \ @@ -266,13 +239,7 @@ CR_END_C_API CR_VA_TAIL(__VA_ARGS__) \ )) -# define cr_assert_null(...) CR_EXPAND(cr_assert_null_op_va_(CR_FAIL_ABORT_, ==, CRITERION_ASSERT_MSG_IS_NOT_NULL, __VA_ARGS__)) -# define cr_expect_null(...) CR_EXPAND(cr_assert_null_op_va_(CR_FAIL_CONTINUES_, ==, CRITERION_ASSERT_MSG_IS_NOT_NULL, __VA_ARGS__)) - -# define cr_assert_not_null(...) CR_EXPAND(cr_assert_null_op_va_(CR_FAIL_ABORT_, !=, CRITERION_ASSERT_MSG_IS_NULL, __VA_ARGS__)) -# define cr_expect_not_null(...) CR_EXPAND(cr_assert_null_op_va_(CR_FAIL_CONTINUES_, !=, CRITERION_ASSERT_MSG_IS_NULL, __VA_ARGS__)) - -// Floating-point assertions +// Floating point # define cr_assert_float_eq_op_(Actual, Expected, Epsilon) \ (Expected) - (Actual) <= (Epsilon) && (Actual) - (Expected) <= (Epsilon) @@ -300,13 +267,7 @@ CR_END_C_API CR_VA_TAIL(CR_VA_TAIL(CR_VA_TAIL(__VA_ARGS__))) \ )) -# define cr_assert_float_eq(...) CR_EXPAND(cr_assert_float_op_va_(CR_FAIL_ABORT_, cr_assert_float_eq_op_, __VA_ARGS__)) -# define cr_expect_float_eq(...) CR_EXPAND(cr_assert_float_op_va_(CR_FAIL_CONTINUES_, cr_assert_float_eq_op_, __VA_ARGS__)) - -# define cr_assert_float_neq(...) CR_EXPAND(cr_assert_float_op_va_(CR_FAIL_ABORT_, cr_assert_float_neq_op_, __VA_ARGS__)) -# define cr_expect_float_neq(...) CR_EXPAND(cr_assert_float_op_va_(CR_FAIL_CONTINUES_, cr_assert_float_neq_op_, __VA_ARGS__)) - -// String assertions +// String # define cr_assert_str_op_empty_(Fail, Op, Msg, Value, ...) \ CR_EXPAND(cr_assert_impl( \ @@ -327,12 +288,6 @@ CR_END_C_API CR_VA_TAIL(__VA_ARGS__) \ )) -# define cr_assert_str_empty(...) CR_EXPAND(cr_assert_str_op_empty_va_(CR_FAIL_ABORT_, ==, CRITERION_ASSERT_MSG_IS_NOT_EMPTY, __VA_ARGS__)) -# define cr_expect_str_empty(...) CR_EXPAND(cr_assert_str_op_empty_va_(CR_FAIL_CONTINUES_, ==, CRITERION_ASSERT_MSG_IS_NOT_EMPTY, __VA_ARGS__)) - -# define cr_assert_str_not_empty(...) CR_EXPAND(cr_assert_str_op_empty_va_(CR_FAIL_ABORT_, !=, CRITERION_ASSERT_MSG_IS_EMPTY, __VA_ARGS__)) -# define cr_expect_str_not_empty(...) CR_EXPAND(cr_assert_str_op_empty_va_(CR_FAIL_CONTINUES_, !=, CRITERION_ASSERT_MSG_IS_EMPTY, __VA_ARGS__)) - # define cr_assert_str_op_(Fail, Op, Actual, Expected, ...) \ CR_EXPAND(cr_assert_impl( \ Fail, \ @@ -352,22 +307,165 @@ CR_END_C_API CR_VA_TAIL(CR_VA_TAIL(__VA_ARGS__)) \ )) -# define cr_assert_str_eq(...) CR_EXPAND(cr_assert_str_op_va_(CR_FAIL_ABORT_, ==, __VA_ARGS__)) -# define cr_expect_str_eq(...) CR_EXPAND(cr_assert_str_op_va_(CR_FAIL_CONTINUES_, ==, __VA_ARGS__)) +// Array -# define cr_assert_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_mem_op_(Fail, Op, Actual, Expected, Size, ...) \ + CR_EXPAND(cr_assert_impl( \ + Fail, \ + CR_STDN memcmp((Actual), (Expected), (Size)) Op 0, \ + dummy, \ + CRITERION_ASSERT_MSG_EXPR_FALSE, \ + (CR_STR((Actual)[0 .. Size] Op (Expected)[0 .. Size])), \ + __VA_ARGS__ \ + )) -# define cr_assert_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_mem_op_va_(Fail, Op, ...) \ + CR_EXPAND(cr_assert_mem_op_( \ + Fail, \ + Op, \ + CR_VA_HEAD(__VA_ARGS__), \ + CR_VA_HEAD(CR_VA_TAIL(__VA_ARGS__)), \ + CR_VA_HEAD(CR_VA_TAIL(CR_VA_TAIL(__VA_ARGS__))), \ + CR_VA_TAIL(CR_VA_TAIL(CR_VA_TAIL(__VA_ARGS__))) \ + )) -# define cr_assert_str_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__)) +// Array comparisons -# 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__)) +# 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_str_geq(...) CR_EXPAND(cr_assert_str_op_va_(CR_FAIL_ABORT_, >=, __VA_ARGS__)) -# define cr_expect_str_geq(...) CR_EXPAND(cr_assert_str_op_va_(CR_FAIL_CONTINUES_, >=, __VA_ARGS__)) +# define cr_assert_arr_op_cmp_(Fail, Op, Actual, Expected, Size, Cmp, ...) \ + do { \ + CR_ARR_COMPARE_(Actual, Expected, Size, Cmp, order); \ + CR_EXPAND(cr_assert_impl( \ + Fail, \ + order Op 0, \ + dummy, \ + CRITERION_ASSERT_MSG_EXPR_FALSE, \ + (CR_STR((Actual)[0 .. Size] Op (Expected)[0 .. Size])), \ + __VA_ARGS__ \ + )); \ + } while (0) -#endif /* !CRITERION_ASSERT_BASE_H_ */ +# define cr_assert_arr_op_cmp_va_(Fail, Op, ...) \ + CR_EXPAND(cr_assert_arr_op_cmp_( \ + Fail, \ + Op, \ + CR_VA_HEAD(__VA_ARGS__), \ + CR_VA_HEAD(CR_VA_TAIL(__VA_ARGS__)), \ + CR_VA_HEAD(CR_VA_TAIL(CR_VA_TAIL(__VA_ARGS__))), \ + CR_VA_HEAD(CR_VA_TAIL(CR_VA_TAIL(CR_VA_TAIL(__VA_ARGS__)))), \ + CR_VA_TAIL(CR_VA_TAIL(CR_VA_TAIL(CR_VA_TAIL(__VA_ARGS__)))) \ + )) + +// Exceptions + +# define cr_assert_throw_abort_(Fail, Msg, MsgArgs, ...) \ + CR_EXPAND(cr_assert_impl( \ + Fail, \ + 0, \ + dummy, \ + Msg, \ + MsgArgs, \ + CR_VA_TAIL(__VA_ARGS__) \ + )) + +# define cr_assert_throw_(Fail, Statement, Exception, ...) \ + try { \ + Statement; \ + } catch (Exception const &) { \ + } catch (...) { \ + CR_EXPAND(cr_assert_throw_abort_( \ + Fail, \ + CRITERION_ASSERT_MSG_NO_THROW, \ + (CR_STR(Statement), CR_STR(Exception)), \ + __VA_ARGS__)); \ + } + +# define cr_assert_throw_va_(...) \ + CR_EXPAND(cr_assert_throw_( \ + CR_VA_HEAD(__VA_ARGS__), \ + CR_VA_HEAD(CR_VA_TAIL(__VA_ARGS__)), \ + CR_VA_HEAD(CR_VA_TAIL(CR_VA_TAIL(__VA_ARGS__))), \ + dummy, \ + CR_VA_TAIL(CR_VA_TAIL(CR_VA_TAIL(__VA_ARGS__))) \ + )) + +# define cr_assert_no_throw_(Fail, Statement, Exception, ...) \ + try { \ + Statement; \ + } catch (Exception const &) { \ + CR_EXPAND(cr_assert_throw_abort_( \ + Fail, \ + CRITERION_ASSERT_MSG_THROW, \ + (CR_STR(Statement), CR_STR(Exception)), \ + __VA_ARGS__)); \ + } + +# define cr_assert_no_throw_va_(...) \ + CR_EXPAND(cr_assert_no_throw_( \ + CR_VA_HEAD(__VA_ARGS__), \ + CR_VA_HEAD(CR_VA_TAIL(__VA_ARGS__)), \ + CR_VA_HEAD(CR_VA_TAIL(CR_VA_TAIL(__VA_ARGS__))), \ + dummy, \ + CR_VA_TAIL(CR_VA_TAIL(CR_VA_TAIL(__VA_ARGS__))) \ + )) + +# define cr_assert_any_throw_(Fail, Statement, ...) \ + try { \ + Statement; \ + CR_EXPAND(cr_assert_throw_abort_( \ + Fail, \ + CRITERION_ASSERT_MSG_ANY_THROW, \ + (CR_STR(Statement)), \ + __VA_ARGS__)); \ + } catch (...) {} + +# define cr_assert_any_throw_va_(...) \ + CR_EXPAND(cr_assert_any_throw_( \ + CR_VA_HEAD(__VA_ARGS__), \ + CR_VA_HEAD(CR_VA_TAIL(__VA_ARGS__)), \ + dummy, \ + CR_VA_TAIL(CR_VA_TAIL(__VA_ARGS__)) \ + )) + +# define cr_assert_none_throw_(Fail, Statement, ...) \ + try { \ + Statement; \ + } catch (...) { \ + CR_EXPAND(cr_assert_throw_abort_( \ + Fail, \ + CRITERION_ASSERT_MSG_NONE_THROW, \ + (CR_STR(Statement)), \ + __VA_ARGS__)); \ + } + +# define cr_assert_none_throw_va_(...) \ + CR_EXPAND(cr_assert_none_throw_( \ + CR_VA_HEAD(__VA_ARGS__), \ + CR_VA_HEAD(CR_VA_TAIL(__VA_ARGS__)), \ + dummy, \ + CR_VA_TAIL(CR_VA_TAIL(__VA_ARGS__)) \ + )) + +// Messages + +# 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." \ + ) + +#endif /* !CRITERION_INTERNAL_ASSERT_H_ */ diff --git a/include/criterion/internal/hooks.h b/include/criterion/internal/hooks.h new file mode 100644 index 0000000..cf33de5 --- /dev/null +++ b/include/criterion/internal/hooks.h @@ -0,0 +1,84 @@ +/* + * The MIT License (MIT) + * + * Copyright © 2015 Franklin "Snaipe" Mathieu + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#ifndef CRITERION_INTERNAL_HOOKS_H_ +# define CRITERION_INTERNAL_HOOKS_H_ + +# include "common.h" +# include "../types.h" + +# define CR_HOOK_IDENTIFIER_(Suffix) CR_HOOK_IDENTIFIER__(__LINE__, Suffix) +# define CR_HOOK_IDENTIFIER__(Line, Suffix) CR_HOOK_IDENTIFIER___(Line, Suffix) +# define CR_HOOK_IDENTIFIER___(Line, Suffix) hook_l ## Line ## _ ## Suffix + +# ifdef __cplusplus +# define CR_HOOK_PROTOTYPE_ \ + extern "C" void CR_HOOK_IDENTIFIER_(impl) +# else +# define CR_HOOK_PROTOTYPE_ \ + void CR_HOOK_IDENTIFIER_(impl) +# endif + +// Section abbreviations +# define CR_HOOK_SECTION_PRE_ALL cr_pra +# define CR_HOOK_SECTION_PRE_SUITE cr_prs +# define CR_HOOK_SECTION_PRE_INIT cr_pri +# define CR_HOOK_SECTION_PRE_TEST cr_prt +# define CR_HOOK_SECTION_ASSERT cr_ast +# define CR_HOOK_SECTION_THEORY_FAIL cr_thf +# define CR_HOOK_SECTION_TEST_CRASH cr_tsc +# define CR_HOOK_SECTION_POST_TEST cr_pot +# define CR_HOOK_SECTION_POST_FINI cr_pof +# define CR_HOOK_SECTION_POST_SUITE cr_pos +# define CR_HOOK_SECTION_POST_ALL cr_poa + +# define CR_HOOK_SECTION(Kind) CR_HOOK_SECTION_ ## Kind + +# define CR_HOOK_SECTION_STRINGIFY__(Sec) #Sec +# define CR_HOOK_SECTION_STRINGIFY_(Sec) CR_HOOK_SECTION_STRINGIFY__(Sec) +# define CR_HOOK_SECTION_STRINGIFY(Kind) CR_HOOK_SECTION_STRINGIFY_(CR_HOOK_SECTION(Kind)) + +# define CR_HOOK_PARAM_TYPE_PRE_ALL struct criterion_test_set * +# define CR_HOOK_PARAM_TYPE_PRE_SUITE struct criterion_suite_set * +# define CR_HOOK_PARAM_TYPE_PRE_INIT struct criterion_test * +# define CR_HOOK_PARAM_TYPE_PRE_TEST struct criterion_test * +# define CR_HOOK_PARAM_TYPE_ASSERT struct criterion_assert_stats * +# define CR_HOOK_PARAM_TYPE_THEORY_FAIL struct criterion_theory_stats * +# define CR_HOOK_PARAM_TYPE_TEST_CRASH struct criterion_test_stats * +# define CR_HOOK_PARAM_TYPE_POST_TEST struct criterion_test_stats * +# define CR_HOOK_PARAM_TYPE_POST_FINI struct criterion_test_stats * +# define CR_HOOK_PARAM_TYPE_POST_SUITE struct criterion_suite_stats * +# define CR_HOOK_PARAM_TYPE_POST_ALL struct criterion_global_stats * + +# define CR_HOOK_PARAM_TYPE(Kind) CR_HOOK_PARAM_TYPE_ ## Kind + +# define CR_REPORT_HOOK_IMPL(Kind) \ + CR_HOOK_PROTOTYPE_(CR_HOOK_PARAM_TYPE(Kind)); \ + CR_SECTION_(CR_HOOK_SECTION_STRINGIFY(Kind)) \ + f_report_hook CR_HOOK_IDENTIFIER_(func) = \ + (f_report_hook) CR_HOOK_IDENTIFIER_(impl) \ + CR_SECTION_SUFFIX_; \ + CR_HOOK_PROTOTYPE_ + + +#endif /* !CRITERION_INTERNAL_HOOKS_H_ */ diff --git a/include/criterion/internal/parameterized.h b/include/criterion/internal/parameterized.h new file mode 100644 index 0000000..017a599 --- /dev/null +++ b/include/criterion/internal/parameterized.h @@ -0,0 +1,72 @@ +/* + * The MIT License (MIT) + * + * Copyright © 2015 Franklin "Snaipe" Mathieu + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#ifndef CRITERION_INTERNAL_PARAMETERIZED_H_ +# define CRITERION_INTERNAL_PARAMETERIZED_H_ + +# include "test.h" +# include "../types.h" + +# ifdef __cplusplus +# define CR_PARAM_TEST_PROTOTYPE_(Param, Category, Name) \ + extern "C" void CR_IDENTIFIER_(Category, Name, impl)(Param) +# else +# define CR_PARAM_TEST_PROTOTYPE_(Param, Category, Name) \ + void CR_IDENTIFIER_(Category, Name, impl)(Param) +# endif + +# define CR_PARAM_TEST_BASE(Param, Category, Name, ...) \ + CR_PARAM_TEST_PROTOTYPE_(Param, Category, Name); \ + struct criterion_test_extra_data CR_IDENTIFIER_(Category, Name, extra) = \ + CR_EXPAND(CRITERION_MAKE_STRUCT(struct criterion_test_extra_data, \ + .lang_ = CR_LANG, \ + .kind_ = CR_TEST_PARAMETERIZED, \ + .param_ = CR_IDENTIFIER_(Category, Name, param), \ + .identifier_ = #Category "/" #Name, \ + .file_ = __FILE__, \ + .line_ = __LINE__, \ + __VA_ARGS__ \ + )); \ + struct criterion_test CR_IDENTIFIER_(Category, Name, meta) = { \ + #Name, \ + #Category, \ + (void(*)(void)) CR_IDENTIFIER_(Category, Name, impl), \ + &CR_IDENTIFIER_(Category, Name, extra) \ + }; \ + CR_SECTION_("cr_tst") \ + struct criterion_test *CR_IDENTIFIER_(Category, Name, ptr) \ + = &CR_IDENTIFIER_(Category, Name, meta) CR_SECTION_SUFFIX_; \ + CR_PARAM_TEST_PROTOTYPE_(Param, Category, Name) + +# define CR_PARAM_TEST_PARAMS(Category, Name) \ + static struct criterion_test_params CR_IDENTIFIER_(Category, Name, param)(void) + +# ifdef __cplusplus +# define cr_make_param_array(Type, Array, ...) \ + criterion_test_params(sizeof (Type), (Array), __VA_ARGS__) +# else +# define cr_make_param_array(Type, Array, ...) \ + (struct criterion_test_params) { .size = sizeof (Type), (void*)(Array), __VA_ARGS__ } +# endif + +#endif /* !CRITERION_INTERNAL_PARAMETERIZED_H_ */ diff --git a/include/criterion/internal/redirect.h b/include/criterion/internal/redirect.h new file mode 100644 index 0000000..64c003b --- /dev/null +++ b/include/criterion/internal/redirect.h @@ -0,0 +1,48 @@ +#ifndef CRITERION_INTERNAL_REDIRECT_H_ +# define CRITERION_INTERNAL_REDIRECT_H_ + +# include "common.h" +# include "assert.h" + +# define cr_assert_redir_op_(Fail, Fun, Op, File, Str, ...) \ + CR_EXPAND(cr_assert_impl( \ + Fail, \ + !(Fun((File), (Str)) Op 0), \ + dummy, \ + CRITERION_ASSERT_MSG_FILE_STR_MATCH, \ + (CR_STR(File), Str), \ + __VA_ARGS__ \ + )) + +# define cr_assert_redir_op_va_(Fail, Fun, Op, ...) \ + CR_EXPAND(cr_assert_redir_op_( \ + Fail, \ + Fun, \ + Op, \ + CR_VA_HEAD(__VA_ARGS__), \ + CR_VA_HEAD(CR_VA_TAIL(__VA_ARGS__)), \ + CR_VA_TAIL(CR_VA_TAIL(__VA_ARGS__)) \ + )) + +# define cr_assert_redir_f_op_(Fail, Fun, Op, File, Ref, ...) \ + CR_EXPAND(cr_assert_impl( \ + Fail, \ + !(Fun((File), (Ref)) Op 0), \ + dummy, \ + CRITERION_ASSERT_MSG_FILE_MATCH, \ + (CR_STR(File), CR_STR(Ref)), \ + __VA_ARGS__ \ + )) + +# define cr_assert_redir_f_op_va_(Fail, Fun, Op, ...) \ + CR_EXPAND(cr_assert_redir_op_( \ + Fail, \ + Fun, \ + Op, \ + CR_VA_HEAD(__VA_ARGS__), \ + CR_VA_HEAD(CR_VA_TAIL(__VA_ARGS__)), \ + CR_VA_TAIL(CR_VA_TAIL(__VA_ARGS__)) \ + )) + + +#endif /* !CRITERION_INTERNAL_REDIRECT_H_ */ diff --git a/include/criterion/internal/stdio_filebuf.hxx b/include/criterion/internal/stdio_filebuf.hxx new file mode 100644 index 0000000..0cb53d7 --- /dev/null +++ b/include/criterion/internal/stdio_filebuf.hxx @@ -0,0 +1,138 @@ +#ifndef CRITERION_INTERNAL_STDIO_FILEBUF_HXX_ +# define CRITERION_INTERNAL_STDIO_FILEBUF_HXX_ + +# include + +namespace criterion { namespace internal { + + template > + class stdio_sync_filebuf : public std::basic_streambuf { + public: + typedef Traits traits; + typedef std::basic_filebuf super; + typedef typename Traits::int_type int_type; + typedef typename Traits::pos_type pos_type; + typedef typename Traits::off_type off_type; + + stdio_sync_filebuf(std::FILE *file) + : file(file) + , lastchar(Traits::eof()) + {} + + stdio_sync_filebuf(stdio_sync_filebuf&& other) = default; + stdio_sync_filebuf& operator=(stdio_sync_filebuf&& other) = default; + + void swap(stdio_sync_filebuf& other) { + super::swap(other); + std::swap(file, other.file); + std::swap(lastchar, other.lastchar); + } + + protected: + int_type syncgetc(); + int_type syncungetc(int_type); + int_type syncputc(int_type); + + virtual std::streampos seekoff(std::streamoff off, + std::ios_base::seekdir dir, + std::ios_base::openmode = std::ios_base::in | std::ios_base::out) { + + int whence; + if (dir == std::ios_base::beg) + whence = SEEK_SET; + else if (dir == std::ios_base::cur) + whence = SEEK_CUR; + else + whence = SEEK_END; + + if (!fseek(file, off, whence)) + return std::streampos(std::ftell(file)); + return std::streamoff(-1); + } + + virtual std::streampos seekpos(std::streampos pos, + std::ios_base::openmode mode = std::ios_base::in | std::ios_base::out) { + return seekoff(std::streamoff(pos), std::ios_base::beg, mode); + } + + virtual std::streamsize xsgetn(CharT* s, std::streamsize n); + virtual std::streamsize xsputn(const CharT* s, std::streamsize n); + + virtual int sync() { + return std::fflush(file); + } + + virtual int_type underflow() { + int_type c = syncgetc(); + return syncungetc(c); + } + + virtual int_type uflow() { + return lastchar = syncgetc(); + } + + static inline bool is_eof(int_type c) { + static const int_type eof = Traits::eof(); + return Traits::eq_int_type(c, eof); + } + + virtual int_type overflow(int_type c = Traits::eof()) { + int_type ret; + if (is_eof(c)) { + if (std::fflush(file)) + ret = Traits::eof(); + else + ret = Traits::not_eof(c); + } else { + ret = syncputc(c); + } + return ret; + } + + virtual int_type pbackfail(int_type c = Traits::eof()) { + int_type ret = syncungetc(is_eof(c) && !is_eof(lastchar) ? lastchar : c); + lastchar = Traits::eof(); + return ret; + } + + private: + std::FILE *file; + bool file_open; + int_type lastchar; + }; + + template <> + inline stdio_sync_filebuf::int_type + stdio_sync_filebuf::syncgetc() { + return std::getc(file); + } + + template <> + inline stdio_sync_filebuf::int_type + stdio_sync_filebuf::syncungetc(stdio_sync_filebuf::int_type c) { + return std::ungetc(c, file); + } + + template <> + inline stdio_sync_filebuf::int_type + stdio_sync_filebuf::syncputc(stdio_sync_filebuf::int_type c) { + return std::putc(c, file); + } + + template <> + inline std::streamsize + stdio_sync_filebuf::xsgetn(char *s, std::streamsize n) { + std::streamsize res = std::fread(s, 1, n, file); + lastchar = res > 0 ? traits::to_int_type(s[res - 1]) : traits::eof(); + return res; + } + + template <> + inline std::streamsize + stdio_sync_filebuf::xsputn(const char *s, std::streamsize n) { + return std::fwrite(s, 1, n, file); + } + +}} + +#endif /* !CRITERION_INTERNAL_STDIO_FILEBUF_HXX_ */ diff --git a/include/criterion/internal/stream.hxx b/include/criterion/internal/stream.hxx new file mode 100644 index 0000000..d8c5a08 --- /dev/null +++ b/include/criterion/internal/stream.hxx @@ -0,0 +1,114 @@ +#ifndef CRITERION_INTERNAL_STREAM_HXX_ +# define CRITERION_INTERNAL_STREAM_HXX_ + +# include +# include +# include + +# include "stdio_filebuf.hxx" + +namespace criterion { namespace internal { + + template + class stream_mixin : public Super { +public: + stream_mixin(FILE* f) + : Super() + , fbuf(new stdio_sync_filebuf(f)) + , file(f) + { + std::ios::rdbuf(&*fbuf); + } + + stream_mixin(const stream_mixin& other) = delete; + stream_mixin& operator=(const stream_mixin& other) = delete; + + stream_mixin(stream_mixin&& other) : + fbuf(std::move(other.fbuf)), + file(std::move(other.file)) + {} + + stream_mixin& operator=(stream_mixin&& other) { + fbuf = std::move(other.fbuf); + file = std::move(other.file); + } + + void close(void) { + Super::flush(); + Super::close(); + std::fclose(file); + } + + private: + std::shared_ptr> fbuf; + std::FILE* file; + }; + + template + using ofstream_mixin = stream_mixin>; + + template + using ifstream_mixin = stream_mixin>; + + template + using fstream_mixin = stream_mixin>; + + template + class basic_ofstream : public ofstream_mixin { + public: + basic_ofstream(FILE* f) + : ofstream_mixin(f) + {} + + basic_ofstream(basic_ofstream&& other) + : ofstream_mixin(std::move(other)) + {} + }; + + template + class basic_ifstream : public ifstream_mixin { + public: + basic_ifstream(FILE* f) + : ifstream_mixin(f) + {} + + basic_ifstream(basic_ifstream&& other) + : ifstream_mixin(std::move(other)) + {} + }; + + template + class basic_fstream : public fstream_mixin { + public: + basic_fstream(FILE* f) + : fstream_mixin(f) + {} + + basic_fstream(basic_fstream&& other) + : fstream_mixin(std::move(other)) + {} + }; + + struct get_redirected_out_stream_ { + static inline basic_ofstream& call(std::FILE* f) { + static std::unique_ptr> stream; + + if (!stream) + stream.reset(new basic_ofstream(f)); + return *stream; + } + + }; + + struct get_redirected_in_stream_ { + static inline basic_ifstream& call(std::FILE* f) { + static std::unique_ptr> stream; + if (!stream) + stream.reset(new basic_ifstream(f)); + return *stream; + } + }; + +}} + +#endif /* !CRITERION_INTERNAL_STREAM_HXX_ */ diff --git a/include/criterion/internal/test.h b/include/criterion/internal/test.h new file mode 100644 index 0000000..2b4e3d9 --- /dev/null +++ b/include/criterion/internal/test.h @@ -0,0 +1,97 @@ +/* + * The MIT License (MIT) + * + * Copyright © 2015 Franklin "Snaipe" Mathieu + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#ifndef CRITERION_INTERNAL_TEST_H_ +# define CRITERION_INTERNAL_TEST_H_ + +# include "designated-initializer-compat.h" +# include "common.h" + +# define CR_IDENTIFIER_(Category, Name, Suffix) \ + Category ## _ ## Name ## _ ## Suffix + +# ifdef __cplusplus +# ifdef __OBJC__ +# define CR_LANG CR_LANG_OBJCXX +# else +# define CR_LANG CR_LANG_CXX +# endif +# else +# ifdef __OBJC__ +# define CR_LANG CR_LANG_OBJC +# else +# define CR_LANG CR_LANG_C +# endif +# endif + +# ifdef __cplusplus +# define CR_TEST_PROTOTYPE_(Category, Name) \ + extern "C" void CR_IDENTIFIER_(Category, Name, impl)(void) +# else +# define CR_TEST_PROTOTYPE_(Category, Name) \ + void CR_IDENTIFIER_(Category, Name, impl)(void) +# endif + +# define CR_SUITE_IDENTIFIER_(Name, Suffix) \ + suite_ ## Name ## _ ## Suffix + +# define CR_TEST_BASE(Category, Name, ...) \ + CR_TEST_PROTOTYPE_(Category, Name); \ + struct criterion_test_extra_data CR_IDENTIFIER_(Category, Name, extra) = \ + CR_EXPAND(CRITERION_MAKE_STRUCT(struct criterion_test_extra_data, \ + .lang_ = CR_LANG, \ + .kind_ = CR_TEST_NORMAL, \ + .param_ = (struct criterion_test_params(*)(void)) NULL, \ + .identifier_ = #Category "/" #Name, \ + .file_ = __FILE__, \ + .line_ = __LINE__, \ + __VA_ARGS__ \ + )); \ + struct criterion_test CR_IDENTIFIER_(Category, Name, meta) = { \ + #Name, \ + #Category, \ + CR_IDENTIFIER_(Category, Name, impl), \ + &CR_IDENTIFIER_(Category, Name, extra) \ + }; \ + CR_SECTION_("cr_tst") \ + struct criterion_test *CR_IDENTIFIER_(Category, Name, ptr) \ + = &CR_IDENTIFIER_(Category, Name, meta) CR_SECTION_SUFFIX_; \ + CR_TEST_PROTOTYPE_(Category, Name) + +# define CR_SUITE_BASE(Name, ...) \ + struct criterion_test_extra_data CR_SUITE_IDENTIFIER_(Name, extra) = \ + CR_EXPAND(CRITERION_MAKE_STRUCT(struct criterion_test_extra_data, \ + .file_ = __FILE__, \ + .line_ = 0, \ + __VA_ARGS__ \ + )); \ + struct criterion_suite CR_SUITE_IDENTIFIER_(Name, meta) = { \ + #Name, \ + &CR_SUITE_IDENTIFIER_(Name, extra), \ + }; \ + CR_SECTION_("cr_sts") \ + struct criterion_suite *CR_SUITE_IDENTIFIER_(Name, ptr) \ + = &CR_SUITE_IDENTIFIER_(Name, meta) CR_SECTION_SUFFIX_ + + +#endif /* !CRITERION_INTERNAL_TEST_H_ */ diff --git a/include/criterion/internal/theories.h b/include/criterion/internal/theories.h new file mode 100644 index 0000000..172d96d --- /dev/null +++ b/include/criterion/internal/theories.h @@ -0,0 +1,94 @@ +/* + * The MIT License (MIT) + * + * Copyright © 2015 Franklin "Snaipe" Mathieu + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#ifndef CRITERION_INTERNAL_THEORIES_H_ +# define CRITERION_INTERNAL_THEORIES_H_ + +# include "test.h" + +# ifdef __cplusplus +# include +using std::size_t; +# else +# include +# endif + +# ifdef __cplusplus +template +constexpr size_t criterion_va_num__(const T &...) { + return sizeof...(T); +} +# endif + +struct criterion_datapoints { + size_t size; + size_t len; + const char *name; + void *arr; +}; + +CR_BEGIN_C_API + +CR_API void cr_theory_main(struct criterion_datapoints *dps, size_t datapoints, void (*fnptr)(void)); + +CR_END_C_API + +# ifdef __cplusplus +# define CR_TH_VA_NUM(Type, ...) criterion_va_num__(__VA_ARGS__) +# define CR_TH_TEMP_ARRAY(Type, ...) []() { static Type arr[] = { __VA_ARGS__ }; return &arr; }() +# else +# define CR_TH_VA_NUM(Type, ...) sizeof ((Type[]) { __VA_ARGS__ }) / sizeof (Type) +# define CR_TH_TEMP_ARRAY(Type, ...) &(Type[]) { __VA_ARGS__ } +# endif + +# define CR_TH_INTERNAL_TDPS(Category, Name) \ + static struct criterion_datapoints CR_IDENTIFIER_(Category, Name, dps)[] + +# define CR_TH_INTERNAL_TDP(Category, Name) \ + (CR_IDENTIFIER_(Category, Name, dps)) + +# define CR_TH_INTERNAL_DP(Type, ...) { \ + sizeof (Type), \ + CR_EXPAND(CR_TH_VA_NUM(Type, __VA_ARGS__)), \ + #Type, \ + CR_EXPAND(CR_TH_TEMP_ARRAY(Type, __VA_ARGS__)), \ + } + +# define CR_NB_DATAPOINTS(Var) \ + (sizeof (Var) / sizeof (struct criterion_datapoints)) + +# define CR_VAARG_ID(Suffix, Category, Name, ...) \ + CR_IDENTIFIER_(Category, Name, Suffix) + +# define CR_THEORY_BASE(Args, ...) \ + void CR_EXPAND(CR_VAARG_ID(theory, __VA_ARGS__,))Args; \ + CR_EXPAND(CR_TEST_BASE(__VA_ARGS__, .sentinel_ = 0)) { \ + cr_theory_main( \ + CR_EXPAND(CR_VAARG_ID(dps, __VA_ARGS__,)), \ + CR_NB_DATAPOINTS(CR_EXPAND(CR_VAARG_ID(dps, __VA_ARGS__,))), \ + (void(*)(void)) CR_EXPAND(CR_VAARG_ID(theory, __VA_ARGS__,)) \ + ); \ + } \ + void CR_EXPAND(CR_VAARG_ID(theory, __VA_ARGS__,))Args + +#endif /* !CRITERION_INTERNAL_THEORIES_H_ */ diff --git a/include/criterion/parameterized.h b/include/criterion/parameterized.h index 2c6d96c..7099009 100644 --- a/include/criterion/parameterized.h +++ b/include/criterion/parameterized.h @@ -1,58 +1,40 @@ +/* + * The MIT License (MIT) + * + * Copyright © 2015 Franklin "Snaipe" Mathieu + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ #ifndef CRITERION_PARAMETERIZED_H_ # define CRITERION_PARAMETERIZED_H_ -# include "criterion.h" # include "alloc.h" +# include "assert.h" +# include "internal/parameterized.h" + +# define ParameterizedTest(...) CR_EXPAND(CR_PARAM_TEST_BASE(__VA_ARGS__, .sentinel_ = 0)) + +# define ParameterizedTestParameters(Category, Name) CR_PARAM_TEST_PARAMS(Category, Name) + # ifdef __cplusplus # include -# endif -# ifdef __cplusplus -# define CR_PARAM_TEST_PROTOTYPE_(Param, Category, Name) \ - extern "C" void CR_IDENTIFIER_(Category, Name, impl)(Param) -# else -# define CR_PARAM_TEST_PROTOTYPE_(Param, Category, Name) \ - void CR_IDENTIFIER_(Category, Name, impl)(Param) -# endif - -# define ParameterizedTest(...) \ - CR_EXPAND(ParameterizedTest_(__VA_ARGS__, .sentinel_ = 0)) - -# define ParameterizedTest_(Param, Category, Name, ...) \ - CR_PARAM_TEST_PROTOTYPE_(Param, Category, Name); \ - struct criterion_test_extra_data CR_IDENTIFIER_(Category, Name, extra) = \ - CR_EXPAND(CRITERION_MAKE_STRUCT(struct criterion_test_extra_data, \ - .lang_ = CR_LANG, \ - .kind_ = CR_TEST_PARAMETERIZED, \ - .param_ = CR_IDENTIFIER_(Category, Name, param), \ - .identifier_ = #Category "/" #Name, \ - .file_ = __FILE__, \ - .line_ = __LINE__, \ - __VA_ARGS__ \ - )); \ - struct criterion_test CR_IDENTIFIER_(Category, Name, meta) = { \ - #Name, \ - #Category, \ - (void(*)(void)) CR_IDENTIFIER_(Category, Name, impl), \ - &CR_IDENTIFIER_(Category, Name, extra) \ - }; \ - CR_SECTION_("cr_tst") \ - struct criterion_test *CR_IDENTIFIER_(Category, Name, ptr) \ - = &CR_IDENTIFIER_(Category, Name, meta) CR_SECTION_SUFFIX_; \ - CR_PARAM_TEST_PROTOTYPE_(Param, Category, Name) - -# define ParameterizedTestParameters(Category, Name) \ - static struct criterion_test_params CR_IDENTIFIER_(Category, Name, param)(void) - -# ifdef __cplusplus -# define cr_make_param_array(Type, Array, ...) \ - criterion_test_params(sizeof (Type), (Array), __VA_ARGS__) -# else -# define cr_make_param_array(Type, Array, ...) \ - (struct criterion_test_params) { .size = sizeof (Type), (void*)(Array), __VA_ARGS__ } -# endif - -# ifdef __cplusplus namespace criterion { template using parameters = std::vector>; diff --git a/include/criterion/redirect.h b/include/criterion/redirect.h index c00f42f..6fd5f58 100644 --- a/include/criterion/redirect.h +++ b/include/criterion/redirect.h @@ -25,12 +25,10 @@ # define CRITERION_REDIRECT_H_ # include "internal/common.h" -# include "assert.h" +# include "internal/redirect.h" # ifdef __cplusplus # include -# include -# include # else # include # endif @@ -52,46 +50,6 @@ CR_API CR_STDN FILE *cr_mock_file_size(size_t max_size); CR_END_C_API -# define cr_assert_redir_op_(Fail, Fun, Op, File, Str, ...) \ - CR_EXPAND(cr_assert_impl( \ - Fail, \ - !(Fun((File), (Str)) Op 0), \ - dummy, \ - CRITERION_ASSERT_MSG_FILE_STR_MATCH, \ - (CR_STR(File), Str), \ - __VA_ARGS__ \ - )) - -# define cr_assert_redir_op_va_(Fail, Fun, Op, ...) \ - CR_EXPAND(cr_assert_redir_op_( \ - Fail, \ - Fun, \ - Op, \ - CR_VA_HEAD(__VA_ARGS__), \ - CR_VA_HEAD(CR_VA_TAIL(__VA_ARGS__)), \ - CR_VA_TAIL(CR_VA_TAIL(__VA_ARGS__)) \ - )) - -# define cr_assert_redir_f_op_(Fail, Fun, Op, File, Ref, ...) \ - CR_EXPAND(cr_assert_impl( \ - Fail, \ - !(Fun((File), (Ref)) Op 0), \ - dummy, \ - CRITERION_ASSERT_MSG_FILE_MATCH, \ - (CR_STR(File), CR_STR(Ref)), \ - __VA_ARGS__ \ - )) - -# define cr_assert_redir_f_op_va_(Fail, Fun, Op, ...) \ - CR_EXPAND(cr_assert_redir_op_( \ - Fail, \ - Fun, \ - Op, \ - CR_VA_HEAD(__VA_ARGS__), \ - CR_VA_HEAD(CR_VA_TAIL(__VA_ARGS__)), \ - CR_VA_TAIL(CR_VA_TAIL(__VA_ARGS__)) \ - )) - # define cr_assert_file_contents_eq_str(...) CR_EXPAND(cr_assert_redir_op_va_(CR_FAIL_ABORT_, cr_file_match_str, ==, __VA_ARGS__)) # define cr_expect_file_contents_eq_str(...) CR_EXPAND(cr_assert_redir_op_va_(CR_FAIL_CONTINUES_, cr_file_match_str, ==, __VA_ARGS__)) @@ -129,250 +87,24 @@ CR_END_C_API # define cr_expect_stderr_neq(...) CR_EXPAND(cr_assert_redir_f_op_va_(CR_FAIL_CONTINUES_, cr_file_match_file, !=, cr_get_redirected_stderr(), __VA_ARGS__)) # ifdef __cplusplus +# include "internal/stream.hxx" + namespace criterion { - template > - class stdio_sync_filebuf : public std::basic_streambuf { - public: - typedef Traits traits; - typedef std::basic_filebuf super; - typedef typename Traits::int_type int_type; - typedef typename Traits::pos_type pos_type; - typedef typename Traits::off_type off_type; - - stdio_sync_filebuf(std::FILE *file) - : file(file) - , lastchar(Traits::eof()) - {} - - stdio_sync_filebuf(stdio_sync_filebuf&& other) = default; - stdio_sync_filebuf& operator=(stdio_sync_filebuf&& other) = default; - - void swap(stdio_sync_filebuf& other) { - super::swap(other); - std::swap(file, other.file); - std::swap(lastchar, other.lastchar); - } - - protected: - int_type syncgetc(); - int_type syncungetc(int_type); - int_type syncputc(int_type); - - virtual std::streampos seekoff(std::streamoff off, - std::ios_base::seekdir dir, - std::ios_base::openmode = std::ios_base::in | std::ios_base::out) { - - int whence; - if (dir == std::ios_base::beg) - whence = SEEK_SET; - else if (dir == std::ios_base::cur) - whence = SEEK_CUR; - else - whence = SEEK_END; - - if (!fseek(file, off, whence)) - return std::streampos(std::ftell(file)); - return std::streamoff(-1); - } - - virtual std::streampos seekpos(std::streampos pos, - std::ios_base::openmode mode = std::ios_base::in | std::ios_base::out) { - return seekoff(std::streamoff(pos), std::ios_base::beg, mode); - } - - virtual std::streamsize xsgetn(CharT* s, std::streamsize n); - virtual std::streamsize xsputn(const CharT* s, std::streamsize n); - - virtual int sync() { - return std::fflush(file); - } - - virtual int_type underflow() { - int_type c = syncgetc(); - return syncungetc(c); - } - - virtual int_type uflow() { - return lastchar = syncgetc(); - } - - static inline bool is_eof(int_type c) { - static const int_type eof = Traits::eof(); - return Traits::eq_int_type(c, eof); - } - - virtual int_type overflow(int_type c = Traits::eof()) { - int_type ret; - if (is_eof(c)) { - if (std::fflush(file)) - ret = Traits::eof(); - else - ret = Traits::not_eof(c); - } else { - ret = syncputc(c); - } - return ret; - } - - virtual int_type pbackfail(int_type c = Traits::eof()) { - int_type ret = syncungetc(is_eof(c) && !is_eof(lastchar) ? lastchar : c); - lastchar = Traits::eof(); - return ret; - } - - private: - std::FILE *file; - bool file_open; - int_type lastchar; - }; - - template <> - inline stdio_sync_filebuf::int_type - stdio_sync_filebuf::syncgetc() { - return std::getc(file); - } - - template <> - inline stdio_sync_filebuf::int_type - stdio_sync_filebuf::syncungetc(stdio_sync_filebuf::int_type c) { - return std::ungetc(c, file); - } - - template <> - inline stdio_sync_filebuf::int_type - stdio_sync_filebuf::syncputc(stdio_sync_filebuf::int_type c) { - return std::putc(c, file); - } - - template <> - inline std::streamsize - stdio_sync_filebuf::xsgetn(char *s, std::streamsize n) { - std::streamsize res = std::fread(s, 1, n, file); - lastchar = res > 0 ? traits::to_int_type(s[res - 1]) : traits::eof(); - return res; - } - - template <> - inline std::streamsize - stdio_sync_filebuf::xsputn(const char *s, std::streamsize n) { - return std::fwrite(s, 1, n, file); - } - - template - class stream_mixin : public Super { -public: - stream_mixin(FILE* f) - : Super() - , fbuf(new stdio_sync_filebuf(f)) - , file(f) - { - std::ios::rdbuf(&*fbuf); - } - - stream_mixin(const stream_mixin& other) = delete; - stream_mixin& operator=(const stream_mixin& other) = delete; - - stream_mixin(stream_mixin&& other) : - fbuf(std::move(other.fbuf)), - file(std::move(other.file)) - {} - - stream_mixin& operator=(stream_mixin&& other) { - fbuf = std::move(other.fbuf); - file = std::move(other.file); - } - - void close(void) { - Super::flush(); - Super::close(); - std::fclose(file); - } - - private: - std::shared_ptr> fbuf; - std::FILE* file; - }; - - template - using ofstream_mixin = stream_mixin>; - - template - using ifstream_mixin = stream_mixin>; - - template - using fstream_mixin = stream_mixin>; - - template - class basic_ofstream : public ofstream_mixin { - public: - basic_ofstream(FILE* f) - : ofstream_mixin(f) - {} - - basic_ofstream(basic_ofstream&& other) - : ofstream_mixin(std::move(other)) - {} - }; - - template - class basic_ifstream : public ifstream_mixin { - public: - basic_ifstream(FILE* f) - : ifstream_mixin(f) - {} - - basic_ifstream(basic_ifstream&& other) - : ifstream_mixin(std::move(other)) - {} - }; - - template - class basic_fstream : public fstream_mixin { - public: - basic_fstream(FILE* f) - : fstream_mixin(f) - {} - - basic_fstream(basic_fstream&& other) - : fstream_mixin(std::move(other)) - {} - }; - - using ofstream = basic_ofstream; - using ifstream = basic_ifstream; - using fstream = basic_fstream; - - struct get_redirected_out_stream_ { - static inline ofstream& call(std::FILE* f) { - static std::unique_ptr stream; - - if (!stream) - stream.reset(new ofstream(f)); - return *stream; - } - - }; - - struct get_redirected_in_stream_ { - static inline ifstream& call(std::FILE* f) { - static std::unique_ptr stream; - if (!stream) - stream.reset(new ifstream(f)); - return *stream; - } - }; + using ofstream = internal::basic_ofstream; + using ifstream = internal::basic_ifstream; + using fstream = internal::basic_fstream; static inline ofstream& get_redirected_cin(void) { - return get_redirected_out_stream_::call(cr_get_redirected_stdin()); + return internal::get_redirected_out_stream_::call(cr_get_redirected_stdin()); } static inline ifstream& get_redirected_cout(void) { - return get_redirected_in_stream_::call(cr_get_redirected_stdout()); + return internal::get_redirected_in_stream_::call(cr_get_redirected_stdout()); } static inline ifstream& get_redirected_cerr(void) { - return get_redirected_in_stream_::call(cr_get_redirected_stderr()); + return internal::get_redirected_in_stream_::call(cr_get_redirected_stderr()); } # if __GNUC__ >= 5 diff --git a/include/criterion/theories.h b/include/criterion/theories.h index 3777ef7..711e7b1 100644 --- a/include/criterion/theories.h +++ b/include/criterion/theories.h @@ -24,62 +24,30 @@ #ifndef CRITERION_THEORIES_H_ # define CRITERION_THEORIES_H_ -# ifdef __cplusplus -# include -using std::size_t; -# else -# include -# endif - # include "criterion.h" - -# ifdef __cplusplus -template -constexpr size_t criterion_va_num__(const T &...) { - return sizeof...(T); -} -# endif +# include "internal/theories.h" CR_BEGIN_C_API CR_API void cr_theory_abort(void); -# define TheoryDataPoints(Category, Name) \ - static struct criterion_datapoints CR_IDENTIFIER_(Category, Name, dps)[] +CR_END_C_API -# define TheoryDataPoint(Category, Name) \ - (CR_IDENTIFIER_(Category, Name, dps)) +// Theory and datapoint macros -# ifdef __cplusplus -# define CR_TH_VA_NUM(Type, ...) criterion_va_num__(__VA_ARGS__) -# define CR_TH_TEMP_ARRAY(Type, ...) []() { static Type arr[] = { __VA_ARGS__ }; return &arr; }() -# else -# define CR_TH_VA_NUM(Type, ...) sizeof ((Type[]) { __VA_ARGS__ }) / sizeof (Type) -# define CR_TH_TEMP_ARRAY(Type, ...) &(Type[]) { __VA_ARGS__ } -# endif +# define Theory(Args, ...) CR_EXPAND(CR_THEORY_BASE(Args, __VA_ARGS__)) -# define DataPoints(Type, ...) { \ - sizeof (Type), \ - CR_EXPAND(CR_TH_VA_NUM(Type, __VA_ARGS__)), \ - #Type, \ - CR_EXPAND(CR_TH_TEMP_ARRAY(Type, __VA_ARGS__)), \ - } +# define TheoryDataPoints(Category, Name) CR_TH_INTERNAL_TDPS(Category, Name) +# define TheoryDataPoint(Category, Name) CR_TH_INTERNAL_TDP(Category, Name) +# define DataPoints(Type, ...) CR_EXPAND(CR_TH_INTERNAL_DP(Type, __VA_ARGS__)) -struct criterion_datapoints { - size_t size; - size_t len; - const char *name; - void *arr; -}; - -# define CR_NB_DATAPOINTS(Var) \ - (sizeof (Var) / sizeof (struct criterion_datapoints)) +// Theory invariants # define cr_assume(Condition) \ do { \ if (!(Condition)) \ cr_theory_abort(); \ - } while (0); + } while (0) # define cr_assume_not(Condition) cr_assume(!(Condition)) @@ -115,23 +83,7 @@ struct criterion_datapoints { # define cr_assume_arr_eq(Actual, Expected, Size) cr_assume(!memcmp((A), (B), (Size))) # define cr_assume_arr_neq(Actual, Expected, Size) cr_assume(memcmp((A), (B), (Size))) -CR_API void cr_theory_main(struct criterion_datapoints *dps, size_t datapoints, void (*fnptr)(void)); - -# define CR_VAARG_ID(Suffix, Category, Name, ...) \ - CR_IDENTIFIER_(Category, Name, Suffix) - -# define Theory(Args, ...) \ - void CR_EXPAND(CR_VAARG_ID(theory, __VA_ARGS__,))Args; \ - CR_EXPAND(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 - -CR_END_C_API +// Deprecated # ifndef CRITERION_NO_COMPAT # define cr_assume_strings_eq(...) CRITERION_ASSERT_DEPRECATED_B(cr_assume_strings_eq, cr_assume_str_eq) cr_assume_str_eq(__VA_ARGS__) diff --git a/src/core/wrappers/wrap.cc b/src/core/wrappers/wrap.cc index e7f716c..a5bc3eb 100644 --- a/src/core/wrappers/wrap.cc +++ b/src/core/wrappers/wrap.cc @@ -22,13 +22,13 @@ * THE SOFTWARE. */ #include -#include "criterion/assert_base.h" #include "criterion/event.h" +#include "core/report.h" + extern "C" { #include "core/abort.h" -#include "core/report.h" #include "core/worker.h" #include "compat/time.h" #include "wrap.h" @@ -36,6 +36,10 @@ extern "C" { static INLINE void nothing(void) {} +void cxx_wrap(struct criterion_test *test, struct criterion_suite *suite); + +} + void cxx_wrap(struct criterion_test *test, struct criterion_suite *suite) { criterion_send_event(PRE_INIT, NULL, 0); @@ -86,5 +90,3 @@ void cxx_wrap(struct criterion_test *test, struct criterion_suite *suite) { criterion_send_event(POST_FINI, NULL, 0); } - -}