Merge branch 'features/refactor' into bleeding

This commit is contained in:
Snaipe 2015-11-19 14:43:35 +01:00
commit 34fb71dcd6
17 changed files with 930 additions and 857 deletions

1
.gitignore vendored
View file

@ -13,6 +13,7 @@
!*.m
!*.cc
!*.h
!*.hxx
!*.rst
!*.po
!*.in

View file

@ -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

View file

@ -28,29 +28,27 @@
# include <algorithm>
# 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__))

View file

@ -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

View file

@ -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_ */

View file

@ -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 <cstring>
@ -35,12 +37,11 @@
# include <stdlib.h>
# include <stdbool.h>
# 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_ */

View file

@ -0,0 +1,84 @@
/*
* The MIT License (MIT)
*
* Copyright © 2015 Franklin "Snaipe" Mathieu <http://snai.pe/>
*
* 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_ */

View file

@ -0,0 +1,72 @@
/*
* The MIT License (MIT)
*
* Copyright © 2015 Franklin "Snaipe" Mathieu <http://snai.pe/>
*
* 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_ */

View file

@ -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_ */

View file

@ -0,0 +1,138 @@
#ifndef CRITERION_INTERNAL_STDIO_FILEBUF_HXX_
# define CRITERION_INTERNAL_STDIO_FILEBUF_HXX_
# include <fstream>
namespace criterion { namespace internal {
template <typename CharT, typename Traits = std::char_traits<CharT>>
class stdio_sync_filebuf : public std::basic_streambuf<CharT, Traits> {
public:
typedef Traits traits;
typedef std::basic_filebuf<CharT, Traits> 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<char>::int_type
stdio_sync_filebuf<char>::syncgetc() {
return std::getc(file);
}
template <>
inline stdio_sync_filebuf<char>::int_type
stdio_sync_filebuf<char>::syncungetc(stdio_sync_filebuf<char>::int_type c) {
return std::ungetc(c, file);
}
template <>
inline stdio_sync_filebuf<char>::int_type
stdio_sync_filebuf<char>::syncputc(stdio_sync_filebuf<char>::int_type c) {
return std::putc(c, file);
}
template <>
inline std::streamsize
stdio_sync_filebuf<char>::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<char>::xsputn(const char *s, std::streamsize n) {
return std::fwrite(s, 1, n, file);
}
}}
#endif /* !CRITERION_INTERNAL_STDIO_FILEBUF_HXX_ */

View file

@ -0,0 +1,114 @@
#ifndef CRITERION_INTERNAL_STREAM_HXX_
# define CRITERION_INTERNAL_STREAM_HXX_
# include <fstream>
# include <cstdio>
# include <memory>
# include "stdio_filebuf.hxx"
namespace criterion { namespace internal {
template <typename CharT, typename Super>
class stream_mixin : public Super {
public:
stream_mixin(FILE* f)
: Super()
, fbuf(new stdio_sync_filebuf<CharT>(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<stdio_sync_filebuf<CharT>> fbuf;
std::FILE* file;
};
template <typename CharT>
using ofstream_mixin = stream_mixin<CharT, std::basic_ofstream<CharT>>;
template <typename CharT>
using ifstream_mixin = stream_mixin<CharT, std::basic_ifstream<CharT>>;
template <typename CharT>
using fstream_mixin = stream_mixin<CharT, std::basic_fstream<CharT>>;
template <typename CharT>
class basic_ofstream : public ofstream_mixin<CharT> {
public:
basic_ofstream(FILE* f)
: ofstream_mixin<CharT>(f)
{}
basic_ofstream(basic_ofstream&& other)
: ofstream_mixin<CharT>(std::move(other))
{}
};
template <typename CharT>
class basic_ifstream : public ifstream_mixin<CharT> {
public:
basic_ifstream(FILE* f)
: ifstream_mixin<CharT>(f)
{}
basic_ifstream(basic_ifstream&& other)
: ifstream_mixin<CharT>(std::move(other))
{}
};
template <typename CharT>
class basic_fstream : public fstream_mixin<CharT> {
public:
basic_fstream(FILE* f)
: fstream_mixin<CharT>(f)
{}
basic_fstream(basic_fstream&& other)
: fstream_mixin<CharT>(std::move(other))
{}
};
struct get_redirected_out_stream_ {
static inline basic_ofstream<char>& call(std::FILE* f) {
static std::unique_ptr<basic_ofstream<char>> stream;
if (!stream)
stream.reset(new basic_ofstream<char>(f));
return *stream;
}
};
struct get_redirected_in_stream_ {
static inline basic_ifstream<char>& call(std::FILE* f) {
static std::unique_ptr<basic_ifstream<char>> stream;
if (!stream)
stream.reset(new basic_ifstream<char>(f));
return *stream;
}
};
}}
#endif /* !CRITERION_INTERNAL_STREAM_HXX_ */

View file

@ -0,0 +1,97 @@
/*
* The MIT License (MIT)
*
* Copyright © 2015 Franklin "Snaipe" Mathieu <http://snai.pe/>
*
* 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_ */

View file

@ -0,0 +1,94 @@
/*
* The MIT License (MIT)
*
* Copyright © 2015 Franklin "Snaipe" Mathieu <http://snai.pe/>
*
* 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 <cstddef>
using std::size_t;
# else
# include <stddef.h>
# endif
# ifdef __cplusplus
template <typename... T>
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_ */

View file

@ -1,58 +1,40 @@
/*
* The MIT License (MIT)
*
* Copyright © 2015 Franklin "Snaipe" Mathieu <http://snai.pe/>
*
* 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 <vector>
# 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 <typename T>
using parameters = std::vector<T, criterion::allocator<T>>;

View file

@ -25,12 +25,10 @@
# define CRITERION_REDIRECT_H_
# include "internal/common.h"
# include "assert.h"
# include "internal/redirect.h"
# ifdef __cplusplus
# include <cstdio>
# include <memory>
# include <fstream>
# else
# include <stdio.h>
# 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 <typename CharT, typename Traits = std::char_traits<CharT>>
class stdio_sync_filebuf : public std::basic_streambuf<CharT, Traits> {
public:
typedef Traits traits;
typedef std::basic_filebuf<CharT, Traits> 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<char>::int_type
stdio_sync_filebuf<char>::syncgetc() {
return std::getc(file);
}
template <>
inline stdio_sync_filebuf<char>::int_type
stdio_sync_filebuf<char>::syncungetc(stdio_sync_filebuf<char>::int_type c) {
return std::ungetc(c, file);
}
template <>
inline stdio_sync_filebuf<char>::int_type
stdio_sync_filebuf<char>::syncputc(stdio_sync_filebuf<char>::int_type c) {
return std::putc(c, file);
}
template <>
inline std::streamsize
stdio_sync_filebuf<char>::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<char>::xsputn(const char *s, std::streamsize n) {
return std::fwrite(s, 1, n, file);
}
template <typename CharT, typename Super>
class stream_mixin : public Super {
public:
stream_mixin(FILE* f)
: Super()
, fbuf(new stdio_sync_filebuf<CharT>(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<stdio_sync_filebuf<CharT>> fbuf;
std::FILE* file;
};
template <typename CharT>
using ofstream_mixin = stream_mixin<CharT, std::basic_ofstream<CharT>>;
template <typename CharT>
using ifstream_mixin = stream_mixin<CharT, std::basic_ifstream<CharT>>;
template <typename CharT>
using fstream_mixin = stream_mixin<CharT, std::basic_fstream<CharT>>;
template <typename CharT>
class basic_ofstream : public ofstream_mixin<CharT> {
public:
basic_ofstream(FILE* f)
: ofstream_mixin<CharT>(f)
{}
basic_ofstream(basic_ofstream&& other)
: ofstream_mixin<CharT>(std::move(other))
{}
};
template <typename CharT>
class basic_ifstream : public ifstream_mixin<CharT> {
public:
basic_ifstream(FILE* f)
: ifstream_mixin<CharT>(f)
{}
basic_ifstream(basic_ifstream&& other)
: ifstream_mixin<CharT>(std::move(other))
{}
};
template <typename CharT>
class basic_fstream : public fstream_mixin<CharT> {
public:
basic_fstream(FILE* f)
: fstream_mixin<CharT>(f)
{}
basic_fstream(basic_fstream&& other)
: fstream_mixin<CharT>(std::move(other))
{}
};
using ofstream = basic_ofstream<char>;
using ifstream = basic_ifstream<char>;
using fstream = basic_fstream<char>;
struct get_redirected_out_stream_ {
static inline ofstream& call(std::FILE* f) {
static std::unique_ptr<ofstream> 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<ifstream> stream;
if (!stream)
stream.reset(new ifstream(f));
return *stream;
}
};
using ofstream = internal::basic_ofstream<char>;
using ifstream = internal::basic_ifstream<char>;
using fstream = internal::basic_fstream<char>;
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

View file

@ -24,62 +24,30 @@
#ifndef CRITERION_THEORIES_H_
# define CRITERION_THEORIES_H_
# ifdef __cplusplus
# include <cstddef>
using std::size_t;
# else
# include <stddef.h>
# endif
# include "criterion.h"
# ifdef __cplusplus
template <typename... T>
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__)

View file

@ -22,13 +22,13 @@
* THE SOFTWARE.
*/
#include <exception>
#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);
}
}