Merge branch 'features/better-asserts' into bleeding

ChangeLog:
+ Added format strings for all assertion macros.
+ Added cr_assert_fail and cr_expect_fail.
+ Added assertions for array lexicographical comparisons.
- Deprecated: cr_abort_test.
- Deprecated: cr_{assert,expect}_strings_*, cr_{assert,expect}_arrays_*
  are now deprecated in favor of cr_{assert,expect}_str_*,
  cr_{assert,expect}_arr_* respectively.
- Breaking: cr_abort_test(NULL) is now invalid.
This commit is contained in:
Snaipe 2015-09-09 01:52:57 +02:00
commit fc3d34c4e2
34 changed files with 943 additions and 379 deletions

View file

@ -98,6 +98,7 @@ set(SOURCE_FILES
src/ordered-set.c
src/posix-compat.c
src/theories.c
src/asprintf.c
src/main.c
src/entry.c
)
@ -123,6 +124,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

96
doc/assert.rst Normal file
View file

@ -0,0 +1,96 @@
.. _assertions-ref:
Assertion reference
===================
This is an exhaustive list of all assertion macros that Criterion provides.
As each ``assert`` macros have an ``expect`` counterpart with the exact same
number of parameters and name suffix, there is no benefit in adding ``expect``
macros to this list. Hence only ``assert`` macros are represented here.
Common Assertions
-----------------
======================================================================= =========================================================================== ===========================================
Macro Passes if and only if Notes
======================================================================= =========================================================================== ===========================================
cr_assert(Condition, [Message, [Args...]]) ``Condition`` is true.
----------------------------------------------------------------------- --------------------------------------------------------------------------- -------------------------------------------
cr_assert_not(Condition, [Message, [Args...]]) ``Condition`` is false.
----------------------------------------------------------------------- --------------------------------------------------------------------------- -------------------------------------------
cr_assert_null(Value, [Message, [Args...]]) ``Value`` is ``NULL``.
----------------------------------------------------------------------- --------------------------------------------------------------------------- -------------------------------------------
cr_assert_not_null(Value, [Message, [Args...]]) ``Value`` is not ``NULL``.
----------------------------------------------------------------------- --------------------------------------------------------------------------- -------------------------------------------
cr_assert_eq(Actual, Expected, [Message, [Args...]]) ``Actual`` is equal to ``Expected``. Compatible with C++ operator overloading
----------------------------------------------------------------------- --------------------------------------------------------------------------- -------------------------------------------
cr_assert_neq(Actual, Unexpected, [Message, [Args...]]) ``Actual`` is not equal to ``Unexpected``. Compatible with C++ operator overloading
----------------------------------------------------------------------- --------------------------------------------------------------------------- -------------------------------------------
cr_assert_lt(Actual, Reference, [Message, [Args...]]) ``Actual`` is less than ``Reference``. Compatible with C++ operator overloading
----------------------------------------------------------------------- --------------------------------------------------------------------------- -------------------------------------------
cr_assert_leq(Actual, Reference, [Message, [Args...]]) ``Actual`` is less or equal to ``Reference``. Compatible with C++ operator overloading
----------------------------------------------------------------------- --------------------------------------------------------------------------- -------------------------------------------
cr_assert_gt(Actual, Reference, [Message, [Args...]]) ``Actual`` is greater than ``Reference``. Compatible with C++ operator overloading
----------------------------------------------------------------------- --------------------------------------------------------------------------- -------------------------------------------
cr_assert_geq(Actual, Reference, [Message, [Args...]]) ``Actual`` is greater or equal to ``Reference``. Compatible with C++ operator overloading
----------------------------------------------------------------------- --------------------------------------------------------------------------- -------------------------------------------
cr_assert_float_eq(Actual, Expected, Epsilon, [Message, [Args...]]) ``Actual`` is equal to ``Expected`` with a tolerance of ``Epsilon``. Use this to test equality between floats
----------------------------------------------------------------------- --------------------------------------------------------------------------- -------------------------------------------
cr_assert_float_neq(Actual, Unexpected, Epsilon, [Message, [Args...]]) ``Actual`` is not equal to ``Unexpected`` with a tolerance of ``Epsilon``. Use this to test inequality between floats
======================================================================= =========================================================================== ===========================================
String Assertions
-----------------
Note: these macros are meant to deal with *native* strings, i.e. char arrays.
Most of them won't work on ``std::string`` in C++, with some exceptions -- for
``std::string``, you should use regular comparison assersions, as listed above.
=========================================================== =================================================================== ===========================================
Macro Passes if and only if Notes
=========================================================== =================================================================== ===========================================
cr_assert_str_empty(Value, [Message, [Args...]]) ``Value`` is an empty string. Also works on std::string
----------------------------------------------------------- ------------------------------------------------------------------- -------------------------------------------
cr_assert_str_not_empty(Value, [Message, [Args...]]) ``Value`` is not an empty string. Also works on std::string
----------------------------------------------------------- ------------------------------------------------------------------- -------------------------------------------
cr_assert_str_eq(Actual, Expected, [Message, [Args...]]) ``Actual`` is lexicographically equal to ``Expected``.
----------------------------------------------------------- ------------------------------------------------------------------- -------------------------------------------
cr_assert_str_neq(Actual, Unexpected, [Message, [Args...]]) ``Actual`` is not lexicographically equal to ``Unexpected``.
----------------------------------------------------------- ------------------------------------------------------------------- -------------------------------------------
cr_assert_str_lt(Actual, Reference, [Message, [Args...]]) ``Actual`` is lexicographically less than ``Reference``.
----------------------------------------------------------- ------------------------------------------------------------------- -------------------------------------------
cr_assert_str_leq(Actual, Reference, [Message, [Args...]]) ``Actual`` is lexicographically less or equal to ``Reference``.
----------------------------------------------------------- ------------------------------------------------------------------- -------------------------------------------
cr_assert_str_gt(Actual, Reference, [Message, [Args...]]) ``Actual`` is lexicographically greater than ``Reference``.
----------------------------------------------------------- ------------------------------------------------------------------- -------------------------------------------
cr_assert_str_geq(Actual, Reference, [Message, [Args...]]) ``Actual`` is lexicographically greater or equal to ``Reference``.
=========================================================== =================================================================== ===========================================
Array Assertions
-----------------
=========================================================================== =========================================================================== ===========================================
Macro Passes if and only if Notes
=========================================================================== =========================================================================== ===========================================
cr_assert_arr_eq(Actual, Expected, [Message, [Args...]]) ``Actual`` is byte-to-byte equal to ``Expected``. This should not be used on struct arrays,
consider using ``cr_assert_arr_eq_cmp``
instead.
--------------------------------------------------------------------------- --------------------------------------------------------------------------- -------------------------------------------
cr_assert_arr_neq(Actual, Unexpected, [Message, [Args...]]) ``Actual`` is not byte-to-byte equal to ``Unexpected``. This should not be used on struct arrays,
consider using ``cr_assert_arr_neq_cmp``
instead.
--------------------------------------------------------------------------- --------------------------------------------------------------------------- -------------------------------------------
cr_assert_arr_eq_cmp(Actual, Expected, Size, Cmp, [Message, [Args...]]) ``Actual`` is comparatively equal to ``Expected`` Only available in C++ and GNU C99
--------------------------------------------------------------------------- --------------------------------------------------------------------------- -------------------------------------------
cr_assert_arr_neq_cmp(Actual, Unexpected, Size, Cmp, [Message, [Args...]]) ``Actual`` is not comparatively equal to ``Expected`` Only available in C++ and GNU C99
--------------------------------------------------------------------------- --------------------------------------------------------------------------- -------------------------------------------
cr_assert_arr_lt_cmp(Actual, Reference, Size, Cmp, [Message, [Args...]]) ``Actual`` is comparatively less than ``Reference`` Only available in C++ and GNU C99
--------------------------------------------------------------------------- --------------------------------------------------------------------------- -------------------------------------------
cr_assert_arr_leq_cmp(Actual, Reference, Size, Cmp, [Message, [Args...]]) ``Actual`` is comparatively less or equal to ``Reference`` Only available in C++ and GNU C99
--------------------------------------------------------------------------- --------------------------------------------------------------------------- -------------------------------------------
cr_assert_arr_gt_cmp(Actual, Reference, Size, Cmp, [Message, [Args...]]) ``Actual`` is comparatively greater than ``Reference`` Only available in C++ and GNU C99
--------------------------------------------------------------------------- --------------------------------------------------------------------------- -------------------------------------------
cr_assert_arr_geq_cmp(Actual, Reference, Size, Cmp, [Message, [Args...]]) ``Actual`` is comparatively greater or equal to ``Reference`` Only available in C++ and GNU C99
=========================================================================== =========================================================================== ===========================================

View file

@ -7,6 +7,7 @@ Criterion
intro
setup
starter
assert
hooks
env
theories

View file

@ -48,45 +48,8 @@ parameter, and an optional failure message:
cr_assert(strlen("") == 0);
}
On top of those, more assertions are available for common operations:
* ``cr_assert_null(Ptr, [Message])``: passes if Ptr is NULL.
* ``cr_assert_eq(Actual, Expected, [Message])``: passes if Actual == Expected.
* ``cr_assert_lt(Actual, Expected, [Message])``: passes if Actual < Expected.
* ``cr_assert_leq(Actual, Expected, [Message])``: passes if Actual <= Expected.
* ``cr_assert_gt(Actual, Expected, [Message])``: passes if Actual > Expected.
* ``cr_assert_geq(Actual, Expected, [Message])``: passes if Actual >= Expected.
* ``cr_assert_float_eq(Actual, Expected, Epsilon, [Message])``:
passes if Actual == Expected with an error of Epsilon.
* ``cr_assert_arrays_eq(Actual, Expected, Size, [Message])``:
passes if all elements of Actual (from 0 to Size - 1) are equals to those
of Expected.
* ``cr_assert_arrays_eq_cmp(Actual, Expected, Size, Cmp, [Message])``:
Same as ``arrays_eq`` but equality is defined by the result of the binary
Cmp function.
Equality and lexical comparison assertions are also available for strings:
* ``cr_assert_strings_eq(Actual, Expected, [Message])``
* ``cr_assert_strings_lt(Actual, Expected, [Message])``
* ``cr_assert_strings_leq(Actual, Expected, [Message])``
* ``cr_assert_strings_gt(Actual, Expected, [Message])``
* ``cr_assert_strings_geq(Actual, Expected, [Message])``
And some assertions have a logical negative counterpart:
* ``cr_assert_not(Condition, [Message])``
* ``cr_assert_not_null(Ptr, [Message])``
* ``cr_assert_neq(Actual, Unexpected, [Message])``
* ``cr_assert_float_neq(Actual, Unexpected, Epsilon, [Message])``
* ``cr_assert_strings_neq(Actual, Unexpected, [Message])``
* ``cr_assert_arrays_neq(Actual, Unexpected, Size, [Message])``
* ``cr_assert_arrays_neq_cmp(Actual, Unexpected, Size, Cmp, [Message])``
Of course, every ``assert`` has an ``expect`` counterpart.
Please note that ``arrays_(n)eq`` assertions should not be used on padded
structures -- please use ``arrays_(n)eq_cmp`` instead.
On top of those, more assertions are available for common operations. See
:ref:`assertions-ref` for a complete list.
Configuring tests
-----------------

View file

@ -29,6 +29,7 @@
CR_BEGIN_C_API
CR_API NORETURN void criterion_abort_test(void);
CR_INLINE static 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 cr_asprintf(char **strp, const char *fmt, ...);
CR_API int cr_vasprintf(char **strp, const char *fmt, va_list ap);
CR_END_C_API
#endif /* !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,274 +57,457 @@ struct criterion_assert_args {
# define CR_GET_CONDITION_STR(Condition, ...) #Condition
# define CR_VA_SKIP(_, ...) __VA_ARGS__
# ifndef __cplusplus
# define CR_ZERO_FILL(Arg) memset(&(Arg), 0, sizeof (Arg))
# else
# define CR_ZERO_FILL(Arg) std::memset(&(Arg), 0, sizeof (Arg))
# endif
# define cr_assert_impl(Kind, ...) \
do { \
struct criterion_assert_args args = { \
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(); \
} while (0)
// Common asserts
# define cr_abort_test(Message) \
do { \
const char *msg = (Message); \
cr_assert(0, msg ? msg : "The conditions for this test were not met.");\
} while (0)
# ifdef __cplusplus
# define CR_SENTINEL 0
# define CR_STDN std::
# else
# define CR_SENTINEL .sentinel_ = 0
# define CR_STDN
# endif
# define cr_assert(...) CR_EXPAND(cr_assert_(__VA_ARGS__, CR_SENTINEL))
# define CR_INIT_STATS_(BufSize, MsgVar, ...) CR_EXPAND( \
do { \
const char *default_msg = "" CR_VA_HEAD(__VA_ARGS__); \
char *formatted_msg = NULL; \
int msglen = cr_asprintf(&formatted_msg, "" CR_VA_TAIL(__VA_ARGS__)); \
MsgVar = formatted_msg && *formatted_msg ? \
formatted_msg : default_msg; \
\
if (!formatted_msg || !*formatted_msg) \
msglen = strlen(default_msg); \
\
BufSize = sizeof(struct criterion_assert_stats) \
+ sizeof (size_t) + msglen + 1; \
\
char *buf = (char*) CR_STDN malloc(BufSize); \
stat = (struct criterion_assert_stats*) buf; \
CR_STDN memset(buf, 0, sizeof (struct criterion_assert_stats)); \
buf += sizeof (struct criterion_assert_stats); \
*((size_t*) buf) = msglen + 1; \
buf += sizeof (size_t); \
CR_STDN strcpy(buf, MsgVar); \
CR_STDN free(formatted_msg); \
} while (0))
# define cr_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__))
# define CR_FAIL_ABORT_ criterion_abort_test
# define CR_FAIL_CONTINUES_ criterion_continue_test
# 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)
// We disable the format-zero-length warning because we use the validity of
// asprintf(out, "") for empty assertion messages
# pragma GCC diagnostic ignored "-Wformat-zero-length"
# endif
# define cr_assert_arrays_eq_cmp_(A, B, Size, Cmp, ...) \
do { \
CRIT_ARR_COMPARE_(A, B, Size, Cmp, equals); \
cr_assert_impl(FATAL, equals, \
__VA_ARGS__); \
# define cr_assert_impl(Fail, Condition, ...) \
do { \
bool passed = !!(Condition); \
\
const char *msg = NULL; \
size_t bufsize; \
\
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)
# 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__); \
// Base assertions
# define cr_fail(Fail, ...) \
CR_EXPAND(cr_assert_impl( \
Fail, \
0, \
dummy, \
"The conditions for this assertion were not met.", \
__VA_ARGS__ \
))
# define cr_assert_fail(...) CR_EXPAND(cr_fail(CR_FAIL_ABORT_, __VA_ARGS__))
# define cr_expect_fail(...) CR_EXPAND(cr_fail(CR_FAIL_CONTINUES_, __VA_ARGS__))
# define cr_assert(...) \
CR_EXPAND(cr_assert_impl( \
CR_FAIL_ABORT_, \
CR_VA_HEAD(__VA_ARGS__), \
dummy, \
"The expression " CR_STR(CR_VA_HEAD(__VA_ARGS__)) " is false.", \
CR_VA_TAIL(__VA_ARGS__) \
))
# define cr_expect(...) \
CR_EXPAND(cr_assert_impl( \
CR_FAIL_CONTINUES_, \
CR_VA_HEAD(__VA_ARGS__), \
dummy, \
"The expression " CR_STR(CR_VA_HEAD(__VA_ARGS__)) " is false.", \
CR_VA_TAIL(__VA_ARGS__) \
))
# define cr_assert_not(...) \
CR_EXPAND(cr_assert_impl( \
CR_FAIL_ABORT_, \
!(CR_VA_HEAD(__VA_ARGS__)), \
dummy, \
"The expression " CR_STR(!(CR_VA_HEAD(__VA_ARGS__))) " is false.", \
CR_VA_TAIL(__VA_ARGS__) \
))
# define cr_expect_not(...) \
CR_EXPAND(cr_assert_impl( \
CR_FAIL_CONTINUES_, \
!(CR_VA_HEAD(__VA_ARGS__)), \
dummy, \
"The expression " CR_STR(!(CR_VA_HEAD(__VA_ARGS__))) " is false.", \
CR_VA_TAIL(__VA_ARGS__) \
))
// Common binary assertions
# define cr_assert_op_(Fail, Op, Actual, Expected, ...) \
CR_EXPAND(cr_assert_impl( \
Fail, \
(Actual) Op (Expected), \
dummy, \
"The expression " CR_STR((Actual) Op (Expected)) " is false.", \
__VA_ARGS__ \
))
# define cr_assert_op_va_(Fail, Op, ...) \
CR_EXPAND(cr_assert_op_( \
Fail, \
Op, \
CR_VA_HEAD(__VA_ARGS__), \
CR_VA_HEAD(CR_VA_TAIL(__VA_ARGS__)), \
CR_VA_TAIL(CR_VA_TAIL(__VA_ARGS__)) \
))
# define cr_assert_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_op_(Fail, Op, Not, Value, ...) \
CR_EXPAND(cr_assert_impl( \
Fail, \
(Value) Op NULL, \
dummy, \
CR_STR(Value) " is" Not " null.", \
__VA_ARGS__ \
))
# define cr_assert_null_op_va_(Fail, Op, Not, ...) \
CR_EXPAND(cr_assert_null_op_( \
Fail, \
Op, \
Not, \
CR_VA_HEAD(__VA_ARGS__), \
CR_VA_TAIL(__VA_ARGS__) \
))
# define cr_assert_null(...) CR_EXPAND(cr_assert_null_op_va_(CR_FAIL_ABORT_, ==, " not", __VA_ARGS__))
# define cr_expect_null(...) CR_EXPAND(cr_assert_null_op_va_(CR_FAIL_CONTINUES_, ==, " not", __VA_ARGS__))
# define cr_assert_not_null(...) CR_EXPAND(cr_assert_null_op_va_(CR_FAIL_ABORT_, !=, "", __VA_ARGS__))
# define cr_expect_not_null(...) CR_EXPAND(cr_assert_null_op_va_(CR_FAIL_CONTINUES_, !=, "", __VA_ARGS__))
// Floating-point assertions
# 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, \
"The expression " CR_STR(Op(Actual, Expected, Epsilon)) " is false.", \
__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_empty_(Fail, Op, Not, Value, ...) \
CR_EXPAND(cr_assert_impl( \
Fail, \
(Value)[0] Op '\0', \
dummy, \
CR_STR(Value) " is" Not " empty.", \
__VA_ARGS__ \
))
# define cr_assert_str_op_empty_va_(Fail, Op, Not, ...) \
CR_EXPAND(cr_assert_str_op_empty_( \
Fail, \
Op, \
Not, \
CR_VA_HEAD(__VA_ARGS__), \
CR_VA_TAIL(__VA_ARGS__) \
))
# define cr_assert_str_empty(...) CR_EXPAND(cr_assert_str_op_empty_va_(CR_FAIL_ABORT_, ==, " not", __VA_ARGS__))
# define cr_expect_str_empty(...) CR_EXPAND(cr_assert_str_op_empty_va_(CR_FAIL_CONTINUES_, ==, " not", __VA_ARGS__))
# define cr_assert_str_not_empty(...) CR_EXPAND(cr_assert_str_op_empty_va_(CR_FAIL_ABORT_, !=, "", __VA_ARGS__))
# define cr_expect_str_not_empty(...) CR_EXPAND(cr_assert_str_op_empty_va_(CR_FAIL_CONTINUES_, !=, "", __VA_ARGS__))
# define cr_assert_str_op_(Fail, Op, Actual, Expected, ...) \
CR_EXPAND(cr_assert_impl( \
Fail, \
CR_STDN strcmp((Actual), (Expected)) Op 0, \
dummy, \
"The expression (as strings) " \
CR_STR((Actual) Op (Expected)) " is false", \
__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, \
"The expression " \
CR_STR((Actual)[0 .. Size] Op (Expected)[0 .. Size]) \
"is false.", \
__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, \
"The expression " \
CR_STR((Actual)[0 .. Size] Op (Expected)[0 .. Size]) \
" is false.", \
__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_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_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_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_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_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_arrays_neq_cmp(...) \
cr_assert_arrays_eq_cmp_(__VA_ARGS__, CR_SENTINEL)
# define cr_expect_arrays_neq_cmp(...) \
cr_expect_arrays_eq_cmp_(__VA_ARGS__, CR_SENTINEL)
# endif /* !__GNUC__ */
# define cr_assert_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 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
# 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 const &) { \
} 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 const &) { CR_EXPAND(cr_fail(Fail, CR_VA_TAIL(__VA_ARGS__))); }
# define cr_assert_no_throw_va_(...) \
CR_EXPAND(cr_assert_no_throw_( \
CR_VA_HEAD(__VA_ARGS__), \
CR_VA_HEAD(CR_VA_TAIL(__VA_ARGS__)), \
CR_VA_HEAD(CR_VA_TAIL(CR_VA_TAIL(__VA_ARGS__))), \
dummy, \
CR_VA_TAIL(CR_VA_TAIL(CR_VA_TAIL(__VA_ARGS__))) \
))
# define cr_assert_no_throw(...) 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__( \
message \
"The `" #Name "` macro is deprecated, " \
"please use `cr_" #Name "` instead." \
# define CRITERION_ASSERT_DEPRECATED_(Name) CRITERION_ASSERT_DEPRECATED__( \
message \
("The `" #Name "` macro is deprecated, " \
"please use `cr_" #Name "` instead.") \
)
# define CRITERION_ASSERT_DEPRECATED_B(Name, Newname) \
CRITERION_ASSERT_DEPRECATED__( \
message \
("The `" #Name "` macro is deprecated, " \
"please use `" #Newname "` instead.") \
)
# ifdef _MSC_VER
# define CRITERION_ASSERT_DEPRECATED__(Msg) \
__pragma(Msg)
# else
# define CRITERION_ASSERT_DEPRECATED__(Msg) \
_Pragma(#Msg)
# endif
# ifndef assert
# define assert(...) CRITERION_ASSERT_DEPRECATED_(assert) cr_assert(__VA_ARGS__)
@ -339,6 +519,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

@ -26,17 +26,13 @@
# ifdef __cplusplus
# include <cstddef>
# include <cstdio>
# else
# include <stddef.h>
# include <stdio.h>
# endif
# include "common.h"
CR_BEGIN_C_API
extern FILE *g_event_pipe;
CR_API void send_event(int kind, void *data, size_t size);
CR_END_C_API

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

@ -46,23 +46,27 @@ if (HAVE_PCRE)
set(SCRIPTS ${SCRIPTS} pattern)
endif ()
foreach(sample ${SAMPLES})
add_executable(${sample}.bin ${sample})
target_link_libraries(${sample}.bin criterion)
add_test(${sample} ${sample}.bin)
set_property(TEST ${sample} PROPERTY
ENVIRONMENT "CRITERION_ALWAYS_SUCCEED=1"
)
if (NOT MSVC) # we disable the scripted tests when building with MSVC
add_test(${sample}_compare sh ${CMAKE_CURRENT_LIST_DIR}/tests/run_test.sh "${CMAKE_CURRENT_LIST_DIR}" . . ${sample}.bin)
set_property(TEST ${sample}_compare PROPERTY
ENVIRONMENT "LC_ALL=en_US.utf8"
macro(add_samples DIR_ SAMPLES_)
foreach(sample ${SAMPLES_})
add_executable(${sample}.bin ${sample})
target_link_libraries(${sample}.bin criterion)
add_test(${sample} ${sample}.bin)
set_property(TEST ${sample} PROPERTY
ENVIRONMENT "CRITERION_ALWAYS_SUCCEED=1"
ENVIRONMENT "CRITERION_SHORT_FILENAME=1"
)
endif ()
endforeach()
if (NOT MSVC) # we disable the scripted tests when building with MSVC
add_test(${sample}_compare sh ${DIR_}/run_test.sh "${CMAKE_CURRENT_LIST_DIR}" . . ${sample}.bin)
set_property(TEST ${sample}_compare PROPERTY
ENVIRONMENT "LC_ALL=en_US.utf8"
ENVIRONMENT "CRITERION_ALWAYS_SUCCEED=1"
ENVIRONMENT "CRITERION_SHORT_FILENAME=1"
)
endif ()
endforeach()
endmacro()
add_samples("${CMAKE_CURRENT_LIST_DIR}/tests" "${SAMPLES}")
if (NOT MSVC) # we disable the scripted tests when building with MSVC
@ -81,3 +85,5 @@ foreach(script ${SCRIPTS})
endforeach()
endif()
add_subdirectory(tests)

View file

@ -6,29 +6,32 @@ Test(asserts, base) {
cr_assert(true, "Assertions may take failure messages");
cr_assert(true, "Or even %d format string %s", 1, "with parameters");
cr_expect(false, "assert is fatal, expect isn't");
cr_assert(false, "This assert runs");
cr_assert(false, "This does not");
}
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_empty("");
cr_assert_str_not_empty("foo");
cr_assert_strings_gt("hello", "hell");
cr_assert_strings_geq("hello", "hell");
cr_assert_strings_geq("hello", "hello");
cr_assert_str_eq("hello", "hello");
cr_assert_str_neq("hello", "olleh");
cr_assert_strings_lt("hell", "hello");
cr_assert_strings_leq("hell", "hello");
cr_assert_strings_leq("hello", "hello");
cr_assert_str_gt("hello", "hell");
cr_assert_str_geq("hello", "hell");
cr_assert_str_geq("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 +65,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 +77,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

@ -1,6 +1,7 @@
[----] asserts.c:9: Assertion failed: assert is fatal, expect isn't
[----] asserts.c:10: Assertion failed: This assert runs
[----] asserts.c:11: Assertion failed: assert is fatal, expect isn't
[----] asserts.c:12: Assertion failed: This assert runs
[FAIL] asserts::base: (0.00s)
[----] asserts.c:18: Assertion failed: The conditions for this test were not met.
[----] asserts.c:17: Assertion failed: You can fail an assertion with a message from anywhere
[----] asserts.c:18: Assertion failed: The conditions for this assertion were not met.
[FAIL] asserts::old_school: (0.00s)
[====] Synthesis: Tested: 6 | Passing: 4 | Failing: 2 | Crashing: 0 

View file

@ -8,29 +8,32 @@ Test(asserts, base) {
cr_assert(true, "Assertions may take failure messages");
cr_assert(true, "Or even %d format string %s", 1, "with parameters");
cr_expect(false, "assert is fatal, expect isn't");
cr_assert(false, "This assert runs");
cr_assert(false, "This does not");
}
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_empty("");
cr_assert_str_not_empty("foo");
cr_assert_strings_gt("hello", "hell");
cr_assert_strings_geq("hello", "hell");
cr_assert_strings_geq("hello", "hello");
cr_assert_str_eq("hello", "hello");
cr_assert_str_neq("hello", "olleh");
cr_assert_strings_lt("hell", "hello");
cr_assert_strings_leq("hell", "hello");
cr_assert_strings_leq("hello", "hello");
cr_assert_str_gt("hello", "hell");
cr_assert_str_geq("hello", "hell");
cr_assert_str_geq("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 +67,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 +79,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

@ -1,8 +1,11 @@
[----] asserts.cc:11: Assertion failed: assert is fatal, expect isn't
[----] asserts.cc:12: Assertion failed: This assert runs
[----] asserts.cc:83: Assertion failed: The expression (&s1)[0 .. 2] == (&s2)[0 .. 2] is false.
[FAIL] asserts::array: (0.00s)
[----] asserts.cc:13: Assertion failed: assert is fatal, expect isn't
[----] asserts.cc:14: Assertion failed: This assert runs
[FAIL] asserts::base: (0.00s)
[----] asserts.cc:86: Assertion failed: 0
[----] asserts.cc:89: Assertion failed: The conditions for this assertion were not met.
[FAIL] asserts::exception: (0.00s)
[----] asserts.cc:20: Assertion failed: The conditions for this test were not met.
[----] asserts.cc:19: Assertion failed: You can fail an assertion with a message from anywhere
[----] asserts.cc:20: Assertion failed: The conditions for this assertion were not met.
[FAIL] asserts::old_school: (0.00s)
[====] Synthesis: Tested: 7 | Passing: 4 | Failing: 3 | Crashing: 0 
[====] Synthesis: Tested: 7 | Passing: 3 | Failing: 4 | Crashing: 0 

View file

@ -1,3 +1,3 @@
[----] description.c:4: Assertion failed: 0
[----] description.c:4: Assertion failed: The expression 0 is false.
[FAIL] misc::failing: (0.00s)
[====] Synthesis: Tested: 1 | Passing: 0 | Failing: 1 | Crashing: 0 

View file

@ -1,3 +1,3 @@
[----] description.cc:4: Assertion failed: 0
[----] description.cc:4: Assertion failed: The expression 0 is false.
[FAIL] misc::failing: (0.00s)
[====] Synthesis: Tested: 1 | Passing: 0 | Failing: 1 | Crashing: 0 

View file

@ -1,3 +1,3 @@
[----] report.c:5: Assertion failed: 0
[----] report.c:5: Assertion failed: The expression 0 is false.
[FAIL] sample::test: (0.00s)
[====] Synthesis: Tested: 1 | Passing: 0 | Failing: 1 | Crashing: 0 

View file

@ -1,3 +1,3 @@
[----] report.cc:5: Assertion failed: 0
[----] report.cc:5: Assertion failed: The expression 0 is false.
[FAIL] sample::test: (0.00s)
[====] Synthesis: Tested: 1 | Passing: 0 | Failing: 1 | Crashing: 0 

View file

@ -1,3 +1,3 @@
[----] simple.c:4: Assertion failed: 0
[----] simple.c:4: Assertion failed: The expression 0 is false.
[FAIL] misc::failing: (0.00s)
[====] Synthesis: Tested: 2 | Passing: 1 | Failing: 1 | Crashing: 0 

View file

@ -1,3 +1,3 @@
[----] simple.cc:4: Assertion failed: 0
[----] simple.cc:4: Assertion failed: The expression 0 is false.
[FAIL] misc::failing: (0.00s)
[====] Synthesis: Tested: 2 | Passing: 1 | Failing: 1 | Crashing: 0 

View file

@ -0,0 +1,5 @@
set(SAMPLES
failmessages.c
)
add_samples("${CMAKE_CURRENT_LIST_DIR}" "${SAMPLES}")

View file

@ -0,0 +1,49 @@
#include <criterion/criterion.h>
Test(messages, default) {
cr_expect(0);
cr_expect_eq(0, 1);
cr_expect_neq(1, 1);
cr_expect_lt(2, 1);
cr_expect_leq(2, 1);
cr_expect_gt(1, 2);
cr_expect_geq(1, 2);
cr_expect_null("");
cr_expect_not_null(NULL);
cr_expect_float_eq(1, 2, 0.1);
cr_expect_float_neq(2, 2, 0.1);
cr_expect_str_empty("foo");
cr_expect_str_not_empty("");
cr_expect_str_eq("abc", "abd");
cr_expect_str_neq("abc", "abc");
cr_expect_str_lt("abc", "aba");
cr_expect_str_leq("abc", "aba");
cr_expect_str_gt("abc", "abd");
cr_expect_str_geq("abc", "abd");
}
Test(messages, user) {
cr_expect(0, "foo %s", "bar");
cr_expect_eq(0, 1, "foo %s", "bar");
cr_expect_neq(1, 1, "foo %s", "bar");
cr_expect_lt(2, 1, "foo %s", "bar");
cr_expect_leq(2, 1, "foo %s", "bar");
cr_expect_gt(1, 2, "foo %s", "bar");
cr_expect_geq(1, 2, "foo %s", "bar");
cr_expect_null("", "foo %s", "bar");
cr_expect_not_null(NULL, "foo %s", "bar");
cr_expect_float_eq(1, 2, 0.1, "foo %s", "bar");
cr_expect_float_neq(2, 2, 0.1, "foo %s", "bar");
cr_expect_str_empty("foo", "foo %s", "bar");
cr_expect_str_not_empty("", "foo %s", "bar");
cr_expect_str_eq("abc", "abd", "foo %s", "bar");
cr_expect_str_neq("abc", "abc", "foo %s", "bar");
cr_expect_str_lt("abc", "aba", "foo %s", "bar");
cr_expect_str_leq("abc", "aba", "foo %s", "bar");
cr_expect_str_gt("abc", "abd", "foo %s", "bar");
cr_expect_str_geq("abc", "abd", "foo %s", "bar");
}

View file

@ -0,0 +1,41 @@
[----] failmessages.c:4: Assertion failed: The expression 0 is false.
[----] failmessages.c:5: Assertion failed: The expression (0) == (1) is false.
[----] failmessages.c:6: Assertion failed: The expression (1) != (1) is false.
[----] failmessages.c:7: Assertion failed: The expression (2) < (1) is false.
[----] failmessages.c:8: Assertion failed: The expression (2) <= (1) is false.
[----] failmessages.c:9: Assertion failed: The expression (1) > (2) is false.
[----] failmessages.c:10: Assertion failed: The expression (1) >= (2) is false.
[----] failmessages.c:11: Assertion failed: "" is not null.
[----] failmessages.c:12: Assertion failed: ((void *)0) is null.
[----] failmessages.c:14: Assertion failed: The expression (2) - (1) <= (0.1) && (1) - (2) <= (0.1) is false.
[----] failmessages.c:15: Assertion failed: The expression (2) - (2) > (0.1) || (2) - (2) > (0.1) is false.
[----] failmessages.c:17: Assertion failed: "foo" is not empty.
[----] failmessages.c:18: Assertion failed: "" is empty.
[----] failmessages.c:19: Assertion failed: The expression (as strings) ("abc") == ("abd") is false
[----] failmessages.c:20: Assertion failed: The expression (as strings) ("abc") != ("abc") is false
[----] failmessages.c:21: Assertion failed: The expression (as strings) ("abc") < ("aba") is false
[----] failmessages.c:22: Assertion failed: The expression (as strings) ("abc") <= ("aba") is false
[----] failmessages.c:23: Assertion failed: The expression (as strings) ("abc") > ("abd") is false
[----] failmessages.c:24: Assertion failed: The expression (as strings) ("abc") >= ("abd") is false
[FAIL] messages::default: (0.00s)
[----] failmessages.c:28: Assertion failed: foo bar
[----] failmessages.c:29: Assertion failed: foo bar
[----] failmessages.c:30: Assertion failed: foo bar
[----] failmessages.c:31: Assertion failed: foo bar
[----] failmessages.c:32: Assertion failed: foo bar
[----] failmessages.c:33: Assertion failed: foo bar
[----] failmessages.c:34: Assertion failed: foo bar
[----] failmessages.c:35: Assertion failed: foo bar
[----] failmessages.c:36: Assertion failed: foo bar
[----] failmessages.c:38: Assertion failed: foo bar
[----] failmessages.c:39: Assertion failed: foo bar
[----] failmessages.c:41: Assertion failed: foo bar
[----] failmessages.c:42: Assertion failed: foo bar
[----] failmessages.c:43: Assertion failed: foo bar
[----] failmessages.c:44: Assertion failed: foo bar
[----] failmessages.c:45: Assertion failed: foo bar
[----] failmessages.c:46: Assertion failed: foo bar
[----] failmessages.c:47: Assertion failed: foo bar
[----] failmessages.c:48: Assertion failed: foo bar
[FAIL] messages::user: (0.00s)
[====] Synthesis: Tested: 2 | Passing: 0 | Failing: 2 | Crashing: 0 

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
}

63
src/asprintf.c Normal file
View file

@ -0,0 +1,63 @@
/*
* 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 <stdio.h>
#include "criterion/asprintf-compat.h"
int cr_asprintf(char **strp, const char *fmt, ...) {
va_list ap;
va_start(ap, fmt);
int res = cr_vasprintf(strp, fmt, ap);
va_end(ap);
return res;
}
int cr_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->data)->message);
free(ev->data);
}
struct event *read_event(FILE *f) {
unsigned kind;
if (fread(&kind, sizeof (unsigned), 1, f) == 0)
@ -45,33 +51,45 @@ 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;
char *msg = NULL;
buf = malloc(assert_size);
if (fread(buf, assert_size, 1, f) == 0)
goto fail_assert;
size_t len = 0;
if (fread(&len, sizeof (size_t), 1, f) == 0)
goto fail_assert;
msg = malloc(len);
if (fread(msg, 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(buf);
free(msg);
return NULL;
}
case THEORY_FAIL: {
size_t *len = malloc(sizeof (size_t));
if (fread(len, sizeof (size_t), 1, f) == 0) {
free(len);
size_t len = 0;
if (fread(&len, sizeof (size_t), 1, f) == 0)
return NULL;
}
char *buf = malloc(*len);
if (fread(buf, *len, 1, f) == 0) {
free(len);
char *buf = malloc(len);
if (fread(buf, len, 1, f) == 0) {
free(buf);
return NULL;
}
free(len);
struct event *ev = smalloc(
.size = sizeof (struct event),

View file

@ -25,6 +25,9 @@
# define EVENT_H_
# include "criterion/event.h"
# include <stdio.h>
extern FILE *g_event_pipe;
struct event {
int kind;

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

View file

@ -23,6 +23,7 @@
*/
#include <stdbool.h>
#include <stdarg.h>
#include <stdio.h>
#include <setjmp.h>
#include <dyncall.h>
#include <assert.h>