Changed the assert interface to accept a format string

This commit is contained in:
Snaipe 2015-09-08 18:46:04 +02:00
parent b8374bca16
commit 4d114fdd38
15 changed files with 630 additions and 299 deletions

View file

@ -110,6 +110,12 @@ if (PCRE_FOUND)
set(HAVE_PCRE 1)
endif ()
if ("${CMAKE_SYSTEM_NAME}" EQUAL "Linux")
set (SOURCE_FILES ${SOURCE_FILES}
src/asprintf.c
)
endif ()
set(INTERFACE_FILES
include/criterion/assert.h
include/criterion/abort.h
@ -123,6 +129,7 @@ set(INTERFACE_FILES
include/criterion/ordered-set.h
include/criterion/stats.h
include/criterion/theories.h
include/criterion/asprintf-compat.h
)
# Generate the configure file

View file

@ -29,6 +29,7 @@
CR_BEGIN_C_API
CR_API NORETURN void criterion_abort_test(void);
CR_API CR_INLINE void criterion_continue_test(void) {}
CR_END_C_API

View file

@ -0,0 +1,43 @@
/*
* 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_ASPRINTF_COMPAT_H_
# define CRITERION_ASPRINTF_COMPAT_H_
# ifdef __cplusplus
# include <cstdarg>
# else
# include <stdarg.h>
# endif
# include "common.h"
CR_BEGIN_C_API
FORMAT(printf, 2, 3)
CR_API int asprintf(char **strp, const char *fmt, ...) CR_NOTHROW;
CR_API int vasprintf(char **strp, const char *fmt, va_list ap) CR_NOTHROW;
CR_END_C_API
#endif /* !CRITERION_ASPRINTF_COMPAT_H_ */

View file

@ -24,11 +24,13 @@
#ifndef CRITERION_ASSERT_H_
# define CRITERION_ASSERT_H_
# include "preprocess.h"
# include "asprintf-compat.h"
# ifdef __cplusplus
# include <cstring>
# include <cstdlib>
using std::strcmp;
using std::memcmp;
# include <algorithm>
# else
# include <string.h>
# include <stdlib.h>
@ -41,11 +43,6 @@ using std::memcmp;
# include "event.h"
# include "abort.h"
enum criterion_assert_kind {
NORMAL,
FATAL
};
struct criterion_assert_args {
const char *msg;
int sentinel_;
@ -60,264 +57,372 @@ struct criterion_assert_args {
# define CR_GET_CONDITION_STR(Condition, ...) #Condition
# define CR_VA_SKIP(_, ...) __VA_ARGS__
# ifndef __cplusplus
# define CR_ZERO_FILL(Arg) memset(&(Arg), 0, sizeof (Arg))
# ifdef __cplusplus
# define CR_STDN std::
# else
# define CR_ZERO_FILL(Arg) std::memset(&(Arg), 0, sizeof (Arg))
# define CR_STDN
# endif
# define cr_assert_impl(Kind, ...) \
# define CR_INIT_STATS_(BufSize, MsgVar, ...) CR_EXPAND( \
do { \
struct criterion_assert_args args = { \
CR_EXPAND(CR_VA_SKIP(__VA_ARGS__)) \
}; \
bool passed = !!(CR_EXPAND(CR_GET_CONDITION(__VA_ARGS__))); \
struct criterion_assert_stats stat; \
CR_ZERO_FILL(stat); \
stat.kind = (Kind); \
stat.condition = CR_EXPAND(CR_GET_CONDITION_STR(__VA_ARGS__)); \
stat.message = args.msg ? args.msg : ""; \
stat.passed = passed; \
stat.file = __FILE__; \
stat.line = __LINE__; \
send_event(ASSERT, &stat, sizeof (stat)); \
if (!passed && (Kind) == FATAL) \
criterion_abort_test(); \
const char *default_msg = "" CR_VA_HEAD(__VA_ARGS__); \
char *formatted_msg = NULL; \
int msglen = asprintf(&formatted_msg, "" CR_VA_TAIL(__VA_ARGS__)); \
MsgVar = formatted_msg ? formatted_msg : default_msg; \
\
if (!formatted_msg) \
msglen = strlen(default_msg); \
\
BufSize = sizeof(struct criterion_assert_stats) \
+ sizeof (size_t) + msglen + 1; \
\
char *buf = (char*) CR_STDN malloc(BufSize); \
stat = (struct criterion_assert_stats*) buf; \
\
CR_STDN memset(buf, 0, sizeof (struct criterion_assert_stats)); \
buf += sizeof (struct criterion_assert_stats); \
*((size_t*) buf) = msglen; \
buf += sizeof (size_t); \
CR_STDN strcpy(buf, MsgVar); \
CR_STDN free(formatted_msg); \
} while (0))
# define CR_FAIL_ABORT_ criterion_abort_test
# define CR_FAIL_CONTINUES_ criterion_continue_test
# define cr_assert_impl(Fail, Condition, ...) \
do { \
bool passed = !!(Condition); \
\
const char *msg = NULL; \
size_t bufsize; \
\
_Pragma("GCC diagnostic ignored \"-Wformat-zero-length\"") \
struct criterion_assert_stats *stat; \
CR_EXPAND(CR_INIT_STATS_(bufsize, msg, CR_VA_TAIL(__VA_ARGS__))); \
stat->passed = passed; \
stat->file = __FILE__; \
stat->line = __LINE__; \
\
send_event(ASSERT, stat, bufsize); \
CR_STDN free(stat); \
\
if (!passed) \
Fail(); \
} while (0)
// Common asserts
// Base assertions
# define cr_abort_test(Message) \
do { \
const char *msg = (Message); \
cr_assert(0, msg ? msg : "The conditions for this test were not met.");\
# define cr_fail(Fail, ...) \
CR_EXPAND(cr_assert_impl( \
Fail, \
0, \
dummy, \
"The condition for this assertion were not met.", \
__VA_ARGS__ \
))
# define cr_assert_fail(...) CR_EXPAND(cr_fail(CR_FAIL_ABORT_, __VA_ARGS__))
# define cr_expect_fail(...) CR_EXPAND(cr_fail(CR_FAIL_CONTINUES_, __VA_ARGS__))
# define cr_assert(...) CR_EXPAND(cr_assert_impl( \
CR_FAIL_ABORT_, \
CR_VA_HEAD(__VA_ARGS__), \
dummy, \
CR_STR(CR_VA_HEAD(__VA_ARGS__)), \
CR_VA_TAIL(__VA_ARGS__)))
# define cr_expect(...) CR_EXPAND(cr_assert_impl( \
CR_FAIL_CONTINUES_, \
CR_VA_HEAD(__VA_ARGS__), \
dummy, \
CR_STR(CR_VA_HEAD(__VA_ARGS__)), \
CR_VA_TAIL(__VA_ARGS__)))
# define cr_assert_not(...) CR_EXPAND(cr_assert_impl( \
CR_FAIL_ABORT_, \
!(CR_VA_HEAD(__VA_ARGS__)), \
dummy, \
CR_STR(!(CR_VA_HEAD(__VA_ARGS__))), \
CR_VA_TAIL(__VA_ARGS__)))
# define cr_expect_not(...) CR_EXPAND(cr_assert_impl( \
CR_FAIL_CONTINUES_, \
!(CR_VA_HEAD(__VA_ARGS__)), \
dummy, \
CR_STR(!(CR_VA_HEAD(__VA_ARGS__))), \
CR_VA_TAIL(__VA_ARGS__)))
// Common binary assertions
# define cr_assert_op_(Fail, Op, Actual, Expected, ...) CR_EXPAND(cr_assert_impl( \
Fail, \
(Actual) Op (Expected), \
dummy, \
CR_STR((Actual) Op (Expected)), \
__VA_ARGS__ \
))
# define cr_assert_op_va_(Fail, Op, ...) CR_EXPAND(cr_assert_op_( \
Fail, \
Op, \
CR_VA_HEAD(__VA_ARGS__), \
CR_VA_HEAD(CR_VA_TAIL(__VA_ARGS__)), \
CR_VA_TAIL(CR_VA_TAIL(__VA_ARGS__))))
# define cr_assert_eq(...) CR_EXPAND(cr_assert_op_va_(CR_FAIL_ABORT_, ==, __VA_ARGS__))
# define cr_expect_eq(...) CR_EXPAND(cr_assert_op_va_(CR_FAIL_CONTINUES_, ==, __VA_ARGS__))
# define cr_assert_neq(...) CR_EXPAND(cr_assert_op_va_(CR_FAIL_ABORT_, !=, __VA_ARGS__))
# define cr_expect_neq(...) CR_EXPAND(cr_assert_op_va_(CR_FAIL_CONTINUES_, !=, __VA_ARGS__))
# define cr_assert_lt(...) CR_EXPAND(cr_assert_op_va_(CR_FAIL_ABORT_, <, __VA_ARGS__))
# define cr_expect_lt(...) CR_EXPAND(cr_assert_op_va_(CR_FAIL_CONTINUES_, <, __VA_ARGS__))
# define cr_assert_leq(...) CR_EXPAND(cr_assert_op_va_(CR_FAIL_ABORT_, <=, __VA_ARGS__))
# define cr_expect_leq(...) CR_EXPAND(cr_assert_op_va_(CR_FAIL_CONTINUES_, <=, __VA_ARGS__))
# define cr_assert_gt(...) CR_EXPAND(cr_assert_op_va_(CR_FAIL_ABORT_, >, __VA_ARGS__))
# define cr_expect_gt(...) CR_EXPAND(cr_assert_op_va_(CR_FAIL_CONTINUES_, >, __VA_ARGS__))
# define cr_assert_geq(...) CR_EXPAND(cr_assert_op_va_(CR_FAIL_ABORT_, >=, __VA_ARGS__))
# define cr_expect_geq(...) CR_EXPAND(cr_assert_op_va_(CR_FAIL_CONTINUES_, >=, __VA_ARGS__))
// Common unary assertions
# define cr_assert_null(...) CR_EXPAND(cr_assert_eq(CR_VA_HEAD(__VA_ARGS__), NULL, CR_VA_TAIL(__VA_ARGS__)))
# define cr_expect_null(...) CR_EXPAND(cr_expect_eq(CR_VA_HEAD(__VA_ARGS__), NULL, CR_VA_TAIL(__VA_ARGS__)))
# define cr_assert_not_null(...) CR_EXPAND(cr_assert_neq(CR_VA_HEAD(__VA_ARGS__), NULL, CR_VA_TAIL(__VA_ARGS__)))
# define cr_expect_not_null(...) CR_EXPAND(cr_expect_neq(CR_VA_HEAD(__VA_ARGS__), NULL, CR_VA_TAIL(__VA_ARGS__)))
// Floating-point assertions
# define cr_assert_float_eq_op_(Actual, Expected, Epsilon) \
(Expected) - (Actual) <= (Epsilon) && (Actual) - (Expected) <= (Epsilon)
# define cr_assert_float_neq_op_(Actual, Expected, Epsilon) \
(Expected) - (Actual) > (Epsilon) || (Actual) - (Expected) > (Epsilon)
# define cr_assert_float_op_(Fail, Op, Actual, Expected, Epsilon, ...) \
CR_EXPAND(cr_assert_impl( \
Fail, \
Op(Actual, Expected, Epsilon), \
dummy, \
CR_STR(Op(Actual, Expected, Epsilon)), \
__VA_ARGS__ \
))
# define cr_assert_float_op_va_(Fail, Op, ...) \
CR_EXPAND(cr_assert_float_op_( \
Fail, \
Op, \
CR_VA_HEAD(__VA_ARGS__), \
CR_VA_HEAD(CR_VA_TAIL(__VA_ARGS__)), \
CR_VA_HEAD(CR_VA_TAIL(CR_VA_TAIL(__VA_ARGS__))), \
CR_VA_TAIL(CR_VA_TAIL(CR_VA_TAIL(__VA_ARGS__))) \
))
# define cr_assert_float_eq(...) CR_EXPAND(cr_assert_float_op_va_(CR_FAIL_ABORT_, cr_assert_float_eq_op_, __VA_ARGS__))
# define cr_expect_float_eq(...) CR_EXPAND(cr_assert_float_op_va_(CR_FAIL_CONTINUES_, cr_assert_float_eq_op_, __VA_ARGS__))
# define cr_assert_float_neq(...) CR_EXPAND(cr_assert_float_op_va_(CR_FAIL_ABORT_, cr_assert_float_neq_op_, __VA_ARGS__))
# define cr_expect_float_neq(...) CR_EXPAND(cr_assert_float_op_va_(CR_FAIL_CONTINUES_, cr_assert_float_neq_op_, __VA_ARGS__))
// String assertions
# define cr_assert_str_op_(Fail, Op, Actual, Expected, ...) \
CR_EXPAND(cr_assert_impl( \
Fail, \
CR_STDN strcmp((Actual), (Expected)) Op 0, \
dummy, \
CR_STR((as strings) (Actual) Op (Expected)), \
__VA_ARGS__ \
))
# define cr_assert_str_op_va_(Fail, Op, ...) \
CR_EXPAND(cr_assert_str_op_( \
Fail, \
Op, \
CR_VA_HEAD(__VA_ARGS__), \
CR_VA_HEAD(CR_VA_TAIL(__VA_ARGS__)), \
CR_VA_TAIL(CR_VA_TAIL(__VA_ARGS__)) \
))
# define cr_assert_str_eq(...) CR_EXPAND(cr_assert_str_op_va_(CR_FAIL_ABORT_, ==, __VA_ARGS__))
# define cr_expect_str_eq(...) CR_EXPAND(cr_assert_str_op_va_(CR_FAIL_CONTINUES_, ==, __VA_ARGS__))
# define cr_assert_str_neq(...) CR_EXPAND(cr_assert_str_op_va_(CR_FAIL_ABORT_, !=, __VA_ARGS__))
# define cr_expect_str_neq(...) CR_EXPAND(cr_assert_str_op_va_(CR_FAIL_CONTINUES_, !=, __VA_ARGS__))
# define cr_assert_str_lt(...) CR_EXPAND(cr_assert_str_op_va_(CR_FAIL_ABORT_, <, __VA_ARGS__))
# define cr_expect_str_lt(...) CR_EXPAND(cr_assert_str_op_va_(CR_FAIL_CONTINUES_, <, __VA_ARGS__))
# define cr_assert_str_leq(...) CR_EXPAND(cr_assert_str_op_va_(CR_FAIL_ABORT_, <=, __VA_ARGS__))
# define cr_expect_str_leq(...) CR_EXPAND(cr_assert_str_op_va_(CR_FAIL_CONTINUES_, <=, __VA_ARGS__))
# define cr_assert_str_gt(...) CR_EXPAND(cr_assert_str_op_va_(CR_FAIL_ABORT_, >, __VA_ARGS__))
# define cr_expect_str_gt(...) CR_EXPAND(cr_assert_str_op_va_(CR_FAIL_CONTINUES_, >, __VA_ARGS__))
# define cr_assert_str_geq(...) CR_EXPAND(cr_assert_str_op_va_(CR_FAIL_ABORT_, >=, __VA_ARGS__))
# define cr_expect_str_geq(...) CR_EXPAND(cr_assert_str_op_va_(CR_FAIL_CONTINUES_, >=, __VA_ARGS__))
// Array assertions
# define cr_assert_mem_op_(Fail, Op, Actual, Expected, Size, ...) \
CR_EXPAND(cr_assert_impl( \
Fail, \
CR_STDN memcmp((Actual), (Expected), (Size)) Op 0, \
dummy, \
CR_STR((Actual)[0 .. Size] Op (Expected)[0 .. Size]), \
__VA_ARGS__ \
))
# define cr_assert_mem_op_va_(Fail, Op, ...) \
CR_EXPAND(cr_assert_mem_op_( \
Fail, \
Op, \
CR_VA_HEAD(__VA_ARGS__), \
CR_VA_HEAD(CR_VA_TAIL(__VA_ARGS__)), \
CR_VA_HEAD(CR_VA_TAIL(CR_VA_TAIL(__VA_ARGS__))), \
CR_VA_TAIL(CR_VA_TAIL(CR_VA_TAIL(__VA_ARGS__))) \
))
# define cr_assert_arr_eq(...) CR_EXPAND(cr_assert_mem_op_va_(CR_FAIL_ABORT_, ==, __VA_ARGS__))
# define cr_expect_arr_eq(...) CR_EXPAND(cr_assert_mem_op_va_(CR_FAIL_CONTINUES_, ==, __VA_ARGS__))
# define cr_assert_arr_neq(...) CR_EXPAND(cr_assert_mem_op_va_(CR_FAIL_ABORT_, !=, __VA_ARGS__))
# define cr_expect_arr_neq(...) CR_EXPAND(cr_assert_mem_op_va_(CR_FAIL_CONTINUES_, !=, __VA_ARGS__))
// Safe array comparison assertions
# if defined(__GNUC__) || defined(__cplusplus)
# ifdef __cplusplus
# define CR_ARR_COMPARE_(A, B, Size, Cmp, Result) \
int Result = std::lexicographical_compare((A), (A) + Size, (B), (B) + Size, Cmp)
# else
# define CR_ARR_COMPARE_(A, B, Size, Cmp, Result) \
__typeof__(&(A)[0]) first = (A); \
__typeof__(&(B)[0]) second = (B); \
int Result = 0; \
size_t i, size; \
for (i = 0, size = (Size); !Result && i < size; ++i) \
Result = Cmp(first + i, second + i)
# endif
# define cr_assert_arr_op_cmp_(Fail, Op, Actual, Expected, Size, Cmp, ...) \
do { \
CR_ARR_COMPARE_(Actual, Expected, Size, Cmp, order); \
CR_EXPAND(cr_assert_impl( \
Fail, \
order Op 0, \
dummy, \
CR_STR((Actual)[0 .. Size] Op (Expected)[0 .. Size]), \
__VA_ARGS__ \
)); \
} while (0)
# ifdef __cplusplus
# define CR_SENTINEL 0
# define cr_assert_arr_op_cmp_va_(Fail, Op, ...) \
CR_EXPAND(cr_assert_arr_op_cmp_( \
Fail, \
Op, \
CR_VA_HEAD(__VA_ARGS__), \
CR_VA_HEAD(CR_VA_TAIL(__VA_ARGS__)), \
CR_VA_HEAD(CR_VA_TAIL(CR_VA_TAIL(__VA_ARGS__))), \
CR_VA_HEAD(CR_VA_TAIL(CR_VA_TAIL(CR_VA_TAIL(__VA_ARGS__)))), \
CR_VA_TAIL(CR_VA_TAIL(CR_VA_TAIL(CR_VA_TAIL(__VA_ARGS__)))) \
))
# define cr_assert_arr_eq_cmp(...) CR_EXPAND(cr_assert_arr_op_cmp_va_(CR_FAIL_ABORT_, ==, __VA_ARGS__))
# define cr_expect_arr_eq_cmp(...) CR_EXPAND(cr_assert_arr_op_cmp_va_(CR_FAIL_CONTINUES_, ==, __VA_ARGS__))
# define cr_assert_arr_neq_cmp(...) CR_EXPAND(cr_assert_arr_op_cmp_va_(CR_FAIL_ABORT_, !=, __VA_ARGS__))
# define cr_expect_arr_neq_cmp(...) CR_EXPAND(cr_assert_arr_op_cmp_va_(CR_FAIL_CONTINUES_, !=, __VA_ARGS__))
# define cr_assert_arr_lt_cmp(...) CR_EXPAND(cr_assert_arr_op_cmp_va_(CR_FAIL_ABORT_, <, __VA_ARGS__))
# define cr_expect_arr_lt_cmp(...) CR_EXPAND(cr_assert_arr_op_cmp_va_(CR_FAIL_CONTINUES_, <, __VA_ARGS__))
# define cr_assert_arr_leq_cmp(...) CR_EXPAND(cr_assert_arr_op_cmp_va_(CR_FAIL_ABORT_, <=, __VA_ARGS__))
# define cr_expect_arr_leq_cmp(...) CR_EXPAND(cr_assert_arr_op_cmp_va_(CR_FAIL_CONTINUES_, <=, __VA_ARGS__))
# define cr_assert_arr_gt_cmp(...) CR_EXPAND(cr_assert_arr_op_cmp_va_(CR_FAIL_ABORT_, >, __VA_ARGS__))
# define cr_expect_arr_gt_cmp(...) CR_EXPAND(cr_assert_arr_op_cmp_va_(CR_FAIL_CONTINUES_, >, __VA_ARGS__))
# define cr_assert_arr_geq_cmp(...) CR_EXPAND(cr_assert_arr_op_cmp_va_(CR_FAIL_ABORT_, >=, __VA_ARGS__))
# define cr_expect_arr_geq_cmp(...) CR_EXPAND(cr_assert_arr_op_cmp_va_(CR_FAIL_CONTINUES_, >=, __VA_ARGS__))
# else
# define CR_SENTINEL .sentinel_ = 0
# define CRITERION_GNUC_WARN__(Msg) \
_Pragma(#Msg)
# define CRITERION_GNUC_WARN_(Name) CRITERION_GNUC_WARN__( \
message \
"The `" #Name "` macro is only available on GNU C compilers." \
)
# define cr_assert_arr_eq_cmp(...) CRITERION_GNUC_WARN_(cr_assert_arr_eq_cmp) CR_NOOP
# define cr_expect_arr_eq_cmp(...) CRITERION_GNUC_WARN_(cr_expect_arr_eq_cmp) CR_NOOP
# define cr_assert_arr_neq_cmp(...) CRITERION_GNUC_WARN_(cr_assert_arr_neq_cmp) CR_NOOP
# define cr_expect_arr_neq_cmp(...) CRITERION_GNUC_WARN_(cr_expect_arr_neq_cmp) CR_NOOP
# define cr_assert_arr_lt_cmp(...) CRITERION_GNUC_WARN_(cr_assert_arr_lt_cmp) CR_NOOP
# define cr_expect_arr_lt_cmp(...) CRITERION_GNUC_WARN_(cr_expect_arr_lt_cmp) CR_NOOP
# define cr_assert_arr_leq_cmp(...) CRITERION_GNUC_WARN_(cr_assert_arr_leq_cmp) CR_NOOP
# define cr_expect_arr_leq_cmp(...) CRITERION_GNUC_WARN_(cr_expect_arr_leq_cmp) CR_NOOP
# define cr_assert_arr_gt_cmp(...) CRITERION_GNUC_WARN_(cr_assert_arr_gt_cmp) CR_NOOP
# define cr_expect_arr_gt_cmp(...) CRITERION_GNUC_WARN_(cr_expect_arr_gt_cmp) CR_NOOP
# define cr_assert_arr_geq_cmp(...) CRITERION_GNUC_WARN_(cr_assert_arr_geq_cmp) CR_NOOP
# define cr_expect_arr_geq_cmp(...) CRITERION_GNUC_WARN_(cr_expect_arr_geq_cmp) CR_NOOP
# endif
# define cr_assert(...) CR_EXPAND(cr_assert_(__VA_ARGS__, CR_SENTINEL))
# define cr_expect(...) CR_EXPAND(cr_expect_(__VA_ARGS__, CR_SENTINEL))
# define cr_assert_(Condition, ...) CR_EXPAND(cr_assert_impl(FATAL, Condition, __VA_ARGS__))
# define cr_expect_(Condition, ...) CR_EXPAND(cr_assert_impl(NORMAL, Condition, __VA_ARGS__))
# define cr_assert_not(...) CR_EXPAND(cr_assert_not_(__VA_ARGS__, CR_SENTINEL))
# define cr_expect_not(...) CR_EXPAND(cr_expect_not_(__VA_ARGS__, CR_SENTINEL))
# define cr_assert_not_(Condition, ...) \
CR_EXPAND(cr_assert_impl(FATAL, !(Condition), __VA_ARGS__))
# define cr_expect_not_(Condition, ...) \
CR_EXPAND(cr_expect_impl(NORMAL, !(Condition), __VA_ARGS__))
// Native asserts
# define cr_assert_op_(Op, Actual, Expected, ...) \
CR_EXPAND(cr_assert_impl(FATAL, (Actual) Op (Expected), __VA_ARGS__))
# define cr_expect_op_(Op, Actual, Expected, ...) \
CR_EXPAND(cr_assert_impl(NORMAL, (Actual) Op (Expected), __VA_ARGS__))
# define cr_assert_eq(...) CR_EXPAND(cr_assert_op_(==, __VA_ARGS__, CR_SENTINEL))
# define cr_expect_eq(...) CR_EXPAND(cr_expect_op_(==, __VA_ARGS__, CR_SENTINEL))
# define cr_assert_neq(...) CR_EXPAND(cr_assert_op_(!=, __VA_ARGS__, CR_SENTINEL))
# define cr_expect_neq(...) CR_EXPAND(cr_expect_op_(!=, __VA_ARGS__, CR_SENTINEL))
# define cr_assert_lt(...) CR_EXPAND(cr_assert_op_(<, __VA_ARGS__, CR_SENTINEL))
# define cr_expect_lt(...) CR_EXPAND(cr_expect_op_(<, __VA_ARGS__, CR_SENTINEL))
# define cr_assert_gt(...) CR_EXPAND(cr_assert_op_(>, __VA_ARGS__, CR_SENTINEL))
# define cr_expect_gt(...) CR_EXPAND(cr_expect_op_(>, __VA_ARGS__, CR_SENTINEL))
# define cr_assert_leq(...) CR_EXPAND(cr_assert_op_(<=, __VA_ARGS__, CR_SENTINEL))
# define cr_expect_leq(...) CR_EXPAND(cr_expect_op_(<=, __VA_ARGS__, CR_SENTINEL))
# define cr_assert_geq(...) CR_EXPAND(cr_assert_op_(>=, __VA_ARGS__, CR_SENTINEL))
# define cr_expect_geq(...) CR_EXPAND(cr_expect_op_(>=, __VA_ARGS__, CR_SENTINEL))
# define cr_assert_null_(Value, ...) \
CR_EXPAND(cr_assert_impl(FATAL, (Value) == NULL, __VA_ARGS__))
# define cr_expect_null_(Value, ...) \
CR_EXPAND(cr_assert_impl(NORMAL, (Value) == NULL, __VA_ARGS__))
# define cr_assert_null(...) CR_EXPAND(cr_assert_null_(__VA_ARGS__, CR_SENTINEL))
# define cr_expect_null(...) CR_EXPAND(cr_expect_null_(__VA_ARGS__, CR_SENTINEL))
# define cr_assert_not_null_(Value, ...) \
CR_EXPAND(cr_assert_impl(FATAL, (Value) != NULL, __VA_ARGS__))
# define cr_expect_not_null_(Value, ...) \
CR_EXPAND(cr_assert_impl(NORMAL, (Value) != NULL, __VA_ARGS__))
# define cr_assert_not_null(...) CR_EXPAND(cr_assert_not_null_(__VA_ARGS__, CR_SENTINEL))
# define cr_expect_not_null(...) CR_EXPAND(cr_expect_not_null_(__VA_ARGS__, CR_SENTINEL))
// Floating-point asserts
# define cr_assert_float_eq(...) \
CR_EXPAND(cr_assert_float_eq_(__VA_ARGS__, CR_SENTINEL))
# define cr_expect_float_eq(...) \
CR_EXPAND(cr_expect_float_eq_(__VA_ARGS__, CR_SENTINEL))
# define cr_assert_float_eq_(Actual, Expected, Epsilon, ...) \
CR_EXPAND(cr_assert_impl(FATAL, (Expected) - (Actual) <= (Epsilon) \
&& (Actual) - (Expected) <= (Epsilon), \
__VA_ARGS__))
# define cr_expect_float_eq_(Actual, Expected, Epsilon, ...) \
CR_EXPAND(cr_assert_impl(NORMAL, (Expected) - (Actual) <= (Epsilon) \
&& (Actual) - (Expected) <= (Epsilon), \
__VA_ARGS__))
# define cr_assert_float_neq(...) \
CR_EXPAND(cr_assert_float_neq_(__VA_ARGS__, CR_SENTINEL))
# define cr_expect_float_neq(...) \
CR_EXPAND(cr_expect_float_neq_(__VA_ARGS__, CR_SENTINEL))
# define cr_assert_float_neq_(Actual, Expected, Epsilon, ...) \
CR_EXPAND(cr_assert_impl(FATAL, (Expected) - (Actual) > (Epsilon) \
|| (Actual) - (Expected) > (Epsilon), \
__VA_ARGS__))
# define cr_expect_float_neq_(Actual, Expected, Epsilon, ...) \
CR_EXPAND(cr_assert_impl(NORMAL, (Expected) - (Actual) > (Epsilon) \
|| (Actual) - (Expected) > (Epsilon), \
__VA_ARGS__))
// String asserts
# define cr_assert_strings_(Op, Actual, Expected, ...) \
CR_EXPAND(cr_assert_impl(FATAL, strcmp((Actual), (Expected)) Op 0, __VA_ARGS__))
# define cr_expect_strings_(Op, Actual, Expected, ...) \
CR_EXPAND(cr_assert_impl(NORMAL, strcmp((Actual), (Expected)) Op 0, __VA_ARGS__))
# define cr_assert_strings_eq(...) \
CR_EXPAND(cr_assert_strings_(==, __VA_ARGS__, CR_SENTINEL))
# define cr_expect_strings_eq(...) \
CR_EXPAND(cr_expect_strings_(==, __VA_ARGS__, CR_SENTINEL))
# define cr_assert_strings_neq(...) \
CR_EXPAND(cr_assert_strings_(!=, __VA_ARGS__, CR_SENTINEL))
# define cr_expect_strings_neq(...) \
CR_EXPAND(cr_expect_strings_(!=, __VA_ARGS__, CR_SENTINEL))
# define cr_assert_strings_gt(...) CR_EXPAND(cr_assert_strings_(>, __VA_ARGS__, CR_SENTINEL))
# define cr_expect_strings_gt(...) CR_EXPAND(cr_expect_strings_(>, __VA_ARGS__, CR_SENTINEL))
# define cr_assert_strings_lt(...) CR_EXPAND(cr_assert_strings_(<, __VA_ARGS__, CR_SENTINEL))
# define cr_expect_strings_lt(...) CR_EXPAND(cr_expect_strings_(<, __VA_ARGS__, CR_SENTINEL))
# define cr_assert_strings_leq(...) CR_EXPAND(cr_assert_strings_(<=, __VA_ARGS__, CR_SENTINEL))
# define cr_expect_strings_leq(...) CR_EXPAND(cr_expect_strings_(<=, __VA_ARGS__, CR_SENTINEL))
# define cr_assert_strings_geq(...) CR_EXPAND(cr_assert_strings_(>=, __VA_ARGS__, CR_SENTINEL))
# define cr_expect_strings_geq(...) CR_EXPAND(cr_expect_strings_(>=, __VA_ARGS__, CR_SENTINEL))
// Array asserts
# define cr_assert_arrays_eq(...) \
CR_EXPAND(cr_assert_arrays_eq_(__VA_ARGS__, CR_SENTINEL))
# define cr_expect_arrays_eq(...) \
CR_EXPAND(cr_expect_arrays_eq_(__VA_ARGS__, CR_SENTINEL))
# define cr_assert_arrays_neq(...) \
CR_EXPAND(cr_assert_arrays_neq_(__VA_ARGS__, CR_SENTINEL))
# define cr_expect_arrays_neq(...) \
CR_EXPAND(cr_expect_arrays_neq_(__VA_ARGS__, CR_SENTINEL))
# define cr_assert_arrays_eq_(A, B, Size, ...) \
CR_EXPAND(cr_assert_impl(FATAL, !memcmp((A), (B), (Size)), \
__VA_ARGS__))
# define cr_expect_arrays_eq_(A, B, Size, ...) \
CR_EXPAND(cr_assert_impl(NORMAL, !memcmp((A), (B), (Size)), \
__VA_ARGS__))
# define cr_assert_arrays_neq_(A, B, Size, ...) \
CR_EXPAND(cr_assert_impl(FATAL, memcmp((A), (B), (Size)), \
__VA_ARGS__))
# define cr_expect_arrays_neq_(A, B, Size, ...) \
CR_EXPAND(cr_assert_impl(NORMAL, memcmp((A), (B), (Size)), \
__VA_ARGS__))
# ifdef __GNUC__
# define CRIT_ARR_COMPARE_(A, B, Size, Cmp, Result) \
__typeof__(&(A)[0]) first = (A); \
__typeof__(&(B)[0]) second = (B); \
int equals = 1; \
size_t i, size; \
for (i = 0, size = (Size); equals && i < size; ++i) \
equals = equals && !Cmp(first + i, second + i)
# define cr_assert_arrays_eq_cmp_(A, B, Size, Cmp, ...) \
do { \
CRIT_ARR_COMPARE_(A, B, Size, Cmp, equals); \
cr_assert_impl(FATAL, equals, \
__VA_ARGS__); \
} while (0)
# define cr_expect_arrays_eq_cmp_(A, B, Size, Cmp, ...) \
do { \
CRIT_ARR_COMPARE_(A, B, Size, Cmp, equals); \
cr_assert_impl(NORMAL, equals, \
__VA_ARGS__); \
} while (0)
# define cr_assert_arrays_eq_cmp(...) \
cr_assert_arrays_eq_cmp_(__VA_ARGS__, CR_SENTINEL)
# define cr_expect_arrays_eq_cmp(...) \
cr_expect_arrays_eq_cmp_(__VA_ARGS__, CR_SENTINEL)
# define cr_assert_arrays_neq_cmp_(A, B, Size, Cmp, ...) \
do { \
CRIT_ARR_COMPARE_(A, B, Size, Cmp, equals); \
cr_assert_impl(FATAL, !equals, \
__VA_ARGS__); \
} while (0)
# define cr_expect_arrays_neq_cmp_(A, B, Size, Cmp, ...) \
do { \
CRIT_ARR_COMPARE_(A, B, Size, Cmp, equals); \
cr_assert_impl(NORMAL, equals, \
__VA_ARGS__); \
} while (0)
# define cr_assert_arrays_neq_cmp(...) \
cr_assert_arrays_eq_cmp_(__VA_ARGS__, CR_SENTINEL)
# define cr_expect_arrays_neq_cmp(...) \
cr_expect_arrays_eq_cmp_(__VA_ARGS__, CR_SENTINEL)
# endif /* !__GNUC__ */
# ifdef __cplusplus
# define cr_assert_throw(...) CR_EXPAND(cr_assert_throw_(__VA_ARGS__, CR_SENTINEL))
# define cr_assert_throw_(Statement, Exception, ...) \
try { \
Statement; \
} catch (Exception &ex) { \
} catch (...) { CR_EXPAND(cr_assert_impl(FATAL, 0, __VA_ARGS__)); }
# define cr_assert_no_throw(...) CR_EXPAND(cr_assert_not_throw_(__VA_ARGS__, CR_SENTINEL))
# define cr_assert_no_throw_(Statement, Exception, ...) \
try { \
Statement; \
} catch (Exception &ex) { CR_EXPAND(cr_assert_impl(FATAL, 0, __VA_ARGS__)); }
# define cr_assert_throw_(Fail, Statement, Exception, ...) \
try { \
Statement; \
} catch (Exception &ex) { \
} catch (...) { CR_EXPAND(cr_fail(Fail, CR_VA_TAIL(__VA_ARGS__))); }
# define cr_expect_throw(...) CR_EXPAND(cr_expect_throw_(__VA_ARGS__, CR_SENTINEL))
# define cr_expect_throw_(Statement, Exception, ...) \
try { \
Statement; \
} catch (Exception &ex) { \
} catch (...) { CR_EXPAND(cr_assert_impl(NORMAL, 0, __VA_ARGS__)); }
# define cr_assert_throw_va_(...) \
CR_EXPAND(cr_assert_throw_( \
CR_VA_HEAD(__VA_ARGS__), \
CR_VA_HEAD(CR_VA_TAIL(__VA_ARGS__)), \
CR_VA_HEAD(CR_VA_TAIL(CR_VA_TAIL(__VA_ARGS__))), \
dummy, \
CR_VA_TAIL(CR_VA_TAIL(CR_VA_TAIL(__VA_ARGS__))) \
))
# define cr_assert_throw(...) CR_EXPAND(cr_assert_throw_va_(CR_FAIL_ABORT_, __VA_ARGS__))
# define cr_expect_throw(...) CR_EXPAND(cr_assert_throw_va_(CR_FAIL_CONTINUES_, __VA_ARGS__))
# define cr_assert_no_throw_(Fail, Statement, Exception, ...) \
try { \
Statement; \
} catch (Exception &ex) { CR_EXPAND(cr_fail(Fail, CR_VA_TAIL(__VA_ARGS__))); }
# define cr_assert_no_throw_va_(...) \
CR_EXPAND(cr_assert_no_throw_( \
CR_VA_HEAD(__VA_ARGS__), \
CR_VA_HEAD(CR_VA_TAIL(__VA_ARGS__)), \
CR_VA_HEAD(CR_VA_TAIL(CR_VA_TAIL(__VA_ARGS__))), \
dummy, \
CR_VA_TAIL(CR_VA_TAIL(CR_VA_TAIL(__VA_ARGS__))) \
))
# define cr_assert_no_throw(...) CR_EXPAND(cr_assert_no_throw_va_(CR_FAIL_ABORT_, __VA_ARGS__))
# define cr_expect_no_throw(...) CR_EXPAND(cr_assert_no_throw_va_(CR_FAIL_CONTINUES_, __VA_ARGS__))
# define cr_expect_no_throw(...) CR_EXPAND(cr_expect_not_throw_(__VA_ARGS__, CR_SENTINEL))
# define cr_expect_no_throw_(Statement, Exception, ...) \
try { \
Statement; \
} catch (Exception &ex) { CR_EXPAND(cr_assert_impl(NORMAL, 0, __VA_ARGS__)); }
# endif
// The section below is here for backward compatibility purposes.
// It shall be removed in the text major version of Criterion
// It shall be removed in the next major version of Criterion
# ifndef CRITERION_NO_COMPAT
# define CRITERION_ASSERT_DEPRECATED_(Name) CRITERION_ASSERT_DEPRECATED__( \
@ -326,6 +431,13 @@ struct criterion_assert_args {
"please use `cr_" #Name "` instead." \
)
# define CRITERION_ASSERT_DEPRECATED_B(Name, Newname) \
CRITERION_ASSERT_DEPRECATED__( \
message \
"The `" #Name "` macro is deprecated, " \
"please use `" #Newname "` instead." \
)
# define CRITERION_ASSERT_DEPRECATED__(Msg) \
_Pragma(#Msg)
@ -339,6 +451,22 @@ struct criterion_assert_args {
# endif /* !_ASSERT_H */
# endif /* !assert */
// scheduled for removal after 2.0
# define cr_abort_test(Message) CRITERION_ASSERT_DEPRECATED_B(cr_abort_test, cr_assert_fail) cr_assert_fail(Message)
# define cr_assert_strings_eq(...) CRITERION_ASSERT_DEPRECATED_B(cr_assert_strings_eq, cr_assert_str_eq) cr_assert_str_eq(__VA_ARGS__)
# define cr_assert_strings_neq(...) CRITERION_ASSERT_DEPRECATED_B(cr_assert_strings_neq, cr_assert_str_neq) cr_assert_str_neq(__VA_ARGS__)
# define cr_assert_strings_lt(...) CRITERION_ASSERT_DEPRECATED_B(cr_assert_strings_lt, cr_assert_str_lt) cr_assert_str_lt(__VA_ARGS__)
# define cr_assert_strings_leq(...) CRITERION_ASSERT_DEPRECATED_B(cr_assert_strings_leq, cr_assert_str_leq) cr_assert_str_leq(__VA_ARGS__)
# define cr_assert_strings_gt(...) CRITERION_ASSERT_DEPRECATED_B(cr_assert_strings_gt, cr_assert_str_gt) cr_assert_str_gt(__VA_ARGS__)
# define cr_assert_strings_geq(...) CRITERION_ASSERT_DEPRECATED_B(cr_assert_strings_geq, cr_assert_str_geq) cr_assert_str_geq(__VA_ARGS__)
# define cr_assert_arrays_eq(...) CRITERION_ASSERT_DEPRECATED_B(cr_assert_arrays_eq, cr_assert_arr_eq) cr_assert_arr_eq(__VA_ARGS__)
# define cr_assert_arrays_neq(...) CRITERION_ASSERT_DEPRECATED_B(cr_assert_arrays_neq, cr_assert_arr_neq) cr_assert_arr_neq(__VA_ARGS__)
# define cr_assert_arrays_eq_cmp(...) CRITERION_ASSERT_DEPRECATED_B(cr_assert_arrays_eq_cmp, cr_assert_arr_eq_cmp) cr_assert_arr_eq_cmp(__VA_ARGS__)
# define cr_assert_arrays_neq_cmp(...) CRITERION_ASSERT_DEPRECATED_B(cr_assert_arrays_neq_cmp, cr_assert_arr_neq_cmp) cr_assert_arr_neq_cmp(__VA_ARGS__)
// scheduled for removal at 2.0
# define abort_test(Message) CRITERION_ASSERT_DEPRECATED_(abort_test) cr_abort_test(Message)
# define expect(...) CRITERION_ASSERT_DEPRECATED_(expect) cr_expect(__VA_ARGS__)
# define assert_not(...) CRITERION_ASSERT_DEPRECATED_(assert_not) cr_assert_not(__VA_ARGS__)

View file

@ -24,8 +24,6 @@
#ifndef CRITERION_COMMON_H_
# define CRITERION_COMMON_H_
# define CR_EXPAND(x) x
# if defined(_MSC_VER)
# if _MSC_VER < 1900
# error \
@ -101,12 +99,15 @@
# ifdef __GNUC__
# define UNUSED CR_ATTRIBUTE(unused)
# define NORETURN CR_ATTRIBUTE(noreturn)
# define CR_INLINE CR_ATTRIBUTE(always_inline) inline
# elif CR_IS_MSVC
# define UNUSED
# define NORETURN __declspec(noreturn)
# define CR_INLINE __forceinline
# else
# define UNUSED
# define NORETURN
# define CR_INLINE inline
# endif
# ifdef _WIN32

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_PREPROCESS_H_
# define CRITERION_PREPROCESS_H_
# define CR_NOOP do {} while(0)
# ifdef __cplusplus
# define CR_NOTHROW throw()
# else
# define CR_NOTHROW
# endif
# define CR_EXPAND(x) x
# define CR_STR(x) CR_EXPAND(CR_STR_(x))
# define CR_STR_(x) #x
# define CR_VA_TAIL(...) CR_EXPAND(CR_VA_TAIL_HELPER(CR_VA_TAIL_SELECT(__VA_ARGS__), __VA_ARGS__))
# define CR_VA_TAIL_HELPER(N, ...) CR_EXPAND(CR_VA_TAIL_HELPER_(N, __VA_ARGS__))
# define CR_VA_TAIL_HELPER_(N, ...) CR_EXPAND(CR_VA_TAIL_HELPER_##N(__VA_ARGS__))
# define CR_VA_TAIL_HELPER_1(Head)
# define CR_VA_TAIL_HELPER_2(Head, ...) __VA_ARGS__
# define CR_VA_HEAD(...) CR_EXPAND(CR_VA_HEAD_HELPER(CR_VA_TAIL_SELECT(__VA_ARGS__), __VA_ARGS__))
# define CR_VA_HEAD_HELPER(N, ...) CR_EXPAND(CR_VA_HEAD_HELPER_(N, __VA_ARGS__))
# define CR_VA_HEAD_HELPER_(N, ...) CR_EXPAND(CR_VA_HEAD_HELPER_##N(__VA_ARGS__))
# define CR_VA_HEAD_HELPER_1(Head) Head
# define CR_VA_HEAD_HELPER_2(Head, ...) Head
# define CR_VA_TAIL_SELECT(...) CR_EXPAND(CR_VA_TAIL_SELECT64(__VA_ARGS__, \
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, \
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, \
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, \
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, \
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, \
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, \
2, 2, 1, _))
# define CR_VA_TAIL_SELECT64( \
_01, _02, _03, _04, _05, _06, _07, _08, _09, _10, \
_11, _12, _13, _14, _15, _16, _17, _18, _19, _20, \
_21, _22, _23, _24, _25, _26, _27, _28, _29, _30, \
_31, _32, _33, _34, _35, _36, _37, _38, _39, _40, \
_41, _42, _43, _44, _45, _46, _47, _48, _49, _50, \
_51, _52, _53, _54, _55, _56, _57, _58, _59, _60, \
_61, _62, _63, X, ...) X
#endif /* !CRITERION_PREPROCESS_H_ */

View file

@ -27,8 +27,6 @@
# include "types.h"
struct criterion_assert_stats {
int kind;
const char *condition;
const char *message;
bool passed;
unsigned line;

View file

@ -12,23 +12,21 @@ Test(asserts, base) {
}
Test(asserts, old_school) {
if (false)
cr_abort_test("You can abort the test with a message from anywhere");
cr_abort_test(NULL); // or without a message
cr_expect_fail("You can fail an assertion with a message from anywhere");
cr_assert_fail(); // or without a message
}
Test(asserts, string) {
cr_assert_strings_eq("hello", "hello");
cr_assert_strings_neq("hello", "olleh");
cr_assert_str_eq("hello", "hello");
cr_assert_str_neq("hello", "olleh");
cr_assert_strings_gt("hello", "hell");
cr_assert_strings_geq("hello", "hell");
cr_assert_strings_geq("hello", "hello");
cr_assert_str_gt("hello", "hell");
cr_assert_str_geq("hello", "hell");
cr_assert_str_geq("hello", "hello");
cr_assert_strings_lt("hell", "hello");
cr_assert_strings_leq("hell", "hello");
cr_assert_strings_leq("hello", "hello");
cr_assert_str_lt("hell", "hello");
cr_assert_str_leq("hell", "hello");
cr_assert_str_leq("hello", "hello");
}
Test(asserts, native) {
@ -62,8 +60,8 @@ Test(asserts, array) {
int arr1[] = {1, 2, 3, 4};
int arr2[] = {4, 3, 2, 1};
cr_assert_arrays_eq(arr1, arr1, 4);
cr_assert_arrays_neq(arr1, arr2, 4);
cr_assert_arr_eq(arr1, arr1, 4);
cr_assert_arr_neq(arr1, arr2, 4);
#ifdef __GNUC__
struct dummy_struct s1[] = {{4, 2}, {2, 4}};
@ -74,7 +72,7 @@ Test(asserts, array) {
s2[1].a = 2;
s2[1].b = 4;
// cr_assert_arrays_eq(s1, s2, 2); not guaranteed to work on structs.
cr_assert_arrays_eq_cmp(s1, s2, 2, eq_dummy);
// cr_assert_arr_eq(s1, s2, 2); not guaranteed to work on structs.
cr_assert_arr_eq_cmp(s1, s2, 2, eq_dummy);
#endif
}

View file

@ -14,23 +14,21 @@ Test(asserts, base) {
}
Test(asserts, old_school) {
if (false)
cr_abort_test("You can abort the test with a message from anywhere");
cr_abort_test(NULL); // or without a message
cr_expect_fail("You can fail an assertion with a message from anywhere");
cr_assert_fail(); // or without a message
}
Test(asserts, string) {
cr_assert_strings_eq("hello", "hello");
cr_assert_strings_neq("hello", "olleh");
cr_assert_str_eq("hello", "hello");
cr_assert_str_neq("hello", "olleh");
cr_assert_strings_gt("hello", "hell");
cr_assert_strings_geq("hello", "hell");
cr_assert_strings_geq("hello", "hello");
cr_assert_str_gt("hello", "hell");
cr_assert_str_geq("hello", "hell");
cr_assert_str_geq("hello", "hello");
cr_assert_strings_lt("hell", "hello");
cr_assert_strings_leq("hell", "hello");
cr_assert_strings_leq("hello", "hello");
cr_assert_str_lt("hell", "hello");
cr_assert_str_leq("hell", "hello");
cr_assert_str_leq("hello", "hello");
}
Test(asserts, native) {
@ -64,8 +62,8 @@ Test(asserts, array) {
int arr1[] = {1, 2, 3, 4};
int arr2[] = {4, 3, 2, 1};
cr_assert_arrays_eq(arr1, arr1, 4);
cr_assert_arrays_neq(arr1, arr2, 4);
cr_assert_arr_eq(arr1, arr1, 4);
cr_assert_arr_neq(arr1, arr2, 4);
#ifdef __GNUC__
struct dummy_struct s1[] = {{4, 2}, {2, 4}};
@ -76,8 +74,8 @@ Test(asserts, array) {
s2[1].a = 2;
s2[1].b = 4;
// cr_assert_arrays_eq(s1, s2, 2); not guaranteed to work on structs.
cr_assert_arrays_eq_cmp(s1, s2, 2, eq_dummy);
// cr_assert_arrays_eq(&s1, &s2, 2); not guaranteed to work on structs.
cr_assert_arr_eq_cmp(&s1, &s2, 2, eq_dummy);
#endif
}

View file

@ -95,12 +95,12 @@ Theory((char c, bool b, short s, int i, long l, long long ll, float f, double d,
cr_assert_eq(ll, 1);
cr_assert_eq(f, 3.14f);
cr_assert_eq(d, 3.14);
cr_assert_strings_eq(str, "test");
cr_assert_strings_eq(cstr, "other test");
cr_assert_str_eq(str, "test");
cr_assert_str_eq(cstr, "other test");
cr_assert_eq(obj->foo, 42);
// abort to see the formatted string of all parameters
cr_abort_test(NULL);
cr_assert_fail();
}
// Manually generate datapoints
@ -117,5 +117,5 @@ static void generate_datapoints(void) {
Theory((int i), theory, gen, .init = generate_datapoints) {
(void) i;
cr_abort_test(NULL); // we fail to display the parameter
cr_assert_fail(); // we fail to display the parameter
}

View file

@ -103,12 +103,12 @@ Theory((char c, bool b, short s, int i, long l, long long ll, float f, double d,
cr_assert_eq(ll, 1);
cr_assert_eq(f, 3.14f);
cr_assert_eq(d, 3.14);
cr_assert_strings_eq(str, "test");
cr_assert_strings_eq(cstr, "other test");
cr_assert_str_eq(str, "test");
cr_assert_str_eq(cstr, "other test");
cr_assert_eq(obj->foo, 42);
// abort to see the formatted string of all parameters
cr_abort_test(NULL);
cr_assert_fail();
}
// Manually generate datapoints
@ -125,5 +125,5 @@ static void generate_datapoints(void) {
Theory((int i), theory, gen, .init = generate_datapoints) {
(void) i;
cr_abort_test(NULL); // we fail to display the parameter
cr_assert_fail(); // we fail to display the parameter
}

62
src/asprintf.c Normal file
View file

@ -0,0 +1,62 @@
/*
* 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.
*/
#include <limits.h>
#include <stdlib.h>
#include "criterion/asprintf-compat.h"
int asprintf(char **strp, const char *fmt, ...) {
va_list ap;
va_start(ap, fmt);
int res = vasprintf(strp, fmt, ap);
va_end(ap);
return res;
}
int vasprintf(char **strp, const char *fmt, va_list ap) {
va_list vl;
va_copy(vl, ap);
int size = vsnprintf(0, 0, fmt, vl);
int res = -1;
if (size < 0 || size >= INT_MAX) {
goto cleanup;
}
char *str = malloc(size + 1);
if (str) {
int res2 = vsnprintf(str, size + 1, fmt, ap);
if (res2 < 0 || res2 > size) {
free(str);
goto cleanup;
}
*strp = str;
res = res2;
}
cleanup:
va_end(vl);
return res;
}

View file

@ -37,6 +37,12 @@ void destroy_event(void *ptr, UNUSED void *meta) {
free(ev->data);
}
void destroy_assert_event(void *ptr, UNUSED void *meta) {
struct event *ev = ptr;
free((void*) ((struct criterion_assert_stats *) ev)->message);
free(ev->data);
}
struct event *read_event(FILE *f) {
unsigned kind;
if (fread(&kind, sizeof (unsigned), 1, f) == 0)
@ -45,18 +51,36 @@ struct event *read_event(FILE *f) {
switch (kind) {
case ASSERT: {
const size_t assert_size = sizeof (struct criterion_assert_stats);
unsigned char *buf = malloc(assert_size);
if (fread(buf, assert_size, 1, f) == 0) {
free(buf);
return NULL;
}
struct criterion_assert_stats *buf = NULL;
size_t *len = NULL;
char *msg = NULL;
buf = malloc(assert_size);
if (fread(buf, assert_size, 1, f) == 0)
goto fail_assert;
len = malloc(sizeof (size_t));
if (fread(len, sizeof (size_t), 1, f) == 0)
goto fail_assert;
msg = malloc(*len);
if (fread(buf, *len, 1, f) == 0)
goto fail_assert;
buf->message = msg;
struct event *ev = smalloc(
.size = sizeof (struct event),
.dtor = destroy_event
.dtor = destroy_assert_event
);
*ev = (struct event) { .kind = kind, .data = buf };
return ev;
fail_assert:
free(len);
free(buf);
free(msg);
return NULL;
}
case THEORY_FAIL: {
size_t *len = malloc(sizeof (size_t));

View file

@ -160,8 +160,7 @@ void normal_log_post_all(struct criterion_global_stats *stats) {
void normal_log_assert(struct criterion_assert_stats *stats) {
if (!stats->passed) {
char *dup = strdup(*stats->message ? stats->message
: stats->condition);
char *dup = strdup(*stats->message ? stats->message : "");
#ifdef VANILLA_WIN32
char *line = strtok(dup, "\n");

View file

@ -86,7 +86,7 @@ void tap_log_post_test(struct criterion_test_stats *stats) {
stats->elapsed_time);
for (struct criterion_assert_stats *asrt = stats->asserts; asrt; asrt = asrt->next) {
if (!asrt->passed) {
char *dup = strdup(*asrt->message ? asrt->message : asrt->condition);
char *dup = strdup(*asrt->message ? asrt->message : "");
#ifdef VANILLA_WIN32
char *line = strtok(dup, "\n");
#else