[v1.0.0] Merge branch 'bleeding'
This commit is contained in:
commit
0285d32ce1
25 changed files with 402 additions and 146 deletions
|
@ -12,4 +12,4 @@ script:
|
|||
after_success:
|
||||
- coveralls --gcov gcov-4.9 --exclude samples --exclude dependencies --gcov-options '\-lp' -b .
|
||||
after_failure:
|
||||
- cat $(find check -iname '*.log') /dev/null
|
||||
- cat $(find samples -iname '*.log') /dev/null
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
2015-03-18 Franklin "Snaipe" Mathieu <franklinmathieu@gmail.com>
|
||||
* src/timer.*: Added test timings
|
||||
* src/, include/: Changed assert prototypes
|
||||
* include/: ANSI compliance over header files
|
||||
* *: Windows + FreeBSD compatibility
|
||||
|
||||
2015-03-11 Franklin "Snaipe" Mathieu <franklinmathieu@gmail.com>
|
||||
|
||||
* include/criterion/logging.h, src/logging.c: A logging interface
|
||||
|
|
|
@ -45,4 +45,6 @@ libcriterion_la_SOURCES = \
|
|||
src/stats.h \
|
||||
src/logging.c \
|
||||
src/options.c \
|
||||
src/timer.c \
|
||||
src/timer.h \
|
||||
src/main.c
|
||||
|
|
18
README.md
18
README.md
|
@ -7,7 +7,7 @@ Criterion
|
|||
[](https://github.com/Snaipe/Criterion/blob/master/LICENSE)
|
||||
[](https://github.com/Snaipe/Criterion/releases)
|
||||
|
||||
A dead-simple, yet extensible, C test framework.
|
||||
A dead-simple, yet extensible, C unit testing framework.
|
||||
|
||||

|
||||
|
||||
|
@ -30,13 +30,14 @@ the user would have with other frameworks:
|
|||
reported and tested.
|
||||
* [x] Progress and statistics can be followed in real time with report hooks.
|
||||
* [x] TAP output format can be enabled with an option.
|
||||
* [x] Runs on Linux, Mac OS X, and Windows (compiles only with Cygwin for the moment).
|
||||
* [x] Runs on Linux, FreeBSD, Mac OS X, and Windows (compiles only with Cygwin for the moment).
|
||||
|
||||
## Downloads
|
||||
|
||||
* [Linux (x86_64)](https://github.com/Snaipe/Criterion/releases/download/v0.3/criterion-0.3-linux-x86_64.tar.bz2)
|
||||
* [OS X (x86_64)](https://github.com/Snaipe/Criterion/releases/download/v0.3/criterion-0.3-osx-x86_64.tar.bz2)
|
||||
* [Windows (x86_64)](https://github.com/Snaipe/Criterion/releases/download/v0.3/criterion-0.3-win-x86_64.tar.bz2)
|
||||
* [Linux (x86_64)](https://github.com/Snaipe/Criterion/releases/download/v1.0.0/criterion-1.0.0-linux-x86_64.tar.bz2)
|
||||
* [OS X (x86_64)](https://github.com/Snaipe/Criterion/releases/download/v1.0.0/criterion-1.0.0-osx-x86_64.tar.bz2)
|
||||
* [Windows (x86_64)](https://github.com/Snaipe/Criterion/releases/download/v1.0.0/criterion-1.0.0-win-x86_64.tar.bz2)
|
||||
* [FreeBSD (x86_64)](https://github.com/Snaipe/Criterion/releases/download/v1.0.0/criterion-1.0.0-freebsd-x86_64.tar.bz2)
|
||||
|
||||
If you have a different platform, you can still [build the library from source](http://criterion.readthedocs.org/en/latest/setup.html#installation)
|
||||
|
||||
|
@ -51,6 +52,7 @@ Sample tests can be found in the [sample directory][samples].
|
|||
|
||||
* [A simple test][sample-simple]
|
||||
* [Using multiple suites][sample-suites]
|
||||
* [Writing assertions][sample-asserts]
|
||||
* [Adding test fixtures][sample-fixtures]
|
||||
* [Tests with signals][sample-signal]
|
||||
* [Using report hooks][sample-report]
|
||||
|
@ -68,9 +70,8 @@ A. I worked with CUnit and Check, and I must say that they do their job
|
|||
|
||||
**Q. Where has this been tested?**
|
||||
A. Currently, on Linux 2.6.32 and Linux 3.15.7, although it should work on
|
||||
most \*nix systems; Mac OS X Yosemite 10.10, and finally Windows 7 (with
|
||||
the Cygwin port of GCC).
|
||||
More tests will be added on the build matrix.
|
||||
most \*nix systems; Mac OS X Yosemite 10.10, FreeBSD 10.0, and finally
|
||||
Windows 7 (with the Cygwin port of GCC).
|
||||
|
||||
**Q. Can I use it on Windows without Cygwin?**
|
||||
A. Yes, you can, Cygwin is only required to compile the static library if
|
||||
|
@ -85,6 +86,7 @@ A. Yes, you can, Cygwin is only required to compile the static library if
|
|||
[samples]: ./samples/
|
||||
[sample-simple]: ./samples/simple.c
|
||||
[sample-suites]: ./samples/suites.c
|
||||
[sample-asserts]: ./samples/asserts.c
|
||||
[sample-fixtures]: ./samples/fixtures.c
|
||||
[sample-signal]: ./samples/signal.c
|
||||
[sample-report]: ./samples/report.c
|
||||
|
|
70
appveyor.yml
Normal file
70
appveyor.yml
Normal file
|
@ -0,0 +1,70 @@
|
|||
version: 1.0.0_b{build}-{branch}
|
||||
|
||||
os: Windows Server 2012
|
||||
|
||||
init:
|
||||
- ps: (New-Object System.Net.WebClient).DownloadFile("https://cygwin.com/setup-x86.exe", "c:\setup-x86.exe")
|
||||
- git config --global core.autocrlf input
|
||||
- c:\setup-x86.exe -qnNdO -R %CYG_ROOT% -s %CYG_MIRROR% -l %CYG_CACHE% \
|
||||
-P autoconf \
|
||||
-P automake \
|
||||
-P gcc-core \
|
||||
-P mingw-runtime \
|
||||
-P mingw-binutils \
|
||||
-P mingw-gcc-core \
|
||||
-P mingw-pthreads \
|
||||
-P mingw-w32api \
|
||||
-P libtool \
|
||||
-P make \
|
||||
-P python \
|
||||
-P gettext-devel \
|
||||
-P gettext \
|
||||
-P expat \
|
||||
-P intltool \
|
||||
-P libiconv \
|
||||
-P pkg-config \
|
||||
-P check \
|
||||
-P git \
|
||||
-P wget \
|
||||
-P curl
|
||||
- "%CYG_BASH% -lc 'echo $PATH'"
|
||||
|
||||
environment:
|
||||
global:
|
||||
CYG_ROOT: C:\cygwin
|
||||
CYG_MIRROR: http://cygwin.mirror.constant.com
|
||||
CYG_CACHE: C:\cygwin\var\cache\setup
|
||||
CYG_BASH: C:\cygwin\bin\bash
|
||||
|
||||
cache:
|
||||
- '%CYG_CACHE%'
|
||||
|
||||
clone_depth: 5
|
||||
|
||||
matrix:
|
||||
fast_finish: true # set this flag to immediately finish build once one of the jobs fails.
|
||||
|
||||
platform:
|
||||
- x86
|
||||
- Any CPU
|
||||
|
||||
configuration: Release
|
||||
|
||||
install:
|
||||
- "%CYG_BASH% -lc 'cd $APPVEYOR_BUILD_FOLDER; ./autogen.sh'"
|
||||
- '%CYG_BASH% -lc "cd $APPVEYOR_BUILD_FOLDER; exec 0</dev/null; ./configure"'
|
||||
|
||||
build_script:
|
||||
- '%CYG_BASH% -lc "cd $APPVEYOR_BUILD_FOLDER; exec 0</dev/null; make"'
|
||||
|
||||
test_script:
|
||||
- '%CYG_BASH% -lc "cd $APPVEYOR_BUILD_FOLDER; exec 0</dev/null; make check"'
|
||||
|
||||
after_test:
|
||||
- '%CYG_BASH% -lc "cat $(find $APPVEYOR_BUILD_FOLDER/samples -iname \"*.log\") /dev/null'
|
||||
|
||||
notifications:
|
||||
|
||||
- provider: Email
|
||||
to: [franklinmathieu@gmail.com]
|
||||
on_build_status_changed: true
|
|
@ -1,6 +1,6 @@
|
|||
AC_PREREQ([2.60])
|
||||
|
||||
AC_INIT([criterion], [1.0], [], [criterion], [franklinmathieu@gmail.com])
|
||||
AC_INIT([criterion], [1.0.0], [], [criterion], [franklinmathieu@gmail.com])
|
||||
AC_CONFIG_SRCDIR([src/runner.c])
|
||||
|
||||
LT_PREREQ([2.2.4])
|
||||
|
|
2
dependencies/csptr
vendored
2
dependencies/csptr
vendored
|
@ -1 +1 @@
|
|||
Subproject commit 30b3380a9aee3c49a2206d2cced12a6adf26469b
|
||||
Subproject commit 3b6b26f8b3464a70cc76628e4b65b776a7760ba4
|
|
@ -51,22 +51,22 @@ parameter, and an optional failure message:
|
|||
On top of those, more assertions are available for common operations:
|
||||
|
||||
* ``{assert,expect}_not(Actual, Expected, [Message])``
|
||||
* ``{assert,expect}_equal(Actual, Expected, [Message])``
|
||||
* ``{assert,expect}_not_equal(Actual, Unexpected, [Message])``
|
||||
* ``{assert,expect}_eq(Actual, Expected, [Message])``
|
||||
* ``{assert,expect}_neq(Actual, Unexpected, [Message])``
|
||||
* ``{assert,expect}_lt(Actual, Expected, [Message])``
|
||||
* ``{assert,expect}_leq(Actual, Expected, [Message])``
|
||||
* ``{assert,expect}_gt(Actual, Expected, [Message])``
|
||||
* ``{assert,expect}_geq(Actual, Expected, [Message])``
|
||||
* ``{assert,expect}_float_equal(Actual, Expected, Epsilon, [Message])``
|
||||
* ``{assert,expect}_float_not_equal(Actual, Unexpected, Epsilon, [Message])``
|
||||
* ``{assert,expect}_strings_equal(Actual, Expected, [Message])``
|
||||
* ``{assert,expect}_strings_not_equal(Actual, Unexpected, [Message])``
|
||||
* ``{assert,expect}_float_eq(Actual, Expected, Epsilon, [Message])``
|
||||
* ``{assert,expect}_float_neq(Actual, Unexpected, Epsilon, [Message])``
|
||||
* ``{assert,expect}_strings_eq(Actual, Expected, [Message])``
|
||||
* ``{assert,expect}_strings_neq(Actual, Unexpected, [Message])``
|
||||
* ``{assert,expect}_strings_lt(Actual, Expected, [Message])``
|
||||
* ``{assert,expect}_strings_leq(Actual, Expected, [Message])``
|
||||
* ``{assert,expect}_strings_gt(Actual, Expected, [Message])``
|
||||
* ``{assert,expect}_strings_geq(Actual, Expected, [Message])``
|
||||
* ``{assert,expect}_arrays_equal(Actual, Expected, Size, [Message])``
|
||||
* ``{assert,expect}_arrays_not_equal(Actual, Unexpected, Size, [Message])``
|
||||
* ``{assert,expect}_arrays_eq(Actual, Expected, Size, [Message])``
|
||||
* ``{assert,expect}_arrays_neq(Actual, Unexpected, Size, [Message])``
|
||||
|
||||
Fixtures
|
||||
--------
|
||||
|
|
|
@ -37,13 +37,23 @@ enum criterion_assert_kind {
|
|||
FATAL
|
||||
};
|
||||
|
||||
# define assert_impl(Kind, Condition, ...) \
|
||||
struct criterion_assert_args {
|
||||
const char *msg;
|
||||
const char *default_msg;
|
||||
int sentinel_;
|
||||
};
|
||||
|
||||
# define assert_impl(Kind, Condition, ...) \
|
||||
do { \
|
||||
struct criterion_assert_args args = { \
|
||||
__VA_ARGS__ \
|
||||
}; \
|
||||
int passed = !!(Condition); \
|
||||
struct criterion_assert_stats stat = { \
|
||||
.kind = (Kind), \
|
||||
.condition = #Condition, \
|
||||
.message = "" __VA_ARGS__, \
|
||||
.message = args.msg ? args.msg \
|
||||
: (args.default_msg ? args.default_msg : ""), \
|
||||
.passed = passed, \
|
||||
.file = __FILE__, \
|
||||
.line = __LINE__, \
|
||||
|
@ -55,108 +65,130 @@ enum criterion_assert_kind {
|
|||
|
||||
// Common asserts
|
||||
|
||||
# define assert(Condition, ...) assert_impl(FATAL, Condition, "" __VA_ARGS__)
|
||||
# define expect(Condition, ...) assert_impl(NORMAL, Condition, "" __VA_ARGS__)
|
||||
# define abort_test(Message) \
|
||||
assert(0, \
|
||||
.default_msg = "The conditions for this test were not met.", \
|
||||
.msg = (Message) \
|
||||
)
|
||||
|
||||
# define assert_not(Condition, ...) assert(!(Condition), "" __VA_ARGS__)
|
||||
# define expect_not(Condition, ...) expect(!(Condition), "" __VA_ARGS__)
|
||||
# define assert(...) assert_(__VA_ARGS__, .sentinel_ = 0)
|
||||
# define expect(...) expect_(__VA_ARGS__, .sentinel_ = 0)
|
||||
|
||||
# define assert_(Condition, ...) assert_impl(FATAL, Condition, __VA_ARGS__)
|
||||
# define expect_(Condition, ...) assert_impl(NORMAL, Condition, __VA_ARGS__)
|
||||
|
||||
# define assert_not(...) assert_not_(__VA_ARGS__, .sentinel_ = 0)
|
||||
# define expect_not(...) expect_not_(__VA_ARGS__, .sentinel_ = 0)
|
||||
|
||||
# define assert_not_(Condition, ...) \
|
||||
assert_impl(FATAL, !(Condition), __VA_ARGS__)
|
||||
# define expect_not_(Condition, ...) \
|
||||
expect_impl(NORMAL, !(Condition), __VA_ARGS__)
|
||||
|
||||
// Native asserts
|
||||
|
||||
# define assert_op(Actual, Expected, Op, ...) \
|
||||
assert((Actual) Op (Expected), "" __VA_ARGS__)
|
||||
# define expect_op(Actual, Expected, Op, ...) \
|
||||
expect((Actual) Op (Expected), "" __VA_ARGS__)
|
||||
# define assert_op_(Op, Actual, Expected, ...) \
|
||||
assert_impl(FATAL, (Actual) Op (Expected), __VA_ARGS__)
|
||||
# define expect_op_(Op, Actual, Expected, ...) \
|
||||
assert_impl(NORMAL, (Actual) Op (Expected), __VA_ARGS__)
|
||||
|
||||
# define assert_equal(Actual, Expected, ...) \
|
||||
assert_op(Actual, Expected, ==, "" __VA_ARGS__)
|
||||
# define expect_equal(Actual, Expected, ...) \
|
||||
expect_op(Actual, Expected, ==, "" __VA_ARGS__)
|
||||
# define assert_eq(...) assert_op_(==, __VA_ARGS__, .sentinel_ = 0)
|
||||
# define expect_eq(...) expect_op_(==, __VA_ARGS__, .sentinel_ = 0)
|
||||
|
||||
# define assert_not_equal(Actual, Expected, ...) \
|
||||
assert_op(Actual, Expected, !=, "" __VA_ARGS__)
|
||||
# define expectNotEqual(Actual, Expected, ...) \
|
||||
expect_op(Actual, Expected, !=, "" __VA_ARGS__)
|
||||
# define assert_neq(...) assert_op_(!=, __VA_ARGS__, .sentinel_ = 0)
|
||||
# define expect_neq(...) expect_op_(!=, __VA_ARGS__, .sentinel_ = 0)
|
||||
|
||||
# define assert_lt(Actual, Expected, ...) \
|
||||
assert_op(Actual, Expected, <, "" __VA_ARGS__)
|
||||
# define expect_lt(Actual, Expected, ...) \
|
||||
expect_op(Actual, Expected, <, "" __VA_ARGS__)
|
||||
# define assert_lt(...) assert_op_(<, __VA_ARGS__, .sentinel_ = 0)
|
||||
# define expect_lt(...) expect_op_(<, __VA_ARGS__, .sentinel_ = 0)
|
||||
|
||||
# define assert_gt(Actual, Expected, ...) \
|
||||
assert_op(Actual, Expected, >, "" __VA_ARGS__)
|
||||
# define expect_gt(Actual, Expected, ...) \
|
||||
expect_op(Actual, Expected, >, "" __VA_ARGS__)
|
||||
# define assert_gt(...) assert_op_(>, __VA_ARGS__, .sentinel_ = 0)
|
||||
# define expect_gt(...) expect_op_(>, __VA_ARGS__, .sentinel_ = 0)
|
||||
|
||||
# define assert_leq(Actual, Expected, ...) \
|
||||
assert_op(Actual, Expected, <=, "" __VA_ARGS__)
|
||||
# define expect_leq(Actual, Expected, ...) \
|
||||
expect_op(Actual, Expected, <=, "" __VA_ARGS__)
|
||||
# define assert_leq(...) assert_op_(<=, __VA_ARGS__, .sentinel_ = 0)
|
||||
# define expect_leq(...) expect_op_(<=, __VA_ARGS__, .sentinel_ = 0)
|
||||
|
||||
# define assert_geq(Actual, Expected, ...) \
|
||||
assert_op(Actual, Expected, >=, "" __VA_ARGS__)
|
||||
# define expect_geq(Actual, Expected, ...) \
|
||||
expect_op(Actual, Expected, >=, "" __VA_ARGS__)
|
||||
# define assert_geq(...) assert_op_(>=, __VA_ARGS__, .sentinel_ = 0)
|
||||
# define expect_geq(...) expect_op_(>=, __VA_ARGS__, .sentinel_ = 0)
|
||||
|
||||
// Floating-point asserts
|
||||
|
||||
# define assert_float_equal(Actual, Expected, Epsilon, ...) \
|
||||
assert((Expected) - (Actual) <= (Epsilon) && (Actual) - (Expected) <= (Epsilon), "" __VA_ARGS__)
|
||||
# define expect_float_equal(Actual, Expected, Epsilon, ...) \
|
||||
expect((Expected) - (Actual) <= (Epsilon) && (Actual) - (Expected) <= (Epsilon), "" __VA_ARGS__)
|
||||
# define assert_float_eq(...) \
|
||||
assert_float_eq_(__VA_ARGS__, .sentinel_ = 0)
|
||||
# define expect_float_eq(...) \
|
||||
expect_float_eq_(__VA_ARGS__, .sentinel_ = 0)
|
||||
|
||||
# define assert_float_not_equal(Actual, Expected, Epsilon, ...) \
|
||||
assert((Expected) - (Actual) > (Epsilon) || (Actual) - (Expected) > (Epsilon), "" __VA_ARGS__)
|
||||
# define expect_float_not_equal(Actual, Expected, Epsilon, ...) \
|
||||
expect((Expected) - (Actual) > (Epsilon) || (Actual) - (Expected) > (Epsilon), "" __VA_ARGS__)
|
||||
# define assert_float_eq_(Actual, Expected, Epsilon, ...) \
|
||||
assert_impl(FATAL, (Expected) - (Actual) <= (Epsilon) \
|
||||
&& (Actual) - (Expected) <= (Epsilon), \
|
||||
__VA_ARGS__)
|
||||
# define expect_float_eq_(Actual, Expected, Epsilon, ...) \
|
||||
assert_impl(NORMAL, (Expected) - (Actual) <= (Epsilon) \
|
||||
&& (Actual) - (Expected) <= (Epsilon), \
|
||||
__VA_ARGS__)
|
||||
|
||||
# define assert_float_neq(...) \
|
||||
assert_float_neq_(__VA_ARGS__, .sentinel_ = 0)
|
||||
# define expect_float_neq(...) \
|
||||
expect_float_neq_(__VA_ARGS__, .sentinel_ = 0)
|
||||
|
||||
# define assert_float_neq_(Actual, Expected, Epsilon, ...) \
|
||||
assert_impl(FATAL, (Expected) - (Actual) > (Epsilon) \
|
||||
|| (Actual) - (Expected) > (Epsilon), \
|
||||
__VA_ARGS__)
|
||||
# define expect_float_neq_(Actual, Expected, Epsilon, ...) \
|
||||
assert_impl(NORMAL, (Expected) - (Actual) > (Epsilon) \
|
||||
|| (Actual) - (Expected) > (Epsilon), \
|
||||
__VA_ARGS__)
|
||||
|
||||
// String asserts
|
||||
|
||||
# define assert_strings(Actual, Expected, Op, ...) \
|
||||
assert(strcmp((Actual), (Expected)) Op 0, "" __VA_ARGS__)
|
||||
# define expect_strings(Actual, Expected, Op, ...) \
|
||||
expect(strcmp((Actual), (Expected)) Op 0, "" __VA_ARGS__)
|
||||
# define assert_strings_(Op, Actual, Expected, ...) \
|
||||
assert_impl(FATAL, strcmp((Actual), (Expected)) Op 0, __VA_ARGS__)
|
||||
# define expect_strings_(Op, Actual, Expected, ...) \
|
||||
assert_impl(NORMAL, strcmp((Actual), (Expected)) Op 0, __VA_ARGS__)
|
||||
|
||||
# define assert_strings_equal(Actual, Expected, ...) \
|
||||
assert_strings(Actual, Expected, ==, "" __VA_ARGS__)
|
||||
# define expect_strings_equal(Actual, Expected, ...) \
|
||||
expect_strings(Actual, Expected, ==, "" __VA_ARGS__)
|
||||
# define assert_strings_eq(...) \
|
||||
assert_strings_(==, __VA_ARGS__, .sentinel_ = 0)
|
||||
# define expect_strings_eq(...) \
|
||||
expect_strings_(==, __VA_ARGS__, .sentinel_ = 0)
|
||||
|
||||
# define assert_strings_gt(Actual, Expected, ...) \
|
||||
assert_strings(Actual, Expected, >, "" __VA_ARGS__)
|
||||
# define expect_strings_gt(Actual, Expected, ...) \
|
||||
expect_strings(Actual, Expected, >, "" __VA_ARGS__)
|
||||
# define assert_strings_neq(...) \
|
||||
assert_strings_(!=, __VA_ARGS__, .sentinel_ = 0)
|
||||
# define expect_strings_neq(...) \
|
||||
expect_strings_(!=, __VA_ARGS__, .sentinel_ = 0)
|
||||
|
||||
# define assert_strings_lt(Actual, Expected, ...) \
|
||||
assert_strings(Actual, Expected, <, "" __VA_ARGS__)
|
||||
# define expect_strings_lt(Actual, Expected, ...) \
|
||||
expect_strings(Actual, Expected, <, "" __VA_ARGS__)
|
||||
# define assert_strings_gt(...) assert_strings_(>, __VA_ARGS__, .sentinel_ = 0)
|
||||
# define expect_strings_gt(...) expect_strings_(>, __VA_ARGS__, .sentinel_ = 0)
|
||||
|
||||
# define assert_strings_geq(Actual, Expected, ...) \
|
||||
assert_strings(Actual, Expected, >=, "" __VA_ARGS__)
|
||||
# define expect_strings_geq(Actual, Expected, ...) \
|
||||
expect_strings(Actual, Expected, >=, "" __VA_ARGS__)
|
||||
# define assert_strings_lt(...) assert_strings_(<, __VA_ARGS__, .sentinel_ = 0)
|
||||
# define expect_strings_lt(...) expect_strings_(<, __VA_ARGS__, .sentinel_ = 0)
|
||||
|
||||
# define assert_strings_leq(Actual, Expected, ...) \
|
||||
assert_strings(Actual, Expected, <=, "" __VA_ARGS__)
|
||||
# define expect_strings_leq(Actual, Expected, ...) \
|
||||
expect_strings(Actual, Expected, <=, "" __VA_ARGS__)
|
||||
# define assert_strings_leq(...) assert_strings_(<=, __VA_ARGS__, .sentinel_ = 0)
|
||||
# define expect_strings_leq(...) expect_strings_(<=, __VA_ARGS__, .sentinel_ = 0)
|
||||
|
||||
# define assert_strings_not_equal(Actual, Expected, ...) \
|
||||
assert_strings(Actual, Expected, !=, "" __VA_ARGS__)
|
||||
# define expect_strings_not_equal(Actual, Expected, ...) \
|
||||
expect_strings(Actual, Expected, !=, "" __VA_ARGS__)
|
||||
# define assert_strings_geq(...) assert_strings_(>=, __VA_ARGS__, .sentinel_ = 0)
|
||||
# define expect_strings_geq(...) expect_strings_(>=, __VA_ARGS__, .sentinel_ = 0)
|
||||
|
||||
// Array asserts
|
||||
|
||||
# define assert_arrays_equal(A, B, Size, ...) \
|
||||
assert(!memcmp((A), (B), (Size)), "" __VA_ARGS__)
|
||||
# define expect_arrays_equal(A, B, Size, ...) \
|
||||
expect(!memcmp((A), (B), (Size)), "" __VA_ARGS__)
|
||||
# define assert_arrays_eq(...) \
|
||||
assert_arrays_eq_(__VA_ARGS__, .sentinel = 0)
|
||||
# define expect_arrays_eq(...) \
|
||||
expect_arrays_eq_(__VA_ARGS__, .sentinel = 0)
|
||||
|
||||
# define assert_arrays_not_equal(A, B, Size, ...) \
|
||||
assert(memcmp((A), (B), (Size)), "" __VA_ARGS__)
|
||||
# define expect_arrays_not_equal(A, B, Size, ...) \
|
||||
expect(memcmp((A), (B), (Size)), "" __VA_ARGS__)
|
||||
# define assert_arrays_neq(...) \
|
||||
assert_arrays_neq_(__VA_ARGS__, .sentinel = 0)
|
||||
# define expect_arrays_neq(...) \
|
||||
expect_arrays_neq_(__VA_ARGS__, .sentinel = 0)
|
||||
|
||||
# define assert_arrays_eq_(A, B, Size, ...) \
|
||||
assert_impl(FATAL, !memcmp((A), (B), (Size)), __VA_ARGS__)
|
||||
# define expect_arrays_eq_(A, B, Size, ...) \
|
||||
assert_impl(NORMAL, !memcmp((A), (B), (Size)), __VA_ARGS__)
|
||||
|
||||
# define assert_arrays_neq_(A, B, Size, ...) \
|
||||
assert_impl(FATAL, memcmp((A), (B), (Size)), __VA_ARGS__)
|
||||
# define expect_arrays_neq_(A, B, Size, ...) \
|
||||
assert_impl(NORMAL, memcmp((A), (B), (Size)), __VA_ARGS__)
|
||||
|
||||
#endif /* !CRITERION_ASSERT_H_ */
|
||||
|
|
|
@ -57,6 +57,12 @@
|
|||
|
||||
# define UNUSED __attribute__((unused))
|
||||
|
||||
# ifdef _WIN32
|
||||
# define SIZE_T_FORMAT "%Iu"
|
||||
# else
|
||||
# define SIZE_T_FORMAT "%zu"
|
||||
# endif
|
||||
|
||||
# ifdef __GNUC__
|
||||
# define FORMAT(Archetype, Index, Ftc) __attribute__((format(Archetype, Index, Ftc)))
|
||||
# else
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
# include "assert.h"
|
||||
|
||||
struct criterion_test_extra_data {
|
||||
int sentinel_;
|
||||
const char *const file_;
|
||||
const unsigned line_;
|
||||
void (*init)(void);
|
||||
|
@ -56,7 +57,8 @@ struct criterion_test_set {
|
|||
# define TEST_PROTOTYPE_(Category, Name) \
|
||||
void IDENTIFIER_(Category, Name, impl)(void)
|
||||
|
||||
# define Test(Category, Name, ...) \
|
||||
# define Test(...) Test_(__VA_ARGS__, .sentinel_ = 0)
|
||||
# define Test_(Category, Name, ...) \
|
||||
TEST_PROTOTYPE_(Category, Name); \
|
||||
struct criterion_test_extra_data IDENTIFIER_(Category, Name, extra) = { \
|
||||
.file_ = __FILE__, \
|
||||
|
|
|
@ -24,6 +24,8 @@
|
|||
#ifndef CRITERION_EVENT_H_
|
||||
# define CRITERION_EVENT_H_
|
||||
|
||||
# include <stddef.h>
|
||||
|
||||
extern int EVENT_PIPE;
|
||||
|
||||
void send_event(int kind, void *data, size_t size);
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#ifndef CRITERION_OPTIONS_H_
|
||||
# define CRITERION_OPTIONS_H_
|
||||
|
||||
# include <stdbool.h>
|
||||
# include "logging.h"
|
||||
|
||||
struct criterion_options {
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
# define CRITERION_STATS_H_
|
||||
|
||||
# include <stdbool.h>
|
||||
# include <stddef.h>
|
||||
# include "criterion.h"
|
||||
|
||||
struct criterion_assert_stats {
|
||||
|
@ -45,6 +46,7 @@ struct criterion_test_stats {
|
|||
int passed_asserts;
|
||||
int failed_asserts;
|
||||
int signal;
|
||||
float elapsed_time;
|
||||
unsigned progress;
|
||||
const char *file;
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
TESTS = \
|
||||
BIN_TESTS = \
|
||||
signal \
|
||||
report \
|
||||
suites \
|
||||
|
@ -6,18 +6,22 @@ TESTS = \
|
|||
asserts \
|
||||
simple
|
||||
|
||||
TESTS += tests/tap_test.sh \
|
||||
tests/early_exit.sh \
|
||||
tests/verbose.sh \
|
||||
tests/help.sh
|
||||
TESTS_ENVIRONMENT = CRITERION_ALWAYS_SUCCEED=1
|
||||
|
||||
check_PROGRAMS := $(BIN_TESTS)
|
||||
CFLAGS = -I$(top_srcdir)/include/ -std=c99 -Wall -Wextra -pedantic
|
||||
LDADD = -L$(top_srcdir)/ -lcriterion
|
||||
|
||||
SCRIPT_TESTS = tests/tap_test.sh \
|
||||
tests/early_exit.sh \
|
||||
tests/verbose.sh \
|
||||
tests/help.sh
|
||||
|
||||
EXTRA_DIST = $(SCRIPT_TESTS)
|
||||
|
||||
tests/tap_test.sh: simple signal asserts
|
||||
tests/early_exit.sh: simple
|
||||
tests/verbose.sh: simple
|
||||
tests/help.sh: simple
|
||||
|
||||
TESTS_ENVIRONMENT = CRITERION_ALWAYS_SUCCEED=1
|
||||
|
||||
check_PROGRAMS = $(TESTS)
|
||||
CFLAGS = -I$(top_srcdir)/include/ -std=c99
|
||||
LDADD = -L$(top_srcdir)/ -lcriterion
|
||||
TESTS = $(BIN_TESTS) $(SCRIPT_TESTS)
|
||||
|
|
|
@ -6,14 +6,23 @@ Test(asserts, base) {
|
|||
|
||||
assert(true, "Assertions may take failure messages");
|
||||
|
||||
assert(true, .msg = "You can use explicit named arguments");
|
||||
|
||||
expect(false, "assert is fatal, expect isn't");
|
||||
assert(false, "This assert runs");
|
||||
assert(false, "This does not");
|
||||
}
|
||||
|
||||
Test(asserts, old_school) {
|
||||
if (false)
|
||||
abort_test("You can abort the test with a message from anywhere");
|
||||
|
||||
abort_test(NULL); // or without a message
|
||||
}
|
||||
|
||||
Test(asserts, string) {
|
||||
assert_strings_equal("hello", "hello");
|
||||
assert_strings_not_equal("hello", "olleh");
|
||||
assert_strings_eq("hello", "hello");
|
||||
assert_strings_neq("hello", "olleh");
|
||||
|
||||
assert_strings_gt("hello", "hell");
|
||||
assert_strings_geq("hello", "hell");
|
||||
|
@ -25,8 +34,8 @@ Test(asserts, string) {
|
|||
}
|
||||
|
||||
Test(asserts, native) {
|
||||
assert_equal(1, 1);
|
||||
assert_not_equal(1, 2);
|
||||
assert_eq(1, 1);
|
||||
assert_neq(1, 2);
|
||||
|
||||
assert_lt(1, 2);
|
||||
assert_leq(1, 2);
|
||||
|
@ -38,6 +47,6 @@ Test(asserts, native) {
|
|||
}
|
||||
|
||||
Test(asserts, float) {
|
||||
assert_not_equal(0.1 * 0.1, 0.01);
|
||||
assert_float_equal(0.1 * 0.1, 0.01, 0.001);
|
||||
assert_neq(0.1 * 0.1, 0.01);
|
||||
assert_float_eq(0.1 * 0.1, 0.01, 0.001);
|
||||
}
|
||||
|
|
29
src/event.c
29
src/event.c
|
@ -21,14 +21,9 @@
|
|||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
#include "criterion/assert.h"
|
||||
#undef assert
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <assert.h>
|
||||
#include <csptr/smart_ptr.h>
|
||||
#include "criterion/criterion.h"
|
||||
#include "criterion/stats.h"
|
||||
#include "criterion/hooks.h"
|
||||
#include "event.h"
|
||||
|
@ -45,15 +40,25 @@ struct event *read_event(int fd) {
|
|||
if (read(fd, &kind, sizeof (unsigned)) < (ssize_t) sizeof (unsigned))
|
||||
return NULL;
|
||||
|
||||
if (kind != ASSERT)
|
||||
return unique_ptr(struct event, ({ .kind = kind, .data = NULL }));
|
||||
switch (kind) {
|
||||
case ASSERT: {
|
||||
const size_t assert_size = sizeof (struct criterion_assert_stats);
|
||||
unsigned char *buf = malloc(assert_size);
|
||||
if (read(fd, buf, assert_size) < (ssize_t) assert_size)
|
||||
return NULL;
|
||||
|
||||
const size_t assert_size = sizeof (struct criterion_assert_stats);
|
||||
unsigned char *buf = malloc(assert_size);
|
||||
if (read(fd, buf, assert_size) < (ssize_t) assert_size)
|
||||
return NULL;
|
||||
return unique_ptr(struct event, ({ .kind = kind, .data = buf }), destroy_event);
|
||||
}
|
||||
case POST_TEST: {
|
||||
double *elapsed_time = malloc(sizeof (double));
|
||||
if (read(fd, elapsed_time, sizeof (double)) < (ssize_t) sizeof (double))
|
||||
return NULL;
|
||||
|
||||
return unique_ptr(struct event, ({ .kind = kind, .data = buf }), destroy_event);
|
||||
return unique_ptr(struct event, ({ .kind = kind, .data = elapsed_time }), destroy_event);
|
||||
}
|
||||
default:
|
||||
return unique_ptr(struct event, ({ .kind = kind, .data = NULL }));
|
||||
}
|
||||
}
|
||||
|
||||
void send_event(int kind, void *data, size_t size) {
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
#define _GNU_SOURCE
|
||||
#include <criterion/criterion.h>
|
||||
#include <criterion/logging.h>
|
||||
#include <criterion/options.h>
|
||||
#include <stdio.h>
|
||||
#include <getopt.h>
|
||||
|
@ -44,5 +43,5 @@ int main(int argc, char *argv[]) {
|
|||
}
|
||||
}
|
||||
|
||||
return criterion_run_all_tests();
|
||||
return !criterion_run_all_tests();
|
||||
}
|
||||
|
|
|
@ -22,9 +22,7 @@
|
|||
* THE SOFTWARE.
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/signal.h>
|
||||
#include <sys/wait.h>
|
||||
#include <csptr/smart_ptr.h>
|
||||
|
||||
|
@ -71,7 +69,7 @@ struct process *spawn_test_worker(struct criterion_test *test, void (*func)(stru
|
|||
|
||||
func(test);
|
||||
close(fds[1]);
|
||||
if (!criterion_options.no_early_exit)
|
||||
if (criterion_options.no_early_exit)
|
||||
return NULL;
|
||||
else
|
||||
_exit(0);
|
||||
|
|
|
@ -24,6 +24,8 @@
|
|||
#ifndef PROCESS_H_
|
||||
# define PROCESS_H_
|
||||
|
||||
# include <stdbool.h>
|
||||
|
||||
struct process;
|
||||
|
||||
enum status_kind {
|
||||
|
|
20
src/report.c
20
src/report.c
|
@ -27,6 +27,7 @@
|
|||
#include "criterion/logging.h"
|
||||
#include "criterion/options.h"
|
||||
#include "report.h"
|
||||
#include "timer.h"
|
||||
|
||||
#define IMPL_CALL_REPORT_HOOKS(Kind) \
|
||||
IMPL_SECTION_LIMITS(f_report_hook, crit_ ## Kind); \
|
||||
|
@ -57,11 +58,14 @@ ReportHook(PRE_INIT)(struct criterion_test *test) {
|
|||
|
||||
ReportHook(POST_TEST)(struct criterion_test_stats *stats) {
|
||||
if (criterion_options.enable_tap_format) {
|
||||
criterion_important("%s %lu - %s::%s\n",
|
||||
const char *format = can_measure_time() ? "%s " SIZE_T_FORMAT " - %s::%s (%3.2fs)\n"
|
||||
: "%s " SIZE_T_FORMAT " - %s::%s\n";
|
||||
criterion_important(format,
|
||||
stats->failed ? "not ok" : "ok",
|
||||
tap_test_index++,
|
||||
stats->test->category,
|
||||
stats->test->name);
|
||||
stats->test->name,
|
||||
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), *saveptr = NULL;
|
||||
|
@ -76,11 +80,13 @@ ReportHook(POST_TEST)(struct criterion_test_stats *stats) {
|
|||
}
|
||||
}
|
||||
} else {
|
||||
const char *format = can_measure_time() ? "%s::%s: %s (%3.2fs)\n" : "%s::%s: %s\n";
|
||||
criterion_log(stats->failed ? CRITERION_IMPORTANT : CRITERION_INFO,
|
||||
"%s::%s: %s\n",
|
||||
format,
|
||||
stats->test->category,
|
||||
stats->test->name,
|
||||
stats->failed ? "FAILURE" : "SUCCESS");
|
||||
stats->failed ? "FAILURE" : "SUCCESS",
|
||||
stats->elapsed_time);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -93,13 +99,13 @@ ReportHook(PRE_ALL)(struct criterion_test_set *set) {
|
|||
for (struct criterion_test **test = set->tests; i < set->nb_tests; ++i)
|
||||
if (!(test[i])->data->disabled)
|
||||
++enabled_count;
|
||||
criterion_important("1..%lu\n", enabled_count);
|
||||
criterion_important("1.." SIZE_T_FORMAT "\n", enabled_count);
|
||||
}
|
||||
}
|
||||
ReportHook(POST_ALL)(struct criterion_global_stats *stats) {
|
||||
if (criterion_options.enable_tap_format) return;
|
||||
|
||||
criterion_important("Synthesis: %lu tests were run. %lu passed, %lu failed (with %lu crashes)\n",
|
||||
criterion_important("Synthesis: " SIZE_T_FORMAT " tests were run. " SIZE_T_FORMAT " passed, " SIZE_T_FORMAT " failed (with " SIZE_T_FORMAT " crashes)\n",
|
||||
stats->nb_tests,
|
||||
stats->tests_passed,
|
||||
stats->tests_failed,
|
||||
|
@ -119,7 +125,7 @@ ReportHook(ASSERT)(struct criterion_assert_stats *stats) {
|
|||
|
||||
ReportHook(TEST_CRASH)(struct criterion_test_stats *stats) {
|
||||
if (criterion_options.enable_tap_format) {
|
||||
criterion_important("not ok %lu - %s::%s unexpected signal after %s:%u\n",
|
||||
criterion_important("not ok " SIZE_T_FORMAT " - %s::%s unexpected signal after %s:%u\n",
|
||||
tap_test_index++,
|
||||
stats->test->category,
|
||||
stats->test->name,
|
||||
|
|
21
src/runner.c
21
src/runner.c
|
@ -24,15 +24,14 @@
|
|||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/wait.h>
|
||||
#include <csptr/smart_ptr.h>
|
||||
#include "criterion/assert.h"
|
||||
#include "criterion/options.h"
|
||||
#include "stats.h"
|
||||
#include "runner.h"
|
||||
#include "report.h"
|
||||
#include "event.h"
|
||||
#include "process.h"
|
||||
#include "timer.h"
|
||||
|
||||
IMPL_SECTION_LIMITS(struct criterion_test, criterion_tests);
|
||||
|
||||
|
@ -89,8 +88,15 @@ static void run_test_child(struct criterion_test *test) {
|
|||
send_event(PRE_INIT, NULL, 0);
|
||||
(test->data->init ?: nothing)();
|
||||
send_event(PRE_TEST, NULL, 0);
|
||||
|
||||
struct timespec_compat ts;
|
||||
timer_start(&ts);
|
||||
(test->test ?: nothing)();
|
||||
send_event(POST_TEST, NULL, 0);
|
||||
double elapsed_time;
|
||||
if (!timer_end(&elapsed_time, &ts))
|
||||
elapsed_time = -1;
|
||||
|
||||
send_event(POST_TEST, &elapsed_time, sizeof (double));
|
||||
(test->data->fini ?: nothing)();
|
||||
send_event(POST_FINI, NULL, 0);
|
||||
}
|
||||
|
@ -126,11 +132,12 @@ static void run_test(struct criterion_global_stats *stats, struct criterion_test
|
|||
stat_push_event(stats, test_stats, &ev);
|
||||
report(TEST_CRASH, test_stats);
|
||||
} else {
|
||||
struct event ev = { .kind = POST_TEST };
|
||||
double elapsed_time = 0;
|
||||
struct event ev = { .kind = POST_TEST, .data = &elapsed_time };
|
||||
stat_push_event(stats, test_stats, &ev);
|
||||
report(POST_TEST, test_stats);
|
||||
|
||||
ev.kind = POST_FINI;
|
||||
ev = (struct event) { .kind = POST_FINI, .data = NULL };
|
||||
stat_push_event(stats, test_stats, &ev);
|
||||
report(POST_FINI, test_stats);
|
||||
}
|
||||
|
@ -152,7 +159,7 @@ static int criterion_run_all_tests_impl(void) {
|
|||
return -1;
|
||||
|
||||
report(POST_ALL, stats);
|
||||
return stats->tests_failed > 0;
|
||||
return stats->tests_failed == 0;
|
||||
}
|
||||
|
||||
int criterion_run_all_tests(void) {
|
||||
|
@ -160,5 +167,5 @@ int criterion_run_all_tests(void) {
|
|||
if (res == -1) // if this is the test worker terminating
|
||||
_exit(0);
|
||||
|
||||
return !criterion_options.always_succeed && res;
|
||||
return criterion_options.always_succeed || res;
|
||||
}
|
||||
|
|
|
@ -114,7 +114,8 @@ static void push_assert(s_glob_stats *stats,
|
|||
|
||||
static void push_post_test(s_glob_stats *stats,
|
||||
s_test_stats *test,
|
||||
UNUSED void *ptr) {
|
||||
double *ptr) {
|
||||
test->elapsed_time = *ptr;
|
||||
if (test->failed_asserts > 0 || test->signal != test->test->data->signal) {
|
||||
test->failed = 1;
|
||||
++stats->tests_failed;
|
||||
|
|
83
src/timer.c
Normal file
83
src/timer.c
Normal file
|
@ -0,0 +1,83 @@
|
|||
#include <errno.h>
|
||||
#include <inttypes.h>
|
||||
#include "timer.h"
|
||||
|
||||
#define GIGA 1000000000
|
||||
|
||||
#if defined(__unix__) && !defined(__CYGWIN__)
|
||||
|
||||
# ifdef CLOCK_MONOTONIC_RAW
|
||||
# define CLOCK CLOCK_MONOTONIC_RAW
|
||||
# else
|
||||
# define CLOCK CLOCK_MONOTONIC
|
||||
# endif
|
||||
|
||||
extern __attribute__ ((weak)) int clock_gettime(clockid_t, struct timespec *);
|
||||
|
||||
#elif defined(__APPLE__)
|
||||
# include <mach/clock.h>
|
||||
# include <mach/mach.h>
|
||||
#elif defined(_WIN32) || defined(__CYGWIN__)
|
||||
# define VC_EXTRALEAN
|
||||
# define WIN32_LEAN_AND_MEAN
|
||||
# include <Windows.h>
|
||||
#endif
|
||||
|
||||
bool can_measure_time(void) {
|
||||
#if defined(__unix__) && !defined(__CYGWIN__)
|
||||
return clock_gettime != NULL;
|
||||
#else
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
int gettime_compat(struct timespec_compat *ts) {
|
||||
#if defined(__APPLE__)
|
||||
clock_serv_t cclock;
|
||||
mach_timespec_t mts;
|
||||
|
||||
host_get_clock_service(mach_host_self(), SYSTEM_CLOCK, &cclock);
|
||||
int res = clock_get_time(cclock, &mts);
|
||||
mach_port_deallocate(mach_task_self(), cclock);
|
||||
|
||||
*ts = (struct timespec_compat) { mts.tv_sec, mts.tv_nsec };
|
||||
return res > 0 ? -1 : 0;
|
||||
#elif defined(_WIN32) || defined(__CYGWIN__)
|
||||
LARGE_INTEGER freq, count;
|
||||
if (!QueryPerformanceFrequency(&freq)
|
||||
|| !QueryPerformanceCounter(&count))
|
||||
return -1;
|
||||
|
||||
int64_t sec = count.QuadPart / freq.QuadPart;
|
||||
int64_t nano = (int64_t) ((double) count.QuadPart * GIGA / (double) freq.QuadPart) % GIGA;
|
||||
|
||||
*ts = (struct timespec_compat) { sec, nano };
|
||||
return 0;
|
||||
#elif defined(__unix__)
|
||||
if (!can_measure_time()) {
|
||||
errno = ENOTSUP;
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct timespec ts_;
|
||||
int res = clock_gettime(CLOCK, &ts_);
|
||||
|
||||
*ts = (struct timespec_compat) { ts_.tv_sec, ts_.tv_nsec };
|
||||
return res;
|
||||
#else
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
int timer_start(struct timespec_compat *state) {
|
||||
return gettime_compat(state) == -1 ? 0 : 1;
|
||||
}
|
||||
|
||||
int timer_end(double *time, struct timespec_compat *state) {
|
||||
struct timespec_compat last;
|
||||
if (gettime_compat(&last) == -1)
|
||||
return 0;
|
||||
|
||||
*time = (last.tv_sec - state->tv_sec) + (last.tv_nsec - state->tv_nsec) / (double) GIGA;
|
||||
return 1;
|
||||
}
|
17
src/timer.h
Normal file
17
src/timer.h
Normal file
|
@ -0,0 +1,17 @@
|
|||
#ifndef TIMER_H_
|
||||
# define TIMER_H_
|
||||
|
||||
# include <time.h>
|
||||
# include <inttypes.h>
|
||||
# include <stdbool.h>
|
||||
|
||||
struct timespec_compat {
|
||||
int64_t tv_sec;
|
||||
int64_t tv_nsec;
|
||||
};
|
||||
|
||||
bool can_measure_time(void);
|
||||
int timer_start(struct timespec_compat *state);
|
||||
int timer_end(double *time, struct timespec_compat *state);
|
||||
|
||||
#endif /* !TIMER_H_ */
|
Loading…
Add table
Reference in a new issue