diff --git a/.bumpversion.cfg b/.bumpversion.cfg index 654fcff..a3c3c42 100644 --- a/.bumpversion.cfg +++ b/.bumpversion.cfg @@ -1,5 +1,5 @@ [bumpversion] -current_version = 1.3.0 +current_version = 1.3.1 commit = True [bumpversion:file:CMakeLists.txt] diff --git a/.cmake/Modules/CoverallsGenerateGcov.cmake b/.cmake/Modules/CoverallsGenerateGcov.cmake index 429b695..b923f6e 100644 --- a/.cmake/Modules/CoverallsGenerateGcov.cmake +++ b/.cmake/Modules/CoverallsGenerateGcov.cmake @@ -268,8 +268,17 @@ foreach (GCOV_FILE ${ALL_GCOV_FILES}) endforeach() # TODO: Enable setting these -set(JSON_SERVICE_NAME "travis-ci") -set(JSON_SERVICE_JOB_ID $ENV{TRAVIS_JOB_ID}) +if (NOT DEFINED ENV{CI_NAME}) + set(JSON_SERVICE_NAME "travis-ci") +else () + set(JSON_SERVICE_NAME $ENV{CI_NAME}) +endif() + +if (NOT DEFINED ENV{CI_JOB_ID}) + set(JSON_SERVICE_JOB_ID $ENV{TRAVIS_JOB_ID}) +else () + set(JSON_SERVICE_JOB_ID $ENV{CI_JOB_ID}) +endif() set(JSON_REPO_TOKEN $ENV{COVERALLS_REPO_TOKEN}) set(JSON_TEMPLATE diff --git a/.gitignore b/.gitignore index 48d1edb..8dd4a19 100644 --- a/.gitignore +++ b/.gitignore @@ -9,6 +9,7 @@ !*.rst !samples/tests/*.sh !*.po +!samples/*.expected !LICENSE !HEADER diff --git a/.travis.yml b/.travis.yml index 010eab6..4df2cb7 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,24 +1,39 @@ language: c +os: +- linux +- osx compiler: - gcc sudo: false -addons: - apt: - packages: - - check - - gettext - - cmake before_install: - export LOCAL_INSTALL="$HOME" - ".ci/install-libcsptr.sh" - export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$HOME/lib - export CFLAGS="-g -O0" script: -- mkdir -p build && cd $_ && cmake -DCOVERALLS=ON -DCMAKE_BUILD_TYPE=Debug -DCMAKE_PREFIX_PATH=$HOME .. && make && make test +- mkdir -p build +- cd build +- cmake -DCOVERALLS=ON -DCMAKE_BUILD_TYPE=Debug -DCMAKE_PREFIX_PATH=$HOME -DCMAKE_INSTALL_PREFIX=criterion-${TRAVIS_TAG} .. +- make +- make test after_success: - make coveralls after_failure: -- cat Testing/Temporary/LastTest.log +- cat Testing/Temporary/LastTest.log samples/*.{out,err} ../samples/tests/*.{out,err} env: global: secure: bzZcWjdqoTgceC40kEBucx7NuWYJPk+rxgF3UJJDXi+ijQAFYPv70p5eVsGR6rfc+XgqXCxcUFQtuL4ZVt7QEfVk1ZOJITNeHbKIeKaEYS4nX8mFf+CBeEm9bJGZ04KiQJdJu5mzzAHvXbW7roGXDGWe1Bjnk5wwA+dNUCa7H04= + +before_deploy: +- make install +- tar -cvjf criterion-${TRAVIS_TAG}-${TRAVIS_OS_NAME}-x86_64.tar.bz2 criterion-${TRAVIS_TAG} + +deploy: + provider: releases + skip_cleanup: true + api_key: + secure: d3l2Ohb2FF3tSXku1d0ASR5dntdnQ48Jyc39IEloDBxFXCselCkYruUQv6p0TA3P+Dmrz4wS7/AFlBMMsQ3XfGFVIOnITiTaGWg5fEpIf7zYsDf0zECPE0MOHMGqJMn3/SrSKdtEA4N84Q4JS7Ou+ewG65mxUDO5Ce60OoEG5JA= + file: criterion-${TRAVIS_TAG}-${TRAVIS_OS_NAME}-x86_64.tar.bz2 + on: + repo: Snaipe/Criterion + tags: true diff --git a/CMakeLists.txt b/CMakeLists.txt index da1994c..5b8ad20 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -7,15 +7,18 @@ project(Criterion C) enable_testing() add_subdirectory(samples) -set(PROJECT_VERSION "1.3.0") +set(PROJECT_VERSION "1.3.1") set(LOCALEDIR ${CMAKE_INSTALL_PREFIX}/share/locale) -set(GettextTranslate_ALL) -set(GettextTranslate_GMO_BINARY) +set(GettextTranslate_ALL 1) +set(GettextTranslate_GMO_BINARY 1) set(MODULE_DIR "${CMAKE_SOURCE_DIR}/.cmake/Modules") set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${MODULE_DIR}) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Werror -g -std=gnu99") -set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,-no-undefined") + +if (WIN32) + set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,-no-undefined") +endif() # Setup coveralls diff --git a/ChangeLog b/ChangeLog index afba940..514345a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2015-08-20 Franklin "Snaipe" Mathieu + + * criterion: version 1.3.1 + * Fixed OS X and Windows section iterations + * Fixed report hooks not working on OS X and Windows + * Fixed duplicated output when writing in PRE_ALL to a redirected stdout/err + * Added -S switch to display filenames in their short version + 2015-08-05 Franklin "Snaipe" Mathieu * criterion: version 1.3.0 diff --git a/README.md b/README.md index ac6f1e7..b68c6c1 100644 --- a/README.md +++ b/README.md @@ -35,10 +35,9 @@ the user would have with other frameworks: ## Downloads -* [Linux (x86_64)](https://github.com/Snaipe/Criterion/releases/download/v1.3.0/criterion-1.3.0-linux-x86_64.tar.bz2) -* [OS X (x86_64)](https://github.com/Snaipe/Criterion/releases/download/v1.3.0/criterion-1.3.0-osx-x86_64.tar.bz2) -* [FreeBSD (x86_64)](https://github.com/Snaipe/Criterion/releases/download/v1.3.0/criterion-1.3.0-freebsd-x86_64.tar.bz2) -* [Windows (x86_64)](https://github.com/Snaipe/Criterion/releases/download/v1.3.0/criterion-1.3.0-windows-x86_64.tar.bz2) +* [Linux (x86_64)](https://github.com/Snaipe/Criterion/releases/download/v1.3.1/criterion-1.3.1-linux-x86_64.tar.bz2) +* [OS X (x86_64)](https://github.com/Snaipe/Criterion/releases/download/v1.3.1/criterion-1.3.1-osx-x86_64.tar.bz2) +* [Windows (x86)](https://github.com/Snaipe/Criterion/releases/download/v1.3.1/criterion-1.3.1-windows-x86.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) diff --git a/appveyor.yml b/appveyor.yml index ae1ca2b..1f74e15 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,4 +1,4 @@ -version: 1.3.0_b{build}-{branch} +version: 1.3.1_b{build}-{branch} os: Windows Server 2012 @@ -9,6 +9,10 @@ init: environment: COVERALLS_REPO_TOKEN: secure: 5nuCg+faxFPeppoNNcSwVobswAVFUf8ut83vw8CX/4W2y0kZkGmwEfCUxSQWiQDU + CI_NAME: appveyor + CI_JOB_ID: $(APPVEYOR_JOB_ID) + LOCAL_INSTALL: $(APPVEYOR_BUILD_FOLDER) + GCOV_PREFIX: $(APPVEYOR_BUILD_FOLDER) clone_depth: 5 @@ -16,20 +20,28 @@ matrix: fast_finish: true # set this flag to immediately finish build once one of the jobs fails. platform: - - x86 + - x86_64 configuration: Release install: - - 'set GCOV_PREFIX=%APPVEYOR_BUILD_FOLDER%' - - 'set LOCAL_INSTALL=%APPVEYOR_BUILD_FOLDER%' - - 'bash -lc "cd $APPVEYOR_BUILD_FOLDER; exec 0 + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ #ifndef CRITERION_H_ # define CRITERION_H_ diff --git a/include/criterion/options.h b/include/criterion/options.h index 3e2dee6..31b90d2 100644 --- a/include/criterion/options.h +++ b/include/criterion/options.h @@ -35,6 +35,7 @@ struct criterion_options { bool use_ascii; bool fail_fast; const char *pattern; + bool short_filename; }; extern struct criterion_options criterion_options; diff --git a/po/Makevars b/po/Makevars index 036417c..81da661 100644 --- a/po/Makevars +++ b/po/Makevars @@ -8,7 +8,7 @@ subdir = po top_builddir = .. # These options get passed to xgettext. -XGETTEXT_OPTIONS = --keyword=_ --keyword=N_ +XGETTEXT_OPTIONS = --keyword=_ --keyword=N_ --keyword=N_s:1,2 --keyword=_s:1,2 # This is the copyright holder that gets inserted into the header of the # $(DOMAIN).pot file. Set this to the copyright holder of the surrounding @@ -41,7 +41,7 @@ PACKAGE_GNU = no # It can be your email address, or a mailing list address where translators # can write to without being subscribed, or the URL of a web page through # which the translators can contact you. -MSGID_BUGS_ADDRESS = +MSGID_BUGS_ADDRESS = franklinmathieu+criterion@gmail.com # This is the list of locale categories, beyond LC_MESSAGES, for which the # message catalogs shall be used. It is usually empty. diff --git a/po/fr.po b/po/fr.po index 7727e40..af25ab8 100644 --- a/po/fr.po +++ b/po/fr.po @@ -7,8 +7,8 @@ msgid "" msgstr "" "Project-Id-Version: criterion 1.0.0\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2015-07-28 22:17+0200\n" +"Report-Msgid-Bugs-To: franklinmathieu+criterion@gmail.com\n" +"POT-Creation-Date: 2015-08-05 11:37+0200\n" "PO-Revision-Date: 2015-04-03 17:58+0200\n" "Last-Translator: \n" "Language-Team: French\n" @@ -18,58 +18,54 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n" -#: src/log/normal.c:38 +#: src/log/normal.c:51 #, c-format msgid "Criterion v%s\n" msgstr "Criterion v%s\n" -#: src/log/normal.c:42 -#, c-format -msgid "%1$s::%2$s\n" -msgstr "%1$s::%2$s\n" - -#: src/log/normal.c:47 src/log/normal.c:121 +#: src/log/normal.c:52 #, c-format msgid " %s\n" msgstr " %s\n" -#: src/log/normal.c:76 +#: src/log/normal.c:55 src/log/normal.c:57 +#, c-format +msgid "%1$s::%2$s\n" +msgstr "%1$s::%2$s\n" + +#: src/log/normal.c:56 +#, fuzzy, c-format +msgid "%1$s::%2$s: (%3$3.2fs)\n" +msgstr "%1$s::%2$s: (%3$3.2fs)\n" + +#: src/log/normal.c:58 #, c-format msgid "%1$s::%2$s: Test is disabled\n" msgstr "%1$s::%2$s: Le test est désactivé\n" -#: src/log/normal.c:77 +#: src/log/normal.c:59 #, c-format msgid "%1$s::%2$s: Suite is disabled\n" msgstr "%1$s::%2$s: La suite est désactivée\n" -#: src/log/normal.c:94 -#, c-format -msgid "" -"%1$sSynthesis: Tested: %2$s%3$lu%4$s | Passing: %5$s%6$lu%7$s | Failing: %8$s" -"%9$lu%10$s | Crashing: %11$s%12$lu%13$s %14$s\n" -msgstr "" -"%1$sSynthèse: Testés: %2$s%3$lu%4$s | Validés: %5$s%6$lu%7$s | Échoués: %8$s" -"%9$lu%10$s | Plantages: %11$s%12$lu%13$s %14$s\n" - -#: src/log/normal.c:115 +#: src/log/normal.c:60 #, c-format msgid "%1$s%2$s%3$s:%4$s%5$d%6$s: Assertion failed: %7$s\n" msgstr "%1$s%2$s%3$s:%4$s%5$d%6$s: Échec d'assertion: %7$s\n" -#: src/log/normal.c:128 +#: src/log/normal.c:61 #, c-format msgid "%1$s%2$s%3$s:%4$s%5$u%6$s: Unexpected signal caught below this line!\n" msgstr "" "%1$s%2$s%3$s:%4$s%5$u%6$s: Un signal inattendu a été reçu après cette " "ligne!\n" -#: src/log/normal.c:132 +#: src/log/normal.c:62 #, c-format msgid "%1$s::%2$s: CRASH!\n" msgstr "%1$s::%2$s: PLANTAGE!\n" -#: src/log/normal.c:139 +#: src/log/normal.c:63 #, fuzzy, c-format msgid "" "%1$sWarning! The test `%2$s::%3$s` crashed during its setup or teardown." @@ -77,3 +73,19 @@ msgid "" msgstr "" "%1$sAttention! Le test `%2$s::%3$s` a planté pendant son initialisation ou " "sa finalisation.%4$s\n" + +#: src/log/normal.c:64 +#, c-format +msgid "Running %1$s%2$lu%3$s test from %4$s%5$s%6$s:\n" +msgid_plural "Running %1$s%2$lu%3$s tests from %4$s%5$s%6$s:\n" +msgstr[0] "Lancement de %1$s%2$lu%3$s test dans %4$s%5$s%6$s:\n" +msgstr[1] "Lancement de %1$s%2$lu%3$s tests dans %4$s%5$s%6$s:\n" + +#: src/log/normal.c:66 +#, c-format +msgid "" +"%1$sSynthesis: Tested: %2$s%3$lu%4$s | Passing: %5$s%6$lu%7$s | Failing: %8$s" +"%9$lu%10$s | Crashing: %11$s%12$lu%13$s %14$s\n" +msgstr "" +"%1$sSynthèse: Testés: %2$s%3$lu%4$s | Validés: %5$s%6$lu%7$s | Échoués: %8$s" +"%9$lu%10$s | Plantages: %11$s%12$lu%13$s %14$s\n" diff --git a/samples/CMakeLists.txt b/samples/CMakeLists.txt index 206c049..4f928b2 100644 --- a/samples/CMakeLists.txt +++ b/samples/CMakeLists.txt @@ -34,6 +34,13 @@ foreach(sample ${SAMPLES}) set_property(TEST ${sample} PROPERTY ENVIRONMENT "CRITERION_ALWAYS_SUCCEED=1" ) + + add_test(${sample}_compare sh ${CMAKE_CURRENT_LIST_DIR}/tests/run_test.sh "${CMAKE_CURRENT_LIST_DIR}" . . ${sample}) + set_property(TEST ${sample}_compare PROPERTY + ENVIRONMENT "LC_ALL=en_US.utf8" + ENVIRONMENT "CRITERION_ALWAYS_SUCCEED=1" + ENVIRONMENT "CRITERION_SHORT_FILENAME=1" + ) endforeach() foreach(script ${SCRIPTS}) @@ -41,4 +48,11 @@ foreach(script ${SCRIPTS}) set_property(TEST ${script} PROPERTY ENVIRONMENT "CRITERION_ALWAYS_SUCCEED=1" ) + + add_test(${script}_compare sh ${CMAKE_CURRENT_LIST_DIR}/tests/run_test.sh "${CMAKE_CURRENT_LIST_DIR}" . "${CMAKE_CURRENT_LIST_DIR}" tests/${sample}) + set_property(TEST ${script}_compare PROPERTY + ENVIRONMENT "LC_ALL=en_US.utf8" + ENVIRONMENT "CRITERION_ALWAYS_SUCCEED=1" + ENVIRONMENT "CRITERION_SHORT_FILENAME=1" + ) endforeach() diff --git a/samples/asserts.err.expected b/samples/asserts.err.expected new file mode 100644 index 0000000..644a440 --- /dev/null +++ b/samples/asserts.err.expected @@ -0,0 +1,6 @@ +[----] asserts.c:11: Assertion failed: assert is fatal, expect isn't +[----] asserts.c:12: Assertion failed: This assert runs +[FAIL] asserts::base: (0.00s) +[----] asserts.c:20: Assertion failed: The conditions for this test were not met. +[FAIL] asserts::old_school: (0.00s) +[====] Synthesis: Tested: 6 | Passing: 4 | Failing: 2 | Crashing: 0  diff --git a/samples/asserts.out.expected b/samples/asserts.out.expected new file mode 100644 index 0000000..e69de29 diff --git a/samples/description.err.expected b/samples/description.err.expected new file mode 100644 index 0000000..64ffe21 --- /dev/null +++ b/samples/description.err.expected @@ -0,0 +1,3 @@ +[----] description.c:4: Assertion failed: 0 +[FAIL] misc::failing: (0.00s) +[====] Synthesis: Tested: 1 | Passing: 0 | Failing: 1 | Crashing: 0  diff --git a/samples/description.out.expected b/samples/description.out.expected new file mode 100644 index 0000000..e69de29 diff --git a/samples/fixtures.err.expected b/samples/fixtures.err.expected new file mode 100644 index 0000000..a34f221 --- /dev/null +++ b/samples/fixtures.err.expected @@ -0,0 +1 @@ +[====] Synthesis: Tested: 1 | Passing: 1 | Failing: 0 | Crashing: 0  diff --git a/samples/fixtures.out.expected b/samples/fixtures.out.expected new file mode 100644 index 0000000..a74afed --- /dev/null +++ b/samples/fixtures.out.expected @@ -0,0 +1,2 @@ +Runs before the test +Runs after the test diff --git a/samples/long-messages.err.expected b/samples/long-messages.err.expected new file mode 100644 index 0000000..9658ae5 --- /dev/null +++ b/samples/long-messages.err.expected @@ -0,0 +1,6 @@ +[----] long-messages.c:4: Assertion failed: This is +[----] A long message +[----] Spawning multiple lines. +[----] Formatting is respected. +[FAIL] sample::long_msg: (0.00s) +[====] Synthesis: Tested: 1 | Passing: 0 | Failing: 1 | Crashing: 0  diff --git a/samples/long-messages.out.expected b/samples/long-messages.out.expected new file mode 100644 index 0000000..e69de29 diff --git a/samples/more-suites.err.expected b/samples/more-suites.err.expected new file mode 100644 index 0000000..09eb50f --- /dev/null +++ b/samples/more-suites.err.expected @@ -0,0 +1 @@ +[====] Synthesis: Tested: 2 | Passing: 2 | Failing: 0 | Crashing: 0  diff --git a/samples/more-suites.out.expected b/samples/more-suites.out.expected new file mode 100644 index 0000000..e69de29 diff --git a/samples/other-crashes.err.expected b/samples/other-crashes.err.expected new file mode 100644 index 0000000..41d3cb8 --- /dev/null +++ b/samples/other-crashes.err.expected @@ -0,0 +1,3 @@ +[----] Warning! The test `misc::setup_crash` crashed during its setup or teardown. +[----] Warning! The test `misc::teardown_crash` crashed during its setup or teardown. +[====] Synthesis: Tested: 2 | Passing: 1 | Failing: 1 | Crashing: 1  diff --git a/samples/other-crashes.out.expected b/samples/other-crashes.out.expected new file mode 100644 index 0000000..e69de29 diff --git a/samples/report.err.expected b/samples/report.err.expected new file mode 100644 index 0000000..5b8f140 --- /dev/null +++ b/samples/report.err.expected @@ -0,0 +1,3 @@ +[----] report.c:5: Assertion failed: 0 +[FAIL] sample::test: (0.00s) +[====] Synthesis: Tested: 1 | Passing: 0 | Failing: 1 | Crashing: 0  diff --git a/samples/report.out.expected b/samples/report.out.expected new file mode 100644 index 0000000..d560277 --- /dev/null +++ b/samples/report.out.expected @@ -0,0 +1,4 @@ +criterion_init +testing test in category sample +Asserts: [1 passed, 1 failed, 2 total] +criterion_fini diff --git a/samples/signal.err.expected b/samples/signal.err.expected new file mode 100644 index 0000000..8bc2b30 --- /dev/null +++ b/samples/signal.err.expected @@ -0,0 +1,4 @@ +[----] signal.c:16: Unexpected signal caught below this line! +[FAIL] simple::uncaught: CRASH! +[FAIL] simple::wrong_signal: (0.00s) +[====] Synthesis: Tested: 3 | Passing: 1 | Failing: 2 | Crashing: 1  diff --git a/samples/signal.out.expected b/samples/signal.out.expected new file mode 100644 index 0000000..e69de29 diff --git a/samples/simple.err.expected b/samples/simple.err.expected new file mode 100644 index 0000000..ef375ca --- /dev/null +++ b/samples/simple.err.expected @@ -0,0 +1,3 @@ +[----] simple.c:4: Assertion failed: 0 +[FAIL] misc::failing: (0.00s) +[====] Synthesis: Tested: 2 | Passing: 1 | Failing: 1 | Crashing: 0  diff --git a/samples/simple.out.expected b/samples/simple.out.expected new file mode 100644 index 0000000..e69de29 diff --git a/samples/suites.err.expected b/samples/suites.err.expected new file mode 100644 index 0000000..09eb50f --- /dev/null +++ b/samples/suites.err.expected @@ -0,0 +1 @@ +[====] Synthesis: Tested: 2 | Passing: 2 | Failing: 0 | Crashing: 0  diff --git a/samples/suites.out.expected b/samples/suites.out.expected new file mode 100644 index 0000000..e69de29 diff --git a/samples/tests/run_test.sh b/samples/tests/run_test.sh new file mode 100755 index 0000000..8d81472 --- /dev/null +++ b/samples/tests/run_test.sh @@ -0,0 +1,26 @@ +#!/bin/sh -e + +cmp_dir=$1; shift +out_dir=$1; shift +bin_dir=$1; shift + +mkdir -p $out_dir + +if [ -f $cmp_dir/$1.in ]; then + sh -c "$bin_dir/$*" > $out_dir/$1.out 2> $out_dir/$1.err < $cmp_dir/$1.in +else + mkdir -p $(dirname $out_dir/$1) + sh -c "$bin_dir/$*" > $out_dir/$1.out 2> $out_dir/$1.err +fi + +dos2unix $out_dir/$1.err $out_dir/$1.out + +if [ -f $cmp_dir/$1.out.expected ] && [ "$(md5sum $out_dir/$1.out | cut -d' ' -f1)" != "$(md5sum $cmp_dir/$1.out.expected | cut -d' ' -f1)" ]; then + diff $out_dir/$1.out $cmp_dir/$1.out.expected + exit 255 +fi + +if [ -f $cmp_dir/$1.err.expected ] && [ "$(md5sum $out_dir/$1.err | cut -d' ' -f1)" != "$(md5sum $cmp_dir/$1.err.expected | cut -d' ' -f1)" ]; then + diff $out_dir/$1.err $cmp_dir/$1.err.expected + exit 255 +fi diff --git a/src/extmatch.c b/src/extmatch.c index 205a148..604d418 100644 --- a/src/extmatch.c +++ b/src/extmatch.c @@ -1,3 +1,26 @@ +/* + * The MIT License (MIT) + * + * Copyright © 2015 Franklin "Snaipe" Mathieu + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ #include #include #include diff --git a/src/extmatch.h b/src/extmatch.h index d65eeb1..8fe4974 100644 --- a/src/extmatch.h +++ b/src/extmatch.h @@ -1,3 +1,26 @@ +/* + * The MIT License (MIT) + * + * Copyright © 2015 Franklin "Snaipe" Mathieu + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ #ifndef EXTMATCH_H_ # define EXTMATCH_H_ diff --git a/src/log/normal.c b/src/log/normal.c index ff83888..565e763 100644 --- a/src/log/normal.c +++ b/src/log/normal.c @@ -44,26 +44,30 @@ typedef const char *const msg_t; -static msg_t msg_pre_all = "Criterion v%s\n"; -static msg_t msg_desc = " %s\n"; +// Used to mark string for gettext +# define N_(Str) Str +# define N_s(Str, Pl) {Str, Pl} + +static msg_t msg_pre_all = N_("Criterion v%s\n"); +static msg_t msg_desc = N_(" %s\n"); #ifdef ENABLE_NLS -static msg_t msg_pre_init = "%1$s::%2$s\n"; -static msg_t msg_post_test_timed = "%1$s::%2$s: (%3$3.2fs)\n"; -static msg_t msg_post_test = "%1$s::%2$s\n"; -static msg_t msg_post_suite_test = "%1$s::%2$s: Test is disabled\n"; -static msg_t msg_post_suite_suite = "%1$s::%2$s: Suite is disabled\n"; -static msg_t msg_assert_fail = "%1$s%2$s%3$s:%4$s%5$d%6$s: Assertion failed: %7$s\n"; -static msg_t msg_test_crash_line = "%1$s%2$s%3$s:%4$s%5$u%6$s: Unexpected signal caught below this line!\n"; -static msg_t msg_test_crash = "%1$s::%2$s: CRASH!\n"; -static msg_t msg_test_other_crash = "%1$sWarning! The test `%2$s::%3$s` crashed during its setup or teardown.%4$s\n"; -static msg_t msg_pre_suite = "Running %1$s%2$lu%3$s test from %4$s%5$s%6$s:\n"; -static msg_t msg_pre_suite_pl = "Running %1$s%2$lu%3$s tests from %4$s%5$s%6$s:\n"; -static msg_t msg_post_all = "%1$sSynthesis: Tested: %2$s%3$lu%4$s " - "| Passing: %5$s%6$lu%7$s " - "| Failing: %8$s%9$lu%10$s " - "| Crashing: %11$s%12$lu%13$s " - "%14$s\n"; +static msg_t msg_pre_init = N_("%1$s::%2$s\n"); +static msg_t msg_post_test_timed = N_("%1$s::%2$s: (%3$3.2fs)\n"); +static msg_t msg_post_test = N_("%1$s::%2$s\n"); +static msg_t msg_post_suite_test = N_("%1$s::%2$s: Test is disabled\n"); +static msg_t msg_post_suite_suite = N_("%1$s::%2$s: Suite is disabled\n"); +static msg_t msg_assert_fail = N_("%1$s%2$s%3$s:%4$s%5$d%6$s: Assertion failed: %7$s\n"); +static msg_t msg_test_crash_line = N_("%1$s%2$s%3$s:%4$s%5$u%6$s: Unexpected signal caught below this line!\n"); +static msg_t msg_test_crash = N_("%1$s::%2$s: CRASH!\n"); +static msg_t msg_test_other_crash = N_("%1$sWarning! The test `%2$s::%3$s` crashed during its setup or teardown.%4$s\n"); +static msg_t msg_pre_suite[] = N_s("Running %1$s%2$lu%3$s test from %4$s%5$s%6$s:\n", + "Running %1$s%2$lu%3$s tests from %4$s%5$s%6$s:\n"); +static msg_t msg_post_all = N_("%1$sSynthesis: Tested: %2$s%3$lu%4$s " + "| Passing: %5$s%6$lu%7$s " + "| Failing: %8$s%9$lu%10$s " + "| Crashing: %11$s%12$lu%13$s " + "%14$s\n"); #else static msg_t msg_pre_init = "%s::%s\n"; static msg_t msg_post_test_timed = "%s::%s: (%3.2fs)\n"; @@ -74,13 +78,13 @@ static msg_t msg_assert_fail = "%s%s%s:%s%d%s: Assertion failed: %s\n"; static msg_t msg_test_crash_line = "%s%s%s:%s%u%s: Unexpected signal caught below this line!\n"; static msg_t msg_test_crash = "%s::%s: CRASH!\n"; static msg_t msg_test_other_crash = "%sWarning! The test `%s::%s` crashed during its setup or teardown.%s\n"; -static msg_t msg_pre_suite = "Running %s%lu%s test from %s%s%s:\n"; -static msg_t msg_pre_suite_pl = "Running %s%lu%s tests from %s%s%s:\n"; +static msg_t msg_pre_suite[] = { "Running %s%lu%s test from %s%s%s:\n", + "Running %s%lu%s tests from %s%s%s:\n" }; static msg_t msg_post_all = "%sSynthesis: Tested: %s%lu%s " - "| Passing: %s%lu%s " - "| Failing: %s%lu%s " - "| Crashing: %s%lu%s " - "%s\n"; + "| Passing: %s%lu%s " + "| Failing: %s%lu%s " + "| Crashing: %s%lu%s " + "%s\n"; #endif void normal_log_pre_all(UNUSED struct criterion_test_set *set) { @@ -160,9 +164,10 @@ void normal_log_assert(struct criterion_assert_stats *stats) { char *line = strtok_r(dup, "\n", &saveptr); #endif + bool sf = criterion_options.short_filename; criterion_pimportant(CRITERION_PREFIX_DASHES, _(msg_assert_fail), - FG_BOLD, stats->file, RESET, + FG_BOLD, sf ? basename_compat(stats->file) : stats->file, RESET, FG_RED, stats->line, RESET, line); @@ -177,9 +182,10 @@ void normal_log_assert(struct criterion_assert_stats *stats) { } void normal_log_test_crash(struct criterion_test_stats *stats) { + bool sf = criterion_options.short_filename; criterion_pimportant(CRITERION_PREFIX_DASHES, _(msg_test_crash_line), - FG_BOLD, stats->file, RESET, + FG_BOLD, sf ? basename_compat(stats->file) : stats->file, RESET, FG_RED, stats->progress, RESET); criterion_pimportant(CRITERION_PREFIX_FAIL, _(msg_test_crash), stats->test->category, @@ -194,7 +200,7 @@ void normal_log_other_crash(UNUSED struct criterion_test_stats *stats) { void normal_log_pre_suite(struct criterion_suite_set *set) { criterion_pinfo(CRITERION_PREFIX_EQUALS, - _s(msg_pre_suite, msg_pre_suite_pl, set->tests->size), + _s(msg_pre_suite[0], msg_pre_suite[1], set->tests->size), FG_BLUE, (unsigned long) set->tests->size, RESET, FG_GOLD, set->suite.name, RESET); } diff --git a/src/log/tap.c b/src/log/tap.c index e8a9d97..23898f4 100644 --- a/src/log/tap.c +++ b/src/log/tap.c @@ -89,8 +89,9 @@ void tap_log_post_test(struct criterion_test_stats *stats) { char *saveptr = NULL; char *line = strtok_r(dup, "\n", &saveptr); #endif + bool sf = criterion_options.short_filename; criterion_important(" %s:%u: Assertion failed: %s\n", - asrt->file, + sf ? basename_compat(asrt->file) : asrt->file, asrt->line, line); #ifdef VANILLA_WIN32 @@ -105,10 +106,11 @@ void tap_log_post_test(struct criterion_test_stats *stats) { } void tap_log_test_crash(struct criterion_test_stats *stats) { + bool sf = criterion_options.short_filename; criterion_important("not ok - %s::%s unexpected signal after %s:%u\n", stats->test->category, stats->test->name, - stats->file, + sf ? basename_compat(stats->file) : stats->file, stats->progress); } diff --git a/src/main.c b/src/main.c index 0402d71..1faa4a3 100644 --- a/src/main.c +++ b/src/main.c @@ -57,6 +57,8 @@ " -f or --fail-fast: exit after the first failure\n" \ " --ascii: don't use fancy unicode symbols " \ "or colors in the output\n" \ + " -S or --short-filename: only display the base " \ + "name of the source file on a failure\n" \ PATTERN_USAGE \ " --tap: enables TAP formatting\n" \ " --always-succeed: always exit with 0\n" \ @@ -124,6 +126,7 @@ int main(int argc, char *argv[]) { {"list", no_argument, 0, 'l'}, {"ascii", no_argument, 0, 'k'}, {"fail-fast", no_argument, 0, 'f'}, + {"short-filename", no_argument, 0, 'S'}, #ifdef HAVE_PCRE {"pattern", required_argument, 0, 'p'}, #endif @@ -146,6 +149,7 @@ int main(int argc, char *argv[]) { opt->fail_fast = !strcmp("1", getenv("CRITERION_FAIL_FAST") ?: "0"); opt->use_ascii = use_ascii; opt->logging_threshold = atoi(getenv("CRITERION_VERBOSITY_LEVEL") ?: "2"); + opt->short_filename = !strcmp("1", getenv("CRITERION_SHORT_FILENAME") ?: "0"); #ifdef HAVE_PCRE opt->pattern = getenv("CRITERION_TEST_PATTERN"); #endif @@ -155,13 +159,14 @@ int main(int argc, char *argv[]) { bool do_list_tests = false; bool do_print_version = false; bool do_print_usage = false; - for (int c; (c = getopt_long(argc, argv, "hvlf", opts, NULL)) != -1;) { + for (int c; (c = getopt_long(argc, argv, "hvlfS", opts, NULL)) != -1;) { switch (c) { case 'b': criterion_options.logging_threshold = atoi(optarg ?: "1"); break; case 'y': criterion_options.always_succeed = true; break; case 'z': criterion_options.no_early_exit = true; break; case 'k': criterion_options.use_ascii = true; break; case 'f': criterion_options.fail_fast = true; break; + case 'S': criterion_options.short_filename = true; break; #ifdef HAVE_PCRE case 'p': criterion_options.pattern = optarg; break; #endif diff --git a/src/posix-compat.c b/src/posix-compat.c index 72afb91..376cd27 100644 --- a/src/posix-compat.c +++ b/src/posix-compat.c @@ -1,3 +1,26 @@ +/* + * The MIT License (MIT) + * + * Copyright © 2015 Franklin "Snaipe" Mathieu + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ #include #include "posix-compat.h" #include "process.h" @@ -304,7 +327,7 @@ bool is_current_process(s_proc_handle *proc) { #endif } -#ifdef VANILLA_WIN32 +#ifdef _WIN32 void *get_win_section_start(const char *section) { PIMAGE_DOS_HEADER dosHeader = (PIMAGE_DOS_HEADER) GetModuleHandle(NULL); PIMAGE_NT_HEADERS ntHeader = ntHeader = (PIMAGE_NT_HEADERS) ((DWORD)(dosHeader) + (dosHeader->e_lfanew)); @@ -337,3 +360,38 @@ void *get_win_section_end(const char *section) { return NULL; } #endif + +#ifdef __APPLE__ +# include +# include + +# define BASE_IMAGE_INDEX 0 + +static inline void *get_real_address(void *addr) { + if (!addr) + return NULL; + + // We need to slide the section address to get a valid pointer + // because ASLR will shift the image by a random offset + return addr + _dyld_get_image_vmaddr_slide(BASE_IMAGE_INDEX); +} + +void *get_osx_section_start(const char *section) { + unsigned long secsize; + return get_real_address(getsectdata("__DATA", section, &secsize)); +} + +void *get_osx_section_end(const char *section) { + unsigned long secsize; + char *section_start = getsectdata("__DATA", section, &secsize); + return get_real_address(section_start) + secsize; +} +#endif + +const char *basename_compat(const char *str) { + const char *start = str; + for (const char *c = str; *c; ++c) + if ((*c == '/' || *c == '\\') && c[1]) + start = c + 1; + return start; +} diff --git a/src/posix-compat.h b/src/posix-compat.h index 0ee7a57..9f938db 100644 --- a/src/posix-compat.h +++ b/src/posix-compat.h @@ -1,3 +1,26 @@ +/* + * The MIT License (MIT) + * + * Copyright © 2015 Franklin "Snaipe" Mathieu + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ #ifndef POSIX_COMPAT_H_ # define POSIX_COMPAT_H_ @@ -53,14 +76,25 @@ void wait_process(s_proc_handle *handle, int *status); s_proc_handle *get_current_process(); bool is_current_process(s_proc_handle *proc); -# ifdef VANILLA_WIN32 +# ifdef _WIN32 void *get_win_section_start(const char *section); void *get_win_section_end(const char *section); -# define GET_SECTION_START(Name) get_win_section_start(#Name) -# define GET_SECTION_END(Name) get_win_section_end(#Name) +# define CR_STRINGIFY_(Param) #Param +# define CR_STRINGIFY(Param) CR_STRINGIFY_(Param) +# define GET_SECTION_START(Name) get_win_section_start(CR_STRINGIFY(Name)) +# define GET_SECTION_END(Name) get_win_section_end(CR_STRINGIFY(Name)) +# elif defined(__APPLE__) +void *get_osx_section_start(const char *section); +void *get_osx_section_end(const char *section); +# define CR_STRINGIFY_(Param) #Param +# define CR_STRINGIFY(Param) CR_STRINGIFY_(Param) +# define GET_SECTION_START(Name) get_osx_section_start(CR_STRINGIFY(Name)) +# define GET_SECTION_END(Name) get_osx_section_end(CR_STRINGIFY(Name)) # else # define GET_SECTION_START(Name) SECTION_START(Name) # define GET_SECTION_END(Name) SECTION_END(Name) # endif +const char *basename_compat(const char *str); + #endif /* !POSIX_COMPAT_H_ */ diff --git a/src/report.c b/src/report.c index 8f8bf39..64a6861 100644 --- a/src/report.c +++ b/src/report.c @@ -33,13 +33,15 @@ #include "config.h" #include "posix-compat.h" +static inline void nothing() {} + #define IMPL_CALL_REPORT_HOOKS(Kind) \ IMPL_SECTION_LIMITS(f_report_hook, HOOK_SECTION(Kind)); \ void call_report_hooks_##Kind(void *data) { \ for (f_report_hook *hook = GET_SECTION_START(HOOK_SECTION(Kind)); \ hook < (f_report_hook*) GET_SECTION_END(HOOK_SECTION(Kind)); \ ++hook) { \ - (*hook)(data); \ + (*hook ?: nothing)(data); \ } \ } diff --git a/src/runner.c b/src/runner.c index a35a57c..c28da67 100644 --- a/src/runner.c +++ b/src/runner.c @@ -296,6 +296,8 @@ static int criterion_run_all_tests_impl(void) { report(PRE_ALL, set); log(pre_all, set); + fflush(NULL); // flush everything before forking + smart struct criterion_global_stats *stats = stats_init(); map_tests(set, stats, run_test);