From a6b13abb816f9ab4575fa9862e1b57b443a0840b Mon Sep 17 00:00:00 2001 From: Snaipe Date: Mon, 16 Mar 2015 02:45:22 +0100 Subject: [PATCH 01/31] Added FreeBSD downloads & support in README.md --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 2cdb128..31470a3 100644 --- a/README.md +++ b/README.md @@ -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) +* [FreeBSD (x86_64)](https://github.com/Snaipe/Criterion/releases/download/v0.3/criterion-0.3-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) @@ -68,9 +69,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 From b81d71855f22831c072a2c8403ad43de7059b0f0 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Mon, 16 Mar 2015 02:49:15 +0100 Subject: [PATCH 02/31] Fixed test scripts being deleted on make clean --- samples/Makefile.am | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/samples/Makefile.am b/samples/Makefile.am index e92ca78..2c3ba25 100644 --- a/samples/Makefile.am +++ b/samples/Makefile.am @@ -1,4 +1,4 @@ -TESTS = \ +BIN_TESTS = \ signal \ report \ suites \ @@ -6,18 +6,20 @@ 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 +LDADD = -L$(top_srcdir)/ -lcriterion + +SCRIPT_TESTS = tests/tap_test.sh \ + tests/early_exit.sh \ + tests/verbose.sh \ + tests/help.sh 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) From 4eb5cc7ee40a01d16b150898eff1a99569a4e93a Mon Sep 17 00:00:00 2001 From: Snaipe Date: Mon, 16 Mar 2015 10:30:43 +0100 Subject: [PATCH 03/31] Added base appveyor config --- appveyor.yml | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 appveyor.yml diff --git a/appveyor.yml b/appveyor.yml new file mode 100644 index 0000000..229be4a --- /dev/null +++ b/appveyor.yml @@ -0,0 +1,54 @@ +version: 3.0.0.{build}-{branch} + +os: Windows Server 2012 + +init: + - git config --global core.autocrlf input + - c:\cygwin\setup-x86.exe -qnNdO -R C:/cygwin -s http://cygwin.mirror.constant.com -l C:/cygwin/var/cache/setup \ + -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 + +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: + - cmd: c:\cygwin\bin\bash -C './autogen && ./configure' + +build_script: + - cmd: c:\cygwin\bin\bash -C 'make' + +test_script: + - cmd: c:\cygwin\bin\bash -C 'make check' + +notifications: + + - provider: Email + to: [franklinmathieu@gmail.com] + on_build_status_changed: true From aee490227c42884813e6a6ec116f15a3106655c2 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Mon, 16 Mar 2015 10:31:45 +0100 Subject: [PATCH 04/31] Fixed appveyor build version --- appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index 229be4a..abde5ea 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,4 +1,4 @@ -version: 3.0.0.{build}-{branch} +version: 0.3.0.{build}-{branch} os: Windows Server 2012 From 1ad80a2f47d18dc8c08100b1605fa884f4880cff Mon Sep 17 00:00:00 2001 From: Snaipe Date: Mon, 16 Mar 2015 10:37:28 +0100 Subject: [PATCH 05/31] Added cygwin download --- appveyor.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index abde5ea..e33b3c8 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -3,8 +3,9 @@ version: 0.3.0.{build}-{branch} os: Windows Server 2012 init: + - ps: (New-Object System.Net.WebClient).DownloadFile("https://cygwin.com/setup-x86.exe", "$pwd\setup-x86.exe") - git config --global core.autocrlf input - - c:\cygwin\setup-x86.exe -qnNdO -R C:/cygwin -s http://cygwin.mirror.constant.com -l C:/cygwin/var/cache/setup \ + - setup-x86.exe -qnNdO -R C:/cygwin -s http://cygwin.mirror.constant.com -l C:/cygwin/var/cache/setup \ -P autoconf \ -P automake \ -P gcc-core \ From d5add26f1d006f337d460baa28e600c3a4445a33 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Mon, 16 Mar 2015 10:43:21 +0100 Subject: [PATCH 06/31] Download cygwin to the filesystem root --- appveyor.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index e33b3c8..4fa807e 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -3,9 +3,9 @@ version: 0.3.0.{build}-{branch} os: Windows Server 2012 init: - - ps: (New-Object System.Net.WebClient).DownloadFile("https://cygwin.com/setup-x86.exe", "$pwd\setup-x86.exe") + - ps: (New-Object System.Net.WebClient).DownloadFile("https://cygwin.com/setup-x86.exe", "c:\setup-x86.exe") - git config --global core.autocrlf input - - setup-x86.exe -qnNdO -R C:/cygwin -s http://cygwin.mirror.constant.com -l C:/cygwin/var/cache/setup \ + - c:\setup-x86.exe -qnNdO -R C:/cygwin -s http://cygwin.mirror.constant.com -l C:/cygwin/var/cache/setup \ -P autoconf \ -P automake \ -P gcc-core \ From 54426c5590e0efb2d01552845aa37c438964dd81 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Mon, 16 Mar 2015 10:48:17 +0100 Subject: [PATCH 07/31] Fixed ./autogen -> ./autogen.sh --- appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index 4fa807e..15027b4 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -40,7 +40,7 @@ platform: configuration: Release install: - - cmd: c:\cygwin\bin\bash -C './autogen && ./configure' + - cmd: c:\cygwin\bin\bash -C './autogen.sh && ./configure' build_script: - cmd: c:\cygwin\bin\bash -C 'make' From 360161977c4ae7d480e847a7210ace19acad5b13 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Mon, 16 Mar 2015 10:55:06 +0100 Subject: [PATCH 08/31] Change work directory before doing anything --- appveyor.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 15027b4..91f3d7a 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -40,13 +40,13 @@ platform: configuration: Release install: - - cmd: c:\cygwin\bin\bash -C './autogen.sh && ./configure' + - cmd: c:\cygwin\bin\bash -C 'cd /cygdrive/c/projects/criterion && ./autogen.sh && ./configure' build_script: - - cmd: c:\cygwin\bin\bash -C 'make' + - cmd: c:\cygwin\bin\bash -C 'cd /cygdrive/c/projects/criterion && make' test_script: - - cmd: c:\cygwin\bin\bash -C 'make check' + - cmd: c:\cygwin\bin\bash -C 'cd /cygdrive/c/projects/criterion && make check' notifications: From 7ac470b0da81b97fda42472801348088fb8fde39 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Mon, 16 Mar 2015 11:12:53 +0100 Subject: [PATCH 09/31] Fixed build script options --- appveyor.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 91f3d7a..f6940c6 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -40,13 +40,13 @@ platform: configuration: Release install: - - cmd: c:\cygwin\bin\bash -C 'cd /cygdrive/c/projects/criterion && ./autogen.sh && ./configure' + - cmd: c:\cygwin\bin\bash -c './autogen.sh && ./configure' build_script: - - cmd: c:\cygwin\bin\bash -C 'cd /cygdrive/c/projects/criterion && make' + - cmd: c:\cygwin\bin\bash -c 'make' test_script: - - cmd: c:\cygwin\bin\bash -C 'cd /cygdrive/c/projects/criterion && make check' + - cmd: c:\cygwin\bin\bash -c 'make check' notifications: From 96e6d2e6c95b5e7baec41660532bb87cf5e68259 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Mon, 16 Mar 2015 11:26:03 +0100 Subject: [PATCH 10/31] Fixing autoreconf being not found --- appveyor.yml | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index f6940c6..293a953 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -5,7 +5,7 @@ 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 C:/cygwin -s http://cygwin.mirror.constant.com -l C:/cygwin/var/cache/setup \ + - c:\setup-x86.exe -qnNdO -R %CYG_ROOT% -s %CYG_MIRROR% -l %CYG_CACHE% \ -P autoconf \ -P automake \ -P gcc-core \ @@ -27,6 +27,17 @@ init: -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 @@ -40,13 +51,14 @@ platform: configuration: Release install: - - cmd: c:\cygwin\bin\bash -c './autogen.sh && ./configure' + - "%CYG_BASH% -lc 'cd $APPVEYOR_BUILD_FOLDER; ./autogen.sh'" + - "%CYG_BASH% -lc 'cd $APPVEYOR_BUILD_FOLDER; ./configure'" build_script: - - cmd: c:\cygwin\bin\bash -c 'make' + - "%CYG_BASH% -lc 'cd $APPVEYOR_BUILD_FOLDER; make'" test_script: - - cmd: c:\cygwin\bin\bash -c 'make check' + - "%CYG_BASH% -lc 'cd $APPVEYOR_BUILD_FOLDER; make check'" notifications: From af7e921af2d057f0e27a65673dbdcfcef3c8b9cf Mon Sep 17 00:00:00 2001 From: Snaipe Date: Mon, 16 Mar 2015 14:43:23 +0100 Subject: [PATCH 11/31] Opening stdin from /dev/null --- appveyor.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 293a953..bffb175 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -52,13 +52,13 @@ configuration: Release install: - "%CYG_BASH% -lc 'cd $APPVEYOR_BUILD_FOLDER; ./autogen.sh'" - - "%CYG_BASH% -lc 'cd $APPVEYOR_BUILD_FOLDER; ./configure'" + - '%CYG_BASH% -lc "cd $APPVEYOR_BUILD_FOLDER; exec 0 Date: Mon, 16 Mar 2015 15:05:47 +0100 Subject: [PATCH 12/31] Activated warnings on samples --- samples/Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/Makefile.am b/samples/Makefile.am index 2c3ba25..4df3627 100644 --- a/samples/Makefile.am +++ b/samples/Makefile.am @@ -9,7 +9,7 @@ BIN_TESTS = \ TESTS_ENVIRONMENT = CRITERION_ALWAYS_SUCCEED=1 check_PROGRAMS := $(BIN_TESTS) -CFLAGS = -I$(top_srcdir)/include/ -std=c99 +CFLAGS = -I$(top_srcdir)/include/ -std=c99 -Wall -Wextra LDADD = -L$(top_srcdir)/ -lcriterion SCRIPT_TESTS = tests/tap_test.sh \ From edd62ccd71c822ef042e65f1b721b0a1f9d0cbf5 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Mon, 16 Mar 2015 15:12:18 +0100 Subject: [PATCH 13/31] Added portable size_t printf format code --- include/criterion/common.h | 6 ++++++ src/report.c | 8 ++++---- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/include/criterion/common.h b/include/criterion/common.h index 32d6420..cdeffa9 100644 --- a/include/criterion/common.h +++ b/include/criterion/common.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 diff --git a/src/report.c b/src/report.c index 0a79eb9..fc07f03 100644 --- a/src/report.c +++ b/src/report.c @@ -57,7 +57,7 @@ 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", + criterion_important("%s " SIZE_T_FORMAT " - %s::%s\n", stats->failed ? "not ok" : "ok", tap_test_index++, stats->test->category, @@ -93,13 +93,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 +119,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, From 053623c1b1792c8344f7b3393bbf4ca20781965b Mon Sep 17 00:00:00 2001 From: Snaipe Date: Mon, 16 Mar 2015 15:23:20 +0100 Subject: [PATCH 14/31] Added -pedantic switch on samples --- samples/Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/Makefile.am b/samples/Makefile.am index 4df3627..ba6868c 100644 --- a/samples/Makefile.am +++ b/samples/Makefile.am @@ -9,7 +9,7 @@ BIN_TESTS = \ TESTS_ENVIRONMENT = CRITERION_ALWAYS_SUCCEED=1 check_PROGRAMS := $(BIN_TESTS) -CFLAGS = -I$(top_srcdir)/include/ -std=c99 -Wall -Wextra +CFLAGS = -I$(top_srcdir)/include/ -std=c99 -Wall -Wextra -pedantic LDADD = -L$(top_srcdir)/ -lcriterion SCRIPT_TESTS = tests/tap_test.sh \ From 51bccd8753fc1abf732fbe2a80972480d06f2d8a Mon Sep 17 00:00:00 2001 From: Snaipe Date: Mon, 16 Mar 2015 15:30:13 +0100 Subject: [PATCH 15/31] Made Test -pedantic compliant --- include/criterion/criterion.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/include/criterion/criterion.h b/include/criterion/criterion.h index 6c59180..2c0d963 100644 --- a/include/criterion/criterion.h +++ b/include/criterion/criterion.h @@ -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__, \ From 45f9eca9cdc7456b00c355ddc2e4d6cc4f71c9c7 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Mon, 16 Mar 2015 18:28:37 +0100 Subject: [PATCH 16/31] Made asserts -pedantic compliant --- include/criterion/assert.h | 182 +++++++++++++++++++++---------------- 1 file changed, 104 insertions(+), 78 deletions(-) diff --git a/include/criterion/assert.h b/include/criterion/assert.h index a5a6bed..75e3c61 100644 --- a/include/criterion/assert.h +++ b/include/criterion/assert.h @@ -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,124 @@ 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 assert(...) assert_(__VA_ARGS__, .sentinel_ = 0) +# define expect(...) expect_(__VA_ARGS__, .sentinel_ = 0) -# define assert_not(Condition, ...) assert(!(Condition), "" __VA_ARGS__) -# define expect_not(Condition, ...) expect(!(Condition), "" __VA_ARGS__) +# 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_equal(...) assert_op_(==, __VA_ARGS__, .sentinel_ = 0) +# define expect_equal(...) 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_not_equal(...) assert_op_(!=, __VA_ARGS__, .sentinel_ = 0) +# define expect_not_equal(...) 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_equal(...) \ + assert_float_equal_(__VA_ARGS__, .sentinel_ = 0) +# define expect_float_equal(...) \ + expect_float_equal_(__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_equal_(Actual, Expected, Epsilon, ...) \ + assert_impl(FATAL, (Expected) - (Actual) <= (Epsilon) \ + && (Actual) - (Expected) <= (Epsilon), \ + __VA_ARGS__) +# define expect_float_equal_(Actual, Expected, Epsilon, ...) \ + assert_impl(NORMAL, (Expected) - (Actual) <= (Epsilon) \ + && (Actual) - (Expected) <= (Epsilon), \ + __VA_ARGS__) + +# define assert_float_not_equal(...) \ + assert_float_not_equal_(__VA_ARGS__, .sentinel_ = 0) +# define expect_float_not_equal(...) \ + expect_float_not_equal_(__VA_ARGS__, .sentinel_ = 0) + +# define assert_float_not_equal_(Actual, Expected, Epsilon, ...) \ + assert_impl(FATAL, (Expected) - (Actual) > (Epsilon) \ + || (Actual) - (Expected) > (Epsilon), \ + __VA_ARGS__) +# define expect_float_not_equal_(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_equal(...) \ + assert_strings_(==, __VA_ARGS__, .sentinel_ = 0) +# define expect_strings_equal(...) \ + 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_not_equal(...) \ + assert_strings_(!=, __VA_ARGS__, .sentinel_ = 0) +# define expect_strings_not_equal(...) \ + 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_equal(...) \ + assert_arrays_equal_(__VA_ARGS__, .sentinel = 0) +# define expect_arrays_equal(...) \ + expect_arrays_equal_(__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_not_equal(...) \ + assert_arrays_not_equal_(__VA_ARGS__, .sentinel = 0) +# define expect_arrays_not_equal(...) \ + expect_arrays_not_equal_(__VA_ARGS__, .sentinel = 0) + +# define assert_arrays_equal_(A, B, Size, ...) \ + assert_impl(FATAL, !memcmp((A), (B), (Size)), __VA_ARGS__) +# define expect_arrays_equal_(A, B, Size, ...) \ + assert_impl(NORMAL, !memcmp((A), (B), (Size)), __VA_ARGS__) + +# define assert_arrays_not_equal_(A, B, Size, ...) \ + assert_impl(FATAL, memcmp((A), (B), (Size)), __VA_ARGS__) +# define expect_arrays_not_equal_(A, B, Size, ...) \ + assert_impl(NORMAL, memcmp((A), (B), (Size)), __VA_ARGS__) #endif /* !CRITERION_ASSERT_H_ */ From a8cd9fca5e1aaec376d605731cbd1541fa103f17 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Tue, 17 Mar 2015 00:14:07 +0100 Subject: [PATCH 17/31] Changed 'test framework' -> 'unit testing framework' in README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 31470a3..0657f16 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ Criterion [![License](https://img.shields.io/badge/license-MIT-blue.svg?style=flat)](https://github.com/Snaipe/Criterion/blob/master/LICENSE) [![Version](https://img.shields.io/github/tag/Snaipe/Criterion.svg?label=version&style=flat)](https://github.com/Snaipe/Criterion/releases) -A dead-simple, yet extensible, C test framework. +A dead-simple, yet extensible, C unit testing framework. ![Screencast](./doc/screencast.gif) From f075bb111bfd2f52c5b62f06180f3cea994db20d Mon Sep 17 00:00:00 2001 From: Snaipe Date: Tue, 17 Mar 2015 00:22:06 +0100 Subject: [PATCH 18/31] Changed prototype of criterion_run_all_tests --- src/main.c | 2 +- src/runner.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main.c b/src/main.c index 3c5f26e..a240396 100644 --- a/src/main.c +++ b/src/main.c @@ -44,5 +44,5 @@ int main(int argc, char *argv[]) { } } - return criterion_run_all_tests(); + return !criterion_run_all_tests(); } diff --git a/src/runner.c b/src/runner.c index cc749ba..50088e7 100644 --- a/src/runner.c +++ b/src/runner.c @@ -152,7 +152,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 +160,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; } From 99d84d8009131c942bf0b483b18a2f10b65d232c Mon Sep 17 00:00:00 2001 From: Snaipe Date: Tue, 17 Mar 2015 00:26:19 +0100 Subject: [PATCH 19/31] Fixed --no-early-exit behavior being inverted --- src/process.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/process.c b/src/process.c index ffc971e..f7048a6 100644 --- a/src/process.c +++ b/src/process.c @@ -71,7 +71,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); From a939356f2e5ef08db5cece752ee245908a01d05d Mon Sep 17 00:00:00 2001 From: Snaipe Date: Tue, 17 Mar 2015 00:56:33 +0100 Subject: [PATCH 20/31] Cleaned up includes --- include/criterion/event.h | 2 ++ include/criterion/options.h | 1 + include/criterion/stats.h | 1 + src/event.c | 5 ----- src/main.c | 1 - src/process.c | 2 -- src/process.h | 2 ++ src/runner.c | 2 -- 8 files changed, 6 insertions(+), 10 deletions(-) diff --git a/include/criterion/event.h b/include/criterion/event.h index 37080ee..75f4a7c 100644 --- a/include/criterion/event.h +++ b/include/criterion/event.h @@ -24,6 +24,8 @@ #ifndef CRITERION_EVENT_H_ # define CRITERION_EVENT_H_ +# include + extern int EVENT_PIPE; void send_event(int kind, void *data, size_t size); diff --git a/include/criterion/options.h b/include/criterion/options.h index 2d24fb5..d04db21 100644 --- a/include/criterion/options.h +++ b/include/criterion/options.h @@ -24,6 +24,7 @@ #ifndef CRITERION_OPTIONS_H_ # define CRITERION_OPTIONS_H_ +# include # include "logging.h" struct criterion_options { diff --git a/include/criterion/stats.h b/include/criterion/stats.h index c836cbe..03600db 100644 --- a/include/criterion/stats.h +++ b/include/criterion/stats.h @@ -25,6 +25,7 @@ # define CRITERION_STATS_H_ # include +# include # include "criterion.h" struct criterion_assert_stats { diff --git a/src/event.c b/src/event.c index 0e569d7..19ca42d 100644 --- a/src/event.c +++ b/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 #include -#include #include -#include "criterion/criterion.h" #include "criterion/stats.h" #include "criterion/hooks.h" #include "event.h" diff --git a/src/main.c b/src/main.c index a240396..ad350c0 100644 --- a/src/main.c +++ b/src/main.c @@ -1,6 +1,5 @@ #define _GNU_SOURCE #include -#include #include #include #include diff --git a/src/process.c b/src/process.c index f7048a6..17ef862 100644 --- a/src/process.c +++ b/src/process.c @@ -22,9 +22,7 @@ * THE SOFTWARE. */ #include -#include #include -#include #include #include diff --git a/src/process.h b/src/process.h index fcf9e62..712648c 100644 --- a/src/process.h +++ b/src/process.h @@ -24,6 +24,8 @@ #ifndef PROCESS_H_ # define PROCESS_H_ +# include + struct process; enum status_kind { diff --git a/src/runner.c b/src/runner.c index 50088e7..2fd63f8 100644 --- a/src/runner.c +++ b/src/runner.c @@ -24,9 +24,7 @@ #include #include #include -#include #include -#include "criterion/assert.h" #include "criterion/options.h" #include "stats.h" #include "runner.h" From 96c05610cc78b50f9e48ac44e79ad44462ca5221 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Tue, 17 Mar 2015 01:06:41 +0100 Subject: [PATCH 21/31] Display test logs after build --- .travis.yml | 2 +- appveyor.yml | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 7d2629c..95ce90a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -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 diff --git a/appveyor.yml b/appveyor.yml index bffb175..e1e4acc 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -60,6 +60,9 @@ build_script: test_script: - '%CYG_BASH% -lc "cd $APPVEYOR_BUILD_FOLDER; exec 0 Date: Sat, 7 Feb 2015 14:22:08 +0100 Subject: [PATCH 22/31] [Issue #1] Added time measurements --- include/criterion/stats.h | 1 + src/event.c | 24 +++++++++++++++++------- src/runner.c | 11 +++++++++-- src/stats.c | 3 ++- 4 files changed, 29 insertions(+), 10 deletions(-) diff --git a/include/criterion/stats.h b/include/criterion/stats.h index 03600db..2225896 100644 --- a/include/criterion/stats.h +++ b/include/criterion/stats.h @@ -46,6 +46,7 @@ struct criterion_test_stats { int passed_asserts; int failed_asserts; int signal; + float elapsed_time; unsigned progress; const char *file; diff --git a/src/event.c b/src/event.c index 19ca42d..d77709a 100644 --- a/src/event.c +++ b/src/event.c @@ -40,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: { + float *elapsed_time = malloc(sizeof (float)); + if (read(fd, elapsed_time, sizeof (float)) < (ssize_t) sizeof (float)) + 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) { diff --git a/src/runner.c b/src/runner.c index 2fd63f8..2f51512 100644 --- a/src/runner.c +++ b/src/runner.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include "criterion/options.h" #include "stats.h" @@ -87,8 +88,13 @@ 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); + + clock_t before = clock(); (test->test ?: nothing)(); - send_event(POST_TEST, NULL, 0); + clock_t after = clock(); + + double elapsed_time = (double) (after - before) / CLOCKS_PER_SEC; + send_event(POST_TEST, &elapsed_time, sizeof (double)); (test->data->fini ?: nothing)(); send_event(POST_FINI, NULL, 0); } @@ -124,7 +130,8 @@ 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); diff --git a/src/stats.c b/src/stats.c index e12db58..ba5a2ed 100644 --- a/src/stats.c +++ b/src/stats.c @@ -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) { + float *ptr) { + test->elapsed_time = *ptr; if (test->failed_asserts > 0 || test->signal != test->test->data->signal) { test->failed = 1; ++stats->tests_failed; From 4a5c19a08c2fb393d0ccb992ef26f8f6f4784700 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Mon, 16 Mar 2015 23:32:03 +0100 Subject: [PATCH 23/31] Added monotonic cross-platform timer --- Makefile.am | 1 + src/event.c | 4 +-- src/report.c | 14 +++++++--- src/runner.c | 12 ++++---- src/stats.c | 2 +- src/timer.c | 79 ++++++++++++++++++++++++++++++++++++++++++++++++++++ src/timer.h | 17 +++++++++++ 7 files changed, 117 insertions(+), 12 deletions(-) create mode 100644 src/timer.c create mode 100644 src/timer.h diff --git a/Makefile.am b/Makefile.am index f373ec2..9e4c7bd 100644 --- a/Makefile.am +++ b/Makefile.am @@ -45,4 +45,5 @@ libcriterion_la_SOURCES = \ src/stats.h \ src/logging.c \ src/options.c \ + src/timer.c \ src/main.c diff --git a/src/event.c b/src/event.c index d77709a..e5df964 100644 --- a/src/event.c +++ b/src/event.c @@ -50,8 +50,8 @@ struct event *read_event(int fd) { return unique_ptr(struct event, ({ .kind = kind, .data = buf }), destroy_event); } case POST_TEST: { - float *elapsed_time = malloc(sizeof (float)); - if (read(fd, elapsed_time, sizeof (float)) < (ssize_t) sizeof (float)) + 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 = elapsed_time }), destroy_event); diff --git a/src/report.c b/src/report.c index fc07f03..e135732 100644 --- a/src/report.c +++ b/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 " SIZE_T_FORMAT " - %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); } } diff --git a/src/runner.c b/src/runner.c index 2f51512..0572c6c 100644 --- a/src/runner.c +++ b/src/runner.c @@ -24,7 +24,6 @@ #include #include #include -#include #include #include "criterion/options.h" #include "stats.h" @@ -32,6 +31,7 @@ #include "report.h" #include "event.h" #include "process.h" +#include "timer.h" IMPL_SECTION_LIMITS(struct criterion_test, criterion_tests); @@ -89,11 +89,13 @@ static void run_test_child(struct criterion_test *test) { (test->data->init ?: nothing)(); send_event(PRE_TEST, NULL, 0); - clock_t before = clock(); + struct timespec_compat ts; + timer_start(&ts); (test->test ?: nothing)(); - clock_t after = clock(); + double elapsed_time; + if (!timer_end(&elapsed_time, &ts)) + elapsed_time = -1; - double elapsed_time = (double) (after - before) / CLOCKS_PER_SEC; send_event(POST_TEST, &elapsed_time, sizeof (double)); (test->data->fini ?: nothing)(); send_event(POST_FINI, NULL, 0); @@ -135,7 +137,7 @@ static void run_test(struct criterion_global_stats *stats, struct criterion_test 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); } diff --git a/src/stats.c b/src/stats.c index ba5a2ed..4c33793 100644 --- a/src/stats.c +++ b/src/stats.c @@ -114,7 +114,7 @@ static void push_assert(s_glob_stats *stats, static void push_post_test(s_glob_stats *stats, s_test_stats *test, - float *ptr) { + double *ptr) { test->elapsed_time = *ptr; if (test->failed_asserts > 0 || test->signal != test->test->data->signal) { test->failed = 1; diff --git a/src/timer.c b/src/timer.c new file mode 100644 index 0000000..67939ad --- /dev/null +++ b/src/timer.c @@ -0,0 +1,79 @@ +#include +#include "timer.h" + +#define GIGA 1e9 + +#if defined(__unix__) + +# 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 +# include +#elif defined(_WIN32) +# define VC_EXTRALEAN +# define WIN32_LEAN_AND_MEAN +# include +#endif + +bool can_measure_time(void) { +#ifdef __unix__ + 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) + LARGE_INTEGER freq, count; + if (!QueryPerformanceFrequency(&freq) + || !QueryPerformanceCounter(&count)) + return -1; + + *ts = (struct timespec_compat) { count / freq, count * (GIGA - 1) / freq }; + 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) / GIGA; + return 1; +} diff --git a/src/timer.h b/src/timer.h new file mode 100644 index 0000000..2d334cb --- /dev/null +++ b/src/timer.h @@ -0,0 +1,17 @@ +#ifndef TIMER_H_ +# define TIMER_H_ + +# include +# include +# include + +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_ */ From a52010c6845400b1e26714afa0eb9de34d3839d2 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Tue, 17 Mar 2015 14:53:41 +0100 Subject: [PATCH 24/31] Updated csptr to latest --- dependencies/csptr | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencies/csptr b/dependencies/csptr index 30b3380..3b6b26f 160000 --- a/dependencies/csptr +++ b/dependencies/csptr @@ -1 +1 @@ -Subproject commit 30b3380a9aee3c49a2206d2cced12a6adf26469b +Subproject commit 3b6b26f8b3464a70cc76628e4b65b776a7760ba4 From 56ff31b13501cfee8aa256d72fbfb1b4f58e57df Mon Sep 17 00:00:00 2001 From: Snaipe Date: Tue, 17 Mar 2015 14:59:25 +0100 Subject: [PATCH 25/31] Fixed make distcheck not distributing test scripts --- samples/Makefile.am | 2 ++ 1 file changed, 2 insertions(+) diff --git a/samples/Makefile.am b/samples/Makefile.am index ba6868c..6660f1c 100644 --- a/samples/Makefile.am +++ b/samples/Makefile.am @@ -17,6 +17,8 @@ SCRIPT_TESTS = tests/tap_test.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 From 547bd032d22e77b3a4ab610b57b34c85bce7915a Mon Sep 17 00:00:00 2001 From: Snaipe Date: Tue, 17 Mar 2015 16:11:32 +0100 Subject: [PATCH 26/31] Renamed equal asserts, added asserts sample in README, added abort_test --- README.md | 2 ++ doc/starter.rst | 16 ++++----- include/criterion/assert.h | 70 +++++++++++++++++++++----------------- samples/asserts.c | 21 ++++++++---- 4 files changed, 63 insertions(+), 46 deletions(-) diff --git a/README.md b/README.md index 0657f16..ac9d5b7 100644 --- a/README.md +++ b/README.md @@ -52,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] @@ -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 diff --git a/doc/starter.rst b/doc/starter.rst index 54e3819..b974bdd 100644 --- a/doc/starter.rst +++ b/doc/starter.rst @@ -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 -------- diff --git a/include/criterion/assert.h b/include/criterion/assert.h index 75e3c61..9f2e7cd 100644 --- a/include/criterion/assert.h +++ b/include/criterion/assert.h @@ -65,6 +65,12 @@ struct criterion_assert_args { // Common asserts +# define abort_test(Message) \ + assert(0, \ + .default_msg = "The conditions for this test were not met.", \ + .msg = (Message) \ + ) + # define assert(...) assert_(__VA_ARGS__, .sentinel_ = 0) # define expect(...) expect_(__VA_ARGS__, .sentinel_ = 0) @@ -86,11 +92,11 @@ struct criterion_assert_args { # define expect_op_(Op, Actual, Expected, ...) \ assert_impl(NORMAL, (Actual) Op (Expected), __VA_ARGS__) -# define assert_equal(...) assert_op_(==, __VA_ARGS__, .sentinel_ = 0) -# define expect_equal(...) expect_op_(==, __VA_ARGS__, .sentinel_ = 0) +# define assert_eq(...) assert_op_(==, __VA_ARGS__, .sentinel_ = 0) +# define expect_eq(...) expect_op_(==, __VA_ARGS__, .sentinel_ = 0) -# define assert_not_equal(...) assert_op_(!=, __VA_ARGS__, .sentinel_ = 0) -# define expect_not_equal(...) expect_op_(!=, __VA_ARGS__, .sentinel_ = 0) +# define assert_neq(...) assert_op_(!=, __VA_ARGS__, .sentinel_ = 0) +# define expect_neq(...) expect_op_(!=, __VA_ARGS__, .sentinel_ = 0) # define assert_lt(...) assert_op_(<, __VA_ARGS__, .sentinel_ = 0) # define expect_lt(...) expect_op_(<, __VA_ARGS__, .sentinel_ = 0) @@ -106,30 +112,30 @@ struct criterion_assert_args { // Floating-point asserts -# define assert_float_equal(...) \ - assert_float_equal_(__VA_ARGS__, .sentinel_ = 0) -# define expect_float_equal(...) \ - expect_float_equal_(__VA_ARGS__, .sentinel_ = 0) +# 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_equal_(Actual, Expected, Epsilon, ...) \ +# define assert_float_eq_(Actual, Expected, Epsilon, ...) \ assert_impl(FATAL, (Expected) - (Actual) <= (Epsilon) \ && (Actual) - (Expected) <= (Epsilon), \ __VA_ARGS__) -# define expect_float_equal_(Actual, Expected, Epsilon, ...) \ +# define expect_float_eq_(Actual, Expected, Epsilon, ...) \ assert_impl(NORMAL, (Expected) - (Actual) <= (Epsilon) \ && (Actual) - (Expected) <= (Epsilon), \ __VA_ARGS__) -# define assert_float_not_equal(...) \ - assert_float_not_equal_(__VA_ARGS__, .sentinel_ = 0) -# define expect_float_not_equal(...) \ - expect_float_not_equal_(__VA_ARGS__, .sentinel_ = 0) +# 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_not_equal_(Actual, Expected, Epsilon, ...) \ +# define assert_float_neq_(Actual, Expected, Epsilon, ...) \ assert_impl(FATAL, (Expected) - (Actual) > (Epsilon) \ || (Actual) - (Expected) > (Epsilon), \ __VA_ARGS__) -# define expect_float_not_equal_(Actual, Expected, Epsilon, ...) \ +# define expect_float_neq_(Actual, Expected, Epsilon, ...) \ assert_impl(NORMAL, (Expected) - (Actual) > (Epsilon) \ || (Actual) - (Expected) > (Epsilon), \ __VA_ARGS__) @@ -141,14 +147,14 @@ struct criterion_assert_args { # define expect_strings_(Op, Actual, Expected, ...) \ assert_impl(NORMAL, strcmp((Actual), (Expected)) Op 0, __VA_ARGS__) -# define assert_strings_equal(...) \ +# define assert_strings_eq(...) \ assert_strings_(==, __VA_ARGS__, .sentinel_ = 0) -# define expect_strings_equal(...) \ +# define expect_strings_eq(...) \ expect_strings_(==, __VA_ARGS__, .sentinel_ = 0) -# define assert_strings_not_equal(...) \ +# define assert_strings_neq(...) \ assert_strings_(!=, __VA_ARGS__, .sentinel_ = 0) -# define expect_strings_not_equal(...) \ +# define expect_strings_neq(...) \ expect_strings_(!=, __VA_ARGS__, .sentinel_ = 0) # define assert_strings_gt(...) assert_strings_(>, __VA_ARGS__, .sentinel_ = 0) @@ -165,24 +171,24 @@ struct criterion_assert_args { // Array asserts -# define assert_arrays_equal(...) \ - assert_arrays_equal_(__VA_ARGS__, .sentinel = 0) -# define expect_arrays_equal(...) \ - expect_arrays_equal_(__VA_ARGS__, .sentinel = 0) +# 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(...) \ - assert_arrays_not_equal_(__VA_ARGS__, .sentinel = 0) -# define expect_arrays_not_equal(...) \ - expect_arrays_not_equal_(__VA_ARGS__, .sentinel = 0) +# 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_equal_(A, B, Size, ...) \ +# define assert_arrays_eq_(A, B, Size, ...) \ assert_impl(FATAL, !memcmp((A), (B), (Size)), __VA_ARGS__) -# define expect_arrays_equal_(A, B, Size, ...) \ +# define expect_arrays_eq_(A, B, Size, ...) \ assert_impl(NORMAL, !memcmp((A), (B), (Size)), __VA_ARGS__) -# define assert_arrays_not_equal_(A, B, Size, ...) \ +# define assert_arrays_neq_(A, B, Size, ...) \ assert_impl(FATAL, memcmp((A), (B), (Size)), __VA_ARGS__) -# define expect_arrays_not_equal_(A, B, Size, ...) \ +# define expect_arrays_neq_(A, B, Size, ...) \ assert_impl(NORMAL, memcmp((A), (B), (Size)), __VA_ARGS__) #endif /* !CRITERION_ASSERT_H_ */ diff --git a/samples/asserts.c b/samples/asserts.c index deec0b4..811824f 100644 --- a/samples/asserts.c +++ b/samples/asserts.c @@ -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); } From 098eabb7e75d746c7ef87566f6bede341d507926 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Tue, 17 Mar 2015 23:16:30 +0100 Subject: [PATCH 27/31] Fixed test timing on windows --- src/timer.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/src/timer.c b/src/timer.c index 67939ad..8e41f14 100644 --- a/src/timer.c +++ b/src/timer.c @@ -1,9 +1,10 @@ #include +#include #include "timer.h" -#define GIGA 1e9 +#define GIGA 1000000000 -#if defined(__unix__) +#if defined(__unix__) && !defined(__CYGWIN__) # ifdef CLOCK_MONOTONIC_RAW # define CLOCK CLOCK_MONOTONIC_RAW @@ -16,14 +17,14 @@ extern __attribute__ ((weak)) int clock_gettime(clockid_t, struct timespec *); #elif defined(__APPLE__) # include # include -#elif defined(_WIN32) +#elif defined(_WIN32) || defined(__CYGWIN__) # define VC_EXTRALEAN # define WIN32_LEAN_AND_MEAN # include #endif bool can_measure_time(void) { -#ifdef __unix__ +#if defined(__unix__) && !defined(__CYGWIN__) return clock_gettime != NULL; #else return true; @@ -41,13 +42,16 @@ int gettime_compat(struct timespec_compat *ts) { *ts = (struct timespec_compat) { mts->tv_sec, mts->tv_nsec }; return res > 0 ? -1 : 0; -#elif defined(_WIN32) +#elif defined(_WIN32) || defined(__CYGWIN__) LARGE_INTEGER freq, count; if (!QueryPerformanceFrequency(&freq) || !QueryPerformanceCounter(&count)) return -1; - *ts = (struct timespec_compat) { count / freq, count * (GIGA - 1) / freq }; + 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()) { @@ -74,6 +78,6 @@ int timer_end(double *time, struct timespec_compat *state) { if (gettime_compat(&last) == -1) return 0; - *time = (last.tv_sec - state->tv_sec) + (last.tv_nsec - state->tv_nsec) / GIGA; + *time = (last.tv_sec - state->tv_sec) + (last.tv_nsec - state->tv_nsec) / (double) GIGA; return 1; } From 73eae59b056a829670838877960b441d13212777 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Tue, 17 Mar 2015 17:50:01 +0100 Subject: [PATCH 28/31] Fixed compile error on OS X timers --- src/timer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/timer.c b/src/timer.c index 8e41f14..edb181e 100644 --- a/src/timer.c +++ b/src/timer.c @@ -40,7 +40,7 @@ int gettime_compat(struct timespec_compat *ts) { int res = clock_get_time(cclock, &mts); mach_port_deallocate(mach_task_self(), cclock); - *ts = (struct timespec_compat) { mts->tv_sec, mts->tv_nsec }; + *ts = (struct timespec_compat) { mts.tv_sec, mts.tv_nsec }; return res > 0 ? -1 : 0; #elif defined(_WIN32) || defined(__CYGWIN__) LARGE_INTEGER freq, count; From 1bdcd412dfb93c9678940285ed02b5dba86827fa Mon Sep 17 00:00:00 2001 From: Snaipe Date: Tue, 17 Mar 2015 23:45:21 +0100 Subject: [PATCH 29/31] Fixed appveyor version format --- appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index e1e4acc..92dd21f 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,4 +1,4 @@ -version: 0.3.0.{build}-{branch} +version: 0.3.0_b{build}-{branch} os: Windows Server 2012 From 05bc6fb88ec155f34499cdab327b956da0dbedd3 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Tue, 17 Mar 2015 23:50:37 +0100 Subject: [PATCH 30/31] Fixed timer header not being distributed --- Makefile.am | 1 + 1 file changed, 1 insertion(+) diff --git a/Makefile.am b/Makefile.am index 9e4c7bd..371c649 100644 --- a/Makefile.am +++ b/Makefile.am @@ -46,4 +46,5 @@ libcriterion_la_SOURCES = \ src/logging.c \ src/options.c \ src/timer.c \ + src/timer.h \ src/main.c From b14c56f28991612da883f1211a3ee61d16cc3620 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Tue, 17 Mar 2015 23:56:16 +0100 Subject: [PATCH 31/31] Bumping version to 1.0.0 --- appveyor.yml | 2 +- configure.ac | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 92dd21f..5ef46fa 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,4 +1,4 @@ -version: 0.3.0_b{build}-{branch} +version: 1.0.0_b{build}-{branch} os: Windows Server 2012 diff --git a/configure.ac b/configure.ac index e141d59..d095e15 100644 --- a/configure.ac +++ b/configure.ac @@ -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])