diff options
Diffstat (limited to 'unittest')
225 files changed, 53788 insertions, 0 deletions
diff --git a/unittest/Catch/.gitattributes b/unittest/Catch/.gitattributes new file mode 100644 index 0000000..a2d66d3 --- /dev/null +++ b/unittest/Catch/.gitattributes @@ -0,0 +1,11 @@ +# This sets the default behaviour, overriding core.autocrlf +* text=auto + +# All source files should have unix line-endings in the repository, +# but convert to native line-endings on checkout +*.cpp text +*.h text +*.hpp text + +# Windows specific files should retain windows line-endings +*.sln text eol=crlf
\ No newline at end of file diff --git a/unittest/Catch/.gitignore b/unittest/Catch/.gitignore new file mode 100644 index 0000000..3ca4b5c --- /dev/null +++ b/unittest/Catch/.gitignore @@ -0,0 +1,22 @@ +*.build +*.pbxuser +*.mode1v3 +*.ncb +*.suo +Debug +Release +*.user +*.xcuserstate +.DS_Store +xcuserdata +CatchSelfTest.xcscheme +Breakpoints.xcbkptlist +projects/VS2010/TestCatch/_UpgradeReport_Files/ +projects/VS2010/TestCatch/TestCatch/TestCatch.vcxproj.filters +projects/VisualStudio/TestCatch/UpgradeLog.XML +UpgradeLog.XML +Resources/DWARF +projects/XCode/iOSTest/Build +*.pyc +DerivedData +*.xccheckout diff --git a/unittest/Catch/.travis.yml b/unittest/Catch/.travis.yml new file mode 100644 index 0000000..e63a76a --- /dev/null +++ b/unittest/Catch/.travis.yml @@ -0,0 +1,163 @@ +language: cpp +sudo: false + +cache: + ccache: true + directories: + - $HOME/.ccache + +env: + global: + - USE_CCACHE=1 + - CCACHE_COMPRESS=1 + - CCACHE_MAXSIZE=200M + - CCACHE_CPP2=1 + + +matrix: + include: + + # 1/ Linux Clang Builds + - os: linux + compiler: clang + addons: &clang35 + apt: + sources: ['llvm-toolchain-precise-3.5', 'ubuntu-toolchain-r-test'] + packages: ['clang-3.5'] + env: COMPILER='ccache clang++-3.5' BUILD_TYPE='Release' + + - os: linux + compiler: clang + addons: *clang35 + env: COMPILER='ccache clang++-3.5' BUILD_TYPE='Debug' + + + - os: linux + compiler: clang + addons: &clang36 + apt: + sources: ['llvm-toolchain-precise-3.6', 'ubuntu-toolchain-r-test'] + packages: ['clang-3.6'] + env: COMPILER='ccache clang++-3.6' BUILD_TYPE='Release' + + - os: linux + compiler: clang + addons: *clang36 + env: COMPILER='ccache clang++-3.6' BUILD_TYPE='Debug' + + + - os: linux + compiler: clang + addons: &clang37 + apt: + sources: ['llvm-toolchain-precise-3.7', 'ubuntu-toolchain-r-test'] + packages: ['clang-3.7'] + env: COMPILER='ccache clang++-3.7' BUILD_TYPE='Release' + + - os: linux + compiler: clang + addons: *clang37 + env: COMPILER='ccache clang++-3.7' BUILD_TYPE='Debug' + + + - os: linux + compiler: clang + addons: &clang38 + apt: + sources: ['llvm-toolchain-precise', 'ubuntu-toolchain-r-test'] + packages: ['clang-3.8'] + env: COMPILER='ccache clang++-3.8' BUILD_TYPE='Release' + + - os: linux + compiler: clang + addons: *clang38 + env: COMPILER='ccache clang++-3.8' BUILD_TYPE='Debug' + + + # 2/ Linux GCC Builds + - os: linux + compiler: gcc + addons: &gcc48 + apt: + sources: ['ubuntu-toolchain-r-test'] + packages: ['g++-4.8'] + env: COMPILER='ccache g++-4.8' BUILD_TYPE='Release' + + - os: linux + compiler: gcc + addons: *gcc48 + env: COMPILER='ccache g++-4.8' BUILD_TYPE='Debug' + + + - os: linux + compiler: gcc + addons: &gcc49 + apt: + sources: ['ubuntu-toolchain-r-test'] + packages: ['g++-4.9'] + env: COMPILER='ccache g++-4.9' BUILD_TYPE='Release' + + - os: linux + compiler: gcc + addons: *gcc49 + env: COMPILER='ccache g++-4.9' BUILD_TYPE='Debug' + + + - os: linux + compiler: gcc + addons: &gcc5 + apt: + sources: ['ubuntu-toolchain-r-test'] + packages: ['g++-5'] + env: COMPILER='ccache g++-5' BUILD_TYPE='Release' + + - os: linux + compiler: gcc + addons: *gcc5 + env: COMPILER='ccache g++-5' BUILD_TYPE='Debug' + + + # 3/ OSX Clang Builds + - os: osx + osx_image: xcode6.4 + compiler: clang + env: COMPILER='ccache clang++' BUILD_TYPE='Debug' + + - os: osx + osx_image: xcode6.4 + compiler: clang + env: COMPILER='ccache clang++' BUILD_TYPE='Release' + + + - os: osx + osx_image: xcode7 + compiler: clang + env: COMPILER='ccache clang++' BUILD_TYPE='Debug' + + - os: osx + osx_image: xcode7 + compiler: clang + env: COMPILER='ccache clang++' BUILD_TYPE='Release' + + +install: + - DEPS_DIR="${TRAVIS_BUILD_DIR}/deps" + - mkdir -p ${DEPS_DIR} && cd ${DEPS_DIR} + - | + if [[ "${TRAVIS_OS_NAME}" == "linux" ]]; then + CMAKE_URL="http://www.cmake.org/files/v3.3/cmake-3.3.2-Linux-x86_64.tar.gz" + mkdir cmake && travis_retry wget --quiet -O - ${CMAKE_URL} | tar --strip-components=1 -xz -C cmake + export PATH=${DEPS_DIR}/cmake/bin:${PATH} + elif [[ "${TRAVIS_OS_NAME}" == "osx" ]]; then + brew install cmake ccache + fi + +before_script: + - export CXX=${COMPILER} + - cd ${TRAVIS_BUILD_DIR} + - cmake -Hprojects/CMake -BBuild -DCMAKE_BUILD_TYPE=${BUILD_TYPE} + - cd Build + +script: + - make -j 2 + - ctest -V -j 2 diff --git a/unittest/Catch/LICENSE_1_0.txt b/unittest/Catch/LICENSE_1_0.txt new file mode 100644 index 0000000..36b7cd9 --- /dev/null +++ b/unittest/Catch/LICENSE_1_0.txt @@ -0,0 +1,23 @@ +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +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, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/unittest/Catch/README.md b/unittest/Catch/README.md new file mode 100644 index 0000000..942053f --- /dev/null +++ b/unittest/Catch/README.md @@ -0,0 +1,22 @@ +![catch logo](catch-logo-small.png) + +*v1.3.5* + +Build status (on Travis CI) [![Build Status](https://travis-ci.org/philsquared/Catch.png)](https://travis-ci.org/philsquared/Catch) + +<a href="https://raw.githubusercontent.com/philsquared/Catch/master/single_include/catch.hpp">The latest, single header, version can be downloaded directly using this link</a> + +## What's the Catch? + +Catch stands for C++ Automated Test Cases in Headers and is a multi-paradigm automated test framework for C++ and Objective-C (and, maybe, C). It is implemented entirely in a set of header files, but is packaged up as a single header for extra convenience. + +## How to use it +This documentation comprises these three parts: + +* [Why do we need yet another C++ Test Framework?](docs/why-catch.md) +* [Tutorial](docs/tutorial.md) - getting started +* [Reference section](docs/Readme.md) - all the details + +## More +* Issues and bugs can be raised on the [Issue tracker on GitHub](https://github.com/philsquared/Catch/issues) +* For discussion or questions please use [the dedicated Google Groups forum](https://groups.google.com/forum/?fromgroups#!forum/catch-forum) diff --git a/unittest/Catch/catch-logo-small.png b/unittest/Catch/catch-logo-small.png Binary files differnew file mode 100644 index 0000000..a4e74e8 --- /dev/null +++ b/unittest/Catch/catch-logo-small.png diff --git a/unittest/Catch/docs/Readme.md b/unittest/Catch/docs/Readme.md new file mode 100644 index 0000000..6621fb8 --- /dev/null +++ b/unittest/Catch/docs/Readme.md @@ -0,0 +1,19 @@ +These are the currently documented areas of the framework. There is more to come. + +Before looking at this material be sure to read the [tutorial](tutorial.md) + +* [Assertion macros](assertions.md) +* [Logging macros](logging.md) +* [Test cases and sections](test-cases-and-sections.md) +* [Test fixtures](test-fixtures.md) +* [Command line](command-line.md) +* [Build systems](build-systems.md) +* [Supplying your own main()](own-main.md) +* [Configuration](configuration.md) +* [String Conversions](tostring.md) +* [Why are my tests slow to compile?](slow-compiles.md) + +Other + +* [Why Catch?](why-catch.md) +* [Contributing](contributing.md) diff --git a/unittest/Catch/docs/assertions.md b/unittest/Catch/docs/assertions.md new file mode 100644 index 0000000..82bb96a --- /dev/null +++ b/unittest/Catch/docs/assertions.md @@ -0,0 +1,82 @@ +# Assertion Macros + +Most test frameworks have a large collection of assertion macros to capture all possible conditional forms (```_EQUALS```, ```_NOTEQUALS```, ```_GREATER_THAN``` etc). + +Catch is different. Because it decomposes natural C-style conditional expressions most of these forms are reduced to one or two that you will use all the time. That said there are a rich set of auxilliary macros as well. We'll describe all of these here. + +Most of these macros come in two forms: + +## Natural Expressions + +The ```REQUIRE``` family of macros tests an expression and aborts the test case if it fails. +The ```CHECK``` family are equivalent but execution continues in the same test case even if the assertion fails. This is useful if you have a series of essentially orthogonal assertions and it is useful to see all the results rather than stopping at the first failure. + +* **REQUIRE(** _expression_ **)** and +* **CHECK(** _expression_ **)** + +Evaluates the expression and records the result. If an exception is thrown it is caught, reported, and counted as a failure. These are the macros you will use most of the time + +Examples: +``` +CHECK( str == "string value" ); +CHECK( thisReturnsTrue() ); +REQUIRE( i == 42 ); +``` + +* **REQUIRE_FALSE(** _expression_ **)** and +* **CHECK_FALSE(** _expression_ **)** + +Evaluates the expression and records the _logical NOT_ of the result. If an exception is thrown it is caught, reported, and counted as a failure. +(these forms exist as a workaround for the fact that ! prefixed expressions cannot be decomposed). + +Example: +``` +REQUIRE_FALSE( thisReturnsFalse() ); +``` + +### Floating point comparisons + +When comparing floating point numbers - especially if at least one of them has been computed - great care must be taken to allow for rounding errors and inexact representations. + +Catch provides a way to perform tolerant comparisons of floating point values through use of a wrapper class called ```Approx```. ```Approx``` can be used on either side of a comparison expression. It overloads the comparisons operators to take a tolerance into account. Here's a simple example: + +``` +REQUIRE( performComputation() == Approx( 2.1 ) ); +``` + +By default a small epsilon value is used that covers many simple cases of rounding errors. When this is insufficent the epsilon value (the amount within which a difference either way is ignored) can be specified by calling the ```epsilon()``` method on the ```Approx``` instance. e.g.: + +``` +REQUIRE( 22/7 == Approx( 3.141 ).epsilon( 0.01 ) ); +``` + +When dealing with very large or very small numbers it can be useful to specify a scale, which can be achieved by calling the ```scale()``` method on the ```Approx``` instance. + +## Exceptions + +* **REQUIRE_THROWS(** _expression_ **)** and +* **CHECK_THROWS(** _expression_ **)** + +Expects that an exception (of any type) is be thrown during evaluation of the expression. + +* **REQUIRE_THROWS_AS(** _expression_, _exception type_ **)** and +* **CHECK_THROWS_AS(** _expression_, _exception type_ **)** + +Expects that an exception of the _specified type_ is thrown during evaluation of the expression. + +* **REQUIRE_NOTHROW(** _expression_ **)** and +* **CHECK_NOTHROW(** _expression_ **)** + +Expects that no exception is thrown during evaluation of the expression. + +## Matcher expressions + +To support Matchers a slightly different form is used. Matchers will be more fully documented elsewhere. *Note that Matchers are still at early stage development and are subject to change.* + +* **REQUIRE_THAT(** _lhs_, _matcher call_ **)** and +* **CHECK_THAT(** _lhs_, _matcher call_ **)** + + +--- + +[Home](Readme.md)
\ No newline at end of file diff --git a/unittest/Catch/docs/build-systems.md b/unittest/Catch/docs/build-systems.md new file mode 100644 index 0000000..b001dc1 --- /dev/null +++ b/unittest/Catch/docs/build-systems.md @@ -0,0 +1,86 @@ +# Integration with build systems + +Build Systems may refer to low-level tools, like CMake, or larger systems that run on servers, like Jenkins or TeamCity. This page will talk about both. + +# Continuous Integration systems + +Probably the most important aspect to using Catch with a build server is the use of different reporters. Catch comes bundled with three reporters that should cover the majority of build servers out there - although adding more for better integration with some is always a possibility (as has been done with TeamCity). + +Two of these reporters are built in (XML and JUnit) and the third (TeamCity) is included as a separate header. It's possible that the other two may be split out in the future too - as that would make the core of Catch smaller for those that don't need them. + +## XML Reporter +```-r xml``` + +The XML Reporter writes in an XML format that is specific to Catch. + +The advantage of this format is that it corresponds well to the way Catch works (especially the more unusual features, such as nested sections) and is a fully streaming format - that is it writes output as it goes, without having to store up all its results before it can start writing. + +The disadvantage is that, being specific to Catch, no existing build servers understand the format natively. It can be used as input to an XSLT transformation that could covert it to, say, HTML - although this loses the streaming advantage, of course. + +## JUnit Reporter +```-r junit``` + +The JUnit Reporter writes in an XML format that mimics the JUnit ANT schema. + +The advantage of this format is that the JUnit Ant schema is widely understood by most build servers and so can usually be consumed with no additional work. + +The disadvantage is that this schema was designed to correspond to how JUnit works - and there is a significant mismatch with how Catch works. Additionally the format is not streamable (because opening elements hold counts of failed and passing tests as attributes) - so the whole test run must complete before it can be written. + +## TeamCity Reporter +```-r teamcity``` + +The TeamCity Reporter writes TeamCity service messages to stdout. In order to be able to use this reporter an additional header must also be included. + +```catch_reporter_teamcity.hpp``` can be found in the ```include\reporters``` directory. It should be included in the same file that ```#define```s ```CATCH_CONFIG_MAIN``` or ```CATCH_CONFIG_RUNNER```. The ```#include``` should be placed after ```#include```ing Catch itself. + +e.g.: + +``` +#define CATCH_CONFIG_MAIN +#include "catch.hpp" +#include "catch_reporter_teamcity.hpp" +``` + +Being specific to TeamCity this is the best reporter to use with it - but it is completely unsuitable for any other purpose. It is a streaming format (it writes as it goes) - although test results don't appear in the TeamCity interface until the completion of a suite (usually the whole test run). + +# Low-level tools + +## CMake + +You can use the following CMake script to automatically fetch Catch from github and configure it as an external project: + +```CMake +cmake_minimum_required(VERSION 2.8.8) +project(catch_builder CXX) +include(ExternalProject) +find_package(Git REQUIRED) + +ExternalProject_Add( + catch + PREFIX ${CMAKE_BINARY_DIR}/catch + GIT_REPOSITORY https://github.com/philsquared/Catch.git + TIMEOUT 10 + UPDATE_COMMAND ${GIT_EXECUTABLE} pull + CONFIGURE_COMMAND "" + BUILD_COMMAND "" + INSTALL_COMMAND "" + LOG_DOWNLOAD ON + ) + +# Expose required variable (CATCH_INCLUDE_DIR) to parent scope +ExternalProject_Get_Property(catch source_dir) +set(CATCH_INCLUDE_DIR ${source_dir}/include CACHE INTERNAL "Path to include folder for Catch") +``` + +If you put it in, e.g., `${PROJECT_SRC_DIR}/${EXT_PROJECTS_DIR}/catch/`, you can use it in your project by adding the following to your root CMake file: + +```CMake +# Includes Catch in the project: +add_subdirectory(${EXT_PROJECTS_DIR}/catch) +include_directories(${CATCH_INCLUDE_DIR} ${COMMON_INCLUDES}) +enable_testing(true) # Enables unit-testing. +``` + +--- + +[Home](Readme.md)
\ No newline at end of file diff --git a/unittest/Catch/docs/command-line.md b/unittest/Catch/docs/command-line.md new file mode 100644 index 0000000..d1d4bd4 --- /dev/null +++ b/unittest/Catch/docs/command-line.md @@ -0,0 +1,220 @@ +Catch works quite nicely without any command line options at all - but for those times when you want greater control the following options are available. +Click one of the followings links to take you straight to that option - or scroll on to browse the available options. + +<a href="#specifying-which-tests-to-run"> ` <test-spec> ...`</a><br /> +<a href="#usage"> ` -h, -?, --help`</a><br /> +<a href="#listing-available-tests-tags-or-reporters"> ` -l, --list-tests`</a><br /> +<a href="#listing-available-tests-tags-or-reporters"> ` -t, --list-tags`</a><br /> +<a href="#showing-results-for-successful-tests"> ` -s, --success`</a><br /> +<a href="#breaking-into-the-debugger"> ` -b, --break`</a><br /> +<a href="#eliding-assertions-expected-to-throw"> ` -e, --nothrow`</a><br /> +<a href="#invisibles"> ` -i, --invisibles`</a><br /> +<a href="#sending-output-to-a-file"> ` -o, --out`</a><br /> +<a href="#choosing-a-reporter-to-use"> ` -r, --reporter`</a><br /> +<a href="#naming-a-test-run"> ` -n, --name`</a><br /> +<a href="#aborting-after-a-certain-number-of-failures"> ` -a, --abort`</a><br /> +<a href="#aborting-after-a-certain-number-of-failures"> ` -x, --abortx`</a><br /> +<a href="#warnings"> ` -w, --warn`</a><br /> +<a href="#reporting-timings"> ` -d, --durations`</a><br /> +<a href="#input-file"> ` -f, --input-file`</a><br /> + +</br> + +<a href="#list-test-names-only"> ` --list-test-names-only`</a><br /> +<a href="#listing-available-tests-tags-or-reporters"> ` --list-reporters`</a><br /> +<a href="#order"> ` --order`</a><br /> +<a href="#rng-seed"> ` --rng-seed`</a><br /> + +</br> + + + +<a id="specifying-which-tests-to-run"></a> +## Specifying which tests to run + +<pre><test-spec> ...</pre> + +Test cases, wildcarded test cases, tags and tag expressions are all passed directly as arguments. Tags are distinguished by being enclosed in square brackets. + +If no test specs are supplied then all test cases, except "hidden" tests, are run. +A test is hidden by giving it any tag starting with (or just) a period (```.```) - or, in the deprecated case, tagged ```[hide]``` or given name starting with `'./'`. To specify hidden tests from the command line ```[.]``` or ```[hide]``` can be used *regardless of how they were declared*. + +Specs must be enclosed in quotes if they contain spaces. If they do not contain spaces the quotes are optional. + +Wildcards consist of the `*` character at the beginning and/or end of test case names and can substitute for any number of any characters (including none). + +Test specs are case insensitive. + +If a spec is prefixed with `exclude:` or the `~` character then the pattern matches an exclusion. This means that tests matching the pattern are excluded from the set - even if a prior inclusion spec included them. Subsequent inclusion specs will take precendence, however. +Inclusions and exclusions are evaluated in left-to-right order. + +Test case examples: + +<pre>thisTestOnly Matches the test case called, 'thisTestOnly' +"this test only" Matches the test case called, 'this test only' +these* Matches all cases starting with 'these' +exclude:notThis Matches all tests except, 'notThis' +~notThis Matches all tests except, 'notThis' +~*private* Matches all tests except those that contain 'private' +a* ~ab* abc Matches all tests that start with 'a', except those that + start with 'ab', except 'abc', which is included +</pre> + +Names within square brackets are interpreted as tags. +A series of tags form an AND expression wheras a comma-separated sequence forms an OR expression. e.g.: + +<pre>[one][two],[three]</pre> +This matches all tests tagged `[one]` and `[two]`, as well as all tests tagged `[three]` + + +<a id="choosing-a-reporter-to-use"></a> +## Choosing a reporter to use + +<pre>-r, --reporter <reporter></pre> + +A reporter is an object that formats and structures the output of running tests, and potentially summarises the results. By default a console reporter is used that writes, IDE friendly, textual output. Catch comes bundled with some alternative reporters, but more can be added in client code.<br /> +The bundled reporters are: + +<pre>-r console +-r compact +-r xml +-r junit +</pre> + +The JUnit reporter is an xml format that follows the structure of the JUnit XML Report ANT task, as consumed by a number of third-party tools, including Continuous Integration servers such as Hudson. If not otherwise needed, the standard XML reporter is preferred as this is a streaming reporter, whereas the Junit reporter needs to hold all its results until the end so it can write the overall results into attributes of the root node. + +<a id="breaking-into-the-debugger"></a> +## Breaking into the debugger +<pre>-b, --break</pre> + +In some IDEs (currently XCode and Visual Studio) it is possible for Catch to break into the debugger on a test failure. This can be very helpful during debug sessions - especially when there is more than one path through a particular test. +In addition to the command line option, ensure you have built your code with the DEBUG preprocessor symbol + +<a id="showing-results-for-successful-tests"></a> +## Showing results for successful tests +<pre>-s, --success</pre> + +Usually you only want to see reporting for failed tests. Sometimes it's useful to see *all* the output (especially when you don't trust that that test you just added worked first time!). +To see successful, as well as failing, test results just pass this option. Note that each reporter may treat this option differently. The Junit reporter, for example, logs all results regardless. + +<a id="aborting-after-a-certain-number-of-failures"></a> +## Aborting after a certain number of failures +<pre>-a, --abort +-x, --abortx [<failure threshold>] +</pre> + +If a ```REQUIRE``` assertion fails the test case aborts, but subsequent test cases are still run. +If a ```CHECK``` assertion fails even the current test case is not aborted. + +Sometimes this results in a flood of failure messages and you'd rather just see the first few. Specifying ```-a``` or ```--abort``` on its own will abort the whole test run on the first failed assertion of any kind. Use ```-x``` or ```--abortx``` followed by a number to abort after that number of assertion failures. + +<a id="listing-available-tests-tags-or-reporters"></a> +## Listing available tests, tags or reporters +<pre>-l, --list-tests +-t, --list-tags +--list-reporters +</pre> + +```-l``` or ```--list-tests`` will list all registered tests, along with any tags. +If one or more test-specs have been supplied too then only the matching tests will be listed. + +```-t``` or ```--list-tags``` lists all available tags, along with the number of test cases they match. Again, supplying test specs limits the tags that match. + +```--list-reporters``` lists the available reporters. + +<a id="sending-output-to-a-file"></a> +## Sending output to a file +<pre>-o, --out <filename> +</pre> + +Use this option to send all output to a file. By default output is sent to stdout (note that uses of stdout and stderr *from within test cases* are redirected and included in the report - so even stderr will effectively end up on stdout). + +<a id="naming-a-test-run"></a> +## Naming a test run +<pre>-n, --name <name for test run></pre> + +If a name is supplied it will be used by the reporter to provide an overall name for the test run. This can be useful if you are sending to a file, for example, and need to distinguish different test runs - either from different Catch executables or runs of the same executable with different options. If not supplied the name is defaulted to the name of the executable. + +<a id="eliding-assertions-expected-to-throw"></a> +## Eliding assertions expected to throw +<pre>-e, --nothrow</pre> + +Skips all assertions that test that an exception is thrown, e.g. ```REQUIRE_THROWS```. + +These can be a nuisance in certain debugging environments that may break when exceptions are thrown (while this is usually optional for handled exceptions, it can be useful to have enabled if you are trying to track down something unexpected). + +Sometimes exceptions are expected outside of one of the assertions that tests for them (perhaps thrown and caught within the code-under-test). The whole test case can be skipped when using ```-e``` by marking it with the ```[!throws]``` tag. + +When running with this option any throw checking assertions are skipped so as not to contribute additional noise. Be careful if this affects the behaviour of subsequent tests. + +<a id="invisibles"></a> +## Make whitespace visible +<pre>-i, --invisibles</pre> + +If a string comparison fails due to differences in whitespace - especially leading or trailing whitespace - it can be hard to see what's going on. +This option transforms tabs and newline characters into ```\t``` and ```\n``` respectively when printing. + +<a id="warnings"></a> +## Warnings +<pre>-w, --warn <warning name></pre> + +Enables reporting of warnings (only one, at time of this writing). If a warning is issued it fails the test. + +The ony available warning, presently, is ```NoAssertions```. This warning fails a test case, or (leaf) section if no assertions (```REQUIRE```/ ```CHECK``` etc) are encountered. + +<a id="reporting-timings"></a> +## Reporting timings +<pre>-d, --durations <yes/no></pre> + +When set to ```yes``` Catch will report the duration of each test case, in milliseconds. Note that it does this regardless of whether a test case passes or fails. Note, also, the certain reporters (e.g. Junit) always report test case durations regardless of this option being set or not. + +<a id="input-file"></a> +## Load test names to run from a file +<pre>-f, --input-file <filename></pre> + +Provide the name of a file that contains a list of test case names - one per line. Blank lines are skipped and anything after the comment character, ```#```, is ignored. + +A useful way to generate an initial instance of this file is to use the <a href="#list-test-names-only">list-test-names-only</a> option. This can then be manually curated to specify a specific subset of tests - or in a specific order. + +<a id="list-test-names-only"></a> +## Just test names +<pre>--list-test-names-only</pre> + +This option lists all available tests in a non-indented form, one on each line. This makes it ideal for saving to a file and feeding back into the <a href="#input-file">```-f``` or ```--input-file```</a> option. + + +<a id="order"></a> +## Specify the order test cases are run +<pre>--order <decl|lex|rand></pre> + +Test cases are ordered one of three ways: + + +### decl +Declaration order. The order the tests were originally declared in. Note that ordering between files is not guaranteed and is implementation dependent. + +### lex +Lexicographically sorted. Tests are sorted, alpha-numerically, by name. + +### rand +Randomly sorted. Test names are sorted using ```std::random_shuffle()```. By default the random number generator is seeded with 0 - and so the order is repeatable. To control the random seed see <a href="#rng-seed">rng-seed</a>. + +<a id="rng-seed"></a> +## Specify a seed for the Random Number Generator +<pre>--rng-seed <'time'|number></pre> + +Sets a seed for the random number generator using ```std::srand()```. +If a number is provided this is used directly as the seed so the random pattern is repeatable. +Alternatively if the keyword ```time``` is provided then the result of calling ```std::time(0)``` is used and so the pattern becomes unpredictable. + +In either case the actual value for the seed is printed as part of Catch's output so if an issue is discovered that is sensitive to test ordering the ordering can be reproduced - even if it was originally seeded from ```std::time(0)```. + +<a id="usage"></a> +## Usage +<pre>-h, -?, --help</pre> + +Prints the command line arguments to stdout + +--- + +[Home](Readme.md)
\ No newline at end of file diff --git a/unittest/Catch/docs/configuration.md b/unittest/Catch/docs/configuration.md new file mode 100644 index 0000000..3305219 --- /dev/null +++ b/unittest/Catch/docs/configuration.md @@ -0,0 +1,73 @@ +Catch is designed to "just work" as much as possible. For most people the only configuration needed is telling Catch which source file should host all the implementation code (```CATCH_CONFIG_MAIN```). + +Nonetheless there are still some occasions where finer control is needed. For these occasions Catch exposes a small set of macros for configuring how it is built. + +# main()/ implementation + + CATCH_CONFIG_MAIN // Designates this as implementation file and defines main() + CATCH_CONFIG_RUNNER // Designates this as implementation file + +Although Catch is header only it still, internally, maintains a distinction between interface headers and headers that contain implementation. Only one source file in your test project should compile the implementation headers and this is controlled through the use of one of these macros - one of these identifiers should be defined before including Catch in *exactly one implementation file in your project*. + +# Prefixing Catch macros + + CATCH_CONFIG_PREFIX_ALL + +To keep test code clean and uncluttered Catch uses short macro names (e.g. ```TEST_CASE``` and ```REQUIRE```). Occasionally these may conflict with identifiers from platform headers or the system under test. In this case the above identifier can be defined. This will cause all the Catch user macros to be prefixed with ```CATCH_``` (e.g. ```CATCH_TEST_CASE``` and ```CATCH_REQUIRE```). + + +# Terminal colour + + CATCH_CONFIG_COLOUR_NONE // completely disables all text colouring + CATCH_CONFIG_COLOUR_WINDOWS // forces the Win32 console API to be used + CATCH_CONFIG_COLOUR_ANSI // forces ANSI colour codes to be used + +Yes, I am English, so I will continue to spell "colour" with a 'u'. + +When sending output to the terminal, if it detects that it can, Catch will use colourised text. On Windows the Win32 API, ```SetConsoleTextAttribute```, is used. On POSIX systems ANSI colour escape codes are inserted into the stream. + +For finer control you can define one of the above identifiers (these are mutually exclusive - but that is not checked so may behave unexpectedly if you mix them): + +Note that when ANSI colour codes are used "unistd.h" must be includable - along with a definition of ```isatty()``` + +Typically you should place the ```#define``` before #including "catch.hpp" in your main source file - but if you prefer you can define it for your whole project by whatever your IDE or build system provides for you to do so. + +# Console width + + CATCH_CONFIG_CONSOLE_WIDTH = x // where x is a number + +Catch formats output intended for the console to fit within a fixed number of characters. This is especially important as indentation is used extensively and uncontrolled line wraps break this. +By default a console width of 80 is assumed but this can be controlled by defining the above identifier to be a different value. + +# stdout + + CATCH_CONFIG_NOSTDOUT + +Catch does not use ```std::cout``` and ```std::cerr``` directly but gets them from ```Catch::cout()``` and ```Catch::cerr()``` respectively. If the above identifier is defined these functions are left unimplemented and you must implement them yourself. Their signatures are: + + std::ostream& cout(); + std::ostream& cerr(); + +This can be useful on certain platforms that do not provide ```std::cout``` and ```std::cerr```, such as certain embedded systems. + +# C++ conformance toggles + + CATCH_CONFIG_CPP11_NULLPTR // nullptr is supported? + CATCH_CONFIG_CPP11_NOEXCEPT // noexcept is supported? + CATCH_CONFIG_CPP11_GENERATED_METHODS // delete and default keywords for methods + CATCH_CONFIG_CPP11_IS_ENUM // std::is_enum is supported? + CATCH_CONFIG_CPP11_TUPLE // std::tuple is supported + CATCH_CONFIG_VARIADIC_MACROS // Usually pre-C++11 compiler extensions are sufficient + CATCH_CONFIG_CPP11_LONG_LONG // generates overloads for the long long type + CATCH_CONFIG_CPP11_OVERRIDE // CATCH_OVERRIDE expands to override (for virtual function implementations) + CATCH_CONFIG_CPP11_UNIQUE_PTR // Use std::unique_ptr instead of std::auto_ptr + +Catch has some basic compiler detection that will attempt to select the appropriate mix of these macros. However being incomplete - and often without access to the respective compilers - this detection tends to be conservative. +So overriding control is given to the user. If a compiler supports a feature (and Catch does not already detect it) then one or more of these may be defined to enable it (or suppress it, in some cases). If you do do this please raise an issue, specifying your compiler version (ideally with an idea of how to detect it) and stating that it has such support. +You may also suppress any of these features by using the `_NO_` form, e.g. `CATCH_CONFIG_CPP11_NO_NULLPTR`. + +All C++11 support can be disabled with `CATCH_CONFIG_NO_CPP11` + +--- + +[Home](Readme.md)
\ No newline at end of file diff --git a/unittest/Catch/docs/contributing.md b/unittest/Catch/docs/contributing.md new file mode 100644 index 0000000..49a663c --- /dev/null +++ b/unittest/Catch/docs/contributing.md @@ -0,0 +1,23 @@ +# Contributing to Catch + +So you want to contribute something to Catch? That's great! Whether it's a bug fix, a new feature, support for additional compilers - or just a fix to the documentation - all contributions are very welcome and very much appreciated. Of course so are bug reports and other comments and questions. + +If you are contributing to the code base there are a few simple guidelines to keep in mind. This also includes notes to help you find your way around. As this is liable to drift out of date please raise an issue or, better still, a pull request for this file, if you notice that. + +## Branches + +Ongoing development is on the "develop" branch (if there is one, currently), or on feature branches that are branched off of develop. Please target any pull requests at develop, or, for larger chunks of work, a branch off of develop. + +## Directory structure + +Users of Catch primarily use the single header version. Maintainers should work with the full source (which is still, primarily, in headers). This can be found in the ```include``` folder, but you may prefer to use one of the IDE project files (for MSVC or XCode). These can be found under ```projects/```*IDE Name*```/```*project name*. A number of contributors have proposed make files, and submitted their own versions. At some point these should be made available too. + +In addition to the include files and IDE projects there are a number of tests in cpp files. These can all be found in ```projects/SelfTest```. You'll also see a ```SurrogateCpps``` directory in there. This contains a set of cpp files that each ```#include``` a single header. While these files are not essential to compilation they help to keep the implementation headers self-contained. At time of writing this set is not complete but has reasonable coverage. If you add additional headers please try to remember to add a surrogate cpp for it. + +The other directories are ```scripts``` which contains a set of python scripts to help in testing Catch as well as generating the single include, and docs, which contains the documentation as a set of markdown files. + + *this document is in-progress...* + +--- + +[Home](Readme.md)
\ No newline at end of file diff --git a/unittest/Catch/docs/logging.md b/unittest/Catch/docs/logging.md new file mode 100644 index 0000000..a659b3e --- /dev/null +++ b/unittest/Catch/docs/logging.md @@ -0,0 +1,52 @@ +# Logging macros + +Additional messages can be logged during a test case. + +## Streaming macros + +All these macros allow heterogenous sequences of values to be streaming using the insertion operator (```<<```) in the same way that std::ostream, std::cout, etc support it. + +E.g.: +```c++ +INFO( "The number is " << i ); +``` + +(Note that there is no initial ```<<``` - instead the insertion sequence is placed in parentheses.) +These macros come in three forms: + +**INFO(** _message expression_ **)** + +The message is logged to a buffer, but only reported with the next assertion that is logged. This allows you to log contextual information in case of failures which is not shown during a successful test run (for the console reporter, without -s). Messages are removed from the buffer at the end of their scope, so may be used, for example, in loops. + +**WARN(** _message expression_ **)** + +The message is always reported but does not fail the test. + +**FAIL(** _message expression_ **)** + +The message is reported and the test case fails. + +## Quickly capture a variable value + +**CAPTURE(** _expression_ **)** + +Sometimes you just want to log the name and value of a variable. While you can easily do this with the INFO macro, above, as a convenience the CAPTURE macro handles the stringising of the variable name for you (actually it works with any expression, not just variables). + +E.g. +```c++ +CAPTURE( theAnswer ); +``` + +This would log something like: + +<pre>"theAnswer := 42"</pre> + +## Deprecated macros + +**SCOPED_INFO and SCOPED_CAPTURE** + +These macros are now deprecated and are just aliases for INFO and CAPTURE (which were not previously scoped). + +--- + +[Home](Readme.md)
\ No newline at end of file diff --git a/unittest/Catch/docs/own-main.md b/unittest/Catch/docs/own-main.md new file mode 100644 index 0000000..f8c836e --- /dev/null +++ b/unittest/Catch/docs/own-main.md @@ -0,0 +1,68 @@ +# Supplying main() yourself + +The easiest way to use Catch is to let it supply ```main()``` for you and handle configuring itself from the command line. + +This is achieved by writing ```#define CATCH_CONFIG_MAIN``` before the ```#include "catch.hpp"``` in *exactly one* source file. + +Sometimes, though, you need to write your own version of main(). You can do this by writing ```#define CATCH_CONFIG_RUNNER``` instead. Now you are free to write ```main()``` as normal and call into Catch yourself manually. + +You now have a lot of flexibility - but here are three recipes to get your started: + +## Let Catch take full control of args and config + +If you just need to have code that executes before and/ or after Catch this is the simplest option. + +```c++ +#define CATCH_CONFIG_RUNNER +#include "catch.hpp" + +int main( int argc, char* const argv[] ) +{ + // global setup... + + int result = Catch::Session().run( argc, argv ); + + // global clean-up... + + return result; +} +``` + +## Amending the config + +If you still want Catch to process the command line, but you want to programatically tweak the config, you can do so in one of two ways: + +```c++ +#define CATCH_CONFIG_RUNNER +#include "catch.hpp" + +int main( int argc, char* const argv[] ) +{ + Catch::Session session; // There must be exactly once instance + + // writing to session.configData() here sets defaults + // this is the preferred way to set them + + int returnCode = session.applyCommandLine( argc, argv ); + if( returnCode != 0 ) // Indicates a command line error + return returnCode; + + // writing to session.configData() or session.Config() here + // overrides command line args + // only do this if you know you need to + + return session.run(); +} +``` + +Take a look at the definitions of Config and ConfigData to see what you can do with them. + +To take full control of the config simply omit the call to ```applyCommandLine()```. + +## Adding your own command line options + +Catch embeds a powerful command line parser which you can also use to parse your own options out. This capability is still in active development but will be documented here when it is ready. + +--- + +[Home](Readme.md)
\ No newline at end of file diff --git a/unittest/Catch/docs/slow-compiles.md b/unittest/Catch/docs/slow-compiles.md new file mode 100644 index 0000000..5291aec --- /dev/null +++ b/unittest/Catch/docs/slow-compiles.md @@ -0,0 +1,22 @@ +# Why do my tests take so long to compile? + +Several people have reported that test code written with Catch takes much longer to compile than they would expect. Why is that? + +Catch is implemented entirely in headers. There is a little overhead due to this - but not as much as you might think - and you can minimise it simply by organising your test code as follows: + +## Short answer +Exactly one source file must ```#define``` either ```CATCH_CONFIG_MAIN``` or ```CATCH_CONFIG_RUNNER``` before ```#include```-ing Catch. In this file *do not write any test cases*! In most cases that means this file will just contain two lines (the ```#define``` and the ```#include```). + +## Long answer + +Usually C++ code is split between a header file, containing declarations and prototypes, and an implementation file (.cpp) containing the definition, or implementation, code. Each implementation file, along with all the headers that it includes (and which those headers include, etc), is expanded into a single entity called a translation unit - which is then passed to the compiler and compiled down to an object file. + +But functions and methods can also be written inline in header files. The downside to this is that these definitions will then be compiled in *every* translation unit that includes the header. + +Because Catch is implemented *entirely* in headers you might think that the whole of Catch must be compiled into every translation unit that uses it! Actually it's not quite as bad as that. Catch mitigates this situation by effectively maintaining the traditional separation between the implementation code and declarations. Internally the implementation code is protected by ```#ifdef```s and is conditionally compiled into only one translation unit. This translation unit is that one that ```#define```s ```CATCH_CONFIG_MAIN``` or ```CATCH_CONFIG_RUNNER```. Let's call this the main source file. + +As a result the main source file *does* compile the whole of Catch every time! So it makes sense to dedicate this file to *only* ```#define```-ing the identifier and ```#include```-ing Catch (and implementing the runner code, if you're doing that). Keep all your test cases in other files. This way you won't pay the recompilation cost for the whole of Catch + +--- + +[Home](Readme.md)
\ No newline at end of file diff --git a/unittest/Catch/docs/test-cases-and-sections.md b/unittest/Catch/docs/test-cases-and-sections.md new file mode 100644 index 0000000..86644f0 --- /dev/null +++ b/unittest/Catch/docs/test-cases-and-sections.md @@ -0,0 +1,86 @@ +# Test cases and sections + +While Catch fully supports the traditional, xUnit, style of class-based fixtures containing test case methods this is not the preferred style. + +Instead Catch provides a powerful mechanism for nesting test case sections within a test case. For a more detailed discussion see the [tutorial](tutorial.md#testCasesAndSections). + +Test cases and sections are very easy to use in practice: + +* **TEST_CASE(** _test name_ \[, _tags_ \] **)** +* **SECTION(** _section name_ **)** + +_test name_ and _section name_ are free form, quoted, strings. The optional _tags_ argument is a quoted string containing one or more tags enclosed in square brackets. Tags are discussed below. Test names must be unique within the Catch executable. + +For examples see the [Tutorial](tutorial.md) + +## Tags + +Tags allow an arbitrary number of additional strings to be associated with a test case. Test cases can be selected (for running, or just for listing) by tag - or even by an expression that combines several tags. At their most basic level they provide a simple way to group several related tests together. + +As an example - given the following test cases: + + TEST_CASE( "A", "[widget]" ) { /* ... */ } + TEST_CASE( "B", "[widget]" ) { /* ... */ } + TEST_CASE( "C", "[gadget]" ) { /* ... */ } + TEST_CASE( "D", "[widget][gadget]" ) { /* ... */ } + +The tag expression, ```"[widget]"``` selects A, B & D. ```"[gadget]"``` selects C & D. ```"[widget][gadget]"``` selects just D and ```"[widget],[gadget]"``` selects all four test cases. + +For more detail on command line selection see [the command line docs](command-line.md#specifying-which-tests-to-run) + +Tag names are not case sensitive. + +### Special Tags + +All tag names beginning with non-alphanumeric characters are reserved by Catch. Catch defines a number of "special" tags, which have meaning to the test runner itself. These special tags all begin with a symbol character. Following is a list of currently defined special tags and their meanings. + +* `[!hide]` or `[.]` (or, for legacy reasons, `[hide]`) - causes test cases to be skipped from the default list (ie when no test cases have been explicitly selected through tag expressions or name wildcards). The hide tag is often combined with another, user, tag (for example `[.][integration]` - so all integration tests are excluded from the default run but can be run by passing `[integration]` on the command line). As a short-cut you can combine these by simply prefixing your user tag with a `.` - e.g. `[.integration]`. Because the hide tag has evolved to have several forms, all forms are added as tags if you use one of them. + +* `[!throws]` - lets Catch know that this test is likely to throw an exception even if successful. This causes the test to be exluded when running with `-e` or `--nothrow`. + +* `[!shouldfail]` - reverse the failing logic of the test: if the test is successful if it fails, and vice-versa. + +* `[!mayfail]` - doesn't fail the test if any given assertion fails (but still reports it). This can be useful to flag a work-in-progress, or a known issue that you don't want to immediately fix but still want to track in the your tests. + +* `[#<filename>]` - running with `-#` or `--filenames-as-tags` causes Catch to add the filename, prefixed with `#` (and with any extension stripped) as a tag. e.g. tests in testfile.cpp would all be tagged `[#testfile]`. + +* `[@<alias>]` - tag aliases all begin with `@` (see below). + +## Tag aliases + +Between tag expressions and wildcarded test names (as well as combinations of the two) quite complex patterns can be constructed to direct which test cases are run. If a complex pattern is used often it is convenient to be able to create an alias for the expression. this can be done, in code, using the following form: + + CATCH_REGISTER_TAG_ALIAS( <alias string>, <tag expression> ) + +Aliases must begining with the `@` character. An example of a tag alias is: + + CATCH_REGISTER_TAG_ALIAS( "[@nhf]", "[failing]~[.]" ) + +Now when `[@nhf]` is used on the command line this matches all tests that are tagged `[failing]`, but which are not also hidden. + +## BDD-style test cases + +In addition to Catch's take on the classic style of test cases, Catch supports an alternative syntax that allow tests to be written as "executable specifications" (one of the early goals of [Behaviour Driven Development](http://dannorth.net/introducing-bdd/)). This set of macros map on to ```TEST_CASE```s and ```SECTION```s, with a little internal support to make them smoother to work with. + +* **SCENARIO(** _scenario name_ \[, _tags_ \] **)** + +This macro maps onto ```TEST_CASE``` and works in the same way, except that the test case name will be prefixed by "Scenario: " + +* **GIVEN(** _something_ **)** +* **WHEN(** _something_ **)** +* **THEN(** _something_ **)** + +These macros map onto ```SECTION```s except that the section names are the _something_s prefixed by "given: ", "when: " or "then: " respectively. + +* **AND_WHEN(** _something_ **)** +* **AND_THEN(** _something_ **)** + +Similar to ```WHEN``` and ```THEN``` except that the prefixes start with "and ". These are used to chain ```WHEN```s and ```THEN```s together. + +When any of these macros are used the console reporter recognises them and formats the test case header such that the Givens, Whens and Thens are aligned to aid readability. + +Other than the additional prefixes and the formatting in the console reporter these macros behave exactly as ```TEST_CASE```s and ```SECTION```s. As such there is nothing enforcing the correct sequencing of these macros - that's up to the programmer! + +--- + +[Home](Readme.md)
\ No newline at end of file diff --git a/unittest/Catch/docs/test-fixtures.md b/unittest/Catch/docs/test-fixtures.md new file mode 100644 index 0000000..6bef762 --- /dev/null +++ b/unittest/Catch/docs/test-fixtures.md @@ -0,0 +1,32 @@ +Although Catch allows you to group tests together as sections within a test case, it can still convenient, sometimes, to group them using a more traditional test fixture. Catch fully supports this too. You define the test fixture as a simple structure: + +```c++ +class UniqueTestsFixture { + private: + static int uniqueID; + protected: + DBConnection conn; + public: + UniqueTestsFixture() : conn(DBConnection::createConnection("myDB")) { + } + protected: + int getID() { + return ++uniqueID; + } + }; + + int UniqueTestsFixture::uniqueID = 0; + + TEST_CASE_METHOD(UniqueTestsFixture, "Create Employee/No Name", "[create]") { + REQUIRE_THROWS(conn.executeSQL("INSERT INTO employee (id, name) VALUES (?, ?)", getID(), "")); + } + TEST_CASE_METHOD(UniqueTestsFixture, "Create Employee/Normal", "[create]") { + REQUIRE(conn.executeSQL("INSERT INTO employee (id, name) VALUES (?, ?)", getID(), "Joe Bloggs")); + } +``` + +The two test cases here will create uniquely-named derived classes of UniqueTestsFixture and thus can access the `getID()` protected method and `conn` member variables. This ensures that both the test cases are able to create a DBConnection using the same method (DRY principle) and that any ID's created are unique such that the order that tests are executed does not matter. + +--- + +[Home](Readme.md)
\ No newline at end of file diff --git a/unittest/Catch/docs/tostring.md b/unittest/Catch/docs/tostring.md new file mode 100644 index 0000000..dbb6cb8 --- /dev/null +++ b/unittest/Catch/docs/tostring.md @@ -0,0 +1,70 @@ +# String conversions + +Catch needs to be able to convert types you use in assertions and logging expressions into strings (for logging and reporting purposes). +Most built-in or std types are supported out of the box but there are three ways that you can tell Catch how to convert your own types (or other, third-party types) into strings. + +## operator << overload for std::ostream + +This is the standard way of providing string conversions in C++ - and the chances are you may already provide this for your own purposes. If you're not familiar with this idiom it involves writing a free function of the form: + +``` +std::ostream& operator << ( std::ostream& os, T const& value ) { + os << convertMyTypeToString( value ); + return os; +} +``` + +(where ```T``` is your type and ```convertMyTypeToString``` is where you'll write whatever code is necessary to make your type printable - it doesn't have to be in another function). + +You should put this function in the same namespace as your type. + +Alternatively you may prefer to write it as a member function: + +``` +std::ostream& T::operator << ( std::ostream& os ) const { + os << convertMyTypeToString( *this ); + return os; +} +``` + +## Catch::toString overload + +If you don't want to provide an ```operator <<``` overload, or you want to convert your type differently for testing purposes, you can provide an overload for ```Catch::toString()``` for your type. + +``` +namespace Catch { + std::string toString( T const& value ) { + return convertMyTypeToString( value ); + } +} +``` + +Again ```T``` is your type and ```convertMyTypeToString``` is where you'll write whatever code is necessary to make your type printable. Note that the function must be in the Catch namespace, which itself must be in the global namespace. + +## Catch::StringMaker<T> specialisation + +There are some cases where overloading toString does not work as expected. Specialising StringMaker<T> gives you more precise, and reliable, control - but at the cost of slightly more code and complexity: + +``` +namespace Catch { + template<> struct StringMaker<T> { + static std::string convert( T const& value ) { + return convertMyTypeToString( value ); + } + }; +} +``` + +## Exceptions + +By default all exceptions deriving from `std::exception` will be translated to strings by calling the `what()` method. For exception types that do not derive from `std::exception` - or if `what()` does not return a suitable string - use `CATCH_TRANSLATE_EXCEPTION`. This defines a function that takes your exception type, by reference, and returns a string. It can appear anywhere in the code - it doesn't have to be in the same translation unit. For example: + +``` +CATCH_TRANSLATE_EXCEPTION( MyType& ex ) { + return ex.message(); +} +``` + +--- + +[Home](Readme.md) diff --git a/unittest/Catch/docs/tutorial.md b/unittest/Catch/docs/tutorial.md new file mode 100644 index 0000000..0fdaff9 --- /dev/null +++ b/unittest/Catch/docs/tutorial.md @@ -0,0 +1,249 @@ +# Getting Catch + +The simplest way to get Catch is to download the single header version from [http://builds.catch-lib.net](http://builds.catch-lib.net). Don't be put off by the word "builds" there. The single header is generated by merging a set of individual headers but it is still just normal source code in a header file. + +The full source for Catch, including test projects, documentation, and other things, is hosted on GitHub. [http://catch-lib.net](http://catch-lib.net) will redirect you there. + + +## Where to put it? + +Catch is header only. All you need to do is drop the file(s) somewhere reachable from your project - either in some central location you can set your header search path to find, or directly into your project tree itself! This is a particularly good option for other Open-Source projects that want to use Catch for their test suite. See [this blog entry for more on that](http://www.levelofindirection.com/journal/2011/5/27/unit-testing-in-c-and-objective-c-just-got-ridiculously-easi.html). + +The rest of this tutorial will assume that the Catch single-include header (or the include folder) is available unqualified - but you may need to prefix it with a folder name if necessary. + +# Writing tests + +Let's start with a really simple example. Say you have written a function to calculate factorials and now you want to test it (let's leave aside TDD for now). + +```c++ +unsigned int Factorial( unsigned int number ) { + return number <= 1 ? number : Factorial(number-1)*number; +} +``` + +To keep things simple we'll put everything in a single file (<a href="#scaling-up">see later for more on how to structure your test files</a>) + +```c++ +#define CATCH_CONFIG_MAIN // This tells Catch to provide a main() - only do this in one cpp file +#include "catch.hpp" + +unsigned int Factorial( unsigned int number ) { + return number <= 1 ? number : Factorial(number-1)*number; +} + +TEST_CASE( "Factorials are computed", "[factorial]" ) { + REQUIRE( Factorial(1) == 1 ); + REQUIRE( Factorial(2) == 2 ); + REQUIRE( Factorial(3) == 6 ); + REQUIRE( Factorial(10) == 3628800 ); +} +``` + +This will compile to a complete executable which responds to [command line arguments](command-line.md). If you just run it with no arguments it will execute all test cases (in this case there is just one), report any failures, report a summary of how many tests passed and failed and return the number of failed tests (useful for if you just want a yes/ no answer to: "did it work"). + +If you run this as written it will pass. Everything is good. Right? +Well, there is still a bug here. In fact the first version of this tutorial I posted here genuinely had the bug in! So it's not completely contrived (thanks to Daryle Walker (```@CTMacUser```) for pointing this out). + +What is the bug? Well what is the factorial of zero? +[The factorial of zero is one](http://mathforum.org/library/drmath/view/57128.html) - which is just one of those things you have to know (and remember!). + +Let's add that to the test case: + +```c++ +TEST_CASE( "Factorials are computed", "[factorial]" ) { + REQUIRE( Factorial(0) == 1 ); + REQUIRE( Factorial(1) == 1 ); + REQUIRE( Factorial(2) == 2 ); + REQUIRE( Factorial(3) == 6 ); + REQUIRE( Factorial(10) == 3628800 ); +} +``` + +Now we get a failure - something like: + +``` +Example.cpp:9: FAILED: + REQUIRE( Factorial(0) == 1 ) +with expansion: + 0 == 1 +``` + +Note that we get the actual return value of Factorial(0) printed for us (0) - even though we used a natural expression with the == operator. That let's us immediately see what the problem is. + +Let's change the factorial function to: + +```c++ +unsigned int Factorial( unsigned int number ) { + return number > 1 ? Factorial(number-1)*number : 1; +} +``` + +Now all the tests pass. + +Of course there are still more issues to do deal with. For example we'll hit problems when the return value starts to exceed the range of an unsigned int. With factorials that can happen quite quickly. You might want to add tests for such cases and decide how to handle them. We'll stop short of doing that here. + +## What did we do here? + +Although this was a simple test it's been enough to demonstrate a few things about how Catch is used. Let's take moment to consider those before we move on. + +1. All we did was ```#define``` one identifier and ```#include``` one header and we got everything - even an implementation of ```main()``` that will [respond to command line arguments](command-line.md). You can only use that ```#define``` in one implementation file, for (hopefully) obvious reasons. Once you have more than one file with unit tests in you'll just ```#include "catch.hpp"``` and go. Usually it's a good idea to have a dedicated implementation file that just has ```#define CATCH_CONFIG_MAIN``` and ```#include "catch.hpp"```. You can also provide your own implementation of main and drive Catch yourself (see [Supplying-your-own-main()](own-main.md)). +2. We introduce test cases with the ```TEST_CASE``` macro. This macro takes one or two arguments - a free form test name and, optionally, one or more tags (for more see <a href="#test-cases-and-sections">Test cases and Sections</a>, ). The test name must be unique. You can run sets of tests by specifying a wildcarded test name or a tag expression. See the [command line docs](command-line.md) for more information on running tests. +3. The name and tags arguments are just strings. We haven't had to declare a function or method - or explicitly register the test case anywhere. Behind the scenes a function with a generated name is defined for you, and automatically registered using static registry classes. By abstracting the function name away we can name our tests without the constraints of identifier names. +4. We write our individual test assertions using the ```REQUIRE``` macro. Rather than a separate macro for each type of condition we express the condition naturally using C/C++ syntax. Behind the scenes a simple set of expression templates captures the left-hand-side and right-hand-side of the expression so we can display the values in our test report. As we'll see later there _are_ other assertion macros - but because of this technique the number of them is drastically reduced. + +<a id="test-cases-and-sections"></a> +## Test cases and sections + +Most test frameworks have a class-based fixture mechanism. That is, test cases map to methods on a class and common setup and teardown can be performed in ```setup()``` and ```teardown()``` methods (or constructor/ destructor in languages, like C++, that support deterministic destruction). + +While Catch fully supports this way of working there are a few problems with the approach. In particular the way your code must be split up, and the blunt granularity of it, may cause problems. You can only have one setup/ teardown pair across a set of methods, but sometimes you want slightly different setup in each method, or you may even want several levels of setup (a concept which we will clarify later on in this tutorial). It was <a href="http://jamesnewkirk.typepad.com/posts/2007/09/why-you-should-.html">problems like these</a> that led James Newkirk, who led the team that built NUnit, to start again from scratch and <a href="http://jamesnewkirk.typepad.com/posts/2007/09/announcing-xuni.html">build xUnit</a>). + +Catch takes a different approach (to both NUnit and xUnit) that is a more natural fit for C++ and the C family of languages. This is best explained through an example: + +```c++ +TEST_CASE( "vectors can be sized and resized", "[vector]" ) { + + std::vector<int> v( 5 ); + + REQUIRE( v.size() == 5 ); + REQUIRE( v.capacity() >= 5 ); + + SECTION( "resizing bigger changes size and capacity" ) { + v.resize( 10 ); + + REQUIRE( v.size() == 10 ); + REQUIRE( v.capacity() >= 10 ); + } + SECTION( "resizing smaller changes size but not capacity" ) { + v.resize( 0 ); + + REQUIRE( v.size() == 0 ); + REQUIRE( v.capacity() >= 5 ); + } + SECTION( "reserving bigger changes capacity but not size" ) { + v.reserve( 10 ); + + REQUIRE( v.size() == 5 ); + REQUIRE( v.capacity() >= 10 ); + } + SECTION( "reserving smaller does not change size or capacity" ) { + v.reserve( 0 ); + + REQUIRE( v.size() == 5 ); + REQUIRE( v.capacity() >= 5 ); + } +} +``` + +For each ```SECTION``` the ```TEST_CASE``` is executed from the start - so as we enter each section we know that size is 5 and capacity is at least 5. We enforced those requirements with the ```REQUIRE```s at the top level so we can be confident in them. +This works because the ```SECTION``` macro contains an if statement that calls back into Catch to see if the section should be executed. One leaf section is executed on each run through a ```TEST_CASE```. The other sections are skipped. Next time through the next section is executed, and so on until no new sections are encountered. + +So far so good - this is already an improvement on the setup/teardown approach because now we see our setup code inline and use the stack. + +The power of sections really shows, however, when we need to execute a sequence of, checked, operations. Continuing the vector example, we might want to verify that attempting to reserve a capacity smaller than the current capacity of the vector changes nothing. We can do that, naturally, like so: + +```c++ + SECTION( "reserving bigger changes capacity but not size" ) { + v.reserve( 10 ); + + REQUIRE( v.size() == 5 ); + REQUIRE( v.capacity() >= 10 ); + + SECTION( "reserving smaller again does not change capacity" ) { + v.reserve( 7 ); + + REQUIRE( v.capacity() >= 10 ); + } + } +``` + +Sections can be nested to an arbitrary depth (limited only by your stack size). Each leaf section (i.e. a section that contains no nested sections) will be executed exactly once, on a separate path of execution from any other leaf section (so no leaf section can interfere with another). A failure in a parent section will prevent nested sections from running - but then that's the idea. + +## BDD-Style + +If you name your test cases and sections appropriately you can achieve a BDD-style specification structure. This became such a useful way of working that first class support has been added to Catch. Scenarios can be specified using ```SCENARIO```, ```GIVEN```, ```WHEN``` and ```THEN``` macros, which map on to ```TEST_CASE```s and ```SECTION```s, respectively. For more details see [Test cases and sections](test-cases-and-sections.md). + +The vector example can be adjusted to use these macros like so: + +```c++ +SCENARIO( "vectors can be sized and resized", "[vector]" ) { + + GIVEN( "A vector with some items" ) { + std::vector<int> v( 5 ); + + REQUIRE( v.size() == 5 ); + REQUIRE( v.capacity() >= 5 ); + + WHEN( "the size is increased" ) { + v.resize( 10 ); + + THEN( "the size and capacity change" ) { + REQUIRE( v.size() == 10 ); + REQUIRE( v.capacity() >= 10 ); + } + } + WHEN( "the size is reduced" ) { + v.resize( 0 ); + + THEN( "the size changes but not capacity" ) { + REQUIRE( v.size() == 0 ); + REQUIRE( v.capacity() >= 5 ); + } + } + WHEN( "more capacity is reserved" ) { + v.reserve( 10 ); + + THEN( "the capacity changes but not the size" ) { + REQUIRE( v.size() == 5 ); + REQUIRE( v.capacity() >= 10 ); + } + } + WHEN( "less capacity is reserved" ) { + v.reserve( 0 ); + + THEN( "neither size nor capacity are changed" ) { + REQUIRE( v.size() == 5 ); + REQUIRE( v.capacity() >= 5 ); + } + } + } +} +``` + +Conveniently, these tests will be reported as follows when run: + +``` +Scenario: vectors can be sized and resized + Given: A vector with some items + When: more capacity is reserved + Then: the capacity changes but not the size +``` + +<a id="scaling-up"></a> +## Scaling up + +To keep the tutorial simple we put all our code in a single file. This is fine to get started - and makes jumping into Catch even quicker and easier. As you write more real-world tests, though, this is not really the best approach. + +The requirement is that the following block of code ([or equivalent](own-main.md)): + +```c++ +#define CATCH_CONFIG_MAIN +#include "catch.hpp" +``` + +appears in _exactly one_ source file. Use as many additional cpp files (or whatever you call your implementation files) as you need for your tests, partitioned however makes most sense for your way of working. Each additional file need only ```#include "catch.hpp"``` - do not repeat the ```#define```! + +In fact it is usually a good idea to put the block with the ```#define``` [in it's own source file](slow-compiles.md). + +Do not write your tests in header files! + + +## Next steps + +This has been a brief introduction to get you up and running with Catch, and to point out some of the key differences between Catch and other frameworks you may already be familiar with. This will get you going quite far already and you are now in a position to dive in and write some tests. + +Of course there is more to learn - most of which you should be able to page-fault in as you go. Please see the ever-growing [Reference section](Readme.md) for what's available. + +--- + +[Home](Readme.md) diff --git a/unittest/Catch/docs/why-catch.md b/unittest/Catch/docs/why-catch.md new file mode 100644 index 0000000..93488d2 --- /dev/null +++ b/unittest/Catch/docs/why-catch.md @@ -0,0 +1,42 @@ +# Why do we need yet another C++ test framework? + +Good question. For C++ there are quite a number of established frameworks, including (but not limited to), [CppUnit](http://sourceforge.net/apps/mediawiki/cppunit/index.php?title=Main_Page), [Google Test](http://code.google.com/p/googletest/), [Boost.Test](http://www.boost.org/doc/libs/1_49_0/libs/test/doc/html/index.html), [Aeryn](https://launchpad.net/aeryn), [Cute](http://r2.ifs.hsr.ch/cute), [Fructose](http://fructose.sourceforge.net/) and [many, many more](http://en.wikipedia.org/wiki/List_of_unit_testing_frameworks#C.2B.2B). Even for Objective-C there are a few, including OCUnit - which now comes bundled with XCode. + +So what does Catch bring to the party that differentiates it from these? Apart from a Catchy name, of course. + +## Key Features + +* Really easy to get started. Just download catch.hpp, #include it and you're away. +* No external dependencies. As long as you can compile C++98 and have a C++ standard library available. +* Write test cases as, self-registering, functions or methods. +* Divide test cases into sections, each of which is run in isolation (eliminates the need for fixtures!) +* Use BDD-style Given-When-Then sections as well as traditional unit test cases. +* Only one core assertion macro for comparisons. Standard C/C++ operators are used for the comparison - yet the full expression is decomposed and lhs and rhs values are logged. + +## Other core features + +* Tests are named using free-form strings - no more couching names in legal identifiers. +* Tests can be tagged for easily running ad-hoc groups of tests. +* Failures can (optionally) break into the debugger on Windows and Mac. +* Output is through modular reporter objects. Basic textual and XML reporters are included. Custom reporters can easily be added. +* JUnit xml output is supported for integration with third-party tools, such as CI servers. +* A default main() function is provided (in a header), but you can supply your own for complete control (e.g. integration into your own test runner GUI). +* A command line parser is provided and can still be used if you choose to provided your own main() function. +* Catch can test itself. +* Alternative assertion macro(s) report failures but don't abort the test case +* Floating point tolerance comparisons are built in using an expressive Approx() syntax. +* Internal and friendly macros are isolated so name clashes can be managed +* Support for Matchers (early stages) + +## Objective-C-specific features + +* Automatically detects if you are using it from an Objective-C project +* Works with and without ARC with no additional configuration +* Implement test fixtures using Obj-C classes too (like OCUnit) +* Additional built in matchers that work with Obj-C types (e.g. string matchers) + +See the [tutorial](tutorial.md) to get more of a taste of using CATCH in practice + +--- + +[Home](Readme.md)
\ No newline at end of file diff --git a/unittest/Catch/include/catch.hpp b/unittest/Catch/include/catch.hpp new file mode 100644 index 0000000..332fcd0 --- /dev/null +++ b/unittest/Catch/include/catch.hpp @@ -0,0 +1,213 @@ +/* + * Created by Phil on 22/10/2010. + * Copyright 2010 Two Blue Cubes Ltd + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + */ + +#ifndef TWOBLUECUBES_CATCH_HPP_INCLUDED +#define TWOBLUECUBES_CATCH_HPP_INCLUDED + +#ifdef __clang__ +# pragma clang system_header +#elif defined __GNUC__ +# pragma GCC system_header +#endif + +#include "internal/catch_suppress_warnings.h" + +#if defined(CATCH_CONFIG_MAIN) || defined(CATCH_CONFIG_RUNNER) +# define CATCH_IMPL +#endif + +#ifdef CATCH_IMPL +# ifndef CLARA_CONFIG_MAIN +# define CLARA_CONFIG_MAIN_NOT_DEFINED +# define CLARA_CONFIG_MAIN +# endif +#endif + +#include "internal/catch_notimplemented_exception.h" +#include "internal/catch_context.h" +#include "internal/catch_test_registry.hpp" +#include "internal/catch_capture.hpp" +#include "internal/catch_section.h" +#include "internal/catch_generators.hpp" +#include "internal/catch_interfaces_exception.h" +#include "internal/catch_approx.hpp" +#include "internal/catch_matchers.hpp" +#include "internal/catch_compiler_capabilities.h" +#include "internal/catch_interfaces_tag_alias_registry.h" + +// These files are included here so the single_include script doesn't put them +// in the conditionally compiled sections +#include "internal/catch_test_case_info.h" +#include "internal/catch_interfaces_runner.h" + +#ifdef __OBJC__ +#include "internal/catch_objc.hpp" +#endif + +#ifdef CATCH_IMPL +#include "internal/catch_impl.hpp" +#endif + +#ifdef CATCH_CONFIG_MAIN +#include "internal/catch_default_main.hpp" +#endif + + +#ifdef CLARA_CONFIG_MAIN_NOT_DEFINED +# undef CLARA_CONFIG_MAIN +#endif + +////// + +// If this config identifier is defined then all CATCH macros are prefixed with CATCH_ +#ifdef CATCH_CONFIG_PREFIX_ALL + +#define CATCH_REQUIRE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal, "CATCH_REQUIRE" ) +#define CATCH_REQUIRE_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, "CATCH_REQUIRE_FALSE" ) + +#define CATCH_REQUIRE_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::Normal, "", "CATCH_REQUIRE_THROWS" ) +#define CATCH_REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_THROWS_AS" ) +#define CATCH_REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::Normal, matcher, "CATCH_REQUIRE_THROWS_WITH" ) +#define CATCH_REQUIRE_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_NOTHROW" ) + +#define CATCH_CHECK( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK" ) +#define CATCH_CHECK_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::FalseTest, "CATCH_CHECK_FALSE" ) +#define CATCH_CHECKED_IF( expr ) INTERNAL_CATCH_IF( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECKED_IF" ) +#define CATCH_CHECKED_ELSE( expr ) INTERNAL_CATCH_ELSE( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECKED_ELSE" ) +#define CATCH_CHECK_NOFAIL( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, "CATCH_CHECK_NOFAIL" ) + +#define CATCH_CHECK_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_THROWS" ) +#define CATCH_CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_THROWS_AS" ) +#define CATCH_CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::ContinueOnFailure, matcher, "CATCH_CHECK_THROWS_WITH" ) +#define CATCH_CHECK_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_NOTHROW" ) + +#define CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_THAT" ) +#define CATCH_REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_THAT" ) + +#define CATCH_INFO( msg ) INTERNAL_CATCH_INFO( msg, "CATCH_INFO" ) +#define CATCH_WARN( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, "CATCH_WARN", msg ) +#define CATCH_SCOPED_INFO( msg ) INTERNAL_CATCH_INFO( msg, "CATCH_INFO" ) +#define CATCH_CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CATCH_CAPTURE" ) +#define CATCH_SCOPED_CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CATCH_CAPTURE" ) + +#ifdef CATCH_CONFIG_VARIADIC_MACROS + #define CATCH_TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ ) + #define CATCH_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ ) + #define CATCH_METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ ) + #define CATCH_REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ ) + #define CATCH_SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ ) + #define CATCH_FAIL( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "CATCH_FAIL", __VA_ARGS__ ) + #define CATCH_SUCCEED( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "CATCH_SUCCEED", __VA_ARGS__ ) +#else + #define CATCH_TEST_CASE( name, description ) INTERNAL_CATCH_TESTCASE( name, description ) + #define CATCH_TEST_CASE_METHOD( className, name, description ) INTERNAL_CATCH_TEST_CASE_METHOD( className, name, description ) + #define CATCH_METHOD_AS_TEST_CASE( method, name, description ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, name, description ) + #define CATCH_REGISTER_TEST_CASE( function, name, description ) INTERNAL_CATCH_REGISTER_TESTCASE( function, name, description ) + #define CATCH_SECTION( name, description ) INTERNAL_CATCH_SECTION( name, description ) + #define CATCH_FAIL( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "CATCH_FAIL", msg ) + #define CATCH_SUCCEED( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "CATCH_SUCCEED", msg ) +#endif +#define CATCH_ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE( "", "" ) + +#define CATCH_REGISTER_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType ) +#define CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) + +#define CATCH_GENERATE( expr) INTERNAL_CATCH_GENERATE( expr ) + +// "BDD-style" convenience wrappers +#ifdef CATCH_CONFIG_VARIADIC_MACROS +#define CATCH_SCENARIO( ... ) CATCH_TEST_CASE( "Scenario: " __VA_ARGS__ ) +#define CATCH_SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ ) +#else +#define CATCH_SCENARIO( name, tags ) CATCH_TEST_CASE( "Scenario: " name, tags ) +#define CATCH_SCENARIO_METHOD( className, name, tags ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " name, tags ) +#endif +#define CATCH_GIVEN( desc ) CATCH_SECTION( std::string( "Given: ") + desc, "" ) +#define CATCH_WHEN( desc ) CATCH_SECTION( std::string( " When: ") + desc, "" ) +#define CATCH_AND_WHEN( desc ) CATCH_SECTION( std::string( " And: ") + desc, "" ) +#define CATCH_THEN( desc ) CATCH_SECTION( std::string( " Then: ") + desc, "" ) +#define CATCH_AND_THEN( desc ) CATCH_SECTION( std::string( " And: ") + desc, "" ) + +// If CATCH_CONFIG_PREFIX_ALL is not defined then the CATCH_ prefix is not required +#else + +#define REQUIRE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal, "REQUIRE" ) +#define REQUIRE_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, "REQUIRE_FALSE" ) + +#define REQUIRE_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::Normal, "", "REQUIRE_THROWS" ) +#define REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::Normal, "REQUIRE_THROWS_AS" ) +#define REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::Normal, matcher, "REQUIRE_THROWS_WITH" ) +#define REQUIRE_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::Normal, "REQUIRE_NOTHROW" ) + +#define CHECK( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECK" ) +#define CHECK_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::FalseTest, "CHECK_FALSE" ) +#define CHECKED_IF( expr ) INTERNAL_CATCH_IF( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECKED_IF" ) +#define CHECKED_ELSE( expr ) INTERNAL_CATCH_ELSE( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECKED_ELSE" ) +#define CHECK_NOFAIL( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, "CHECK_NOFAIL" ) + +#define CHECK_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::ContinueOnFailure, "", "CHECK_THROWS" ) +#define CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::ContinueOnFailure, "CHECK_THROWS_AS" ) +#define CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::ContinueOnFailure, matcher, "CHECK_THROWS_WITH" ) +#define CHECK_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECK_NOTHROW" ) + +#define CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::ContinueOnFailure, "CHECK_THAT" ) +#define REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::Normal, "REQUIRE_THAT" ) + +#define INFO( msg ) INTERNAL_CATCH_INFO( msg, "INFO" ) +#define WARN( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, "WARN", msg ) +#define SCOPED_INFO( msg ) INTERNAL_CATCH_INFO( msg, "INFO" ) +#define CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CAPTURE" ) +#define SCOPED_CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CAPTURE" ) + +#ifdef CATCH_CONFIG_VARIADIC_MACROS + #define TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ ) + #define TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ ) + #define METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ ) + #define REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ ) + #define SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ ) + #define FAIL( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "FAIL", __VA_ARGS__ ) + #define SUCCEED( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "SUCCEED", __VA_ARGS__ ) +#else + #define TEST_CASE( name, description ) INTERNAL_CATCH_TESTCASE( name, description ) + #define TEST_CASE_METHOD( className, name, description ) INTERNAL_CATCH_TEST_CASE_METHOD( className, name, description ) + #define METHOD_AS_TEST_CASE( method, name, description ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, name, description ) + #define REGISTER_TEST_CASE( method, name, description ) INTERNAL_CATCH_REGISTER_TESTCASE( method, name, description ) + #define SECTION( name, description ) INTERNAL_CATCH_SECTION( name, description ) + #define FAIL( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "FAIL", msg ) + #define SUCCEED( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "SUCCEED", msg ) +#endif +#define ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE( "", "" ) + +#define REGISTER_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType ) +#define REGISTER_LEGACY_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) + +#define GENERATE( expr) INTERNAL_CATCH_GENERATE( expr ) + +#endif + +#define CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) + +// "BDD-style" convenience wrappers +#ifdef CATCH_CONFIG_VARIADIC_MACROS +#define SCENARIO( ... ) TEST_CASE( "Scenario: " __VA_ARGS__ ) +#define SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ ) +#else +#define SCENARIO( name, tags ) TEST_CASE( "Scenario: " name, tags ) +#define SCENARIO_METHOD( className, name, tags ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " name, tags ) +#endif +#define GIVEN( desc ) SECTION( std::string(" Given: ") + desc, "" ) +#define WHEN( desc ) SECTION( std::string(" When: ") + desc, "" ) +#define AND_WHEN( desc ) SECTION( std::string("And when: ") + desc, "" ) +#define THEN( desc ) SECTION( std::string(" Then: ") + desc, "" ) +#define AND_THEN( desc ) SECTION( std::string(" And: ") + desc, "" ) + +using Catch::Detail::Approx; + +#include "internal/catch_reenable_warnings.h" + +#endif // TWOBLUECUBES_CATCH_HPP_INCLUDED diff --git a/unittest/Catch/include/catch_session.hpp b/unittest/Catch/include/catch_session.hpp new file mode 100644 index 0000000..3884b95 --- /dev/null +++ b/unittest/Catch/include/catch_session.hpp @@ -0,0 +1,222 @@ +/* + * Created by Phil on 31/10/2010. + * Copyright 2010 Two Blue Cubes Ltd. All rights reserved. + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + */ +#ifndef TWOBLUECUBES_CATCH_RUNNER_HPP_INCLUDED +#define TWOBLUECUBES_CATCH_RUNNER_HPP_INCLUDED + +#include "internal/catch_commandline.hpp" +#include "internal/catch_list.hpp" +#include "internal/catch_run_context.hpp" +#include "internal/catch_test_spec.hpp" +#include "internal/catch_version.h" +#include "internal/catch_text.h" + +#include <fstream> +#include <stdlib.h> +#include <limits> + +namespace Catch { + + Ptr<IStreamingReporter> createReporter( std::string const& reporterName, Ptr<Config> const& config ) { + Ptr<IStreamingReporter> reporter = getRegistryHub().getReporterRegistry().create( reporterName, config.get() ); + if( !reporter ) { + std::ostringstream oss; + oss << "No reporter registered with name: '" << reporterName << "'"; + throw std::domain_error( oss.str() ); + } + return reporter; + } + + Ptr<IStreamingReporter> makeReporter( Ptr<Config> const& config ) { + std::vector<std::string> reporters = config->getReporterNames(); + if( reporters.empty() ) + reporters.push_back( "console" ); + + Ptr<IStreamingReporter> reporter; + for( std::vector<std::string>::const_iterator it = reporters.begin(), itEnd = reporters.end(); + it != itEnd; + ++it ) + reporter = addReporter( reporter, createReporter( *it, config ) ); + return reporter; + } + Ptr<IStreamingReporter> addListeners( Ptr<IConfig const> const& config, Ptr<IStreamingReporter> reporters ) { + IReporterRegistry::Listeners listeners = getRegistryHub().getReporterRegistry().getListeners(); + for( IReporterRegistry::Listeners::const_iterator it = listeners.begin(), itEnd = listeners.end(); + it != itEnd; + ++it ) + reporters = addReporter(reporters, (*it)->create( ReporterConfig( config ) ) ); + return reporters; + } + + + Totals runTests( Ptr<Config> const& config ) { + + Ptr<IConfig const> iconfig = config.get(); + + Ptr<IStreamingReporter> reporter = makeReporter( config ); + reporter = addListeners( iconfig, reporter ); + + RunContext context( iconfig, reporter ); + + Totals totals; + + context.testGroupStarting( config->name(), 1, 1 ); + + TestSpec testSpec = config->testSpec(); + if( !testSpec.hasFilters() ) + testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "~[.]" ).testSpec(); // All not hidden tests + + std::vector<TestCase> const& allTestCases = getAllTestCasesSorted( *iconfig ); + for( std::vector<TestCase>::const_iterator it = allTestCases.begin(), itEnd = allTestCases.end(); + it != itEnd; + ++it ) { + if( !context.aborting() && matchTest( *it, testSpec, *iconfig ) ) + totals += context.runTest( *it ); + else + reporter->skipTest( *it ); + } + + context.testGroupEnded( iconfig->name(), totals, 1, 1 ); + return totals; + } + + void applyFilenamesAsTags( IConfig const& config ) { + std::vector<TestCase> const& tests = getAllTestCasesSorted( config ); + for(std::size_t i = 0; i < tests.size(); ++i ) { + TestCase& test = const_cast<TestCase&>( tests[i] ); + std::set<std::string> tags = test.tags; + + std::string filename = test.lineInfo.file; + std::string::size_type lastSlash = filename.find_last_of( "\\/" ); + if( lastSlash != std::string::npos ) + filename = filename.substr( lastSlash+1 ); + + std::string::size_type lastDot = filename.find_last_of( "." ); + if( lastDot != std::string::npos ) + filename = filename.substr( 0, lastDot ); + + tags.insert( "#" + filename ); + setTags( test, tags ); + } + } + + class Session : NonCopyable { + static bool alreadyInstantiated; + + public: + + struct OnUnusedOptions { enum DoWhat { Ignore, Fail }; }; + + Session() + : m_cli( makeCommandLineParser() ) { + if( alreadyInstantiated ) { + std::string msg = "Only one instance of Catch::Session can ever be used"; + Catch::cerr() << msg << std::endl; + throw std::logic_error( msg ); + } + alreadyInstantiated = true; + } + ~Session() { + Catch::cleanUp(); + } + + void showHelp( std::string const& processName ) { + Catch::cout() << "\nCatch v" << libraryVersion << "\n"; + + m_cli.usage( Catch::cout(), processName ); + Catch::cout() << "For more detail usage please see the project docs\n" << std::endl; + } + + int applyCommandLine( int argc, char const* argv[], OnUnusedOptions::DoWhat unusedOptionBehaviour = OnUnusedOptions::Fail ) { + try { + m_cli.setThrowOnUnrecognisedTokens( unusedOptionBehaviour == OnUnusedOptions::Fail ); + m_unusedTokens = m_cli.parseInto( argc, argv, m_configData ); + if( m_configData.showHelp ) + showHelp( m_configData.processName ); + m_config.reset(); + } + catch( std::exception& ex ) { + { + Colour colourGuard( Colour::Red ); + Catch::cerr() + << "\nError(s) in input:\n" + << Text( ex.what(), TextAttributes().setIndent(2) ) + << "\n\n"; + } + m_cli.usage( Catch::cout(), m_configData.processName ); + return (std::numeric_limits<int>::max)(); + } + return 0; + } + + void useConfigData( ConfigData const& _configData ) { + m_configData = _configData; + m_config.reset(); + } + + int run( int argc, char const* argv[] ) { + + int returnCode = applyCommandLine( argc, argv ); + if( returnCode == 0 ) + returnCode = run(); + return returnCode; + } + int run( int argc, char* argv[] ) { + return run( argc, const_cast<char const**>( argv ) ); + } + + int run() { + if( m_configData.showHelp ) + return 0; + + try + { + config(); // Force config to be constructed + + seedRng( *m_config ); + + if( m_configData.filenamesAsTags ) + applyFilenamesAsTags( *m_config ); + + // Handle list request + if( Option<std::size_t> listed = list( config() ) ) + return static_cast<int>( *listed ); + + return static_cast<int>( runTests( m_config ).assertions.failed ); + } + catch( std::exception& ex ) { + Catch::cerr() << ex.what() << std::endl; + return (std::numeric_limits<int>::max)(); + } + } + + Clara::CommandLine<ConfigData> const& cli() const { + return m_cli; + } + std::vector<Clara::Parser::Token> const& unusedTokens() const { + return m_unusedTokens; + } + ConfigData& configData() { + return m_configData; + } + Config& config() { + if( !m_config ) + m_config = new Config( m_configData ); + return *m_config; + } + private: + Clara::CommandLine<ConfigData> m_cli; + std::vector<Clara::Parser::Token> m_unusedTokens; + ConfigData m_configData; + Ptr<Config> m_config; + }; + + bool Session::alreadyInstantiated = false; + +} // end namespace Catch + +#endif // TWOBLUECUBES_CATCH_RUNNER_HPP_INCLUDED diff --git a/unittest/Catch/include/catch_with_main.hpp b/unittest/Catch/include/catch_with_main.hpp new file mode 100644 index 0000000..54aa651 --- /dev/null +++ b/unittest/Catch/include/catch_with_main.hpp @@ -0,0 +1,14 @@ + /* + * Created by Phil on 01/11/2010. + * Copyright 2010 Two Blue Cubes Ltd. All rights reserved. + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + */ +#ifndef TWOBLUECUBES_CATCH_WITH_MAIN_HPP_INCLUDED +#define TWOBLUECUBES_CATCH_WITH_MAIN_HPP_INCLUDED + +#define CATCH_CONFIG_MAIN +#include "catch.hpp" + +#endif // TWOBLUECUBES_CATCH_WITH_MAIN_HPP_INCLUDED diff --git a/unittest/Catch/include/external/clara.h b/unittest/Catch/include/external/clara.h new file mode 100644 index 0000000..f2ea14b --- /dev/null +++ b/unittest/Catch/include/external/clara.h @@ -0,0 +1,1028 @@ +/* + * Created by Phil on 25/05/2013. + * Copyright 2013 Two Blue Cubes Ltd. All rights reserved. + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + */ + +// Version 0.0.1.1 + +// Only use header guard if we are not using an outer namespace +#if !defined(TWOBLUECUBES_CLARA_H_INCLUDED) || defined(STITCH_CLARA_OPEN_NAMESPACE) + +#ifndef STITCH_CLARA_OPEN_NAMESPACE +#define TWOBLUECUBES_CLARA_H_INCLUDED +#define STITCH_CLARA_OPEN_NAMESPACE +#define STITCH_CLARA_CLOSE_NAMESPACE +#else +#define STITCH_CLARA_CLOSE_NAMESPACE } +#endif + + +#define STITCH_TBC_TEXT_FORMAT_OPEN_NAMESPACE STITCH_CLARA_OPEN_NAMESPACE + +// ----------- #included from tbc_text_format.h ----------- + +/* + * Created by Phil on 18/4/2013. + * Copyright 2013 Two Blue Cubes Ltd. All rights reserved. + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + */ +// Only use header guard if we are not using an outer namespace +#if !defined(TBC_TEXT_FORMAT_H_INCLUDED) || defined(STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE) +#ifndef STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE +#define TBC_TEXT_FORMAT_H_INCLUDED +#endif + +#include <string> +#include <vector> +#include <sstream> +#include <algorithm> + +// Use optional outer namespace +#ifdef STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE +namespace STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE { +#endif + +namespace Tbc { + +#ifdef TBC_TEXT_FORMAT_CONSOLE_WIDTH + const unsigned int consoleWidth = TBC_TEXT_FORMAT_CONSOLE_WIDTH; +#else + const unsigned int consoleWidth = 80; +#endif + + struct TextAttributes { + TextAttributes() + : initialIndent( std::string::npos ), + indent( 0 ), + width( consoleWidth-1 ), + tabChar( '\t' ) + {} + + TextAttributes& setInitialIndent( std::size_t _value ) { initialIndent = _value; return *this; } + TextAttributes& setIndent( std::size_t _value ) { indent = _value; return *this; } + TextAttributes& setWidth( std::size_t _value ) { width = _value; return *this; } + TextAttributes& setTabChar( char _value ) { tabChar = _value; return *this; } + + std::size_t initialIndent; // indent of first line, or npos + std::size_t indent; // indent of subsequent lines, or all if initialIndent is npos + std::size_t width; // maximum width of text, including indent. Longer text will wrap + char tabChar; // If this char is seen the indent is changed to current pos + }; + + class Text { + public: + Text( std::string const& _str, TextAttributes const& _attr = TextAttributes() ) + : attr( _attr ) + { + std::string wrappableChars = " [({.,/|\\-"; + std::size_t indent = _attr.initialIndent != std::string::npos + ? _attr.initialIndent + : _attr.indent; + std::string remainder = _str; + + while( !remainder.empty() ) { + if( lines.size() >= 1000 ) { + lines.push_back( "... message truncated due to excessive size" ); + return; + } + std::size_t tabPos = std::string::npos; + std::size_t width = (std::min)( remainder.size(), _attr.width - indent ); + std::size_t pos = remainder.find_first_of( '\n' ); + if( pos <= width ) { + width = pos; + } + pos = remainder.find_last_of( _attr.tabChar, width ); + if( pos != std::string::npos ) { + tabPos = pos; + if( remainder[width] == '\n' ) + width--; + remainder = remainder.substr( 0, tabPos ) + remainder.substr( tabPos+1 ); + } + + if( width == remainder.size() ) { + spliceLine( indent, remainder, width ); + } + else if( remainder[width] == '\n' ) { + spliceLine( indent, remainder, width ); + if( width <= 1 || remainder.size() != 1 ) + remainder = remainder.substr( 1 ); + indent = _attr.indent; + } + else { + pos = remainder.find_last_of( wrappableChars, width ); + if( pos != std::string::npos && pos > 0 ) { + spliceLine( indent, remainder, pos ); + if( remainder[0] == ' ' ) + remainder = remainder.substr( 1 ); + } + else { + spliceLine( indent, remainder, width-1 ); + lines.back() += "-"; + } + if( lines.size() == 1 ) + indent = _attr.indent; + if( tabPos != std::string::npos ) + indent += tabPos; + } + } + } + + void spliceLine( std::size_t _indent, std::string& _remainder, std::size_t _pos ) { + lines.push_back( std::string( _indent, ' ' ) + _remainder.substr( 0, _pos ) ); + _remainder = _remainder.substr( _pos ); + } + + typedef std::vector<std::string>::const_iterator const_iterator; + + const_iterator begin() const { return lines.begin(); } + const_iterator end() const { return lines.end(); } + std::string const& last() const { return lines.back(); } + std::size_t size() const { return lines.size(); } + std::string const& operator[]( std::size_t _index ) const { return lines[_index]; } + std::string toString() const { + std::ostringstream oss; + oss << *this; + return oss.str(); + } + + inline friend std::ostream& operator << ( std::ostream& _stream, Text const& _text ) { + for( Text::const_iterator it = _text.begin(), itEnd = _text.end(); + it != itEnd; ++it ) { + if( it != _text.begin() ) + _stream << "\n"; + _stream << *it; + } + return _stream; + } + + private: + std::string str; + TextAttributes attr; + std::vector<std::string> lines; + }; + +} // end namespace Tbc + +#ifdef STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE +} // end outer namespace +#endif + +#endif // TBC_TEXT_FORMAT_H_INCLUDED + +// ----------- end of #include from tbc_text_format.h ----------- +// ........... back in clara.h + +#undef STITCH_TBC_TEXT_FORMAT_OPEN_NAMESPACE + + +// ----------- #included from clara_compilers.h ----------- + +/* + * Created by Phil on 10/02/2016. + * Copyright 2016 Two Blue Cubes Ltd. All rights reserved. + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + */ +#ifndef TWOBLUECUBES_CLARA_COMPILERS_H_INCLUDED +#define TWOBLUECUBES_CLARA_COMPILERS_H_INCLUDED + +// Detect a number of compiler features - mostly C++11/14 conformance - by compiler +// The following features are defined: +// +// CLARA_CONFIG_CPP11_NULLPTR : is nullptr supported? +// CLARA_CONFIG_CPP11_NOEXCEPT : is noexcept supported? +// CLARA_CONFIG_CPP11_GENERATED_METHODS : The delete and default keywords for compiler generated methods +// CLARA_CONFIG_CPP11_OVERRIDE : is override supported? +// CLARA_CONFIG_CPP11_UNIQUE_PTR : is unique_ptr supported (otherwise use auto_ptr) + +// CLARA_CONFIG_CPP11_OR_GREATER : Is C++11 supported? + +// CLARA_CONFIG_VARIADIC_MACROS : are variadic macros supported? + +// In general each macro has a _NO_<feature name> form +// (e.g. CLARA_CONFIG_CPP11_NO_NULLPTR) which disables the feature. +// Many features, at point of detection, define an _INTERNAL_ macro, so they +// can be combined, en-mass, with the _NO_ forms later. + +// All the C++11 features can be disabled with CLARA_CONFIG_NO_CPP11 + +#ifdef __clang__ + +#if __has_feature(cxx_nullptr) +#define CLARA_INTERNAL_CONFIG_CPP11_NULLPTR +#endif + +#if __has_feature(cxx_noexcept) +#define CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT +#endif + +#endif // __clang__ + +//////////////////////////////////////////////////////////////////////////////// +// GCC +#ifdef __GNUC__ + +#if __GNUC__ == 4 && __GNUC_MINOR__ >= 6 && defined(__GXX_EXPERIMENTAL_CXX0X__) +#define CLARA_INTERNAL_CONFIG_CPP11_NULLPTR +#endif + +// - otherwise more recent versions define __cplusplus >= 201103L +// and will get picked up below + +#endif // __GNUC__ + +//////////////////////////////////////////////////////////////////////////////// +// Visual C++ +#ifdef _MSC_VER + +#if (_MSC_VER >= 1600) +#define CLARA_INTERNAL_CONFIG_CPP11_NULLPTR +#define CLARA_INTERNAL_CONFIG_CPP11_UNIQUE_PTR +#endif + +#if (_MSC_VER >= 1900 ) // (VC++ 13 (VS2015)) +#define CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT +#define CLARA_INTERNAL_CONFIG_CPP11_GENERATED_METHODS +#endif + +#endif // _MSC_VER + + +//////////////////////////////////////////////////////////////////////////////// +// C++ language feature support + +// catch all support for C++11 +#if defined(__cplusplus) && __cplusplus >= 201103L + +#define CLARA_CPP11_OR_GREATER + +#if !defined(CLARA_INTERNAL_CONFIG_CPP11_NULLPTR) +#define CLARA_INTERNAL_CONFIG_CPP11_NULLPTR +#endif + +#ifndef CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT +#define CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT +#endif + +#ifndef CLARA_INTERNAL_CONFIG_CPP11_GENERATED_METHODS +#define CLARA_INTERNAL_CONFIG_CPP11_GENERATED_METHODS +#endif + +#if !defined(CLARA_INTERNAL_CONFIG_CPP11_OVERRIDE) +#define CLARA_INTERNAL_CONFIG_CPP11_OVERRIDE +#endif +#if !defined(CLARA_INTERNAL_CONFIG_CPP11_UNIQUE_PTR) +#define CLARA_INTERNAL_CONFIG_CPP11_UNIQUE_PTR +#endif + + +#endif // __cplusplus >= 201103L + +// Now set the actual defines based on the above + anything the user has configured +#if defined(CLARA_INTERNAL_CONFIG_CPP11_NULLPTR) && !defined(CLARA_CONFIG_CPP11_NO_NULLPTR) && !defined(CLARA_CONFIG_CPP11_NULLPTR) && !defined(CLARA_CONFIG_NO_CPP11) +#define CLARA_CONFIG_CPP11_NULLPTR +#endif +#if defined(CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT) && !defined(CLARA_CONFIG_CPP11_NO_NOEXCEPT) && !defined(CLARA_CONFIG_CPP11_NOEXCEPT) && !defined(CLARA_CONFIG_NO_CPP11) +#define CLARA_CONFIG_CPP11_NOEXCEPT +#endif +#if defined(CLARA_INTERNAL_CONFIG_CPP11_GENERATED_METHODS) && !defined(CLARA_CONFIG_CPP11_NO_GENERATED_METHODS) && !defined(CLARA_CONFIG_CPP11_GENERATED_METHODS) && !defined(CLARA_CONFIG_NO_CPP11) +#define CLARA_CONFIG_CPP11_GENERATED_METHODS +#endif +#if defined(CLARA_INTERNAL_CONFIG_CPP11_OVERRIDE) && !defined(CLARA_CONFIG_NO_OVERRIDE) && !defined(CLARA_CONFIG_CPP11_OVERRIDE) && !defined(CLARA_CONFIG_NO_CPP11) +#define CLARA_CONFIG_CPP11_OVERRIDE +#endif +#if defined(CLARA_INTERNAL_CONFIG_CPP11_UNIQUE_PTR) && !defined(CLARA_CONFIG_NO_UNIQUE_PTR) && !defined(CLARA_CONFIG_CPP11_UNIQUE_PTR) && !defined(CLARA_CONFIG_NO_CPP11) +#define CLARA_CONFIG_CPP11_UNIQUE_PTR +#endif + + +// noexcept support: +#if defined(CLARA_CONFIG_CPP11_NOEXCEPT) && !defined(CLARA_NOEXCEPT) +#define CLARA_NOEXCEPT noexcept +# define CLARA_NOEXCEPT_IS(x) noexcept(x) +#else +#define CLARA_NOEXCEPT throw() +# define CLARA_NOEXCEPT_IS(x) +#endif + +// nullptr support +#ifdef CLARA_CONFIG_CPP11_NULLPTR +#define CLARA_NULL nullptr +#else +#define CLARA_NULL NULL +#endif + +// override support +#ifdef CLARA_CONFIG_CPP11_OVERRIDE +#define CLARA_OVERRIDE override +#else +#define CLARA_OVERRIDE +#endif + +// unique_ptr support +#ifdef CLARA_CONFIG_CPP11_UNIQUE_PTR +# define CLARA_AUTO_PTR( T ) std::unique_ptr<T> +#else +# define CLARA_AUTO_PTR( T ) std::auto_ptr<T> +#endif + +#endif // TWOBLUECUBES_CLARA_COMPILERS_H_INCLUDED + + +// ----------- end of #include from clara_compilers.h ----------- +// ........... back in clara.h + + +#include <map> +#include <stdexcept> +#include <memory> + +// Use optional outer namespace +#ifdef STITCH_CLARA_OPEN_NAMESPACE +STITCH_CLARA_OPEN_NAMESPACE +#endif + +namespace Clara { + + struct UnpositionalTag {}; + + extern UnpositionalTag _; + +#ifdef CLARA_CONFIG_MAIN + UnpositionalTag _; +#endif + + namespace Detail { + +#ifdef CLARA_CONSOLE_WIDTH + const unsigned int consoleWidth = CLARA_CONFIG_CONSOLE_WIDTH; +#else + const unsigned int consoleWidth = 80; +#endif + + // Use this to try and stop compiler from warning about unreachable code + inline bool isTrue( bool value ) { return value; } + + using namespace Tbc; + + inline bool startsWith( std::string const& str, std::string const& prefix ) { + return str.size() >= prefix.size() && str.substr( 0, prefix.size() ) == prefix; + } + + template<typename T> struct RemoveConstRef{ typedef T type; }; + template<typename T> struct RemoveConstRef<T&>{ typedef T type; }; + template<typename T> struct RemoveConstRef<T const&>{ typedef T type; }; + template<typename T> struct RemoveConstRef<T const>{ typedef T type; }; + + template<typename T> struct IsBool { static const bool value = false; }; + template<> struct IsBool<bool> { static const bool value = true; }; + + template<typename T> + void convertInto( std::string const& _source, T& _dest ) { + std::stringstream ss; + ss << _source; + ss >> _dest; + if( ss.fail() ) + throw std::runtime_error( "Unable to convert " + _source + " to destination type" ); + } + inline void convertInto( std::string const& _source, std::string& _dest ) { + _dest = _source; + } + inline void convertInto( std::string const& _source, bool& _dest ) { + std::string sourceLC = _source; + std::transform( sourceLC.begin(), sourceLC.end(), sourceLC.begin(), ::tolower ); + if( sourceLC == "y" || sourceLC == "1" || sourceLC == "true" || sourceLC == "yes" || sourceLC == "on" ) + _dest = true; + else if( sourceLC == "n" || sourceLC == "0" || sourceLC == "false" || sourceLC == "no" || sourceLC == "off" ) + _dest = false; + else + throw std::runtime_error( "Expected a boolean value but did not recognise:\n '" + _source + "'" ); + } + inline void convertInto( bool _source, bool& _dest ) { + _dest = _source; + } + template<typename T> + inline void convertInto( bool, T& ) { + if( isTrue( true ) ) + throw std::runtime_error( "Invalid conversion" ); + } + + template<typename ConfigT> + struct IArgFunction { + virtual ~IArgFunction() {} +#ifdef CLARA_CONFIG_CPP11_GENERATED_METHODS + IArgFunction() = default; + IArgFunction( IArgFunction const& ) = default; +#endif + virtual void set( ConfigT& config, std::string const& value ) const = 0; + virtual void setFlag( ConfigT& config ) const = 0; + virtual bool takesArg() const = 0; + virtual IArgFunction* clone() const = 0; + }; + + template<typename ConfigT> + class BoundArgFunction { + public: + BoundArgFunction() : functionObj( CLARA_NULL ) {} + BoundArgFunction( IArgFunction<ConfigT>* _functionObj ) : functionObj( _functionObj ) {} + BoundArgFunction( BoundArgFunction const& other ) : functionObj( other.functionObj ? other.functionObj->clone() : CLARA_NULL ) {} + BoundArgFunction& operator = ( BoundArgFunction const& other ) { + IArgFunction<ConfigT>* newFunctionObj = other.functionObj ? other.functionObj->clone() : CLARA_NULL; + delete functionObj; + functionObj = newFunctionObj; + return *this; + } + ~BoundArgFunction() { delete functionObj; } + + void set( ConfigT& config, std::string const& value ) const { + functionObj->set( config, value ); + } + void setFlag( ConfigT& config ) const { + functionObj->setFlag( config ); + } + bool takesArg() const { return functionObj->takesArg(); } + + bool isSet() const { + return functionObj != CLARA_NULL; + } + private: + IArgFunction<ConfigT>* functionObj; + }; + + + template<typename C> + struct NullBinder : IArgFunction<C>{ + virtual void set( C&, std::string const& ) const {} + virtual void setFlag( C& ) const {} + virtual bool takesArg() const { return true; } + virtual IArgFunction<C>* clone() const { return new NullBinder( *this ); } + }; + + template<typename C, typename M> + struct BoundDataMember : IArgFunction<C>{ + BoundDataMember( M C::* _member ) : member( _member ) {} + virtual void set( C& p, std::string const& stringValue ) const { + convertInto( stringValue, p.*member ); + } + virtual void setFlag( C& p ) const { + convertInto( true, p.*member ); + } + virtual bool takesArg() const { return !IsBool<M>::value; } + virtual IArgFunction<C>* clone() const { return new BoundDataMember( *this ); } + M C::* member; + }; + template<typename C, typename M> + struct BoundUnaryMethod : IArgFunction<C>{ + BoundUnaryMethod( void (C::*_member)( M ) ) : member( _member ) {} + virtual void set( C& p, std::string const& stringValue ) const { + typename RemoveConstRef<M>::type value; + convertInto( stringValue, value ); + (p.*member)( value ); + } + virtual void setFlag( C& p ) const { + typename RemoveConstRef<M>::type value; + convertInto( true, value ); + (p.*member)( value ); + } + virtual bool takesArg() const { return !IsBool<M>::value; } + virtual IArgFunction<C>* clone() const { return new BoundUnaryMethod( *this ); } + void (C::*member)( M ); + }; + template<typename C> + struct BoundNullaryMethod : IArgFunction<C>{ + BoundNullaryMethod( void (C::*_member)() ) : member( _member ) {} + virtual void set( C& p, std::string const& stringValue ) const { + bool value; + convertInto( stringValue, value ); + if( value ) + (p.*member)(); + } + virtual void setFlag( C& p ) const { + (p.*member)(); + } + virtual bool takesArg() const { return false; } + virtual IArgFunction<C>* clone() const { return new BoundNullaryMethod( *this ); } + void (C::*member)(); + }; + + template<typename C> + struct BoundUnaryFunction : IArgFunction<C>{ + BoundUnaryFunction( void (*_function)( C& ) ) : function( _function ) {} + virtual void set( C& obj, std::string const& stringValue ) const { + bool value; + convertInto( stringValue, value ); + if( value ) + function( obj ); + } + virtual void setFlag( C& p ) const { + function( p ); + } + virtual bool takesArg() const { return false; } + virtual IArgFunction<C>* clone() const { return new BoundUnaryFunction( *this ); } + void (*function)( C& ); + }; + + template<typename C, typename T> + struct BoundBinaryFunction : IArgFunction<C>{ + BoundBinaryFunction( void (*_function)( C&, T ) ) : function( _function ) {} + virtual void set( C& obj, std::string const& stringValue ) const { + typename RemoveConstRef<T>::type value; + convertInto( stringValue, value ); + function( obj, value ); + } + virtual void setFlag( C& obj ) const { + typename RemoveConstRef<T>::type value; + convertInto( true, value ); + function( obj, value ); + } + virtual bool takesArg() const { return !IsBool<T>::value; } + virtual IArgFunction<C>* clone() const { return new BoundBinaryFunction( *this ); } + void (*function)( C&, T ); + }; + + } // namespace Detail + + struct Parser { + Parser() : separators( " \t=:" ) {} + + struct Token { + enum Type { Positional, ShortOpt, LongOpt }; + Token( Type _type, std::string const& _data ) : type( _type ), data( _data ) {} + Type type; + std::string data; + }; + + void parseIntoTokens( int argc, char const* const argv[], std::vector<Parser::Token>& tokens ) const { + const std::string doubleDash = "--"; + for( int i = 1; i < argc && argv[i] != doubleDash; ++i ) + parseIntoTokens( argv[i] , tokens); + } + void parseIntoTokens( std::string arg, std::vector<Parser::Token>& tokens ) const { + while( !arg.empty() ) { + Parser::Token token( Parser::Token::Positional, arg ); + arg = ""; + if( token.data[0] == '-' ) { + if( token.data.size() > 1 && token.data[1] == '-' ) { + token = Parser::Token( Parser::Token::LongOpt, token.data.substr( 2 ) ); + } + else { + token = Parser::Token( Parser::Token::ShortOpt, token.data.substr( 1 ) ); + if( token.data.size() > 1 && separators.find( token.data[1] ) == std::string::npos ) { + arg = "-" + token.data.substr( 1 ); + token.data = token.data.substr( 0, 1 ); + } + } + } + if( token.type != Parser::Token::Positional ) { + std::size_t pos = token.data.find_first_of( separators ); + if( pos != std::string::npos ) { + arg = token.data.substr( pos+1 ); + token.data = token.data.substr( 0, pos ); + } + } + tokens.push_back( token ); + } + } + std::string separators; + }; + + template<typename ConfigT> + struct CommonArgProperties { + CommonArgProperties() {} + CommonArgProperties( Detail::BoundArgFunction<ConfigT> const& _boundField ) : boundField( _boundField ) {} + + Detail::BoundArgFunction<ConfigT> boundField; + std::string description; + std::string detail; + std::string placeholder; // Only value if boundField takes an arg + + bool takesArg() const { + return !placeholder.empty(); + } + void validate() const { + if( !boundField.isSet() ) + throw std::logic_error( "option not bound" ); + } + }; + struct OptionArgProperties { + std::vector<std::string> shortNames; + std::string longName; + + bool hasShortName( std::string const& shortName ) const { + return std::find( shortNames.begin(), shortNames.end(), shortName ) != shortNames.end(); + } + bool hasLongName( std::string const& _longName ) const { + return _longName == longName; + } + }; + struct PositionalArgProperties { + PositionalArgProperties() : position( -1 ) {} + int position; // -1 means non-positional (floating) + + bool isFixedPositional() const { + return position != -1; + } + }; + + template<typename ConfigT> + class CommandLine { + + struct Arg : CommonArgProperties<ConfigT>, OptionArgProperties, PositionalArgProperties { + Arg() {} + Arg( Detail::BoundArgFunction<ConfigT> const& _boundField ) : CommonArgProperties<ConfigT>( _boundField ) {} + + using CommonArgProperties<ConfigT>::placeholder; // !TBD + + std::string dbgName() const { + if( !longName.empty() ) + return "--" + longName; + if( !shortNames.empty() ) + return "-" + shortNames[0]; + return "positional args"; + } + std::string commands() const { + std::ostringstream oss; + bool first = true; + std::vector<std::string>::const_iterator it = shortNames.begin(), itEnd = shortNames.end(); + for(; it != itEnd; ++it ) { + if( first ) + first = false; + else + oss << ", "; + oss << "-" << *it; + } + if( !longName.empty() ) { + if( !first ) + oss << ", "; + oss << "--" << longName; + } + if( !placeholder.empty() ) + oss << " <" << placeholder << ">"; + return oss.str(); + } + }; + + typedef CLARA_AUTO_PTR( Arg ) ArgAutoPtr; + + friend void addOptName( Arg& arg, std::string const& optName ) + { + if( optName.empty() ) + return; + if( Detail::startsWith( optName, "--" ) ) { + if( !arg.longName.empty() ) + throw std::logic_error( "Only one long opt may be specified. '" + + arg.longName + + "' already specified, now attempting to add '" + + optName + "'" ); + arg.longName = optName.substr( 2 ); + } + else if( Detail::startsWith( optName, "-" ) ) + arg.shortNames.push_back( optName.substr( 1 ) ); + else + throw std::logic_error( "option must begin with - or --. Option was: '" + optName + "'" ); + } + friend void setPositionalArg( Arg& arg, int position ) + { + arg.position = position; + } + + + class ArgBuilder { + public: + ArgBuilder( Arg* arg ) : m_arg( arg ) {} + + // Bind a non-boolean data member (requires placeholder string) + template<typename C, typename M> + void bind( M C::* field, std::string const& placeholder ) { + m_arg->boundField = new Detail::BoundDataMember<C,M>( field ); + m_arg->placeholder = placeholder; + } + // Bind a boolean data member (no placeholder required) + template<typename C> + void bind( bool C::* field ) { + m_arg->boundField = new Detail::BoundDataMember<C,bool>( field ); + } + + // Bind a method taking a single, non-boolean argument (requires a placeholder string) + template<typename C, typename M> + void bind( void (C::* unaryMethod)( M ), std::string const& placeholder ) { + m_arg->boundField = new Detail::BoundUnaryMethod<C,M>( unaryMethod ); + m_arg->placeholder = placeholder; + } + + // Bind a method taking a single, boolean argument (no placeholder string required) + template<typename C> + void bind( void (C::* unaryMethod)( bool ) ) { + m_arg->boundField = new Detail::BoundUnaryMethod<C,bool>( unaryMethod ); + } + + // Bind a method that takes no arguments (will be called if opt is present) + template<typename C> + void bind( void (C::* nullaryMethod)() ) { + m_arg->boundField = new Detail::BoundNullaryMethod<C>( nullaryMethod ); + } + + // Bind a free function taking a single argument - the object to operate on (no placeholder string required) + template<typename C> + void bind( void (* unaryFunction)( C& ) ) { + m_arg->boundField = new Detail::BoundUnaryFunction<C>( unaryFunction ); + } + + // Bind a free function taking a single argument - the object to operate on (requires a placeholder string) + template<typename C, typename T> + void bind( void (* binaryFunction)( C&, T ), std::string const& placeholder ) { + m_arg->boundField = new Detail::BoundBinaryFunction<C, T>( binaryFunction ); + m_arg->placeholder = placeholder; + } + + ArgBuilder& describe( std::string const& description ) { + m_arg->description = description; + return *this; + } + ArgBuilder& detail( std::string const& detail ) { + m_arg->detail = detail; + return *this; + } + + protected: + Arg* m_arg; + }; + + class OptBuilder : public ArgBuilder { + public: + OptBuilder( Arg* arg ) : ArgBuilder( arg ) {} + OptBuilder( OptBuilder& other ) : ArgBuilder( other ) {} + + OptBuilder& operator[]( std::string const& optName ) { + addOptName( *ArgBuilder::m_arg, optName ); + return *this; + } + }; + + public: + + CommandLine() + : m_boundProcessName( new Detail::NullBinder<ConfigT>() ), + m_highestSpecifiedArgPosition( 0 ), + m_throwOnUnrecognisedTokens( false ) + {} + CommandLine( CommandLine const& other ) + : m_boundProcessName( other.m_boundProcessName ), + m_options ( other.m_options ), + m_positionalArgs( other.m_positionalArgs ), + m_highestSpecifiedArgPosition( other.m_highestSpecifiedArgPosition ), + m_throwOnUnrecognisedTokens( other.m_throwOnUnrecognisedTokens ) + { + if( other.m_floatingArg.get() ) + m_floatingArg.reset( new Arg( *other.m_floatingArg ) ); + } + + CommandLine& setThrowOnUnrecognisedTokens( bool shouldThrow = true ) { + m_throwOnUnrecognisedTokens = shouldThrow; + return *this; + } + + + OptBuilder operator[]( std::string const& optName ) { + m_options.push_back( Arg() ); + addOptName( m_options.back(), optName ); + OptBuilder builder( &m_options.back() ); + return builder; + } + + ArgBuilder operator[]( int position ) { + m_positionalArgs.insert( std::make_pair( position, Arg() ) ); + if( position > m_highestSpecifiedArgPosition ) + m_highestSpecifiedArgPosition = position; + setPositionalArg( m_positionalArgs[position], position ); + ArgBuilder builder( &m_positionalArgs[position] ); + return builder; + } + + // Invoke this with the _ instance + ArgBuilder operator[]( UnpositionalTag ) { + if( m_floatingArg.get() ) + throw std::logic_error( "Only one unpositional argument can be added" ); + m_floatingArg.reset( new Arg() ); + ArgBuilder builder( m_floatingArg.get() ); + return builder; + } + + template<typename C, typename M> + void bindProcessName( M C::* field ) { + m_boundProcessName = new Detail::BoundDataMember<C,M>( field ); + } + template<typename C, typename M> + void bindProcessName( void (C::*_unaryMethod)( M ) ) { + m_boundProcessName = new Detail::BoundUnaryMethod<C,M>( _unaryMethod ); + } + + void optUsage( std::ostream& os, std::size_t indent = 0, std::size_t width = Detail::consoleWidth ) const { + typename std::vector<Arg>::const_iterator itBegin = m_options.begin(), itEnd = m_options.end(), it; + std::size_t maxWidth = 0; + for( it = itBegin; it != itEnd; ++it ) + maxWidth = (std::max)( maxWidth, it->commands().size() ); + + for( it = itBegin; it != itEnd; ++it ) { + Detail::Text usage( it->commands(), Detail::TextAttributes() + .setWidth( maxWidth+indent ) + .setIndent( indent ) ); + Detail::Text desc( it->description, Detail::TextAttributes() + .setWidth( width - maxWidth - 3 ) ); + + for( std::size_t i = 0; i < (std::max)( usage.size(), desc.size() ); ++i ) { + std::string usageCol = i < usage.size() ? usage[i] : ""; + os << usageCol; + + if( i < desc.size() && !desc[i].empty() ) + os << std::string( indent + 2 + maxWidth - usageCol.size(), ' ' ) + << desc[i]; + os << "\n"; + } + } + } + std::string optUsage() const { + std::ostringstream oss; + optUsage( oss ); + return oss.str(); + } + + void argSynopsis( std::ostream& os ) const { + for( int i = 1; i <= m_highestSpecifiedArgPosition; ++i ) { + if( i > 1 ) + os << " "; + typename std::map<int, Arg>::const_iterator it = m_positionalArgs.find( i ); + if( it != m_positionalArgs.end() ) + os << "<" << it->second.placeholder << ">"; + else if( m_floatingArg.get() ) + os << "<" << m_floatingArg->placeholder << ">"; + else + throw std::logic_error( "non consecutive positional arguments with no floating args" ); + } + // !TBD No indication of mandatory args + if( m_floatingArg.get() ) { + if( m_highestSpecifiedArgPosition > 1 ) + os << " "; + os << "[<" << m_floatingArg->placeholder << "> ...]"; + } + } + std::string argSynopsis() const { + std::ostringstream oss; + argSynopsis( oss ); + return oss.str(); + } + + void usage( std::ostream& os, std::string const& procName ) const { + validate(); + os << "usage:\n " << procName << " "; + argSynopsis( os ); + if( !m_options.empty() ) { + os << " [options]\n\nwhere options are: \n"; + optUsage( os, 2 ); + } + os << "\n"; + } + std::string usage( std::string const& procName ) const { + std::ostringstream oss; + usage( oss, procName ); + return oss.str(); + } + + ConfigT parse( int argc, char const* const argv[] ) const { + ConfigT config; + parseInto( argc, argv, config ); + return config; + } + + std::vector<Parser::Token> parseInto( int argc, char const* argv[], ConfigT& config ) const { + std::string processName = argv[0]; + std::size_t lastSlash = processName.find_last_of( "/\\" ); + if( lastSlash != std::string::npos ) + processName = processName.substr( lastSlash+1 ); + m_boundProcessName.set( config, processName ); + std::vector<Parser::Token> tokens; + Parser parser; + parser.parseIntoTokens( argc, argv, tokens ); + return populate( tokens, config ); + } + + std::vector<Parser::Token> populate( std::vector<Parser::Token> const& tokens, ConfigT& config ) const { + validate(); + std::vector<Parser::Token> unusedTokens = populateOptions( tokens, config ); + unusedTokens = populateFixedArgs( unusedTokens, config ); + unusedTokens = populateFloatingArgs( unusedTokens, config ); + return unusedTokens; + } + + std::vector<Parser::Token> populateOptions( std::vector<Parser::Token> const& tokens, ConfigT& config ) const { + std::vector<Parser::Token> unusedTokens; + std::vector<std::string> errors; + for( std::size_t i = 0; i < tokens.size(); ++i ) { + Parser::Token const& token = tokens[i]; + typename std::vector<Arg>::const_iterator it = m_options.begin(), itEnd = m_options.end(); + for(; it != itEnd; ++it ) { + Arg const& arg = *it; + + try { + if( ( token.type == Parser::Token::ShortOpt && arg.hasShortName( token.data ) ) || + ( token.type == Parser::Token::LongOpt && arg.hasLongName( token.data ) ) ) { + if( arg.takesArg() ) { + if( i == tokens.size()-1 || tokens[i+1].type != Parser::Token::Positional ) + errors.push_back( "Expected argument to option: " + token.data ); + else + arg.boundField.set( config, tokens[++i].data ); + } + else { + arg.boundField.setFlag( config ); + } + break; + } + } + catch( std::exception& ex ) { + errors.push_back( std::string( ex.what() ) + "\n- while parsing: (" + arg.commands() + ")" ); + } + } + if( it == itEnd ) { + if( token.type == Parser::Token::Positional || !m_throwOnUnrecognisedTokens ) + unusedTokens.push_back( token ); + else if( errors.empty() && m_throwOnUnrecognisedTokens ) + errors.push_back( "unrecognised option: " + token.data ); + } + } + if( !errors.empty() ) { + std::ostringstream oss; + for( std::vector<std::string>::const_iterator it = errors.begin(), itEnd = errors.end(); + it != itEnd; + ++it ) { + if( it != errors.begin() ) + oss << "\n"; + oss << *it; + } + throw std::runtime_error( oss.str() ); + } + return unusedTokens; + } + std::vector<Parser::Token> populateFixedArgs( std::vector<Parser::Token> const& tokens, ConfigT& config ) const { + std::vector<Parser::Token> unusedTokens; + int position = 1; + for( std::size_t i = 0; i < tokens.size(); ++i ) { + Parser::Token const& token = tokens[i]; + typename std::map<int, Arg>::const_iterator it = m_positionalArgs.find( position ); + if( it != m_positionalArgs.end() ) + it->second.boundField.set( config, token.data ); + else + unusedTokens.push_back( token ); + if( token.type == Parser::Token::Positional ) + position++; + } + return unusedTokens; + } + std::vector<Parser::Token> populateFloatingArgs( std::vector<Parser::Token> const& tokens, ConfigT& config ) const { + if( !m_floatingArg.get() ) + return tokens; + std::vector<Parser::Token> unusedTokens; + for( std::size_t i = 0; i < tokens.size(); ++i ) { + Parser::Token const& token = tokens[i]; + if( token.type == Parser::Token::Positional ) + m_floatingArg->boundField.set( config, token.data ); + else + unusedTokens.push_back( token ); + } + return unusedTokens; + } + + void validate() const + { + if( m_options.empty() && m_positionalArgs.empty() && !m_floatingArg.get() ) + throw std::logic_error( "No options or arguments specified" ); + + for( typename std::vector<Arg>::const_iterator it = m_options.begin(), + itEnd = m_options.end(); + it != itEnd; ++it ) + it->validate(); + } + + private: + Detail::BoundArgFunction<ConfigT> m_boundProcessName; + std::vector<Arg> m_options; + std::map<int, Arg> m_positionalArgs; + ArgAutoPtr m_floatingArg; + int m_highestSpecifiedArgPosition; + bool m_throwOnUnrecognisedTokens; + }; + +} // end namespace Clara + + +STITCH_CLARA_CLOSE_NAMESPACE +#undef STITCH_CLARA_OPEN_NAMESPACE +#undef STITCH_CLARA_CLOSE_NAMESPACE + + +#endif // TWOBLUECUBES_CLARA_H_INCLUDED diff --git a/unittest/Catch/include/external/tbc_text_format.h b/unittest/Catch/include/external/tbc_text_format.h new file mode 100644 index 0000000..a63d6a1 --- /dev/null +++ b/unittest/Catch/include/external/tbc_text_format.h @@ -0,0 +1,153 @@ +/* + * Created by Phil on 18/4/2013. + * Copyright 2013 Two Blue Cubes Ltd. All rights reserved. + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + */ +// Only use header guard if we are not using an outer namespace +#ifndef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE +# ifdef TWOBLUECUBES_TEXT_FORMAT_H_INCLUDED +# ifndef TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED +# define TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED +# endif +# else +# define TWOBLUECUBES_TEXT_FORMAT_H_INCLUDED +# endif +#endif +#ifndef TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED +#include <string> +#include <vector> +#include <sstream> + +// Use optional outer namespace +#ifdef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE +namespace CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE { +#endif + +namespace Tbc { + +#ifdef TBC_TEXT_FORMAT_CONSOLE_WIDTH + const unsigned int consoleWidth = TBC_TEXT_FORMAT_CONSOLE_WIDTH; +#else + const unsigned int consoleWidth = 80; +#endif + + struct TextAttributes { + TextAttributes() + : initialIndent( std::string::npos ), + indent( 0 ), + width( consoleWidth-1 ), + tabChar( '\t' ) + {} + + TextAttributes& setInitialIndent( std::size_t _value ) { initialIndent = _value; return *this; } + TextAttributes& setIndent( std::size_t _value ) { indent = _value; return *this; } + TextAttributes& setWidth( std::size_t _value ) { width = _value; return *this; } + TextAttributes& setTabChar( char _value ) { tabChar = _value; return *this; } + + std::size_t initialIndent; // indent of first line, or npos + std::size_t indent; // indent of subsequent lines, or all if initialIndent is npos + std::size_t width; // maximum width of text, including indent. Longer text will wrap + char tabChar; // If this char is seen the indent is changed to current pos + }; + + class Text { + public: + Text( std::string const& _str, TextAttributes const& _attr = TextAttributes() ) + : attr( _attr ) + { + std::string wrappableChars = " [({.,/|\\-"; + std::size_t indent = _attr.initialIndent != std::string::npos + ? _attr.initialIndent + : _attr.indent; + std::string remainder = _str; + + while( !remainder.empty() ) { + if( lines.size() >= 1000 ) { + lines.push_back( "... message truncated due to excessive size" ); + return; + } + std::size_t tabPos = std::string::npos; + std::size_t width = (std::min)( remainder.size(), _attr.width - indent ); + std::size_t pos = remainder.find_first_of( '\n' ); + if( pos <= width ) { + width = pos; + } + pos = remainder.find_last_of( _attr.tabChar, width ); + if( pos != std::string::npos ) { + tabPos = pos; + if( remainder[width] == '\n' ) + width--; + remainder = remainder.substr( 0, tabPos ) + remainder.substr( tabPos+1 ); + } + + if( width == remainder.size() ) { + spliceLine( indent, remainder, width ); + } + else if( remainder[width] == '\n' ) { + spliceLine( indent, remainder, width ); + if( width <= 1 || remainder.size() != 1 ) + remainder = remainder.substr( 1 ); + indent = _attr.indent; + } + else { + pos = remainder.find_last_of( wrappableChars, width ); + if( pos != std::string::npos && pos > 0 ) { + spliceLine( indent, remainder, pos ); + if( remainder[0] == ' ' ) + remainder = remainder.substr( 1 ); + } + else { + spliceLine( indent, remainder, width-1 ); + lines.back() += "-"; + } + if( lines.size() == 1 ) + indent = _attr.indent; + if( tabPos != std::string::npos ) + indent += tabPos; + } + } + } + + void spliceLine( std::size_t _indent, std::string& _remainder, std::size_t _pos ) { + lines.push_back( std::string( _indent, ' ' ) + _remainder.substr( 0, _pos ) ); + _remainder = _remainder.substr( _pos ); + } + + typedef std::vector<std::string>::const_iterator const_iterator; + + const_iterator begin() const { return lines.begin(); } + const_iterator end() const { return lines.end(); } + std::string const& last() const { return lines.back(); } + std::size_t size() const { return lines.size(); } + std::string const& operator[]( std::size_t _index ) const { return lines[_index]; } + std::string toString() const { + std::ostringstream oss; + oss << *this; + return oss.str(); + } + + inline friend std::ostream& operator << ( std::ostream& _stream, Text const& _text ) { + for( Text::const_iterator it = _text.begin(), itEnd = _text.end(); + it != itEnd; ++it ) { + if( it != _text.begin() ) + _stream << "\n"; + _stream << *it; + } + return _stream; + } + + private: + std::string str; + TextAttributes attr; + std::vector<std::string> lines; + }; + +} // end namespace Tbc + +#ifdef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE +} // end outer namespace +#endif + +#endif // TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED diff --git a/unittest/Catch/include/internal/catch_approx.hpp b/unittest/Catch/include/internal/catch_approx.hpp new file mode 100644 index 0000000..f5dba61 --- /dev/null +++ b/unittest/Catch/include/internal/catch_approx.hpp @@ -0,0 +1,91 @@ +/* + * Created by Phil on 28/04/2011. + * Copyright 2010 Two Blue Cubes Ltd. All rights reserved. + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + */ +#ifndef TWOBLUECUBES_CATCH_APPROX_HPP_INCLUDED +#define TWOBLUECUBES_CATCH_APPROX_HPP_INCLUDED + +#include "catch_tostring.h" + +#include <cmath> +#include <limits> + +namespace Catch { +namespace Detail { + + class Approx { + public: + explicit Approx ( double value ) + : m_epsilon( std::numeric_limits<float>::epsilon()*100 ), + m_scale( 1.0 ), + m_value( value ) + {} + + Approx( Approx const& other ) + : m_epsilon( other.m_epsilon ), + m_scale( other.m_scale ), + m_value( other.m_value ) + {} + + static Approx custom() { + return Approx( 0 ); + } + + Approx operator()( double value ) { + Approx approx( value ); + approx.epsilon( m_epsilon ); + approx.scale( m_scale ); + return approx; + } + + friend bool operator == ( double lhs, Approx const& rhs ) { + // Thanks to Richard Harris for his help refining this formula + return fabs( lhs - rhs.m_value ) < rhs.m_epsilon * (rhs.m_scale + (std::max)( fabs(lhs), fabs(rhs.m_value) ) ); + } + + friend bool operator == ( Approx const& lhs, double rhs ) { + return operator==( rhs, lhs ); + } + + friend bool operator != ( double lhs, Approx const& rhs ) { + return !operator==( lhs, rhs ); + } + + friend bool operator != ( Approx const& lhs, double rhs ) { + return !operator==( rhs, lhs ); + } + + Approx& epsilon( double newEpsilon ) { + m_epsilon = newEpsilon; + return *this; + } + + Approx& scale( double newScale ) { + m_scale = newScale; + return *this; + } + + std::string toString() const { + std::ostringstream oss; + oss << "Approx( " << Catch::toString( m_value ) << " )"; + return oss.str(); + } + + private: + double m_epsilon; + double m_scale; + double m_value; + }; +} + +template<> +inline std::string toString<Detail::Approx>( Detail::Approx const& value ) { + return value.toString(); +} + +} // end namespace Catch + +#endif // TWOBLUECUBES_CATCH_APPROX_HPP_INCLUDED diff --git a/unittest/Catch/include/internal/catch_assertionresult.h b/unittest/Catch/include/internal/catch_assertionresult.h new file mode 100644 index 0000000..99b3a7c --- /dev/null +++ b/unittest/Catch/include/internal/catch_assertionresult.h @@ -0,0 +1,71 @@ +/* + * Created by Phil on 28/10/2010. + * Copyright 2010 Two Blue Cubes Ltd. All rights reserved. + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + */ +#ifndef TWOBLUECUBES_CATCH_ASSERTIONRESULT_H_INCLUDED +#define TWOBLUECUBES_CATCH_ASSERTIONRESULT_H_INCLUDED + +#include <string> +#include "catch_result_type.h" + +namespace Catch { + + struct AssertionInfo + { + AssertionInfo() {} + AssertionInfo( std::string const& _macroName, + SourceLineInfo const& _lineInfo, + std::string const& _capturedExpression, + ResultDisposition::Flags _resultDisposition ); + + std::string macroName; + SourceLineInfo lineInfo; + std::string capturedExpression; + ResultDisposition::Flags resultDisposition; + }; + + struct AssertionResultData + { + AssertionResultData() : resultType( ResultWas::Unknown ) {} + + std::string reconstructedExpression; + std::string message; + ResultWas::OfType resultType; + }; + + class AssertionResult { + public: + AssertionResult(); + AssertionResult( AssertionInfo const& info, AssertionResultData const& data ); + ~AssertionResult(); +# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS + AssertionResult( AssertionResult const& ) = default; + AssertionResult( AssertionResult && ) = default; + AssertionResult& operator = ( AssertionResult const& ) = default; + AssertionResult& operator = ( AssertionResult && ) = default; +# endif + + bool isOk() const; + bool succeeded() const; + ResultWas::OfType getResultType() const; + bool hasExpression() const; + bool hasMessage() const; + std::string getExpression() const; + std::string getExpressionInMacro() const; + bool hasExpandedExpression() const; + std::string getExpandedExpression() const; + std::string getMessage() const; + SourceLineInfo getSourceInfo() const; + std::string getTestMacroName() const; + + protected: + AssertionInfo m_info; + AssertionResultData m_resultData; + }; + +} // end namespace Catch + +#endif // TWOBLUECUBES_CATCH_ASSERTIONRESULT_H_INCLUDED diff --git a/unittest/Catch/include/internal/catch_assertionresult.hpp b/unittest/Catch/include/internal/catch_assertionresult.hpp new file mode 100644 index 0000000..bd59de9 --- /dev/null +++ b/unittest/Catch/include/internal/catch_assertionresult.hpp @@ -0,0 +1,91 @@ +/* + * Created by Phil on 8/8/12 + * Copyright 2012 Two Blue Cubes Ltd. All rights reserved. + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + */ +#ifndef TWOBLUECUBES_CATCH_ASSERTIONRESULT_HPP_INCLUDED +#define TWOBLUECUBES_CATCH_ASSERTIONRESULT_HPP_INCLUDED + +#include "catch_assertionresult.h" + +namespace Catch { + + + AssertionInfo::AssertionInfo( std::string const& _macroName, + SourceLineInfo const& _lineInfo, + std::string const& _capturedExpression, + ResultDisposition::Flags _resultDisposition ) + : macroName( _macroName ), + lineInfo( _lineInfo ), + capturedExpression( _capturedExpression ), + resultDisposition( _resultDisposition ) + {} + + AssertionResult::AssertionResult() {} + + AssertionResult::AssertionResult( AssertionInfo const& info, AssertionResultData const& data ) + : m_info( info ), + m_resultData( data ) + {} + + AssertionResult::~AssertionResult() {} + + // Result was a success + bool AssertionResult::succeeded() const { + return Catch::isOk( m_resultData.resultType ); + } + + // Result was a success, or failure is suppressed + bool AssertionResult::isOk() const { + return Catch::isOk( m_resultData.resultType ) || shouldSuppressFailure( m_info.resultDisposition ); + } + + ResultWas::OfType AssertionResult::getResultType() const { + return m_resultData.resultType; + } + + bool AssertionResult::hasExpression() const { + return !m_info.capturedExpression.empty(); + } + + bool AssertionResult::hasMessage() const { + return !m_resultData.message.empty(); + } + + std::string AssertionResult::getExpression() const { + if( isFalseTest( m_info.resultDisposition ) ) + return "!" + m_info.capturedExpression; + else + return m_info.capturedExpression; + } + std::string AssertionResult::getExpressionInMacro() const { + if( m_info.macroName.empty() ) + return m_info.capturedExpression; + else + return m_info.macroName + "( " + m_info.capturedExpression + " )"; + } + + bool AssertionResult::hasExpandedExpression() const { + return hasExpression() && getExpandedExpression() != getExpression(); + } + + std::string AssertionResult::getExpandedExpression() const { + return m_resultData.reconstructedExpression; + } + + std::string AssertionResult::getMessage() const { + return m_resultData.message; + } + SourceLineInfo AssertionResult::getSourceInfo() const { + return m_info.lineInfo; + } + + std::string AssertionResult::getTestMacroName() const { + return m_info.macroName; + } + +} // end namespace Catch + +#endif // TWOBLUECUBES_CATCH_ASSERTIONRESULT_HPP_INCLUDED diff --git a/unittest/Catch/include/internal/catch_capture.hpp b/unittest/Catch/include/internal/catch_capture.hpp new file mode 100644 index 0000000..1496fe3 --- /dev/null +++ b/unittest/Catch/include/internal/catch_capture.hpp @@ -0,0 +1,148 @@ +/* + * Created by Phil on 18/10/2010. + * Copyright 2010 Two Blue Cubes Ltd. All rights reserved. + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + */ +#ifndef TWOBLUECUBES_CATCH_CAPTURE_HPP_INCLUDED +#define TWOBLUECUBES_CATCH_CAPTURE_HPP_INCLUDED + +#include "catch_result_builder.h" +#include "catch_message.h" +#include "catch_interfaces_capture.h" +#include "catch_debugger.h" +#include "catch_common.h" +#include "catch_tostring.h" +#include "catch_interfaces_runner.h" +#include "catch_compiler_capabilities.h" + + +/////////////////////////////////////////////////////////////////////////////// +// In the event of a failure works out if the debugger needs to be invoked +// and/or an exception thrown and takes appropriate action. +// This needs to be done as a macro so the debugger will stop in the user +// source code rather than in Catch library code +#define INTERNAL_CATCH_REACT( resultBuilder ) \ + if( resultBuilder.shouldDebugBreak() ) CATCH_BREAK_INTO_DEBUGGER(); \ + resultBuilder.react(); + + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_TEST( expr, resultDisposition, macroName ) \ + do { \ + Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \ + try { \ + CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \ + ( __catchResult <= expr ).endExpression(); \ + } \ + catch( ... ) { \ + __catchResult.useActiveException( Catch::ResultDisposition::Normal ); \ + } \ + INTERNAL_CATCH_REACT( __catchResult ) \ + } while( Catch::isTrue( false && static_cast<bool>(expr) ) ) // expr here is never evaluated at runtime but it forces the compiler to give it a look + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_IF( expr, resultDisposition, macroName ) \ + INTERNAL_CATCH_TEST( expr, resultDisposition, macroName ); \ + if( Catch::getResultCapture().getLastResult()->succeeded() ) + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_ELSE( expr, resultDisposition, macroName ) \ + INTERNAL_CATCH_TEST( expr, resultDisposition, macroName ); \ + if( !Catch::getResultCapture().getLastResult()->succeeded() ) + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_NO_THROW( expr, resultDisposition, macroName ) \ + do { \ + Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \ + try { \ + expr; \ + __catchResult.captureResult( Catch::ResultWas::Ok ); \ + } \ + catch( ... ) { \ + __catchResult.useActiveException( resultDisposition ); \ + } \ + INTERNAL_CATCH_REACT( __catchResult ) \ + } while( Catch::alwaysFalse() ) + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_THROWS( expr, resultDisposition, matcher, macroName ) \ + do { \ + Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition, #matcher ); \ + if( __catchResult.allowThrows() ) \ + try { \ + expr; \ + __catchResult.captureResult( Catch::ResultWas::DidntThrowException ); \ + } \ + catch( ... ) { \ + __catchResult.captureExpectedException( matcher ); \ + } \ + else \ + __catchResult.captureResult( Catch::ResultWas::Ok ); \ + INTERNAL_CATCH_REACT( __catchResult ) \ + } while( Catch::alwaysFalse() ) + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_THROWS_AS( expr, exceptionType, resultDisposition, macroName ) \ + do { \ + Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \ + if( __catchResult.allowThrows() ) \ + try { \ + expr; \ + __catchResult.captureResult( Catch::ResultWas::DidntThrowException ); \ + } \ + catch( exceptionType ) { \ + __catchResult.captureResult( Catch::ResultWas::Ok ); \ + } \ + catch( ... ) { \ + __catchResult.useActiveException( resultDisposition ); \ + } \ + else \ + __catchResult.captureResult( Catch::ResultWas::Ok ); \ + INTERNAL_CATCH_REACT( __catchResult ) \ + } while( Catch::alwaysFalse() ) + + +/////////////////////////////////////////////////////////////////////////////// +#ifdef CATCH_CONFIG_VARIADIC_MACROS + #define INTERNAL_CATCH_MSG( messageType, resultDisposition, macroName, ... ) \ + do { \ + Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, "", resultDisposition ); \ + __catchResult << __VA_ARGS__ + ::Catch::StreamEndStop(); \ + __catchResult.captureResult( messageType ); \ + INTERNAL_CATCH_REACT( __catchResult ) \ + } while( Catch::alwaysFalse() ) +#else + #define INTERNAL_CATCH_MSG( messageType, resultDisposition, macroName, log ) \ + do { \ + Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, "", resultDisposition ); \ + __catchResult << log + ::Catch::StreamEndStop(); \ + __catchResult.captureResult( messageType ); \ + INTERNAL_CATCH_REACT( __catchResult ) \ + } while( Catch::alwaysFalse() ) +#endif + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_INFO( log, macroName ) \ + Catch::ScopedMessage INTERNAL_CATCH_UNIQUE_NAME( scopedMessage ) = Catch::MessageBuilder( macroName, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info ) << log; + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CHECK_THAT( arg, matcher, resultDisposition, macroName ) \ + do { \ + Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #arg ", " #matcher, resultDisposition ); \ + try { \ + std::string matcherAsString = (matcher).toString(); \ + __catchResult \ + .setLhs( Catch::toString( arg ) ) \ + .setRhs( matcherAsString == Catch::Detail::unprintableString ? #matcher : matcherAsString ) \ + .setOp( "matches" ) \ + .setResultType( (matcher).match( arg ) ); \ + __catchResult.captureExpression(); \ + } catch( ... ) { \ + __catchResult.useActiveException( resultDisposition | Catch::ResultDisposition::ContinueOnFailure ); \ + } \ + INTERNAL_CATCH_REACT( __catchResult ) \ + } while( Catch::alwaysFalse() ) + +#endif // TWOBLUECUBES_CATCH_CAPTURE_HPP_INCLUDED diff --git a/unittest/Catch/include/internal/catch_clara.h b/unittest/Catch/include/internal/catch_clara.h new file mode 100644 index 0000000..bfe2f4b --- /dev/null +++ b/unittest/Catch/include/internal/catch_clara.h @@ -0,0 +1,32 @@ +/* + * Created by Phil on 10/2/2014. + * Copyright 2014 Two Blue Cubes Ltd. All rights reserved. + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + * + */ +#ifndef TWOBLUECUBES_CATCH_CLARA_H_INCLUDED +#define TWOBLUECUBES_CATCH_CLARA_H_INCLUDED + +// Use Catch's value for console width (store Clara's off to the side, if present) +#ifdef CLARA_CONFIG_CONSOLE_WIDTH +#define CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH CLARA_CONFIG_CONSOLE_WIDTH +#undef CLARA_CONFIG_CONSOLE_WIDTH +#endif +#define CLARA_CONFIG_CONSOLE_WIDTH CATCH_CONFIG_CONSOLE_WIDTH + + +// Declare Clara inside the Catch namespace +#define STITCH_CLARA_OPEN_NAMESPACE namespace Catch { +#include "../external/clara.h" +#undef STITCH_CLARA_OPEN_NAMESPACE + + +// Restore Clara's value for console width, if present +#ifdef CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH +#define CLARA_CONFIG_CONSOLE_WIDTH CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH +#undef CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH +#endif + +#endif // TWOBLUECUBES_CATCH_CLARA_H_INCLUDED diff --git a/unittest/Catch/include/internal/catch_commandline.hpp b/unittest/Catch/include/internal/catch_commandline.hpp new file mode 100644 index 0000000..6926559 --- /dev/null +++ b/unittest/Catch/include/internal/catch_commandline.hpp @@ -0,0 +1,206 @@ +/* + * Created by Phil on 02/11/2010. + * Copyright 2010 Two Blue Cubes Ltd. All rights reserved. + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + */ +#ifndef TWOBLUECUBES_CATCH_COMMANDLINE_HPP_INCLUDED +#define TWOBLUECUBES_CATCH_COMMANDLINE_HPP_INCLUDED + +#include "catch_config.hpp" +#include "catch_common.h" +#include "catch_clara.h" + +#include <fstream> + +namespace Catch { + + inline void abortAfterFirst( ConfigData& config ) { config.abortAfter = 1; } + inline void abortAfterX( ConfigData& config, int x ) { + if( x < 1 ) + throw std::runtime_error( "Value after -x or --abortAfter must be greater than zero" ); + config.abortAfter = x; + } + inline void addTestOrTags( ConfigData& config, std::string const& _testSpec ) { config.testsOrTags.push_back( _testSpec ); } + inline void addReporterName( ConfigData& config, std::string const& _reporterName ) { config.reporterNames.push_back( _reporterName ); } + + inline void addWarning( ConfigData& config, std::string const& _warning ) { + if( _warning == "NoAssertions" ) + config.warnings = static_cast<WarnAbout::What>( config.warnings | WarnAbout::NoAssertions ); + else + throw std::runtime_error( "Unrecognised warning: '" + _warning + "'" ); + } + inline void setOrder( ConfigData& config, std::string const& order ) { + if( startsWith( "declared", order ) ) + config.runOrder = RunTests::InDeclarationOrder; + else if( startsWith( "lexical", order ) ) + config.runOrder = RunTests::InLexicographicalOrder; + else if( startsWith( "random", order ) ) + config.runOrder = RunTests::InRandomOrder; + else + throw std::runtime_error( "Unrecognised ordering: '" + order + "'" ); + } + inline void setRngSeed( ConfigData& config, std::string const& seed ) { + if( seed == "time" ) { + config.rngSeed = static_cast<unsigned int>( std::time(0) ); + } + else { + std::stringstream ss; + ss << seed; + ss >> config.rngSeed; + if( ss.fail() ) + throw std::runtime_error( "Argment to --rng-seed should be the word 'time' or a number" ); + } + } + inline void setVerbosity( ConfigData& config, int level ) { + // !TBD: accept strings? + config.verbosity = static_cast<Verbosity::Level>( level ); + } + inline void setShowDurations( ConfigData& config, bool _showDurations ) { + config.showDurations = _showDurations + ? ShowDurations::Always + : ShowDurations::Never; + } + inline void setUseColour( ConfigData& config, std::string const& value ) { + std::string mode = toLower( value ); + + if( mode == "yes" ) + config.useColour = UseColour::Yes; + else if( mode == "no" ) + config.useColour = UseColour::No; + else if( mode == "auto" ) + config.useColour = UseColour::Auto; + else + throw std::runtime_error( "colour mode must be one of: auto, yes or no" ); + } + inline void forceColour( ConfigData& config ) { + config.useColour = UseColour::Yes; + } + inline void loadTestNamesFromFile( ConfigData& config, std::string const& _filename ) { + std::ifstream f( _filename.c_str() ); + if( !f.is_open() ) + throw std::domain_error( "Unable to load input file: " + _filename ); + + std::string line; + while( std::getline( f, line ) ) { + line = trim(line); + if( !line.empty() && !startsWith( line, "#" ) ) + addTestOrTags( config, "\"" + line + "\"," ); + } + } + + inline Clara::CommandLine<ConfigData> makeCommandLineParser() { + + using namespace Clara; + CommandLine<ConfigData> cli; + + cli.bindProcessName( &ConfigData::processName ); + + cli["-?"]["-h"]["--help"] + .describe( "display usage information" ) + .bind( &ConfigData::showHelp ); + + cli["-l"]["--list-tests"] + .describe( "list all/matching test cases" ) + .bind( &ConfigData::listTests ); + + cli["-t"]["--list-tags"] + .describe( "list all/matching tags" ) + .bind( &ConfigData::listTags ); + + cli["-s"]["--success"] + .describe( "include successful tests in output" ) + .bind( &ConfigData::showSuccessfulTests ); + + cli["-b"]["--break"] + .describe( "break into debugger on failure" ) + .bind( &ConfigData::shouldDebugBreak ); + + cli["-e"]["--nothrow"] + .describe( "skip exception tests" ) + .bind( &ConfigData::noThrow ); + + cli["-i"]["--invisibles"] + .describe( "show invisibles (tabs, newlines)" ) + .bind( &ConfigData::showInvisibles ); + + cli["-o"]["--out"] + .describe( "output filename" ) + .bind( &ConfigData::outputFilename, "filename" ); + + cli["-r"]["--reporter"] +// .placeholder( "name[:filename]" ) + .describe( "reporter to use (defaults to console)" ) + .bind( &addReporterName, "name" ); + + cli["-n"]["--name"] + .describe( "suite name" ) + .bind( &ConfigData::name, "name" ); + + cli["-a"]["--abort"] + .describe( "abort at first failure" ) + .bind( &abortAfterFirst ); + + cli["-x"]["--abortx"] + .describe( "abort after x failures" ) + .bind( &abortAfterX, "no. failures" ); + + cli["-w"]["--warn"] + .describe( "enable warnings" ) + .bind( &addWarning, "warning name" ); + +// - needs updating if reinstated +// cli.into( &setVerbosity ) +// .describe( "level of verbosity (0=no output)" ) +// .shortOpt( "v") +// .longOpt( "verbosity" ) +// .placeholder( "level" ); + + cli[_] + .describe( "which test or tests to use" ) + .bind( &addTestOrTags, "test name, pattern or tags" ); + + cli["-d"]["--durations"] + .describe( "show test durations" ) + .bind( &setShowDurations, "yes|no" ); + + cli["-f"]["--input-file"] + .describe( "load test names to run from a file" ) + .bind( &loadTestNamesFromFile, "filename" ); + + cli["-#"]["--filenames-as-tags"] + .describe( "adds a tag for the filename" ) + .bind( &ConfigData::filenamesAsTags ); + + // Less common commands which don't have a short form + cli["--list-test-names-only"] + .describe( "list all/matching test cases names only" ) + .bind( &ConfigData::listTestNamesOnly ); + + cli["--list-reporters"] + .describe( "list all reporters" ) + .bind( &ConfigData::listReporters ); + + cli["--order"] + .describe( "test case order (defaults to decl)" ) + .bind( &setOrder, "decl|lex|rand" ); + + cli["--rng-seed"] + .describe( "set a specific seed for random numbers" ) + .bind( &setRngSeed, "'time'|number" ); + + cli["--force-colour"] + .describe( "force colourised output (deprecated)" ) + .bind( &forceColour ); + + cli["--use-colour"] + .describe( "should output be colourised" ) + .bind( &setUseColour, "yes|no" ); + + return cli; + } + +} // end namespace Catch + +#endif // TWOBLUECUBES_CATCH_COMMANDLINE_HPP_INCLUDED diff --git a/unittest/Catch/include/internal/catch_common.h b/unittest/Catch/include/internal/catch_common.h new file mode 100644 index 0000000..7f9cfc4 --- /dev/null +++ b/unittest/Catch/include/internal/catch_common.h @@ -0,0 +1,141 @@ +/* + * Created by Phil on 29/10/2010. + * Copyright 2010 Two Blue Cubes Ltd. All rights reserved. + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + */ +#ifndef TWOBLUECUBES_CATCH_COMMON_H_INCLUDED +#define TWOBLUECUBES_CATCH_COMMON_H_INCLUDED + +#define INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) name##line +#define INTERNAL_CATCH_UNIQUE_NAME_LINE( name, line ) INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) +#define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __LINE__ ) + +#define INTERNAL_CATCH_STRINGIFY2( expr ) #expr +#define INTERNAL_CATCH_STRINGIFY( expr ) INTERNAL_CATCH_STRINGIFY2( expr ) + +#include <sstream> +#include <stdexcept> +#include <algorithm> + +#include "catch_compiler_capabilities.h" + +namespace Catch { + + struct IConfig; + + struct CaseSensitive { enum Choice { + Yes, + No + }; }; + + class NonCopyable { +#ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS + NonCopyable( NonCopyable const& ) = delete; + NonCopyable( NonCopyable && ) = delete; + NonCopyable& operator = ( NonCopyable const& ) = delete; + NonCopyable& operator = ( NonCopyable && ) = delete; +#else + NonCopyable( NonCopyable const& info ); + NonCopyable& operator = ( NonCopyable const& ); +#endif + + protected: + NonCopyable() {} + virtual ~NonCopyable(); + }; + + class SafeBool { + public: + typedef void (SafeBool::*type)() const; + + static type makeSafe( bool value ) { + return value ? &SafeBool::trueValue : 0; + } + private: + void trueValue() const {} + }; + + template<typename ContainerT> + inline void deleteAll( ContainerT& container ) { + typename ContainerT::const_iterator it = container.begin(); + typename ContainerT::const_iterator itEnd = container.end(); + for(; it != itEnd; ++it ) + delete *it; + } + template<typename AssociativeContainerT> + inline void deleteAllValues( AssociativeContainerT& container ) { + typename AssociativeContainerT::const_iterator it = container.begin(); + typename AssociativeContainerT::const_iterator itEnd = container.end(); + for(; it != itEnd; ++it ) + delete it->second; + } + + bool startsWith( std::string const& s, std::string const& prefix ); + bool endsWith( std::string const& s, std::string const& suffix ); + bool contains( std::string const& s, std::string const& infix ); + void toLowerInPlace( std::string& s ); + std::string toLower( std::string const& s ); + std::string trim( std::string const& str ); + bool replaceInPlace( std::string& str, std::string const& replaceThis, std::string const& withThis ); + + struct pluralise { + pluralise( std::size_t count, std::string const& label ); + + friend std::ostream& operator << ( std::ostream& os, pluralise const& pluraliser ); + + std::size_t m_count; + std::string m_label; + }; + + struct SourceLineInfo { + + SourceLineInfo(); + SourceLineInfo( char const* _file, std::size_t _line ); + SourceLineInfo( SourceLineInfo const& other ); +# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS + SourceLineInfo( SourceLineInfo && ) = default; + SourceLineInfo& operator = ( SourceLineInfo const& ) = default; + SourceLineInfo& operator = ( SourceLineInfo && ) = default; +# endif + bool empty() const; + bool operator == ( SourceLineInfo const& other ) const; + bool operator < ( SourceLineInfo const& other ) const; + + std::string file; + std::size_t line; + }; + + std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info ); + + // This is just here to avoid compiler warnings with macro constants and boolean literals + inline bool isTrue( bool value ){ return value; } + inline bool alwaysTrue() { return true; } + inline bool alwaysFalse() { return false; } + + void throwLogicError( std::string const& message, SourceLineInfo const& locationInfo ); + + void seedRng( IConfig const& config ); + unsigned int rngSeed(); + + // Use this in variadic streaming macros to allow + // >> +StreamEndStop + // as well as + // >> stuff +StreamEndStop + struct StreamEndStop { + std::string operator+() { + return std::string(); + } + }; + template<typename T> + T const& operator + ( T const& value, StreamEndStop ) { + return value; + } +} + +#define CATCH_INTERNAL_LINEINFO ::Catch::SourceLineInfo( __FILE__, static_cast<std::size_t>( __LINE__ ) ) +#define CATCH_INTERNAL_ERROR( msg ) ::Catch::throwLogicError( msg, CATCH_INTERNAL_LINEINFO ); + +#endif // TWOBLUECUBES_CATCH_COMMON_H_INCLUDED + diff --git a/unittest/Catch/include/internal/catch_common.hpp b/unittest/Catch/include/internal/catch_common.hpp new file mode 100644 index 0000000..2342ae6 --- /dev/null +++ b/unittest/Catch/include/internal/catch_common.hpp @@ -0,0 +1,111 @@ +/* + * Created by Phil on 27/11/2013. + * Copyright 2013 Two Blue Cubes Ltd. All rights reserved. + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + */ +#ifndef TWOBLUECUBES_CATCH_COMMON_HPP_INCLUDED +#define TWOBLUECUBES_CATCH_COMMON_HPP_INCLUDED + +#include "catch_common.h" + +namespace Catch { + + bool startsWith( std::string const& s, std::string const& prefix ) { + return s.size() >= prefix.size() && s.substr( 0, prefix.size() ) == prefix; + } + bool endsWith( std::string const& s, std::string const& suffix ) { + return s.size() >= suffix.size() && s.substr( s.size()-suffix.size(), suffix.size() ) == suffix; + } + bool contains( std::string const& s, std::string const& infix ) { + return s.find( infix ) != std::string::npos; + } + void toLowerInPlace( std::string& s ) { + std::transform( s.begin(), s.end(), s.begin(), ::tolower ); + } + std::string toLower( std::string const& s ) { + std::string lc = s; + toLowerInPlace( lc ); + return lc; + } + std::string trim( std::string const& str ) { + static char const* whitespaceChars = "\n\r\t "; + std::string::size_type start = str.find_first_not_of( whitespaceChars ); + std::string::size_type end = str.find_last_not_of( whitespaceChars ); + + return start != std::string::npos ? str.substr( start, 1+end-start ) : ""; + } + + bool replaceInPlace( std::string& str, std::string const& replaceThis, std::string const& withThis ) { + bool replaced = false; + std::size_t i = str.find( replaceThis ); + while( i != std::string::npos ) { + replaced = true; + str = str.substr( 0, i ) + withThis + str.substr( i+replaceThis.size() ); + if( i < str.size()-withThis.size() ) + i = str.find( replaceThis, i+withThis.size() ); + else + i = std::string::npos; + } + return replaced; + } + + pluralise::pluralise( std::size_t count, std::string const& label ) + : m_count( count ), + m_label( label ) + {} + + std::ostream& operator << ( std::ostream& os, pluralise const& pluraliser ) { + os << pluraliser.m_count << " " << pluraliser.m_label; + if( pluraliser.m_count != 1 ) + os << "s"; + return os; + } + + SourceLineInfo::SourceLineInfo() : line( 0 ){} + SourceLineInfo::SourceLineInfo( char const* _file, std::size_t _line ) + : file( _file ), + line( _line ) + {} + SourceLineInfo::SourceLineInfo( SourceLineInfo const& other ) + : file( other.file ), + line( other.line ) + {} + bool SourceLineInfo::empty() const { + return file.empty(); + } + bool SourceLineInfo::operator == ( SourceLineInfo const& other ) const { + return line == other.line && file == other.file; + } + bool SourceLineInfo::operator < ( SourceLineInfo const& other ) const { + return line < other.line || ( line == other.line && file < other.file ); + } + + void seedRng( IConfig const& config ) { + if( config.rngSeed() != 0 ) + std::srand( config.rngSeed() ); + } + unsigned int rngSeed() { + return getCurrentContext().getConfig()->rngSeed(); + } + + std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info ) { +#ifndef __GNUG__ + os << info.file << "(" << info.line << ")"; +#else + os << info.file << ":" << info.line; +#endif + return os; + } + + void throwLogicError( std::string const& message, SourceLineInfo const& locationInfo ) { + std::ostringstream oss; + oss << locationInfo << ": Internal Catch error: '" << message << "'"; + if( alwaysTrue() ) + throw std::logic_error( oss.str() ); + } +} + +#endif // TWOBLUECUBES_CATCH_COMMON_HPP_INCLUDED + diff --git a/unittest/Catch/include/internal/catch_compiler_capabilities.h b/unittest/Catch/include/internal/catch_compiler_capabilities.h new file mode 100644 index 0000000..cd34537 --- /dev/null +++ b/unittest/Catch/include/internal/catch_compiler_capabilities.h @@ -0,0 +1,235 @@ +/* + * Created by Phil on 15/04/2013. + * Copyright 2013 Two Blue Cubes Ltd. All rights reserved. + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + */ +#ifndef TWOBLUECUBES_CATCH_COMPILER_CAPABILITIES_HPP_INCLUDED +#define TWOBLUECUBES_CATCH_COMPILER_CAPABILITIES_HPP_INCLUDED + +// Detect a number of compiler features - mostly C++11/14 conformance - by compiler +// The following features are defined: +// +// CATCH_CONFIG_CPP11_NULLPTR : is nullptr supported? +// CATCH_CONFIG_CPP11_NOEXCEPT : is noexcept supported? +// CATCH_CONFIG_CPP11_GENERATED_METHODS : The delete and default keywords for compiler generated methods +// CATCH_CONFIG_CPP11_IS_ENUM : std::is_enum is supported? +// CATCH_CONFIG_CPP11_TUPLE : std::tuple is supported +// CATCH_CONFIG_CPP11_LONG_LONG : is long long supported? +// CATCH_CONFIG_CPP11_OVERRIDE : is override supported? +// CATCH_CONFIG_CPP11_UNIQUE_PTR : is unique_ptr supported (otherwise use auto_ptr) + +// CATCH_CONFIG_CPP11_OR_GREATER : Is C++11 supported? + +// CATCH_CONFIG_VARIADIC_MACROS : are variadic macros supported? + +// **************** +// Note to maintainers: if new toggles are added please document them +// in configuration.md, too +// **************** + +// In general each macro has a _NO_<feature name> form +// (e.g. CATCH_CONFIG_CPP11_NO_NULLPTR) which disables the feature. +// Many features, at point of detection, define an _INTERNAL_ macro, so they +// can be combined, en-mass, with the _NO_ forms later. + +// All the C++11 features can be disabled with CATCH_CONFIG_NO_CPP11 + +#if defined(__cplusplus) && __cplusplus >= 201103L +# define CATCH_CPP11_OR_GREATER +#endif + +#ifdef __clang__ + +# if __has_feature(cxx_nullptr) +# define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR +# endif + +# if __has_feature(cxx_noexcept) +# define CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT +# endif + +# if defined(CATCH_CPP11_OR_GREATER) +# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS _Pragma( "clang diagnostic ignored \"-Wparentheses\"" ) +# endif + +#endif // __clang__ + +//////////////////////////////////////////////////////////////////////////////// +// Borland +#ifdef __BORLANDC__ + + +#endif // __BORLANDC__ + +//////////////////////////////////////////////////////////////////////////////// +// EDG +#ifdef __EDG_VERSION__ + + +#endif // __EDG_VERSION__ + +//////////////////////////////////////////////////////////////////////////////// +// Digital Mars +#ifdef __DMC__ + + +#endif // __DMC__ + +//////////////////////////////////////////////////////////////////////////////// +// GCC +#ifdef __GNUC__ + +# if __GNUC__ == 4 && __GNUC_MINOR__ >= 6 && defined(__GXX_EXPERIMENTAL_CXX0X__) +# define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR +# endif + +# if !defined(CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS) && defined(CATCH_CPP11_OR_GREATER) +# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS _Pragma( "gcc diagnostic ignored \"-Wparentheses\"" ) +# endif + +// - otherwise more recent versions define __cplusplus >= 201103L +// and will get picked up below + + +#endif // __GNUC__ + +//////////////////////////////////////////////////////////////////////////////// +// Visual C++ +#ifdef _MSC_VER + +#if (_MSC_VER >= 1600) +# define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR +# define CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR +#endif + +#if (_MSC_VER >= 1900 ) // (VC++ 13 (VS2015)) +#define CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT +#define CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS +#endif + +#endif // _MSC_VER + +//////////////////////////////////////////////////////////////////////////////// + +// Use variadic macros if the compiler supports them +#if ( defined _MSC_VER && _MSC_VER > 1400 && !defined __EDGE__) || \ + ( defined __WAVE__ && __WAVE_HAS_VARIADICS ) || \ + ( defined __GNUC__ && __GNUC__ >= 3 ) || \ + ( !defined __cplusplus && __STDC_VERSION__ >= 199901L || __cplusplus >= 201103L ) + +#define CATCH_INTERNAL_CONFIG_VARIADIC_MACROS + +#endif + + +//////////////////////////////////////////////////////////////////////////////// +// C++ language feature support + +// catch all support for C++11 +#if defined(CATCH_CPP11_OR_GREATER) + +# if !defined(CATCH_INTERNAL_CONFIG_CPP11_NULLPTR) +# define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR +# endif + +# ifndef CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT +# define CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT +# endif + +# ifndef CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS +# define CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS +# endif + +# ifndef CATCH_INTERNAL_CONFIG_CPP11_IS_ENUM +# define CATCH_INTERNAL_CONFIG_CPP11_IS_ENUM +# endif + +# ifndef CATCH_INTERNAL_CONFIG_CPP11_TUPLE +# define CATCH_INTERNAL_CONFIG_CPP11_TUPLE +# endif + +# ifndef CATCH_INTERNAL_CONFIG_VARIADIC_MACROS +# define CATCH_INTERNAL_CONFIG_VARIADIC_MACROS +# endif + +# if !defined(CATCH_INTERNAL_CONFIG_CPP11_LONG_LONG) +# define CATCH_INTERNAL_CONFIG_CPP11_LONG_LONG +# endif + +# if !defined(CATCH_INTERNAL_CONFIG_CPP11_OVERRIDE) +# define CATCH_INTERNAL_CONFIG_CPP11_OVERRIDE +# endif +# if !defined(CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR) +# define CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR +# endif + + +#endif // __cplusplus >= 201103L + +// Now set the actual defines based on the above + anything the user has configured +#if defined(CATCH_INTERNAL_CONFIG_CPP11_NULLPTR) && !defined(CATCH_CONFIG_CPP11_NO_NULLPTR) && !defined(CATCH_CONFIG_CPP11_NULLPTR) && !defined(CATCH_CONFIG_NO_CPP11) +# define CATCH_CONFIG_CPP11_NULLPTR +#endif +#if defined(CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT) && !defined(CATCH_CONFIG_CPP11_NO_NOEXCEPT) && !defined(CATCH_CONFIG_CPP11_NOEXCEPT) && !defined(CATCH_CONFIG_NO_CPP11) +# define CATCH_CONFIG_CPP11_NOEXCEPT +#endif +#if defined(CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS) && !defined(CATCH_CONFIG_CPP11_NO_GENERATED_METHODS) && !defined(CATCH_CONFIG_CPP11_GENERATED_METHODS) && !defined(CATCH_CONFIG_NO_CPP11) +# define CATCH_CONFIG_CPP11_GENERATED_METHODS +#endif +#if defined(CATCH_INTERNAL_CONFIG_CPP11_IS_ENUM) && !defined(CATCH_CONFIG_CPP11_NO_IS_ENUM) && !defined(CATCH_CONFIG_CPP11_IS_ENUM) && !defined(CATCH_CONFIG_NO_CPP11) +# define CATCH_CONFIG_CPP11_IS_ENUM +#endif +#if defined(CATCH_INTERNAL_CONFIG_CPP11_TUPLE) && !defined(CATCH_CONFIG_CPP11_NO_TUPLE) && !defined(CATCH_CONFIG_CPP11_TUPLE) && !defined(CATCH_CONFIG_NO_CPP11) +# define CATCH_CONFIG_CPP11_TUPLE +#endif +#if defined(CATCH_INTERNAL_CONFIG_VARIADIC_MACROS) && !defined(CATCH_CONFIG_NO_VARIADIC_MACROS) && !defined(CATCH_CONFIG_VARIADIC_MACROS) +# define CATCH_CONFIG_VARIADIC_MACROS +#endif +#if defined(CATCH_INTERNAL_CONFIG_CPP11_LONG_LONG) && !defined(CATCH_CONFIG_NO_LONG_LONG) && !defined(CATCH_CONFIG_CPP11_LONG_LONG) && !defined(CATCH_CONFIG_NO_CPP11) +# define CATCH_CONFIG_CPP11_LONG_LONG +#endif +#if defined(CATCH_INTERNAL_CONFIG_CPP11_OVERRIDE) && !defined(CATCH_CONFIG_NO_OVERRIDE) && !defined(CATCH_CONFIG_CPP11_OVERRIDE) && !defined(CATCH_CONFIG_NO_CPP11) +# define CATCH_CONFIG_CPP11_OVERRIDE +#endif +#if defined(CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR) && !defined(CATCH_CONFIG_NO_UNIQUE_PTR) && !defined(CATCH_CONFIG_CPP11_UNIQUE_PTR) && !defined(CATCH_CONFIG_NO_CPP11) +# define CATCH_CONFIG_CPP11_UNIQUE_PTR +#endif + +#if !defined(CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS) +# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS +#endif + +// noexcept support: +#if defined(CATCH_CONFIG_CPP11_NOEXCEPT) && !defined(CATCH_NOEXCEPT) +# define CATCH_NOEXCEPT noexcept +# define CATCH_NOEXCEPT_IS(x) noexcept(x) +#else +# define CATCH_NOEXCEPT throw() +# define CATCH_NOEXCEPT_IS(x) +#endif + +// nullptr support +#ifdef CATCH_CONFIG_CPP11_NULLPTR +# define CATCH_NULL nullptr +#else +# define CATCH_NULL NULL +#endif + +// override support +#ifdef CATCH_CONFIG_CPP11_OVERRIDE +# define CATCH_OVERRIDE override +#else +# define CATCH_OVERRIDE +#endif + +// unique_ptr support +#ifdef CATCH_CONFIG_CPP11_UNIQUE_PTR +# define CATCH_AUTO_PTR( T ) std::unique_ptr<T> +#else +# define CATCH_AUTO_PTR( T ) std::auto_ptr<T> +#endif + +#endif // TWOBLUECUBES_CATCH_COMPILER_CAPABILITIES_HPP_INCLUDED + diff --git a/unittest/Catch/include/internal/catch_config.hpp b/unittest/Catch/include/internal/catch_config.hpp new file mode 100644 index 0000000..2665f47 --- /dev/null +++ b/unittest/Catch/include/internal/catch_config.hpp @@ -0,0 +1,160 @@ +/* + * Created by Phil on 08/11/2010. + * Copyright 2010 Two Blue Cubes Ltd. All rights reserved. + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + */ +#ifndef TWOBLUECUBES_CATCH_CONFIG_HPP_INCLUDED +#define TWOBLUECUBES_CATCH_CONFIG_HPP_INCLUDED + +#include "catch_test_spec_parser.hpp" +#include "catch_context.h" +#include "catch_interfaces_config.h" +#include "catch_stream.h" + +#include <memory> +#include <vector> +#include <string> +#include <iostream> +#include <ctime> + +#ifndef CATCH_CONFIG_CONSOLE_WIDTH +#define CATCH_CONFIG_CONSOLE_WIDTH 80 +#endif + +namespace Catch { + + struct ConfigData { + + ConfigData() + : listTests( false ), + listTags( false ), + listReporters( false ), + listTestNamesOnly( false ), + showSuccessfulTests( false ), + shouldDebugBreak( false ), + noThrow( false ), + showHelp( false ), + showInvisibles( false ), + filenamesAsTags( false ), + abortAfter( -1 ), + rngSeed( 0 ), + verbosity( Verbosity::Normal ), + warnings( WarnAbout::Nothing ), + showDurations( ShowDurations::DefaultForReporter ), + runOrder( RunTests::InDeclarationOrder ), + useColour( UseColour::Auto ) + {} + + bool listTests; + bool listTags; + bool listReporters; + bool listTestNamesOnly; + + bool showSuccessfulTests; + bool shouldDebugBreak; + bool noThrow; + bool showHelp; + bool showInvisibles; + bool filenamesAsTags; + + int abortAfter; + unsigned int rngSeed; + + Verbosity::Level verbosity; + WarnAbout::What warnings; + ShowDurations::OrNot showDurations; + RunTests::InWhatOrder runOrder; + UseColour::YesOrNo useColour; + + std::string outputFilename; + std::string name; + std::string processName; + + std::vector<std::string> reporterNames; + std::vector<std::string> testsOrTags; + }; + + + class Config : public SharedImpl<IConfig> { + private: + Config( Config const& other ); + Config& operator = ( Config const& other ); + virtual void dummy(); + public: + + Config() + {} + + Config( ConfigData const& data ) + : m_data( data ), + m_stream( openStream() ) + { + if( !data.testsOrTags.empty() ) { + TestSpecParser parser( ITagAliasRegistry::get() ); + for( std::size_t i = 0; i < data.testsOrTags.size(); ++i ) + parser.parse( data.testsOrTags[i] ); + m_testSpec = parser.testSpec(); + } + } + + virtual ~Config() { + } + + std::string const& getFilename() const { + return m_data.outputFilename ; + } + + bool listTests() const { return m_data.listTests; } + bool listTestNamesOnly() const { return m_data.listTestNamesOnly; } + bool listTags() const { return m_data.listTags; } + bool listReporters() const { return m_data.listReporters; } + + std::string getProcessName() const { return m_data.processName; } + + bool shouldDebugBreak() const { return m_data.shouldDebugBreak; } + + std::vector<std::string> getReporterNames() const { return m_data.reporterNames; } + + int abortAfter() const { return m_data.abortAfter; } + + TestSpec const& testSpec() const { return m_testSpec; } + + bool showHelp() const { return m_data.showHelp; } + bool showInvisibles() const { return m_data.showInvisibles; } + + // IConfig interface + virtual bool allowThrows() const { return !m_data.noThrow; } + virtual std::ostream& stream() const { return m_stream->stream(); } + virtual std::string name() const { return m_data.name.empty() ? m_data.processName : m_data.name; } + virtual bool includeSuccessfulResults() const { return m_data.showSuccessfulTests; } + virtual bool warnAboutMissingAssertions() const { return m_data.warnings & WarnAbout::NoAssertions; } + virtual ShowDurations::OrNot showDurations() const { return m_data.showDurations; } + virtual RunTests::InWhatOrder runOrder() const { return m_data.runOrder; } + virtual unsigned int rngSeed() const { return m_data.rngSeed; } + virtual UseColour::YesOrNo useColour() const { return m_data.useColour; } + + private: + + IStream const* openStream() { + if( m_data.outputFilename.empty() ) + return new CoutStream(); + else if( m_data.outputFilename[0] == '%' ) { + if( m_data.outputFilename == "%debug" ) + return new DebugOutStream(); + else + throw std::domain_error( "Unrecognised stream: " + m_data.outputFilename ); + } + else + return new FileStream( m_data.outputFilename ); + } + ConfigData m_data; + + std::auto_ptr<IStream const> m_stream; + TestSpec m_testSpec; + }; + +} // end namespace Catch + +#endif // TWOBLUECUBES_CATCH_CONFIG_HPP_INCLUDED diff --git a/unittest/Catch/include/internal/catch_console_colour.hpp b/unittest/Catch/include/internal/catch_console_colour.hpp new file mode 100644 index 0000000..f0a8a69 --- /dev/null +++ b/unittest/Catch/include/internal/catch_console_colour.hpp @@ -0,0 +1,67 @@ +/* + * Created by Phil on 25/2/2012. + * Copyright 2012 Two Blue Cubes Ltd. All rights reserved. + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + */ +#ifndef TWOBLUECUBES_CATCH_CONSOLE_COLOUR_HPP_INCLUDED +#define TWOBLUECUBES_CATCH_CONSOLE_COLOUR_HPP_INCLUDED + +#include "catch_common.h" + +namespace Catch { + + struct Colour { + enum Code { + None = 0, + + White, + Red, + Green, + Blue, + Cyan, + Yellow, + Grey, + + Bright = 0x10, + + BrightRed = Bright | Red, + BrightGreen = Bright | Green, + LightGrey = Bright | Grey, + BrightWhite = Bright | White, + + // By intention + FileName = LightGrey, + Warning = Yellow, + ResultError = BrightRed, + ResultSuccess = BrightGreen, + ResultExpectedFailure = Warning, + + Error = BrightRed, + Success = Green, + + OriginalExpression = Cyan, + ReconstructedExpression = Yellow, + + SecondaryText = LightGrey, + Headers = White + }; + + // Use constructed object for RAII guard + Colour( Code _colourCode ); + Colour( Colour const& other ); + ~Colour(); + + // Use static method for one-shot changes + static void use( Code _colourCode ); + + private: + bool m_moved; + }; + + inline std::ostream& operator << ( std::ostream& os, Colour const& ) { return os; } + +} // end namespace Catch + +#endif // TWOBLUECUBES_CATCH_CONSOLE_COLOUR_HPP_INCLUDED diff --git a/unittest/Catch/include/internal/catch_console_colour_impl.hpp b/unittest/Catch/include/internal/catch_console_colour_impl.hpp new file mode 100644 index 0000000..f776952 --- /dev/null +++ b/unittest/Catch/include/internal/catch_console_colour_impl.hpp @@ -0,0 +1,198 @@ +/* + * Created by Phil on 25/2/2012. + * Copyright 2012 Two Blue Cubes Ltd. All rights reserved. + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + */ +#ifndef TWOBLUECUBES_CATCH_CONSOLE_COLOUR_IMPL_HPP_INCLUDED +#define TWOBLUECUBES_CATCH_CONSOLE_COLOUR_IMPL_HPP_INCLUDED + +#include "catch_console_colour.hpp" + +namespace Catch { + namespace { + + struct IColourImpl { + virtual ~IColourImpl() {} + virtual void use( Colour::Code _colourCode ) = 0; + }; + + struct NoColourImpl : IColourImpl { + void use( Colour::Code ) {} + + static IColourImpl* instance() { + static NoColourImpl s_instance; + return &s_instance; + } + }; + + } // anon namespace +} // namespace Catch + +#if !defined( CATCH_CONFIG_COLOUR_NONE ) && !defined( CATCH_CONFIG_COLOUR_WINDOWS ) && !defined( CATCH_CONFIG_COLOUR_ANSI ) +# ifdef CATCH_PLATFORM_WINDOWS +# define CATCH_CONFIG_COLOUR_WINDOWS +# else +# define CATCH_CONFIG_COLOUR_ANSI +# endif +#endif + + +#if defined ( CATCH_CONFIG_COLOUR_WINDOWS ) ///////////////////////////////////////// + +#ifndef NOMINMAX +#define NOMINMAX +#endif + +#ifdef __AFXDLL +#include <AfxWin.h> +#else +#include <windows.h> +#endif + +namespace Catch { +namespace { + + class Win32ColourImpl : public IColourImpl { + public: + Win32ColourImpl() : stdoutHandle( GetStdHandle(STD_OUTPUT_HANDLE) ) + { + CONSOLE_SCREEN_BUFFER_INFO csbiInfo; + GetConsoleScreenBufferInfo( stdoutHandle, &csbiInfo ); + originalForegroundAttributes = csbiInfo.wAttributes & ~( BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_BLUE | BACKGROUND_INTENSITY ); + originalBackgroundAttributes = csbiInfo.wAttributes & ~( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY ); + } + + virtual void use( Colour::Code _colourCode ) { + switch( _colourCode ) { + case Colour::None: return setTextAttribute( originalForegroundAttributes ); + case Colour::White: return setTextAttribute( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE ); + case Colour::Red: return setTextAttribute( FOREGROUND_RED ); + case Colour::Green: return setTextAttribute( FOREGROUND_GREEN ); + case Colour::Blue: return setTextAttribute( FOREGROUND_BLUE ); + case Colour::Cyan: return setTextAttribute( FOREGROUND_BLUE | FOREGROUND_GREEN ); + case Colour::Yellow: return setTextAttribute( FOREGROUND_RED | FOREGROUND_GREEN ); + case Colour::Grey: return setTextAttribute( 0 ); + + case Colour::LightGrey: return setTextAttribute( FOREGROUND_INTENSITY ); + case Colour::BrightRed: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_RED ); + case Colour::BrightGreen: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN ); + case Colour::BrightWhite: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE ); + + case Colour::Bright: throw std::logic_error( "not a colour" ); + } + } + + private: + void setTextAttribute( WORD _textAttribute ) { + SetConsoleTextAttribute( stdoutHandle, _textAttribute | originalBackgroundAttributes ); + } + HANDLE stdoutHandle; + WORD originalForegroundAttributes; + WORD originalBackgroundAttributes; + }; + + IColourImpl* platformColourInstance() { + static Win32ColourImpl s_instance; + + Ptr<IConfig const> config = getCurrentContext().getConfig(); + UseColour::YesOrNo colourMode = config + ? config->useColour() + : UseColour::Auto; + if( colourMode == UseColour::Auto ) + colourMode = !isDebuggerActive() + ? UseColour::Yes + : UseColour::No; + return colourMode == UseColour::Yes + ? &s_instance + : NoColourImpl::instance(); + } + +} // end anon namespace +} // end namespace Catch + +#elif defined( CATCH_CONFIG_COLOUR_ANSI ) ////////////////////////////////////// + +#include <unistd.h> + +namespace Catch { +namespace { + + // use POSIX/ ANSI console terminal codes + // Thanks to Adam Strzelecki for original contribution + // (http://github.com/nanoant) + // https://github.com/philsquared/Catch/pull/131 + class PosixColourImpl : public IColourImpl { + public: + virtual void use( Colour::Code _colourCode ) { + switch( _colourCode ) { + case Colour::None: + case Colour::White: return setColour( "[0m" ); + case Colour::Red: return setColour( "[0;31m" ); + case Colour::Green: return setColour( "[0;32m" ); + case Colour::Blue: return setColour( "[0:34m" ); + case Colour::Cyan: return setColour( "[0;36m" ); + case Colour::Yellow: return setColour( "[0;33m" ); + case Colour::Grey: return setColour( "[1;30m" ); + + case Colour::LightGrey: return setColour( "[0;37m" ); + case Colour::BrightRed: return setColour( "[1;31m" ); + case Colour::BrightGreen: return setColour( "[1;32m" ); + case Colour::BrightWhite: return setColour( "[1;37m" ); + + case Colour::Bright: throw std::logic_error( "not a colour" ); + } + } + static IColourImpl* instance() { + static PosixColourImpl s_instance; + return &s_instance; + } + + private: + void setColour( const char* _escapeCode ) { + Catch::cout() << '\033' << _escapeCode; + } + }; + + IColourImpl* platformColourInstance() { + Ptr<IConfig const> config = getCurrentContext().getConfig(); + UseColour::YesOrNo colourMode = config + ? config->useColour() + : UseColour::Auto; + if( colourMode == UseColour::Auto ) + colourMode = (!isDebuggerActive() && isatty(STDOUT_FILENO) ) + ? UseColour::Yes + : UseColour::No; + return colourMode == UseColour::Yes + ? PosixColourImpl::instance() + : NoColourImpl::instance(); + } + +} // end anon namespace +} // end namespace Catch + +#else // not Windows or ANSI /////////////////////////////////////////////// + +namespace Catch { + + static IColourImpl* platformColourInstance() { return NoColourImpl::instance(); } + +} // end namespace Catch + +#endif // Windows/ ANSI/ None + +namespace Catch { + + Colour::Colour( Code _colourCode ) : m_moved( false ) { use( _colourCode ); } + Colour::Colour( Colour const& _other ) : m_moved( false ) { const_cast<Colour&>( _other ).m_moved = true; } + Colour::~Colour(){ if( !m_moved ) use( None ); } + + void Colour::use( Code _colourCode ) { + static IColourImpl* impl = platformColourInstance(); + impl->use( _colourCode ); + } + +} // end namespace Catch + +#endif // TWOBLUECUBES_CATCH_CONSOLE_COLOUR_IMPL_HPP_INCLUDED diff --git a/unittest/Catch/include/internal/catch_context.h b/unittest/Catch/include/internal/catch_context.h new file mode 100644 index 0000000..9304b30 --- /dev/null +++ b/unittest/Catch/include/internal/catch_context.h @@ -0,0 +1,53 @@ +/* + * Created by Phil on 31/12/2010. + * Copyright 2010 Two Blue Cubes Ltd. All rights reserved. + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + */ +#ifndef TWOBLUECUBES_CATCH_CONTEXT_H_INCLUDED +#define TWOBLUECUBES_CATCH_CONTEXT_H_INCLUDED + +#include "catch_interfaces_generators.h" +#include "catch_ptr.hpp" + +#include <memory> +#include <vector> +#include <stdlib.h> + +namespace Catch { + + class TestCase; + class Stream; + struct IResultCapture; + struct IRunner; + struct IGeneratorsForTest; + struct IConfig; + + struct IContext + { + virtual ~IContext(); + + virtual IResultCapture* getResultCapture() = 0; + virtual IRunner* getRunner() = 0; + virtual size_t getGeneratorIndex( std::string const& fileInfo, size_t totalSize ) = 0; + virtual bool advanceGeneratorsForCurrentTest() = 0; + virtual Ptr<IConfig const> getConfig() const = 0; + }; + + struct IMutableContext : IContext + { + virtual ~IMutableContext(); + virtual void setResultCapture( IResultCapture* resultCapture ) = 0; + virtual void setRunner( IRunner* runner ) = 0; + virtual void setConfig( Ptr<IConfig const> const& config ) = 0; + }; + + IContext& getCurrentContext(); + IMutableContext& getCurrentMutableContext(); + void cleanUpContext(); + Stream createStream( std::string const& streamName ); + +} + +#endif // TWOBLUECUBES_CATCH_CONTEXT_H_INCLUDED diff --git a/unittest/Catch/include/internal/catch_context_impl.hpp b/unittest/Catch/include/internal/catch_context_impl.hpp new file mode 100644 index 0000000..030f29e --- /dev/null +++ b/unittest/Catch/include/internal/catch_context_impl.hpp @@ -0,0 +1,104 @@ +/* + * Created by Phil on 31/12/2010. + * Copyright 2010 Two Blue Cubes Ltd. All rights reserved. + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + */ +#ifndef TWOBLUECUBES_CATCH_CONTEXT_IMPL_HPP_INCLUDED +#define TWOBLUECUBES_CATCH_CONTEXT_IMPL_HPP_INCLUDED + +#include "catch_run_context.hpp" + +#include "catch_context.h" +#include "catch_stream.hpp" + +namespace Catch { + + class Context : public IMutableContext { + + Context() : m_config( CATCH_NULL ), m_runner( CATCH_NULL ), m_resultCapture( CATCH_NULL ) {} + Context( Context const& ); + void operator=( Context const& ); + + public: // IContext + virtual IResultCapture* getResultCapture() { + return m_resultCapture; + } + virtual IRunner* getRunner() { + return m_runner; + } + virtual size_t getGeneratorIndex( std::string const& fileInfo, size_t totalSize ) { + return getGeneratorsForCurrentTest() + .getGeneratorInfo( fileInfo, totalSize ) + .getCurrentIndex(); + } + virtual bool advanceGeneratorsForCurrentTest() { + IGeneratorsForTest* generators = findGeneratorsForCurrentTest(); + return generators && generators->moveNext(); + } + + virtual Ptr<IConfig const> getConfig() const { + return m_config; + } + + public: // IMutableContext + virtual void setResultCapture( IResultCapture* resultCapture ) { + m_resultCapture = resultCapture; + } + virtual void setRunner( IRunner* runner ) { + m_runner = runner; + } + virtual void setConfig( Ptr<IConfig const> const& config ) { + m_config = config; + } + + friend IMutableContext& getCurrentMutableContext(); + + private: + IGeneratorsForTest* findGeneratorsForCurrentTest() { + std::string testName = getResultCapture()->getCurrentTestName(); + + std::map<std::string, IGeneratorsForTest*>::const_iterator it = + m_generatorsByTestName.find( testName ); + return it != m_generatorsByTestName.end() + ? it->second + : CATCH_NULL; + } + + IGeneratorsForTest& getGeneratorsForCurrentTest() { + IGeneratorsForTest* generators = findGeneratorsForCurrentTest(); + if( !generators ) { + std::string testName = getResultCapture()->getCurrentTestName(); + generators = createGeneratorsForTest(); + m_generatorsByTestName.insert( std::make_pair( testName, generators ) ); + } + return *generators; + } + + private: + Ptr<IConfig const> m_config; + IRunner* m_runner; + IResultCapture* m_resultCapture; + std::map<std::string, IGeneratorsForTest*> m_generatorsByTestName; + }; + + namespace { + Context* currentContext = CATCH_NULL; + } + IMutableContext& getCurrentMutableContext() { + if( !currentContext ) + currentContext = new Context(); + return *currentContext; + } + IContext& getCurrentContext() { + return getCurrentMutableContext(); + } + + void cleanUpContext() { + delete currentContext; + currentContext = CATCH_NULL; + } +} + +#endif // TWOBLUECUBES_CATCH_CONTEXT_IMPL_HPP_INCLUDED diff --git a/unittest/Catch/include/internal/catch_debugger.h b/unittest/Catch/include/internal/catch_debugger.h new file mode 100644 index 0000000..0dd36aa --- /dev/null +++ b/unittest/Catch/include/internal/catch_debugger.h @@ -0,0 +1,49 @@ +/* + * Created by Phil on 3/12/2013. + * Copyright 2013 Two Blue Cubes Ltd. All rights reserved. + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + * + */ +#ifndef TWOBLUECUBES_CATCH_DEBUGGER_H_INCLUDED +#define TWOBLUECUBES_CATCH_DEBUGGER_H_INCLUDED + +#include "catch_platform.h" + +#include <string> + +namespace Catch{ + + bool isDebuggerActive(); + void writeToDebugConsole( std::string const& text ); +} + +#ifdef CATCH_PLATFORM_MAC + + // The following code snippet based on: + // http://cocoawithlove.com/2008/03/break-into-debugger.html + #ifdef DEBUG + #if defined(__ppc64__) || defined(__ppc__) + #define CATCH_BREAK_INTO_DEBUGGER() \ + if( Catch::isDebuggerActive() ) { \ + __asm__("li r0, 20\nsc\nnop\nli r0, 37\nli r4, 2\nsc\nnop\n" \ + : : : "memory","r0","r3","r4" ); \ + } + #else + #define CATCH_BREAK_INTO_DEBUGGER() if( Catch::isDebuggerActive() ) {__asm__("int $3\n" : : );} + #endif + #endif + +#elif defined(_MSC_VER) + #define CATCH_BREAK_INTO_DEBUGGER() if( Catch::isDebuggerActive() ) { __debugbreak(); } +#elif defined(__MINGW32__) + extern "C" __declspec(dllimport) void __stdcall DebugBreak(); + #define CATCH_BREAK_INTO_DEBUGGER() if( Catch::isDebuggerActive() ) { DebugBreak(); } +#endif + +#ifndef CATCH_BREAK_INTO_DEBUGGER +#define CATCH_BREAK_INTO_DEBUGGER() Catch::alwaysTrue(); +#endif + +#endif // TWOBLUECUBES_CATCH_DEBUGGER_H_INCLUDED diff --git a/unittest/Catch/include/internal/catch_debugger.hpp b/unittest/Catch/include/internal/catch_debugger.hpp new file mode 100644 index 0000000..8c55266 --- /dev/null +++ b/unittest/Catch/include/internal/catch_debugger.hpp @@ -0,0 +1,100 @@ +/* + * Created by Phil on 27/12/2010. + * Copyright 2010 Two Blue Cubes Ltd. All rights reserved. + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + * + */ +#ifndef TWOBLUECUBES_CATCH_DEBUGGER_HPP_INCLUDED +#define TWOBLUECUBES_CATCH_DEBUGGER_HPP_INCLUDED + +#include "catch_debugger.h" + +#include <iostream> + +#ifdef CATCH_PLATFORM_MAC + + #include <assert.h> + #include <stdbool.h> + #include <sys/types.h> + #include <unistd.h> + #include <sys/sysctl.h> + + namespace Catch{ + + // The following function is taken directly from the following technical note: + // http://developer.apple.com/library/mac/#qa/qa2004/qa1361.html + + // Returns true if the current process is being debugged (either + // running under the debugger or has a debugger attached post facto). + bool isDebuggerActive(){ + + int mib[4]; + struct kinfo_proc info; + size_t size; + + // Initialize the flags so that, if sysctl fails for some bizarre + // reason, we get a predictable result. + + info.kp_proc.p_flag = 0; + + // Initialize mib, which tells sysctl the info we want, in this case + // we're looking for information about a specific process ID. + + mib[0] = CTL_KERN; + mib[1] = KERN_PROC; + mib[2] = KERN_PROC_PID; + mib[3] = getpid(); + + // Call sysctl. + + size = sizeof(info); + if( sysctl(mib, sizeof(mib) / sizeof(*mib), &info, &size, CATCH_NULL, 0) != 0 ) { + Catch::cerr() << "\n** Call to sysctl failed - unable to determine if debugger is active **\n" << std::endl; + return false; + } + + // We're being debugged if the P_TRACED flag is set. + + return ( (info.kp_proc.p_flag & P_TRACED) != 0 ); + } + } // namespace Catch + +#elif defined(_MSC_VER) + extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent(); + namespace Catch { + bool isDebuggerActive() { + return IsDebuggerPresent() != 0; + } + } +#elif defined(__MINGW32__) + extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent(); + namespace Catch { + bool isDebuggerActive() { + return IsDebuggerPresent() != 0; + } + } +#else + namespace Catch { + inline bool isDebuggerActive() { return false; } + } +#endif // Platform + +#ifdef CATCH_PLATFORM_WINDOWS + extern "C" __declspec(dllimport) void __stdcall OutputDebugStringA( const char* ); + namespace Catch { + void writeToDebugConsole( std::string const& text ) { + ::OutputDebugStringA( text.c_str() ); + } + } +#else + namespace Catch { + void writeToDebugConsole( std::string const& text ) { + // !TBD: Need a version for Mac/ XCode and other IDEs + Catch::cout() << text; + } + } +#endif // Platform + +#endif // TWOBLUECUBES_CATCH_DEBUGGER_HPP_INCLUDED diff --git a/unittest/Catch/include/internal/catch_default_main.hpp b/unittest/Catch/include/internal/catch_default_main.hpp new file mode 100644 index 0000000..54202fb --- /dev/null +++ b/unittest/Catch/include/internal/catch_default_main.hpp @@ -0,0 +1,38 @@ +/* + * Created by Phil on 20/05/2011. + * Copyright 2011 Two Blue Cubes Ltd. All rights reserved. + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + */ +#ifndef TWOBLUECUBES_CATCH_DEFAULT_MAIN_HPP_INCLUDED +#define TWOBLUECUBES_CATCH_DEFAULT_MAIN_HPP_INCLUDED + +#ifndef __OBJC__ + +// Standard C/C++ main entry point +int main (int argc, char * argv[]) { + return Catch::Session().run( argc, argv ); +} + +#else // __OBJC__ + +// Objective-C entry point +int main (int argc, char * const argv[]) { +#if !CATCH_ARC_ENABLED + NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; +#endif + + Catch::registerTestMethods(); + int result = Catch::Session().run( argc, (char* const*)argv ); + +#if !CATCH_ARC_ENABLED + [pool drain]; +#endif + + return result; +} + +#endif // __OBJC__ + +#endif // TWOBLUECUBES_CATCH_DEFAULT_MAIN_HPP_INCLUDED diff --git a/unittest/Catch/include/internal/catch_evaluate.hpp b/unittest/Catch/include/internal/catch_evaluate.hpp new file mode 100644 index 0000000..b2f47cd --- /dev/null +++ b/unittest/Catch/include/internal/catch_evaluate.hpp @@ -0,0 +1,218 @@ +/* + * Created by Phil on 04/03/2011. + * Copyright 2011 Two Blue Cubes Ltd. All rights reserved. + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + */ +#ifndef TWOBLUECUBES_CATCH_EVALUATE_HPP_INCLUDED +#define TWOBLUECUBES_CATCH_EVALUATE_HPP_INCLUDED + +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable:4389) // '==' : signed/unsigned mismatch +#endif + +#include <cstddef> + +namespace Catch { +namespace Internal { + + enum Operator { + IsEqualTo, + IsNotEqualTo, + IsLessThan, + IsGreaterThan, + IsLessThanOrEqualTo, + IsGreaterThanOrEqualTo + }; + + template<Operator Op> struct OperatorTraits { static const char* getName(){ return "*error*"; } }; + template<> struct OperatorTraits<IsEqualTo> { static const char* getName(){ return "=="; } }; + template<> struct OperatorTraits<IsNotEqualTo> { static const char* getName(){ return "!="; } }; + template<> struct OperatorTraits<IsLessThan> { static const char* getName(){ return "<"; } }; + template<> struct OperatorTraits<IsGreaterThan> { static const char* getName(){ return ">"; } }; + template<> struct OperatorTraits<IsLessThanOrEqualTo> { static const char* getName(){ return "<="; } }; + template<> struct OperatorTraits<IsGreaterThanOrEqualTo>{ static const char* getName(){ return ">="; } }; + + template<typename T> + inline T& opCast(T const& t) { return const_cast<T&>(t); } + +// nullptr_t support based on pull request #154 from Konstantin Baumann +#ifdef CATCH_CONFIG_CPP11_NULLPTR + inline std::nullptr_t opCast(std::nullptr_t) { return nullptr; } +#endif // CATCH_CONFIG_CPP11_NULLPTR + + + // So the compare overloads can be operator agnostic we convey the operator as a template + // enum, which is used to specialise an Evaluator for doing the comparison. + template<typename T1, typename T2, Operator Op> + class Evaluator{}; + + template<typename T1, typename T2> + struct Evaluator<T1, T2, IsEqualTo> { + static bool evaluate( T1 const& lhs, T2 const& rhs) { + return bool( opCast( lhs ) == opCast( rhs ) ); + } + }; + template<typename T1, typename T2> + struct Evaluator<T1, T2, IsNotEqualTo> { + static bool evaluate( T1 const& lhs, T2 const& rhs ) { + return bool( opCast( lhs ) != opCast( rhs ) ); + } + }; + template<typename T1, typename T2> + struct Evaluator<T1, T2, IsLessThan> { + static bool evaluate( T1 const& lhs, T2 const& rhs ) { + return bool( opCast( lhs ) < opCast( rhs ) ); + } + }; + template<typename T1, typename T2> + struct Evaluator<T1, T2, IsGreaterThan> { + static bool evaluate( T1 const& lhs, T2 const& rhs ) { + return bool( opCast( lhs ) > opCast( rhs ) ); + } + }; + template<typename T1, typename T2> + struct Evaluator<T1, T2, IsGreaterThanOrEqualTo> { + static bool evaluate( T1 const& lhs, T2 const& rhs ) { + return bool( opCast( lhs ) >= opCast( rhs ) ); + } + }; + template<typename T1, typename T2> + struct Evaluator<T1, T2, IsLessThanOrEqualTo> { + static bool evaluate( T1 const& lhs, T2 const& rhs ) { + return bool( opCast( lhs ) <= opCast( rhs ) ); + } + }; + + template<Operator Op, typename T1, typename T2> + bool applyEvaluator( T1 const& lhs, T2 const& rhs ) { + return Evaluator<T1, T2, Op>::evaluate( lhs, rhs ); + } + + // This level of indirection allows us to specialise for integer types + // to avoid signed/ unsigned warnings + + // "base" overload + template<Operator Op, typename T1, typename T2> + bool compare( T1 const& lhs, T2 const& rhs ) { + return Evaluator<T1, T2, Op>::evaluate( lhs, rhs ); + } + + // unsigned X to int + template<Operator Op> bool compare( unsigned int lhs, int rhs ) { + return applyEvaluator<Op>( lhs, static_cast<unsigned int>( rhs ) ); + } + template<Operator Op> bool compare( unsigned long lhs, int rhs ) { + return applyEvaluator<Op>( lhs, static_cast<unsigned int>( rhs ) ); + } + template<Operator Op> bool compare( unsigned char lhs, int rhs ) { + return applyEvaluator<Op>( lhs, static_cast<unsigned int>( rhs ) ); + } + + // unsigned X to long + template<Operator Op> bool compare( unsigned int lhs, long rhs ) { + return applyEvaluator<Op>( lhs, static_cast<unsigned long>( rhs ) ); + } + template<Operator Op> bool compare( unsigned long lhs, long rhs ) { + return applyEvaluator<Op>( lhs, static_cast<unsigned long>( rhs ) ); + } + template<Operator Op> bool compare( unsigned char lhs, long rhs ) { + return applyEvaluator<Op>( lhs, static_cast<unsigned long>( rhs ) ); + } + + // int to unsigned X + template<Operator Op> bool compare( int lhs, unsigned int rhs ) { + return applyEvaluator<Op>( static_cast<unsigned int>( lhs ), rhs ); + } + template<Operator Op> bool compare( int lhs, unsigned long rhs ) { + return applyEvaluator<Op>( static_cast<unsigned int>( lhs ), rhs ); + } + template<Operator Op> bool compare( int lhs, unsigned char rhs ) { + return applyEvaluator<Op>( static_cast<unsigned int>( lhs ), rhs ); + } + + // long to unsigned X + template<Operator Op> bool compare( long lhs, unsigned int rhs ) { + return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs ); + } + template<Operator Op> bool compare( long lhs, unsigned long rhs ) { + return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs ); + } + template<Operator Op> bool compare( long lhs, unsigned char rhs ) { + return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs ); + } + + // pointer to long (when comparing against NULL) + template<Operator Op, typename T> bool compare( long lhs, T* rhs ) { + return Evaluator<T*, T*, Op>::evaluate( reinterpret_cast<T*>( lhs ), rhs ); + } + template<Operator Op, typename T> bool compare( T* lhs, long rhs ) { + return Evaluator<T*, T*, Op>::evaluate( lhs, reinterpret_cast<T*>( rhs ) ); + } + + // pointer to int (when comparing against NULL) + template<Operator Op, typename T> bool compare( int lhs, T* rhs ) { + return Evaluator<T*, T*, Op>::evaluate( reinterpret_cast<T*>( lhs ), rhs ); + } + template<Operator Op, typename T> bool compare( T* lhs, int rhs ) { + return Evaluator<T*, T*, Op>::evaluate( lhs, reinterpret_cast<T*>( rhs ) ); + } + +#ifdef CATCH_CONFIG_CPP11_LONG_LONG + // long long to unsigned X + template<Operator Op> bool compare( long long lhs, unsigned int rhs ) { + return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs ); + } + template<Operator Op> bool compare( long long lhs, unsigned long rhs ) { + return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs ); + } + template<Operator Op> bool compare( long long lhs, unsigned long long rhs ) { + return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs ); + } + template<Operator Op> bool compare( long long lhs, unsigned char rhs ) { + return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs ); + } + + // unsigned long long to X + template<Operator Op> bool compare( unsigned long long lhs, int rhs ) { + return applyEvaluator<Op>( static_cast<long>( lhs ), rhs ); + } + template<Operator Op> bool compare( unsigned long long lhs, long rhs ) { + return applyEvaluator<Op>( static_cast<long>( lhs ), rhs ); + } + template<Operator Op> bool compare( unsigned long long lhs, long long rhs ) { + return applyEvaluator<Op>( static_cast<long>( lhs ), rhs ); + } + template<Operator Op> bool compare( unsigned long long lhs, char rhs ) { + return applyEvaluator<Op>( static_cast<long>( lhs ), rhs ); + } + + // pointer to long long (when comparing against NULL) + template<Operator Op, typename T> bool compare( long long lhs, T* rhs ) { + return Evaluator<T*, T*, Op>::evaluate( reinterpret_cast<T*>( lhs ), rhs ); + } + template<Operator Op, typename T> bool compare( T* lhs, long long rhs ) { + return Evaluator<T*, T*, Op>::evaluate( lhs, reinterpret_cast<T*>( rhs ) ); + } +#endif // CATCH_CONFIG_CPP11_LONG_LONG + +#ifdef CATCH_CONFIG_CPP11_NULLPTR + // pointer to nullptr_t (when comparing against nullptr) + template<Operator Op, typename T> bool compare( std::nullptr_t, T* rhs ) { + return Evaluator<T*, T*, Op>::evaluate( nullptr, rhs ); + } + template<Operator Op, typename T> bool compare( T* lhs, std::nullptr_t ) { + return Evaluator<T*, T*, Op>::evaluate( lhs, nullptr ); + } +#endif // CATCH_CONFIG_CPP11_NULLPTR + +} // end of namespace Internal +} // end of namespace Catch + +#ifdef _MSC_VER +#pragma warning(pop) +#endif + +#endif // TWOBLUECUBES_CATCH_EVALUATE_HPP_INCLUDED diff --git a/unittest/Catch/include/internal/catch_exception_translator_registry.hpp b/unittest/Catch/include/internal/catch_exception_translator_registry.hpp new file mode 100644 index 0000000..c4bdb40 --- /dev/null +++ b/unittest/Catch/include/internal/catch_exception_translator_registry.hpp @@ -0,0 +1,73 @@ +/* + * Created by Phil on 20/04/2011. + * Copyright 2011 Two Blue Cubes Ltd. All rights reserved. + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + */ +#ifndef TWOBLUECUBES_CATCH_EXCEPTION_TRANSLATOR_REGISTRY_HPP_INCLUDED +#define TWOBLUECUBES_CATCH_EXCEPTION_TRANSLATOR_REGISTRY_HPP_INCLUDED + +#include "catch_interfaces_exception.h" +#include "catch_tostring.h" + +#ifdef __OBJC__ +#import "Foundation/Foundation.h" +#endif + +namespace Catch { + + class ExceptionTranslatorRegistry : public IExceptionTranslatorRegistry { + public: + ~ExceptionTranslatorRegistry() { + deleteAll( m_translators ); + } + + virtual void registerTranslator( const IExceptionTranslator* translator ) { + m_translators.push_back( translator ); + } + + virtual std::string translateActiveException() const { + try { +#ifdef __OBJC__ + // In Objective-C try objective-c exceptions first + @try { + return tryTranslators(); + } + @catch (NSException *exception) { + return Catch::toString( [exception description] ); + } +#else + return tryTranslators(); +#endif + } + catch( TestFailureException& ) { + throw; + } + catch( std::exception& ex ) { + return ex.what(); + } + catch( std::string& msg ) { + return msg; + } + catch( const char* msg ) { + return msg; + } + catch(...) { + return "Unknown exception"; + } + } + + std::string tryTranslators() const { + if( m_translators.empty() ) + throw; + else + return m_translators[0]->translate( m_translators.begin()+1, m_translators.end() ); + } + + private: + std::vector<const IExceptionTranslator*> m_translators; + }; +} + +#endif // TWOBLUECUBES_CATCH_EXCEPTION_TRANSLATOR_REGISTRY_HPP_INCLUDED diff --git a/unittest/Catch/include/internal/catch_expression_lhs.hpp b/unittest/Catch/include/internal/catch_expression_lhs.hpp new file mode 100644 index 0000000..51b803e --- /dev/null +++ b/unittest/Catch/include/internal/catch_expression_lhs.hpp @@ -0,0 +1,105 @@ +/* + * Created by Phil on 11/5/2012. + * Copyright 2012 Two Blue Cubes Ltd. All rights reserved. + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + */ +#ifndef TWOBLUECUBES_CATCH_EXPRESSION_LHS_HPP_INCLUDED +#define TWOBLUECUBES_CATCH_EXPRESSION_LHS_HPP_INCLUDED + +#include "catch_result_builder.h" +#include "catch_evaluate.hpp" +#include "catch_tostring.h" + +namespace Catch { + +// Wraps the LHS of an expression and captures the operator and RHS (if any) - +// wrapping them all in a ResultBuilder object +template<typename T> +class ExpressionLhs { + ExpressionLhs& operator = ( ExpressionLhs const& ); +# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS + ExpressionLhs& operator = ( ExpressionLhs && ) = delete; +# endif + +public: + ExpressionLhs( ResultBuilder& rb, T lhs ) : m_rb( rb ), m_lhs( lhs ) {} +# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS + ExpressionLhs( ExpressionLhs const& ) = default; + ExpressionLhs( ExpressionLhs && ) = default; +# endif + + template<typename RhsT> + ResultBuilder& operator == ( RhsT const& rhs ) { + return captureExpression<Internal::IsEqualTo>( rhs ); + } + + template<typename RhsT> + ResultBuilder& operator != ( RhsT const& rhs ) { + return captureExpression<Internal::IsNotEqualTo>( rhs ); + } + + template<typename RhsT> + ResultBuilder& operator < ( RhsT const& rhs ) { + return captureExpression<Internal::IsLessThan>( rhs ); + } + + template<typename RhsT> + ResultBuilder& operator > ( RhsT const& rhs ) { + return captureExpression<Internal::IsGreaterThan>( rhs ); + } + + template<typename RhsT> + ResultBuilder& operator <= ( RhsT const& rhs ) { + return captureExpression<Internal::IsLessThanOrEqualTo>( rhs ); + } + + template<typename RhsT> + ResultBuilder& operator >= ( RhsT const& rhs ) { + return captureExpression<Internal::IsGreaterThanOrEqualTo>( rhs ); + } + + ResultBuilder& operator == ( bool rhs ) { + return captureExpression<Internal::IsEqualTo>( rhs ); + } + + ResultBuilder& operator != ( bool rhs ) { + return captureExpression<Internal::IsNotEqualTo>( rhs ); + } + + void endExpression() { + bool value = m_lhs ? true : false; + m_rb + .setLhs( Catch::toString( value ) ) + .setResultType( value ) + .endExpression(); + } + + // Only simple binary expressions are allowed on the LHS. + // If more complex compositions are required then place the sub expression in parentheses + template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator + ( RhsT const& ); + template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator - ( RhsT const& ); + template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator / ( RhsT const& ); + template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator * ( RhsT const& ); + template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator && ( RhsT const& ); + template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator || ( RhsT const& ); + +private: + template<Internal::Operator Op, typename RhsT> + ResultBuilder& captureExpression( RhsT const& rhs ) { + return m_rb + .setResultType( Internal::compare<Op>( m_lhs, rhs ) ) + .setLhs( Catch::toString( m_lhs ) ) + .setRhs( Catch::toString( rhs ) ) + .setOp( Internal::OperatorTraits<Op>::getName() ); + } + +private: + ResultBuilder& m_rb; + T m_lhs; +}; + +} // end namespace Catch + +#endif // TWOBLUECUBES_CATCH_EXPRESSION_LHS_HPP_INCLUDED diff --git a/unittest/Catch/include/internal/catch_fatal_condition.hpp b/unittest/Catch/include/internal/catch_fatal_condition.hpp new file mode 100644 index 0000000..dd21d59 --- /dev/null +++ b/unittest/Catch/include/internal/catch_fatal_condition.hpp @@ -0,0 +1,85 @@ +/* + * Created by Phil on 21/08/2014 + * Copyright 2014 Two Blue Cubes Ltd. All rights reserved. + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + * + */ +#ifndef TWOBLUECUBES_CATCH_FATAL_CONDITION_H_INCLUDED +#define TWOBLUECUBES_CATCH_FATAL_CONDITION_H_INCLUDED + + +namespace Catch { + + // Report the error condition then exit the process + inline void fatal( std::string const& message, int exitCode ) { + IContext& context = Catch::getCurrentContext(); + IResultCapture* resultCapture = context.getResultCapture(); + resultCapture->handleFatalErrorCondition( message ); + + if( Catch::alwaysTrue() ) // avoids "no return" warnings + exit( exitCode ); + } + +} // namespace Catch + +#if defined ( CATCH_PLATFORM_WINDOWS ) ///////////////////////////////////////// + +namespace Catch { + + struct FatalConditionHandler { + void reset() {} + }; + +} // namespace Catch + +#else // Not Windows - assumed to be POSIX compatible ////////////////////////// + +#include <signal.h> + +namespace Catch { + + struct SignalDefs { int id; const char* name; }; + extern SignalDefs signalDefs[]; + SignalDefs signalDefs[] = { + { SIGINT, "SIGINT - Terminal interrupt signal" }, + { SIGILL, "SIGILL - Illegal instruction signal" }, + { SIGFPE, "SIGFPE - Floating point error signal" }, + { SIGSEGV, "SIGSEGV - Segmentation violation signal" }, + { SIGTERM, "SIGTERM - Termination request signal" }, + { SIGABRT, "SIGABRT - Abort (abnormal termination) signal" } + }; + + struct FatalConditionHandler { + + static void handleSignal( int sig ) { + for( std::size_t i = 0; i < sizeof(signalDefs)/sizeof(SignalDefs); ++i ) + if( sig == signalDefs[i].id ) + fatal( signalDefs[i].name, -sig ); + fatal( "<unknown signal>", -sig ); + } + + FatalConditionHandler() : m_isSet( true ) { + for( std::size_t i = 0; i < sizeof(signalDefs)/sizeof(SignalDefs); ++i ) + signal( signalDefs[i].id, handleSignal ); + } + ~FatalConditionHandler() { + reset(); + } + void reset() { + if( m_isSet ) { + for( std::size_t i = 0; i < sizeof(signalDefs)/sizeof(SignalDefs); ++i ) + signal( signalDefs[i].id, SIG_DFL ); + m_isSet = false; + } + } + + bool m_isSet; + }; + +} // namespace Catch + +#endif // not Windows + +#endif // TWOBLUECUBES_CATCH_FATAL_CONDITION_H_INCLUDED diff --git a/unittest/Catch/include/internal/catch_generators.hpp b/unittest/Catch/include/internal/catch_generators.hpp new file mode 100644 index 0000000..84eb22f --- /dev/null +++ b/unittest/Catch/include/internal/catch_generators.hpp @@ -0,0 +1,190 @@ +/* + * Created by Phil on 27/01/2011. + * Copyright 2011 Two Blue Cubes Ltd. All rights reserved. + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + */ +#ifndef TWOBLUECUBES_CATCH_GENERATORS_HPP_INCLUDED +#define TWOBLUECUBES_CATCH_GENERATORS_HPP_INCLUDED + +#include "catch_context.h" + +#include <iterator> +#include <vector> +#include <string> +#include <stdlib.h> + +namespace Catch { + +template<typename T> +struct IGenerator { + virtual ~IGenerator() {} + virtual T getValue( std::size_t index ) const = 0; + virtual std::size_t size () const = 0; +}; + +template<typename T> +class BetweenGenerator : public IGenerator<T> { +public: + BetweenGenerator( T from, T to ) : m_from( from ), m_to( to ){} + + virtual T getValue( std::size_t index ) const { + return m_from+static_cast<int>( index ); + } + + virtual std::size_t size() const { + return static_cast<std::size_t>( 1+m_to-m_from ); + } + +private: + + T m_from; + T m_to; +}; + +template<typename T> +class ValuesGenerator : public IGenerator<T> { +public: + ValuesGenerator(){} + + void add( T value ) { + m_values.push_back( value ); + } + + virtual T getValue( std::size_t index ) const { + return m_values[index]; + } + + virtual std::size_t size() const { + return m_values.size(); + } + +private: + std::vector<T> m_values; +}; + +template<typename T> +class CompositeGenerator { +public: + CompositeGenerator() : m_totalSize( 0 ) {} + + // *** Move semantics, similar to auto_ptr *** + CompositeGenerator( CompositeGenerator& other ) + : m_fileInfo( other.m_fileInfo ), + m_totalSize( 0 ) + { + move( other ); + } + + CompositeGenerator& setFileInfo( const char* fileInfo ) { + m_fileInfo = fileInfo; + return *this; + } + + ~CompositeGenerator() { + deleteAll( m_composed ); + } + + operator T () const { + size_t overallIndex = getCurrentContext().getGeneratorIndex( m_fileInfo, m_totalSize ); + + typename std::vector<const IGenerator<T>*>::const_iterator it = m_composed.begin(); + typename std::vector<const IGenerator<T>*>::const_iterator itEnd = m_composed.end(); + for( size_t index = 0; it != itEnd; ++it ) + { + const IGenerator<T>* generator = *it; + if( overallIndex >= index && overallIndex < index + generator->size() ) + { + return generator->getValue( overallIndex-index ); + } + index += generator->size(); + } + CATCH_INTERNAL_ERROR( "Indexed past end of generated range" ); + return T(); // Suppress spurious "not all control paths return a value" warning in Visual Studio - if you know how to fix this please do so + } + + void add( const IGenerator<T>* generator ) { + m_totalSize += generator->size(); + m_composed.push_back( generator ); + } + + CompositeGenerator& then( CompositeGenerator& other ) { + move( other ); + return *this; + } + + CompositeGenerator& then( T value ) { + ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>(); + valuesGen->add( value ); + add( valuesGen ); + return *this; + } + +private: + + void move( CompositeGenerator& other ) { + std::copy( other.m_composed.begin(), other.m_composed.end(), std::back_inserter( m_composed ) ); + m_totalSize += other.m_totalSize; + other.m_composed.clear(); + } + + std::vector<const IGenerator<T>*> m_composed; + std::string m_fileInfo; + size_t m_totalSize; +}; + +namespace Generators +{ + template<typename T> + CompositeGenerator<T> between( T from, T to ) { + CompositeGenerator<T> generators; + generators.add( new BetweenGenerator<T>( from, to ) ); + return generators; + } + + template<typename T> + CompositeGenerator<T> values( T val1, T val2 ) { + CompositeGenerator<T> generators; + ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>(); + valuesGen->add( val1 ); + valuesGen->add( val2 ); + generators.add( valuesGen ); + return generators; + } + + template<typename T> + CompositeGenerator<T> values( T val1, T val2, T val3 ){ + CompositeGenerator<T> generators; + ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>(); + valuesGen->add( val1 ); + valuesGen->add( val2 ); + valuesGen->add( val3 ); + generators.add( valuesGen ); + return generators; + } + + template<typename T> + CompositeGenerator<T> values( T val1, T val2, T val3, T val4 ) { + CompositeGenerator<T> generators; + ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>(); + valuesGen->add( val1 ); + valuesGen->add( val2 ); + valuesGen->add( val3 ); + valuesGen->add( val4 ); + generators.add( valuesGen ); + return generators; + } + +} // end namespace Generators + +using namespace Generators; + +} // end namespace Catch + +#define INTERNAL_CATCH_LINESTR2( line ) #line +#define INTERNAL_CATCH_LINESTR( line ) INTERNAL_CATCH_LINESTR2( line ) + +#define INTERNAL_CATCH_GENERATE( expr ) expr.setFileInfo( __FILE__ "(" INTERNAL_CATCH_LINESTR( __LINE__ ) ")" ) + +#endif // TWOBLUECUBES_CATCH_GENERATORS_HPP_INCLUDED diff --git a/unittest/Catch/include/internal/catch_generators_impl.hpp b/unittest/Catch/include/internal/catch_generators_impl.hpp new file mode 100644 index 0000000..fea699a --- /dev/null +++ b/unittest/Catch/include/internal/catch_generators_impl.hpp @@ -0,0 +1,86 @@ +/* + * Created by Phil on 28/01/2011. + * Copyright 2011 Two Blue Cubes Ltd. All rights reserved. + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + */ +#ifndef TWOBLUECUBES_CATCH_GENERATORS_IMPL_HPP_INCLUDED +#define TWOBLUECUBES_CATCH_GENERATORS_IMPL_HPP_INCLUDED + +#include "catch_interfaces_generators.h" + +#include "catch_common.h" + +#include <vector> +#include <string> +#include <map> + +namespace Catch { + + struct GeneratorInfo : IGeneratorInfo { + + GeneratorInfo( std::size_t size ) + : m_size( size ), + m_currentIndex( 0 ) + {} + + bool moveNext() { + if( ++m_currentIndex == m_size ) { + m_currentIndex = 0; + return false; + } + return true; + } + + std::size_t getCurrentIndex() const { + return m_currentIndex; + } + + std::size_t m_size; + std::size_t m_currentIndex; + }; + + /////////////////////////////////////////////////////////////////////////// + + class GeneratorsForTest : public IGeneratorsForTest { + + public: + ~GeneratorsForTest() { + deleteAll( m_generatorsInOrder ); + } + + IGeneratorInfo& getGeneratorInfo( std::string const& fileInfo, std::size_t size ) { + std::map<std::string, IGeneratorInfo*>::const_iterator it = m_generatorsByName.find( fileInfo ); + if( it == m_generatorsByName.end() ) { + IGeneratorInfo* info = new GeneratorInfo( size ); + m_generatorsByName.insert( std::make_pair( fileInfo, info ) ); + m_generatorsInOrder.push_back( info ); + return *info; + } + return *it->second; + } + + bool moveNext() { + std::vector<IGeneratorInfo*>::const_iterator it = m_generatorsInOrder.begin(); + std::vector<IGeneratorInfo*>::const_iterator itEnd = m_generatorsInOrder.end(); + for(; it != itEnd; ++it ) { + if( (*it)->moveNext() ) + return true; + } + return false; + } + + private: + std::map<std::string, IGeneratorInfo*> m_generatorsByName; + std::vector<IGeneratorInfo*> m_generatorsInOrder; + }; + + IGeneratorsForTest* createGeneratorsForTest() + { + return new GeneratorsForTest(); + } + +} // end namespace Catch + +#endif // TWOBLUECUBES_CATCH_GENERATORS_IMPL_HPP_INCLUDED diff --git a/unittest/Catch/include/internal/catch_impl.hpp b/unittest/Catch/include/internal/catch_impl.hpp new file mode 100644 index 0000000..53c8957 --- /dev/null +++ b/unittest/Catch/include/internal/catch_impl.hpp @@ -0,0 +1,113 @@ +/* + * Created by Phil on 5/8/2012. + * Copyright 2012 Two Blue Cubes Ltd. All rights reserved. + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + */ +#ifndef TWOBLUECUBES_CATCH_IMPL_HPP_INCLUDED +#define TWOBLUECUBES_CATCH_IMPL_HPP_INCLUDED + +// Collect all the implementation files together here +// These are the equivalent of what would usually be cpp files + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wweak-vtables" +#endif + +#include "../catch_session.hpp" +#include "catch_registry_hub.hpp" +#include "catch_notimplemented_exception.hpp" +#include "catch_context_impl.hpp" +#include "catch_console_colour_impl.hpp" +#include "catch_generators_impl.hpp" +#include "catch_assertionresult.hpp" +#include "catch_test_case_info.hpp" +#include "catch_test_spec.hpp" +#include "catch_version.hpp" +#include "catch_message.hpp" +#include "catch_legacy_reporter_adapter.hpp" +#include "catch_timer.hpp" +#include "catch_common.hpp" +#include "catch_section.hpp" +#include "catch_debugger.hpp" +#include "catch_tostring.hpp" +#include "catch_result_builder.hpp" +#include "catch_tag_alias_registry.hpp" +#include "catch_test_case_tracker.hpp" + +#include "../reporters/catch_reporter_multi.hpp" +#include "../reporters/catch_reporter_xml.hpp" +#include "../reporters/catch_reporter_junit.hpp" +#include "../reporters/catch_reporter_console.hpp" +#include "../reporters/catch_reporter_compact.hpp" + +namespace Catch { + // These are all here to avoid warnings about not having any out of line + // virtual methods + NonCopyable::~NonCopyable() {} + IShared::~IShared() {} + IStream::~IStream() CATCH_NOEXCEPT {} + FileStream::~FileStream() CATCH_NOEXCEPT {} + CoutStream::~CoutStream() CATCH_NOEXCEPT {} + DebugOutStream::~DebugOutStream() CATCH_NOEXCEPT {} + StreamBufBase::~StreamBufBase() CATCH_NOEXCEPT {} + IContext::~IContext() {} + IResultCapture::~IResultCapture() {} + ITestCase::~ITestCase() {} + ITestCaseRegistry::~ITestCaseRegistry() {} + IRegistryHub::~IRegistryHub() {} + IMutableRegistryHub::~IMutableRegistryHub() {} + IExceptionTranslator::~IExceptionTranslator() {} + IExceptionTranslatorRegistry::~IExceptionTranslatorRegistry() {} + IReporter::~IReporter() {} + IReporterFactory::~IReporterFactory() {} + IReporterRegistry::~IReporterRegistry() {} + IStreamingReporter::~IStreamingReporter() {} + AssertionStats::~AssertionStats() {} + SectionStats::~SectionStats() {} + TestCaseStats::~TestCaseStats() {} + TestGroupStats::~TestGroupStats() {} + TestRunStats::~TestRunStats() {} + CumulativeReporterBase::SectionNode::~SectionNode() {} + CumulativeReporterBase::~CumulativeReporterBase() {} + + StreamingReporterBase::~StreamingReporterBase() {} + ConsoleReporter::~ConsoleReporter() {} + CompactReporter::~CompactReporter() {} + IRunner::~IRunner() {} + IMutableContext::~IMutableContext() {} + IConfig::~IConfig() {} + XmlReporter::~XmlReporter() {} + JunitReporter::~JunitReporter() {} + TestRegistry::~TestRegistry() {} + FreeFunctionTestCase::~FreeFunctionTestCase() {} + IGeneratorInfo::~IGeneratorInfo() {} + IGeneratorsForTest::~IGeneratorsForTest() {} + WildcardPattern::~WildcardPattern() {} + TestSpec::Pattern::~Pattern() {} + TestSpec::NamePattern::~NamePattern() {} + TestSpec::TagPattern::~TagPattern() {} + TestSpec::ExcludedPattern::~ExcludedPattern() {} + + Matchers::Impl::StdString::Equals::~Equals() {} + Matchers::Impl::StdString::Contains::~Contains() {} + Matchers::Impl::StdString::StartsWith::~StartsWith() {} + Matchers::Impl::StdString::EndsWith::~EndsWith() {} + + void Config::dummy() {} + + namespace TestCaseTracking { + ITracker::~ITracker() {} + TrackerBase::~TrackerBase() {} + SectionTracker::~SectionTracker() {} + IndexTracker::~IndexTracker() {} + } +} + +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + +#endif // TWOBLUECUBES_CATCH_IMPL_HPP_INCLUDED diff --git a/unittest/Catch/include/internal/catch_interfaces_capture.h b/unittest/Catch/include/internal/catch_interfaces_capture.h new file mode 100644 index 0000000..b7b6e32 --- /dev/null +++ b/unittest/Catch/include/internal/catch_interfaces_capture.h @@ -0,0 +1,47 @@ +/* + * Created by Phil on 07/01/2011. + * Copyright 2011 Two Blue Cubes Ltd. All rights reserved. + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + */ +#ifndef TWOBLUECUBES_CATCH_INTERFACES_CAPTURE_H_INCLUDED +#define TWOBLUECUBES_CATCH_INTERFACES_CAPTURE_H_INCLUDED + +#include <string> +#include "catch_result_type.h" +#include "catch_common.h" + +namespace Catch { + + class TestCase; + class AssertionResult; + struct AssertionInfo; + struct SectionInfo; + struct SectionEndInfo; + struct MessageInfo; + class ScopedMessageBuilder; + struct Counts; + + struct IResultCapture { + + virtual ~IResultCapture(); + + virtual void assertionEnded( AssertionResult const& result ) = 0; + virtual bool sectionStarted( SectionInfo const& sectionInfo, + Counts& assertions ) = 0; + virtual void sectionEnded( SectionEndInfo const& endInfo ) = 0; + virtual void sectionEndedEarly( SectionEndInfo const& endInfo ) = 0; + virtual void pushScopedMessage( MessageInfo const& message ) = 0; + virtual void popScopedMessage( MessageInfo const& message ) = 0; + + virtual std::string getCurrentTestName() const = 0; + virtual const AssertionResult* getLastResult() const = 0; + + virtual void handleFatalErrorCondition( std::string const& message ) = 0; + }; + + IResultCapture& getResultCapture(); +} + +#endif // TWOBLUECUBES_CATCH_INTERFACES_CAPTURE_H_INCLUDED diff --git a/unittest/Catch/include/internal/catch_interfaces_config.h b/unittest/Catch/include/internal/catch_interfaces_config.h new file mode 100644 index 0000000..17914b4 --- /dev/null +++ b/unittest/Catch/include/internal/catch_interfaces_config.h @@ -0,0 +1,68 @@ +/* + * Created by Phil on 05/06/2012. + * Copyright 2012 Two Blue Cubes Ltd. All rights reserved. + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + */ +#ifndef TWOBLUECUBES_CATCH_INTERFACES_CONFIG_H_INCLUDED +#define TWOBLUECUBES_CATCH_INTERFACES_CONFIG_H_INCLUDED + +#include <iostream> +#include <string> +#include <vector> + +#include "catch_ptr.hpp" + +namespace Catch { + + struct Verbosity { enum Level { + NoOutput = 0, + Quiet, + Normal + }; }; + + struct WarnAbout { enum What { + Nothing = 0x00, + NoAssertions = 0x01 + }; }; + + struct ShowDurations { enum OrNot { + DefaultForReporter, + Always, + Never + }; }; + struct RunTests { enum InWhatOrder { + InDeclarationOrder, + InLexicographicalOrder, + InRandomOrder + }; }; + struct UseColour { enum YesOrNo { + Auto, + Yes, + No + }; }; + + class TestSpec; + + struct IConfig : IShared { + + virtual ~IConfig(); + + virtual bool allowThrows() const = 0; + virtual std::ostream& stream() const = 0; + virtual std::string name() const = 0; + virtual bool includeSuccessfulResults() const = 0; + virtual bool shouldDebugBreak() const = 0; + virtual bool warnAboutMissingAssertions() const = 0; + virtual int abortAfter() const = 0; + virtual bool showInvisibles() const = 0; + virtual ShowDurations::OrNot showDurations() const = 0; + virtual TestSpec const& testSpec() const = 0; + virtual RunTests::InWhatOrder runOrder() const = 0; + virtual unsigned int rngSeed() const = 0; + virtual UseColour::YesOrNo useColour() const = 0; + }; +} + +#endif // TWOBLUECUBES_CATCH_INTERFACES_CONFIG_H_INCLUDED diff --git a/unittest/Catch/include/internal/catch_interfaces_exception.h b/unittest/Catch/include/internal/catch_interfaces_exception.h new file mode 100644 index 0000000..186995a --- /dev/null +++ b/unittest/Catch/include/internal/catch_interfaces_exception.h @@ -0,0 +1,74 @@ +/* + * Created by Phil on 20/04/2011. + * Copyright 2011 Two Blue Cubes Ltd. All rights reserved. + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + */ +#ifndef TWOBLUECUBES_CATCH_INTERFACES_EXCEPTION_H_INCLUDED +#define TWOBLUECUBES_CATCH_INTERFACES_EXCEPTION_H_INCLUDED + +#include <string> +#include <vector> + +#include "catch_interfaces_registry_hub.h" + +namespace Catch { + + typedef std::string(*exceptionTranslateFunction)(); + + struct IExceptionTranslator; + typedef std::vector<const IExceptionTranslator*> ExceptionTranslators; + + struct IExceptionTranslator { + virtual ~IExceptionTranslator(); + virtual std::string translate( ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd ) const = 0; + }; + + struct IExceptionTranslatorRegistry { + virtual ~IExceptionTranslatorRegistry(); + + virtual std::string translateActiveException() const = 0; + }; + + class ExceptionTranslatorRegistrar { + template<typename T> + class ExceptionTranslator : public IExceptionTranslator { + public: + + ExceptionTranslator( std::string(*translateFunction)( T& ) ) + : m_translateFunction( translateFunction ) + {} + + virtual std::string translate( ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd ) const CATCH_OVERRIDE { + try { + if( it == itEnd ) + throw; + else + return (*it)->translate( it+1, itEnd ); + } + catch( T& ex ) { + return m_translateFunction( ex ); + } + } + + protected: + std::string(*m_translateFunction)( T& ); + }; + + public: + template<typename T> + ExceptionTranslatorRegistrar( std::string(*translateFunction)( T& ) ) { + getMutableRegistryHub().registerTranslator + ( new ExceptionTranslator<T>( translateFunction ) ); + } + }; +} + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) \ + static std::string INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator )( signature ); \ + namespace{ Catch::ExceptionTranslatorRegistrar INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionRegistrar )( &INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator ) ); }\ + static std::string INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator )( signature ) + +#endif // TWOBLUECUBES_CATCH_INTERFACES_EXCEPTION_H_INCLUDED diff --git a/unittest/Catch/include/internal/catch_interfaces_generators.h b/unittest/Catch/include/internal/catch_interfaces_generators.h new file mode 100644 index 0000000..d163d5a --- /dev/null +++ b/unittest/Catch/include/internal/catch_interfaces_generators.h @@ -0,0 +1,32 @@ +/* + * Created by Phil on 7/8/2012. + * Copyright 2011 Two Blue Cubes Ltd. All rights reserved. + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + */ +#ifndef TWOBLUECUBES_CATCH_INTERFACES_GENERATORS_H_INCLUDED +#define TWOBLUECUBES_CATCH_INTERFACES_GENERATORS_H_INCLUDED + +#include <string> + +namespace Catch { + + struct IGeneratorInfo { + virtual ~IGeneratorInfo(); + virtual bool moveNext() = 0; + virtual std::size_t getCurrentIndex() const = 0; + }; + + struct IGeneratorsForTest { + virtual ~IGeneratorsForTest(); + + virtual IGeneratorInfo& getGeneratorInfo( std::string const& fileInfo, std::size_t size ) = 0; + virtual bool moveNext() = 0; + }; + + IGeneratorsForTest* createGeneratorsForTest(); + +} // end namespace Catch + +#endif // TWOBLUECUBES_CATCH_INTERFACES_GENERATORS_H_INCLUDED diff --git a/unittest/Catch/include/internal/catch_interfaces_registry_hub.h b/unittest/Catch/include/internal/catch_interfaces_registry_hub.h new file mode 100644 index 0000000..ec06ca2 --- /dev/null +++ b/unittest/Catch/include/internal/catch_interfaces_registry_hub.h @@ -0,0 +1,47 @@ +/* + * Created by Phil on 5/8/2012. + * Copyright 2012 Two Blue Cubes Ltd. All rights reserved. + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + */ +#ifndef TWOBLUECUBES_CATCH_INTERFACES_REGISTRY_HUB_H_INCLUDED +#define TWOBLUECUBES_CATCH_INTERFACES_REGISTRY_HUB_H_INCLUDED + +#include "catch_ptr.hpp" + +#include <string> + +namespace Catch { + + class TestCase; + struct ITestCaseRegistry; + struct IExceptionTranslatorRegistry; + struct IExceptionTranslator; + struct IReporterRegistry; + struct IReporterFactory; + + struct IRegistryHub { + virtual ~IRegistryHub(); + + virtual IReporterRegistry const& getReporterRegistry() const = 0; + virtual ITestCaseRegistry const& getTestCaseRegistry() const = 0; + virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() = 0; + }; + + struct IMutableRegistryHub { + virtual ~IMutableRegistryHub(); + virtual void registerReporter( std::string const& name, Ptr<IReporterFactory> const& factory ) = 0; + virtual void registerListener( Ptr<IReporterFactory> const& factory ) = 0; + virtual void registerTest( TestCase const& testInfo ) = 0; + virtual void registerTranslator( const IExceptionTranslator* translator ) = 0; + }; + + IRegistryHub& getRegistryHub(); + IMutableRegistryHub& getMutableRegistryHub(); + void cleanUp(); + std::string translateActiveException(); + +} + +#endif // TWOBLUECUBES_CATCH_INTERFACES_REGISTRY_HUB_H_INCLUDED diff --git a/unittest/Catch/include/internal/catch_interfaces_reporter.h b/unittest/Catch/include/internal/catch_interfaces_reporter.h new file mode 100644 index 0000000..d1c6e70 --- /dev/null +++ b/unittest/Catch/include/internal/catch_interfaces_reporter.h @@ -0,0 +1,273 @@ +/* + * Created by Phil on 31/12/2010. + * Copyright 2010 Two Blue Cubes Ltd. All rights reserved. + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + */ +#ifndef TWOBLUECUBES_CATCH_INTERFACES_REPORTER_H_INCLUDED +#define TWOBLUECUBES_CATCH_INTERFACES_REPORTER_H_INCLUDED + +#include "catch_section_info.h" +#include "catch_common.h" +#include "catch_totals.hpp" +#include "catch_ptr.hpp" +#include "catch_config.hpp" +#include "catch_test_case_info.h" +#include "catch_assertionresult.h" +#include "catch_message.h" +#include "catch_option.hpp" + +#include <string> +#include <ostream> +#include <map> +#include <assert.h> + +namespace Catch +{ + struct ReporterConfig { + explicit ReporterConfig( Ptr<IConfig const> const& _fullConfig ) + : m_stream( &_fullConfig->stream() ), m_fullConfig( _fullConfig ) {} + + ReporterConfig( Ptr<IConfig const> const& _fullConfig, std::ostream& _stream ) + : m_stream( &_stream ), m_fullConfig( _fullConfig ) {} + + std::ostream& stream() const { return *m_stream; } + Ptr<IConfig const> fullConfig() const { return m_fullConfig; } + + private: + std::ostream* m_stream; + Ptr<IConfig const> m_fullConfig; + }; + + struct ReporterPreferences { + ReporterPreferences() + : shouldRedirectStdOut( false ) + {} + + bool shouldRedirectStdOut; + }; + + template<typename T> + struct LazyStat : Option<T> { + LazyStat() : used( false ) {} + LazyStat& operator=( T const& _value ) { + Option<T>::operator=( _value ); + used = false; + return *this; + } + void reset() { + Option<T>::reset(); + used = false; + } + bool used; + }; + + struct TestRunInfo { + TestRunInfo( std::string const& _name ) : name( _name ) {} + std::string name; + }; + struct GroupInfo { + GroupInfo( std::string const& _name, + std::size_t _groupIndex, + std::size_t _groupsCount ) + : name( _name ), + groupIndex( _groupIndex ), + groupsCounts( _groupsCount ) + {} + + std::string name; + std::size_t groupIndex; + std::size_t groupsCounts; + }; + + struct AssertionStats { + AssertionStats( AssertionResult const& _assertionResult, + std::vector<MessageInfo> const& _infoMessages, + Totals const& _totals ) + : assertionResult( _assertionResult ), + infoMessages( _infoMessages ), + totals( _totals ) + { + if( assertionResult.hasMessage() ) { + // Copy message into messages list. + // !TBD This should have been done earlier, somewhere + MessageBuilder builder( assertionResult.getTestMacroName(), assertionResult.getSourceInfo(), assertionResult.getResultType() ); + builder << assertionResult.getMessage(); + builder.m_info.message = builder.m_stream.str(); + + infoMessages.push_back( builder.m_info ); + } + } + virtual ~AssertionStats(); + +# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS + AssertionStats( AssertionStats const& ) = default; + AssertionStats( AssertionStats && ) = default; + AssertionStats& operator = ( AssertionStats const& ) = default; + AssertionStats& operator = ( AssertionStats && ) = default; +# endif + + AssertionResult assertionResult; + std::vector<MessageInfo> infoMessages; + Totals totals; + }; + + struct SectionStats { + SectionStats( SectionInfo const& _sectionInfo, + Counts const& _assertions, + double _durationInSeconds, + bool _missingAssertions ) + : sectionInfo( _sectionInfo ), + assertions( _assertions ), + durationInSeconds( _durationInSeconds ), + missingAssertions( _missingAssertions ) + {} + virtual ~SectionStats(); +# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS + SectionStats( SectionStats const& ) = default; + SectionStats( SectionStats && ) = default; + SectionStats& operator = ( SectionStats const& ) = default; + SectionStats& operator = ( SectionStats && ) = default; +# endif + + SectionInfo sectionInfo; + Counts assertions; + double durationInSeconds; + bool missingAssertions; + }; + + struct TestCaseStats { + TestCaseStats( TestCaseInfo const& _testInfo, + Totals const& _totals, + std::string const& _stdOut, + std::string const& _stdErr, + bool _aborting ) + : testInfo( _testInfo ), + totals( _totals ), + stdOut( _stdOut ), + stdErr( _stdErr ), + aborting( _aborting ) + {} + virtual ~TestCaseStats(); + +# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS + TestCaseStats( TestCaseStats const& ) = default; + TestCaseStats( TestCaseStats && ) = default; + TestCaseStats& operator = ( TestCaseStats const& ) = default; + TestCaseStats& operator = ( TestCaseStats && ) = default; +# endif + + TestCaseInfo testInfo; + Totals totals; + std::string stdOut; + std::string stdErr; + bool aborting; + }; + + struct TestGroupStats { + TestGroupStats( GroupInfo const& _groupInfo, + Totals const& _totals, + bool _aborting ) + : groupInfo( _groupInfo ), + totals( _totals ), + aborting( _aborting ) + {} + TestGroupStats( GroupInfo const& _groupInfo ) + : groupInfo( _groupInfo ), + aborting( false ) + {} + virtual ~TestGroupStats(); + +# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS + TestGroupStats( TestGroupStats const& ) = default; + TestGroupStats( TestGroupStats && ) = default; + TestGroupStats& operator = ( TestGroupStats const& ) = default; + TestGroupStats& operator = ( TestGroupStats && ) = default; +# endif + + GroupInfo groupInfo; + Totals totals; + bool aborting; + }; + + struct TestRunStats { + TestRunStats( TestRunInfo const& _runInfo, + Totals const& _totals, + bool _aborting ) + : runInfo( _runInfo ), + totals( _totals ), + aborting( _aborting ) + {} + virtual ~TestRunStats(); + +# ifndef CATCH_CONFIG_CPP11_GENERATED_METHODS + TestRunStats( TestRunStats const& _other ) + : runInfo( _other.runInfo ), + totals( _other.totals ), + aborting( _other.aborting ) + {} +# else + TestRunStats( TestRunStats const& ) = default; + TestRunStats( TestRunStats && ) = default; + TestRunStats& operator = ( TestRunStats const& ) = default; + TestRunStats& operator = ( TestRunStats && ) = default; +# endif + + TestRunInfo runInfo; + Totals totals; + bool aborting; + }; + + + struct IStreamingReporter : IShared { + virtual ~IStreamingReporter(); + + // Implementing class must also provide the following static method: + // static std::string getDescription(); + + virtual ReporterPreferences getPreferences() const = 0; + + virtual void noMatchingTestCases( std::string const& spec ) = 0; + + virtual void testRunStarting( TestRunInfo const& testRunInfo ) = 0; + virtual void testGroupStarting( GroupInfo const& groupInfo ) = 0; + + virtual void testCaseStarting( TestCaseInfo const& testInfo ) = 0; + virtual void sectionStarting( SectionInfo const& sectionInfo ) = 0; + + virtual void assertionStarting( AssertionInfo const& assertionInfo ) = 0; + + // The return value indicates if the messages buffer should be cleared: + virtual bool assertionEnded( AssertionStats const& assertionStats ) = 0; + + virtual void sectionEnded( SectionStats const& sectionStats ) = 0; + virtual void testCaseEnded( TestCaseStats const& testCaseStats ) = 0; + virtual void testGroupEnded( TestGroupStats const& testGroupStats ) = 0; + virtual void testRunEnded( TestRunStats const& testRunStats ) = 0; + + virtual void skipTest( TestCaseInfo const& testInfo ) = 0; + }; + + + struct IReporterFactory : IShared { + virtual ~IReporterFactory(); + virtual IStreamingReporter* create( ReporterConfig const& config ) const = 0; + virtual std::string getDescription() const = 0; + }; + + struct IReporterRegistry { + typedef std::map<std::string, Ptr<IReporterFactory> > FactoryMap; + typedef std::vector<Ptr<IReporterFactory> > Listeners; + + virtual ~IReporterRegistry(); + virtual IStreamingReporter* create( std::string const& name, Ptr<IConfig const> const& config ) const = 0; + virtual FactoryMap const& getFactories() const = 0; + virtual Listeners const& getListeners() const = 0; + }; + + Ptr<IStreamingReporter> addReporter( Ptr<IStreamingReporter> const& existingReporter, Ptr<IStreamingReporter> const& additionalReporter ); + +} + +#endif // TWOBLUECUBES_CATCH_INTERFACES_REPORTER_H_INCLUDED diff --git a/unittest/Catch/include/internal/catch_interfaces_runner.h b/unittest/Catch/include/internal/catch_interfaces_runner.h new file mode 100644 index 0000000..25decfb --- /dev/null +++ b/unittest/Catch/include/internal/catch_interfaces_runner.h @@ -0,0 +1,20 @@ +/* + * Created by Phil on 07/01/2011. + * Copyright 2011 Two Blue Cubes Ltd. All rights reserved. + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + */ +#ifndef TWOBLUECUBES_CATCH_INTERFACES_RUNNER_H_INCLUDED +#define TWOBLUECUBES_CATCH_INTERFACES_RUNNER_H_INCLUDED + +namespace Catch { + class TestCase; + + struct IRunner { + virtual ~IRunner(); + virtual bool aborting() const = 0; + }; +} + +#endif // TWOBLUECUBES_CATCH_INTERFACES_RUNNER_H_INCLUDED diff --git a/unittest/Catch/include/internal/catch_interfaces_tag_alias_registry.h b/unittest/Catch/include/internal/catch_interfaces_tag_alias_registry.h new file mode 100644 index 0000000..cd6ac51 --- /dev/null +++ b/unittest/Catch/include/internal/catch_interfaces_tag_alias_registry.h @@ -0,0 +1,26 @@ +/* + * Created by Phil on 27/6/2014. + * Copyright 2014 Two Blue Cubes Ltd. All rights reserved. + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + */ +#ifndef TWOBLUECUBES_CATCH_INTERFACES_TAG_ALIAS_REGISTRY_H_INCLUDED +#define TWOBLUECUBES_CATCH_INTERFACES_TAG_ALIAS_REGISTRY_H_INCLUDED + +#include "catch_tag_alias.h" +#include "catch_option.hpp" + +namespace Catch { + + struct ITagAliasRegistry { + virtual ~ITagAliasRegistry(); + virtual Option<TagAlias> find( std::string const& alias ) const = 0; + virtual std::string expandAliases( std::string const& unexpandedTestSpec ) const = 0; + + static ITagAliasRegistry const& get(); + }; + +} // end namespace Catch + +#endif // TWOBLUECUBES_CATCH_INTERFACES_TAG_ALIAS_REGISTRY_H_INCLUDED diff --git a/unittest/Catch/include/internal/catch_interfaces_testcase.h b/unittest/Catch/include/internal/catch_interfaces_testcase.h new file mode 100644 index 0000000..a1052b7 --- /dev/null +++ b/unittest/Catch/include/internal/catch_interfaces_testcase.h @@ -0,0 +1,40 @@ +/* + * Created by Phil on 07/01/2011. + * Copyright 2011 Two Blue Cubes Ltd. All rights reserved. + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + */ +#ifndef TWOBLUECUBES_CATCH_INTERFACES_TESTCASE_H_INCLUDED +#define TWOBLUECUBES_CATCH_INTERFACES_TESTCASE_H_INCLUDED + +#include "catch_ptr.hpp" + +#include <vector> + +namespace Catch { + + class TestSpec; + + struct ITestCase : IShared { + virtual void invoke () const = 0; + protected: + virtual ~ITestCase(); + }; + + class TestCase; + struct IConfig; + + struct ITestCaseRegistry { + virtual ~ITestCaseRegistry(); + virtual std::vector<TestCase> const& getAllTests() const = 0; + virtual std::vector<TestCase> const& getAllTestsSorted( IConfig const& config ) const = 0; + }; + + bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config ); + std::vector<TestCase> filterTests( std::vector<TestCase> const& testCases, TestSpec const& testSpec, IConfig const& config ); + std::vector<TestCase> const& getAllTestCasesSorted( IConfig const& config ); + +} + +#endif // TWOBLUECUBES_CATCH_INTERFACES_TESTCASE_H_INCLUDED diff --git a/unittest/Catch/include/internal/catch_legacy_reporter_adapter.h b/unittest/Catch/include/internal/catch_legacy_reporter_adapter.h new file mode 100644 index 0000000..72c43d7 --- /dev/null +++ b/unittest/Catch/include/internal/catch_legacy_reporter_adapter.h @@ -0,0 +1,60 @@ +/* + * Created by Phil on 6th April 2013. + * Copyright 2013 Two Blue Cubes Ltd. All rights reserved. + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + */ +#ifndef TWOBLUECUBES_CATCH_LEGACY_REPORTER_ADAPTER_H_INCLUDED +#define TWOBLUECUBES_CATCH_LEGACY_REPORTER_ADAPTER_H_INCLUDED + +#include "catch_interfaces_reporter.h" + +namespace Catch +{ + // Deprecated + struct IReporter : IShared { + virtual ~IReporter(); + + virtual bool shouldRedirectStdout() const = 0; + + virtual void StartTesting() = 0; + virtual void EndTesting( Totals const& totals ) = 0; + virtual void StartGroup( std::string const& groupName ) = 0; + virtual void EndGroup( std::string const& groupName, Totals const& totals ) = 0; + virtual void StartTestCase( TestCaseInfo const& testInfo ) = 0; + virtual void EndTestCase( TestCaseInfo const& testInfo, Totals const& totals, std::string const& stdOut, std::string const& stdErr ) = 0; + virtual void StartSection( std::string const& sectionName, std::string const& description ) = 0; + virtual void EndSection( std::string const& sectionName, Counts const& assertions ) = 0; + virtual void NoAssertionsInSection( std::string const& sectionName ) = 0; + virtual void NoAssertionsInTestCase( std::string const& testName ) = 0; + virtual void Aborted() = 0; + virtual void Result( AssertionResult const& result ) = 0; + }; + + class LegacyReporterAdapter : public SharedImpl<IStreamingReporter> + { + public: + LegacyReporterAdapter( Ptr<IReporter> const& legacyReporter ); + virtual ~LegacyReporterAdapter(); + + virtual ReporterPreferences getPreferences() const; + virtual void noMatchingTestCases( std::string const& ); + virtual void testRunStarting( TestRunInfo const& ); + virtual void testGroupStarting( GroupInfo const& groupInfo ); + virtual void testCaseStarting( TestCaseInfo const& testInfo ); + virtual void sectionStarting( SectionInfo const& sectionInfo ); + virtual void assertionStarting( AssertionInfo const& ); + virtual bool assertionEnded( AssertionStats const& assertionStats ); + virtual void sectionEnded( SectionStats const& sectionStats ); + virtual void testCaseEnded( TestCaseStats const& testCaseStats ); + virtual void testGroupEnded( TestGroupStats const& testGroupStats ); + virtual void testRunEnded( TestRunStats const& testRunStats ); + virtual void skipTest( TestCaseInfo const& ); + + private: + Ptr<IReporter> m_legacyReporter; + }; +} + +#endif // TWOBLUECUBES_CATCH_LEGACY_REPORTER_ADAPTER_H_INCLUDED diff --git a/unittest/Catch/include/internal/catch_legacy_reporter_adapter.hpp b/unittest/Catch/include/internal/catch_legacy_reporter_adapter.hpp new file mode 100644 index 0000000..6034581 --- /dev/null +++ b/unittest/Catch/include/internal/catch_legacy_reporter_adapter.hpp @@ -0,0 +1,84 @@ +/* + * Created by Phil on 6th April 2013. + * Copyright 2013 Two Blue Cubes Ltd. All rights reserved. + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + */ +#ifndef TWOBLUECUBES_CATCH_LEGACY_REPORTER_ADAPTER_HPP_INCLUDED +#define TWOBLUECUBES_CATCH_LEGACY_REPORTER_ADAPTER_HPP_INCLUDED + +#include "catch_legacy_reporter_adapter.h" + +namespace Catch +{ + LegacyReporterAdapter::LegacyReporterAdapter( Ptr<IReporter> const& legacyReporter ) + : m_legacyReporter( legacyReporter ) + {} + LegacyReporterAdapter::~LegacyReporterAdapter() {} + + ReporterPreferences LegacyReporterAdapter::getPreferences() const { + ReporterPreferences prefs; + prefs.shouldRedirectStdOut = m_legacyReporter->shouldRedirectStdout(); + return prefs; + } + + void LegacyReporterAdapter::noMatchingTestCases( std::string const& ) {} + void LegacyReporterAdapter::testRunStarting( TestRunInfo const& ) { + m_legacyReporter->StartTesting(); + } + void LegacyReporterAdapter::testGroupStarting( GroupInfo const& groupInfo ) { + m_legacyReporter->StartGroup( groupInfo.name ); + } + void LegacyReporterAdapter::testCaseStarting( TestCaseInfo const& testInfo ) { + m_legacyReporter->StartTestCase( testInfo ); + } + void LegacyReporterAdapter::sectionStarting( SectionInfo const& sectionInfo ) { + m_legacyReporter->StartSection( sectionInfo.name, sectionInfo.description ); + } + void LegacyReporterAdapter::assertionStarting( AssertionInfo const& ) { + // Not on legacy interface + } + + bool LegacyReporterAdapter::assertionEnded( AssertionStats const& assertionStats ) { + if( assertionStats.assertionResult.getResultType() != ResultWas::Ok ) { + for( std::vector<MessageInfo>::const_iterator it = assertionStats.infoMessages.begin(), itEnd = assertionStats.infoMessages.end(); + it != itEnd; + ++it ) { + if( it->type == ResultWas::Info ) { + ResultBuilder rb( it->macroName.c_str(), it->lineInfo, "", ResultDisposition::Normal ); + rb << it->message; + rb.setResultType( ResultWas::Info ); + AssertionResult result = rb.build(); + m_legacyReporter->Result( result ); + } + } + } + m_legacyReporter->Result( assertionStats.assertionResult ); + return true; + } + void LegacyReporterAdapter::sectionEnded( SectionStats const& sectionStats ) { + if( sectionStats.missingAssertions ) + m_legacyReporter->NoAssertionsInSection( sectionStats.sectionInfo.name ); + m_legacyReporter->EndSection( sectionStats.sectionInfo.name, sectionStats.assertions ); + } + void LegacyReporterAdapter::testCaseEnded( TestCaseStats const& testCaseStats ) { + m_legacyReporter->EndTestCase + ( testCaseStats.testInfo, + testCaseStats.totals, + testCaseStats.stdOut, + testCaseStats.stdErr ); + } + void LegacyReporterAdapter::testGroupEnded( TestGroupStats const& testGroupStats ) { + if( testGroupStats.aborting ) + m_legacyReporter->Aborted(); + m_legacyReporter->EndGroup( testGroupStats.groupInfo.name, testGroupStats.totals ); + } + void LegacyReporterAdapter::testRunEnded( TestRunStats const& testRunStats ) { + m_legacyReporter->EndTesting( testRunStats.totals ); + } + void LegacyReporterAdapter::skipTest( TestCaseInfo const& ) { + } +} + +#endif // TWOBLUECUBES_CATCH_LEGACY_REPORTER_ADAPTER_H_INCLUDED diff --git a/unittest/Catch/include/internal/catch_list.hpp b/unittest/Catch/include/internal/catch_list.hpp new file mode 100644 index 0000000..4c87ccf --- /dev/null +++ b/unittest/Catch/include/internal/catch_list.hpp @@ -0,0 +1,176 @@ +/* + * Created by Phil on 5/11/2010. + * Copyright 2010 Two Blue Cubes Ltd. All rights reserved. + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + */ +#ifndef TWOBLUECUBES_CATCH_LIST_HPP_INCLUDED +#define TWOBLUECUBES_CATCH_LIST_HPP_INCLUDED + +#include "catch_commandline.hpp" +#include "catch_text.h" +#include "catch_console_colour.hpp" +#include "catch_interfaces_reporter.h" +#include "catch_test_spec_parser.hpp" + +#include <limits> +#include <algorithm> + +namespace Catch { + + inline std::size_t listTests( Config const& config ) { + + TestSpec testSpec = config.testSpec(); + if( config.testSpec().hasFilters() ) + Catch::cout() << "Matching test cases:\n"; + else { + Catch::cout() << "All available test cases:\n"; + testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "*" ).testSpec(); + } + + std::size_t matchedTests = 0; + TextAttributes nameAttr, tagsAttr; + nameAttr.setInitialIndent( 2 ).setIndent( 4 ); + tagsAttr.setIndent( 6 ); + + std::vector<TestCase> matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config ); + for( std::vector<TestCase>::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end(); + it != itEnd; + ++it ) { + matchedTests++; + TestCaseInfo const& testCaseInfo = it->getTestCaseInfo(); + Colour::Code colour = testCaseInfo.isHidden() + ? Colour::SecondaryText + : Colour::None; + Colour colourGuard( colour ); + + Catch::cout() << Text( testCaseInfo.name, nameAttr ) << std::endl; + if( !testCaseInfo.tags.empty() ) + Catch::cout() << Text( testCaseInfo.tagsAsString, tagsAttr ) << std::endl; + } + + if( !config.testSpec().hasFilters() ) + Catch::cout() << pluralise( matchedTests, "test case" ) << "\n" << std::endl; + else + Catch::cout() << pluralise( matchedTests, "matching test case" ) << "\n" << std::endl; + return matchedTests; + } + + inline std::size_t listTestsNamesOnly( Config const& config ) { + TestSpec testSpec = config.testSpec(); + if( !config.testSpec().hasFilters() ) + testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "*" ).testSpec(); + std::size_t matchedTests = 0; + std::vector<TestCase> matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config ); + for( std::vector<TestCase>::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end(); + it != itEnd; + ++it ) { + matchedTests++; + TestCaseInfo const& testCaseInfo = it->getTestCaseInfo(); + Catch::cout() << testCaseInfo.name << std::endl; + } + return matchedTests; + } + + struct TagInfo { + TagInfo() : count ( 0 ) {} + void add( std::string const& spelling ) { + ++count; + spellings.insert( spelling ); + } + std::string all() const { + std::string out; + for( std::set<std::string>::const_iterator it = spellings.begin(), itEnd = spellings.end(); + it != itEnd; + ++it ) + out += "[" + *it + "]"; + return out; + } + std::set<std::string> spellings; + std::size_t count; + }; + + inline std::size_t listTags( Config const& config ) { + TestSpec testSpec = config.testSpec(); + if( config.testSpec().hasFilters() ) + Catch::cout() << "Tags for matching test cases:\n"; + else { + Catch::cout() << "All available tags:\n"; + testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "*" ).testSpec(); + } + + std::map<std::string, TagInfo> tagCounts; + + std::vector<TestCase> matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config ); + for( std::vector<TestCase>::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end(); + it != itEnd; + ++it ) { + for( std::set<std::string>::const_iterator tagIt = it->getTestCaseInfo().tags.begin(), + tagItEnd = it->getTestCaseInfo().tags.end(); + tagIt != tagItEnd; + ++tagIt ) { + std::string tagName = *tagIt; + std::string lcaseTagName = toLower( tagName ); + std::map<std::string, TagInfo>::iterator countIt = tagCounts.find( lcaseTagName ); + if( countIt == tagCounts.end() ) + countIt = tagCounts.insert( std::make_pair( lcaseTagName, TagInfo() ) ).first; + countIt->second.add( tagName ); + } + } + + for( std::map<std::string, TagInfo>::const_iterator countIt = tagCounts.begin(), + countItEnd = tagCounts.end(); + countIt != countItEnd; + ++countIt ) { + std::ostringstream oss; + oss << " " << std::setw(2) << countIt->second.count << " "; + Text wrapper( countIt->second.all(), TextAttributes() + .setInitialIndent( 0 ) + .setIndent( oss.str().size() ) + .setWidth( CATCH_CONFIG_CONSOLE_WIDTH-10 ) ); + Catch::cout() << oss.str() << wrapper << "\n"; + } + Catch::cout() << pluralise( tagCounts.size(), "tag" ) << "\n" << std::endl; + return tagCounts.size(); + } + + inline std::size_t listReporters( Config const& /*config*/ ) { + Catch::cout() << "Available reporters:\n"; + IReporterRegistry::FactoryMap const& factories = getRegistryHub().getReporterRegistry().getFactories(); + IReporterRegistry::FactoryMap::const_iterator itBegin = factories.begin(), itEnd = factories.end(), it; + std::size_t maxNameLen = 0; + for(it = itBegin; it != itEnd; ++it ) + maxNameLen = (std::max)( maxNameLen, it->first.size() ); + + for(it = itBegin; it != itEnd; ++it ) { + Text wrapper( it->second->getDescription(), TextAttributes() + .setInitialIndent( 0 ) + .setIndent( 7+maxNameLen ) + .setWidth( CATCH_CONFIG_CONSOLE_WIDTH - maxNameLen-8 ) ); + Catch::cout() << " " + << it->first + << ":" + << std::string( maxNameLen - it->first.size() + 2, ' ' ) + << wrapper << "\n"; + } + Catch::cout() << std::endl; + return factories.size(); + } + + inline Option<std::size_t> list( Config const& config ) { + Option<std::size_t> listedCount; + if( config.listTests() ) + listedCount = listedCount.valueOr(0) + listTests( config ); + if( config.listTestNamesOnly() ) + listedCount = listedCount.valueOr(0) + listTestsNamesOnly( config ); + if( config.listTags() ) + listedCount = listedCount.valueOr(0) + listTags( config ); + if( config.listReporters() ) + listedCount = listedCount.valueOr(0) + listReporters( config ); + return listedCount; + } + +} // end namespace Catch + +#endif // TWOBLUECUBES_CATCH_LIST_HPP_INCLUDED diff --git a/unittest/Catch/include/internal/catch_matchers.hpp b/unittest/Catch/include/internal/catch_matchers.hpp new file mode 100644 index 0000000..ab8fec1 --- /dev/null +++ b/unittest/Catch/include/internal/catch_matchers.hpp @@ -0,0 +1,326 @@ +/* + * Created by Phil Nash on 04/03/2012. + * Copyright (c) 2012 Two Blue Cubes Ltd. All rights reserved. + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + */ +#ifndef TWOBLUECUBES_CATCH_MATCHERS_HPP_INCLUDED +#define TWOBLUECUBES_CATCH_MATCHERS_HPP_INCLUDED + +namespace Catch { +namespace Matchers { + namespace Impl { + + namespace Generic { + template<typename ExpressionT> class AllOf; + template<typename ExpressionT> class AnyOf; + template<typename ExpressionT> class Not; + } + + template<typename ExpressionT> + struct Matcher : SharedImpl<IShared> + { + typedef ExpressionT ExpressionType; + + virtual ~Matcher() {} + virtual Ptr<Matcher> clone() const = 0; + virtual bool match( ExpressionT const& expr ) const = 0; + virtual std::string toString() const = 0; + + Generic::AllOf<ExpressionT> operator && ( Matcher<ExpressionT> const& other ) const; + Generic::AnyOf<ExpressionT> operator || ( Matcher<ExpressionT> const& other ) const; + Generic::Not<ExpressionT> operator ! () const; + }; + + template<typename DerivedT, typename ExpressionT> + struct MatcherImpl : Matcher<ExpressionT> { + + virtual Ptr<Matcher<ExpressionT> > clone() const { + return Ptr<Matcher<ExpressionT> >( new DerivedT( static_cast<DerivedT const&>( *this ) ) ); + } + }; + + namespace Generic { + template<typename ExpressionT> + class Not : public MatcherImpl<Not<ExpressionT>, ExpressionT> { + public: + explicit Not( Matcher<ExpressionT> const& matcher ) : m_matcher(matcher.clone()) {} + Not( Not const& other ) : m_matcher( other.m_matcher ) {} + + virtual bool match( ExpressionT const& expr ) const CATCH_OVERRIDE { + return !m_matcher->match( expr ); + } + + virtual std::string toString() const CATCH_OVERRIDE { + return "not " + m_matcher->toString(); + } + private: + Ptr< Matcher<ExpressionT> > m_matcher; + }; + + template<typename ExpressionT> + class AllOf : public MatcherImpl<AllOf<ExpressionT>, ExpressionT> { + public: + + AllOf() {} + AllOf( AllOf const& other ) : m_matchers( other.m_matchers ) {} + + AllOf& add( Matcher<ExpressionT> const& matcher ) { + m_matchers.push_back( matcher.clone() ); + return *this; + } + virtual bool match( ExpressionT const& expr ) const + { + for( std::size_t i = 0; i < m_matchers.size(); ++i ) + if( !m_matchers[i]->match( expr ) ) + return false; + return true; + } + virtual std::string toString() const { + std::ostringstream oss; + oss << "( "; + for( std::size_t i = 0; i < m_matchers.size(); ++i ) { + if( i != 0 ) + oss << " and "; + oss << m_matchers[i]->toString(); + } + oss << " )"; + return oss.str(); + } + + AllOf operator && ( Matcher<ExpressionT> const& other ) const { + AllOf allOfExpr( *this ); + allOfExpr.add( other ); + return allOfExpr; + } + + private: + std::vector<Ptr<Matcher<ExpressionT> > > m_matchers; + }; + + template<typename ExpressionT> + class AnyOf : public MatcherImpl<AnyOf<ExpressionT>, ExpressionT> { + public: + + AnyOf() {} + AnyOf( AnyOf const& other ) : m_matchers( other.m_matchers ) {} + + AnyOf& add( Matcher<ExpressionT> const& matcher ) { + m_matchers.push_back( matcher.clone() ); + return *this; + } + virtual bool match( ExpressionT const& expr ) const + { + for( std::size_t i = 0; i < m_matchers.size(); ++i ) + if( m_matchers[i]->match( expr ) ) + return true; + return false; + } + virtual std::string toString() const { + std::ostringstream oss; + oss << "( "; + for( std::size_t i = 0; i < m_matchers.size(); ++i ) { + if( i != 0 ) + oss << " or "; + oss << m_matchers[i]->toString(); + } + oss << " )"; + return oss.str(); + } + + AnyOf operator || ( Matcher<ExpressionT> const& other ) const { + AnyOf anyOfExpr( *this ); + anyOfExpr.add( other ); + return anyOfExpr; + } + + private: + std::vector<Ptr<Matcher<ExpressionT> > > m_matchers; + }; + + } // namespace Generic + + template<typename ExpressionT> + Generic::AllOf<ExpressionT> Matcher<ExpressionT>::operator && ( Matcher<ExpressionT> const& other ) const { + Generic::AllOf<ExpressionT> allOfExpr; + allOfExpr.add( *this ); + allOfExpr.add( other ); + return allOfExpr; + } + + template<typename ExpressionT> + Generic::AnyOf<ExpressionT> Matcher<ExpressionT>::operator || ( Matcher<ExpressionT> const& other ) const { + Generic::AnyOf<ExpressionT> anyOfExpr; + anyOfExpr.add( *this ); + anyOfExpr.add( other ); + return anyOfExpr; + } + + template<typename ExpressionT> + Generic::Not<ExpressionT> Matcher<ExpressionT>::operator ! () const { + return Generic::Not<ExpressionT>( *this ); + } + + + namespace StdString { + + inline std::string makeString( std::string const& str ) { return str; } + inline std::string makeString( const char* str ) { return str ? std::string( str ) : std::string(); } + + struct CasedString + { + CasedString( std::string const& str, CaseSensitive::Choice caseSensitivity ) + : m_caseSensitivity( caseSensitivity ), + m_str( adjustString( str ) ) + {} + std::string adjustString( std::string const& str ) const { + return m_caseSensitivity == CaseSensitive::No + ? toLower( str ) + : str; + + } + std::string toStringSuffix() const + { + return m_caseSensitivity == CaseSensitive::No + ? " (case insensitive)" + : ""; + } + CaseSensitive::Choice m_caseSensitivity; + std::string m_str; + }; + + struct Equals : MatcherImpl<Equals, std::string> { + Equals( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) + : m_data( str, caseSensitivity ) + {} + Equals( Equals const& other ) : m_data( other.m_data ){} + + virtual ~Equals(); + + virtual bool match( std::string const& expr ) const { + return m_data.m_str == m_data.adjustString( expr );; + } + virtual std::string toString() const { + return "equals: \"" + m_data.m_str + "\"" + m_data.toStringSuffix(); + } + + CasedString m_data; + }; + + struct Contains : MatcherImpl<Contains, std::string> { + Contains( std::string const& substr, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) + : m_data( substr, caseSensitivity ){} + Contains( Contains const& other ) : m_data( other.m_data ){} + + virtual ~Contains(); + + virtual bool match( std::string const& expr ) const { + return m_data.adjustString( expr ).find( m_data.m_str ) != std::string::npos; + } + virtual std::string toString() const { + return "contains: \"" + m_data.m_str + "\"" + m_data.toStringSuffix(); + } + + CasedString m_data; + }; + + struct StartsWith : MatcherImpl<StartsWith, std::string> { + StartsWith( std::string const& substr, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) + : m_data( substr, caseSensitivity ){} + + StartsWith( StartsWith const& other ) : m_data( other.m_data ){} + + virtual ~StartsWith(); + + virtual bool match( std::string const& expr ) const { + return startsWith( m_data.adjustString( expr ), m_data.m_str ); + } + virtual std::string toString() const { + return "starts with: \"" + m_data.m_str + "\"" + m_data.toStringSuffix(); + } + + CasedString m_data; + }; + + struct EndsWith : MatcherImpl<EndsWith, std::string> { + EndsWith( std::string const& substr, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) + : m_data( substr, caseSensitivity ){} + EndsWith( EndsWith const& other ) : m_data( other.m_data ){} + + virtual ~EndsWith(); + + virtual bool match( std::string const& expr ) const { + return endsWith( m_data.adjustString( expr ), m_data.m_str ); + } + virtual std::string toString() const { + return "ends with: \"" + m_data.m_str + "\"" + m_data.toStringSuffix(); + } + + CasedString m_data; + }; + } // namespace StdString + } // namespace Impl + + // The following functions create the actual matcher objects. + // This allows the types to be inferred + template<typename ExpressionT> + inline Impl::Generic::Not<ExpressionT> Not( Impl::Matcher<ExpressionT> const& m ) { + return Impl::Generic::Not<ExpressionT>( m ); + } + + template<typename ExpressionT> + inline Impl::Generic::AllOf<ExpressionT> AllOf( Impl::Matcher<ExpressionT> const& m1, + Impl::Matcher<ExpressionT> const& m2 ) { + return Impl::Generic::AllOf<ExpressionT>().add( m1 ).add( m2 ); + } + template<typename ExpressionT> + inline Impl::Generic::AllOf<ExpressionT> AllOf( Impl::Matcher<ExpressionT> const& m1, + Impl::Matcher<ExpressionT> const& m2, + Impl::Matcher<ExpressionT> const& m3 ) { + return Impl::Generic::AllOf<ExpressionT>().add( m1 ).add( m2 ).add( m3 ); + } + template<typename ExpressionT> + inline Impl::Generic::AnyOf<ExpressionT> AnyOf( Impl::Matcher<ExpressionT> const& m1, + Impl::Matcher<ExpressionT> const& m2 ) { + return Impl::Generic::AnyOf<ExpressionT>().add( m1 ).add( m2 ); + } + template<typename ExpressionT> + inline Impl::Generic::AnyOf<ExpressionT> AnyOf( Impl::Matcher<ExpressionT> const& m1, + Impl::Matcher<ExpressionT> const& m2, + Impl::Matcher<ExpressionT> const& m3 ) { + return Impl::Generic::AnyOf<ExpressionT>().add( m1 ).add( m2 ).add( m3 ); + } + + inline Impl::StdString::Equals Equals( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) { + return Impl::StdString::Equals( str, caseSensitivity ); + } + inline Impl::StdString::Equals Equals( const char* str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) { + return Impl::StdString::Equals( Impl::StdString::makeString( str ), caseSensitivity ); + } + inline Impl::StdString::Contains Contains( std::string const& substr, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) { + return Impl::StdString::Contains( substr, caseSensitivity ); + } + inline Impl::StdString::Contains Contains( const char* substr, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) { + return Impl::StdString::Contains( Impl::StdString::makeString( substr ), caseSensitivity ); + } + inline Impl::StdString::StartsWith StartsWith( std::string const& substr ) { + return Impl::StdString::StartsWith( substr ); + } + inline Impl::StdString::StartsWith StartsWith( const char* substr ) { + return Impl::StdString::StartsWith( Impl::StdString::makeString( substr ) ); + } + inline Impl::StdString::EndsWith EndsWith( std::string const& substr ) { + return Impl::StdString::EndsWith( substr ); + } + inline Impl::StdString::EndsWith EndsWith( const char* substr ) { + return Impl::StdString::EndsWith( Impl::StdString::makeString( substr ) ); + } + +} // namespace Matchers + +using namespace Matchers; + +} // namespace Catch + +#endif // TWOBLUECUBES_CATCH_MATCHERS_HPP_INCLUDED diff --git a/unittest/Catch/include/internal/catch_message.h b/unittest/Catch/include/internal/catch_message.h new file mode 100644 index 0000000..84ff95e --- /dev/null +++ b/unittest/Catch/include/internal/catch_message.h @@ -0,0 +1,66 @@ +/* + * Created by Phil Nash on 1/2/2013. + * Copyright 2013 Two Blue Cubes Ltd. All rights reserved. + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + */ +#ifndef TWOBLUECUBES_CATCH_MESSAGE_H_INCLUDED +#define TWOBLUECUBES_CATCH_MESSAGE_H_INCLUDED + +#include <string> +#include "catch_result_type.h" +#include "catch_common.h" + +namespace Catch { + + struct MessageInfo { + MessageInfo( std::string const& _macroName, + SourceLineInfo const& _lineInfo, + ResultWas::OfType _type ); + + std::string macroName; + SourceLineInfo lineInfo; + ResultWas::OfType type; + std::string message; + unsigned int sequence; + + bool operator == ( MessageInfo const& other ) const { + return sequence == other.sequence; + } + bool operator < ( MessageInfo const& other ) const { + return sequence < other.sequence; + } + private: + static unsigned int globalCount; + }; + + struct MessageBuilder { + MessageBuilder( std::string const& macroName, + SourceLineInfo const& lineInfo, + ResultWas::OfType type ) + : m_info( macroName, lineInfo, type ) + {} + + template<typename T> + MessageBuilder& operator << ( T const& value ) { + m_stream << value; + return *this; + } + + MessageInfo m_info; + std::ostringstream m_stream; + }; + + class ScopedMessage { + public: + ScopedMessage( MessageBuilder const& builder ); + ScopedMessage( ScopedMessage const& other ); + ~ScopedMessage(); + + MessageInfo m_info; + }; + +} // end namespace Catch + +#endif // TWOBLUECUBES_CATCH_MESSAGE_H_INCLUDED diff --git a/unittest/Catch/include/internal/catch_message.hpp b/unittest/Catch/include/internal/catch_message.hpp new file mode 100644 index 0000000..42866be --- /dev/null +++ b/unittest/Catch/include/internal/catch_message.hpp @@ -0,0 +1,47 @@ +/* + * Created by Phil Nash on 1/2/2013. + * Copyright 2013 Two Blue Cubes Ltd. All rights reserved. + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + */ +#ifndef TWOBLUECUBES_CATCH_MESSAGE_HPP_INCLUDED +#define TWOBLUECUBES_CATCH_MESSAGE_HPP_INCLUDED + +#include "catch_message.h" + +namespace Catch { + + MessageInfo::MessageInfo( std::string const& _macroName, + SourceLineInfo const& _lineInfo, + ResultWas::OfType _type ) + : macroName( _macroName ), + lineInfo( _lineInfo ), + type( _type ), + sequence( ++globalCount ) + {} + + // This may need protecting if threading support is added + unsigned int MessageInfo::globalCount = 0; + + + //////////////////////////////////////////////////////////////////////////// + + ScopedMessage::ScopedMessage( MessageBuilder const& builder ) + : m_info( builder.m_info ) + { + m_info.message = builder.m_stream.str(); + getResultCapture().pushScopedMessage( m_info ); + } + ScopedMessage::ScopedMessage( ScopedMessage const& other ) + : m_info( other.m_info ) + {} + + ScopedMessage::~ScopedMessage() { + getResultCapture().popScopedMessage( m_info ); + } + + +} // end namespace Catch + +#endif // TWOBLUECUBES_CATCH_MESSAGE_HPP_INCLUDED diff --git a/unittest/Catch/include/internal/catch_notimplemented_exception.h b/unittest/Catch/include/internal/catch_notimplemented_exception.h new file mode 100644 index 0000000..2e38b98 --- /dev/null +++ b/unittest/Catch/include/internal/catch_notimplemented_exception.h @@ -0,0 +1,36 @@ +/* + * Created by Phil on 5/8/2012. + * Copyright 2012 Two Blue Cubes Ltd. All rights reserved. + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + */ +#ifndef TWOBLUECUBES_CATCH_NOTIMPLEMENTED_EXCEPTION_H_INCLUDED +#define TWOBLUECUBES_CATCH_NOTIMPLEMENTED_EXCEPTION_H_INCLUDED + +#include "catch_common.h" +#include <ostream> + +namespace Catch { + + class NotImplementedException : public std::exception + { + public: + NotImplementedException( SourceLineInfo const& lineInfo ); + NotImplementedException( NotImplementedException const& ) {} + + virtual ~NotImplementedException() CATCH_NOEXCEPT {} + + virtual const char* what() const CATCH_NOEXCEPT; + + private: + std::string m_what; + SourceLineInfo m_lineInfo; + }; + +} // end namespace Catch + +/////////////////////////////////////////////////////////////////////////////// +#define CATCH_NOT_IMPLEMENTED throw Catch::NotImplementedException( CATCH_INTERNAL_LINEINFO ) + +#endif // TWOBLUECUBES_CATCH_NOTIMPLEMENTED_EXCEPTION_H_INCLUDED diff --git a/unittest/Catch/include/internal/catch_notimplemented_exception.hpp b/unittest/Catch/include/internal/catch_notimplemented_exception.hpp new file mode 100644 index 0000000..4d263f1 --- /dev/null +++ b/unittest/Catch/include/internal/catch_notimplemented_exception.hpp @@ -0,0 +1,30 @@ +/* + * Created by Phil on 5/8/2012. + * Copyright 2012 Two Blue Cubes Ltd. All rights reserved. + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + */ +#ifndef TWOBLUECUBES_CATCH_NOTIMPLEMENTED_EXCEPTION_HPP_INCLUDED +#define TWOBLUECUBES_CATCH_NOTIMPLEMENTED_EXCEPTION_HPP_INCLUDED + +#include "catch_notimplemented_exception.h" +#include <ostream> + +namespace Catch { + + NotImplementedException::NotImplementedException( SourceLineInfo const& lineInfo ) + : m_lineInfo( lineInfo ) { + std::ostringstream oss; + oss << lineInfo << ": function "; + oss << "not implemented"; + m_what = oss.str(); + } + + const char* NotImplementedException::what() const CATCH_NOEXCEPT { + return m_what.c_str(); + } + +} // end namespace Catch + +#endif // TWOBLUECUBES_CATCH_NOTIMPLEMENTED_EXCEPTION_HPP_INCLUDED diff --git a/unittest/Catch/include/internal/catch_objc.hpp b/unittest/Catch/include/internal/catch_objc.hpp new file mode 100644 index 0000000..489cf55 --- /dev/null +++ b/unittest/Catch/include/internal/catch_objc.hpp @@ -0,0 +1,203 @@ +/* + * Created by Phil on 14/11/2010. + * Copyright 2010 Two Blue Cubes Ltd. All rights reserved. + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + */ +#ifndef TWOBLUECUBES_CATCH_OBJC_HPP_INCLUDED +#define TWOBLUECUBES_CATCH_OBJC_HPP_INCLUDED + +#include "catch_objc_arc.hpp" + +#import <objc/runtime.h> + +#include <string> + +// NB. Any general catch headers included here must be included +// in catch.hpp first to make sure they are included by the single +// header for non obj-usage +#include "catch_test_case_info.h" + +/////////////////////////////////////////////////////////////////////////////// +// This protocol is really only here for (self) documenting purposes, since +// all its methods are optional. +@protocol OcFixture + +@optional + +-(void) setUp; +-(void) tearDown; + +@end + +namespace Catch { + + class OcMethod : public SharedImpl<ITestCase> { + + public: + OcMethod( Class cls, SEL sel ) : m_cls( cls ), m_sel( sel ) {} + + virtual void invoke() const { + id obj = [[m_cls alloc] init]; + + performOptionalSelector( obj, @selector(setUp) ); + performOptionalSelector( obj, m_sel ); + performOptionalSelector( obj, @selector(tearDown) ); + + arcSafeRelease( obj ); + } + private: + virtual ~OcMethod() {} + + Class m_cls; + SEL m_sel; + }; + + namespace Detail{ + + + inline std::string getAnnotation( Class cls, + std::string const& annotationName, + std::string const& testCaseName ) { + NSString* selStr = [[NSString alloc] initWithFormat:@"Catch_%s_%s", annotationName.c_str(), testCaseName.c_str()]; + SEL sel = NSSelectorFromString( selStr ); + arcSafeRelease( selStr ); + id value = performOptionalSelector( cls, sel ); + if( value ) + return [(NSString*)value UTF8String]; + return ""; + } + } + + inline size_t registerTestMethods() { + size_t noTestMethods = 0; + int noClasses = objc_getClassList( CATCH_NULL, 0 ); + + Class* classes = (CATCH_UNSAFE_UNRETAINED Class *)malloc( sizeof(Class) * noClasses); + objc_getClassList( classes, noClasses ); + + for( int c = 0; c < noClasses; c++ ) { + Class cls = classes[c]; + { + u_int count; + Method* methods = class_copyMethodList( cls, &count ); + for( u_int m = 0; m < count ; m++ ) { + SEL selector = method_getName(methods[m]); + std::string methodName = sel_getName(selector); + if( startsWith( methodName, "Catch_TestCase_" ) ) { + std::string testCaseName = methodName.substr( 15 ); + std::string name = Detail::getAnnotation( cls, "Name", testCaseName ); + std::string desc = Detail::getAnnotation( cls, "Description", testCaseName ); + const char* className = class_getName( cls ); + + getMutableRegistryHub().registerTest( makeTestCase( new OcMethod( cls, selector ), className, name.c_str(), desc.c_str(), SourceLineInfo() ) ); + noTestMethods++; + } + } + free(methods); + } + } + return noTestMethods; + } + + namespace Matchers { + namespace Impl { + namespace NSStringMatchers { + + template<typename MatcherT> + struct StringHolder : MatcherImpl<MatcherT, NSString*>{ + StringHolder( NSString* substr ) : m_substr( [substr copy] ){} + StringHolder( StringHolder const& other ) : m_substr( [other.m_substr copy] ){} + StringHolder() { + arcSafeRelease( m_substr ); + } + + NSString* m_substr; + }; + + struct Equals : StringHolder<Equals> { + Equals( NSString* substr ) : StringHolder( substr ){} + + virtual bool match( ExpressionType const& str ) const { + return (str != nil || m_substr == nil ) && + [str isEqualToString:m_substr]; + } + + virtual std::string toString() const { + return "equals string: " + Catch::toString( m_substr ); + } + }; + + struct Contains : StringHolder<Contains> { + Contains( NSString* substr ) : StringHolder( substr ){} + + virtual bool match( ExpressionType const& str ) const { + return (str != nil || m_substr == nil ) && + [str rangeOfString:m_substr].location != NSNotFound; + } + + virtual std::string toString() const { + return "contains string: " + Catch::toString( m_substr ); + } + }; + + struct StartsWith : StringHolder<StartsWith> { + StartsWith( NSString* substr ) : StringHolder( substr ){} + + virtual bool match( ExpressionType const& str ) const { + return (str != nil || m_substr == nil ) && + [str rangeOfString:m_substr].location == 0; + } + + virtual std::string toString() const { + return "starts with: " + Catch::toString( m_substr ); + } + }; + struct EndsWith : StringHolder<EndsWith> { + EndsWith( NSString* substr ) : StringHolder( substr ){} + + virtual bool match( ExpressionType const& str ) const { + return (str != nil || m_substr == nil ) && + [str rangeOfString:m_substr].location == [str length] - [m_substr length]; + } + + virtual std::string toString() const { + return "ends with: " + Catch::toString( m_substr ); + } + }; + + } // namespace NSStringMatchers + } // namespace Impl + + inline Impl::NSStringMatchers::Equals + Equals( NSString* substr ){ return Impl::NSStringMatchers::Equals( substr ); } + + inline Impl::NSStringMatchers::Contains + Contains( NSString* substr ){ return Impl::NSStringMatchers::Contains( substr ); } + + inline Impl::NSStringMatchers::StartsWith + StartsWith( NSString* substr ){ return Impl::NSStringMatchers::StartsWith( substr ); } + + inline Impl::NSStringMatchers::EndsWith + EndsWith( NSString* substr ){ return Impl::NSStringMatchers::EndsWith( substr ); } + + } // namespace Matchers + + using namespace Matchers; + +} // namespace Catch + +/////////////////////////////////////////////////////////////////////////////// +#define OC_TEST_CASE( name, desc )\ ++(NSString*) INTERNAL_CATCH_UNIQUE_NAME( Catch_Name_test ) \ +{\ +return @ name; \ +}\ ++(NSString*) INTERNAL_CATCH_UNIQUE_NAME( Catch_Description_test ) \ +{ \ +return @ desc; \ +} \ +-(void) INTERNAL_CATCH_UNIQUE_NAME( Catch_TestCase_test ) + +#endif // TWOBLUECUBES_CATCH_OBJC_HPP_INCLUDED diff --git a/unittest/Catch/include/internal/catch_objc_arc.hpp b/unittest/Catch/include/internal/catch_objc_arc.hpp new file mode 100644 index 0000000..6bcd6b8 --- /dev/null +++ b/unittest/Catch/include/internal/catch_objc_arc.hpp @@ -0,0 +1,51 @@ +/* + * Created by Phil on 1/08/2012. + * Copyright 2012 Two Blue Cubes Ltd. All rights reserved. + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + */ +#ifndef TWOBLUECUBES_CATCH_OBJC_ARC_HPP_INCLUDED +#define TWOBLUECUBES_CATCH_OBJC_ARC_HPP_INCLUDED + +#import <Foundation/Foundation.h> + +#ifdef __has_feature +#define CATCH_ARC_ENABLED __has_feature(objc_arc) +#else +#define CATCH_ARC_ENABLED 0 +#endif + +void arcSafeRelease( NSObject* obj ); +id performOptionalSelector( id obj, SEL sel ); + +#if !CATCH_ARC_ENABLED +inline void arcSafeRelease( NSObject* obj ) { + [obj release]; +} +inline id performOptionalSelector( id obj, SEL sel ) { + if( [obj respondsToSelector: sel] ) + return [obj performSelector: sel]; + return nil; +} +#define CATCH_UNSAFE_UNRETAINED +#define CATCH_ARC_STRONG +#else +inline void arcSafeRelease( NSObject* ){} +inline id performOptionalSelector( id obj, SEL sel ) { +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Warc-performSelector-leaks" +#endif + if( [obj respondsToSelector: sel] ) + return [obj performSelector: sel]; +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + return nil; +} +#define CATCH_UNSAFE_UNRETAINED __unsafe_unretained +#define CATCH_ARC_STRONG __strong +#endif + +#endif // TWOBLUECUBES_CATCH_OBJC_ARC_HPP_INCLUDED diff --git a/unittest/Catch/include/internal/catch_option.hpp b/unittest/Catch/include/internal/catch_option.hpp new file mode 100644 index 0000000..5413abf --- /dev/null +++ b/unittest/Catch/include/internal/catch_option.hpp @@ -0,0 +1,75 @@ +/* + * Created by Phil on 02/12/2012. + * Copyright 2012 Two Blue Cubes Ltd. All rights reserved. + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + */ +#ifndef TWOBLUECUBES_CATCH_OPTION_HPP_INCLUDED +#define TWOBLUECUBES_CATCH_OPTION_HPP_INCLUDED + +#include "catch_common.h" + +namespace Catch { + + // An optional type + template<typename T> + class Option { + public: + Option() : nullableValue( CATCH_NULL ) {} + Option( T const& _value ) + : nullableValue( new( storage ) T( _value ) ) + {} + Option( Option const& _other ) + : nullableValue( _other ? new( storage ) T( *_other ) : CATCH_NULL ) + {} + + ~Option() { + reset(); + } + + Option& operator= ( Option const& _other ) { + if( &_other != this ) { + reset(); + if( _other ) + nullableValue = new( storage ) T( *_other ); + } + return *this; + } + Option& operator = ( T const& _value ) { + reset(); + nullableValue = new( storage ) T( _value ); + return *this; + } + + void reset() { + if( nullableValue ) + nullableValue->~T(); + nullableValue = CATCH_NULL; + } + + T& operator*() { return *nullableValue; } + T const& operator*() const { return *nullableValue; } + T* operator->() { return nullableValue; } + const T* operator->() const { return nullableValue; } + + T valueOr( T const& defaultValue ) const { + return nullableValue ? *nullableValue : defaultValue; + } + + bool some() const { return nullableValue != CATCH_NULL; } + bool none() const { return nullableValue == CATCH_NULL; } + + bool operator !() const { return nullableValue == CATCH_NULL; } + operator SafeBool::type() const { + return SafeBool::makeSafe( some() ); + } + + private: + T* nullableValue; + char storage[sizeof(T)]; + }; + +} // end namespace Catch + +#endif // TWOBLUECUBES_CATCH_OPTION_HPP_INCLUDED diff --git a/unittest/Catch/include/internal/catch_platform.h b/unittest/Catch/include/internal/catch_platform.h new file mode 100644 index 0000000..0142dc1 --- /dev/null +++ b/unittest/Catch/include/internal/catch_platform.h @@ -0,0 +1,20 @@ +/* + * Created by Phil on 16/8/2013. + * Copyright 2013 Two Blue Cubes Ltd. All rights reserved. + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + * + */ +#ifndef TWOBLUECUBES_CATCH_PLATFORM_H_INCLUDED +#define TWOBLUECUBES_CATCH_PLATFORM_H_INCLUDED + +#if defined(__MAC_OS_X_VERSION_MIN_REQUIRED) +#define CATCH_PLATFORM_MAC +#elif defined(__IPHONE_OS_VERSION_MIN_REQUIRED) +#define CATCH_PLATFORM_IPHONE +#elif defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) +#define CATCH_PLATFORM_WINDOWS +#endif + +#endif // TWOBLUECUBES_CATCH_PLATFORM_H_INCLUDED diff --git a/unittest/Catch/include/internal/catch_ptr.hpp b/unittest/Catch/include/internal/catch_ptr.hpp new file mode 100644 index 0000000..940e5d1 --- /dev/null +++ b/unittest/Catch/include/internal/catch_ptr.hpp @@ -0,0 +1,93 @@ +/* + * Created by Phil on 02/05/2012. + * Copyright 2012 Two Blue Cubes Ltd. All rights reserved. + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + */ +#ifndef TWOBLUECUBES_CATCH_PTR_HPP_INCLUDED +#define TWOBLUECUBES_CATCH_PTR_HPP_INCLUDED + +#include "catch_common.h" + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wpadded" +#endif + +namespace Catch { + + // An intrusive reference counting smart pointer. + // T must implement addRef() and release() methods + // typically implementing the IShared interface + template<typename T> + class Ptr { + public: + Ptr() : m_p( CATCH_NULL ){} + Ptr( T* p ) : m_p( p ){ + if( m_p ) + m_p->addRef(); + } + Ptr( Ptr const& other ) : m_p( other.m_p ){ + if( m_p ) + m_p->addRef(); + } + ~Ptr(){ + if( m_p ) + m_p->release(); + } + void reset() { + if( m_p ) + m_p->release(); + m_p = CATCH_NULL; + } + Ptr& operator = ( T* p ){ + Ptr temp( p ); + swap( temp ); + return *this; + } + Ptr& operator = ( Ptr const& other ){ + Ptr temp( other ); + swap( temp ); + return *this; + } + void swap( Ptr& other ) { std::swap( m_p, other.m_p ); } + T* get() const{ return m_p; } + T& operator*() const { return *m_p; } + T* operator->() const { return m_p; } + bool operator !() const { return m_p == CATCH_NULL; } + operator SafeBool::type() const { return SafeBool::makeSafe( m_p != CATCH_NULL ); } + + private: + T* m_p; + }; + + struct IShared : NonCopyable { + virtual ~IShared(); + virtual void addRef() const = 0; + virtual void release() const = 0; + }; + + template<typename T = IShared> + struct SharedImpl : T { + + SharedImpl() : m_rc( 0 ){} + + virtual void addRef() const { + ++m_rc; + } + virtual void release() const { + if( --m_rc == 0 ) + delete this; + } + + mutable unsigned int m_rc; + }; + +} // end namespace Catch + +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + +#endif // TWOBLUECUBES_CATCH_PTR_HPP_INCLUDED diff --git a/unittest/Catch/include/internal/catch_reenable_warnings.h b/unittest/Catch/include/internal/catch_reenable_warnings.h new file mode 100644 index 0000000..33574e0 --- /dev/null +++ b/unittest/Catch/include/internal/catch_reenable_warnings.h @@ -0,0 +1,21 @@ +/* + * Copyright 2014 Two Blue Cubes Ltd + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + */ + +#ifndef TWOBLUECUBES_CATCH_REENABLE_WARNINGS_H_INCLUDED +#define TWOBLUECUBES_CATCH_REENABLE_WARNINGS_H_INCLUDED + +#ifdef __clang__ +# ifdef __ICC // icpc defines the __clang__ macro +# pragma warning(pop) +# else +# pragma clang diagnostic pop +# endif +#elif defined __GNUC__ +# pragma GCC diagnostic pop +#endif + +#endif // TWOBLUECUBES_CATCH_REENABLE_WARNINGS_H_INCLUDED diff --git a/unittest/Catch/include/internal/catch_registry_hub.hpp b/unittest/Catch/include/internal/catch_registry_hub.hpp new file mode 100644 index 0000000..35293bf --- /dev/null +++ b/unittest/Catch/include/internal/catch_registry_hub.hpp @@ -0,0 +1,86 @@ +/* + * Created by Phil on 5/8/2012. + * Copyright 2012 Two Blue Cubes Ltd. All rights reserved. + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + */ +#ifndef TWOBLUECUBES_CATCH_REGISTRY_HUB_HPP_INCLUDED +#define TWOBLUECUBES_CATCH_REGISTRY_HUB_HPP_INCLUDED + +#include "catch_interfaces_registry_hub.h" + +#include "catch_test_case_registry_impl.hpp" +#include "catch_reporter_registry.hpp" +#include "catch_exception_translator_registry.hpp" + +namespace Catch { + + namespace { + + class RegistryHub : public IRegistryHub, public IMutableRegistryHub { + + RegistryHub( RegistryHub const& ); + void operator=( RegistryHub const& ); + + public: // IRegistryHub + RegistryHub() { + } + virtual IReporterRegistry const& getReporterRegistry() const CATCH_OVERRIDE { + return m_reporterRegistry; + } + virtual ITestCaseRegistry const& getTestCaseRegistry() const CATCH_OVERRIDE { + return m_testCaseRegistry; + } + virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() CATCH_OVERRIDE { + return m_exceptionTranslatorRegistry; + } + + public: // IMutableRegistryHub + virtual void registerReporter( std::string const& name, Ptr<IReporterFactory> const& factory ) CATCH_OVERRIDE { + m_reporterRegistry.registerReporter( name, factory ); + } + virtual void registerListener( Ptr<IReporterFactory> const& factory ) CATCH_OVERRIDE { + m_reporterRegistry.registerListener( factory ); + } + virtual void registerTest( TestCase const& testInfo ) CATCH_OVERRIDE { + m_testCaseRegistry.registerTest( testInfo ); + } + virtual void registerTranslator( const IExceptionTranslator* translator ) CATCH_OVERRIDE { + m_exceptionTranslatorRegistry.registerTranslator( translator ); + } + + private: + TestRegistry m_testCaseRegistry; + ReporterRegistry m_reporterRegistry; + ExceptionTranslatorRegistry m_exceptionTranslatorRegistry; + }; + + // Single, global, instance + inline RegistryHub*& getTheRegistryHub() { + static RegistryHub* theRegistryHub = CATCH_NULL; + if( !theRegistryHub ) + theRegistryHub = new RegistryHub(); + return theRegistryHub; + } + } + + IRegistryHub& getRegistryHub() { + return *getTheRegistryHub(); + } + IMutableRegistryHub& getMutableRegistryHub() { + return *getTheRegistryHub(); + } + void cleanUp() { + delete getTheRegistryHub(); + getTheRegistryHub() = CATCH_NULL; + cleanUpContext(); + } + std::string translateActiveException() { + return getRegistryHub().getExceptionTranslatorRegistry().translateActiveException(); + } + + +} // end namespace Catch + +#endif // TWOBLUECUBES_CATCH_REGISTRY_HUB_HPP_INCLUDED diff --git a/unittest/Catch/include/internal/catch_reporter_registrars.hpp b/unittest/Catch/include/internal/catch_reporter_registrars.hpp new file mode 100644 index 0000000..7bd7b61 --- /dev/null +++ b/unittest/Catch/include/internal/catch_reporter_registrars.hpp @@ -0,0 +1,98 @@ +/* + * Created by Phil on 31/12/2010. + * Copyright 2010 Two Blue Cubes Ltd. All rights reserved. + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + */ +#ifndef TWOBLUECUBES_CATCH_REPORTER_REGISTRARS_HPP_INCLUDED +#define TWOBLUECUBES_CATCH_REPORTER_REGISTRARS_HPP_INCLUDED + +#include "catch_interfaces_registry_hub.h" +#include "catch_legacy_reporter_adapter.h" + +namespace Catch { + + template<typename T> + class LegacyReporterRegistrar { + + class ReporterFactory : public IReporterFactory { + virtual IStreamingReporter* create( ReporterConfig const& config ) const { + return new LegacyReporterAdapter( new T( config ) ); + } + + virtual std::string getDescription() const { + return T::getDescription(); + } + }; + + public: + + LegacyReporterRegistrar( std::string const& name ) { + getMutableRegistryHub().registerReporter( name, new ReporterFactory() ); + } + }; + + template<typename T> + class ReporterRegistrar { + + class ReporterFactory : public SharedImpl<IReporterFactory> { + + // *** Please Note ***: + // - If you end up here looking at a compiler error because it's trying to register + // your custom reporter class be aware that the native reporter interface has changed + // to IStreamingReporter. The "legacy" interface, IReporter, is still supported via + // an adapter. Just use REGISTER_LEGACY_REPORTER to take advantage of the adapter. + // However please consider updating to the new interface as the old one is now + // deprecated and will probably be removed quite soon! + // Please contact me via github if you have any questions at all about this. + // In fact, ideally, please contact me anyway to let me know you've hit this - as I have + // no idea who is actually using custom reporters at all (possibly no-one!). + // The new interface is designed to minimise exposure to interface changes in the future. + virtual IStreamingReporter* create( ReporterConfig const& config ) const { + return new T( config ); + } + + virtual std::string getDescription() const { + return T::getDescription(); + } + }; + + public: + + ReporterRegistrar( std::string const& name ) { + getMutableRegistryHub().registerReporter( name, new ReporterFactory() ); + } + }; + + template<typename T> + class ListenerRegistrar { + + class ListenerFactory : public SharedImpl<IReporterFactory> { + + virtual IStreamingReporter* create( ReporterConfig const& config ) const { + return new T( config ); + } + virtual std::string getDescription() const { + return ""; + } + }; + + public: + + ListenerRegistrar() { + getMutableRegistryHub().registerListener( new ListenerFactory() ); + } + }; +} + +#define INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) \ + namespace{ Catch::LegacyReporterRegistrar<reporterType> catch_internal_RegistrarFor##reporterType( name ); } + +#define INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType ) \ + namespace{ Catch::ReporterRegistrar<reporterType> catch_internal_RegistrarFor##reporterType( name ); } + +#define INTERNAL_CATCH_REGISTER_LISTENER( listenerType ) \ + namespace{ Catch::ListenerRegistrar<listenerType> catch_internal_RegistrarFor##listenerType; } + +#endif // TWOBLUECUBES_CATCH_REPORTER_REGISTRARS_HPP_INCLUDED diff --git a/unittest/Catch/include/internal/catch_reporter_registry.hpp b/unittest/Catch/include/internal/catch_reporter_registry.hpp new file mode 100644 index 0000000..71f23ff --- /dev/null +++ b/unittest/Catch/include/internal/catch_reporter_registry.hpp @@ -0,0 +1,50 @@ +/* + * Created by Phil on 29/10/2010. + * Copyright 2010 Two Blue Cubes Ltd. All rights reserved. + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + */ +#ifndef TWOBLUECUBES_CATCH_REPORTER_REGISTRY_HPP_INCLUDED +#define TWOBLUECUBES_CATCH_REPORTER_REGISTRY_HPP_INCLUDED + +#include "catch_interfaces_reporter.h" + +#include <map> + +namespace Catch { + + class ReporterRegistry : public IReporterRegistry { + + public: + + virtual ~ReporterRegistry() CATCH_OVERRIDE {} + + virtual IStreamingReporter* create( std::string const& name, Ptr<IConfig const> const& config ) const CATCH_OVERRIDE { + FactoryMap::const_iterator it = m_factories.find( name ); + if( it == m_factories.end() ) + return CATCH_NULL; + return it->second->create( ReporterConfig( config ) ); + } + + void registerReporter( std::string const& name, Ptr<IReporterFactory> const& factory ) { + m_factories.insert( std::make_pair( name, factory ) ); + } + void registerListener( Ptr<IReporterFactory> const& factory ) { + m_listeners.push_back( factory ); + } + + virtual FactoryMap const& getFactories() const CATCH_OVERRIDE { + return m_factories; + } + virtual Listeners const& getListeners() const CATCH_OVERRIDE { + return m_listeners; + } + + private: + FactoryMap m_factories; + Listeners m_listeners; + }; +} + +#endif // TWOBLUECUBES_CATCH_REPORTER_REGISTRY_HPP_INCLUDED diff --git a/unittest/Catch/include/internal/catch_result_builder.h b/unittest/Catch/include/internal/catch_result_builder.h new file mode 100644 index 0000000..8900266 --- /dev/null +++ b/unittest/Catch/include/internal/catch_result_builder.h @@ -0,0 +1,111 @@ +/* + * Created by Phil on 28/5/2014. + * Copyright 2014 Two Blue Cubes Ltd. All rights reserved. + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + */ +#ifndef TWOBLUECUBES_CATCH_RESULT_BUILDER_H_INCLUDED +#define TWOBLUECUBES_CATCH_RESULT_BUILDER_H_INCLUDED + +#include "catch_result_type.h" +#include "catch_assertionresult.h" +#include "catch_common.h" +#include "catch_matchers.hpp" + +namespace Catch { + + struct TestFailureException{}; + + template<typename T> class ExpressionLhs; + + struct STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison; + + struct CopyableStream { + CopyableStream() {} + CopyableStream( CopyableStream const& other ) { + oss << other.oss.str(); + } + CopyableStream& operator=( CopyableStream const& other ) { + oss.str(""); + oss << other.oss.str(); + return *this; + } + std::ostringstream oss; + }; + + class ResultBuilder { + public: + ResultBuilder( char const* macroName, + SourceLineInfo const& lineInfo, + char const* capturedExpression, + ResultDisposition::Flags resultDisposition, + char const* secondArg = "" ); + + template<typename T> + ExpressionLhs<T const&> operator <= ( T const& operand ); + ExpressionLhs<bool> operator <= ( bool value ); + + template<typename T> + ResultBuilder& operator << ( T const& value ) { + m_stream.oss << value; + return *this; + } + + template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator && ( RhsT const& ); + template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator || ( RhsT const& ); + + ResultBuilder& setResultType( ResultWas::OfType result ); + ResultBuilder& setResultType( bool result ); + ResultBuilder& setLhs( std::string const& lhs ); + ResultBuilder& setRhs( std::string const& rhs ); + ResultBuilder& setOp( std::string const& op ); + + void endExpression(); + + std::string reconstructExpression() const; + AssertionResult build() const; + + void useActiveException( ResultDisposition::Flags resultDisposition = ResultDisposition::Normal ); + void captureResult( ResultWas::OfType resultType ); + void captureExpression(); + void captureExpectedException( std::string const& expectedMessage ); + void captureExpectedException( Matchers::Impl::Matcher<std::string> const& matcher ); + void handleResult( AssertionResult const& result ); + void react(); + bool shouldDebugBreak() const; + bool allowThrows() const; + + private: + AssertionInfo m_assertionInfo; + AssertionResultData m_data; + struct ExprComponents { + ExprComponents() : testFalse( false ) {} + bool testFalse; + std::string lhs, rhs, op; + } m_exprComponents; + CopyableStream m_stream; + + bool m_shouldDebugBreak; + bool m_shouldThrow; + }; + +} // namespace Catch + +// Include after due to circular dependency: +#include "catch_expression_lhs.hpp" + +namespace Catch { + + template<typename T> + inline ExpressionLhs<T const&> ResultBuilder::operator <= ( T const& operand ) { + return ExpressionLhs<T const&>( *this, operand ); + } + + inline ExpressionLhs<bool> ResultBuilder::operator <= ( bool value ) { + return ExpressionLhs<bool>( *this, value ); + } + +} // namespace Catch + +#endif // TWOBLUECUBES_CATCH_RESULT_BUILDER_H_INCLUDED diff --git a/unittest/Catch/include/internal/catch_result_builder.hpp b/unittest/Catch/include/internal/catch_result_builder.hpp new file mode 100644 index 0000000..d453fec --- /dev/null +++ b/unittest/Catch/include/internal/catch_result_builder.hpp @@ -0,0 +1,161 @@ +/* + * Created by Phil on 28/5/2014. + * Copyright 2014 Two Blue Cubes Ltd. All rights reserved. + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + */ +#ifndef TWOBLUECUBES_CATCH_RESULT_BUILDER_HPP_INCLUDED +#define TWOBLUECUBES_CATCH_RESULT_BUILDER_HPP_INCLUDED + +#include "catch_result_builder.h" +#include "catch_context.h" +#include "catch_interfaces_config.h" +#include "catch_interfaces_runner.h" +#include "catch_interfaces_capture.h" +#include "catch_interfaces_registry_hub.h" +#include "catch_wildcard_pattern.hpp" + +namespace Catch { + + std::string capturedExpressionWithSecondArgument( std::string const& capturedExpression, std::string const& secondArg ) { + return secondArg.empty() || secondArg == "\"\"" + ? capturedExpression + : capturedExpression + ", " + secondArg; + } + ResultBuilder::ResultBuilder( char const* macroName, + SourceLineInfo const& lineInfo, + char const* capturedExpression, + ResultDisposition::Flags resultDisposition, + char const* secondArg ) + : m_assertionInfo( macroName, lineInfo, capturedExpressionWithSecondArgument( capturedExpression, secondArg ), resultDisposition ), + m_shouldDebugBreak( false ), + m_shouldThrow( false ) + {} + + ResultBuilder& ResultBuilder::setResultType( ResultWas::OfType result ) { + m_data.resultType = result; + return *this; + } + ResultBuilder& ResultBuilder::setResultType( bool result ) { + m_data.resultType = result ? ResultWas::Ok : ResultWas::ExpressionFailed; + return *this; + } + ResultBuilder& ResultBuilder::setLhs( std::string const& lhs ) { + m_exprComponents.lhs = lhs; + return *this; + } + ResultBuilder& ResultBuilder::setRhs( std::string const& rhs ) { + m_exprComponents.rhs = rhs; + return *this; + } + ResultBuilder& ResultBuilder::setOp( std::string const& op ) { + m_exprComponents.op = op; + return *this; + } + + void ResultBuilder::endExpression() { + m_exprComponents.testFalse = isFalseTest( m_assertionInfo.resultDisposition ); + captureExpression(); + } + + void ResultBuilder::useActiveException( ResultDisposition::Flags resultDisposition ) { + m_assertionInfo.resultDisposition = resultDisposition; + m_stream.oss << Catch::translateActiveException(); + captureResult( ResultWas::ThrewException ); + } + + void ResultBuilder::captureResult( ResultWas::OfType resultType ) { + setResultType( resultType ); + captureExpression(); + } + void ResultBuilder::captureExpectedException( std::string const& expectedMessage ) { + if( expectedMessage.empty() ) + captureExpectedException( Matchers::Impl::Generic::AllOf<std::string>() ); + else + captureExpectedException( Matchers::Equals( expectedMessage ) ); + } + + void ResultBuilder::captureExpectedException( Matchers::Impl::Matcher<std::string> const& matcher ) { + + assert( m_exprComponents.testFalse == false ); + AssertionResultData data = m_data; + data.resultType = ResultWas::Ok; + data.reconstructedExpression = m_assertionInfo.capturedExpression; + + std::string actualMessage = Catch::translateActiveException(); + if( !matcher.match( actualMessage ) ) { + data.resultType = ResultWas::ExpressionFailed; + data.reconstructedExpression = actualMessage; + } + AssertionResult result( m_assertionInfo, data ); + handleResult( result ); + } + + void ResultBuilder::captureExpression() { + AssertionResult result = build(); + handleResult( result ); + } + void ResultBuilder::handleResult( AssertionResult const& result ) + { + getResultCapture().assertionEnded( result ); + + if( !result.isOk() ) { + if( getCurrentContext().getConfig()->shouldDebugBreak() ) + m_shouldDebugBreak = true; + if( getCurrentContext().getRunner()->aborting() || (m_assertionInfo.resultDisposition & ResultDisposition::Normal) ) + m_shouldThrow = true; + } + } + void ResultBuilder::react() { + if( m_shouldThrow ) + throw Catch::TestFailureException(); + } + + bool ResultBuilder::shouldDebugBreak() const { return m_shouldDebugBreak; } + bool ResultBuilder::allowThrows() const { return getCurrentContext().getConfig()->allowThrows(); } + + AssertionResult ResultBuilder::build() const + { + assert( m_data.resultType != ResultWas::Unknown ); + + AssertionResultData data = m_data; + + // Flip bool results if testFalse is set + if( m_exprComponents.testFalse ) { + if( data.resultType == ResultWas::Ok ) + data.resultType = ResultWas::ExpressionFailed; + else if( data.resultType == ResultWas::ExpressionFailed ) + data.resultType = ResultWas::Ok; + } + + data.message = m_stream.oss.str(); + data.reconstructedExpression = reconstructExpression(); + if( m_exprComponents.testFalse ) { + if( m_exprComponents.op == "" ) + data.reconstructedExpression = "!" + data.reconstructedExpression; + else + data.reconstructedExpression = "!(" + data.reconstructedExpression + ")"; + } + return AssertionResult( m_assertionInfo, data ); + } + std::string ResultBuilder::reconstructExpression() const { + if( m_exprComponents.op == "" ) + return m_exprComponents.lhs.empty() ? m_assertionInfo.capturedExpression : m_exprComponents.op + m_exprComponents.lhs; + else if( m_exprComponents.op == "matches" ) + return m_exprComponents.lhs + " " + m_exprComponents.rhs; + else if( m_exprComponents.op != "!" ) { + if( m_exprComponents.lhs.size() + m_exprComponents.rhs.size() < 40 && + m_exprComponents.lhs.find("\n") == std::string::npos && + m_exprComponents.rhs.find("\n") == std::string::npos ) + return m_exprComponents.lhs + " " + m_exprComponents.op + " " + m_exprComponents.rhs; + else + return m_exprComponents.lhs + "\n" + m_exprComponents.op + "\n" + m_exprComponents.rhs; + } + else + return "{can't expand - use " + m_assertionInfo.macroName + "_FALSE( " + m_assertionInfo.capturedExpression.substr(1) + " ) instead of " + m_assertionInfo.macroName + "( " + m_assertionInfo.capturedExpression + " ) for better diagnostics}"; + } + +} // end namespace Catch + +#endif // TWOBLUECUBES_CATCH_RESULT_BUILDER_HPP_INCLUDED diff --git a/unittest/Catch/include/internal/catch_result_type.h b/unittest/Catch/include/internal/catch_result_type.h new file mode 100644 index 0000000..4c3d77d --- /dev/null +++ b/unittest/Catch/include/internal/catch_result_type.h @@ -0,0 +1,61 @@ +/* + * Created by Phil on 07/01/2011. + * Copyright 2011 Two Blue Cubes Ltd. All rights reserved. + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + */ +#ifndef TWOBLUECUBES_CATCH_RESULT_TYPE_H_INCLUDED +#define TWOBLUECUBES_CATCH_RESULT_TYPE_H_INCLUDED + +namespace Catch { + + // ResultWas::OfType enum + struct ResultWas { enum OfType { + Unknown = -1, + Ok = 0, + Info = 1, + Warning = 2, + + FailureBit = 0x10, + + ExpressionFailed = FailureBit | 1, + ExplicitFailure = FailureBit | 2, + + Exception = 0x100 | FailureBit, + + ThrewException = Exception | 1, + DidntThrowException = Exception | 2, + + FatalErrorCondition = 0x200 | FailureBit + + }; }; + + inline bool isOk( ResultWas::OfType resultType ) { + return ( resultType & ResultWas::FailureBit ) == 0; + } + inline bool isJustInfo( int flags ) { + return flags == ResultWas::Info; + } + + + // ResultDisposition::Flags enum + struct ResultDisposition { enum Flags { + Normal = 0x01, + + ContinueOnFailure = 0x02, // Failures fail test, but execution continues + FalseTest = 0x04, // Prefix expression with ! + SuppressFail = 0x08 // Failures are reported but do not fail the test + }; }; + + inline ResultDisposition::Flags operator | ( ResultDisposition::Flags lhs, ResultDisposition::Flags rhs ) { + return static_cast<ResultDisposition::Flags>( static_cast<int>( lhs ) | static_cast<int>( rhs ) ); + } + + inline bool shouldContinueOnFailure( int flags ) { return ( flags & ResultDisposition::ContinueOnFailure ) != 0; } + inline bool isFalseTest( int flags ) { return ( flags & ResultDisposition::FalseTest ) != 0; } + inline bool shouldSuppressFailure( int flags ) { return ( flags & ResultDisposition::SuppressFail ) != 0; } + +} // end namespace Catch + +#endif // TWOBLUECUBES_CATCH_RESULT_TYPE_H_INCLUDED diff --git a/unittest/Catch/include/internal/catch_run_context.hpp b/unittest/Catch/include/internal/catch_run_context.hpp new file mode 100644 index 0000000..da5990a --- /dev/null +++ b/unittest/Catch/include/internal/catch_run_context.hpp @@ -0,0 +1,359 @@ + /* + * Created by Phil on 22/10/2010. + * Copyright 2010 Two Blue Cubes Ltd. All rights reserved. + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + */ +#ifndef TWOBLUECUBES_CATCH_RUNNER_IMPL_HPP_INCLUDED +#define TWOBLUECUBES_CATCH_RUNNER_IMPL_HPP_INCLUDED + +#include "catch_interfaces_runner.h" +#include "catch_interfaces_reporter.h" +#include "catch_interfaces_exception.h" +#include "catch_config.hpp" +#include "catch_test_registry.hpp" +#include "catch_test_case_info.h" +#include "catch_capture.hpp" +#include "catch_totals.hpp" +#include "catch_test_spec.hpp" +#include "catch_test_case_tracker.hpp" +#include "catch_timer.h" +#include "catch_result_builder.h" +#include "catch_fatal_condition.hpp" + +#include <set> +#include <string> + +namespace Catch { + + class StreamRedirect { + + public: + StreamRedirect( std::ostream& stream, std::string& targetString ) + : m_stream( stream ), + m_prevBuf( stream.rdbuf() ), + m_targetString( targetString ) + { + stream.rdbuf( m_oss.rdbuf() ); + } + + ~StreamRedirect() { + m_targetString += m_oss.str(); + m_stream.rdbuf( m_prevBuf ); + } + + private: + std::ostream& m_stream; + std::streambuf* m_prevBuf; + std::ostringstream m_oss; + std::string& m_targetString; + }; + + /////////////////////////////////////////////////////////////////////////// + + class RunContext : public IResultCapture, public IRunner { + + RunContext( RunContext const& ); + void operator =( RunContext const& ); + + public: + + explicit RunContext( Ptr<IConfig const> const& _config, Ptr<IStreamingReporter> const& reporter ) + : m_runInfo( _config->name() ), + m_context( getCurrentMutableContext() ), + m_activeTestCase( CATCH_NULL ), + m_config( _config ), + m_reporter( reporter ) + { + m_context.setRunner( this ); + m_context.setConfig( m_config ); + m_context.setResultCapture( this ); + m_reporter->testRunStarting( m_runInfo ); + } + + virtual ~RunContext() { + m_reporter->testRunEnded( TestRunStats( m_runInfo, m_totals, aborting() ) ); + } + + void testGroupStarting( std::string const& testSpec, std::size_t groupIndex, std::size_t groupsCount ) { + m_reporter->testGroupStarting( GroupInfo( testSpec, groupIndex, groupsCount ) ); + } + void testGroupEnded( std::string const& testSpec, Totals const& totals, std::size_t groupIndex, std::size_t groupsCount ) { + m_reporter->testGroupEnded( TestGroupStats( GroupInfo( testSpec, groupIndex, groupsCount ), totals, aborting() ) ); + } + + Totals runTest( TestCase const& testCase ) { + Totals prevTotals = m_totals; + + std::string redirectedCout; + std::string redirectedCerr; + + TestCaseInfo testInfo = testCase.getTestCaseInfo(); + + m_reporter->testCaseStarting( testInfo ); + + m_activeTestCase = &testCase; + + + do { + m_trackerContext.startRun(); + do { + m_trackerContext.startCycle(); + m_testCaseTracker = &SectionTracker::acquire( m_trackerContext, testInfo.name ); + runCurrentTest( redirectedCout, redirectedCerr ); + } + while( !m_testCaseTracker->isSuccessfullyCompleted() && !aborting() ); + } + // !TBD: deprecated - this will be replaced by indexed trackers + while( getCurrentContext().advanceGeneratorsForCurrentTest() && !aborting() ); + + Totals deltaTotals = m_totals.delta( prevTotals ); + m_totals.testCases += deltaTotals.testCases; + m_reporter->testCaseEnded( TestCaseStats( testInfo, + deltaTotals, + redirectedCout, + redirectedCerr, + aborting() ) ); + + m_activeTestCase = CATCH_NULL; + m_testCaseTracker = CATCH_NULL; + + return deltaTotals; + } + + Ptr<IConfig const> config() const { + return m_config; + } + + private: // IResultCapture + + + virtual void assertionEnded( AssertionResult const& result ) { + if( result.getResultType() == ResultWas::Ok ) { + m_totals.assertions.passed++; + } + else if( !result.isOk() ) { + m_totals.assertions.failed++; + } + + if( m_reporter->assertionEnded( AssertionStats( result, m_messages, m_totals ) ) ) + m_messages.clear(); + + // Reset working state + m_lastAssertionInfo = AssertionInfo( "", m_lastAssertionInfo.lineInfo, "{Unknown expression after the reported line}" , m_lastAssertionInfo.resultDisposition ); + m_lastResult = result; + } + + virtual bool sectionStarted ( + SectionInfo const& sectionInfo, + Counts& assertions + ) + { + std::ostringstream oss; + oss << sectionInfo.name << "@" << sectionInfo.lineInfo; + + ITracker& sectionTracker = SectionTracker::acquire( m_trackerContext, oss.str() ); + if( !sectionTracker.isOpen() ) + return false; + m_activeSections.push_back( §ionTracker ); + + m_lastAssertionInfo.lineInfo = sectionInfo.lineInfo; + + m_reporter->sectionStarting( sectionInfo ); + + assertions = m_totals.assertions; + + return true; + } + bool testForMissingAssertions( Counts& assertions ) { + if( assertions.total() != 0 ) + return false; + if( !m_config->warnAboutMissingAssertions() ) + return false; + if( m_trackerContext.currentTracker().hasChildren() ) + return false; + m_totals.assertions.failed++; + assertions.failed++; + return true; + } + + virtual void sectionEnded( SectionEndInfo const& endInfo ) { + Counts assertions = m_totals.assertions - endInfo.prevAssertions; + bool missingAssertions = testForMissingAssertions( assertions ); + + if( !m_activeSections.empty() ) { + m_activeSections.back()->close(); + m_activeSections.pop_back(); + } + + m_reporter->sectionEnded( SectionStats( endInfo.sectionInfo, assertions, endInfo.durationInSeconds, missingAssertions ) ); + m_messages.clear(); + } + + virtual void sectionEndedEarly( SectionEndInfo const& endInfo ) { + if( m_unfinishedSections.empty() ) + m_activeSections.back()->fail(); + else + m_activeSections.back()->close(); + m_activeSections.pop_back(); + + m_unfinishedSections.push_back( endInfo ); + } + + virtual void pushScopedMessage( MessageInfo const& message ) { + m_messages.push_back( message ); + } + + virtual void popScopedMessage( MessageInfo const& message ) { + m_messages.erase( std::remove( m_messages.begin(), m_messages.end(), message ), m_messages.end() ); + } + + virtual std::string getCurrentTestName() const { + return m_activeTestCase + ? m_activeTestCase->getTestCaseInfo().name + : ""; + } + + virtual const AssertionResult* getLastResult() const { + return &m_lastResult; + } + + virtual void handleFatalErrorCondition( std::string const& message ) { + ResultBuilder resultBuilder = makeUnexpectedResultBuilder(); + resultBuilder.setResultType( ResultWas::FatalErrorCondition ); + resultBuilder << message; + resultBuilder.captureExpression(); + + handleUnfinishedSections(); + + // Recreate section for test case (as we will lose the one that was in scope) + TestCaseInfo const& testCaseInfo = m_activeTestCase->getTestCaseInfo(); + SectionInfo testCaseSection( testCaseInfo.lineInfo, testCaseInfo.name, testCaseInfo.description ); + + Counts assertions; + assertions.failed = 1; + SectionStats testCaseSectionStats( testCaseSection, assertions, 0, false ); + m_reporter->sectionEnded( testCaseSectionStats ); + + TestCaseInfo testInfo = m_activeTestCase->getTestCaseInfo(); + + Totals deltaTotals; + deltaTotals.testCases.failed = 1; + m_reporter->testCaseEnded( TestCaseStats( testInfo, + deltaTotals, + "", + "", + false ) ); + m_totals.testCases.failed++; + testGroupEnded( "", m_totals, 1, 1 ); + m_reporter->testRunEnded( TestRunStats( m_runInfo, m_totals, false ) ); + } + + public: + // !TBD We need to do this another way! + bool aborting() const { + return m_totals.assertions.failed == static_cast<std::size_t>( m_config->abortAfter() ); + } + + private: + + void runCurrentTest( std::string& redirectedCout, std::string& redirectedCerr ) { + TestCaseInfo const& testCaseInfo = m_activeTestCase->getTestCaseInfo(); + SectionInfo testCaseSection( testCaseInfo.lineInfo, testCaseInfo.name, testCaseInfo.description ); + m_reporter->sectionStarting( testCaseSection ); + Counts prevAssertions = m_totals.assertions; + double duration = 0; + try { + m_lastAssertionInfo = AssertionInfo( "TEST_CASE", testCaseInfo.lineInfo, "", ResultDisposition::Normal ); + + seedRng( *m_config ); + + Timer timer; + timer.start(); + if( m_reporter->getPreferences().shouldRedirectStdOut ) { + StreamRedirect coutRedir( Catch::cout(), redirectedCout ); + StreamRedirect cerrRedir( Catch::cerr(), redirectedCerr ); + invokeActiveTestCase(); + } + else { + invokeActiveTestCase(); + } + duration = timer.getElapsedSeconds(); + } + catch( TestFailureException& ) { + // This just means the test was aborted due to failure + } + catch(...) { + makeUnexpectedResultBuilder().useActiveException(); + } + m_testCaseTracker->close(); + handleUnfinishedSections(); + m_messages.clear(); + + Counts assertions = m_totals.assertions - prevAssertions; + bool missingAssertions = testForMissingAssertions( assertions ); + + if( testCaseInfo.okToFail() ) { + std::swap( assertions.failedButOk, assertions.failed ); + m_totals.assertions.failed -= assertions.failedButOk; + m_totals.assertions.failedButOk += assertions.failedButOk; + } + + SectionStats testCaseSectionStats( testCaseSection, assertions, duration, missingAssertions ); + m_reporter->sectionEnded( testCaseSectionStats ); + } + + void invokeActiveTestCase() { + FatalConditionHandler fatalConditionHandler; // Handle signals + m_activeTestCase->invoke(); + fatalConditionHandler.reset(); + } + + private: + + ResultBuilder makeUnexpectedResultBuilder() const { + return ResultBuilder( m_lastAssertionInfo.macroName.c_str(), + m_lastAssertionInfo.lineInfo, + m_lastAssertionInfo.capturedExpression.c_str(), + m_lastAssertionInfo.resultDisposition ); + } + + void handleUnfinishedSections() { + // If sections ended prematurely due to an exception we stored their + // infos here so we can tear them down outside the unwind process. + for( std::vector<SectionEndInfo>::const_reverse_iterator it = m_unfinishedSections.rbegin(), + itEnd = m_unfinishedSections.rend(); + it != itEnd; + ++it ) + sectionEnded( *it ); + m_unfinishedSections.clear(); + } + + TestRunInfo m_runInfo; + IMutableContext& m_context; + TestCase const* m_activeTestCase; + ITracker* m_testCaseTracker; + ITracker* m_currentSectionTracker; + AssertionResult m_lastResult; + + Ptr<IConfig const> m_config; + Totals m_totals; + Ptr<IStreamingReporter> m_reporter; + std::vector<MessageInfo> m_messages; + AssertionInfo m_lastAssertionInfo; + std::vector<SectionEndInfo> m_unfinishedSections; + std::vector<ITracker*> m_activeSections; + TrackerContext m_trackerContext; + }; + + IResultCapture& getResultCapture() { + if( IResultCapture* capture = getCurrentContext().getResultCapture() ) + return *capture; + else + throw std::logic_error( "No result capture instance" ); + } + +} // end namespace Catch + +#endif // TWOBLUECUBES_CATCH_RUNNER_IMPL_HPP_INCLUDED diff --git a/unittest/Catch/include/internal/catch_section.h b/unittest/Catch/include/internal/catch_section.h new file mode 100644 index 0000000..d8b3ae4 --- /dev/null +++ b/unittest/Catch/include/internal/catch_section.h @@ -0,0 +1,46 @@ +/* + * Created by Phil on 03/12/2013. + * Copyright 2013 Two Blue Cubes Ltd. All rights reserved. + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + */ +#ifndef TWOBLUECUBES_CATCH_SECTION_H_INCLUDED +#define TWOBLUECUBES_CATCH_SECTION_H_INCLUDED + +#include "catch_section_info.h" +#include "catch_totals.hpp" +#include "catch_timer.h" + +#include <string> + +namespace Catch { + + class Section : NonCopyable { + public: + Section( SectionInfo const& info ); + ~Section(); + + // This indicates whether the section should be executed or not + operator bool() const; + + private: + SectionInfo m_info; + + std::string m_name; + Counts m_assertions; + bool m_sectionIncluded; + Timer m_timer; + }; + +} // end namespace Catch + +#ifdef CATCH_CONFIG_VARIADIC_MACROS + #define INTERNAL_CATCH_SECTION( ... ) \ + if( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::SectionInfo( CATCH_INTERNAL_LINEINFO, __VA_ARGS__ ) ) +#else + #define INTERNAL_CATCH_SECTION( name, desc ) \ + if( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::SectionInfo( CATCH_INTERNAL_LINEINFO, name, desc ) ) +#endif + +#endif // TWOBLUECUBES_CATCH_SECTION_H_INCLUDED diff --git a/unittest/Catch/include/internal/catch_section.hpp b/unittest/Catch/include/internal/catch_section.hpp new file mode 100644 index 0000000..de65c4c --- /dev/null +++ b/unittest/Catch/include/internal/catch_section.hpp @@ -0,0 +1,52 @@ +/* + * Created by Phil on 03/11/2010. + * Copyright 2010 Two Blue Cubes Ltd. All rights reserved. + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + */ +#ifndef TWOBLUECUBES_CATCH_SECTION_HPP_INCLUDED +#define TWOBLUECUBES_CATCH_SECTION_HPP_INCLUDED + +#include "catch_section.h" +#include "catch_capture.hpp" +#include "catch_compiler_capabilities.h" +#include "catch_timer.h" + +namespace Catch { + + SectionInfo::SectionInfo + ( SourceLineInfo const& _lineInfo, + std::string const& _name, + std::string const& _description ) + : name( _name ), + description( _description ), + lineInfo( _lineInfo ) + {} + + Section::Section( SectionInfo const& info ) + : m_info( info ), + m_sectionIncluded( getResultCapture().sectionStarted( m_info, m_assertions ) ) + { + m_timer.start(); + } + + Section::~Section() { + if( m_sectionIncluded ) { + SectionEndInfo endInfo( m_info, m_assertions, m_timer.getElapsedSeconds() ); + if( std::uncaught_exception() ) + getResultCapture().sectionEndedEarly( endInfo ); + else + getResultCapture().sectionEnded( endInfo ); + } + } + + // This indicates whether the section should be executed or not + Section::operator bool() const { + return m_sectionIncluded; + } + + +} // end namespace Catch + +#endif // TWOBLUECUBES_CATCH_SECTION_HPP_INCLUDED diff --git a/unittest/Catch/include/internal/catch_section_info.h b/unittest/Catch/include/internal/catch_section_info.h new file mode 100644 index 0000000..00b6560 --- /dev/null +++ b/unittest/Catch/include/internal/catch_section_info.h @@ -0,0 +1,39 @@ +/* + * Created by Phil on 03/11/2010. + * Copyright 2010 Two Blue Cubes Ltd. All rights reserved. + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + */ +#ifndef TWOBLUECUBES_CATCH_SECTION_INFO_H_INCLUDED +#define TWOBLUECUBES_CATCH_SECTION_INFO_H_INCLUDED + +#include "catch_common.h" +#include "catch_totals.hpp" + +namespace Catch { + + struct SectionInfo { + SectionInfo + ( SourceLineInfo const& _lineInfo, + std::string const& _name, + std::string const& _description = std::string() ); + + std::string name; + std::string description; + SourceLineInfo lineInfo; + }; + + struct SectionEndInfo { + SectionEndInfo( SectionInfo const& _sectionInfo, Counts const& _prevAssertions, double _durationInSeconds ) + : sectionInfo( _sectionInfo ), prevAssertions( _prevAssertions ), durationInSeconds( _durationInSeconds ) + {} + + SectionInfo sectionInfo; + Counts prevAssertions; + double durationInSeconds; + }; + +} // end namespace Catch + +#endif // TWOBLUECUBES_CATCH_SECTION_INFO_H_INCLUDED diff --git a/unittest/Catch/include/internal/catch_section_info.hpp b/unittest/Catch/include/internal/catch_section_info.hpp new file mode 100644 index 0000000..6258a28 --- /dev/null +++ b/unittest/Catch/include/internal/catch_section_info.hpp @@ -0,0 +1,113 @@ +/* + * Created by Phil Nash on 4/5/2012 + * Copyright 2012 Two Blue Cubes Ltd. All rights reserved. + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + */ +#ifndef TWOBLUECUBES_CATCH_SECTION_INFO_HPP_INCLUDED +#define TWOBLUECUBES_CATCH_SECTION_INFO_HPP_INCLUDED + +#include "catch_common.h" + +#include <map> +#include <string> + +namespace Catch { + + class RunningSection { + public: + + typedef std::vector<RunningSection*> SubSections; + + enum State { + Root, + Unknown, + Branch, + TestedBranch, + TestedLeaf + }; + + RunningSection( RunningSection* parent, std::string const& name ) + : m_state( Unknown ), + m_parent( parent ), + m_name( name ) + {} + + RunningSection( std::string const& name ) + : m_state( Root ), + m_parent( CATCH_NULL ), + m_name( name ) + {} + + ~RunningSection() { + deleteAll( m_subSections ); + } + + std::string getName() const { + return m_name; + } + + bool shouldRun() const { + return m_state < TestedBranch; + } + + bool isBranch() const { + return m_state == Branch; + } + + const RunningSection* getParent() const { + return m_parent; + } + + bool hasUntestedSections() const { + if( m_state == Unknown ) + return true; + for( SubSections::const_iterator it = m_subSections.begin(); + it != m_subSections.end(); + ++it) + if( (*it)->hasUntestedSections() ) + return true; + return false; + } + + // Mutable methods: + + RunningSection* getParent() { + return m_parent; + } + + RunningSection* findOrAddSubSection( std::string const& name, bool& changed ) { + for( SubSections::const_iterator it = m_subSections.begin(); + it != m_subSections.end(); + ++it) + if( (*it)->getName() == name ) + return *it; + RunningSection* subSection = new RunningSection( this, name ); + m_subSections.push_back( subSection ); + m_state = Branch; + changed = true; + return subSection; + } + + bool ran() { + if( m_state >= Branch ) + return false; + m_state = TestedLeaf; + return true; + } + + void ranToCompletion() { + if( m_state == Branch && !hasUntestedSections() ) + m_state = TestedBranch; + } + + private: + State m_state; + RunningSection* m_parent; + std::string m_name; + SubSections m_subSections; + }; +} + +#endif // TWOBLUECUBES_CATCH_SECTION_INFO_HPP_INCLUDED diff --git a/unittest/Catch/include/internal/catch_stream.h b/unittest/Catch/include/internal/catch_stream.h new file mode 100644 index 0000000..5f22ad6 --- /dev/null +++ b/unittest/Catch/include/internal/catch_stream.h @@ -0,0 +1,63 @@ +/* + * Created by Phil on 2/12/2013. + * Copyright 2013 Two Blue Cubes Ltd. All rights reserved. + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + * + */ +#ifndef TWOBLUECUBES_CATCH_STREAM_H_INCLUDED +#define TWOBLUECUBES_CATCH_STREAM_H_INCLUDED + +#include "catch_compiler_capabilities.h" +#include "catch_streambuf.h" + +#include <streambuf> +#include <ostream> +#include <fstream> + +namespace Catch { + + std::ostream& cout(); + std::ostream& cerr(); + + + struct IStream { + virtual ~IStream() CATCH_NOEXCEPT; + virtual std::ostream& stream() const = 0; + }; + + class FileStream : public IStream { + mutable std::ofstream m_ofs; + public: + FileStream( std::string const& filename ); + virtual ~FileStream() CATCH_NOEXCEPT; + public: // IStream + virtual std::ostream& stream() const CATCH_OVERRIDE; + }; + + + class CoutStream : public IStream { + mutable std::ostream m_os; + public: + CoutStream(); + virtual ~CoutStream() CATCH_NOEXCEPT; + + public: // IStream + virtual std::ostream& stream() const CATCH_OVERRIDE; + }; + + + class DebugOutStream : public IStream { + std::auto_ptr<StreamBufBase> m_streamBuf; + mutable std::ostream m_os; + public: + DebugOutStream(); + virtual ~DebugOutStream() CATCH_NOEXCEPT; + + public: // IStream + virtual std::ostream& stream() const CATCH_OVERRIDE; + }; +} + +#endif // TWOBLUECUBES_CATCH_STREAM_H_INCLUDED diff --git a/unittest/Catch/include/internal/catch_stream.hpp b/unittest/Catch/include/internal/catch_stream.hpp new file mode 100644 index 0000000..2703df5 --- /dev/null +++ b/unittest/Catch/include/internal/catch_stream.hpp @@ -0,0 +1,109 @@ +/* + * Created by Phil on 17/01/2011. + * Copyright 2011 Two Blue Cubes Ltd. All rights reserved. + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + * + */ +#ifndef TWOBLUECUBES_CATCH_STREAM_HPP_INCLUDED +#define TWOBLUECUBES_CATCH_STREAM_HPP_INCLUDED + +#include "catch_stream.h" +#include "catch_debugger.h" + +#include <stdexcept> +#include <cstdio> +#include <iostream> + +namespace Catch { + + template<typename WriterF, size_t bufferSize=256> + class StreamBufImpl : public StreamBufBase { + char data[bufferSize]; + WriterF m_writer; + + public: + StreamBufImpl() { + setp( data, data + sizeof(data) ); + } + + ~StreamBufImpl() CATCH_NOEXCEPT { + sync(); + } + + private: + int overflow( int c ) { + sync(); + + if( c != EOF ) { + if( pbase() == epptr() ) + m_writer( std::string( 1, static_cast<char>( c ) ) ); + else + sputc( static_cast<char>( c ) ); + } + return 0; + } + + int sync() { + if( pbase() != pptr() ) { + m_writer( std::string( pbase(), static_cast<std::string::size_type>( pptr() - pbase() ) ) ); + setp( pbase(), epptr() ); + } + return 0; + } + }; + + /////////////////////////////////////////////////////////////////////////// + + + FileStream::FileStream( std::string const& filename ) { + m_ofs.open( filename.c_str() ); + if( m_ofs.fail() ) { + std::ostringstream oss; + oss << "Unable to open file: '" << filename << "'"; + throw std::domain_error( oss.str() ); + } + } + + std::ostream& FileStream::stream() const { + return m_ofs; + } + + struct OutputDebugWriter { + + void operator()( std::string const&str ) { + writeToDebugConsole( str ); + } + }; + + DebugOutStream::DebugOutStream() + : m_streamBuf( new StreamBufImpl<OutputDebugWriter>() ), + m_os( m_streamBuf.get() ) + {} + + std::ostream& DebugOutStream::stream() const { + return m_os; + } + + // Store the streambuf from cout up-front because + // cout may get redirected when running tests + CoutStream::CoutStream() + : m_os( Catch::cout().rdbuf() ) + {} + + std::ostream& CoutStream::stream() const { + return m_os; + } + +#ifndef CATCH_CONFIG_NOSTDOUT // If you #define this you must implement these functions + std::ostream& cout() { + return std::cout; + } + std::ostream& cerr() { + return std::cerr; + } +#endif +} + +#endif // TWOBLUECUBES_CATCH_STREAM_HPP_INCLUDED diff --git a/unittest/Catch/include/internal/catch_streambuf.h b/unittest/Catch/include/internal/catch_streambuf.h new file mode 100644 index 0000000..4f5e238 --- /dev/null +++ b/unittest/Catch/include/internal/catch_streambuf.h @@ -0,0 +1,23 @@ +/* + * Created by Phil on 27/11/2012. + * Copyright 2012 Two Blue Cubes Ltd. All rights reserved. + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + */ +#ifndef TWOBLUECUBES_CATCH_STREAMBUF_H_INCLUDED +#define TWOBLUECUBES_CATCH_STREAMBUF_H_INCLUDED + +#include "catch_compiler_capabilities.h" + +#include <streambuf> + +namespace Catch { + + class StreamBufBase : public std::streambuf { + public: + virtual ~StreamBufBase() CATCH_NOEXCEPT; + }; +} + +#endif // TWOBLUECUBES_CATCH_STREAMBUF_H_INCLUDED diff --git a/unittest/Catch/include/internal/catch_suppress_warnings.h b/unittest/Catch/include/internal/catch_suppress_warnings.h new file mode 100644 index 0000000..8f57b28 --- /dev/null +++ b/unittest/Catch/include/internal/catch_suppress_warnings.h @@ -0,0 +1,29 @@ +/* + * Copyright 2014 Two Blue Cubes Ltd + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + */ + +#ifdef __clang__ +# ifdef __ICC // icpc defines the __clang__ macro +# pragma warning(push) +# pragma warning(disable: 161 1682) +# else // __ICC +# pragma clang diagnostic ignored "-Wglobal-constructors" +# pragma clang diagnostic ignored "-Wvariadic-macros" +# pragma clang diagnostic ignored "-Wc99-extensions" +# pragma clang diagnostic ignored "-Wunused-variable" +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wpadded" +# pragma clang diagnostic ignored "-Wc++98-compat" +# pragma clang diagnostic ignored "-Wc++98-compat-pedantic" +# pragma clang diagnostic ignored "-Wswitch-enum" +# pragma clang diagnostic ignored "-Wcovered-switch-default" +# endif +#elif defined __GNUC__ +# pragma GCC diagnostic ignored "-Wvariadic-macros" +# pragma GCC diagnostic ignored "-Wunused-variable" +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wpadded" +#endif diff --git a/unittest/Catch/include/internal/catch_tag_alias.h b/unittest/Catch/include/internal/catch_tag_alias.h new file mode 100644 index 0000000..6dde74a --- /dev/null +++ b/unittest/Catch/include/internal/catch_tag_alias.h @@ -0,0 +1,32 @@ +/* + * Created by Phil on 27/6/2014. + * Copyright 2014 Two Blue Cubes Ltd. All rights reserved. + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + */ +#ifndef TWOBLUECUBES_CATCH_TAG_ALIAS_H_INCLUDED +#define TWOBLUECUBES_CATCH_TAG_ALIAS_H_INCLUDED + +#include "catch_common.h" + +#include <string> + +namespace Catch { + + struct TagAlias { + TagAlias( std::string _tag, SourceLineInfo _lineInfo ) : tag( _tag ), lineInfo( _lineInfo ) {} + + std::string tag; + SourceLineInfo lineInfo; + }; + + struct RegistrarForTagAliases { + RegistrarForTagAliases( char const* alias, char const* tag, SourceLineInfo const& lineInfo ); + }; + +} // end namespace Catch + +#endif // TWOBLUECUBES_CATCH_TAG_ALIAS_H_INCLUDED + +#define CATCH_REGISTER_TAG_ALIAS( alias, spec ) namespace{ Catch::RegistrarForTagAliases INTERNAL_CATCH_UNIQUE_NAME( AutoRegisterTagAlias )( alias, spec, CATCH_INTERNAL_LINEINFO ); } diff --git a/unittest/Catch/include/internal/catch_tag_alias_registry.h b/unittest/Catch/include/internal/catch_tag_alias_registry.h new file mode 100644 index 0000000..98c796e --- /dev/null +++ b/unittest/Catch/include/internal/catch_tag_alias_registry.h @@ -0,0 +1,31 @@ +/* + * Created by Phil on 27/6/2014. + * Copyright 2014 Two Blue Cubes Ltd. All rights reserved. + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + */ +#ifndef TWOBLUECUBES_CATCH_TAG_ALIAS_REGISTRY_H_INCLUDED +#define TWOBLUECUBES_CATCH_TAG_ALIAS_REGISTRY_H_INCLUDED + +#include "catch_interfaces_tag_alias_registry.h" + +#include <map> + +namespace Catch { + + class TagAliasRegistry : public ITagAliasRegistry { + public: + virtual ~TagAliasRegistry(); + virtual Option<TagAlias> find( std::string const& alias ) const; + virtual std::string expandAliases( std::string const& unexpandedTestSpec ) const; + void add( char const* alias, char const* tag, SourceLineInfo const& lineInfo ); + static TagAliasRegistry& get(); + + private: + std::map<std::string, TagAlias> m_registry; + }; + +} // end namespace Catch + +#endif // TWOBLUECUBES_CATCH_TAG_ALIAS_REGISTRY_H_INCLUDED diff --git a/unittest/Catch/include/internal/catch_tag_alias_registry.hpp b/unittest/Catch/include/internal/catch_tag_alias_registry.hpp new file mode 100644 index 0000000..e5ad11b --- /dev/null +++ b/unittest/Catch/include/internal/catch_tag_alias_registry.hpp @@ -0,0 +1,83 @@ +/* + * Created by Phil on 27/6/2014. + * Copyright 2014 Two Blue Cubes Ltd. All rights reserved. + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + */ +#ifndef TWOBLUECUBES_CATCH_TAG_ALIAS_REGISTRY_HPP_INCLUDED +#define TWOBLUECUBES_CATCH_TAG_ALIAS_REGISTRY_HPP_INCLUDED + +#include "catch_tag_alias_registry.h" +#include "catch_console_colour.hpp" + +#include <map> +#include <iostream> + +namespace Catch { + + TagAliasRegistry::~TagAliasRegistry() {} + + Option<TagAlias> TagAliasRegistry::find( std::string const& alias ) const { + std::map<std::string, TagAlias>::const_iterator it = m_registry.find( alias ); + if( it != m_registry.end() ) + return it->second; + else + return Option<TagAlias>(); + } + + std::string TagAliasRegistry::expandAliases( std::string const& unexpandedTestSpec ) const { + std::string expandedTestSpec = unexpandedTestSpec; + for( std::map<std::string, TagAlias>::const_iterator it = m_registry.begin(), itEnd = m_registry.end(); + it != itEnd; + ++it ) { + std::size_t pos = expandedTestSpec.find( it->first ); + if( pos != std::string::npos ) { + expandedTestSpec = expandedTestSpec.substr( 0, pos ) + + it->second.tag + + expandedTestSpec.substr( pos + it->first.size() ); + } + } + return expandedTestSpec; + } + + void TagAliasRegistry::add( char const* alias, char const* tag, SourceLineInfo const& lineInfo ) { + + if( !startsWith( alias, "[@" ) || !endsWith( alias, "]" ) ) { + std::ostringstream oss; + oss << "error: tag alias, \"" << alias << "\" is not of the form [@alias name].\n" << lineInfo; + throw std::domain_error( oss.str().c_str() ); + } + if( !m_registry.insert( std::make_pair( alias, TagAlias( tag, lineInfo ) ) ).second ) { + std::ostringstream oss; + oss << "error: tag alias, \"" << alias << "\" already registered.\n" + << "\tFirst seen at " << find(alias)->lineInfo << "\n" + << "\tRedefined at " << lineInfo; + throw std::domain_error( oss.str().c_str() ); + } + } + + TagAliasRegistry& TagAliasRegistry::get() { + static TagAliasRegistry instance; + return instance; + + } + + ITagAliasRegistry::~ITagAliasRegistry() {} + ITagAliasRegistry const& ITagAliasRegistry::get() { return TagAliasRegistry::get(); } + + + RegistrarForTagAliases::RegistrarForTagAliases( char const* alias, char const* tag, SourceLineInfo const& lineInfo ) { + try { + TagAliasRegistry::get().add( alias, tag, lineInfo ); + } + catch( std::exception& ex ) { + Colour colourGuard( Colour::Red ); + Catch::cerr() << ex.what() << std::endl; + exit(1); + } + } + +} // end namespace Catch + +#endif // TWOBLUECUBES_CATCH_TAG_ALIAS_REGISTRY_HPP_INCLUDED diff --git a/unittest/Catch/include/internal/catch_test_case_info.h b/unittest/Catch/include/internal/catch_test_case_info.h new file mode 100644 index 0000000..6ab1f37 --- /dev/null +++ b/unittest/Catch/include/internal/catch_test_case_info.h @@ -0,0 +1,92 @@ +/* + * Created by Phil on 29/10/2010. + * Copyright 2010 Two Blue Cubes Ltd. All rights reserved. + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + */ +#ifndef TWOBLUECUBES_CATCH_TEST_CASE_INFO_H_INCLUDED +#define TWOBLUECUBES_CATCH_TEST_CASE_INFO_H_INCLUDED + +#include "catch_common.h" +#include "catch_ptr.hpp" + +#include <string> +#include <set> + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wpadded" +#endif + +namespace Catch { + + struct ITestCase; + + struct TestCaseInfo { + enum SpecialProperties{ + None = 0, + IsHidden = 1 << 1, + ShouldFail = 1 << 2, + MayFail = 1 << 3, + Throws = 1 << 4 + }; + + TestCaseInfo( std::string const& _name, + std::string const& _className, + std::string const& _description, + std::set<std::string> const& _tags, + SourceLineInfo const& _lineInfo ); + + TestCaseInfo( TestCaseInfo const& other ); + + friend void setTags( TestCaseInfo& testCaseInfo, std::set<std::string> const& tags ); + + bool isHidden() const; + bool throws() const; + bool okToFail() const; + bool expectedToFail() const; + + std::string name; + std::string className; + std::string description; + std::set<std::string> tags; + std::set<std::string> lcaseTags; + std::string tagsAsString; + SourceLineInfo lineInfo; + SpecialProperties properties; + }; + + class TestCase : public TestCaseInfo { + public: + + TestCase( ITestCase* testCase, TestCaseInfo const& info ); + TestCase( TestCase const& other ); + + TestCase withName( std::string const& _newName ) const; + + void invoke() const; + + TestCaseInfo const& getTestCaseInfo() const; + + void swap( TestCase& other ); + bool operator == ( TestCase const& other ) const; + bool operator < ( TestCase const& other ) const; + TestCase& operator = ( TestCase const& other ); + + private: + Ptr<ITestCase> test; + }; + + TestCase makeTestCase( ITestCase* testCase, + std::string const& className, + std::string const& name, + std::string const& description, + SourceLineInfo const& lineInfo ); +} + +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + +#endif // TWOBLUECUBES_CATCH_TEST_CASE_INFO_H_INCLUDED diff --git a/unittest/Catch/include/internal/catch_test_case_info.hpp b/unittest/Catch/include/internal/catch_test_case_info.hpp new file mode 100644 index 0000000..90f5341 --- /dev/null +++ b/unittest/Catch/include/internal/catch_test_case_info.hpp @@ -0,0 +1,201 @@ +/* + * Created by Phil on 14/08/2012. + * Copyright 2012 Two Blue Cubes Ltd. All rights reserved. + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + */ +#ifndef TWOBLUECUBES_CATCH_TEST_CASE_INFO_HPP_INCLUDED +#define TWOBLUECUBES_CATCH_TEST_CASE_INFO_HPP_INCLUDED + +#include "catch_test_spec.hpp" +#include "catch_test_case_info.h" +#include "catch_interfaces_testcase.h" +#include "catch_common.h" + +namespace Catch { + + inline TestCaseInfo::SpecialProperties parseSpecialTag( std::string const& tag ) { + if( startsWith( tag, "." ) || + tag == "hide" || + tag == "!hide" ) + return TestCaseInfo::IsHidden; + else if( tag == "!throws" ) + return TestCaseInfo::Throws; + else if( tag == "!shouldfail" ) + return TestCaseInfo::ShouldFail; + else if( tag == "!mayfail" ) + return TestCaseInfo::MayFail; + else + return TestCaseInfo::None; + } + inline bool isReservedTag( std::string const& tag ) { + return parseSpecialTag( tag ) == TestCaseInfo::None && tag.size() > 0 && !isalnum( tag[0] ); + } + inline void enforceNotReservedTag( std::string const& tag, SourceLineInfo const& _lineInfo ) { + if( isReservedTag( tag ) ) { + { + Colour colourGuard( Colour::Red ); + Catch::cerr() + << "Tag name [" << tag << "] not allowed.\n" + << "Tag names starting with non alpha-numeric characters are reserved\n"; + } + { + Colour colourGuard( Colour::FileName ); + Catch::cerr() << _lineInfo << std::endl; + } + exit(1); + } + } + + TestCase makeTestCase( ITestCase* _testCase, + std::string const& _className, + std::string const& _name, + std::string const& _descOrTags, + SourceLineInfo const& _lineInfo ) + { + bool isHidden( startsWith( _name, "./" ) ); // Legacy support + + // Parse out tags + std::set<std::string> tags; + std::string desc, tag; + bool inTag = false; + for( std::size_t i = 0; i < _descOrTags.size(); ++i ) { + char c = _descOrTags[i]; + if( !inTag ) { + if( c == '[' ) + inTag = true; + else + desc += c; + } + else { + if( c == ']' ) { + TestCaseInfo::SpecialProperties prop = parseSpecialTag( tag ); + if( prop == TestCaseInfo::IsHidden ) + isHidden = true; + else if( prop == TestCaseInfo::None ) + enforceNotReservedTag( tag, _lineInfo ); + + tags.insert( tag ); + tag.clear(); + inTag = false; + } + else + tag += c; + } + } + if( isHidden ) { + tags.insert( "hide" ); + tags.insert( "." ); + } + + TestCaseInfo info( _name, _className, desc, tags, _lineInfo ); + return TestCase( _testCase, info ); + } + + void setTags( TestCaseInfo& testCaseInfo, std::set<std::string> const& tags ) + { + testCaseInfo.tags = tags; + testCaseInfo.lcaseTags.clear(); + + std::ostringstream oss; + for( std::set<std::string>::const_iterator it = tags.begin(), itEnd = tags.end(); it != itEnd; ++it ) { + oss << "[" << *it << "]"; + std::string lcaseTag = toLower( *it ); + testCaseInfo.properties = static_cast<TestCaseInfo::SpecialProperties>( testCaseInfo.properties | parseSpecialTag( lcaseTag ) ); + testCaseInfo.lcaseTags.insert( lcaseTag ); + } + testCaseInfo.tagsAsString = oss.str(); + } + + TestCaseInfo::TestCaseInfo( std::string const& _name, + std::string const& _className, + std::string const& _description, + std::set<std::string> const& _tags, + SourceLineInfo const& _lineInfo ) + : name( _name ), + className( _className ), + description( _description ), + lineInfo( _lineInfo ), + properties( None ) + { + setTags( *this, _tags ); + } + + TestCaseInfo::TestCaseInfo( TestCaseInfo const& other ) + : name( other.name ), + className( other.className ), + description( other.description ), + tags( other.tags ), + lcaseTags( other.lcaseTags ), + tagsAsString( other.tagsAsString ), + lineInfo( other.lineInfo ), + properties( other.properties ) + {} + + bool TestCaseInfo::isHidden() const { + return ( properties & IsHidden ) != 0; + } + bool TestCaseInfo::throws() const { + return ( properties & Throws ) != 0; + } + bool TestCaseInfo::okToFail() const { + return ( properties & (ShouldFail | MayFail ) ) != 0; + } + bool TestCaseInfo::expectedToFail() const { + return ( properties & (ShouldFail ) ) != 0; + } + + + TestCase::TestCase( ITestCase* testCase, TestCaseInfo const& info ) : TestCaseInfo( info ), test( testCase ) {} + + TestCase::TestCase( TestCase const& other ) + : TestCaseInfo( other ), + test( other.test ) + {} + + TestCase TestCase::withName( std::string const& _newName ) const { + TestCase other( *this ); + other.name = _newName; + return other; + } + + void TestCase::swap( TestCase& other ) { + test.swap( other.test ); + name.swap( other.name ); + className.swap( other.className ); + description.swap( other.description ); + tags.swap( other.tags ); + lcaseTags.swap( other.lcaseTags ); + tagsAsString.swap( other.tagsAsString ); + std::swap( TestCaseInfo::properties, static_cast<TestCaseInfo&>( other ).properties ); + std::swap( lineInfo, other.lineInfo ); + } + + void TestCase::invoke() const { + test->invoke(); + } + + bool TestCase::operator == ( TestCase const& other ) const { + return test.get() == other.test.get() && + name == other.name && + className == other.className; + } + + bool TestCase::operator < ( TestCase const& other ) const { + return name < other.name; + } + TestCase& TestCase::operator = ( TestCase const& other ) { + TestCase temp( other ); + swap( temp ); + return *this; + } + + TestCaseInfo const& TestCase::getTestCaseInfo() const + { + return *this; + } + +} // end namespace Catch + +#endif // TWOBLUECUBES_CATCH_TEST_CASE_INFO_HPP_INCLUDED diff --git a/unittest/Catch/include/internal/catch_test_case_registry_impl.hpp b/unittest/Catch/include/internal/catch_test_case_registry_impl.hpp new file mode 100644 index 0000000..a2b041a --- /dev/null +++ b/unittest/Catch/include/internal/catch_test_case_registry_impl.hpp @@ -0,0 +1,193 @@ +/* + * Created by Phil on 7/1/2011 + * Copyright 2010 Two Blue Cubes Ltd. All rights reserved. + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + */ +#ifndef TWOBLUECUBES_CATCH_TEST_CASE_REGISTRY_IMPL_HPP_INCLUDED +#define TWOBLUECUBES_CATCH_TEST_CASE_REGISTRY_IMPL_HPP_INCLUDED + +#include "catch_test_registry.hpp" +#include "catch_test_case_info.h" +#include "catch_test_spec.hpp" +#include "catch_context.h" + +#include <vector> +#include <set> +#include <sstream> +#include <iostream> +#include <algorithm> + +namespace Catch { + + struct LexSort { + bool operator() (TestCase i,TestCase j) const { return (i<j);} + }; + struct RandomNumberGenerator { + int operator()( int n ) const { return std::rand() % n; } + }; + + inline std::vector<TestCase> sortTests( IConfig const& config, std::vector<TestCase> const& unsortedTestCases ) { + + std::vector<TestCase> sorted = unsortedTestCases; + + switch( config.runOrder() ) { + case RunTests::InLexicographicalOrder: + std::sort( sorted.begin(), sorted.end(), LexSort() ); + break; + case RunTests::InRandomOrder: + { + seedRng( config ); + + RandomNumberGenerator rng; + std::random_shuffle( sorted.begin(), sorted.end(), rng ); + } + break; + case RunTests::InDeclarationOrder: + // already in declaration order + break; + } + return sorted; + } + bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config ) { + return testSpec.matches( testCase ) && ( config.allowThrows() || !testCase.throws() ); + } + + void enforceNoDuplicateTestCases( std::vector<TestCase> const& functions ) { + std::set<TestCase> seenFunctions; + for( std::vector<TestCase>::const_iterator it = functions.begin(), itEnd = functions.end(); + it != itEnd; + ++it ) { + std::pair<std::set<TestCase>::const_iterator, bool> prev = seenFunctions.insert( *it ); + if( !prev.second ){ + Catch::cerr() + << Colour( Colour::Red ) + << "error: TEST_CASE( \"" << it->name << "\" ) already defined.\n" + << "\tFirst seen at " << prev.first->getTestCaseInfo().lineInfo << "\n" + << "\tRedefined at " << it->getTestCaseInfo().lineInfo << std::endl; + exit(1); + } + } + } + + std::vector<TestCase> filterTests( std::vector<TestCase> const& testCases, TestSpec const& testSpec, IConfig const& config ) { + std::vector<TestCase> filtered; + filtered.reserve( testCases.size() ); + for( std::vector<TestCase>::const_iterator it = testCases.begin(), itEnd = testCases.end(); + it != itEnd; + ++it ) + if( matchTest( *it, testSpec, config ) ) + filtered.push_back( *it ); + return filtered; + } + std::vector<TestCase> const& getAllTestCasesSorted( IConfig const& config ) { + return getRegistryHub().getTestCaseRegistry().getAllTestsSorted( config ); + } + + class TestRegistry : public ITestCaseRegistry { + public: + TestRegistry() + : m_currentSortOrder( RunTests::InDeclarationOrder ), + m_unnamedCount( 0 ) + {} + virtual ~TestRegistry(); + + virtual void registerTest( TestCase const& testCase ) { + std::string name = testCase.getTestCaseInfo().name; + if( name == "" ) { + std::ostringstream oss; + oss << "Anonymous test case " << ++m_unnamedCount; + return registerTest( testCase.withName( oss.str() ) ); + } + m_functions.push_back( testCase ); + } + + virtual std::vector<TestCase> const& getAllTests() const { + return m_functions; + } + virtual std::vector<TestCase> const& getAllTestsSorted( IConfig const& config ) const { + if( m_sortedFunctions.empty() ) + enforceNoDuplicateTestCases( m_functions ); + + if( m_currentSortOrder != config.runOrder() || m_sortedFunctions.empty() ) { + m_sortedFunctions = sortTests( config, m_functions ); + m_currentSortOrder = config.runOrder(); + } + return m_sortedFunctions; + } + + private: + std::vector<TestCase> m_functions; + mutable RunTests::InWhatOrder m_currentSortOrder; + mutable std::vector<TestCase> m_sortedFunctions; + size_t m_unnamedCount; + std::ios_base::Init m_ostreamInit; // Forces cout/ cerr to be initialised + }; + + /////////////////////////////////////////////////////////////////////////// + + class FreeFunctionTestCase : public SharedImpl<ITestCase> { + public: + + FreeFunctionTestCase( TestFunction fun ) : m_fun( fun ) {} + + virtual void invoke() const { + m_fun(); + } + + private: + virtual ~FreeFunctionTestCase(); + + TestFunction m_fun; + }; + + inline std::string extractClassName( std::string const& classOrQualifiedMethodName ) { + std::string className = classOrQualifiedMethodName; + if( startsWith( className, "&" ) ) + { + std::size_t lastColons = className.rfind( "::" ); + std::size_t penultimateColons = className.rfind( "::", lastColons-1 ); + if( penultimateColons == std::string::npos ) + penultimateColons = 1; + className = className.substr( penultimateColons, lastColons-penultimateColons ); + } + return className; + } + + void registerTestCase + ( ITestCase* testCase, + char const* classOrQualifiedMethodName, + NameAndDesc const& nameAndDesc, + SourceLineInfo const& lineInfo ) { + + getMutableRegistryHub().registerTest + ( makeTestCase + ( testCase, + extractClassName( classOrQualifiedMethodName ), + nameAndDesc.name, + nameAndDesc.description, + lineInfo ) ); + } + void registerTestCaseFunction + ( TestFunction function, + SourceLineInfo const& lineInfo, + NameAndDesc const& nameAndDesc ) { + registerTestCase( new FreeFunctionTestCase( function ), "", nameAndDesc, lineInfo ); + } + + /////////////////////////////////////////////////////////////////////////// + + AutoReg::AutoReg + ( TestFunction function, + SourceLineInfo const& lineInfo, + NameAndDesc const& nameAndDesc ) { + registerTestCaseFunction( function, lineInfo, nameAndDesc ); + } + + AutoReg::~AutoReg() {} + +} // end namespace Catch + + +#endif // TWOBLUECUBES_CATCH_TEST_CASE_REGISTRY_IMPL_HPP_INCLUDED diff --git a/unittest/Catch/include/internal/catch_test_case_tracker.hpp b/unittest/Catch/include/internal/catch_test_case_tracker.hpp new file mode 100644 index 0000000..505c3ab --- /dev/null +++ b/unittest/Catch/include/internal/catch_test_case_tracker.hpp @@ -0,0 +1,316 @@ +/* + * Created by Phil Nash on 23/7/2013 + * Copyright 2013 Two Blue Cubes Ltd. All rights reserved. + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + */ +#ifndef TWOBLUECUBES_CATCH_TEST_CASE_TRACKER_HPP_INCLUDED +#define TWOBLUECUBES_CATCH_TEST_CASE_TRACKER_HPP_INCLUDED + +#include "catch_compiler_capabilities.h" +#include "catch_ptr.hpp" + +#include <map> +#include <string> +#include <assert.h> +#include <vector> + +namespace Catch { +namespace TestCaseTracking { + + struct ITracker : SharedImpl<> { + virtual ~ITracker(); + + // static queries + virtual std::string name() const = 0; + + // dynamic queries + virtual bool isComplete() const = 0; // Successfully completed or failed + virtual bool isSuccessfullyCompleted() const = 0; + virtual bool isOpen() const = 0; // Started but not complete + virtual bool hasChildren() const = 0; + + virtual ITracker& parent() = 0; + + // actions + virtual void close() = 0; // Successfully complete + virtual void fail() = 0; + virtual void markAsNeedingAnotherRun() = 0; + + virtual void addChild( Ptr<ITracker> const& child ) = 0; + virtual ITracker* findChild( std::string const& name ) = 0; + virtual void openChild() = 0; + }; + + class TrackerContext { + + enum RunState { + NotStarted, + Executing, + CompletedCycle + }; + + Ptr<ITracker> m_rootTracker; + ITracker* m_currentTracker; + RunState m_runState; + + public: + + static TrackerContext& instance() { + static TrackerContext s_instance; + return s_instance; + } + + TrackerContext() + : m_currentTracker( CATCH_NULL ), + m_runState( NotStarted ) + {} + + + ITracker& startRun(); + + void endRun() { + m_rootTracker.reset(); + m_currentTracker = CATCH_NULL; + m_runState = NotStarted; + } + + void startCycle() { + m_currentTracker = m_rootTracker.get(); + m_runState = Executing; + } + void completeCycle() { + m_runState = CompletedCycle; + } + + bool completedCycle() const { + return m_runState == CompletedCycle; + } + ITracker& currentTracker() { + return *m_currentTracker; + } + void setCurrentTracker( ITracker* tracker ) { + m_currentTracker = tracker; + } + }; + + class TrackerBase : public ITracker { + protected: + enum CycleState { + NotStarted, + Executing, + ExecutingChildren, + NeedsAnotherRun, + CompletedSuccessfully, + Failed + }; + class TrackerHasName { + std::string m_name; + public: + TrackerHasName( std::string const& name ) : m_name( name ) {} + bool operator ()( Ptr<ITracker> const& tracker ) { + return tracker->name() == m_name; + } + }; + typedef std::vector<Ptr<ITracker> > Children; + std::string m_name; + TrackerContext& m_ctx; + ITracker* m_parent; + Children m_children; + CycleState m_runState; + public: + TrackerBase( std::string const& name, TrackerContext& ctx, ITracker* parent ) + : m_name( name ), + m_ctx( ctx ), + m_parent( parent ), + m_runState( NotStarted ) + {} + virtual ~TrackerBase(); + + virtual std::string name() const CATCH_OVERRIDE { + return m_name; + } + virtual bool isComplete() const CATCH_OVERRIDE { + return m_runState == CompletedSuccessfully || m_runState == Failed; + } + virtual bool isSuccessfullyCompleted() const CATCH_OVERRIDE { + return m_runState == CompletedSuccessfully; + } + virtual bool isOpen() const CATCH_OVERRIDE { + return m_runState != NotStarted && !isComplete(); + } + virtual bool hasChildren() const CATCH_OVERRIDE { + return !m_children.empty(); + } + + + virtual void addChild( Ptr<ITracker> const& child ) CATCH_OVERRIDE { + m_children.push_back( child ); + } + + virtual ITracker* findChild( std::string const& name ) CATCH_OVERRIDE { + Children::const_iterator it = std::find_if( m_children.begin(), m_children.end(), TrackerHasName( name ) ); + return( it != m_children.end() ) + ? it->get() + : CATCH_NULL; + } + virtual ITracker& parent() CATCH_OVERRIDE { + assert( m_parent ); // Should always be non-null except for root + return *m_parent; + } + + virtual void openChild() CATCH_OVERRIDE { + if( m_runState != ExecutingChildren ) { + m_runState = ExecutingChildren; + if( m_parent ) + m_parent->openChild(); + } + } + void open() { + m_runState = Executing; + moveToThis(); + if( m_parent ) + m_parent->openChild(); + } + + virtual void close() CATCH_OVERRIDE { + + // Close any still open children (e.g. generators) + while( &m_ctx.currentTracker() != this ) + m_ctx.currentTracker().close(); + + switch( m_runState ) { + case NotStarted: + case CompletedSuccessfully: + case Failed: + throw std::logic_error( "Illogical state" ); + + case NeedsAnotherRun: + break;; + + case Executing: + m_runState = CompletedSuccessfully; + break; + case ExecutingChildren: + if( m_children.empty() || m_children.back()->isComplete() ) + m_runState = CompletedSuccessfully; + break; + + default: + throw std::logic_error( "Unexpected state" ); + } + moveToParent(); + m_ctx.completeCycle(); + } + virtual void fail() CATCH_OVERRIDE { + m_runState = Failed; + if( m_parent ) + m_parent->markAsNeedingAnotherRun(); + moveToParent(); + m_ctx.completeCycle(); + } + virtual void markAsNeedingAnotherRun() CATCH_OVERRIDE { + m_runState = NeedsAnotherRun; + } + private: + void moveToParent() { + assert( m_parent ); + m_ctx.setCurrentTracker( m_parent ); + } + void moveToThis() { + m_ctx.setCurrentTracker( this ); + } + }; + + class SectionTracker : public TrackerBase { + public: + SectionTracker( std::string const& name, TrackerContext& ctx, ITracker* parent ) + : TrackerBase( name, ctx, parent ) + {} + virtual ~SectionTracker(); + + static SectionTracker& acquire( TrackerContext& ctx, std::string const& name ) { + SectionTracker* section = CATCH_NULL; + + ITracker& currentTracker = ctx.currentTracker(); + if( ITracker* childTracker = currentTracker.findChild( name ) ) { + section = dynamic_cast<SectionTracker*>( childTracker ); + assert( section ); + } + else { + section = new SectionTracker( name, ctx, ¤tTracker ); + currentTracker.addChild( section ); + } + if( !ctx.completedCycle() && !section->isComplete() ) { + + section->open(); + } + return *section; + } + }; + + class IndexTracker : public TrackerBase { + int m_size; + int m_index; + public: + IndexTracker( std::string const& name, TrackerContext& ctx, ITracker* parent, int size ) + : TrackerBase( name, ctx, parent ), + m_size( size ), + m_index( -1 ) + {} + virtual ~IndexTracker(); + + static IndexTracker& acquire( TrackerContext& ctx, std::string const& name, int size ) { + IndexTracker* tracker = CATCH_NULL; + + ITracker& currentTracker = ctx.currentTracker(); + if( ITracker* childTracker = currentTracker.findChild( name ) ) { + tracker = dynamic_cast<IndexTracker*>( childTracker ); + assert( tracker ); + } + else { + tracker = new IndexTracker( name, ctx, ¤tTracker, size ); + currentTracker.addChild( tracker ); + } + + if( !ctx.completedCycle() && !tracker->isComplete() ) { + if( tracker->m_runState != ExecutingChildren && tracker->m_runState != NeedsAnotherRun ) + tracker->moveNext(); + tracker->open(); + } + + return *tracker; + } + + int index() const { return m_index; } + + void moveNext() { + m_index++; + m_children.clear(); + } + + virtual void close() CATCH_OVERRIDE { + TrackerBase::close(); + if( m_runState == CompletedSuccessfully && m_index < m_size-1 ) + m_runState = Executing; + } + }; + + inline ITracker& TrackerContext::startRun() { + m_rootTracker = new SectionTracker( "{root}", *this, CATCH_NULL ); + m_currentTracker = CATCH_NULL; + m_runState = Executing; + return *m_rootTracker; + } + +} // namespace TestCaseTracking + +using TestCaseTracking::ITracker; +using TestCaseTracking::TrackerContext; +using TestCaseTracking::SectionTracker; +using TestCaseTracking::IndexTracker; + +} // namespace Catch + +#endif // TWOBLUECUBES_CATCH_TEST_CASE_TRACKER_HPP_INCLUDED diff --git a/unittest/Catch/include/internal/catch_test_registry.hpp b/unittest/Catch/include/internal/catch_test_registry.hpp new file mode 100644 index 0000000..bd27ba0 --- /dev/null +++ b/unittest/Catch/include/internal/catch_test_registry.hpp @@ -0,0 +1,137 @@ +/* + * Created by Phil on 18/10/2010. + * Copyright 2010 Two Blue Cubes Ltd. All rights reserved. + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + */ +#ifndef TWOBLUECUBES_CATCH_TEST_REGISTRY_HPP_INCLUDED +#define TWOBLUECUBES_CATCH_TEST_REGISTRY_HPP_INCLUDED + +#include "catch_common.h" +#include "catch_interfaces_testcase.h" +#include "catch_compiler_capabilities.h" + +namespace Catch { + +template<typename C> +class MethodTestCase : public SharedImpl<ITestCase> { + +public: + MethodTestCase( void (C::*method)() ) : m_method( method ) {} + + virtual void invoke() const { + C obj; + (obj.*m_method)(); + } + +private: + virtual ~MethodTestCase() {} + + void (C::*m_method)(); +}; + +typedef void(*TestFunction)(); + +struct NameAndDesc { + NameAndDesc( const char* _name = "", const char* _description= "" ) + : name( _name ), description( _description ) + {} + + const char* name; + const char* description; +}; + +void registerTestCase + ( ITestCase* testCase, + char const* className, + NameAndDesc const& nameAndDesc, + SourceLineInfo const& lineInfo ); + +struct AutoReg { + + AutoReg + ( TestFunction function, + SourceLineInfo const& lineInfo, + NameAndDesc const& nameAndDesc ); + + template<typename C> + AutoReg + ( void (C::*method)(), + char const* className, + NameAndDesc const& nameAndDesc, + SourceLineInfo const& lineInfo ) { + + registerTestCase + ( new MethodTestCase<C>( method ), + className, + nameAndDesc, + lineInfo ); + } + + ~AutoReg(); + +private: + AutoReg( AutoReg const& ); + void operator= ( AutoReg const& ); +}; + +void registerTestCaseFunction + ( TestFunction function, + SourceLineInfo const& lineInfo, + NameAndDesc const& nameAndDesc ); + +} // end namespace Catch + +#ifdef CATCH_CONFIG_VARIADIC_MACROS + /////////////////////////////////////////////////////////////////////////////// + #define INTERNAL_CATCH_TESTCASE( ... ) \ + static void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )(); \ + namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( __VA_ARGS__ ) ); }\ + static void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )() + + /////////////////////////////////////////////////////////////////////////////// + #define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, ... ) \ + namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &QualifiedMethod, "&" #QualifiedMethod, Catch::NameAndDesc( __VA_ARGS__ ), CATCH_INTERNAL_LINEINFO ); } + + /////////////////////////////////////////////////////////////////////////////// + #define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, ... )\ + namespace{ \ + struct INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ) : ClassName{ \ + void test(); \ + }; \ + Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( &INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )::test, #ClassName, Catch::NameAndDesc( __VA_ARGS__ ), CATCH_INTERNAL_LINEINFO ); \ + } \ + void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )::test() + + /////////////////////////////////////////////////////////////////////////////// + #define INTERNAL_CATCH_REGISTER_TESTCASE( Function, ... ) \ + Catch::AutoReg( Function, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( __VA_ARGS__ ) ); + +#else + /////////////////////////////////////////////////////////////////////////////// + #define INTERNAL_CATCH_TESTCASE( Name, Desc ) \ + static void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )(); \ + namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( Name, Desc ) ); }\ + static void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )() + + /////////////////////////////////////////////////////////////////////////////// + #define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, Name, Desc ) \ + namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &QualifiedMethod, "&" #QualifiedMethod, Catch::NameAndDesc( Name, Desc ), CATCH_INTERNAL_LINEINFO ); } + + /////////////////////////////////////////////////////////////////////////////// + #define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, TestName, Desc )\ + namespace{ \ + struct INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ) : ClassName{ \ + void test(); \ + }; \ + Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( &INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )::test, #ClassName, Catch::NameAndDesc( TestName, Desc ), CATCH_INTERNAL_LINEINFO ); \ + } \ + void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )::test() + + /////////////////////////////////////////////////////////////////////////////// + #define INTERNAL_CATCH_REGISTER_TESTCASE( Function, Name, Desc ) \ + Catch::AutoReg( Function, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( Name, Desc ) ); +#endif + +#endif // TWOBLUECUBES_CATCH_TEST_REGISTRY_HPP_INCLUDED diff --git a/unittest/Catch/include/internal/catch_test_spec.hpp b/unittest/Catch/include/internal/catch_test_spec.hpp new file mode 100644 index 0000000..7e4ea9d --- /dev/null +++ b/unittest/Catch/include/internal/catch_test_spec.hpp @@ -0,0 +1,97 @@ +/* + * Created by Phil on 14/8/2012. + * Copyright 2010 Two Blue Cubes Ltd. All rights reserved. + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + */ +#ifndef TWOBLUECUBES_CATCH_TEST_SPEC_HPP_INCLUDED +#define TWOBLUECUBES_CATCH_TEST_SPEC_HPP_INCLUDED + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wpadded" +#endif + +#include "catch_wildcard_pattern.hpp" +#include "catch_test_case_info.h" + +#include <string> +#include <vector> + +namespace Catch { + + class TestSpec { + struct Pattern : SharedImpl<> { + virtual ~Pattern(); + virtual bool matches( TestCaseInfo const& testCase ) const = 0; + }; + class NamePattern : public Pattern { + public: + NamePattern( std::string const& name ) + : m_wildcardPattern( toLower( name ), CaseSensitive::No ) + {} + virtual ~NamePattern(); + virtual bool matches( TestCaseInfo const& testCase ) const { + return m_wildcardPattern.matches( toLower( testCase.name ) ); + } + private: + WildcardPattern m_wildcardPattern; + }; + + class TagPattern : public Pattern { + public: + TagPattern( std::string const& tag ) : m_tag( toLower( tag ) ) {} + virtual ~TagPattern(); + virtual bool matches( TestCaseInfo const& testCase ) const { + return testCase.lcaseTags.find( m_tag ) != testCase.lcaseTags.end(); + } + private: + std::string m_tag; + }; + + class ExcludedPattern : public Pattern { + public: + ExcludedPattern( Ptr<Pattern> const& underlyingPattern ) : m_underlyingPattern( underlyingPattern ) {} + virtual ~ExcludedPattern(); + virtual bool matches( TestCaseInfo const& testCase ) const { return !m_underlyingPattern->matches( testCase ); } + private: + Ptr<Pattern> m_underlyingPattern; + }; + + struct Filter { + std::vector<Ptr<Pattern> > m_patterns; + + bool matches( TestCaseInfo const& testCase ) const { + // All patterns in a filter must match for the filter to be a match + for( std::vector<Ptr<Pattern> >::const_iterator it = m_patterns.begin(), itEnd = m_patterns.end(); it != itEnd; ++it ) + if( !(*it)->matches( testCase ) ) + return false; + return true; + } + }; + + public: + bool hasFilters() const { + return !m_filters.empty(); + } + bool matches( TestCaseInfo const& testCase ) const { + // A TestSpec matches if any filter matches + for( std::vector<Filter>::const_iterator it = m_filters.begin(), itEnd = m_filters.end(); it != itEnd; ++it ) + if( it->matches( testCase ) ) + return true; + return false; + } + + private: + std::vector<Filter> m_filters; + + friend class TestSpecParser; + }; +} + +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + +#endif // TWOBLUECUBES_CATCH_TEST_SPEC_HPP_INCLUDED diff --git a/unittest/Catch/include/internal/catch_test_spec_parser.hpp b/unittest/Catch/include/internal/catch_test_spec_parser.hpp new file mode 100644 index 0000000..3f794c6 --- /dev/null +++ b/unittest/Catch/include/internal/catch_test_spec_parser.hpp @@ -0,0 +1,116 @@ +/* + * Created by Phil on 15/5/2013. + * Copyright 2014 Two Blue Cubes Ltd. All rights reserved. + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + */ +#ifndef TWOBLUECUBES_CATCH_TEST_SPEC_PARSER_HPP_INCLUDED +#define TWOBLUECUBES_CATCH_TEST_SPEC_PARSER_HPP_INCLUDED + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wpadded" +#endif + +#include "catch_test_spec.hpp" +#include "catch_interfaces_tag_alias_registry.h" + +namespace Catch { + + class TestSpecParser { + enum Mode{ None, Name, QuotedName, Tag }; + Mode m_mode; + bool m_exclusion; + std::size_t m_start, m_pos; + std::string m_arg; + TestSpec::Filter m_currentFilter; + TestSpec m_testSpec; + ITagAliasRegistry const* m_tagAliases; + + public: + TestSpecParser( ITagAliasRegistry const& tagAliases ) : m_tagAliases( &tagAliases ) {} + + TestSpecParser& parse( std::string const& arg ) { + m_mode = None; + m_exclusion = false; + m_start = std::string::npos; + m_arg = m_tagAliases->expandAliases( arg ); + for( m_pos = 0; m_pos < m_arg.size(); ++m_pos ) + visitChar( m_arg[m_pos] ); + if( m_mode == Name ) + addPattern<TestSpec::NamePattern>(); + return *this; + } + TestSpec testSpec() { + addFilter(); + return m_testSpec; + } + private: + void visitChar( char c ) { + if( m_mode == None ) { + switch( c ) { + case ' ': return; + case '~': m_exclusion = true; return; + case '[': return startNewMode( Tag, ++m_pos ); + case '"': return startNewMode( QuotedName, ++m_pos ); + default: startNewMode( Name, m_pos ); break; + } + } + if( m_mode == Name ) { + if( c == ',' ) { + addPattern<TestSpec::NamePattern>(); + addFilter(); + } + else if( c == '[' ) { + if( subString() == "exclude:" ) + m_exclusion = true; + else + addPattern<TestSpec::NamePattern>(); + startNewMode( Tag, ++m_pos ); + } + } + else if( m_mode == QuotedName && c == '"' ) + addPattern<TestSpec::NamePattern>(); + else if( m_mode == Tag && c == ']' ) + addPattern<TestSpec::TagPattern>(); + } + void startNewMode( Mode mode, std::size_t start ) { + m_mode = mode; + m_start = start; + } + std::string subString() const { return m_arg.substr( m_start, m_pos - m_start ); } + template<typename T> + void addPattern() { + std::string token = subString(); + if( startsWith( token, "exclude:" ) ) { + m_exclusion = true; + token = token.substr( 8 ); + } + if( !token.empty() ) { + Ptr<TestSpec::Pattern> pattern = new T( token ); + if( m_exclusion ) + pattern = new TestSpec::ExcludedPattern( pattern ); + m_currentFilter.m_patterns.push_back( pattern ); + } + m_exclusion = false; + m_mode = None; + } + void addFilter() { + if( !m_currentFilter.m_patterns.empty() ) { + m_testSpec.m_filters.push_back( m_currentFilter ); + m_currentFilter = TestSpec::Filter(); + } + } + }; + inline TestSpec parseTestSpec( std::string const& arg ) { + return TestSpecParser( ITagAliasRegistry::get() ).parse( arg ).testSpec(); + } + +} // namespace Catch + +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + +#endif // TWOBLUECUBES_CATCH_TEST_SPEC_PARSER_HPP_INCLUDED diff --git a/unittest/Catch/include/internal/catch_text.h b/unittest/Catch/include/internal/catch_text.h new file mode 100644 index 0000000..b66751f --- /dev/null +++ b/unittest/Catch/include/internal/catch_text.h @@ -0,0 +1,24 @@ +/* + * Created by Phil on 10/2/2014. + * Copyright 2014 Two Blue Cubes Ltd. All rights reserved. + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + */ +#ifndef TWOBLUECUBES_CATCH_TEXT_H_INCLUDED +#define TWOBLUECUBES_CATCH_TEXT_H_INCLUDED + +#include "catch_config.hpp" + +#define TBC_TEXT_FORMAT_CONSOLE_WIDTH CATCH_CONFIG_CONSOLE_WIDTH + +#define CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE Catch +#include "../external/tbc_text_format.h" +#undef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE + +namespace Catch { + using Tbc::Text; + using Tbc::TextAttributes; +} + +#endif // TWOBLUECUBES_CATCH_TEXT_H_INCLUDED diff --git a/unittest/Catch/include/internal/catch_timer.h b/unittest/Catch/include/internal/catch_timer.h new file mode 100644 index 0000000..22e9e63 --- /dev/null +++ b/unittest/Catch/include/internal/catch_timer.h @@ -0,0 +1,35 @@ +/* + * Created by Phil on 05/08/2013. + * Copyright 2013 Two Blue Cubes Ltd. All rights reserved. + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + */ +#ifndef TWOBLUECUBES_CATCH_TIMER_H_INCLUDED +#define TWOBLUECUBES_CATCH_TIMER_H_INCLUDED + +#include "catch_platform.h" + +#ifdef CATCH_PLATFORM_WINDOWS +typedef unsigned long long uint64_t; +#else +#include <stdint.h> +#endif + +namespace Catch { + + class Timer { + public: + Timer() : m_ticks( 0 ) {} + void start(); + unsigned int getElapsedMicroseconds() const; + unsigned int getElapsedMilliseconds() const; + double getElapsedSeconds() const; + + private: + uint64_t m_ticks; + }; + +} // namespace Catch + +#endif // TWOBLUECUBES_CATCH_TIMER_H_INCLUDED diff --git a/unittest/Catch/include/internal/catch_timer.hpp b/unittest/Catch/include/internal/catch_timer.hpp new file mode 100644 index 0000000..2ba709e --- /dev/null +++ b/unittest/Catch/include/internal/catch_timer.hpp @@ -0,0 +1,63 @@ +/* + * Created by Phil on 05/08/2013. + * Copyright 2013 Two Blue Cubes Ltd. All rights reserved. + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + */ + +#include "catch_timer.h" +#include "catch_platform.h" + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wc++11-long-long" +#endif + +#ifdef CATCH_PLATFORM_WINDOWS +#include <windows.h> +#else +#include <sys/time.h> +#endif + +namespace Catch { + + namespace { +#ifdef CATCH_PLATFORM_WINDOWS + uint64_t getCurrentTicks() { + static uint64_t hz=0, hzo=0; + if (!hz) { + QueryPerformanceFrequency( reinterpret_cast<LARGE_INTEGER*>( &hz ) ); + QueryPerformanceCounter( reinterpret_cast<LARGE_INTEGER*>( &hzo ) ); + } + uint64_t t; + QueryPerformanceCounter( reinterpret_cast<LARGE_INTEGER*>( &t ) ); + return ((t-hzo)*1000000)/hz; + } +#else + uint64_t getCurrentTicks() { + timeval t; + gettimeofday(&t,CATCH_NULL); + return static_cast<uint64_t>( t.tv_sec ) * 1000000ull + static_cast<uint64_t>( t.tv_usec ); + } +#endif + } + + void Timer::start() { + m_ticks = getCurrentTicks(); + } + unsigned int Timer::getElapsedMicroseconds() const { + return static_cast<unsigned int>(getCurrentTicks() - m_ticks); + } + unsigned int Timer::getElapsedMilliseconds() const { + return static_cast<unsigned int>(getElapsedMicroseconds()/1000); + } + double Timer::getElapsedSeconds() const { + return getElapsedMicroseconds()/1000000.0; + } + +} // namespace Catch + +#ifdef __clang__ +#pragma clang diagnostic pop +#endif diff --git a/unittest/Catch/include/internal/catch_tostring.h b/unittest/Catch/include/internal/catch_tostring.h new file mode 100644 index 0000000..e6f7ec9 --- /dev/null +++ b/unittest/Catch/include/internal/catch_tostring.h @@ -0,0 +1,269 @@ +/* + * Created by Phil on 8/5/2012. + * Copyright 2012 Two Blue Cubes Ltd. All rights reserved. + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + */ +#ifndef TWOBLUECUBES_CATCH_TOSTRING_H_INCLUDED +#define TWOBLUECUBES_CATCH_TOSTRING_H_INCLUDED + +#include "catch_common.h" + +#include <sstream> +#include <iomanip> +#include <limits> +#include <vector> +#include <cstddef> + +#ifdef __OBJC__ +#include "catch_objc_arc.hpp" +#endif + +#ifdef CATCH_CONFIG_CPP11_TUPLE +#include <tuple> +#endif + +#ifdef CATCH_CONFIG_CPP11_IS_ENUM +#include <type_traits> +#endif + +namespace Catch { + +// Why we're here. +template<typename T> +std::string toString( T const& value ); + +// Built in overloads + +std::string toString( std::string const& value ); +std::string toString( std::wstring const& value ); +std::string toString( const char* const value ); +std::string toString( char* const value ); +std::string toString( const wchar_t* const value ); +std::string toString( wchar_t* const value ); +std::string toString( int value ); +std::string toString( unsigned long value ); +std::string toString( unsigned int value ); +std::string toString( const double value ); +std::string toString( const float value ); +std::string toString( bool value ); +std::string toString( char value ); +std::string toString( signed char value ); +std::string toString( unsigned char value ); + +#ifdef CATCH_CONFIG_CPP11_LONG_LONG +std::string toString( long long value ); +std::string toString( unsigned long long value ); +#endif + +#ifdef CATCH_CONFIG_CPP11_NULLPTR +std::string toString( std::nullptr_t ); +#endif + +#ifdef __OBJC__ + std::string toString( NSString const * const& nsstring ); + std::string toString( NSString * CATCH_ARC_STRONG const& nsstring ); + std::string toString( NSObject* const& nsObject ); +#endif + + +namespace Detail { + + extern const std::string unprintableString; + + struct BorgType { + template<typename T> BorgType( T const& ); + }; + + struct TrueType { char sizer[1]; }; + struct FalseType { char sizer[2]; }; + + TrueType& testStreamable( std::ostream& ); + FalseType testStreamable( FalseType ); + + FalseType operator<<( std::ostream const&, BorgType const& ); + + template<typename T> + struct IsStreamInsertable { + static std::ostream &s; + static T const&t; + enum { value = sizeof( testStreamable(s << t) ) == sizeof( TrueType ) }; + }; + +#if defined(CATCH_CONFIG_CPP11_IS_ENUM) + template<typename T, + bool IsEnum = std::is_enum<T>::value + > + struct EnumStringMaker + { + static std::string convert( T const& ) { return unprintableString; } + }; + + template<typename T> + struct EnumStringMaker<T,true> + { + static std::string convert( T const& v ) + { + return ::Catch::toString( + static_cast<typename std::underlying_type<T>::type>(v) + ); + } + }; +#endif + template<bool C> + struct StringMakerBase { +#if defined(CATCH_CONFIG_CPP11_IS_ENUM) + template<typename T> + static std::string convert( T const& v ) + { + return EnumStringMaker<T>::convert( v ); + } +#else + template<typename T> + static std::string convert( T const& ) { return unprintableString; } +#endif + }; + + template<> + struct StringMakerBase<true> { + template<typename T> + static std::string convert( T const& _value ) { + std::ostringstream oss; + oss << _value; + return oss.str(); + } + }; + + std::string rawMemoryToString( const void *object, std::size_t size ); + + template<typename T> + inline std::string rawMemoryToString( const T& object ) { + return rawMemoryToString( &object, sizeof(object) ); + } + +} // end namespace Detail + +template<typename T> +struct StringMaker : + Detail::StringMakerBase<Detail::IsStreamInsertable<T>::value> {}; + +template<typename T> +struct StringMaker<T*> { + template<typename U> + static std::string convert( U* p ) { + if( !p ) + return "NULL"; + else + return Detail::rawMemoryToString( p ); + } +}; + +template<typename R, typename C> +struct StringMaker<R C::*> { + static std::string convert( R C::* p ) { + if( !p ) + return "NULL"; + else + return Detail::rawMemoryToString( p ); + } +}; + +namespace Detail { + template<typename InputIterator> + std::string rangeToString( InputIterator first, InputIterator last ); +} + +//template<typename T, typename Allocator> +//struct StringMaker<std::vector<T, Allocator> > { +// static std::string convert( std::vector<T,Allocator> const& v ) { +// return Detail::rangeToString( v.begin(), v.end() ); +// } +//}; + +template<typename T, typename Allocator> +std::string toString( std::vector<T,Allocator> const& v ) { + return Detail::rangeToString( v.begin(), v.end() ); +} + + +#ifdef CATCH_CONFIG_CPP11_TUPLE + +// toString for tuples +namespace TupleDetail { + template< + typename Tuple, + std::size_t N = 0, + bool = (N < std::tuple_size<Tuple>::value) + > + struct ElementPrinter { + static void print( const Tuple& tuple, std::ostream& os ) + { + os << ( N ? ", " : " " ) + << Catch::toString(std::get<N>(tuple)); + ElementPrinter<Tuple,N+1>::print(tuple,os); + } + }; + + template< + typename Tuple, + std::size_t N + > + struct ElementPrinter<Tuple,N,false> { + static void print( const Tuple&, std::ostream& ) {} + }; + +} + +template<typename ...Types> +struct StringMaker<std::tuple<Types...>> { + + static std::string convert( const std::tuple<Types...>& tuple ) + { + std::ostringstream os; + os << '{'; + TupleDetail::ElementPrinter<std::tuple<Types...>>::print( tuple, os ); + os << " }"; + return os.str(); + } +}; +#endif // CATCH_CONFIG_CPP11_TUPLE + +namespace Detail { + template<typename T> + std::string makeString( T const& value ) { + return StringMaker<T>::convert( value ); + } +} // end namespace Detail + +/// \brief converts any type to a string +/// +/// The default template forwards on to ostringstream - except when an +/// ostringstream overload does not exist - in which case it attempts to detect +/// that and writes {?}. +/// Overload (not specialise) this template for custom typs that you don't want +/// to provide an ostream overload for. +template<typename T> +std::string toString( T const& value ) { + return StringMaker<T>::convert( value ); +} + + + namespace Detail { + template<typename InputIterator> + std::string rangeToString( InputIterator first, InputIterator last ) { + std::ostringstream oss; + oss << "{ "; + if( first != last ) { + oss << Catch::toString( *first ); + for( ++first ; first != last ; ++first ) + oss << ", " << Catch::toString( *first ); + } + oss << " }"; + return oss.str(); + } +} + +} // end namespace Catch + +#endif // TWOBLUECUBES_CATCH_TOSTRING_H_INCLUDED diff --git a/unittest/Catch/include/internal/catch_tostring.hpp b/unittest/Catch/include/internal/catch_tostring.hpp new file mode 100644 index 0000000..0a20ee2 --- /dev/null +++ b/unittest/Catch/include/internal/catch_tostring.hpp @@ -0,0 +1,203 @@ +/* + * Created by Phil on 23/4/2014. + * Copyright 2014 Two Blue Cubes Ltd. All rights reserved. + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + */ +#ifndef TWOBLUECUBES_CATCH_TOSTRING_HPP_INCLUDED +#define TWOBLUECUBES_CATCH_TOSTRING_HPP_INCLUDED + +#include "catch_tostring.h" +#include "catch_interfaces_config.h" + +namespace Catch { + +namespace Detail { + + const std::string unprintableString = "{?}"; + + namespace { + const int hexThreshold = 255; + + struct Endianness { + enum Arch { Big, Little }; + + static Arch which() { + union _{ + int asInt; + char asChar[sizeof (int)]; + } u; + + u.asInt = 1; + return ( u.asChar[sizeof(int)-1] == 1 ) ? Big : Little; + } + }; + } + + std::string rawMemoryToString( const void *object, std::size_t size ) + { + // Reverse order for little endian architectures + int i = 0, end = static_cast<int>( size ), inc = 1; + if( Endianness::which() == Endianness::Little ) { + i = end-1; + end = inc = -1; + } + + unsigned char const *bytes = static_cast<unsigned char const *>(object); + std::ostringstream os; + os << "0x" << std::setfill('0') << std::hex; + for( ; i != end; i += inc ) + os << std::setw(2) << static_cast<unsigned>(bytes[i]); + return os.str(); + } +} + +std::string toString( std::string const& value ) { + std::string s = value; + if( getCurrentContext().getConfig()->showInvisibles() ) { + for(size_t i = 0; i < s.size(); ++i ) { + std::string subs; + switch( s[i] ) { + case '\n': subs = "\\n"; break; + case '\t': subs = "\\t"; break; + default: break; + } + if( !subs.empty() ) { + s = s.substr( 0, i ) + subs + s.substr( i+1 ); + ++i; + } + } + } + return "\"" + s + "\""; +} +std::string toString( std::wstring const& value ) { + + std::string s; + s.reserve( value.size() ); + for(size_t i = 0; i < value.size(); ++i ) + s += value[i] <= 0xff ? static_cast<char>( value[i] ) : '?'; + return Catch::toString( s ); +} + +std::string toString( const char* const value ) { + return value ? Catch::toString( std::string( value ) ) : std::string( "{null string}" ); +} + +std::string toString( char* const value ) { + return Catch::toString( static_cast<const char*>( value ) ); +} + +std::string toString( const wchar_t* const value ) +{ + return value ? Catch::toString( std::wstring(value) ) : std::string( "{null string}" ); +} + +std::string toString( wchar_t* const value ) +{ + return Catch::toString( static_cast<const wchar_t*>( value ) ); +} + +std::string toString( int value ) { + std::ostringstream oss; + oss << value; + if( value > Detail::hexThreshold ) + oss << " (0x" << std::hex << value << ")"; + return oss.str(); +} + +std::string toString( unsigned long value ) { + std::ostringstream oss; + oss << value; + if( value > Detail::hexThreshold ) + oss << " (0x" << std::hex << value << ")"; + return oss.str(); +} + +std::string toString( unsigned int value ) { + return Catch::toString( static_cast<unsigned long>( value ) ); +} + +template<typename T> +std::string fpToString( T value, int precision ) { + std::ostringstream oss; + oss << std::setprecision( precision ) + << std::fixed + << value; + std::string d = oss.str(); + std::size_t i = d.find_last_not_of( '0' ); + if( i != std::string::npos && i != d.size()-1 ) { + if( d[i] == '.' ) + i++; + d = d.substr( 0, i+1 ); + } + return d; +} + +std::string toString( const double value ) { + return fpToString( value, 10 ); +} +std::string toString( const float value ) { + return fpToString( value, 5 ) + "f"; +} + +std::string toString( bool value ) { + return value ? "true" : "false"; +} + +std::string toString( char value ) { + return value < ' ' + ? toString( static_cast<unsigned int>( value ) ) + : Detail::makeString( value ); +} + +std::string toString( signed char value ) { + return toString( static_cast<char>( value ) ); +} + +std::string toString( unsigned char value ) { + return toString( static_cast<char>( value ) ); +} + +#ifdef CATCH_CONFIG_CPP11_LONG_LONG +std::string toString( long long value ) { + std::ostringstream oss; + oss << value; + if( value > Detail::hexThreshold ) + oss << " (0x" << std::hex << value << ")"; + return oss.str(); +} +std::string toString( unsigned long long value ) { + std::ostringstream oss; + oss << value; + if( value > Detail::hexThreshold ) + oss << " (0x" << std::hex << value << ")"; + return oss.str(); +} +#endif + +#ifdef CATCH_CONFIG_CPP11_NULLPTR +std::string toString( std::nullptr_t ) { + return "nullptr"; +} +#endif + +#ifdef __OBJC__ + std::string toString( NSString const * const& nsstring ) { + if( !nsstring ) + return "nil"; + return "@" + toString([nsstring UTF8String]); + } + std::string toString( NSString * CATCH_ARC_STRONG const& nsstring ) { + if( !nsstring ) + return "nil"; + return "@" + toString([nsstring UTF8String]); + } + std::string toString( NSObject* const& nsObject ) { + return toString( [nsObject description] ); + } +#endif + +} // end namespace Catch + +#endif // TWOBLUECUBES_CATCH_TOSTRING_HPP_INCLUDED diff --git a/unittest/Catch/include/internal/catch_totals.hpp b/unittest/Catch/include/internal/catch_totals.hpp new file mode 100644 index 0000000..551e294 --- /dev/null +++ b/unittest/Catch/include/internal/catch_totals.hpp @@ -0,0 +1,78 @@ +/* + * Created by Phil Nash on 23/02/2012. + * Copyright (c) 2012 Two Blue Cubes Ltd. All rights reserved. + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + */ +#ifndef TWOBLUECUBES_CATCH_TOTALS_HPP_INCLUDED +#define TWOBLUECUBES_CATCH_TOTALS_HPP_INCLUDED + +#include <cstddef> + +namespace Catch { + + struct Counts { + Counts() : passed( 0 ), failed( 0 ), failedButOk( 0 ) {} + + Counts operator - ( Counts const& other ) const { + Counts diff; + diff.passed = passed - other.passed; + diff.failed = failed - other.failed; + diff.failedButOk = failedButOk - other.failedButOk; + return diff; + } + Counts& operator += ( Counts const& other ) { + passed += other.passed; + failed += other.failed; + failedButOk += other.failedButOk; + return *this; + } + + std::size_t total() const { + return passed + failed + failedButOk; + } + bool allPassed() const { + return failed == 0 && failedButOk == 0; + } + bool allOk() const { + return failed == 0; + } + + std::size_t passed; + std::size_t failed; + std::size_t failedButOk; + }; + + struct Totals { + + Totals operator - ( Totals const& other ) const { + Totals diff; + diff.assertions = assertions - other.assertions; + diff.testCases = testCases - other.testCases; + return diff; + } + + Totals delta( Totals const& prevTotals ) const { + Totals diff = *this - prevTotals; + if( diff.assertions.failed > 0 ) + ++diff.testCases.failed; + else if( diff.assertions.failedButOk > 0 ) + ++diff.testCases.failedButOk; + else + ++diff.testCases.passed; + return diff; + } + + Totals& operator += ( Totals const& other ) { + assertions += other.assertions; + testCases += other.testCases; + return *this; + } + + Counts assertions; + Counts testCases; + }; +} + +#endif // TWOBLUECUBES_CATCH_TOTALS_HPP_INCLUDED diff --git a/unittest/Catch/include/internal/catch_version.h b/unittest/Catch/include/internal/catch_version.h new file mode 100644 index 0000000..1a79c5c --- /dev/null +++ b/unittest/Catch/include/internal/catch_version.h @@ -0,0 +1,38 @@ +/* + * Created by Phil on 13/11/2012. + * Copyright 2012 Two Blue Cubes Ltd. All rights reserved. + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + */ +#ifndef TWOBLUECUBES_CATCH_VERSION_H_INCLUDED +#define TWOBLUECUBES_CATCH_VERSION_H_INCLUDED + +namespace Catch { + + // Versioning information + struct Version { + Version( unsigned int _majorVersion, + unsigned int _minorVersion, + unsigned int _patchNumber, + std::string const& _branchName, + unsigned int _buildNumber ); + + unsigned int const majorVersion; + unsigned int const minorVersion; + unsigned int const patchNumber; + + // buildNumber is only used if branchName is not null + std::string const branchName; + unsigned int const buildNumber; + + friend std::ostream& operator << ( std::ostream& os, Version const& version ); + + private: + void operator=( Version const& ); + }; + + extern Version libraryVersion; +} + +#endif // TWOBLUECUBES_CATCH_VERSION_H_INCLUDED diff --git a/unittest/Catch/include/internal/catch_version.hpp b/unittest/Catch/include/internal/catch_version.hpp new file mode 100644 index 0000000..7aa9353 --- /dev/null +++ b/unittest/Catch/include/internal/catch_version.hpp @@ -0,0 +1,44 @@ +/* + * Created by Phil on 14/11/2012. + * Copyright 2012 Two Blue Cubes Ltd. All rights reserved. + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + */ +#ifndef TWOBLUECUBES_CATCH_VERSION_HPP_INCLUDED +#define TWOBLUECUBES_CATCH_VERSION_HPP_INCLUDED + +#include "catch_version.h" + +namespace Catch { + + Version::Version + ( unsigned int _majorVersion, + unsigned int _minorVersion, + unsigned int _patchNumber, + std::string const& _branchName, + unsigned int _buildNumber ) + : majorVersion( _majorVersion ), + minorVersion( _minorVersion ), + patchNumber( _patchNumber ), + branchName( _branchName ), + buildNumber( _buildNumber ) + {} + + std::ostream& operator << ( std::ostream& os, Version const& version ) { + os << version.majorVersion << "." + << version.minorVersion << "." + << version.patchNumber; + + if( !version.branchName.empty() ) { + os << "-" << version.branchName + << "." << version.buildNumber; + } + return os; + } + + Version libraryVersion( 1, 3, 5, "", 0 ); + +} + +#endif // TWOBLUECUBES_CATCH_VERSION_HPP_INCLUDED diff --git a/unittest/Catch/include/internal/catch_wildcard_pattern.hpp b/unittest/Catch/include/internal/catch_wildcard_pattern.hpp new file mode 100644 index 0000000..cd8b07e --- /dev/null +++ b/unittest/Catch/include/internal/catch_wildcard_pattern.hpp @@ -0,0 +1,71 @@ +/* + * Created by Phil on 13/7/2015. + * Copyright 2015 Two Blue Cubes Ltd. All rights reserved. + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + */ +#ifndef TWOBLUECUBES_CATCH_WILDCARD_PATTERN_HPP_INCLUDED +#define TWOBLUECUBES_CATCH_WILDCARD_PATTERN_HPP_INCLUDED + +#include "catch_common.h" + +namespace Catch +{ + class WildcardPattern { + enum WildcardPosition { + NoWildcard = 0, + WildcardAtStart = 1, + WildcardAtEnd = 2, + WildcardAtBothEnds = WildcardAtStart | WildcardAtEnd + }; + + public: + + WildcardPattern( std::string const& pattern, CaseSensitive::Choice caseSensitivity ) + : m_caseSensitivity( caseSensitivity ), + m_wildcard( NoWildcard ), + m_pattern( adjustCase( pattern ) ) + { + if( startsWith( m_pattern, "*" ) ) { + m_pattern = m_pattern.substr( 1 ); + m_wildcard = WildcardAtStart; + } + if( endsWith( m_pattern, "*" ) ) { + m_pattern = m_pattern.substr( 0, m_pattern.size()-1 ); + m_wildcard = static_cast<WildcardPosition>( m_wildcard | WildcardAtEnd ); + } + } + virtual ~WildcardPattern(); + virtual bool matches( std::string const& str ) const { + switch( m_wildcard ) { + case NoWildcard: + return m_pattern == adjustCase( str ); + case WildcardAtStart: + return endsWith( adjustCase( str ), m_pattern ); + case WildcardAtEnd: + return startsWith( adjustCase( str ), m_pattern ); + case WildcardAtBothEnds: + return contains( adjustCase( str ), m_pattern ); + } + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunreachable-code" +#endif + throw std::logic_error( "Unknown enum" ); +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + } + private: + std::string adjustCase( std::string const& str ) const { + return m_caseSensitivity == CaseSensitive::No ? toLower( str ) : str; + } + CaseSensitive::Choice m_caseSensitivity; + WildcardPosition m_wildcard; + std::string m_pattern; + }; +} + +#endif // TWOBLUECUBES_CATCH_WILDCARD_PATTERN_HPP_INCLUDED diff --git a/unittest/Catch/include/internal/catch_xmlwriter.hpp b/unittest/Catch/include/internal/catch_xmlwriter.hpp new file mode 100644 index 0000000..c59725b --- /dev/null +++ b/unittest/Catch/include/internal/catch_xmlwriter.hpp @@ -0,0 +1,237 @@ +/* + * Created by Phil on 09/12/2010. + * Copyright 2010 Two Blue Cubes Ltd. All rights reserved. + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + */ +#ifndef TWOBLUECUBES_CATCH_XMLWRITER_HPP_INCLUDED +#define TWOBLUECUBES_CATCH_XMLWRITER_HPP_INCLUDED + +#include "catch_stream.h" +#include "catch_compiler_capabilities.h" +#include "catch_suppress_warnings.h" + +#include <sstream> +#include <string> +#include <vector> +#include <iomanip> + +namespace Catch { + + class XmlEncode { + public: + enum ForWhat { ForTextNodes, ForAttributes }; + + XmlEncode( std::string const& str, ForWhat forWhat = ForTextNodes ) + : m_str( str ), + m_forWhat( forWhat ) + {} + + void encodeTo( std::ostream& os ) const { + + // Apostrophe escaping not necessary if we always use " to write attributes + // (see: http://www.w3.org/TR/xml/#syntax) + + for( std::size_t i = 0; i < m_str.size(); ++ i ) { + char c = m_str[i]; + switch( c ) { + case '<': os << "<"; break; + case '&': os << "&"; break; + + case '>': + // See: http://www.w3.org/TR/xml/#syntax + if( i > 2 && m_str[i-1] == ']' && m_str[i-2] == ']' ) + os << ">"; + else + os << c; + break; + + case '\"': + if( m_forWhat == ForAttributes ) + os << """; + else + os << c; + break; + + default: + // Escape control chars - based on contribution by @espenalb in PR #465 + if ( ( c < '\x09' ) || ( c > '\x0D' && c < '\x20') || c=='\x7F' ) + os << "&#x" << std::uppercase << std::hex << static_cast<int>( c ); + else + os << c; + } + } + } + + friend std::ostream& operator << ( std::ostream& os, XmlEncode const& xmlEncode ) { + xmlEncode.encodeTo( os ); + return os; + } + + private: + std::string m_str; + ForWhat m_forWhat; + }; + + class XmlWriter { + public: + + class ScopedElement { + public: + ScopedElement( XmlWriter* writer ) + : m_writer( writer ) + {} + + ScopedElement( ScopedElement const& other ) + : m_writer( other.m_writer ){ + other.m_writer = CATCH_NULL; + } + + ~ScopedElement() { + if( m_writer ) + m_writer->endElement(); + } + + ScopedElement& writeText( std::string const& text, bool indent = true ) { + m_writer->writeText( text, indent ); + return *this; + } + + template<typename T> + ScopedElement& writeAttribute( std::string const& name, T const& attribute ) { + m_writer->writeAttribute( name, attribute ); + return *this; + } + + private: + mutable XmlWriter* m_writer; + }; + + XmlWriter() + : m_tagIsOpen( false ), + m_needsNewline( false ), + m_os( &Catch::cout() ) + {} + + XmlWriter( std::ostream& os ) + : m_tagIsOpen( false ), + m_needsNewline( false ), + m_os( &os ) + {} + + ~XmlWriter() { + while( !m_tags.empty() ) + endElement(); + } + + XmlWriter& startElement( std::string const& name ) { + ensureTagClosed(); + newlineIfNecessary(); + stream() << m_indent << "<" << name; + m_tags.push_back( name ); + m_indent += " "; + m_tagIsOpen = true; + return *this; + } + + ScopedElement scopedElement( std::string const& name ) { + ScopedElement scoped( this ); + startElement( name ); + return scoped; + } + + XmlWriter& endElement() { + newlineIfNecessary(); + m_indent = m_indent.substr( 0, m_indent.size()-2 ); + if( m_tagIsOpen ) { + stream() << "/>\n"; + m_tagIsOpen = false; + } + else { + stream() << m_indent << "</" << m_tags.back() << ">\n"; + } + m_tags.pop_back(); + return *this; + } + + XmlWriter& writeAttribute( std::string const& name, std::string const& attribute ) { + if( !name.empty() && !attribute.empty() ) + stream() << " " << name << "=\"" << XmlEncode( attribute, XmlEncode::ForAttributes ) << "\""; + return *this; + } + + XmlWriter& writeAttribute( std::string const& name, bool attribute ) { + stream() << " " << name << "=\"" << ( attribute ? "true" : "false" ) << "\""; + return *this; + } + + template<typename T> + XmlWriter& writeAttribute( std::string const& name, T const& attribute ) { + std::ostringstream oss; + oss << attribute; + return writeAttribute( name, oss.str() ); + } + + XmlWriter& writeText( std::string const& text, bool indent = true ) { + if( !text.empty() ){ + bool tagWasOpen = m_tagIsOpen; + ensureTagClosed(); + if( tagWasOpen && indent ) + stream() << m_indent; + stream() << XmlEncode( text ); + m_needsNewline = true; + } + return *this; + } + + XmlWriter& writeComment( std::string const& text ) { + ensureTagClosed(); + stream() << m_indent << "<!--" << text << "-->"; + m_needsNewline = true; + return *this; + } + + XmlWriter& writeBlankLine() { + ensureTagClosed(); + stream() << "\n"; + return *this; + } + + void setStream( std::ostream& os ) { + m_os = &os; + } + + private: + XmlWriter( XmlWriter const& ); + void operator=( XmlWriter const& ); + + std::ostream& stream() { + return *m_os; + } + + void ensureTagClosed() { + if( m_tagIsOpen ) { + stream() << ">\n"; + m_tagIsOpen = false; + } + } + + void newlineIfNecessary() { + if( m_needsNewline ) { + stream() << "\n"; + m_needsNewline = false; + } + } + + bool m_tagIsOpen; + bool m_needsNewline; + std::vector<std::string> m_tags; + std::string m_indent; + std::ostream* m_os; + }; + +} +#include "catch_reenable_warnings.h" + +#endif // TWOBLUECUBES_CATCH_XMLWRITER_HPP_INCLUDED diff --git a/unittest/Catch/include/reporters/catch_reporter_bases.hpp b/unittest/Catch/include/reporters/catch_reporter_bases.hpp new file mode 100644 index 0000000..4fdeb19 --- /dev/null +++ b/unittest/Catch/include/reporters/catch_reporter_bases.hpp @@ -0,0 +1,247 @@ +/* + * Created by Phil on 27/11/2013. + * Copyright 2013 Two Blue Cubes Ltd. All rights reserved. + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + */ +#ifndef TWOBLUECUBES_CATCH_REPORTER_BASES_HPP_INCLUDED +#define TWOBLUECUBES_CATCH_REPORTER_BASES_HPP_INCLUDED + +#include "../internal/catch_interfaces_reporter.h" + +#include <cstring> + +namespace Catch { + + struct StreamingReporterBase : SharedImpl<IStreamingReporter> { + + StreamingReporterBase( ReporterConfig const& _config ) + : m_config( _config.fullConfig() ), + stream( _config.stream() ) + { + m_reporterPrefs.shouldRedirectStdOut = false; + } + + virtual ReporterPreferences getPreferences() const CATCH_OVERRIDE { + return m_reporterPrefs; + } + + virtual ~StreamingReporterBase() CATCH_OVERRIDE; + + virtual void noMatchingTestCases( std::string const& ) CATCH_OVERRIDE {} + + virtual void testRunStarting( TestRunInfo const& _testRunInfo ) CATCH_OVERRIDE { + currentTestRunInfo = _testRunInfo; + } + virtual void testGroupStarting( GroupInfo const& _groupInfo ) CATCH_OVERRIDE { + currentGroupInfo = _groupInfo; + } + + virtual void testCaseStarting( TestCaseInfo const& _testInfo ) CATCH_OVERRIDE { + currentTestCaseInfo = _testInfo; + } + virtual void sectionStarting( SectionInfo const& _sectionInfo ) CATCH_OVERRIDE { + m_sectionStack.push_back( _sectionInfo ); + } + + virtual void sectionEnded( SectionStats const& /* _sectionStats */ ) CATCH_OVERRIDE { + m_sectionStack.pop_back(); + } + virtual void testCaseEnded( TestCaseStats const& /* _testCaseStats */ ) CATCH_OVERRIDE { + currentTestCaseInfo.reset(); + } + virtual void testGroupEnded( TestGroupStats const& /* _testGroupStats */ ) CATCH_OVERRIDE { + currentGroupInfo.reset(); + } + virtual void testRunEnded( TestRunStats const& /* _testRunStats */ ) CATCH_OVERRIDE { + currentTestCaseInfo.reset(); + currentGroupInfo.reset(); + currentTestRunInfo.reset(); + } + + virtual void skipTest( TestCaseInfo const& ) CATCH_OVERRIDE { + // Don't do anything with this by default. + // It can optionally be overridden in the derived class. + } + + Ptr<IConfig const> m_config; + std::ostream& stream; + + LazyStat<TestRunInfo> currentTestRunInfo; + LazyStat<GroupInfo> currentGroupInfo; + LazyStat<TestCaseInfo> currentTestCaseInfo; + + std::vector<SectionInfo> m_sectionStack; + ReporterPreferences m_reporterPrefs; + }; + + struct CumulativeReporterBase : SharedImpl<IStreamingReporter> { + template<typename T, typename ChildNodeT> + struct Node : SharedImpl<> { + explicit Node( T const& _value ) : value( _value ) {} + virtual ~Node() {} + + typedef std::vector<Ptr<ChildNodeT> > ChildNodes; + T value; + ChildNodes children; + }; + struct SectionNode : SharedImpl<> { + explicit SectionNode( SectionStats const& _stats ) : stats( _stats ) {} + virtual ~SectionNode(); + + bool operator == ( SectionNode const& other ) const { + return stats.sectionInfo.lineInfo == other.stats.sectionInfo.lineInfo; + } + bool operator == ( Ptr<SectionNode> const& other ) const { + return operator==( *other ); + } + + SectionStats stats; + typedef std::vector<Ptr<SectionNode> > ChildSections; + typedef std::vector<AssertionStats> Assertions; + ChildSections childSections; + Assertions assertions; + std::string stdOut; + std::string stdErr; + }; + + struct BySectionInfo { + BySectionInfo( SectionInfo const& other ) : m_other( other ) {} + BySectionInfo( BySectionInfo const& other ) : m_other( other.m_other ) {} + bool operator() ( Ptr<SectionNode> const& node ) const { + return node->stats.sectionInfo.lineInfo == m_other.lineInfo; + } + private: + void operator=( BySectionInfo const& ); + SectionInfo const& m_other; + }; + + + typedef Node<TestCaseStats, SectionNode> TestCaseNode; + typedef Node<TestGroupStats, TestCaseNode> TestGroupNode; + typedef Node<TestRunStats, TestGroupNode> TestRunNode; + + CumulativeReporterBase( ReporterConfig const& _config ) + : m_config( _config.fullConfig() ), + stream( _config.stream() ) + { + m_reporterPrefs.shouldRedirectStdOut = false; + } + ~CumulativeReporterBase(); + + virtual ReporterPreferences getPreferences() const CATCH_OVERRIDE { + return m_reporterPrefs; + } + + virtual void testRunStarting( TestRunInfo const& ) CATCH_OVERRIDE {} + virtual void testGroupStarting( GroupInfo const& ) CATCH_OVERRIDE {} + + virtual void testCaseStarting( TestCaseInfo const& ) CATCH_OVERRIDE {} + + virtual void sectionStarting( SectionInfo const& sectionInfo ) CATCH_OVERRIDE { + SectionStats incompleteStats( sectionInfo, Counts(), 0, false ); + Ptr<SectionNode> node; + if( m_sectionStack.empty() ) { + if( !m_rootSection ) + m_rootSection = new SectionNode( incompleteStats ); + node = m_rootSection; + } + else { + SectionNode& parentNode = *m_sectionStack.back(); + SectionNode::ChildSections::const_iterator it = + std::find_if( parentNode.childSections.begin(), + parentNode.childSections.end(), + BySectionInfo( sectionInfo ) ); + if( it == parentNode.childSections.end() ) { + node = new SectionNode( incompleteStats ); + parentNode.childSections.push_back( node ); + } + else + node = *it; + } + m_sectionStack.push_back( node ); + m_deepestSection = node; + } + + virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE {} + + virtual bool assertionEnded( AssertionStats const& assertionStats ) { + assert( !m_sectionStack.empty() ); + SectionNode& sectionNode = *m_sectionStack.back(); + sectionNode.assertions.push_back( assertionStats ); + return true; + } + virtual void sectionEnded( SectionStats const& sectionStats ) CATCH_OVERRIDE { + assert( !m_sectionStack.empty() ); + SectionNode& node = *m_sectionStack.back(); + node.stats = sectionStats; + m_sectionStack.pop_back(); + } + virtual void testCaseEnded( TestCaseStats const& testCaseStats ) CATCH_OVERRIDE { + Ptr<TestCaseNode> node = new TestCaseNode( testCaseStats ); + assert( m_sectionStack.size() == 0 ); + node->children.push_back( m_rootSection ); + m_testCases.push_back( node ); + m_rootSection.reset(); + + assert( m_deepestSection ); + m_deepestSection->stdOut = testCaseStats.stdOut; + m_deepestSection->stdErr = testCaseStats.stdErr; + } + virtual void testGroupEnded( TestGroupStats const& testGroupStats ) CATCH_OVERRIDE { + Ptr<TestGroupNode> node = new TestGroupNode( testGroupStats ); + node->children.swap( m_testCases ); + m_testGroups.push_back( node ); + } + virtual void testRunEnded( TestRunStats const& testRunStats ) CATCH_OVERRIDE { + Ptr<TestRunNode> node = new TestRunNode( testRunStats ); + node->children.swap( m_testGroups ); + m_testRuns.push_back( node ); + testRunEndedCumulative(); + } + virtual void testRunEndedCumulative() = 0; + + virtual void skipTest( TestCaseInfo const& ) CATCH_OVERRIDE {} + + Ptr<IConfig const> m_config; + std::ostream& stream; + std::vector<AssertionStats> m_assertions; + std::vector<std::vector<Ptr<SectionNode> > > m_sections; + std::vector<Ptr<TestCaseNode> > m_testCases; + std::vector<Ptr<TestGroupNode> > m_testGroups; + + std::vector<Ptr<TestRunNode> > m_testRuns; + + Ptr<SectionNode> m_rootSection; + Ptr<SectionNode> m_deepestSection; + std::vector<Ptr<SectionNode> > m_sectionStack; + ReporterPreferences m_reporterPrefs; + + }; + + template<char C> + char const* getLineOfChars() { + static char line[CATCH_CONFIG_CONSOLE_WIDTH] = {0}; + if( !*line ) { + memset( line, C, CATCH_CONFIG_CONSOLE_WIDTH-1 ); + line[CATCH_CONFIG_CONSOLE_WIDTH-1] = 0; + } + return line; + } + + + struct TestEventListenerBase : StreamingReporterBase { + TestEventListenerBase( ReporterConfig const& _config ) + : StreamingReporterBase( _config ) + {} + + virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE {} + virtual bool assertionEnded( AssertionStats const& ) CATCH_OVERRIDE { + return false; + } + }; + +} // end namespace Catch + +#endif // TWOBLUECUBES_CATCH_REPORTER_BASES_HPP_INCLUDED diff --git a/unittest/Catch/include/reporters/catch_reporter_compact.hpp b/unittest/Catch/include/reporters/catch_reporter_compact.hpp new file mode 100644 index 0000000..a5a1729 --- /dev/null +++ b/unittest/Catch/include/reporters/catch_reporter_compact.hpp @@ -0,0 +1,301 @@ +/* + * Created by Martin Moene on 2013-12-05. + * Copyright 2012 Martin Moene. All rights reserved. + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + */ +#ifndef TWOBLUECUBES_CATCH_REPORTER_COMPACT_HPP_INCLUDED +#define TWOBLUECUBES_CATCH_REPORTER_COMPACT_HPP_INCLUDED + +#include "catch_reporter_bases.hpp" + +#include "../internal/catch_reporter_registrars.hpp" +#include "../internal/catch_console_colour.hpp" + +namespace Catch { + + struct CompactReporter : StreamingReporterBase { + + CompactReporter( ReporterConfig const& _config ) + : StreamingReporterBase( _config ) + {} + + virtual ~CompactReporter(); + + static std::string getDescription() { + return "Reports test results on a single line, suitable for IDEs"; + } + + virtual ReporterPreferences getPreferences() const { + ReporterPreferences prefs; + prefs.shouldRedirectStdOut = false; + return prefs; + } + + virtual void noMatchingTestCases( std::string const& spec ) { + stream << "No test cases matched '" << spec << "'" << std::endl; + } + + virtual void assertionStarting( AssertionInfo const& ) { + } + + virtual bool assertionEnded( AssertionStats const& _assertionStats ) { + AssertionResult const& result = _assertionStats.assertionResult; + + bool printInfoMessages = true; + + // Drop out if result was successful and we're not printing those + if( !m_config->includeSuccessfulResults() && result.isOk() ) { + if( result.getResultType() != ResultWas::Warning ) + return false; + printInfoMessages = false; + } + + AssertionPrinter printer( stream, _assertionStats, printInfoMessages ); + printer.print(); + + stream << std::endl; + return true; + } + + virtual void testRunEnded( TestRunStats const& _testRunStats ) { + printTotals( _testRunStats.totals ); + stream << "\n" << std::endl; + StreamingReporterBase::testRunEnded( _testRunStats ); + } + + private: + class AssertionPrinter { + void operator= ( AssertionPrinter const& ); + public: + AssertionPrinter( std::ostream& _stream, AssertionStats const& _stats, bool _printInfoMessages ) + : stream( _stream ) + , stats( _stats ) + , result( _stats.assertionResult ) + , messages( _stats.infoMessages ) + , itMessage( _stats.infoMessages.begin() ) + , printInfoMessages( _printInfoMessages ) + {} + + void print() { + printSourceInfo(); + + itMessage = messages.begin(); + + switch( result.getResultType() ) { + case ResultWas::Ok: + printResultType( Colour::ResultSuccess, passedString() ); + printOriginalExpression(); + printReconstructedExpression(); + if ( ! result.hasExpression() ) + printRemainingMessages( Colour::None ); + else + printRemainingMessages(); + break; + case ResultWas::ExpressionFailed: + if( result.isOk() ) + printResultType( Colour::ResultSuccess, failedString() + std::string( " - but was ok" ) ); + else + printResultType( Colour::Error, failedString() ); + printOriginalExpression(); + printReconstructedExpression(); + printRemainingMessages(); + break; + case ResultWas::ThrewException: + printResultType( Colour::Error, failedString() ); + printIssue( "unexpected exception with message:" ); + printMessage(); + printExpressionWas(); + printRemainingMessages(); + break; + case ResultWas::FatalErrorCondition: + printResultType( Colour::Error, failedString() ); + printIssue( "fatal error condition with message:" ); + printMessage(); + printExpressionWas(); + printRemainingMessages(); + break; + case ResultWas::DidntThrowException: + printResultType( Colour::Error, failedString() ); + printIssue( "expected exception, got none" ); + printExpressionWas(); + printRemainingMessages(); + break; + case ResultWas::Info: + printResultType( Colour::None, "info" ); + printMessage(); + printRemainingMessages(); + break; + case ResultWas::Warning: + printResultType( Colour::None, "warning" ); + printMessage(); + printRemainingMessages(); + break; + case ResultWas::ExplicitFailure: + printResultType( Colour::Error, failedString() ); + printIssue( "explicitly" ); + printRemainingMessages( Colour::None ); + break; + // These cases are here to prevent compiler warnings + case ResultWas::Unknown: + case ResultWas::FailureBit: + case ResultWas::Exception: + printResultType( Colour::Error, "** internal error **" ); + break; + } + } + + private: + // Colour::LightGrey + + static Colour::Code dimColour() { return Colour::FileName; } + +#ifdef CATCH_PLATFORM_MAC + static const char* failedString() { return "FAILED"; } + static const char* passedString() { return "PASSED"; } +#else + static const char* failedString() { return "failed"; } + static const char* passedString() { return "passed"; } +#endif + + void printSourceInfo() const { + Colour colourGuard( Colour::FileName ); + stream << result.getSourceInfo() << ":"; + } + + void printResultType( Colour::Code colour, std::string passOrFail ) const { + if( !passOrFail.empty() ) { + { + Colour colourGuard( colour ); + stream << " " << passOrFail; + } + stream << ":"; + } + } + + void printIssue( std::string issue ) const { + stream << " " << issue; + } + + void printExpressionWas() { + if( result.hasExpression() ) { + stream << ";"; + { + Colour colour( dimColour() ); + stream << " expression was:"; + } + printOriginalExpression(); + } + } + + void printOriginalExpression() const { + if( result.hasExpression() ) { + stream << " " << result.getExpression(); + } + } + + void printReconstructedExpression() const { + if( result.hasExpandedExpression() ) { + { + Colour colour( dimColour() ); + stream << " for: "; + } + stream << result.getExpandedExpression(); + } + } + + void printMessage() { + if ( itMessage != messages.end() ) { + stream << " '" << itMessage->message << "'"; + ++itMessage; + } + } + + void printRemainingMessages( Colour::Code colour = dimColour() ) { + if ( itMessage == messages.end() ) + return; + + // using messages.end() directly yields compilation error: + std::vector<MessageInfo>::const_iterator itEnd = messages.end(); + const std::size_t N = static_cast<std::size_t>( std::distance( itMessage, itEnd ) ); + + { + Colour colourGuard( colour ); + stream << " with " << pluralise( N, "message" ) << ":"; + } + + for(; itMessage != itEnd; ) { + // If this assertion is a warning ignore any INFO messages + if( printInfoMessages || itMessage->type != ResultWas::Info ) { + stream << " '" << itMessage->message << "'"; + if ( ++itMessage != itEnd ) { + Colour colourGuard( dimColour() ); + stream << " and"; + } + } + } + } + + private: + std::ostream& stream; + AssertionStats const& stats; + AssertionResult const& result; + std::vector<MessageInfo> messages; + std::vector<MessageInfo>::const_iterator itMessage; + bool printInfoMessages; + }; + + // Colour, message variants: + // - white: No tests ran. + // - red: Failed [both/all] N test cases, failed [both/all] M assertions. + // - white: Passed [both/all] N test cases (no assertions). + // - red: Failed N tests cases, failed M assertions. + // - green: Passed [both/all] N tests cases with M assertions. + + std::string bothOrAll( std::size_t count ) const { + return count == 1 ? "" : count == 2 ? "both " : "all " ; + } + + void printTotals( const Totals& totals ) const { + if( totals.testCases.total() == 0 ) { + stream << "No tests ran."; + } + else if( totals.testCases.failed == totals.testCases.total() ) { + Colour colour( Colour::ResultError ); + const std::string qualify_assertions_failed = + totals.assertions.failed == totals.assertions.total() ? + bothOrAll( totals.assertions.failed ) : ""; + stream << + "Failed " << bothOrAll( totals.testCases.failed ) + << pluralise( totals.testCases.failed, "test case" ) << ", " + "failed " << qualify_assertions_failed << + pluralise( totals.assertions.failed, "assertion" ) << "."; + } + else if( totals.assertions.total() == 0 ) { + stream << + "Passed " << bothOrAll( totals.testCases.total() ) + << pluralise( totals.testCases.total(), "test case" ) + << " (no assertions)."; + } + else if( totals.assertions.failed ) { + Colour colour( Colour::ResultError ); + stream << + "Failed " << pluralise( totals.testCases.failed, "test case" ) << ", " + "failed " << pluralise( totals.assertions.failed, "assertion" ) << "."; + } + else { + Colour colour( Colour::ResultSuccess ); + stream << + "Passed " << bothOrAll( totals.testCases.passed ) + << pluralise( totals.testCases.passed, "test case" ) << + " with " << pluralise( totals.assertions.passed, "assertion" ) << "."; + } + } + }; + + INTERNAL_CATCH_REGISTER_REPORTER( "compact", CompactReporter ) + +} // end namespace Catch + +#endif // TWOBLUECUBES_CATCH_REPORTER_COMPACT_HPP_INCLUDED diff --git a/unittest/Catch/include/reporters/catch_reporter_console.hpp b/unittest/Catch/include/reporters/catch_reporter_console.hpp new file mode 100644 index 0000000..e736703 --- /dev/null +++ b/unittest/Catch/include/reporters/catch_reporter_console.hpp @@ -0,0 +1,445 @@ +/* + * Created by Phil on 5/12/2012. + * Copyright 2012 Two Blue Cubes Ltd. All rights reserved. + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + */ +#ifndef TWOBLUECUBES_CATCH_REPORTER_CONSOLE_HPP_INCLUDED +#define TWOBLUECUBES_CATCH_REPORTER_CONSOLE_HPP_INCLUDED + +#include "catch_reporter_bases.hpp" + +#include "../internal/catch_reporter_registrars.hpp" +#include "../internal/catch_console_colour.hpp" + +namespace Catch { + + struct ConsoleReporter : StreamingReporterBase { + ConsoleReporter( ReporterConfig const& _config ) + : StreamingReporterBase( _config ), + m_headerPrinted( false ) + {} + + virtual ~ConsoleReporter() CATCH_OVERRIDE; + static std::string getDescription() { + return "Reports test results as plain lines of text"; + } + + virtual void noMatchingTestCases( std::string const& spec ) CATCH_OVERRIDE { + stream << "No test cases matched '" << spec << "'" << std::endl; + } + + virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE { + } + + virtual bool assertionEnded( AssertionStats const& _assertionStats ) CATCH_OVERRIDE { + AssertionResult const& result = _assertionStats.assertionResult; + + bool printInfoMessages = true; + + // Drop out if result was successful and we're not printing those + if( !m_config->includeSuccessfulResults() && result.isOk() ) { + if( result.getResultType() != ResultWas::Warning ) + return false; + printInfoMessages = false; + } + + lazyPrint(); + + AssertionPrinter printer( stream, _assertionStats, printInfoMessages ); + printer.print(); + stream << std::endl; + return true; + } + + virtual void sectionStarting( SectionInfo const& _sectionInfo ) CATCH_OVERRIDE { + m_headerPrinted = false; + StreamingReporterBase::sectionStarting( _sectionInfo ); + } + virtual void sectionEnded( SectionStats const& _sectionStats ) CATCH_OVERRIDE { + if( _sectionStats.missingAssertions ) { + lazyPrint(); + Colour colour( Colour::ResultError ); + if( m_sectionStack.size() > 1 ) + stream << "\nNo assertions in section"; + else + stream << "\nNo assertions in test case"; + stream << " '" << _sectionStats.sectionInfo.name << "'\n" << std::endl; + } + if( m_headerPrinted ) { + if( m_config->showDurations() == ShowDurations::Always ) + stream << "Completed in " << _sectionStats.durationInSeconds << "s" << std::endl; + m_headerPrinted = false; + } + else { + if( m_config->showDurations() == ShowDurations::Always ) + stream << _sectionStats.sectionInfo.name << " completed in " << _sectionStats.durationInSeconds << "s" << std::endl; + } + StreamingReporterBase::sectionEnded( _sectionStats ); + } + + virtual void testCaseEnded( TestCaseStats const& _testCaseStats ) CATCH_OVERRIDE { + StreamingReporterBase::testCaseEnded( _testCaseStats ); + m_headerPrinted = false; + } + virtual void testGroupEnded( TestGroupStats const& _testGroupStats ) CATCH_OVERRIDE { + if( currentGroupInfo.used ) { + printSummaryDivider(); + stream << "Summary for group '" << _testGroupStats.groupInfo.name << "':\n"; + printTotals( _testGroupStats.totals ); + stream << "\n" << std::endl; + } + StreamingReporterBase::testGroupEnded( _testGroupStats ); + } + virtual void testRunEnded( TestRunStats const& _testRunStats ) CATCH_OVERRIDE { + printTotalsDivider( _testRunStats.totals ); + printTotals( _testRunStats.totals ); + stream << std::endl; + StreamingReporterBase::testRunEnded( _testRunStats ); + } + + private: + + class AssertionPrinter { + void operator= ( AssertionPrinter const& ); + public: + AssertionPrinter( std::ostream& _stream, AssertionStats const& _stats, bool _printInfoMessages ) + : stream( _stream ), + stats( _stats ), + result( _stats.assertionResult ), + colour( Colour::None ), + message( result.getMessage() ), + messages( _stats.infoMessages ), + printInfoMessages( _printInfoMessages ) + { + switch( result.getResultType() ) { + case ResultWas::Ok: + colour = Colour::Success; + passOrFail = "PASSED"; + //if( result.hasMessage() ) + if( _stats.infoMessages.size() == 1 ) + messageLabel = "with message"; + if( _stats.infoMessages.size() > 1 ) + messageLabel = "with messages"; + break; + case ResultWas::ExpressionFailed: + if( result.isOk() ) { + colour = Colour::Success; + passOrFail = "FAILED - but was ok"; + } + else { + colour = Colour::Error; + passOrFail = "FAILED"; + } + if( _stats.infoMessages.size() == 1 ) + messageLabel = "with message"; + if( _stats.infoMessages.size() > 1 ) + messageLabel = "with messages"; + break; + case ResultWas::ThrewException: + colour = Colour::Error; + passOrFail = "FAILED"; + messageLabel = "due to unexpected exception with message"; + break; + case ResultWas::FatalErrorCondition: + colour = Colour::Error; + passOrFail = "FAILED"; + messageLabel = "due to a fatal error condition"; + break; + case ResultWas::DidntThrowException: + colour = Colour::Error; + passOrFail = "FAILED"; + messageLabel = "because no exception was thrown where one was expected"; + break; + case ResultWas::Info: + messageLabel = "info"; + break; + case ResultWas::Warning: + messageLabel = "warning"; + break; + case ResultWas::ExplicitFailure: + passOrFail = "FAILED"; + colour = Colour::Error; + if( _stats.infoMessages.size() == 1 ) + messageLabel = "explicitly with message"; + if( _stats.infoMessages.size() > 1 ) + messageLabel = "explicitly with messages"; + break; + // These cases are here to prevent compiler warnings + case ResultWas::Unknown: + case ResultWas::FailureBit: + case ResultWas::Exception: + passOrFail = "** internal error **"; + colour = Colour::Error; + break; + } + } + + void print() const { + printSourceInfo(); + if( stats.totals.assertions.total() > 0 ) { + if( result.isOk() ) + stream << "\n"; + printResultType(); + printOriginalExpression(); + printReconstructedExpression(); + } + else { + stream << "\n"; + } + printMessage(); + } + + private: + void printResultType() const { + if( !passOrFail.empty() ) { + Colour colourGuard( colour ); + stream << passOrFail << ":\n"; + } + } + void printOriginalExpression() const { + if( result.hasExpression() ) { + Colour colourGuard( Colour::OriginalExpression ); + stream << " "; + stream << result.getExpressionInMacro(); + stream << "\n"; + } + } + void printReconstructedExpression() const { + if( result.hasExpandedExpression() ) { + stream << "with expansion:\n"; + Colour colourGuard( Colour::ReconstructedExpression ); + stream << Text( result.getExpandedExpression(), TextAttributes().setIndent(2) ) << "\n"; + } + } + void printMessage() const { + if( !messageLabel.empty() ) + stream << messageLabel << ":" << "\n"; + for( std::vector<MessageInfo>::const_iterator it = messages.begin(), itEnd = messages.end(); + it != itEnd; + ++it ) { + // If this assertion is a warning ignore any INFO messages + if( printInfoMessages || it->type != ResultWas::Info ) + stream << Text( it->message, TextAttributes().setIndent(2) ) << "\n"; + } + } + void printSourceInfo() const { + Colour colourGuard( Colour::FileName ); + stream << result.getSourceInfo() << ": "; + } + + std::ostream& stream; + AssertionStats const& stats; + AssertionResult const& result; + Colour::Code colour; + std::string passOrFail; + std::string messageLabel; + std::string message; + std::vector<MessageInfo> messages; + bool printInfoMessages; + }; + + void lazyPrint() { + + if( !currentTestRunInfo.used ) + lazyPrintRunInfo(); + if( !currentGroupInfo.used ) + lazyPrintGroupInfo(); + + if( !m_headerPrinted ) { + printTestCaseAndSectionHeader(); + m_headerPrinted = true; + } + } + void lazyPrintRunInfo() { + stream << "\n" << getLineOfChars<'~'>() << "\n"; + Colour colour( Colour::SecondaryText ); + stream << currentTestRunInfo->name + << " is a Catch v" << libraryVersion << " host application.\n" + << "Run with -? for options\n\n"; + + if( m_config->rngSeed() != 0 ) + stream << "Randomness seeded to: " << m_config->rngSeed() << "\n\n"; + + currentTestRunInfo.used = true; + } + void lazyPrintGroupInfo() { + if( !currentGroupInfo->name.empty() && currentGroupInfo->groupsCounts > 1 ) { + printClosedHeader( "Group: " + currentGroupInfo->name ); + currentGroupInfo.used = true; + } + } + void printTestCaseAndSectionHeader() { + assert( !m_sectionStack.empty() ); + printOpenHeader( currentTestCaseInfo->name ); + + if( m_sectionStack.size() > 1 ) { + Colour colourGuard( Colour::Headers ); + + std::vector<SectionInfo>::const_iterator + it = m_sectionStack.begin()+1, // Skip first section (test case) + itEnd = m_sectionStack.end(); + for( ; it != itEnd; ++it ) + printHeaderString( it->name, 2 ); + } + + SourceLineInfo lineInfo = m_sectionStack.front().lineInfo; + + if( !lineInfo.empty() ){ + stream << getLineOfChars<'-'>() << "\n"; + Colour colourGuard( Colour::FileName ); + stream << lineInfo << "\n"; + } + stream << getLineOfChars<'.'>() << "\n" << std::endl; + } + + void printClosedHeader( std::string const& _name ) { + printOpenHeader( _name ); + stream << getLineOfChars<'.'>() << "\n"; + } + void printOpenHeader( std::string const& _name ) { + stream << getLineOfChars<'-'>() << "\n"; + { + Colour colourGuard( Colour::Headers ); + printHeaderString( _name ); + } + } + + // if string has a : in first line will set indent to follow it on + // subsequent lines + void printHeaderString( std::string const& _string, std::size_t indent = 0 ) { + std::size_t i = _string.find( ": " ); + if( i != std::string::npos ) + i+=2; + else + i = 0; + stream << Text( _string, TextAttributes() + .setIndent( indent+i) + .setInitialIndent( indent ) ) << "\n"; + } + + struct SummaryColumn { + + SummaryColumn( std::string const& _label, Colour::Code _colour ) + : label( _label ), + colour( _colour ) + {} + SummaryColumn addRow( std::size_t count ) { + std::ostringstream oss; + oss << count; + std::string row = oss.str(); + for( std::vector<std::string>::iterator it = rows.begin(); it != rows.end(); ++it ) { + while( it->size() < row.size() ) + *it = " " + *it; + while( it->size() > row.size() ) + row = " " + row; + } + rows.push_back( row ); + return *this; + } + + std::string label; + Colour::Code colour; + std::vector<std::string> rows; + + }; + + void printTotals( Totals const& totals ) { + if( totals.testCases.total() == 0 ) { + stream << Colour( Colour::Warning ) << "No tests ran\n"; + } + else if( totals.assertions.total() > 0 && totals.assertions.allPassed() ) { + stream << Colour( Colour::ResultSuccess ) << "All tests passed"; + stream << " (" + << pluralise( totals.assertions.passed, "assertion" ) << " in " + << pluralise( totals.testCases.passed, "test case" ) << ")" + << "\n"; + } + else { + + std::vector<SummaryColumn> columns; + columns.push_back( SummaryColumn( "", Colour::None ) + .addRow( totals.testCases.total() ) + .addRow( totals.assertions.total() ) ); + columns.push_back( SummaryColumn( "passed", Colour::Success ) + .addRow( totals.testCases.passed ) + .addRow( totals.assertions.passed ) ); + columns.push_back( SummaryColumn( "failed", Colour::ResultError ) + .addRow( totals.testCases.failed ) + .addRow( totals.assertions.failed ) ); + columns.push_back( SummaryColumn( "failed as expected", Colour::ResultExpectedFailure ) + .addRow( totals.testCases.failedButOk ) + .addRow( totals.assertions.failedButOk ) ); + + printSummaryRow( "test cases", columns, 0 ); + printSummaryRow( "assertions", columns, 1 ); + } + } + void printSummaryRow( std::string const& label, std::vector<SummaryColumn> const& cols, std::size_t row ) { + for( std::vector<SummaryColumn>::const_iterator it = cols.begin(); it != cols.end(); ++it ) { + std::string value = it->rows[row]; + if( it->label.empty() ) { + stream << label << ": "; + if( value != "0" ) + stream << value; + else + stream << Colour( Colour::Warning ) << "- none -"; + } + else if( value != "0" ) { + stream << Colour( Colour::LightGrey ) << " | "; + stream << Colour( it->colour ) + << value << " " << it->label; + } + } + stream << "\n"; + } + + static std::size_t makeRatio( std::size_t number, std::size_t total ) { + std::size_t ratio = total > 0 ? CATCH_CONFIG_CONSOLE_WIDTH * number/ total : 0; + return ( ratio == 0 && number > 0 ) ? 1 : ratio; + } + static std::size_t& findMax( std::size_t& i, std::size_t& j, std::size_t& k ) { + if( i > j && i > k ) + return i; + else if( j > k ) + return j; + else + return k; + } + + void printTotalsDivider( Totals const& totals ) { + if( totals.testCases.total() > 0 ) { + std::size_t failedRatio = makeRatio( totals.testCases.failed, totals.testCases.total() ); + std::size_t failedButOkRatio = makeRatio( totals.testCases.failedButOk, totals.testCases.total() ); + std::size_t passedRatio = makeRatio( totals.testCases.passed, totals.testCases.total() ); + while( failedRatio + failedButOkRatio + passedRatio < CATCH_CONFIG_CONSOLE_WIDTH-1 ) + findMax( failedRatio, failedButOkRatio, passedRatio )++; + while( failedRatio + failedButOkRatio + passedRatio > CATCH_CONFIG_CONSOLE_WIDTH-1 ) + findMax( failedRatio, failedButOkRatio, passedRatio )--; + + stream << Colour( Colour::Error ) << std::string( failedRatio, '=' ); + stream << Colour( Colour::ResultExpectedFailure ) << std::string( failedButOkRatio, '=' ); + if( totals.testCases.allPassed() ) + stream << Colour( Colour::ResultSuccess ) << std::string( passedRatio, '=' ); + else + stream << Colour( Colour::Success ) << std::string( passedRatio, '=' ); + } + else { + stream << Colour( Colour::Warning ) << std::string( CATCH_CONFIG_CONSOLE_WIDTH-1, '=' ); + } + stream << "\n"; + } + void printSummaryDivider() { + stream << getLineOfChars<'-'>() << "\n"; + } + + private: + bool m_headerPrinted; + }; + + INTERNAL_CATCH_REGISTER_REPORTER( "console", ConsoleReporter ) + +} // end namespace Catch + +#endif // TWOBLUECUBES_CATCH_REPORTER_CONSOLE_HPP_INCLUDED diff --git a/unittest/Catch/include/reporters/catch_reporter_junit.hpp b/unittest/Catch/include/reporters/catch_reporter_junit.hpp new file mode 100644 index 0000000..e656882 --- /dev/null +++ b/unittest/Catch/include/reporters/catch_reporter_junit.hpp @@ -0,0 +1,223 @@ +/* + * Created by Phil on 26/11/2010. + * Copyright 2010 Two Blue Cubes Ltd. All rights reserved. + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + */ +#ifndef TWOBLUECUBES_CATCH_REPORTER_JUNIT_HPP_INCLUDED +#define TWOBLUECUBES_CATCH_REPORTER_JUNIT_HPP_INCLUDED + +#include "catch_reporter_bases.hpp" + +#include "../internal/catch_tostring.h" +#include "../internal/catch_reporter_registrars.hpp" +#include "../internal/catch_xmlwriter.hpp" + +#include <assert.h> + +namespace Catch { + + class JunitReporter : public CumulativeReporterBase { + public: + JunitReporter( ReporterConfig const& _config ) + : CumulativeReporterBase( _config ), + xml( _config.stream() ) + { + m_reporterPrefs.shouldRedirectStdOut = true; + } + + virtual ~JunitReporter() CATCH_OVERRIDE; + + static std::string getDescription() { + return "Reports test results in an XML format that looks like Ant's junitreport target"; + } + + virtual void noMatchingTestCases( std::string const& /*spec*/ ) CATCH_OVERRIDE {} + + virtual void testRunStarting( TestRunInfo const& runInfo ) CATCH_OVERRIDE { + CumulativeReporterBase::testRunStarting( runInfo ); + xml.startElement( "testsuites" ); + } + + virtual void testGroupStarting( GroupInfo const& groupInfo ) CATCH_OVERRIDE { + suiteTimer.start(); + stdOutForSuite.str(""); + stdErrForSuite.str(""); + unexpectedExceptions = 0; + CumulativeReporterBase::testGroupStarting( groupInfo ); + } + + virtual bool assertionEnded( AssertionStats const& assertionStats ) CATCH_OVERRIDE { + if( assertionStats.assertionResult.getResultType() == ResultWas::ThrewException ) + unexpectedExceptions++; + return CumulativeReporterBase::assertionEnded( assertionStats ); + } + + virtual void testCaseEnded( TestCaseStats const& testCaseStats ) CATCH_OVERRIDE { + stdOutForSuite << testCaseStats.stdOut; + stdErrForSuite << testCaseStats.stdErr; + CumulativeReporterBase::testCaseEnded( testCaseStats ); + } + + virtual void testGroupEnded( TestGroupStats const& testGroupStats ) CATCH_OVERRIDE { + double suiteTime = suiteTimer.getElapsedSeconds(); + CumulativeReporterBase::testGroupEnded( testGroupStats ); + writeGroup( *m_testGroups.back(), suiteTime ); + } + + virtual void testRunEndedCumulative() CATCH_OVERRIDE { + xml.endElement(); + } + + void writeGroup( TestGroupNode const& groupNode, double suiteTime ) { + XmlWriter::ScopedElement e = xml.scopedElement( "testsuite" ); + TestGroupStats const& stats = groupNode.value; + xml.writeAttribute( "name", stats.groupInfo.name ); + xml.writeAttribute( "errors", unexpectedExceptions ); + xml.writeAttribute( "failures", stats.totals.assertions.failed-unexpectedExceptions ); + xml.writeAttribute( "tests", stats.totals.assertions.total() ); + xml.writeAttribute( "hostname", "tbd" ); // !TBD + if( m_config->showDurations() == ShowDurations::Never ) + xml.writeAttribute( "time", "" ); + else + xml.writeAttribute( "time", suiteTime ); + xml.writeAttribute( "timestamp", "tbd" ); // !TBD + + // Write test cases + for( TestGroupNode::ChildNodes::const_iterator + it = groupNode.children.begin(), itEnd = groupNode.children.end(); + it != itEnd; + ++it ) + writeTestCase( **it ); + + xml.scopedElement( "system-out" ).writeText( trim( stdOutForSuite.str() ), false ); + xml.scopedElement( "system-err" ).writeText( trim( stdErrForSuite.str() ), false ); + } + + void writeTestCase( TestCaseNode const& testCaseNode ) { + TestCaseStats const& stats = testCaseNode.value; + + // All test cases have exactly one section - which represents the + // test case itself. That section may have 0-n nested sections + assert( testCaseNode.children.size() == 1 ); + SectionNode const& rootSection = *testCaseNode.children.front(); + + std::string className = stats.testInfo.className; + + if( className.empty() ) { + if( rootSection.childSections.empty() ) + className = "global"; + } + writeSection( className, "", rootSection ); + } + + void writeSection( std::string const& className, + std::string const& rootName, + SectionNode const& sectionNode ) { + std::string name = trim( sectionNode.stats.sectionInfo.name ); + if( !rootName.empty() ) + name = rootName + "/" + name; + + if( !sectionNode.assertions.empty() || + !sectionNode.stdOut.empty() || + !sectionNode.stdErr.empty() ) { + XmlWriter::ScopedElement e = xml.scopedElement( "testcase" ); + if( className.empty() ) { + xml.writeAttribute( "classname", name ); + xml.writeAttribute( "name", "root" ); + } + else { + xml.writeAttribute( "classname", className ); + xml.writeAttribute( "name", name ); + } + xml.writeAttribute( "time", Catch::toString( sectionNode.stats.durationInSeconds ) ); + + writeAssertions( sectionNode ); + + if( !sectionNode.stdOut.empty() ) + xml.scopedElement( "system-out" ).writeText( trim( sectionNode.stdOut ), false ); + if( !sectionNode.stdErr.empty() ) + xml.scopedElement( "system-err" ).writeText( trim( sectionNode.stdErr ), false ); + } + for( SectionNode::ChildSections::const_iterator + it = sectionNode.childSections.begin(), + itEnd = sectionNode.childSections.end(); + it != itEnd; + ++it ) + if( className.empty() ) + writeSection( name, "", **it ); + else + writeSection( className, name, **it ); + } + + void writeAssertions( SectionNode const& sectionNode ) { + for( SectionNode::Assertions::const_iterator + it = sectionNode.assertions.begin(), itEnd = sectionNode.assertions.end(); + it != itEnd; + ++it ) + writeAssertion( *it ); + } + void writeAssertion( AssertionStats const& stats ) { + AssertionResult const& result = stats.assertionResult; + if( !result.isOk() ) { + std::string elementName; + switch( result.getResultType() ) { + case ResultWas::ThrewException: + case ResultWas::FatalErrorCondition: + elementName = "error"; + break; + case ResultWas::ExplicitFailure: + elementName = "failure"; + break; + case ResultWas::ExpressionFailed: + elementName = "failure"; + break; + case ResultWas::DidntThrowException: + elementName = "failure"; + break; + + // We should never see these here: + case ResultWas::Info: + case ResultWas::Warning: + case ResultWas::Ok: + case ResultWas::Unknown: + case ResultWas::FailureBit: + case ResultWas::Exception: + elementName = "internalError"; + break; + } + + XmlWriter::ScopedElement e = xml.scopedElement( elementName ); + + xml.writeAttribute( "message", result.getExpandedExpression() ); + xml.writeAttribute( "type", result.getTestMacroName() ); + + std::ostringstream oss; + if( !result.getMessage().empty() ) + oss << result.getMessage() << "\n"; + for( std::vector<MessageInfo>::const_iterator + it = stats.infoMessages.begin(), + itEnd = stats.infoMessages.end(); + it != itEnd; + ++it ) + if( it->type == ResultWas::Info ) + oss << it->message << "\n"; + + oss << "at " << result.getSourceInfo(); + xml.writeText( oss.str(), false ); + } + } + + XmlWriter xml; + Timer suiteTimer; + std::ostringstream stdOutForSuite; + std::ostringstream stdErrForSuite; + unsigned int unexpectedExceptions; + }; + + INTERNAL_CATCH_REGISTER_REPORTER( "junit", JunitReporter ) + +} // end namespace Catch + +#endif // TWOBLUECUBES_CATCH_REPORTER_JUNIT_HPP_INCLUDED diff --git a/unittest/Catch/include/reporters/catch_reporter_multi.hpp b/unittest/Catch/include/reporters/catch_reporter_multi.hpp new file mode 100644 index 0000000..d328266 --- /dev/null +++ b/unittest/Catch/include/reporters/catch_reporter_multi.hpp @@ -0,0 +1,147 @@ +/* + * Created by Phil on 5/08/2015. + * Copyright 2015 Two Blue Cubes Ltd. All rights reserved. + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + */ +#ifndef TWOBLUECUBES_CATCH_REPORTER_MULTI_HPP_INCLUDED +#define TWOBLUECUBES_CATCH_REPORTER_MULTI_HPP_INCLUDED + +#include "../internal/catch_interfaces_reporter.h" + +namespace Catch { + +class MultipleReporters : public SharedImpl<IStreamingReporter> { + typedef std::vector<Ptr<IStreamingReporter> > Reporters; + Reporters m_reporters; + +public: + void add( Ptr<IStreamingReporter> const& reporter ) { + m_reporters.push_back( reporter ); + } + +public: // IStreamingReporter + + virtual ReporterPreferences getPreferences() const CATCH_OVERRIDE { + return m_reporters[0]->getPreferences(); + } + + virtual void noMatchingTestCases( std::string const& spec ) CATCH_OVERRIDE { + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + (*it)->noMatchingTestCases( spec ); + } + + + virtual void testRunStarting( TestRunInfo const& testRunInfo ) CATCH_OVERRIDE { + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + (*it)->testRunStarting( testRunInfo ); + } + + virtual void testGroupStarting( GroupInfo const& groupInfo ) CATCH_OVERRIDE { + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + (*it)->testGroupStarting( groupInfo ); + } + + + virtual void testCaseStarting( TestCaseInfo const& testInfo ) CATCH_OVERRIDE { + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + (*it)->testCaseStarting( testInfo ); + } + + virtual void sectionStarting( SectionInfo const& sectionInfo ) CATCH_OVERRIDE { + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + (*it)->sectionStarting( sectionInfo ); + } + + + virtual void assertionStarting( AssertionInfo const& assertionInfo ) CATCH_OVERRIDE { + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + (*it)->assertionStarting( assertionInfo ); + } + + + // The return value indicates if the messages buffer should be cleared: + virtual bool assertionEnded( AssertionStats const& assertionStats ) CATCH_OVERRIDE { + bool clearBuffer = false; + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + clearBuffer |= (*it)->assertionEnded( assertionStats ); + return clearBuffer; + } + + virtual void sectionEnded( SectionStats const& sectionStats ) CATCH_OVERRIDE { + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + (*it)->sectionEnded( sectionStats ); + } + + virtual void testCaseEnded( TestCaseStats const& testCaseStats ) CATCH_OVERRIDE { + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + (*it)->testCaseEnded( testCaseStats ); + } + + virtual void testGroupEnded( TestGroupStats const& testGroupStats ) CATCH_OVERRIDE { + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + (*it)->testGroupEnded( testGroupStats ); + } + + virtual void testRunEnded( TestRunStats const& testRunStats ) CATCH_OVERRIDE { + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + (*it)->testRunEnded( testRunStats ); + } + + + virtual void skipTest( TestCaseInfo const& testInfo ) CATCH_OVERRIDE { + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + (*it)->skipTest( testInfo ); + } +}; + +Ptr<IStreamingReporter> addReporter( Ptr<IStreamingReporter> const& existingReporter, Ptr<IStreamingReporter> const& additionalReporter ) { + Ptr<IStreamingReporter> resultingReporter; + + if( existingReporter ) { + MultipleReporters* multi = dynamic_cast<MultipleReporters*>( existingReporter.get() ); + if( !multi ) { + multi = new MultipleReporters; + resultingReporter = Ptr<IStreamingReporter>( multi ); + if( existingReporter ) + multi->add( existingReporter ); + } + else + resultingReporter = existingReporter; + multi->add( additionalReporter ); + } + else + resultingReporter = additionalReporter; + + return resultingReporter; +} + + +} // end namespace Catch + +#endif // TWOBLUECUBES_CATCH_REPORTER_MULTI_HPP_INCLUDED diff --git a/unittest/Catch/include/reporters/catch_reporter_teamcity.hpp b/unittest/Catch/include/reporters/catch_reporter_teamcity.hpp new file mode 100644 index 0000000..1e633f1 --- /dev/null +++ b/unittest/Catch/include/reporters/catch_reporter_teamcity.hpp @@ -0,0 +1,221 @@ +/* + * Created by Phil Nash on 19th December 2014 + * Copyright 2014 Two Blue Cubes Ltd. All rights reserved. + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + */ +#ifndef TWOBLUECUBES_CATCH_REPORTER_TEAMCITY_HPP_INCLUDED +#define TWOBLUECUBES_CATCH_REPORTER_TEAMCITY_HPP_INCLUDED + +// Don't #include any Catch headers here - we can assume they are already +// included before this header. +// This is not good practice in general but is necessary in this case so this +// file can be distributed as a single header that works with the main +// Catch single header. + +#include <cstring> + +#ifdef __clang__ +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wpadded" +# pragma clang diagnostic ignored "-Wc++98-compat" +# pragma clang diagnostic ignored "-Wc++98-compat-pedantic" +#endif + +namespace Catch { + + struct TeamCityReporter : StreamingReporterBase { + TeamCityReporter( ReporterConfig const& _config ) + : StreamingReporterBase( _config ), + m_headerPrintedForThisSection( false ) + { + m_reporterPrefs.shouldRedirectStdOut = true; + } + + static std::string escape( std::string const& str ) { + std::string escaped = str; + replaceInPlace( escaped, "|", "||" ); + replaceInPlace( escaped, "'", "|'" ); + replaceInPlace( escaped, "\n", "|n" ); + replaceInPlace( escaped, "\r", "|r" ); + replaceInPlace( escaped, "[", "|[" ); + replaceInPlace( escaped, "]", "|]" ); + return escaped; + } + virtual ~TeamCityReporter() CATCH_OVERRIDE; + + static std::string getDescription() { + return "Reports test results as TeamCity service messages"; + } + + virtual void skipTest( TestCaseInfo const& testInfo ) CATCH_OVERRIDE { + stream << "##teamcity[testIgnored name='" + << escape( testInfo.name ) << "'"; + if( testInfo.isHidden() ) + stream << " message='hidden test'"; + else + stream << " message='test skipped because it didn|'t match the test spec'"; + stream << "]\n"; + } + + virtual void noMatchingTestCases( std::string const& /* spec */ ) CATCH_OVERRIDE {} + + virtual void testGroupStarting( GroupInfo const& groupInfo ) CATCH_OVERRIDE { + StreamingReporterBase::testGroupStarting( groupInfo ); + stream << "##teamcity[testSuiteStarted name='" + << escape( groupInfo.name ) << "']\n"; + } + virtual void testGroupEnded( TestGroupStats const& testGroupStats ) CATCH_OVERRIDE { + StreamingReporterBase::testGroupEnded( testGroupStats ); + stream << "##teamcity[testSuiteFinished name='" + << escape( testGroupStats.groupInfo.name ) << "']\n"; + } + + + virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE { + } + + virtual bool assertionEnded( AssertionStats const& assertionStats ) CATCH_OVERRIDE { + AssertionResult const& result = assertionStats.assertionResult; + if( !result.isOk() ) { + + std::ostringstream msg; + if( !m_headerPrintedForThisSection ) + printSectionHeader( msg ); + m_headerPrintedForThisSection = true; + + msg << result.getSourceInfo() << "\n"; + + switch( result.getResultType() ) { + case ResultWas::ExpressionFailed: + msg << "expression failed"; + break; + case ResultWas::ThrewException: + msg << "unexpected exception"; + break; + case ResultWas::FatalErrorCondition: + msg << "fatal error condition"; + break; + case ResultWas::DidntThrowException: + msg << "no exception was thrown where one was expected"; + break; + case ResultWas::ExplicitFailure: + msg << "explicit failure"; + break; + + // We shouldn't get here because of the isOk() test + case ResultWas::Ok: + case ResultWas::Info: + case ResultWas::Warning: + + // These cases are here to prevent compiler warnings + case ResultWas::Unknown: + case ResultWas::FailureBit: + case ResultWas::Exception: + CATCH_NOT_IMPLEMENTED; + } + if( assertionStats.infoMessages.size() == 1 ) + msg << " with message:"; + if( assertionStats.infoMessages.size() > 1 ) + msg << " with messages:"; + for( std::vector<MessageInfo>::const_iterator + it = assertionStats.infoMessages.begin(), + itEnd = assertionStats.infoMessages.end(); + it != itEnd; + ++it ) + msg << "\n \"" << it->message << "\""; + + + if( result.hasExpression() ) { + msg << + "\n " << result.getExpressionInMacro() << "\n" + "with expansion:\n" << + " " << result.getExpandedExpression() << "\n"; + } + + stream << "##teamcity[testFailed" + << " name='" << escape( currentTestCaseInfo->name )<< "'" + << " message='" << escape( msg.str() ) << "'" + << "]\n"; + } + return true; + } + + virtual void sectionStarting( SectionInfo const& sectionInfo ) CATCH_OVERRIDE { + m_headerPrintedForThisSection = false; + StreamingReporterBase::sectionStarting( sectionInfo ); + } + + virtual void testCaseStarting( TestCaseInfo const& testInfo ) CATCH_OVERRIDE { + StreamingReporterBase::testCaseStarting( testInfo ); + stream << "##teamcity[testStarted name='" + << escape( testInfo.name ) << "']\n"; + } + + virtual void testCaseEnded( TestCaseStats const& testCaseStats ) CATCH_OVERRIDE { + StreamingReporterBase::testCaseEnded( testCaseStats ); + if( !testCaseStats.stdOut.empty() ) + stream << "##teamcity[testStdOut name='" + << escape( testCaseStats.testInfo.name ) + << "' out='" << escape( testCaseStats.stdOut ) << "']\n"; + if( !testCaseStats.stdErr.empty() ) + stream << "##teamcity[testStdErr name='" + << escape( testCaseStats.testInfo.name ) + << "' out='" << escape( testCaseStats.stdErr ) << "']\n"; + stream << "##teamcity[testFinished name='" + << escape( testCaseStats.testInfo.name ) << "']\n"; + } + + private: + void printSectionHeader( std::ostream& os ) { + assert( !m_sectionStack.empty() ); + + if( m_sectionStack.size() > 1 ) { + os << getLineOfChars<'-'>() << "\n"; + + std::vector<SectionInfo>::const_iterator + it = m_sectionStack.begin()+1, // Skip first section (test case) + itEnd = m_sectionStack.end(); + for( ; it != itEnd; ++it ) + printHeaderString( os, it->name ); + os << getLineOfChars<'-'>() << "\n"; + } + + SourceLineInfo lineInfo = m_sectionStack.front().lineInfo; + + if( !lineInfo.empty() ) + os << lineInfo << "\n"; + os << getLineOfChars<'.'>() << "\n\n"; + } + + // if string has a : in first line will set indent to follow it on + // subsequent lines + void printHeaderString( std::ostream& os, std::string const& _string, std::size_t indent = 0 ) { + std::size_t i = _string.find( ": " ); + if( i != std::string::npos ) + i+=2; + else + i = 0; + os << Text( _string, TextAttributes() + .setIndent( indent+i) + .setInitialIndent( indent ) ) << "\n"; + } + private: + bool m_headerPrintedForThisSection; + + }; + +#ifdef CATCH_IMPL + TeamCityReporter::~TeamCityReporter() {} +#endif + + INTERNAL_CATCH_REGISTER_REPORTER( "teamcity", TeamCityReporter ) + +} // end namespace Catch + +#ifdef __clang__ +# pragma clang diagnostic pop +#endif + +#endif // TWOBLUECUBES_CATCH_REPORTER_TEAMCITY_HPP_INCLUDED diff --git a/unittest/Catch/include/reporters/catch_reporter_xml.hpp b/unittest/Catch/include/reporters/catch_reporter_xml.hpp new file mode 100644 index 0000000..bbe8780 --- /dev/null +++ b/unittest/Catch/include/reporters/catch_reporter_xml.hpp @@ -0,0 +1,199 @@ +/* + * Created by Phil on 28/10/2010. + * Copyright 2010 Two Blue Cubes Ltd. All rights reserved. + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + */ +#ifndef TWOBLUECUBES_CATCH_REPORTER_XML_HPP_INCLUDED +#define TWOBLUECUBES_CATCH_REPORTER_XML_HPP_INCLUDED + +#include "catch_reporter_bases.hpp" + +#include "../internal/catch_capture.hpp" +#include "../internal/catch_reporter_registrars.hpp" +#include "../internal/catch_xmlwriter.hpp" +#include "../internal/catch_timer.h" + +namespace Catch { + class XmlReporter : public StreamingReporterBase { + public: + XmlReporter( ReporterConfig const& _config ) + : StreamingReporterBase( _config ), + m_sectionDepth( 0 ) + { + m_reporterPrefs.shouldRedirectStdOut = true; + } + + virtual ~XmlReporter() CATCH_OVERRIDE; + + static std::string getDescription() { + return "Reports test results as an XML document"; + } + + public: // StreamingReporterBase + + virtual void noMatchingTestCases( std::string const& s ) CATCH_OVERRIDE { + StreamingReporterBase::noMatchingTestCases( s ); + } + + virtual void testRunStarting( TestRunInfo const& testInfo ) CATCH_OVERRIDE { + StreamingReporterBase::testRunStarting( testInfo ); + m_xml.setStream( stream ); + m_xml.startElement( "Catch" ); + if( !m_config->name().empty() ) + m_xml.writeAttribute( "name", m_config->name() ); + } + + virtual void testGroupStarting( GroupInfo const& groupInfo ) CATCH_OVERRIDE { + StreamingReporterBase::testGroupStarting( groupInfo ); + m_xml.startElement( "Group" ) + .writeAttribute( "name", groupInfo.name ); + } + + virtual void testCaseStarting( TestCaseInfo const& testInfo ) CATCH_OVERRIDE { + StreamingReporterBase::testCaseStarting(testInfo); + m_xml.startElement( "TestCase" ).writeAttribute( "name", trim( testInfo.name ) ); + + if ( m_config->showDurations() == ShowDurations::Always ) + m_testCaseTimer.start(); + } + + virtual void sectionStarting( SectionInfo const& sectionInfo ) CATCH_OVERRIDE { + StreamingReporterBase::sectionStarting( sectionInfo ); + if( m_sectionDepth++ > 0 ) { + m_xml.startElement( "Section" ) + .writeAttribute( "name", trim( sectionInfo.name ) ) + .writeAttribute( "description", sectionInfo.description ); + } + } + + virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE { } + + virtual bool assertionEnded( AssertionStats const& assertionStats ) CATCH_OVERRIDE { + const AssertionResult& assertionResult = assertionStats.assertionResult; + + // Print any info messages in <Info> tags. + if( assertionStats.assertionResult.getResultType() != ResultWas::Ok ) { + for( std::vector<MessageInfo>::const_iterator it = assertionStats.infoMessages.begin(), itEnd = assertionStats.infoMessages.end(); + it != itEnd; + ++it ) { + if( it->type == ResultWas::Info ) { + m_xml.scopedElement( "Info" ) + .writeText( it->message ); + } else if ( it->type == ResultWas::Warning ) { + m_xml.scopedElement( "Warning" ) + .writeText( it->message ); + } + } + } + + // Drop out if result was successful but we're not printing them. + if( !m_config->includeSuccessfulResults() && isOk(assertionResult.getResultType()) ) + return true; + + // Print the expression if there is one. + if( assertionResult.hasExpression() ) { + m_xml.startElement( "Expression" ) + .writeAttribute( "success", assertionResult.succeeded() ) + .writeAttribute( "type", assertionResult.getTestMacroName() ) + .writeAttribute( "filename", assertionResult.getSourceInfo().file ) + .writeAttribute( "line", assertionResult.getSourceInfo().line ); + + m_xml.scopedElement( "Original" ) + .writeText( assertionResult.getExpression() ); + m_xml.scopedElement( "Expanded" ) + .writeText( assertionResult.getExpandedExpression() ); + } + + // And... Print a result applicable to each result type. + switch( assertionResult.getResultType() ) { + case ResultWas::ThrewException: + m_xml.scopedElement( "Exception" ) + .writeAttribute( "filename", assertionResult.getSourceInfo().file ) + .writeAttribute( "line", assertionResult.getSourceInfo().line ) + .writeText( assertionResult.getMessage() ); + break; + case ResultWas::FatalErrorCondition: + m_xml.scopedElement( "Fatal Error Condition" ) + .writeAttribute( "filename", assertionResult.getSourceInfo().file ) + .writeAttribute( "line", assertionResult.getSourceInfo().line ) + .writeText( assertionResult.getMessage() ); + break; + case ResultWas::Info: + m_xml.scopedElement( "Info" ) + .writeText( assertionResult.getMessage() ); + break; + case ResultWas::Warning: + // Warning will already have been written + break; + case ResultWas::ExplicitFailure: + m_xml.scopedElement( "Failure" ) + .writeText( assertionResult.getMessage() ); + break; + default: + break; + } + + if( assertionResult.hasExpression() ) + m_xml.endElement(); + + return true; + } + + virtual void sectionEnded( SectionStats const& sectionStats ) CATCH_OVERRIDE { + StreamingReporterBase::sectionEnded( sectionStats ); + if( --m_sectionDepth > 0 ) { + XmlWriter::ScopedElement e = m_xml.scopedElement( "OverallResults" ); + e.writeAttribute( "successes", sectionStats.assertions.passed ); + e.writeAttribute( "failures", sectionStats.assertions.failed ); + e.writeAttribute( "expectedFailures", sectionStats.assertions.failedButOk ); + + if ( m_config->showDurations() == ShowDurations::Always ) + e.writeAttribute( "durationInSeconds", sectionStats.durationInSeconds ); + + m_xml.endElement(); + } + } + + virtual void testCaseEnded( TestCaseStats const& testCaseStats ) CATCH_OVERRIDE { + StreamingReporterBase::testCaseEnded( testCaseStats ); + XmlWriter::ScopedElement e = m_xml.scopedElement( "OverallResult" ); + e.writeAttribute( "success", testCaseStats.totals.assertions.allOk() ); + + if ( m_config->showDurations() == ShowDurations::Always ) + e.writeAttribute( "durationInSeconds", m_testCaseTimer.getElapsedSeconds() ); + + m_xml.endElement(); + } + + virtual void testGroupEnded( TestGroupStats const& testGroupStats ) CATCH_OVERRIDE { + StreamingReporterBase::testGroupEnded( testGroupStats ); + // TODO: Check testGroupStats.aborting and act accordingly. + m_xml.scopedElement( "OverallResults" ) + .writeAttribute( "successes", testGroupStats.totals.assertions.passed ) + .writeAttribute( "failures", testGroupStats.totals.assertions.failed ) + .writeAttribute( "expectedFailures", testGroupStats.totals.assertions.failedButOk ); + m_xml.endElement(); + } + + virtual void testRunEnded( TestRunStats const& testRunStats ) CATCH_OVERRIDE { + StreamingReporterBase::testRunEnded( testRunStats ); + m_xml.scopedElement( "OverallResults" ) + .writeAttribute( "successes", testRunStats.totals.assertions.passed ) + .writeAttribute( "failures", testRunStats.totals.assertions.failed ) + .writeAttribute( "expectedFailures", testRunStats.totals.assertions.failedButOk ); + m_xml.endElement(); + } + + private: + Timer m_testCaseTimer; + XmlWriter m_xml; + int m_sectionDepth; + }; + + INTERNAL_CATCH_REGISTER_REPORTER( "xml", XmlReporter ) + +} // end namespace Catch + +#endif // TWOBLUECUBES_CATCH_REPORTER_XML_HPP_INCLUDED diff --git a/unittest/Catch/projects/CMake/CMakeLists.txt b/unittest/Catch/projects/CMake/CMakeLists.txt new file mode 100644 index 0000000..960d9fb --- /dev/null +++ b/unittest/Catch/projects/CMake/CMakeLists.txt @@ -0,0 +1,48 @@ +cmake_minimum_required(VERSION 2.8) + +project(Catch) + +# define some folders +get_filename_component(CATCH_DIR "${CMAKE_CURRENT_SOURCE_DIR}" PATH) +get_filename_component(CATCH_DIR "${CATCH_DIR}" PATH) +set(SELF_TEST_DIR ${CATCH_DIR}/projects/SelfTest) +if(USE_CPP11) + ## We can't turn this on by default, since it breaks on travis + message(STATUS "Enabling C++11") + set(CMAKE_CXX_FLAGS "-std=c++11 ${CMAKE_CXX_FLAGS}") +endif() + +# define the sources of the self test +set(SOURCES + ${SELF_TEST_DIR}/ApproxTests.cpp + ${SELF_TEST_DIR}/BDDTests.cpp + ${SELF_TEST_DIR}/ClassTests.cpp + ${SELF_TEST_DIR}/ConditionTests.cpp + ${SELF_TEST_DIR}/ExceptionTests.cpp + ${SELF_TEST_DIR}/GeneratorTests.cpp + ${SELF_TEST_DIR}/MessageTests.cpp + ${SELF_TEST_DIR}/MiscTests.cpp + ${SELF_TEST_DIR}/PartTrackerTests.cpp + ${SELF_TEST_DIR}/TestMain.cpp + ${SELF_TEST_DIR}/TrickyTests.cpp + ${SELF_TEST_DIR}/VariadicMacrosTests.cpp + ${SELF_TEST_DIR}/EnumToString.cpp + ${SELF_TEST_DIR}/ToStringPair.cpp + ${SELF_TEST_DIR}/ToStringVector.cpp + ${SELF_TEST_DIR}/ToStringWhich.cpp + ${SELF_TEST_DIR}/ToStringTuple.cpp +) + +# configure the executable +include_directories(${CATCH_DIR}/include) +add_executable(SelfTest ${SOURCES}) + +# configure unit tests via CTest +enable_testing() +add_test(NAME RunTests COMMAND SelfTest) + +add_test(NAME ListTests COMMAND SelfTest --list-tests) +set_tests_properties(ListTests PROPERTIES PASS_REGULAR_EXPRESSION "[0-9]+ test cases") + +add_test(NAME ListTags COMMAND SelfTest --list-tags) +set_tests_properties(ListTags PROPERTIES PASS_REGULAR_EXPRESSION "[0-9]+ tags") diff --git a/unittest/Catch/projects/SelfTest/ApproxTests.cpp b/unittest/Catch/projects/SelfTest/ApproxTests.cpp new file mode 100644 index 0000000..5365659 --- /dev/null +++ b/unittest/Catch/projects/SelfTest/ApproxTests.cpp @@ -0,0 +1,112 @@ +/* + * Created by Phil on 28/04/2011. + * Copyright 2011 Two Blue Cubes Ltd. All rights reserved. + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + */ + +#include "catch.hpp" + +/////////////////////////////////////////////////////////////////////////////// +TEST_CASE +( + "Some simple comparisons between doubles", + "[Approx]" +) +{ + double d = 1.23; + + REQUIRE( d == Approx( 1.23 ) ); + REQUIRE( d != Approx( 1.22 ) ); + REQUIRE( d != Approx( 1.24 ) ); + + REQUIRE( Approx( d ) == 1.23 ); + REQUIRE( Approx( d ) != 1.22 ); + REQUIRE( Approx( d ) != 1.24 ); +} + +/////////////////////////////////////////////////////////////////////////////// +TEST_CASE +( + "Approximate comparisons with different epsilons", + "[Approx]" + ) +{ + double d = 1.23; + + REQUIRE( d != Approx( 1.231 ) ); + REQUIRE( d == Approx( 1.231 ).epsilon( 0.1 ) ); +} + +/////////////////////////////////////////////////////////////////////////////// +TEST_CASE +( + "Approximate comparisons with floats", + "[Approx]" +) +{ + REQUIRE( 1.23f == Approx( 1.23f ) ); + REQUIRE( 0.0f == Approx( 0.0f ) ); +} + +/////////////////////////////////////////////////////////////////////////////// +TEST_CASE +( + "Approximate comparisons with ints", + "[Approx]" +) +{ + REQUIRE( 1 == Approx( 1 ) ); + REQUIRE( 0 == Approx( 0 ) ); +} + +/////////////////////////////////////////////////////////////////////////////// +TEST_CASE +( + "Approximate comparisons with mixed numeric types", + "[Approx]" +) +{ + const double dZero = 0; + const double dSmall = 0.00001; + const double dMedium = 1.234; + + REQUIRE( 1.0f == Approx( 1 ) ); + REQUIRE( 0 == Approx( dZero) ); + REQUIRE( 0 == Approx( dSmall ).epsilon( 0.001 ) ); + REQUIRE( 1.234f == Approx( dMedium ) ); + REQUIRE( dMedium == Approx( 1.234f ) ); +} + +/////////////////////////////////////////////////////////////////////////////// +TEST_CASE +( + "Use a custom approx", + "[Approx][custom]" +) +{ + double d = 1.23; + + Approx approx = Approx::custom().epsilon( 0.005 ); + + REQUIRE( d == approx( 1.23 ) ); + REQUIRE( d == approx( 1.22 ) ); + REQUIRE( d == approx( 1.24 ) ); + REQUIRE( d != approx( 1.25 ) ); + + REQUIRE( approx( d ) == 1.23 ); + REQUIRE( approx( d ) == 1.22 ); + REQUIRE( approx( d ) == 1.24 ); + REQUIRE( approx( d ) != 1.25 ); +} + +inline double divide( double a, double b ) { + return a/b; +} + +TEST_CASE( "Approximate PI", "[Approx][PI]" ) +{ + REQUIRE( divide( 22, 7 ) == Approx( 3.141 ).epsilon( 0.001 ) ); + REQUIRE( divide( 22, 7 ) != Approx( 3.141 ).epsilon( 0.0001 ) ); +} diff --git a/unittest/Catch/projects/SelfTest/BDDTests.cpp b/unittest/Catch/projects/SelfTest/BDDTests.cpp new file mode 100644 index 0000000..2c8bc24 --- /dev/null +++ b/unittest/Catch/projects/SelfTest/BDDTests.cpp @@ -0,0 +1,103 @@ +/* + * Created by Phil on 29/11/2010. + * Copyright 2010 Two Blue Cubes Ltd. All rights reserved. + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + */ + +#include "catch.hpp" + +inline bool itDoesThis(){ return true; } +inline bool itDoesThat(){ return true; } + +SCENARIO( "Do that thing with the thing", "[Tags]" ) { + GIVEN( "This stuff exists" ) { + // make stuff exist + WHEN( "I do this" ) { + // do this + THEN( "it should do this") + { + REQUIRE( itDoesThis() ); + AND_THEN( "do that") + REQUIRE( itDoesThat() ); + } + } + } +} + +SCENARIO( "Vector resizing affects size and capacity", "[vector][bdd][size][capacity]" ) { + GIVEN( "an empty vector" ) { + std::vector<int> v; + REQUIRE( v.size() == 0 ); + + WHEN( "it is made larger" ) { + v.resize( 10 ); + THEN( "the size and capacity go up" ) { + REQUIRE( v.size() == 10 ); + REQUIRE( v.capacity() >= 10 ); + + AND_WHEN( "it is made smaller again" ) { + v.resize( 5 ); + THEN( "the size goes down but the capacity stays the same" ) { + REQUIRE( v.size() == 5 ); + REQUIRE( v.capacity() >= 10 ); + } + } + } + } + + WHEN( "we reserve more space" ) { + v.reserve( 10 ); + THEN( "The capacity is increased but the size remains the same" ) { + REQUIRE( v.capacity() >= 10 ); + REQUIRE( v.size() == 0 ); + } + } + } +} + +SCENARIO( "This is a really long scenario name to see how the list command deals with wrapping", + "[very long tags][lots][long][tags][verbose]" + "[one very long tag name that should cause line wrapping writing out using the list command]" + "[anotherReallyLongTagNameButThisOneHasNoObviousWrapPointsSoShouldSplitWithinAWordUsingADashCharacter]" ) { + GIVEN( "A section name that is so long that it cannot fit in a single console width" ) + WHEN( "The test headers are printed as part of the normal running of the scenario" ) + THEN( "The, deliberately very long and overly verbose (you see what I did there?) section names must wrap, along with an indent" ) + SUCCEED("boo!"); +} + +namespace { + +// a trivial fixture example to support SCENARIO_METHOD tests +struct Fixture +{ + Fixture() + : d_counter(0) + { + } + + int counter() + { + return d_counter++; + } + + int d_counter; +}; + +} + +SCENARIO_METHOD(Fixture, + "BDD tests requiring Fixtures to provide commonly-accessed data or methods", + "[bdd][fixtures]") { + const int before(counter()); + GIVEN("No operations precede me") { + REQUIRE(before == 0); + WHEN("We get the count") { + const int after(counter()); + THEN("Subsequently values are higher") { + REQUIRE(after > before); + } + } + } +} diff --git a/unittest/Catch/projects/SelfTest/Baselines/console.std.approved.txt b/unittest/Catch/projects/SelfTest/Baselines/console.std.approved.txt new file mode 100644 index 0000000..29870b9 --- /dev/null +++ b/unittest/Catch/projects/SelfTest/Baselines/console.std.approved.txt @@ -0,0 +1,835 @@ + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +CatchSelfTest is a <version> host application. +Run with -? for options + +------------------------------------------------------------------------------- +A METHOD_AS_TEST_CASE based test run that fails +------------------------------------------------------------------------------- +ClassTests.cpp:<line number> +............................................................................... + +ClassTests.cpp:<line number>: FAILED: + REQUIRE( s == "world" ) +with expansion: + "hello" == "world" + +------------------------------------------------------------------------------- +A TEST_CASE_METHOD based test run that fails +------------------------------------------------------------------------------- +ClassTests.cpp:<line number> +............................................................................... + +ClassTests.cpp:<line number>: FAILED: + REQUIRE( m_a == 2 ) +with expansion: + 1 == 2 + +------------------------------------------------------------------------------- +Equality checks that should fail +------------------------------------------------------------------------------- +ConditionTests.cpp:<line number> +............................................................................... + +ConditionTests.cpp:<line number>: FAILED: + CHECK( data.int_seven == 6 ) +with expansion: + 7 == 6 + +ConditionTests.cpp:<line number>: FAILED: + CHECK( data.int_seven == 8 ) +with expansion: + 7 == 8 + +ConditionTests.cpp:<line number>: FAILED: + CHECK( data.int_seven == 0 ) +with expansion: + 7 == 0 + +ConditionTests.cpp:<line number>: FAILED: + CHECK( data.float_nine_point_one == Approx( 9.11f ) ) +with expansion: + 9.1f == Approx( 9.1099996567 ) + +ConditionTests.cpp:<line number>: FAILED: + CHECK( data.float_nine_point_one == Approx( 9.0f ) ) +with expansion: + 9.1f == Approx( 9.0 ) + +ConditionTests.cpp:<line number>: FAILED: + CHECK( data.float_nine_point_one == Approx( 1 ) ) +with expansion: + 9.1f == Approx( 1.0 ) + +ConditionTests.cpp:<line number>: FAILED: + CHECK( data.float_nine_point_one == Approx( 0 ) ) +with expansion: + 9.1f == Approx( 0.0 ) + +ConditionTests.cpp:<line number>: FAILED: + CHECK( data.double_pi == Approx( 3.1415 ) ) +with expansion: + 3.1415926535 == Approx( 3.1415 ) + +ConditionTests.cpp:<line number>: FAILED: + CHECK( data.str_hello == "goodbye" ) +with expansion: + "hello" == "goodbye" + +ConditionTests.cpp:<line number>: FAILED: + CHECK( data.str_hello == "hell" ) +with expansion: + "hello" == "hell" + +ConditionTests.cpp:<line number>: FAILED: + CHECK( data.str_hello == "hello1" ) +with expansion: + "hello" == "hello1" + +ConditionTests.cpp:<line number>: FAILED: + CHECK( data.str_hello.size() == 6 ) +with expansion: + 5 == 6 + +ConditionTests.cpp:<line number>: FAILED: + CHECK( x == Approx( 1.301 ) ) +with expansion: + 1.3 == Approx( 1.301 ) + +------------------------------------------------------------------------------- +Inequality checks that should fail +------------------------------------------------------------------------------- +ConditionTests.cpp:<line number> +............................................................................... + +ConditionTests.cpp:<line number>: FAILED: + CHECK( data.int_seven != 7 ) +with expansion: + 7 != 7 + +ConditionTests.cpp:<line number>: FAILED: + CHECK( data.float_nine_point_one != Approx( 9.1f ) ) +with expansion: + 9.1f != Approx( 9.1000003815 ) + +ConditionTests.cpp:<line number>: FAILED: + CHECK( data.double_pi != Approx( 3.1415926535 ) ) +with expansion: + 3.1415926535 != Approx( 3.1415926535 ) + +ConditionTests.cpp:<line number>: FAILED: + CHECK( data.str_hello != "hello" ) +with expansion: + "hello" != "hello" + +ConditionTests.cpp:<line number>: FAILED: + CHECK( data.str_hello.size() != 5 ) +with expansion: + 5 != 5 + +------------------------------------------------------------------------------- +Ordering comparison checks that should fail +------------------------------------------------------------------------------- +ConditionTests.cpp:<line number> +............................................................................... + +ConditionTests.cpp:<line number>: FAILED: + CHECK( data.int_seven > 7 ) +with expansion: + 7 > 7 + +ConditionTests.cpp:<line number>: FAILED: + CHECK( data.int_seven < 7 ) +with expansion: + 7 < 7 + +ConditionTests.cpp:<line number>: FAILED: + CHECK( data.int_seven > 8 ) +with expansion: + 7 > 8 + +ConditionTests.cpp:<line number>: FAILED: + CHECK( data.int_seven < 6 ) +with expansion: + 7 < 6 + +ConditionTests.cpp:<line number>: FAILED: + CHECK( data.int_seven < 0 ) +with expansion: + 7 < 0 + +ConditionTests.cpp:<line number>: FAILED: + CHECK( data.int_seven < -1 ) +with expansion: + 7 < -1 + +ConditionTests.cpp:<line number>: FAILED: + CHECK( data.int_seven >= 8 ) +with expansion: + 7 >= 8 + +ConditionTests.cpp:<line number>: FAILED: + CHECK( data.int_seven <= 6 ) +with expansion: + 7 <= 6 + +ConditionTests.cpp:<line number>: FAILED: + CHECK( data.float_nine_point_one < 9 ) +with expansion: + 9.1f < 9 + +ConditionTests.cpp:<line number>: FAILED: + CHECK( data.float_nine_point_one > 10 ) +with expansion: + 9.1f > 10 + +ConditionTests.cpp:<line number>: FAILED: + CHECK( data.float_nine_point_one > 9.2 ) +with expansion: + 9.1f > 9.2 + +ConditionTests.cpp:<line number>: FAILED: + CHECK( data.str_hello > "hello" ) +with expansion: + "hello" > "hello" + +ConditionTests.cpp:<line number>: FAILED: + CHECK( data.str_hello < "hello" ) +with expansion: + "hello" < "hello" + +ConditionTests.cpp:<line number>: FAILED: + CHECK( data.str_hello > "hellp" ) +with expansion: + "hello" > "hellp" + +ConditionTests.cpp:<line number>: FAILED: + CHECK( data.str_hello > "z" ) +with expansion: + "hello" > "z" + +ConditionTests.cpp:<line number>: FAILED: + CHECK( data.str_hello < "hellm" ) +with expansion: + "hello" < "hellm" + +ConditionTests.cpp:<line number>: FAILED: + CHECK( data.str_hello < "a" ) +with expansion: + "hello" < "a" + +ConditionTests.cpp:<line number>: FAILED: + CHECK( data.str_hello >= "z" ) +with expansion: + "hello" >= "z" + +ConditionTests.cpp:<line number>: FAILED: + CHECK( data.str_hello <= "a" ) +with expansion: + "hello" <= "a" + +------------------------------------------------------------------------------- +'Not' checks that should fail +------------------------------------------------------------------------------- +ConditionTests.cpp:<line number> +............................................................................... + +ConditionTests.cpp:<line number>: FAILED: + CHECK( false != false ) + +ConditionTests.cpp:<line number>: FAILED: + CHECK( true != true ) + +ConditionTests.cpp:<line number>: FAILED: + CHECK( !true ) +with expansion: + false + +ConditionTests.cpp:<line number>: FAILED: + CHECK_FALSE( true ) + +ConditionTests.cpp:<line number>: FAILED: + CHECK( !trueValue ) +with expansion: + false + +ConditionTests.cpp:<line number>: FAILED: + CHECK_FALSE( trueValue ) +with expansion: + !true + +ConditionTests.cpp:<line number>: FAILED: + CHECK( !(1 == 1) ) +with expansion: + false + +ConditionTests.cpp:<line number>: FAILED: + CHECK_FALSE( 1 == 1 ) +with expansion: + !(1 == 1) + +------------------------------------------------------------------------------- +Expected exceptions that don't throw or unexpected exceptions fail the test +------------------------------------------------------------------------------- +ExceptionTests.cpp:<line number> +............................................................................... + +ExceptionTests.cpp:<line number>: FAILED: + CHECK_THROWS_AS( thisThrows() ) +due to unexpected exception with message: + expected exception + +ExceptionTests.cpp:<line number>: FAILED: + CHECK_THROWS_AS( thisDoesntThrow() ) +because no exception was thrown where one was expected: + +ExceptionTests.cpp:<line number>: FAILED: + CHECK_NOTHROW( thisThrows() ) +due to unexpected exception with message: + expected exception + +------------------------------------------------------------------------------- +When unchecked exceptions are thrown directly they are always failures +------------------------------------------------------------------------------- +ExceptionTests.cpp:<line number> +............................................................................... + +ExceptionTests.cpp:<line number>: FAILED: +due to unexpected exception with message: + unexpected exception + +------------------------------------------------------------------------------- +An unchecked exception reports the line of the last assertion +------------------------------------------------------------------------------- +ExceptionTests.cpp:<line number> +............................................................................... + +ExceptionTests.cpp:<line number>: FAILED: + {Unknown expression after the reported line} +due to unexpected exception with message: + unexpected exception + +------------------------------------------------------------------------------- +When unchecked exceptions are thrown from sections they are always failures + section name +------------------------------------------------------------------------------- +ExceptionTests.cpp:<line number> +............................................................................... + +ExceptionTests.cpp:<line number>: FAILED: +due to unexpected exception with message: + unexpected exception + +------------------------------------------------------------------------------- +When unchecked exceptions are thrown from functions they are always failures +------------------------------------------------------------------------------- +ExceptionTests.cpp:<line number> +............................................................................... + +ExceptionTests.cpp:<line number>: FAILED: + CHECK( thisThrows() == 0 ) +due to unexpected exception with message: + expected exception + +------------------------------------------------------------------------------- +When unchecked exceptions are thrown during a REQUIRE the test should abort +fail +------------------------------------------------------------------------------- +ExceptionTests.cpp:<line number> +............................................................................... + +ExceptionTests.cpp:<line number>: FAILED: + REQUIRE( thisThrows() == 0 ) +due to unexpected exception with message: + expected exception + +------------------------------------------------------------------------------- +When unchecked exceptions are thrown during a CHECK the test should abort and +fail +------------------------------------------------------------------------------- +ExceptionTests.cpp:<line number> +............................................................................... + +ExceptionTests.cpp:<line number>: FAILED: + CHECK( thisThrows() == 0 ) +due to unexpected exception with message: + expected exception + +------------------------------------------------------------------------------- +Non-std exceptions can be translated +------------------------------------------------------------------------------- +ExceptionTests.cpp:<line number> +............................................................................... + +ExceptionTests.cpp:<line number>: FAILED: +due to unexpected exception with message: + custom exception + +------------------------------------------------------------------------------- +Custom std-exceptions can be custom translated +------------------------------------------------------------------------------- +ExceptionTests.cpp:<line number> +............................................................................... + +ExceptionTests.cpp:<line number>: FAILED: +due to unexpected exception with message: + custom std exception + +------------------------------------------------------------------------------- +Custom exceptions can be translated when testing for nothrow +------------------------------------------------------------------------------- +ExceptionTests.cpp:<line number> +............................................................................... + +ExceptionTests.cpp:<line number>: FAILED: + REQUIRE_NOTHROW( throwCustom() ) +due to unexpected exception with message: + custom exception - not std + +------------------------------------------------------------------------------- +Custom exceptions can be translated when testing for throwing as something else +------------------------------------------------------------------------------- +ExceptionTests.cpp:<line number> +............................................................................... + +ExceptionTests.cpp:<line number>: FAILED: + REQUIRE_THROWS_AS( throwCustom() ) +due to unexpected exception with message: + custom exception - not std + +------------------------------------------------------------------------------- +Unexpected exceptions can be translated +------------------------------------------------------------------------------- +ExceptionTests.cpp:<line number> +............................................................................... + +ExceptionTests.cpp:<line number>: FAILED: +due to unexpected exception with message: + 3.14 + +------------------------------------------------------------------------------- +Mismatching exception messages failing the test +------------------------------------------------------------------------------- +ExceptionTests.cpp:<line number> +............................................................................... + +ExceptionTests.cpp:<line number>: FAILED: + REQUIRE_THROWS_WITH( thisThrows(), "should fail" ) +with expansion: + expected exception + +------------------------------------------------------------------------------- +INFO and WARN do not abort tests +------------------------------------------------------------------------------- +MessageTests.cpp:<line number> +............................................................................... + +MessageTests.cpp:<line number>: +warning: + this is a warning + +------------------------------------------------------------------------------- +INFO gets logged on failure +------------------------------------------------------------------------------- +MessageTests.cpp:<line number> +............................................................................... + +MessageTests.cpp:<line number>: FAILED: + REQUIRE( a == 1 ) +with expansion: + 2 == 1 +with messages: + this message should be logged + so should this + +------------------------------------------------------------------------------- +INFO gets logged on failure, even if captured before successful assertions +------------------------------------------------------------------------------- +MessageTests.cpp:<line number> +............................................................................... + +MessageTests.cpp:<line number>: FAILED: + CHECK( a == 1 ) +with expansion: + 2 == 1 +with messages: + this message may be logged later + this message should be logged + +MessageTests.cpp:<line number>: FAILED: + CHECK( a == 0 ) +with expansion: + 2 == 0 +with message: + and this, but later + +------------------------------------------------------------------------------- +FAIL aborts the test +------------------------------------------------------------------------------- +MessageTests.cpp:<line number> +............................................................................... + +MessageTests.cpp:<line number>: FAILED: +explicitly with message: + This is a failure + +------------------------------------------------------------------------------- +FAIL does not require an argument +------------------------------------------------------------------------------- +MessageTests.cpp:<line number> +............................................................................... + +MessageTests.cpp:<line number>: FAILED: + +------------------------------------------------------------------------------- +Output from all sections is reported + one +------------------------------------------------------------------------------- +MessageTests.cpp:<line number> +............................................................................... + +MessageTests.cpp:<line number>: FAILED: +explicitly with message: + Message from section one + +------------------------------------------------------------------------------- +Output from all sections is reported + two +------------------------------------------------------------------------------- +MessageTests.cpp:<line number> +............................................................................... + +MessageTests.cpp:<line number>: FAILED: +explicitly with message: + Message from section two + +Message from section one +Message from section two +------------------------------------------------------------------------------- +SCOPED_INFO is reset for each loop +------------------------------------------------------------------------------- +MessageTests.cpp:<line number> +............................................................................... + +MessageTests.cpp:<line number>: FAILED: + REQUIRE( i < 10 ) +with expansion: + 10 < 10 +with messages: + current counter 10 + i := 10 + +------------------------------------------------------------------------------- +just failure +------------------------------------------------------------------------------- +MessageTests.cpp:<line number> +............................................................................... + +MessageTests.cpp:<line number>: FAILED: +explicitly with message: + Previous info should not be seen + +------------------------------------------------------------------------------- +sends information to INFO +------------------------------------------------------------------------------- +MessageTests.cpp:<line number> +............................................................................... + +MessageTests.cpp:<line number>: FAILED: + REQUIRE( false ) +with messages: + hi + i := 7 + +------------------------------------------------------------------------------- +Pointers can be converted to strings +------------------------------------------------------------------------------- +MessageTests.cpp:<line number> +............................................................................... + +MessageTests.cpp:<line number>: +warning: + actual address of p: 0x<hex digits> + +MessageTests.cpp:<line number>: +warning: + toString(p): 0x<hex digits> + +------------------------------------------------------------------------------- +more nested SECTION tests + s1 + s2 +------------------------------------------------------------------------------- +MiscTests.cpp:<line number> +............................................................................... + +MiscTests.cpp:<line number>: FAILED: + REQUIRE( a == b ) +with expansion: + 1 == 2 + +------------------------------------------------------------------------------- +looped SECTION tests + s1 +------------------------------------------------------------------------------- +MiscTests.cpp:<line number> +............................................................................... + +MiscTests.cpp:<line number>: FAILED: + CHECK( b > a ) +with expansion: + 0 > 1 + +------------------------------------------------------------------------------- +looped tests +------------------------------------------------------------------------------- +MiscTests.cpp:<line number> +............................................................................... + +MiscTests.cpp:<line number>: FAILED: + CHECK( ( fib[i] % 2 ) == 0 ) +with expansion: + 1 == 0 +with message: + Testing if fib[0] (1) is even + +MiscTests.cpp:<line number>: FAILED: + CHECK( ( fib[i] % 2 ) == 0 ) +with expansion: + 1 == 0 +with message: + Testing if fib[1] (1) is even + +MiscTests.cpp:<line number>: FAILED: + CHECK( ( fib[i] % 2 ) == 0 ) +with expansion: + 1 == 0 +with message: + Testing if fib[3] (3) is even + +MiscTests.cpp:<line number>: FAILED: + CHECK( ( fib[i] % 2 ) == 0 ) +with expansion: + 1 == 0 +with message: + Testing if fib[4] (5) is even + +MiscTests.cpp:<line number>: FAILED: + CHECK( ( fib[i] % 2 ) == 0 ) +with expansion: + 1 == 0 +with message: + Testing if fib[6] (13) is even + +MiscTests.cpp:<line number>: FAILED: + CHECK( ( fib[i] % 2 ) == 0 ) +with expansion: + 1 == 0 +with message: + Testing if fib[7] (21) is even + +A string sent directly to stdout +A string sent directly to stderr +------------------------------------------------------------------------------- +checkedIf, failing +------------------------------------------------------------------------------- +MiscTests.cpp:<line number> +............................................................................... + +MiscTests.cpp:<line number>: FAILED: + CHECKED_IF( flag ) +with expansion: + false + +MiscTests.cpp:<line number>: FAILED: + REQUIRE( testCheckedIf( false ) ) +with expansion: + false + +------------------------------------------------------------------------------- +checkedElse, failing +------------------------------------------------------------------------------- +MiscTests.cpp:<line number> +............................................................................... + +MiscTests.cpp:<line number>: FAILED: + CHECKED_ELSE( flag ) +with expansion: + false + +MiscTests.cpp:<line number>: FAILED: + REQUIRE( testCheckedElse( false ) ) +with expansion: + false + +------------------------------------------------------------------------------- +send a single char to INFO +------------------------------------------------------------------------------- +MiscTests.cpp:<line number> +............................................................................... + +MiscTests.cpp:<line number>: FAILED: + REQUIRE( false ) +with message: + 3 + +------------------------------------------------------------------------------- +Contains string matcher +------------------------------------------------------------------------------- +MiscTests.cpp:<line number> +............................................................................... + +MiscTests.cpp:<line number>: FAILED: + CHECK_THAT( testStringForMatching(), Contains( "not there" ) ) +with expansion: + "this string contains 'abc' as a substring" contains: "not there" + +------------------------------------------------------------------------------- +StartsWith string matcher +------------------------------------------------------------------------------- +MiscTests.cpp:<line number> +............................................................................... + +MiscTests.cpp:<line number>: FAILED: + CHECK_THAT( testStringForMatching(), StartsWith( "string" ) ) +with expansion: + "this string contains 'abc' as a substring" starts with: "string" + +------------------------------------------------------------------------------- +EndsWith string matcher +------------------------------------------------------------------------------- +MiscTests.cpp:<line number> +............................................................................... + +MiscTests.cpp:<line number>: FAILED: + CHECK_THAT( testStringForMatching(), EndsWith( "this" ) ) +with expansion: + "this string contains 'abc' as a substring" ends with: "this" + +------------------------------------------------------------------------------- +Equals string matcher +------------------------------------------------------------------------------- +MiscTests.cpp:<line number> +............................................................................... + +MiscTests.cpp:<line number>: FAILED: + CHECK_THAT( testStringForMatching(), Equals( "something else" ) ) +with expansion: + "this string contains 'abc' as a substring" equals: "something else" + +------------------------------------------------------------------------------- +Matchers can be composed with both && and || - failing +------------------------------------------------------------------------------- +MiscTests.cpp:<line number> +............................................................................... + +MiscTests.cpp:<line number>: FAILED: + CHECK_THAT( testStringForMatching(), ( Contains( "string" ) || Contains( "different" ) ) && Contains( "random" ) ) +with expansion: + "this string contains 'abc' as a substring" ( ( contains: "string" or + contains: "different" ) and contains: "random" ) + +------------------------------------------------------------------------------- +Matchers can be negated (Not) with the ! operator - failing +------------------------------------------------------------------------------- +MiscTests.cpp:<line number> +............................................................................... + +MiscTests.cpp:<line number>: FAILED: + CHECK_THAT( testStringForMatching(), !Contains( "substring" ) ) +with expansion: + "this string contains 'abc' as a substring" not contains: "substring" + +------------------------------------------------------------------------------- +Nice descriptive name +------------------------------------------------------------------------------- +MiscTests.cpp:<line number> +............................................................................... + +MiscTests.cpp:<line number>: +warning: + This one ran + +------------------------------------------------------------------------------- +A couple of nested sections followed by a failure +------------------------------------------------------------------------------- +MiscTests.cpp:<line number> +............................................................................... + +MiscTests.cpp:<line number>: FAILED: +explicitly with message: + to infinity and beyond + +------------------------------------------------------------------------------- +Tabs and newlines show in output +------------------------------------------------------------------------------- +MiscTests.cpp:<line number> +............................................................................... + +MiscTests.cpp:<line number>: FAILED: + CHECK( s1 == s2 ) +with expansion: + "if ($b == 10) { + $a= 20; + }" + == + "if ($b == 10) { + $a = 20; + } + " + +hello +hello +------------------------------------------------------------------------------- +Where there is more to the expression after the RHS +------------------------------------------------------------------------------- +TrickyTests.cpp:<line number> +............................................................................... + +TrickyTests.cpp:<line number>: +warning: + Uncomment the code in this test to check that it gives a sensible compiler + error + +------------------------------------------------------------------------------- +Where the LHS is not a simple value +------------------------------------------------------------------------------- +TrickyTests.cpp:<line number> +............................................................................... + +TrickyTests.cpp:<line number>: +warning: + Uncomment the code in this test to check that it gives a sensible compiler + error + +------------------------------------------------------------------------------- +A failing expression with a non streamable type is still captured +------------------------------------------------------------------------------- +TrickyTests.cpp:<line number> +............................................................................... + +TrickyTests.cpp:<line number>: FAILED: + CHECK( &o1 == &o2 ) +with expansion: + 0x<hex digits> == 0x<hex digits> + +TrickyTests.cpp:<line number>: FAILED: + CHECK( o1 == o2 ) +with expansion: + {?} == {?} + +------------------------------------------------------------------------------- +string literals of different sizes can be compared +------------------------------------------------------------------------------- +TrickyTests.cpp:<line number> +............................................................................... + +TrickyTests.cpp:<line number>: FAILED: + REQUIRE( std::string( "first" ) == "second" ) +with expansion: + "first" == "second" + +=============================================================================== +test cases: 167 | 124 passed | 42 failed | 1 failed as expected +assertions: 919 | 823 passed | 83 failed | 13 failed as expected + diff --git a/unittest/Catch/projects/SelfTest/Baselines/console.sw.approved.txt b/unittest/Catch/projects/SelfTest/Baselines/console.sw.approved.txt new file mode 100644 index 0000000..cd73c2a --- /dev/null +++ b/unittest/Catch/projects/SelfTest/Baselines/console.sw.approved.txt @@ -0,0 +1,9098 @@ + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +CatchSelfTest is a <version> host application. +Run with -? for options + +------------------------------------------------------------------------------- +toString(enum) +------------------------------------------------------------------------------- +EnumToString.cpp:<line number> +............................................................................... + +EnumToString.cpp:<line number>: +PASSED: + CHECK( Catch::toString(e0) == "0" ) +with expansion: + "0" == "0" + +EnumToString.cpp:<line number>: +PASSED: + CHECK( Catch::toString(e1) == "1" ) +with expansion: + "1" == "1" + +------------------------------------------------------------------------------- +toString(enum w/operator<<) +------------------------------------------------------------------------------- +EnumToString.cpp:<line number> +............................................................................... + +EnumToString.cpp:<line number>: +PASSED: + CHECK( Catch::toString(e0) == "E2{0}" ) +with expansion: + "E2{0}" == "E2{0}" + +EnumToString.cpp:<line number>: +PASSED: + CHECK( Catch::toString(e1) == "E2{1}" ) +with expansion: + "E2{1}" == "E2{1}" + +------------------------------------------------------------------------------- +toString(enum class) +------------------------------------------------------------------------------- +EnumToString.cpp:<line number> +............................................................................... + +EnumToString.cpp:<line number>: +PASSED: + CHECK( Catch::toString(e0) == "0" ) +with expansion: + "0" == "0" + +EnumToString.cpp:<line number>: +PASSED: + CHECK( Catch::toString(e1) == "1" ) +with expansion: + "1" == "1" + +------------------------------------------------------------------------------- +toString(enum class w/operator<<) +------------------------------------------------------------------------------- +EnumToString.cpp:<line number> +............................................................................... + +EnumToString.cpp:<line number>: +PASSED: + CHECK( Catch::toString(e0) == "E2/V0" ) +with expansion: + "E2/V0" == "E2/V0" + +EnumToString.cpp:<line number>: +PASSED: + CHECK( Catch::toString(e1) == "E2/V1" ) +with expansion: + "E2/V1" == "E2/V1" + +EnumToString.cpp:<line number>: +PASSED: + CHECK( Catch::toString(e3) == "Unknown enum value 10" ) +with expansion: + "Unknown enum value 10" + == + "Unknown enum value 10" + +------------------------------------------------------------------------------- +Some simple comparisons between doubles +------------------------------------------------------------------------------- +ApproxTests.cpp:<line number> +............................................................................... + +ApproxTests.cpp:<line number>: +PASSED: + REQUIRE( d == Approx( 1.23 ) ) +with expansion: + 1.23 == Approx( 1.23 ) + +ApproxTests.cpp:<line number>: +PASSED: + REQUIRE( d != Approx( 1.22 ) ) +with expansion: + 1.23 != Approx( 1.22 ) + +ApproxTests.cpp:<line number>: +PASSED: + REQUIRE( d != Approx( 1.24 ) ) +with expansion: + 1.23 != Approx( 1.24 ) + +ApproxTests.cpp:<line number>: +PASSED: + REQUIRE( Approx( d ) == 1.23 ) +with expansion: + Approx( 1.23 ) == 1.23 + +ApproxTests.cpp:<line number>: +PASSED: + REQUIRE( Approx( d ) != 1.22 ) +with expansion: + Approx( 1.23 ) != 1.22 + +ApproxTests.cpp:<line number>: +PASSED: + REQUIRE( Approx( d ) != 1.24 ) +with expansion: + Approx( 1.23 ) != 1.24 + +------------------------------------------------------------------------------- +Approximate comparisons with different epsilons +------------------------------------------------------------------------------- +ApproxTests.cpp:<line number> +............................................................................... + +ApproxTests.cpp:<line number>: +PASSED: + REQUIRE( d != Approx( 1.231 ) ) +with expansion: + 1.23 != Approx( 1.231 ) + +ApproxTests.cpp:<line number>: +PASSED: + REQUIRE( d == Approx( 1.231 ).epsilon( 0.1 ) ) +with expansion: + 1.23 == Approx( 1.231 ) + +------------------------------------------------------------------------------- +Approximate comparisons with floats +------------------------------------------------------------------------------- +ApproxTests.cpp:<line number> +............................................................................... + +ApproxTests.cpp:<line number>: +PASSED: + REQUIRE( 1.23f == Approx( 1.23f ) ) +with expansion: + 1.23f == Approx( 1.2300000191 ) + +ApproxTests.cpp:<line number>: +PASSED: + REQUIRE( 0.0f == Approx( 0.0f ) ) +with expansion: + 0.0f == Approx( 0.0 ) + +------------------------------------------------------------------------------- +Approximate comparisons with ints +------------------------------------------------------------------------------- +ApproxTests.cpp:<line number> +............................................................................... + +ApproxTests.cpp:<line number>: +PASSED: + REQUIRE( 1 == Approx( 1 ) ) +with expansion: + 1 == Approx( 1.0 ) + +ApproxTests.cpp:<line number>: +PASSED: + REQUIRE( 0 == Approx( 0 ) ) +with expansion: + 0 == Approx( 0.0 ) + +------------------------------------------------------------------------------- +Approximate comparisons with mixed numeric types +------------------------------------------------------------------------------- +ApproxTests.cpp:<line number> +............................................................................... + +ApproxTests.cpp:<line number>: +PASSED: + REQUIRE( 1.0f == Approx( 1 ) ) +with expansion: + 1.0f == Approx( 1.0 ) + +ApproxTests.cpp:<line number>: +PASSED: + REQUIRE( 0 == Approx( dZero) ) +with expansion: + 0 == Approx( 0.0 ) + +ApproxTests.cpp:<line number>: +PASSED: + REQUIRE( 0 == Approx( dSmall ).epsilon( 0.001 ) ) +with expansion: + 0 == Approx( 0.00001 ) + +ApproxTests.cpp:<line number>: +PASSED: + REQUIRE( 1.234f == Approx( dMedium ) ) +with expansion: + 1.234f == Approx( 1.234 ) + +ApproxTests.cpp:<line number>: +PASSED: + REQUIRE( dMedium == Approx( 1.234f ) ) +with expansion: + 1.234 == Approx( 1.2339999676 ) + +------------------------------------------------------------------------------- +Use a custom approx +------------------------------------------------------------------------------- +ApproxTests.cpp:<line number> +............................................................................... + +ApproxTests.cpp:<line number>: +PASSED: + REQUIRE( d == approx( 1.23 ) ) +with expansion: + 1.23 == Approx( 1.23 ) + +ApproxTests.cpp:<line number>: +PASSED: + REQUIRE( d == approx( 1.22 ) ) +with expansion: + 1.23 == Approx( 1.22 ) + +ApproxTests.cpp:<line number>: +PASSED: + REQUIRE( d == approx( 1.24 ) ) +with expansion: + 1.23 == Approx( 1.24 ) + +ApproxTests.cpp:<line number>: +PASSED: + REQUIRE( d != approx( 1.25 ) ) +with expansion: + 1.23 != Approx( 1.25 ) + +ApproxTests.cpp:<line number>: +PASSED: + REQUIRE( approx( d ) == 1.23 ) +with expansion: + Approx( 1.23 ) == 1.23 + +ApproxTests.cpp:<line number>: +PASSED: + REQUIRE( approx( d ) == 1.22 ) +with expansion: + Approx( 1.23 ) == 1.22 + +ApproxTests.cpp:<line number>: +PASSED: + REQUIRE( approx( d ) == 1.24 ) +with expansion: + Approx( 1.23 ) == 1.24 + +ApproxTests.cpp:<line number>: +PASSED: + REQUIRE( approx( d ) != 1.25 ) +with expansion: + Approx( 1.23 ) != 1.25 + +------------------------------------------------------------------------------- +Approximate PI +------------------------------------------------------------------------------- +ApproxTests.cpp:<line number> +............................................................................... + +ApproxTests.cpp:<line number>: +PASSED: + REQUIRE( divide( 22, 7 ) == Approx( 3.141 ).epsilon( 0.001 ) ) +with expansion: + 3.1428571429 == Approx( 3.141 ) + +ApproxTests.cpp:<line number>: +PASSED: + REQUIRE( divide( 22, 7 ) != Approx( 3.141 ).epsilon( 0.0001 ) ) +with expansion: + 3.1428571429 != Approx( 3.141 ) + +------------------------------------------------------------------------------- +A METHOD_AS_TEST_CASE based test run that succeeds +------------------------------------------------------------------------------- +ClassTests.cpp:<line number> +............................................................................... + +ClassTests.cpp:<line number>: +PASSED: + REQUIRE( s == "hello" ) +with expansion: + "hello" == "hello" + +------------------------------------------------------------------------------- +A METHOD_AS_TEST_CASE based test run that fails +------------------------------------------------------------------------------- +ClassTests.cpp:<line number> +............................................................................... + +ClassTests.cpp:<line number>: FAILED: + REQUIRE( s == "world" ) +with expansion: + "hello" == "world" + +------------------------------------------------------------------------------- +A TEST_CASE_METHOD based test run that succeeds +------------------------------------------------------------------------------- +ClassTests.cpp:<line number> +............................................................................... + +ClassTests.cpp:<line number>: +PASSED: + REQUIRE( m_a == 1 ) +with expansion: + 1 == 1 + +------------------------------------------------------------------------------- +A TEST_CASE_METHOD based test run that fails +------------------------------------------------------------------------------- +ClassTests.cpp:<line number> +............................................................................... + +ClassTests.cpp:<line number>: FAILED: + REQUIRE( m_a == 2 ) +with expansion: + 1 == 2 + +------------------------------------------------------------------------------- +Equality checks that should succeed +------------------------------------------------------------------------------- +ConditionTests.cpp:<line number> +............................................................................... + +ConditionTests.cpp:<line number>: +PASSED: + REQUIRE( data.int_seven == 7 ) +with expansion: + 7 == 7 + +ConditionTests.cpp:<line number>: +PASSED: + REQUIRE( data.float_nine_point_one == Approx( 9.1f ) ) +with expansion: + 9.1f == Approx( 9.1000003815 ) + +ConditionTests.cpp:<line number>: +PASSED: + REQUIRE( data.double_pi == Approx( 3.1415926535 ) ) +with expansion: + 3.1415926535 == Approx( 3.1415926535 ) + +ConditionTests.cpp:<line number>: +PASSED: + REQUIRE( data.str_hello == "hello" ) +with expansion: + "hello" == "hello" + +ConditionTests.cpp:<line number>: +PASSED: + REQUIRE( "hello" == data.str_hello ) +with expansion: + "hello" == "hello" + +ConditionTests.cpp:<line number>: +PASSED: + REQUIRE( data.str_hello.size() == 5 ) +with expansion: + 5 == 5 + +ConditionTests.cpp:<line number>: +PASSED: + REQUIRE( x == Approx( 1.3 ) ) +with expansion: + 1.3 == Approx( 1.3 ) + +------------------------------------------------------------------------------- +Equality checks that should fail +------------------------------------------------------------------------------- +ConditionTests.cpp:<line number> +............................................................................... + +ConditionTests.cpp:<line number>: FAILED: + CHECK( data.int_seven == 6 ) +with expansion: + 7 == 6 + +ConditionTests.cpp:<line number>: FAILED: + CHECK( data.int_seven == 8 ) +with expansion: + 7 == 8 + +ConditionTests.cpp:<line number>: FAILED: + CHECK( data.int_seven == 0 ) +with expansion: + 7 == 0 + +ConditionTests.cpp:<line number>: FAILED: + CHECK( data.float_nine_point_one == Approx( 9.11f ) ) +with expansion: + 9.1f == Approx( 9.1099996567 ) + +ConditionTests.cpp:<line number>: FAILED: + CHECK( data.float_nine_point_one == Approx( 9.0f ) ) +with expansion: + 9.1f == Approx( 9.0 ) + +ConditionTests.cpp:<line number>: FAILED: + CHECK( data.float_nine_point_one == Approx( 1 ) ) +with expansion: + 9.1f == Approx( 1.0 ) + +ConditionTests.cpp:<line number>: FAILED: + CHECK( data.float_nine_point_one == Approx( 0 ) ) +with expansion: + 9.1f == Approx( 0.0 ) + +ConditionTests.cpp:<line number>: FAILED: + CHECK( data.double_pi == Approx( 3.1415 ) ) +with expansion: + 3.1415926535 == Approx( 3.1415 ) + +ConditionTests.cpp:<line number>: FAILED: + CHECK( data.str_hello == "goodbye" ) +with expansion: + "hello" == "goodbye" + +ConditionTests.cpp:<line number>: FAILED: + CHECK( data.str_hello == "hell" ) +with expansion: + "hello" == "hell" + +ConditionTests.cpp:<line number>: FAILED: + CHECK( data.str_hello == "hello1" ) +with expansion: + "hello" == "hello1" + +ConditionTests.cpp:<line number>: FAILED: + CHECK( data.str_hello.size() == 6 ) +with expansion: + 5 == 6 + +ConditionTests.cpp:<line number>: FAILED: + CHECK( x == Approx( 1.301 ) ) +with expansion: + 1.3 == Approx( 1.301 ) + +------------------------------------------------------------------------------- +Inequality checks that should succeed +------------------------------------------------------------------------------- +ConditionTests.cpp:<line number> +............................................................................... + +ConditionTests.cpp:<line number>: +PASSED: + REQUIRE( data.int_seven != 6 ) +with expansion: + 7 != 6 + +ConditionTests.cpp:<line number>: +PASSED: + REQUIRE( data.int_seven != 8 ) +with expansion: + 7 != 8 + +ConditionTests.cpp:<line number>: +PASSED: + REQUIRE( data.float_nine_point_one != Approx( 9.11f ) ) +with expansion: + 9.1f != Approx( 9.1099996567 ) + +ConditionTests.cpp:<line number>: +PASSED: + REQUIRE( data.float_nine_point_one != Approx( 9.0f ) ) +with expansion: + 9.1f != Approx( 9.0 ) + +ConditionTests.cpp:<line number>: +PASSED: + REQUIRE( data.float_nine_point_one != Approx( 1 ) ) +with expansion: + 9.1f != Approx( 1.0 ) + +ConditionTests.cpp:<line number>: +PASSED: + REQUIRE( data.float_nine_point_one != Approx( 0 ) ) +with expansion: + 9.1f != Approx( 0.0 ) + +ConditionTests.cpp:<line number>: +PASSED: + REQUIRE( data.double_pi != Approx( 3.1415 ) ) +with expansion: + 3.1415926535 != Approx( 3.1415 ) + +ConditionTests.cpp:<line number>: +PASSED: + REQUIRE( data.str_hello != "goodbye" ) +with expansion: + "hello" != "goodbye" + +ConditionTests.cpp:<line number>: +PASSED: + REQUIRE( data.str_hello != "hell" ) +with expansion: + "hello" != "hell" + +ConditionTests.cpp:<line number>: +PASSED: + REQUIRE( data.str_hello != "hello1" ) +with expansion: + "hello" != "hello1" + +ConditionTests.cpp:<line number>: +PASSED: + REQUIRE( data.str_hello.size() != 6 ) +with expansion: + 5 != 6 + +------------------------------------------------------------------------------- +Inequality checks that should fail +------------------------------------------------------------------------------- +ConditionTests.cpp:<line number> +............................................................................... + +ConditionTests.cpp:<line number>: FAILED: + CHECK( data.int_seven != 7 ) +with expansion: + 7 != 7 + +ConditionTests.cpp:<line number>: FAILED: + CHECK( data.float_nine_point_one != Approx( 9.1f ) ) +with expansion: + 9.1f != Approx( 9.1000003815 ) + +ConditionTests.cpp:<line number>: FAILED: + CHECK( data.double_pi != Approx( 3.1415926535 ) ) +with expansion: + 3.1415926535 != Approx( 3.1415926535 ) + +ConditionTests.cpp:<line number>: FAILED: + CHECK( data.str_hello != "hello" ) +with expansion: + "hello" != "hello" + +ConditionTests.cpp:<line number>: FAILED: + CHECK( data.str_hello.size() != 5 ) +with expansion: + 5 != 5 + +------------------------------------------------------------------------------- +Ordering comparison checks that should succeed +------------------------------------------------------------------------------- +ConditionTests.cpp:<line number> +............................................................................... + +ConditionTests.cpp:<line number>: +PASSED: + REQUIRE( data.int_seven < 8 ) +with expansion: + 7 < 8 + +ConditionTests.cpp:<line number>: +PASSED: + REQUIRE( data.int_seven > 6 ) +with expansion: + 7 > 6 + +ConditionTests.cpp:<line number>: +PASSED: + REQUIRE( data.int_seven > 0 ) +with expansion: + 7 > 0 + +ConditionTests.cpp:<line number>: +PASSED: + REQUIRE( data.int_seven > -1 ) +with expansion: + 7 > -1 + +ConditionTests.cpp:<line number>: +PASSED: + REQUIRE( data.int_seven >= 7 ) +with expansion: + 7 >= 7 + +ConditionTests.cpp:<line number>: +PASSED: + REQUIRE( data.int_seven >= 6 ) +with expansion: + 7 >= 6 + +ConditionTests.cpp:<line number>: +PASSED: + REQUIRE( data.int_seven <= 7 ) +with expansion: + 7 <= 7 + +ConditionTests.cpp:<line number>: +PASSED: + REQUIRE( data.int_seven <= 8 ) +with expansion: + 7 <= 8 + +ConditionTests.cpp:<line number>: +PASSED: + REQUIRE( data.float_nine_point_one > 9 ) +with expansion: + 9.1f > 9 + +ConditionTests.cpp:<line number>: +PASSED: + REQUIRE( data.float_nine_point_one < 10 ) +with expansion: + 9.1f < 10 + +ConditionTests.cpp:<line number>: +PASSED: + REQUIRE( data.float_nine_point_one < 9.2 ) +with expansion: + 9.1f < 9.2 + +ConditionTests.cpp:<line number>: +PASSED: + REQUIRE( data.str_hello <= "hello" ) +with expansion: + "hello" <= "hello" + +ConditionTests.cpp:<line number>: +PASSED: + REQUIRE( data.str_hello >= "hello" ) +with expansion: + "hello" >= "hello" + +ConditionTests.cpp:<line number>: +PASSED: + REQUIRE( data.str_hello < "hellp" ) +with expansion: + "hello" < "hellp" + +ConditionTests.cpp:<line number>: +PASSED: + REQUIRE( data.str_hello < "zebra" ) +with expansion: + "hello" < "zebra" + +ConditionTests.cpp:<line number>: +PASSED: + REQUIRE( data.str_hello > "hellm" ) +with expansion: + "hello" > "hellm" + +ConditionTests.cpp:<line number>: +PASSED: + REQUIRE( data.str_hello > "a" ) +with expansion: + "hello" > "a" + +------------------------------------------------------------------------------- +Ordering comparison checks that should fail +------------------------------------------------------------------------------- +ConditionTests.cpp:<line number> +............................................................................... + +ConditionTests.cpp:<line number>: FAILED: + CHECK( data.int_seven > 7 ) +with expansion: + 7 > 7 + +ConditionTests.cpp:<line number>: FAILED: + CHECK( data.int_seven < 7 ) +with expansion: + 7 < 7 + +ConditionTests.cpp:<line number>: FAILED: + CHECK( data.int_seven > 8 ) +with expansion: + 7 > 8 + +ConditionTests.cpp:<line number>: FAILED: + CHECK( data.int_seven < 6 ) +with expansion: + 7 < 6 + +ConditionTests.cpp:<line number>: FAILED: + CHECK( data.int_seven < 0 ) +with expansion: + 7 < 0 + +ConditionTests.cpp:<line number>: FAILED: + CHECK( data.int_seven < -1 ) +with expansion: + 7 < -1 + +ConditionTests.cpp:<line number>: FAILED: + CHECK( data.int_seven >= 8 ) +with expansion: + 7 >= 8 + +ConditionTests.cpp:<line number>: FAILED: + CHECK( data.int_seven <= 6 ) +with expansion: + 7 <= 6 + +ConditionTests.cpp:<line number>: FAILED: + CHECK( data.float_nine_point_one < 9 ) +with expansion: + 9.1f < 9 + +ConditionTests.cpp:<line number>: FAILED: + CHECK( data.float_nine_point_one > 10 ) +with expansion: + 9.1f > 10 + +ConditionTests.cpp:<line number>: FAILED: + CHECK( data.float_nine_point_one > 9.2 ) +with expansion: + 9.1f > 9.2 + +ConditionTests.cpp:<line number>: FAILED: + CHECK( data.str_hello > "hello" ) +with expansion: + "hello" > "hello" + +ConditionTests.cpp:<line number>: FAILED: + CHECK( data.str_hello < "hello" ) +with expansion: + "hello" < "hello" + +ConditionTests.cpp:<line number>: FAILED: + CHECK( data.str_hello > "hellp" ) +with expansion: + "hello" > "hellp" + +ConditionTests.cpp:<line number>: FAILED: + CHECK( data.str_hello > "z" ) +with expansion: + "hello" > "z" + +ConditionTests.cpp:<line number>: FAILED: + CHECK( data.str_hello < "hellm" ) +with expansion: + "hello" < "hellm" + +ConditionTests.cpp:<line number>: FAILED: + CHECK( data.str_hello < "a" ) +with expansion: + "hello" < "a" + +ConditionTests.cpp:<line number>: FAILED: + CHECK( data.str_hello >= "z" ) +with expansion: + "hello" >= "z" + +ConditionTests.cpp:<line number>: FAILED: + CHECK( data.str_hello <= "a" ) +with expansion: + "hello" <= "a" + +------------------------------------------------------------------------------- +Comparisons with int literals don't warn when mixing signed/ unsigned +------------------------------------------------------------------------------- +ConditionTests.cpp:<line number> +............................................................................... + +ConditionTests.cpp:<line number>: +PASSED: + REQUIRE( i == 1 ) +with expansion: + 1 == 1 + +ConditionTests.cpp:<line number>: +PASSED: + REQUIRE( ui == 2 ) +with expansion: + 2 == 2 + +ConditionTests.cpp:<line number>: +PASSED: + REQUIRE( l == 3 ) +with expansion: + 3 == 3 + +ConditionTests.cpp:<line number>: +PASSED: + REQUIRE( ul == 4 ) +with expansion: + 4 == 4 + +ConditionTests.cpp:<line number>: +PASSED: + REQUIRE( c == 5 ) +with expansion: + 5 == 5 + +ConditionTests.cpp:<line number>: +PASSED: + REQUIRE( uc == 6 ) +with expansion: + 6 == 6 + +ConditionTests.cpp:<line number>: +PASSED: + REQUIRE( 1 == i ) +with expansion: + 1 == 1 + +ConditionTests.cpp:<line number>: +PASSED: + REQUIRE( 2 == ui ) +with expansion: + 2 == 2 + +ConditionTests.cpp:<line number>: +PASSED: + REQUIRE( 3 == l ) +with expansion: + 3 == 3 + +ConditionTests.cpp:<line number>: +PASSED: + REQUIRE( 4 == ul ) +with expansion: + 4 == 4 + +ConditionTests.cpp:<line number>: +PASSED: + REQUIRE( 5 == c ) +with expansion: + 5 == 5 + +ConditionTests.cpp:<line number>: +PASSED: + REQUIRE( 6 == uc ) +with expansion: + 6 == 6 + +ConditionTests.cpp:<line number>: +PASSED: + REQUIRE( (std::numeric_limits<unsigned long>::max)() > ul ) +with expansion: + 18446744073709551615 (0x<hex digits>) + > + 4 + +------------------------------------------------------------------------------- +comparisons between int variables +------------------------------------------------------------------------------- +ConditionTests.cpp:<line number> +............................................................................... + +ConditionTests.cpp:<line number>: +PASSED: + REQUIRE( long_var == unsigned_char_var ) +with expansion: + 1 == 1 + +ConditionTests.cpp:<line number>: +PASSED: + REQUIRE( long_var == unsigned_short_var ) +with expansion: + 1 == 1 + +ConditionTests.cpp:<line number>: +PASSED: + REQUIRE( long_var == unsigned_int_var ) +with expansion: + 1 == 1 + +ConditionTests.cpp:<line number>: +PASSED: + REQUIRE( long_var == unsigned_long_var ) +with expansion: + 1 == 1 + +------------------------------------------------------------------------------- +comparisons between const int variables +------------------------------------------------------------------------------- +ConditionTests.cpp:<line number> +............................................................................... + +ConditionTests.cpp:<line number>: +PASSED: + REQUIRE( unsigned_char_var == 1 ) +with expansion: + 1 == 1 + +ConditionTests.cpp:<line number>: +PASSED: + REQUIRE( unsigned_short_var == 1 ) +with expansion: + 1 == 1 + +ConditionTests.cpp:<line number>: +PASSED: + REQUIRE( unsigned_int_var == 1 ) +with expansion: + 1 == 1 + +ConditionTests.cpp:<line number>: +PASSED: + REQUIRE( unsigned_long_var == 1 ) +with expansion: + 1 == 1 + +------------------------------------------------------------------------------- +Comparisons between unsigned ints and negative signed ints match c++ standard +behaviour +------------------------------------------------------------------------------- +ConditionTests.cpp:<line number> +............................................................................... + +ConditionTests.cpp:<line number>: +PASSED: + CHECK( ( -1 > 2u ) ) +with expansion: + true + +ConditionTests.cpp:<line number>: +PASSED: + CHECK( -1 > 2u ) +with expansion: + -1 > 2 + +ConditionTests.cpp:<line number>: +PASSED: + CHECK( ( 2u < -1 ) ) +with expansion: + true + +ConditionTests.cpp:<line number>: +PASSED: + CHECK( 2u < -1 ) +with expansion: + 2 < -1 + +ConditionTests.cpp:<line number>: +PASSED: + CHECK( ( minInt > 2u ) ) +with expansion: + true + +ConditionTests.cpp:<line number>: +PASSED: + CHECK( minInt > 2u ) +with expansion: + -2147483648 > 2 + +------------------------------------------------------------------------------- +Comparisons between ints where one side is computed +------------------------------------------------------------------------------- +ConditionTests.cpp:<line number> +............................................................................... + +ConditionTests.cpp:<line number>: +PASSED: + CHECK( 54 == 6*9 ) +with expansion: + 54 == 54 + +------------------------------------------------------------------------------- +Pointers can be compared to null +------------------------------------------------------------------------------- +ConditionTests.cpp:<line number> +............................................................................... + +ConditionTests.cpp:<line number>: +PASSED: + REQUIRE( p == nullptr ) +with expansion: + NULL == nullptr + +ConditionTests.cpp:<line number>: +PASSED: + REQUIRE( p == pNULL ) +with expansion: + NULL == NULL + +ConditionTests.cpp:<line number>: +PASSED: + REQUIRE( p != nullptr ) +with expansion: + 0x<hex digits> != nullptr + +ConditionTests.cpp:<line number>: +PASSED: + REQUIRE( cp != nullptr ) +with expansion: + 0x<hex digits> != nullptr + +ConditionTests.cpp:<line number>: +PASSED: + REQUIRE( cpc != nullptr ) +with expansion: + 0x<hex digits> != nullptr + +ConditionTests.cpp:<line number>: +PASSED: + REQUIRE( returnsNull() == nullptr ) +with expansion: + {null string} == nullptr + +ConditionTests.cpp:<line number>: +PASSED: + REQUIRE( returnsConstNull() == nullptr ) +with expansion: + {null string} == nullptr + +ConditionTests.cpp:<line number>: +PASSED: + REQUIRE( nullptr != p ) +with expansion: + nullptr != 0x<hex digits> + +------------------------------------------------------------------------------- +'Not' checks that should succeed +------------------------------------------------------------------------------- +ConditionTests.cpp:<line number> +............................................................................... + +ConditionTests.cpp:<line number>: +PASSED: + REQUIRE( false == false ) + +ConditionTests.cpp:<line number>: +PASSED: + REQUIRE( true == true ) + +ConditionTests.cpp:<line number>: +PASSED: + REQUIRE( !false ) +with expansion: + true + +ConditionTests.cpp:<line number>: +PASSED: + REQUIRE_FALSE( false ) + +ConditionTests.cpp:<line number>: +PASSED: + REQUIRE( !falseValue ) +with expansion: + true + +ConditionTests.cpp:<line number>: +PASSED: + REQUIRE_FALSE( falseValue ) +with expansion: + !false + +ConditionTests.cpp:<line number>: +PASSED: + REQUIRE( !(1 == 2) ) +with expansion: + true + +ConditionTests.cpp:<line number>: +PASSED: + REQUIRE_FALSE( 1 == 2 ) +with expansion: + !(1 == 2) + +------------------------------------------------------------------------------- +'Not' checks that should fail +------------------------------------------------------------------------------- +ConditionTests.cpp:<line number> +............................................................................... + +ConditionTests.cpp:<line number>: FAILED: + CHECK( false != false ) + +ConditionTests.cpp:<line number>: FAILED: + CHECK( true != true ) + +ConditionTests.cpp:<line number>: FAILED: + CHECK( !true ) +with expansion: + false + +ConditionTests.cpp:<line number>: FAILED: + CHECK_FALSE( true ) + +ConditionTests.cpp:<line number>: FAILED: + CHECK( !trueValue ) +with expansion: + false + +ConditionTests.cpp:<line number>: FAILED: + CHECK_FALSE( trueValue ) +with expansion: + !true + +ConditionTests.cpp:<line number>: FAILED: + CHECK( !(1 == 1) ) +with expansion: + false + +ConditionTests.cpp:<line number>: FAILED: + CHECK_FALSE( 1 == 1 ) +with expansion: + !(1 == 1) + +------------------------------------------------------------------------------- +When checked exceptions are thrown they can be expected or unexpected +------------------------------------------------------------------------------- +ExceptionTests.cpp:<line number> +............................................................................... + +ExceptionTests.cpp:<line number>: +PASSED: + REQUIRE_THROWS_AS( thisThrows() ) + +ExceptionTests.cpp:<line number>: +PASSED: + REQUIRE_NOTHROW( thisDoesntThrow() ) + +ExceptionTests.cpp:<line number>: +PASSED: + REQUIRE_THROWS( thisThrows() ) + +------------------------------------------------------------------------------- +Expected exceptions that don't throw or unexpected exceptions fail the test +------------------------------------------------------------------------------- +ExceptionTests.cpp:<line number> +............................................................................... + +ExceptionTests.cpp:<line number>: FAILED: + CHECK_THROWS_AS( thisThrows() ) +due to unexpected exception with message: + expected exception + +ExceptionTests.cpp:<line number>: FAILED: + CHECK_THROWS_AS( thisDoesntThrow() ) +because no exception was thrown where one was expected: + +ExceptionTests.cpp:<line number>: FAILED: + CHECK_NOTHROW( thisThrows() ) +due to unexpected exception with message: + expected exception + +------------------------------------------------------------------------------- +When unchecked exceptions are thrown directly they are always failures +------------------------------------------------------------------------------- +ExceptionTests.cpp:<line number> +............................................................................... + +ExceptionTests.cpp:<line number>: FAILED: +due to unexpected exception with message: + unexpected exception + +------------------------------------------------------------------------------- +An unchecked exception reports the line of the last assertion +------------------------------------------------------------------------------- +ExceptionTests.cpp:<line number> +............................................................................... + +ExceptionTests.cpp:<line number>: +PASSED: + CHECK( 1 == 1 ) + +ExceptionTests.cpp:<line number>: FAILED: + {Unknown expression after the reported line} +due to unexpected exception with message: + unexpected exception + +------------------------------------------------------------------------------- +When unchecked exceptions are thrown from sections they are always failures + section name +------------------------------------------------------------------------------- +ExceptionTests.cpp:<line number> +............................................................................... + +ExceptionTests.cpp:<line number>: FAILED: +due to unexpected exception with message: + unexpected exception + +------------------------------------------------------------------------------- +When unchecked exceptions are thrown from functions they are always failures +------------------------------------------------------------------------------- +ExceptionTests.cpp:<line number> +............................................................................... + +ExceptionTests.cpp:<line number>: FAILED: + CHECK( thisThrows() == 0 ) +due to unexpected exception with message: + expected exception + +------------------------------------------------------------------------------- +When unchecked exceptions are thrown during a REQUIRE the test should abort +fail +------------------------------------------------------------------------------- +ExceptionTests.cpp:<line number> +............................................................................... + +ExceptionTests.cpp:<line number>: FAILED: + REQUIRE( thisThrows() == 0 ) +due to unexpected exception with message: + expected exception + +------------------------------------------------------------------------------- +When unchecked exceptions are thrown during a CHECK the test should abort and +fail +------------------------------------------------------------------------------- +ExceptionTests.cpp:<line number> +............................................................................... + +ExceptionTests.cpp:<line number>: FAILED: + CHECK( thisThrows() == 0 ) +due to unexpected exception with message: + expected exception + +------------------------------------------------------------------------------- +Non-std exceptions can be translated +------------------------------------------------------------------------------- +ExceptionTests.cpp:<line number> +............................................................................... + +ExceptionTests.cpp:<line number>: FAILED: +due to unexpected exception with message: + custom exception + +------------------------------------------------------------------------------- +Custom std-exceptions can be custom translated +------------------------------------------------------------------------------- +ExceptionTests.cpp:<line number> +............................................................................... + +ExceptionTests.cpp:<line number>: FAILED: +due to unexpected exception with message: + custom std exception + +------------------------------------------------------------------------------- +Custom exceptions can be translated when testing for nothrow +------------------------------------------------------------------------------- +ExceptionTests.cpp:<line number> +............................................................................... + +ExceptionTests.cpp:<line number>: FAILED: + REQUIRE_NOTHROW( throwCustom() ) +due to unexpected exception with message: + custom exception - not std + +------------------------------------------------------------------------------- +Custom exceptions can be translated when testing for throwing as something else +------------------------------------------------------------------------------- +ExceptionTests.cpp:<line number> +............................................................................... + +ExceptionTests.cpp:<line number>: FAILED: + REQUIRE_THROWS_AS( throwCustom() ) +due to unexpected exception with message: + custom exception - not std + +------------------------------------------------------------------------------- +Unexpected exceptions can be translated +------------------------------------------------------------------------------- +ExceptionTests.cpp:<line number> +............................................................................... + +ExceptionTests.cpp:<line number>: FAILED: +due to unexpected exception with message: + 3.14 + +------------------------------------------------------------------------------- +NotImplemented exception +------------------------------------------------------------------------------- +ExceptionTests.cpp:<line number> +............................................................................... + +ExceptionTests.cpp:<line number>: +PASSED: + REQUIRE_THROWS( thisFunctionNotImplemented( 7 ) ) + +------------------------------------------------------------------------------- +Exception messages can be tested for + exact match +------------------------------------------------------------------------------- +ExceptionTests.cpp:<line number> +............................................................................... + +ExceptionTests.cpp:<line number>: +PASSED: + REQUIRE_THROWS_WITH( thisThrows(), "expected exception" ) + +------------------------------------------------------------------------------- +Exception messages can be tested for + different case +------------------------------------------------------------------------------- +ExceptionTests.cpp:<line number> +............................................................................... + +ExceptionTests.cpp:<line number>: +PASSED: + REQUIRE_THROWS_WITH( thisThrows(), Equals( "expecteD Exception", Catch::CaseSensitive::No ) ) + +------------------------------------------------------------------------------- +Exception messages can be tested for + wildcarded +------------------------------------------------------------------------------- +ExceptionTests.cpp:<line number> +............................................................................... + +ExceptionTests.cpp:<line number>: +PASSED: + REQUIRE_THROWS_WITH( thisThrows(), StartsWith( "expected" ) ) + +ExceptionTests.cpp:<line number>: +PASSED: + REQUIRE_THROWS_WITH( thisThrows(), EndsWith( "exception" ) ) + +ExceptionTests.cpp:<line number>: +PASSED: + REQUIRE_THROWS_WITH( thisThrows(), Contains( "except" ) ) + +ExceptionTests.cpp:<line number>: +PASSED: + REQUIRE_THROWS_WITH( thisThrows(), Contains( "exCept", Catch::CaseSensitive::No ) ) + +------------------------------------------------------------------------------- +Mismatching exception messages failing the test +------------------------------------------------------------------------------- +ExceptionTests.cpp:<line number> +............................................................................... + +ExceptionTests.cpp:<line number>: +PASSED: + REQUIRE_THROWS_WITH( thisThrows(), "expected exception" ) + +ExceptionTests.cpp:<line number>: FAILED: + REQUIRE_THROWS_WITH( thisThrows(), "should fail" ) +with expansion: + expected exception + +------------------------------------------------------------------------------- +Generators over two ranges +------------------------------------------------------------------------------- +GeneratorTests.cpp:<line number> +............................................................................... + +GeneratorTests.cpp:<line number>: +PASSED: + CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) +with expansion: + 2 == 2 + +GeneratorTests.cpp:<line number>: +PASSED: + CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) +with expansion: + 200 == 200 + +------------------------------------------------------------------------------- +Generators over two ranges +------------------------------------------------------------------------------- +GeneratorTests.cpp:<line number> +............................................................................... + +GeneratorTests.cpp:<line number>: +PASSED: + CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) +with expansion: + 4 == 4 + +GeneratorTests.cpp:<line number>: +PASSED: + CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) +with expansion: + 200 == 200 + +------------------------------------------------------------------------------- +Generators over two ranges +------------------------------------------------------------------------------- +GeneratorTests.cpp:<line number> +............................................................................... + +GeneratorTests.cpp:<line number>: +PASSED: + CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) +with expansion: + 6 == 6 + +GeneratorTests.cpp:<line number>: +PASSED: + CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) +with expansion: + 200 == 200 + +------------------------------------------------------------------------------- +Generators over two ranges +------------------------------------------------------------------------------- +GeneratorTests.cpp:<line number> +............................................................................... + +GeneratorTests.cpp:<line number>: +PASSED: + CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) +with expansion: + 8 == 8 + +GeneratorTests.cpp:<line number>: +PASSED: + CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) +with expansion: + 200 == 200 + +------------------------------------------------------------------------------- +Generators over two ranges +------------------------------------------------------------------------------- +GeneratorTests.cpp:<line number> +............................................................................... + +GeneratorTests.cpp:<line number>: +PASSED: + CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) +with expansion: + 10 == 10 + +GeneratorTests.cpp:<line number>: +PASSED: + CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) +with expansion: + 200 == 200 + +------------------------------------------------------------------------------- +Generators over two ranges +------------------------------------------------------------------------------- +GeneratorTests.cpp:<line number> +............................................................................... + +GeneratorTests.cpp:<line number>: +PASSED: + CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) +with expansion: + 30 == 30 + +GeneratorTests.cpp:<line number>: +PASSED: + CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) +with expansion: + 200 == 200 + +------------------------------------------------------------------------------- +Generators over two ranges +------------------------------------------------------------------------------- +GeneratorTests.cpp:<line number> +............................................................................... + +GeneratorTests.cpp:<line number>: +PASSED: + CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) +with expansion: + 40 == 40 + +GeneratorTests.cpp:<line number>: +PASSED: + CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) +with expansion: + 200 == 200 + +------------------------------------------------------------------------------- +Generators over two ranges +------------------------------------------------------------------------------- +GeneratorTests.cpp:<line number> +............................................................................... + +GeneratorTests.cpp:<line number>: +PASSED: + CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) +with expansion: + 42 == 42 + +GeneratorTests.cpp:<line number>: +PASSED: + CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) +with expansion: + 200 == 200 + +------------------------------------------------------------------------------- +Generators over two ranges +------------------------------------------------------------------------------- +GeneratorTests.cpp:<line number> +............................................................................... + +GeneratorTests.cpp:<line number>: +PASSED: + CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) +with expansion: + 72 == 72 + +GeneratorTests.cpp:<line number>: +PASSED: + CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) +with expansion: + 200 == 200 + +------------------------------------------------------------------------------- +Generators over two ranges +------------------------------------------------------------------------------- +GeneratorTests.cpp:<line number> +............................................................................... + +GeneratorTests.cpp:<line number>: +PASSED: + CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) +with expansion: + 2 == 2 + +GeneratorTests.cpp:<line number>: +PASSED: + CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) +with expansion: + 202 == 202 + +------------------------------------------------------------------------------- +Generators over two ranges +------------------------------------------------------------------------------- +GeneratorTests.cpp:<line number> +............................................................................... + +GeneratorTests.cpp:<line number>: +PASSED: + CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) +with expansion: + 4 == 4 + +GeneratorTests.cpp:<line number>: +PASSED: + CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) +with expansion: + 202 == 202 + +------------------------------------------------------------------------------- +Generators over two ranges +------------------------------------------------------------------------------- +GeneratorTests.cpp:<line number> +............................................................................... + +GeneratorTests.cpp:<line number>: +PASSED: + CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) +with expansion: + 6 == 6 + +GeneratorTests.cpp:<line number>: +PASSED: + CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) +with expansion: + 202 == 202 + +------------------------------------------------------------------------------- +Generators over two ranges +------------------------------------------------------------------------------- +GeneratorTests.cpp:<line number> +............................................................................... + +GeneratorTests.cpp:<line number>: +PASSED: + CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) +with expansion: + 8 == 8 + +GeneratorTests.cpp:<line number>: +PASSED: + CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) +with expansion: + 202 == 202 + +------------------------------------------------------------------------------- +Generators over two ranges +------------------------------------------------------------------------------- +GeneratorTests.cpp:<line number> +............................................................................... + +GeneratorTests.cpp:<line number>: +PASSED: + CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) +with expansion: + 10 == 10 + +GeneratorTests.cpp:<line number>: +PASSED: + CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) +with expansion: + 202 == 202 + +------------------------------------------------------------------------------- +Generators over two ranges +------------------------------------------------------------------------------- +GeneratorTests.cpp:<line number> +............................................................................... + +GeneratorTests.cpp:<line number>: +PASSED: + CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) +with expansion: + 30 == 30 + +GeneratorTests.cpp:<line number>: +PASSED: + CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) +with expansion: + 202 == 202 + +------------------------------------------------------------------------------- +Generators over two ranges +------------------------------------------------------------------------------- +GeneratorTests.cpp:<line number> +............................................................................... + +GeneratorTests.cpp:<line number>: +PASSED: + CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) +with expansion: + 40 == 40 + +GeneratorTests.cpp:<line number>: +PASSED: + CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) +with expansion: + 202 == 202 + +------------------------------------------------------------------------------- +Generators over two ranges +------------------------------------------------------------------------------- +GeneratorTests.cpp:<line number> +............................................................................... + +GeneratorTests.cpp:<line number>: +PASSED: + CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) +with expansion: + 42 == 42 + +GeneratorTests.cpp:<line number>: +PASSED: + CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) +with expansion: + 202 == 202 + +------------------------------------------------------------------------------- +Generators over two ranges +------------------------------------------------------------------------------- +GeneratorTests.cpp:<line number> +............................................................................... + +GeneratorTests.cpp:<line number>: +PASSED: + CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) +with expansion: + 72 == 72 + +GeneratorTests.cpp:<line number>: +PASSED: + CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) +with expansion: + 202 == 202 + +------------------------------------------------------------------------------- +Generators over two ranges +------------------------------------------------------------------------------- +GeneratorTests.cpp:<line number> +............................................................................... + +GeneratorTests.cpp:<line number>: +PASSED: + CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) +with expansion: + 2 == 2 + +GeneratorTests.cpp:<line number>: +PASSED: + CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) +with expansion: + 204 == 204 + +------------------------------------------------------------------------------- +Generators over two ranges +------------------------------------------------------------------------------- +GeneratorTests.cpp:<line number> +............................................................................... + +GeneratorTests.cpp:<line number>: +PASSED: + CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) +with expansion: + 4 == 4 + +GeneratorTests.cpp:<line number>: +PASSED: + CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) +with expansion: + 204 == 204 + +------------------------------------------------------------------------------- +Generators over two ranges +------------------------------------------------------------------------------- +GeneratorTests.cpp:<line number> +............................................................................... + +GeneratorTests.cpp:<line number>: +PASSED: + CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) +with expansion: + 6 == 6 + +GeneratorTests.cpp:<line number>: +PASSED: + CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) +with expansion: + 204 == 204 + +------------------------------------------------------------------------------- +Generators over two ranges +------------------------------------------------------------------------------- +GeneratorTests.cpp:<line number> +............................................................................... + +GeneratorTests.cpp:<line number>: +PASSED: + CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) +with expansion: + 8 == 8 + +GeneratorTests.cpp:<line number>: +PASSED: + CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) +with expansion: + 204 == 204 + +------------------------------------------------------------------------------- +Generators over two ranges +------------------------------------------------------------------------------- +GeneratorTests.cpp:<line number> +............................................................................... + +GeneratorTests.cpp:<line number>: +PASSED: + CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) +with expansion: + 10 == 10 + +GeneratorTests.cpp:<line number>: +PASSED: + CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) +with expansion: + 204 == 204 + +------------------------------------------------------------------------------- +Generators over two ranges +------------------------------------------------------------------------------- +GeneratorTests.cpp:<line number> +............................................................................... + +GeneratorTests.cpp:<line number>: +PASSED: + CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) +with expansion: + 30 == 30 + +GeneratorTests.cpp:<line number>: +PASSED: + CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) +with expansion: + 204 == 204 + +------------------------------------------------------------------------------- +Generators over two ranges +------------------------------------------------------------------------------- +GeneratorTests.cpp:<line number> +............................................................................... + +GeneratorTests.cpp:<line number>: +PASSED: + CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) +with expansion: + 40 == 40 + +GeneratorTests.cpp:<line number>: +PASSED: + CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) +with expansion: + 204 == 204 + +------------------------------------------------------------------------------- +Generators over two ranges +------------------------------------------------------------------------------- +GeneratorTests.cpp:<line number> +............................................................................... + +GeneratorTests.cpp:<line number>: +PASSED: + CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) +with expansion: + 42 == 42 + +GeneratorTests.cpp:<line number>: +PASSED: + CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) +with expansion: + 204 == 204 + +------------------------------------------------------------------------------- +Generators over two ranges +------------------------------------------------------------------------------- +GeneratorTests.cpp:<line number> +............................................................................... + +GeneratorTests.cpp:<line number>: +PASSED: + CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) +with expansion: + 72 == 72 + +GeneratorTests.cpp:<line number>: +PASSED: + CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) +with expansion: + 204 == 204 + +------------------------------------------------------------------------------- +Generators over two ranges +------------------------------------------------------------------------------- +GeneratorTests.cpp:<line number> +............................................................................... + +GeneratorTests.cpp:<line number>: +PASSED: + CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) +with expansion: + 2 == 2 + +GeneratorTests.cpp:<line number>: +PASSED: + CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) +with expansion: + 206 == 206 + +------------------------------------------------------------------------------- +Generators over two ranges +------------------------------------------------------------------------------- +GeneratorTests.cpp:<line number> +............................................................................... + +GeneratorTests.cpp:<line number>: +PASSED: + CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) +with expansion: + 4 == 4 + +GeneratorTests.cpp:<line number>: +PASSED: + CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) +with expansion: + 206 == 206 + +------------------------------------------------------------------------------- +Generators over two ranges +------------------------------------------------------------------------------- +GeneratorTests.cpp:<line number> +............................................................................... + +GeneratorTests.cpp:<line number>: +PASSED: + CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) +with expansion: + 6 == 6 + +GeneratorTests.cpp:<line number>: +PASSED: + CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) +with expansion: + 206 == 206 + +------------------------------------------------------------------------------- +Generators over two ranges +------------------------------------------------------------------------------- +GeneratorTests.cpp:<line number> +............................................................................... + +GeneratorTests.cpp:<line number>: +PASSED: + CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) +with expansion: + 8 == 8 + +GeneratorTests.cpp:<line number>: +PASSED: + CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) +with expansion: + 206 == 206 + +------------------------------------------------------------------------------- +Generators over two ranges +------------------------------------------------------------------------------- +GeneratorTests.cpp:<line number> +............................................................................... + +GeneratorTests.cpp:<line number>: +PASSED: + CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) +with expansion: + 10 == 10 + +GeneratorTests.cpp:<line number>: +PASSED: + CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) +with expansion: + 206 == 206 + +------------------------------------------------------------------------------- +Generators over two ranges +------------------------------------------------------------------------------- +GeneratorTests.cpp:<line number> +............................................................................... + +GeneratorTests.cpp:<line number>: +PASSED: + CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) +with expansion: + 30 == 30 + +GeneratorTests.cpp:<line number>: +PASSED: + CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) +with expansion: + 206 == 206 + +------------------------------------------------------------------------------- +Generators over two ranges +------------------------------------------------------------------------------- +GeneratorTests.cpp:<line number> +............................................................................... + +GeneratorTests.cpp:<line number>: +PASSED: + CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) +with expansion: + 40 == 40 + +GeneratorTests.cpp:<line number>: +PASSED: + CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) +with expansion: + 206 == 206 + +------------------------------------------------------------------------------- +Generators over two ranges +------------------------------------------------------------------------------- +GeneratorTests.cpp:<line number> +............................................................................... + +GeneratorTests.cpp:<line number>: +PASSED: + CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) +with expansion: + 42 == 42 + +GeneratorTests.cpp:<line number>: +PASSED: + CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) +with expansion: + 206 == 206 + +------------------------------------------------------------------------------- +Generators over two ranges +------------------------------------------------------------------------------- +GeneratorTests.cpp:<line number> +............................................................................... + +GeneratorTests.cpp:<line number>: +PASSED: + CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) +with expansion: + 72 == 72 + +GeneratorTests.cpp:<line number>: +PASSED: + CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) +with expansion: + 206 == 206 + +------------------------------------------------------------------------------- +Generators over two ranges +------------------------------------------------------------------------------- +GeneratorTests.cpp:<line number> +............................................................................... + +GeneratorTests.cpp:<line number>: +PASSED: + CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) +with expansion: + 2 == 2 + +GeneratorTests.cpp:<line number>: +PASSED: + CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) +with expansion: + 208 == 208 + +------------------------------------------------------------------------------- +Generators over two ranges +------------------------------------------------------------------------------- +GeneratorTests.cpp:<line number> +............................................................................... + +GeneratorTests.cpp:<line number>: +PASSED: + CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) +with expansion: + 4 == 4 + +GeneratorTests.cpp:<line number>: +PASSED: + CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) +with expansion: + 208 == 208 + +------------------------------------------------------------------------------- +Generators over two ranges +------------------------------------------------------------------------------- +GeneratorTests.cpp:<line number> +............................................................................... + +GeneratorTests.cpp:<line number>: +PASSED: + CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) +with expansion: + 6 == 6 + +GeneratorTests.cpp:<line number>: +PASSED: + CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) +with expansion: + 208 == 208 + +------------------------------------------------------------------------------- +Generators over two ranges +------------------------------------------------------------------------------- +GeneratorTests.cpp:<line number> +............................................................................... + +GeneratorTests.cpp:<line number>: +PASSED: + CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) +with expansion: + 8 == 8 + +GeneratorTests.cpp:<line number>: +PASSED: + CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) +with expansion: + 208 == 208 + +------------------------------------------------------------------------------- +Generators over two ranges +------------------------------------------------------------------------------- +GeneratorTests.cpp:<line number> +............................................................................... + +GeneratorTests.cpp:<line number>: +PASSED: + CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) +with expansion: + 10 == 10 + +GeneratorTests.cpp:<line number>: +PASSED: + CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) +with expansion: + 208 == 208 + +------------------------------------------------------------------------------- +Generators over two ranges +------------------------------------------------------------------------------- +GeneratorTests.cpp:<line number> +............................................................................... + +GeneratorTests.cpp:<line number>: +PASSED: + CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) +with expansion: + 30 == 30 + +GeneratorTests.cpp:<line number>: +PASSED: + CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) +with expansion: + 208 == 208 + +------------------------------------------------------------------------------- +Generators over two ranges +------------------------------------------------------------------------------- +GeneratorTests.cpp:<line number> +............................................................................... + +GeneratorTests.cpp:<line number>: +PASSED: + CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) +with expansion: + 40 == 40 + +GeneratorTests.cpp:<line number>: +PASSED: + CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) +with expansion: + 208 == 208 + +------------------------------------------------------------------------------- +Generators over two ranges +------------------------------------------------------------------------------- +GeneratorTests.cpp:<line number> +............................................................................... + +GeneratorTests.cpp:<line number>: +PASSED: + CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) +with expansion: + 42 == 42 + +GeneratorTests.cpp:<line number>: +PASSED: + CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) +with expansion: + 208 == 208 + +------------------------------------------------------------------------------- +Generators over two ranges +------------------------------------------------------------------------------- +GeneratorTests.cpp:<line number> +............................................................................... + +GeneratorTests.cpp:<line number>: +PASSED: + CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) +with expansion: + 72 == 72 + +GeneratorTests.cpp:<line number>: +PASSED: + CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) +with expansion: + 208 == 208 + +------------------------------------------------------------------------------- +Generators over two ranges +------------------------------------------------------------------------------- +GeneratorTests.cpp:<line number> +............................................................................... + +GeneratorTests.cpp:<line number>: +PASSED: + CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) +with expansion: + 2 == 2 + +GeneratorTests.cpp:<line number>: +PASSED: + CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) +with expansion: + 210 == 210 + +------------------------------------------------------------------------------- +Generators over two ranges +------------------------------------------------------------------------------- +GeneratorTests.cpp:<line number> +............................................................................... + +GeneratorTests.cpp:<line number>: +PASSED: + CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) +with expansion: + 4 == 4 + +GeneratorTests.cpp:<line number>: +PASSED: + CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) +with expansion: + 210 == 210 + +------------------------------------------------------------------------------- +Generators over two ranges +------------------------------------------------------------------------------- +GeneratorTests.cpp:<line number> +............................................................................... + +GeneratorTests.cpp:<line number>: +PASSED: + CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) +with expansion: + 6 == 6 + +GeneratorTests.cpp:<line number>: +PASSED: + CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) +with expansion: + 210 == 210 + +------------------------------------------------------------------------------- +Generators over two ranges +------------------------------------------------------------------------------- +GeneratorTests.cpp:<line number> +............................................................................... + +GeneratorTests.cpp:<line number>: +PASSED: + CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) +with expansion: + 8 == 8 + +GeneratorTests.cpp:<line number>: +PASSED: + CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) +with expansion: + 210 == 210 + +------------------------------------------------------------------------------- +Generators over two ranges +------------------------------------------------------------------------------- +GeneratorTests.cpp:<line number> +............................................................................... + +GeneratorTests.cpp:<line number>: +PASSED: + CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) +with expansion: + 10 == 10 + +GeneratorTests.cpp:<line number>: +PASSED: + CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) +with expansion: + 210 == 210 + +------------------------------------------------------------------------------- +Generators over two ranges +------------------------------------------------------------------------------- +GeneratorTests.cpp:<line number> +............................................................................... + +GeneratorTests.cpp:<line number>: +PASSED: + CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) +with expansion: + 30 == 30 + +GeneratorTests.cpp:<line number>: +PASSED: + CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) +with expansion: + 210 == 210 + +------------------------------------------------------------------------------- +Generators over two ranges +------------------------------------------------------------------------------- +GeneratorTests.cpp:<line number> +............................................................................... + +GeneratorTests.cpp:<line number>: +PASSED: + CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) +with expansion: + 40 == 40 + +GeneratorTests.cpp:<line number>: +PASSED: + CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) +with expansion: + 210 == 210 + +------------------------------------------------------------------------------- +Generators over two ranges +------------------------------------------------------------------------------- +GeneratorTests.cpp:<line number> +............................................................................... + +GeneratorTests.cpp:<line number>: +PASSED: + CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) +with expansion: + 42 == 42 + +GeneratorTests.cpp:<line number>: +PASSED: + CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) +with expansion: + 210 == 210 + +------------------------------------------------------------------------------- +Generators over two ranges +------------------------------------------------------------------------------- +GeneratorTests.cpp:<line number> +............................................................................... + +GeneratorTests.cpp:<line number>: +PASSED: + CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) +with expansion: + 72 == 72 + +GeneratorTests.cpp:<line number>: +PASSED: + CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) +with expansion: + 210 == 210 + +------------------------------------------------------------------------------- +Generators over two ranges +------------------------------------------------------------------------------- +GeneratorTests.cpp:<line number> +............................................................................... + +GeneratorTests.cpp:<line number>: +PASSED: + CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) +with expansion: + 2 == 2 + +GeneratorTests.cpp:<line number>: +PASSED: + CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) +with expansion: + 212 == 212 + +------------------------------------------------------------------------------- +Generators over two ranges +------------------------------------------------------------------------------- +GeneratorTests.cpp:<line number> +............................................................................... + +GeneratorTests.cpp:<line number>: +PASSED: + CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) +with expansion: + 4 == 4 + +GeneratorTests.cpp:<line number>: +PASSED: + CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) +with expansion: + 212 == 212 + +------------------------------------------------------------------------------- +Generators over two ranges +------------------------------------------------------------------------------- +GeneratorTests.cpp:<line number> +............................................................................... + +GeneratorTests.cpp:<line number>: +PASSED: + CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) +with expansion: + 6 == 6 + +GeneratorTests.cpp:<line number>: +PASSED: + CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) +with expansion: + 212 == 212 + +------------------------------------------------------------------------------- +Generators over two ranges +------------------------------------------------------------------------------- +GeneratorTests.cpp:<line number> +............................................................................... + +GeneratorTests.cpp:<line number>: +PASSED: + CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) +with expansion: + 8 == 8 + +GeneratorTests.cpp:<line number>: +PASSED: + CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) +with expansion: + 212 == 212 + +------------------------------------------------------------------------------- +Generators over two ranges +------------------------------------------------------------------------------- +GeneratorTests.cpp:<line number> +............................................................................... + +GeneratorTests.cpp:<line number>: +PASSED: + CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) +with expansion: + 10 == 10 + +GeneratorTests.cpp:<line number>: +PASSED: + CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) +with expansion: + 212 == 212 + +------------------------------------------------------------------------------- +Generators over two ranges +------------------------------------------------------------------------------- +GeneratorTests.cpp:<line number> +............................................................................... + +GeneratorTests.cpp:<line number>: +PASSED: + CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) +with expansion: + 30 == 30 + +GeneratorTests.cpp:<line number>: +PASSED: + CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) +with expansion: + 212 == 212 + +------------------------------------------------------------------------------- +Generators over two ranges +------------------------------------------------------------------------------- +GeneratorTests.cpp:<line number> +............................................................................... + +GeneratorTests.cpp:<line number>: +PASSED: + CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) +with expansion: + 40 == 40 + +GeneratorTests.cpp:<line number>: +PASSED: + CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) +with expansion: + 212 == 212 + +------------------------------------------------------------------------------- +Generators over two ranges +------------------------------------------------------------------------------- +GeneratorTests.cpp:<line number> +............................................................................... + +GeneratorTests.cpp:<line number>: +PASSED: + CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) +with expansion: + 42 == 42 + +GeneratorTests.cpp:<line number>: +PASSED: + CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) +with expansion: + 212 == 212 + +------------------------------------------------------------------------------- +Generators over two ranges +------------------------------------------------------------------------------- +GeneratorTests.cpp:<line number> +............................................................................... + +GeneratorTests.cpp:<line number>: +PASSED: + CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) +with expansion: + 72 == 72 + +GeneratorTests.cpp:<line number>: +PASSED: + CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) +with expansion: + 212 == 212 + +------------------------------------------------------------------------------- +Generators over two ranges +------------------------------------------------------------------------------- +GeneratorTests.cpp:<line number> +............................................................................... + +GeneratorTests.cpp:<line number>: +PASSED: + CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) +with expansion: + 2 == 2 + +GeneratorTests.cpp:<line number>: +PASSED: + CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) +with expansion: + 214 == 214 + +------------------------------------------------------------------------------- +Generators over two ranges +------------------------------------------------------------------------------- +GeneratorTests.cpp:<line number> +............................................................................... + +GeneratorTests.cpp:<line number>: +PASSED: + CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) +with expansion: + 4 == 4 + +GeneratorTests.cpp:<line number>: +PASSED: + CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) +with expansion: + 214 == 214 + +------------------------------------------------------------------------------- +Generators over two ranges +------------------------------------------------------------------------------- +GeneratorTests.cpp:<line number> +............................................................................... + +GeneratorTests.cpp:<line number>: +PASSED: + CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) +with expansion: + 6 == 6 + +GeneratorTests.cpp:<line number>: +PASSED: + CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) +with expansion: + 214 == 214 + +------------------------------------------------------------------------------- +Generators over two ranges +------------------------------------------------------------------------------- +GeneratorTests.cpp:<line number> +............................................................................... + +GeneratorTests.cpp:<line number>: +PASSED: + CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) +with expansion: + 8 == 8 + +GeneratorTests.cpp:<line number>: +PASSED: + CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) +with expansion: + 214 == 214 + +------------------------------------------------------------------------------- +Generators over two ranges +------------------------------------------------------------------------------- +GeneratorTests.cpp:<line number> +............................................................................... + +GeneratorTests.cpp:<line number>: +PASSED: + CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) +with expansion: + 10 == 10 + +GeneratorTests.cpp:<line number>: +PASSED: + CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) +with expansion: + 214 == 214 + +------------------------------------------------------------------------------- +Generators over two ranges +------------------------------------------------------------------------------- +GeneratorTests.cpp:<line number> +............................................................................... + +GeneratorTests.cpp:<line number>: +PASSED: + CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) +with expansion: + 30 == 30 + +GeneratorTests.cpp:<line number>: +PASSED: + CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) +with expansion: + 214 == 214 + +------------------------------------------------------------------------------- +Generators over two ranges +------------------------------------------------------------------------------- +GeneratorTests.cpp:<line number> +............................................................................... + +GeneratorTests.cpp:<line number>: +PASSED: + CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) +with expansion: + 40 == 40 + +GeneratorTests.cpp:<line number>: +PASSED: + CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) +with expansion: + 214 == 214 + +------------------------------------------------------------------------------- +Generators over two ranges +------------------------------------------------------------------------------- +GeneratorTests.cpp:<line number> +............................................................................... + +GeneratorTests.cpp:<line number>: +PASSED: + CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) +with expansion: + 42 == 42 + +GeneratorTests.cpp:<line number>: +PASSED: + CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) +with expansion: + 214 == 214 + +------------------------------------------------------------------------------- +Generators over two ranges +------------------------------------------------------------------------------- +GeneratorTests.cpp:<line number> +............................................................................... + +GeneratorTests.cpp:<line number>: +PASSED: + CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) +with expansion: + 72 == 72 + +GeneratorTests.cpp:<line number>: +PASSED: + CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) +with expansion: + 214 == 214 + +------------------------------------------------------------------------------- +Generator over a range of pairs +------------------------------------------------------------------------------- +GeneratorTests.cpp:<line number> +............................................................................... + +GeneratorTests.cpp:<line number>: +PASSED: + CATCH_REQUIRE( i->first == i->second-1 ) +with expansion: + 0 == 0 + +------------------------------------------------------------------------------- +Generator over a range of pairs +------------------------------------------------------------------------------- +GeneratorTests.cpp:<line number> +............................................................................... + +GeneratorTests.cpp:<line number>: +PASSED: + CATCH_REQUIRE( i->first == i->second-1 ) +with expansion: + 2 == 2 + +------------------------------------------------------------------------------- +INFO and WARN do not abort tests +------------------------------------------------------------------------------- +MessageTests.cpp:<line number> +............................................................................... + +MessageTests.cpp:<line number>: +warning: + this is a message + this is a warning + +------------------------------------------------------------------------------- +SUCCEED counts as a test pass +------------------------------------------------------------------------------- +MessageTests.cpp:<line number> +............................................................................... + +MessageTests.cpp:<line number>: +PASSED: +with message: + this is a success + +------------------------------------------------------------------------------- +INFO gets logged on failure +------------------------------------------------------------------------------- +MessageTests.cpp:<line number> +............................................................................... + +MessageTests.cpp:<line number>: FAILED: + REQUIRE( a == 1 ) +with expansion: + 2 == 1 +with messages: + this message should be logged + so should this + +------------------------------------------------------------------------------- +INFO gets logged on failure, even if captured before successful assertions +------------------------------------------------------------------------------- +MessageTests.cpp:<line number> +............................................................................... + +MessageTests.cpp:<line number>: +PASSED: + CHECK( a == 2 ) +with expansion: + 2 == 2 +with message: + this message may be logged later + +MessageTests.cpp:<line number>: FAILED: + CHECK( a == 1 ) +with expansion: + 2 == 1 +with message: + this message should be logged + +MessageTests.cpp:<line number>: FAILED: + CHECK( a == 0 ) +with expansion: + 2 == 0 +with message: + and this, but later + +MessageTests.cpp:<line number>: +PASSED: + CHECK( a == 2 ) +with expansion: + 2 == 2 +with message: + but not this + +------------------------------------------------------------------------------- +FAIL aborts the test +------------------------------------------------------------------------------- +MessageTests.cpp:<line number> +............................................................................... + +MessageTests.cpp:<line number>: FAILED: +explicitly with message: + This is a failure + +------------------------------------------------------------------------------- +FAIL does not require an argument +------------------------------------------------------------------------------- +MessageTests.cpp:<line number> +............................................................................... + +MessageTests.cpp:<line number>: FAILED: + +------------------------------------------------------------------------------- +SUCCESS does not require an argument +------------------------------------------------------------------------------- +MessageTests.cpp:<line number> +............................................................................... + +MessageTests.cpp:<line number>: +PASSED: + +------------------------------------------------------------------------------- +Output from all sections is reported + one +------------------------------------------------------------------------------- +MessageTests.cpp:<line number> +............................................................................... + +MessageTests.cpp:<line number>: FAILED: +explicitly with message: + Message from section one + +------------------------------------------------------------------------------- +Output from all sections is reported + two +------------------------------------------------------------------------------- +MessageTests.cpp:<line number> +............................................................................... + +MessageTests.cpp:<line number>: FAILED: +explicitly with message: + Message from section two + +Message from section one +------------------------------------------------------------------------------- +Standard output from all sections is reported + one +------------------------------------------------------------------------------- +MessageTests.cpp:<line number> +............................................................................... + + +No assertions in section 'one' + +Message from section two +------------------------------------------------------------------------------- +Standard output from all sections is reported + two +------------------------------------------------------------------------------- +MessageTests.cpp:<line number> +............................................................................... + + +No assertions in section 'two' + +------------------------------------------------------------------------------- +SCOPED_INFO is reset for each loop +------------------------------------------------------------------------------- +MessageTests.cpp:<line number> +............................................................................... + +MessageTests.cpp:<line number>: +PASSED: + REQUIRE( i < 10 ) +with expansion: + 0 < 10 +with messages: + current counter 0 + i := 0 + +MessageTests.cpp:<line number>: +PASSED: + REQUIRE( i < 10 ) +with expansion: + 1 < 10 +with messages: + current counter 1 + i := 1 + +MessageTests.cpp:<line number>: +PASSED: + REQUIRE( i < 10 ) +with expansion: + 2 < 10 +with messages: + current counter 2 + i := 2 + +MessageTests.cpp:<line number>: +PASSED: + REQUIRE( i < 10 ) +with expansion: + 3 < 10 +with messages: + current counter 3 + i := 3 + +MessageTests.cpp:<line number>: +PASSED: + REQUIRE( i < 10 ) +with expansion: + 4 < 10 +with messages: + current counter 4 + i := 4 + +MessageTests.cpp:<line number>: +PASSED: + REQUIRE( i < 10 ) +with expansion: + 5 < 10 +with messages: + current counter 5 + i := 5 + +MessageTests.cpp:<line number>: +PASSED: + REQUIRE( i < 10 ) +with expansion: + 6 < 10 +with messages: + current counter 6 + i := 6 + +MessageTests.cpp:<line number>: +PASSED: + REQUIRE( i < 10 ) +with expansion: + 7 < 10 +with messages: + current counter 7 + i := 7 + +MessageTests.cpp:<line number>: +PASSED: + REQUIRE( i < 10 ) +with expansion: + 8 < 10 +with messages: + current counter 8 + i := 8 + +MessageTests.cpp:<line number>: +PASSED: + REQUIRE( i < 10 ) +with expansion: + 9 < 10 +with messages: + current counter 9 + i := 9 + +MessageTests.cpp:<line number>: FAILED: + REQUIRE( i < 10 ) +with expansion: + 10 < 10 +with messages: + current counter 10 + i := 10 + +------------------------------------------------------------------------------- +The NO_FAIL macro reports a failure but does not fail the test +------------------------------------------------------------------------------- +MessageTests.cpp:<line number> +............................................................................... + +MessageTests.cpp:<line number>: +FAILED - but was ok: + CHECK_NOFAIL( 1 == 2 ) + +------------------------------------------------------------------------------- +just failure +------------------------------------------------------------------------------- +MessageTests.cpp:<line number> +............................................................................... + +MessageTests.cpp:<line number>: FAILED: +explicitly with message: + Previous info should not be seen + +------------------------------------------------------------------------------- +sends information to INFO +------------------------------------------------------------------------------- +MessageTests.cpp:<line number> +............................................................................... + +MessageTests.cpp:<line number>: FAILED: + REQUIRE( false ) +with messages: + hi + i := 7 + +------------------------------------------------------------------------------- +Pointers can be converted to strings +------------------------------------------------------------------------------- +MessageTests.cpp:<line number> +............................................................................... + +MessageTests.cpp:<line number>: +warning: + actual address of p: 0x<hex digits> + +MessageTests.cpp:<line number>: +warning: + toString(p): 0x<hex digits> + +------------------------------------------------------------------------------- +random SECTION tests + s1 +------------------------------------------------------------------------------- +MiscTests.cpp:<line number> +............................................................................... + +MiscTests.cpp:<line number>: +PASSED: + REQUIRE( a != b ) +with expansion: + 1 != 2 + +MiscTests.cpp:<line number>: +PASSED: + REQUIRE( b != a ) +with expansion: + 2 != 1 + +------------------------------------------------------------------------------- +random SECTION tests + s2 +------------------------------------------------------------------------------- +MiscTests.cpp:<line number> +............................................................................... + +MiscTests.cpp:<line number>: +PASSED: + REQUIRE( a != b ) +with expansion: + 1 != 2 + +------------------------------------------------------------------------------- +nested SECTION tests + s1 +------------------------------------------------------------------------------- +MiscTests.cpp:<line number> +............................................................................... + +MiscTests.cpp:<line number>: +PASSED: + REQUIRE( a != b ) +with expansion: + 1 != 2 + +MiscTests.cpp:<line number>: +PASSED: + REQUIRE( b != a ) +with expansion: + 2 != 1 + +------------------------------------------------------------------------------- +nested SECTION tests + s1 + s2 +------------------------------------------------------------------------------- +MiscTests.cpp:<line number> +............................................................................... + +MiscTests.cpp:<line number>: +PASSED: + REQUIRE( a != b ) +with expansion: + 1 != 2 + +------------------------------------------------------------------------------- +more nested SECTION tests + s1 + s2 +------------------------------------------------------------------------------- +MiscTests.cpp:<line number> +............................................................................... + +MiscTests.cpp:<line number>: FAILED: + REQUIRE( a == b ) +with expansion: + 1 == 2 + +------------------------------------------------------------------------------- +more nested SECTION tests + s1 + s3 +------------------------------------------------------------------------------- +MiscTests.cpp:<line number> +............................................................................... + +MiscTests.cpp:<line number>: +PASSED: + REQUIRE( a != b ) +with expansion: + 1 != 2 + +------------------------------------------------------------------------------- +more nested SECTION tests + s1 + s4 +------------------------------------------------------------------------------- +MiscTests.cpp:<line number> +............................................................................... + +MiscTests.cpp:<line number>: +PASSED: + REQUIRE( a < b ) +with expansion: + 1 < 2 + +------------------------------------------------------------------------------- +even more nested SECTION tests + c + d (leaf) +------------------------------------------------------------------------------- +MiscTests.cpp:<line number> +............................................................................... + +MiscTests.cpp:<line number>: +PASSED: + +------------------------------------------------------------------------------- +even more nested SECTION tests + c + e (leaf) +------------------------------------------------------------------------------- +MiscTests.cpp:<line number> +............................................................................... + +MiscTests.cpp:<line number>: +PASSED: + +------------------------------------------------------------------------------- +even more nested SECTION tests + f (leaf) +------------------------------------------------------------------------------- +MiscTests.cpp:<line number> +............................................................................... + +MiscTests.cpp:<line number>: +PASSED: + +------------------------------------------------------------------------------- +looped SECTION tests + s1 +------------------------------------------------------------------------------- +MiscTests.cpp:<line number> +............................................................................... + +MiscTests.cpp:<line number>: FAILED: + CHECK( b > a ) +with expansion: + 0 > 1 + +------------------------------------------------------------------------------- +looped tests +------------------------------------------------------------------------------- +MiscTests.cpp:<line number> +............................................................................... + +MiscTests.cpp:<line number>: FAILED: + CHECK( ( fib[i] % 2 ) == 0 ) +with expansion: + 1 == 0 +with message: + Testing if fib[0] (1) is even + +MiscTests.cpp:<line number>: FAILED: + CHECK( ( fib[i] % 2 ) == 0 ) +with expansion: + 1 == 0 +with message: + Testing if fib[1] (1) is even + +MiscTests.cpp:<line number>: +PASSED: + CHECK( ( fib[i] % 2 ) == 0 ) +with expansion: + 0 == 0 +with message: + Testing if fib[2] (2) is even + +MiscTests.cpp:<line number>: FAILED: + CHECK( ( fib[i] % 2 ) == 0 ) +with expansion: + 1 == 0 +with message: + Testing if fib[3] (3) is even + +MiscTests.cpp:<line number>: FAILED: + CHECK( ( fib[i] % 2 ) == 0 ) +with expansion: + 1 == 0 +with message: + Testing if fib[4] (5) is even + +MiscTests.cpp:<line number>: +PASSED: + CHECK( ( fib[i] % 2 ) == 0 ) +with expansion: + 0 == 0 +with message: + Testing if fib[5] (8) is even + +MiscTests.cpp:<line number>: FAILED: + CHECK( ( fib[i] % 2 ) == 0 ) +with expansion: + 1 == 0 +with message: + Testing if fib[6] (13) is even + +MiscTests.cpp:<line number>: FAILED: + CHECK( ( fib[i] % 2 ) == 0 ) +with expansion: + 1 == 0 +with message: + Testing if fib[7] (21) is even + +A string sent directly to stdout +A string sent directly to stderr +------------------------------------------------------------------------------- +null strings +------------------------------------------------------------------------------- +MiscTests.cpp:<line number> +............................................................................... + +MiscTests.cpp:<line number>: +PASSED: + REQUIRE( makeString( false ) != static_cast<char*>(nullptr) ) +with expansion: + "valid string" != {null string} + +MiscTests.cpp:<line number>: +PASSED: + REQUIRE( makeString( true ) == static_cast<char*>(nullptr) ) +with expansion: + {null string} == {null string} + +------------------------------------------------------------------------------- +checkedIf +------------------------------------------------------------------------------- +MiscTests.cpp:<line number> +............................................................................... + +MiscTests.cpp:<line number>: +PASSED: + CHECKED_IF( flag ) +with expansion: + true + +MiscTests.cpp:<line number>: +PASSED: + REQUIRE( testCheckedIf( true ) ) +with expansion: + true + +------------------------------------------------------------------------------- +checkedIf, failing +------------------------------------------------------------------------------- +MiscTests.cpp:<line number> +............................................................................... + +MiscTests.cpp:<line number>: FAILED: + CHECKED_IF( flag ) +with expansion: + false + +MiscTests.cpp:<line number>: FAILED: + REQUIRE( testCheckedIf( false ) ) +with expansion: + false + +------------------------------------------------------------------------------- +checkedElse +------------------------------------------------------------------------------- +MiscTests.cpp:<line number> +............................................................................... + +MiscTests.cpp:<line number>: +PASSED: + CHECKED_ELSE( flag ) +with expansion: + true + +MiscTests.cpp:<line number>: +PASSED: + REQUIRE( testCheckedElse( true ) ) +with expansion: + true + +------------------------------------------------------------------------------- +checkedElse, failing +------------------------------------------------------------------------------- +MiscTests.cpp:<line number> +............................................................................... + +MiscTests.cpp:<line number>: FAILED: + CHECKED_ELSE( flag ) +with expansion: + false + +MiscTests.cpp:<line number>: FAILED: + REQUIRE( testCheckedElse( false ) ) +with expansion: + false + +------------------------------------------------------------------------------- +xmlentitycheck + embedded xml +------------------------------------------------------------------------------- +MiscTests.cpp:<line number> +............................................................................... + +MiscTests.cpp:<line number>: +PASSED: + +------------------------------------------------------------------------------- +xmlentitycheck + encoded chars +------------------------------------------------------------------------------- +MiscTests.cpp:<line number> +............................................................................... + +MiscTests.cpp:<line number>: +PASSED: + +------------------------------------------------------------------------------- +send a single char to INFO +------------------------------------------------------------------------------- +MiscTests.cpp:<line number> +............................................................................... + +MiscTests.cpp:<line number>: FAILED: + REQUIRE( false ) +with message: + 3 + +------------------------------------------------------------------------------- +atomic if +------------------------------------------------------------------------------- +MiscTests.cpp:<line number> +............................................................................... + +MiscTests.cpp:<line number>: +PASSED: + REQUIRE( x == 0 ) +with expansion: + 0 == 0 + +------------------------------------------------------------------------------- +String matchers +------------------------------------------------------------------------------- +MiscTests.cpp:<line number> +............................................................................... + +MiscTests.cpp:<line number>: +PASSED: + REQUIRE_THAT( testStringForMatching(), Contains( "string" ) ) +with expansion: + "this string contains 'abc' as a substring" contains: "string" + +MiscTests.cpp:<line number>: +PASSED: + CHECK_THAT( testStringForMatching(), Contains( "abc" ) ) +with expansion: + "this string contains 'abc' as a substring" contains: "abc" + +MiscTests.cpp:<line number>: +PASSED: + CHECK_THAT( testStringForMatching(), StartsWith( "this" ) ) +with expansion: + "this string contains 'abc' as a substring" starts with: "this" + +MiscTests.cpp:<line number>: +PASSED: + CHECK_THAT( testStringForMatching(), EndsWith( "substring" ) ) +with expansion: + "this string contains 'abc' as a substring" ends with: "substring" + +------------------------------------------------------------------------------- +Contains string matcher +------------------------------------------------------------------------------- +MiscTests.cpp:<line number> +............................................................................... + +MiscTests.cpp:<line number>: FAILED: + CHECK_THAT( testStringForMatching(), Contains( "not there" ) ) +with expansion: + "this string contains 'abc' as a substring" contains: "not there" + +------------------------------------------------------------------------------- +StartsWith string matcher +------------------------------------------------------------------------------- +MiscTests.cpp:<line number> +............................................................................... + +MiscTests.cpp:<line number>: FAILED: + CHECK_THAT( testStringForMatching(), StartsWith( "string" ) ) +with expansion: + "this string contains 'abc' as a substring" starts with: "string" + +------------------------------------------------------------------------------- +EndsWith string matcher +------------------------------------------------------------------------------- +MiscTests.cpp:<line number> +............................................................................... + +MiscTests.cpp:<line number>: FAILED: + CHECK_THAT( testStringForMatching(), EndsWith( "this" ) ) +with expansion: + "this string contains 'abc' as a substring" ends with: "this" + +------------------------------------------------------------------------------- +Equals string matcher +------------------------------------------------------------------------------- +MiscTests.cpp:<line number> +............................................................................... + +MiscTests.cpp:<line number>: FAILED: + CHECK_THAT( testStringForMatching(), Equals( "something else" ) ) +with expansion: + "this string contains 'abc' as a substring" equals: "something else" + +------------------------------------------------------------------------------- +Equals string matcher, with NULL +------------------------------------------------------------------------------- +MiscTests.cpp:<line number> +............................................................................... + +MiscTests.cpp:<line number>: +PASSED: + REQUIRE_THAT( "", Equals(nullptr) ) +with expansion: + "" equals: "" + +------------------------------------------------------------------------------- +AllOf matcher +------------------------------------------------------------------------------- +MiscTests.cpp:<line number> +............................................................................... + +MiscTests.cpp:<line number>: +PASSED: + CHECK_THAT( testStringForMatching(), AllOf( Catch::Contains( "string" ), Catch::Contains( "abc" ) ) ) +with expansion: + "this string contains 'abc' as a substring" ( contains: "string" and + contains: "abc" ) + +------------------------------------------------------------------------------- +AnyOf matcher +------------------------------------------------------------------------------- +MiscTests.cpp:<line number> +............................................................................... + +MiscTests.cpp:<line number>: +PASSED: + CHECK_THAT( testStringForMatching(), AnyOf( Catch::Contains( "string" ), Catch::Contains( "not there" ) ) ) +with expansion: + "this string contains 'abc' as a substring" ( contains: "string" or contains: + "not there" ) + +MiscTests.cpp:<line number>: +PASSED: + CHECK_THAT( testStringForMatching(), AnyOf( Catch::Contains( "not there" ), Catch::Contains( "string" ) ) ) +with expansion: + "this string contains 'abc' as a substring" ( contains: "not there" or + contains: "string" ) + +------------------------------------------------------------------------------- +Equals +------------------------------------------------------------------------------- +MiscTests.cpp:<line number> +............................................................................... + +MiscTests.cpp:<line number>: +PASSED: + CHECK_THAT( testStringForMatching(), Equals( "this string contains 'abc' as a substring" ) ) +with expansion: + "this string contains 'abc' as a substring" equals: "this string contains + 'abc' as a substring" + +------------------------------------------------------------------------------- +Matchers can be (AllOf) composed with the && operator +------------------------------------------------------------------------------- +MiscTests.cpp:<line number> +............................................................................... + +MiscTests.cpp:<line number>: +PASSED: + CHECK_THAT( testStringForMatching(), Contains( "string" ) && Contains( "abc" ) && Contains( "substring" ) && Contains( "contains" ) ) +with expansion: + "this string contains 'abc' as a substring" ( contains: "string" and + contains: "abc" and contains: "substring" and contains: "contains" ) + +------------------------------------------------------------------------------- +Matchers can be (AnyOf) composed with the || operator +------------------------------------------------------------------------------- +MiscTests.cpp:<line number> +............................................................................... + +MiscTests.cpp:<line number>: +PASSED: + CHECK_THAT( testStringForMatching(), Contains( "string" ) || Contains( "different" ) || Contains( "random" ) ) +with expansion: + "this string contains 'abc' as a substring" ( contains: "string" or contains: + "different" or contains: "random" ) + +MiscTests.cpp:<line number>: +PASSED: + CHECK_THAT( testStringForMatching2(), Contains( "string" ) || Contains( "different" ) || Contains( "random" ) ) +with expansion: + "some completely different text that contains one common word" ( contains: + "string" or contains: "different" or contains: "random" ) + +------------------------------------------------------------------------------- +Matchers can be composed with both && and || +------------------------------------------------------------------------------- +MiscTests.cpp:<line number> +............................................................................... + +MiscTests.cpp:<line number>: +PASSED: + CHECK_THAT( testStringForMatching(), ( Contains( "string" ) || Contains( "different" ) ) && Contains( "substring" ) ) +with expansion: + "this string contains 'abc' as a substring" ( ( contains: "string" or + contains: "different" ) and contains: "substring" ) + +------------------------------------------------------------------------------- +Matchers can be composed with both && and || - failing +------------------------------------------------------------------------------- +MiscTests.cpp:<line number> +............................................................................... + +MiscTests.cpp:<line number>: FAILED: + CHECK_THAT( testStringForMatching(), ( Contains( "string" ) || Contains( "different" ) ) && Contains( "random" ) ) +with expansion: + "this string contains 'abc' as a substring" ( ( contains: "string" or + contains: "different" ) and contains: "random" ) + +------------------------------------------------------------------------------- +Matchers can be negated (Not) with the ! operator +------------------------------------------------------------------------------- +MiscTests.cpp:<line number> +............................................................................... + +MiscTests.cpp:<line number>: +PASSED: + CHECK_THAT( testStringForMatching(), !Contains( "different" ) ) +with expansion: + "this string contains 'abc' as a substring" not contains: "different" + +------------------------------------------------------------------------------- +Matchers can be negated (Not) with the ! operator - failing +------------------------------------------------------------------------------- +MiscTests.cpp:<line number> +............................................................................... + +MiscTests.cpp:<line number>: FAILED: + CHECK_THAT( testStringForMatching(), !Contains( "substring" ) ) +with expansion: + "this string contains 'abc' as a substring" not contains: "substring" + +------------------------------------------------------------------------------- +Factorials are computed +------------------------------------------------------------------------------- +MiscTests.cpp:<line number> +............................................................................... + +MiscTests.cpp:<line number>: +PASSED: + REQUIRE( Factorial(0) == 1 ) +with expansion: + 1 == 1 + +MiscTests.cpp:<line number>: +PASSED: + REQUIRE( Factorial(1) == 1 ) +with expansion: + 1 == 1 + +MiscTests.cpp:<line number>: +PASSED: + REQUIRE( Factorial(2) == 2 ) +with expansion: + 2 == 2 + +MiscTests.cpp:<line number>: +PASSED: + REQUIRE( Factorial(3) == 6 ) +with expansion: + 6 == 6 + +MiscTests.cpp:<line number>: +PASSED: + REQUIRE( Factorial(10) == 3628800 ) +with expansion: + 3628800 (0x<hex digits>) == 3628800 (0x<hex digits>) + +------------------------------------------------------------------------------- +Nice descriptive name +------------------------------------------------------------------------------- +MiscTests.cpp:<line number> +............................................................................... + +MiscTests.cpp:<line number>: +warning: + This one ran + +------------------------------------------------------------------------------- +vectors can be sized and resized +------------------------------------------------------------------------------- +MiscTests.cpp:<line number> +............................................................................... + +MiscTests.cpp:<line number>: +PASSED: + REQUIRE( v.size() == 5 ) +with expansion: + 5 == 5 + +MiscTests.cpp:<line number>: +PASSED: + REQUIRE( v.capacity() >= 5 ) +with expansion: + 5 >= 5 + +------------------------------------------------------------------------------- +vectors can be sized and resized + resizing bigger changes size and capacity +------------------------------------------------------------------------------- +MiscTests.cpp:<line number> +............................................................................... + +MiscTests.cpp:<line number>: +PASSED: + REQUIRE( v.size() == 10 ) +with expansion: + 10 == 10 + +MiscTests.cpp:<line number>: +PASSED: + REQUIRE( v.capacity() >= 10 ) +with expansion: + 10 >= 10 + +------------------------------------------------------------------------------- +vectors can be sized and resized +------------------------------------------------------------------------------- +MiscTests.cpp:<line number> +............................................................................... + +MiscTests.cpp:<line number>: +PASSED: + REQUIRE( v.size() == 5 ) +with expansion: + 5 == 5 + +MiscTests.cpp:<line number>: +PASSED: + REQUIRE( v.capacity() >= 5 ) +with expansion: + 5 >= 5 + +------------------------------------------------------------------------------- +vectors can be sized and resized + resizing smaller changes size but not capacity +------------------------------------------------------------------------------- +MiscTests.cpp:<line number> +............................................................................... + +MiscTests.cpp:<line number>: +PASSED: + REQUIRE( v.size() == 0 ) +with expansion: + 0 == 0 + +MiscTests.cpp:<line number>: +PASSED: + REQUIRE( v.capacity() >= 5 ) +with expansion: + 5 >= 5 + +------------------------------------------------------------------------------- +vectors can be sized and resized + resizing smaller changes size but not capacity + We can use the 'swap trick' to reset the capacity +------------------------------------------------------------------------------- +MiscTests.cpp:<line number> +............................................................................... + +MiscTests.cpp:<line number>: +PASSED: + REQUIRE( v.capacity() == 0 ) +with expansion: + 0 == 0 + +------------------------------------------------------------------------------- +vectors can be sized and resized +------------------------------------------------------------------------------- +MiscTests.cpp:<line number> +............................................................................... + +MiscTests.cpp:<line number>: +PASSED: + REQUIRE( v.size() == 5 ) +with expansion: + 5 == 5 + +MiscTests.cpp:<line number>: +PASSED: + REQUIRE( v.capacity() >= 5 ) +with expansion: + 5 >= 5 + +------------------------------------------------------------------------------- +vectors can be sized and resized + reserving bigger changes capacity but not size +------------------------------------------------------------------------------- +MiscTests.cpp:<line number> +............................................................................... + +MiscTests.cpp:<line number>: +PASSED: + REQUIRE( v.size() == 5 ) +with expansion: + 5 == 5 + +MiscTests.cpp:<line number>: +PASSED: + REQUIRE( v.capacity() >= 10 ) +with expansion: + 10 >= 10 + +------------------------------------------------------------------------------- +vectors can be sized and resized +------------------------------------------------------------------------------- +MiscTests.cpp:<line number> +............................................................................... + +MiscTests.cpp:<line number>: +PASSED: + REQUIRE( v.size() == 5 ) +with expansion: + 5 == 5 + +MiscTests.cpp:<line number>: +PASSED: + REQUIRE( v.capacity() >= 5 ) +with expansion: + 5 >= 5 + +------------------------------------------------------------------------------- +vectors can be sized and resized + reserving smaller does not change size or capacity +------------------------------------------------------------------------------- +MiscTests.cpp:<line number> +............................................................................... + +MiscTests.cpp:<line number>: +PASSED: + REQUIRE( v.size() == 5 ) +with expansion: + 5 == 5 + +MiscTests.cpp:<line number>: +PASSED: + REQUIRE( v.capacity() >= 5 ) +with expansion: + 5 >= 5 + +------------------------------------------------------------------------------- +A couple of nested sections followed by a failure + Outer + Inner +------------------------------------------------------------------------------- +MiscTests.cpp:<line number> +............................................................................... + +MiscTests.cpp:<line number>: +PASSED: +with message: + that's not flying - that's failing in style + +------------------------------------------------------------------------------- +A couple of nested sections followed by a failure +------------------------------------------------------------------------------- +MiscTests.cpp:<line number> +............................................................................... + +MiscTests.cpp:<line number>: FAILED: +explicitly with message: + to infinity and beyond + +------------------------------------------------------------------------------- +not allowed +------------------------------------------------------------------------------- +MiscTests.cpp:<line number> +............................................................................... + +MiscTests.cpp:<line number>: +PASSED: + +------------------------------------------------------------------------------- +Tabs and newlines show in output +------------------------------------------------------------------------------- +MiscTests.cpp:<line number> +............................................................................... + +MiscTests.cpp:<line number>: FAILED: + CHECK( s1 == s2 ) +with expansion: + "if ($b == 10) { + $a= 20; + }" + == + "if ($b == 10) { + $a = 20; + } + " + +------------------------------------------------------------------------------- +toString on const wchar_t const pointer returns the string contents +------------------------------------------------------------------------------- +MiscTests.cpp:<line number> +............................................................................... + +MiscTests.cpp:<line number>: +PASSED: + CHECK( result == "\"wide load\"" ) +with expansion: + ""wide load"" == ""wide load"" + +------------------------------------------------------------------------------- +toString on const wchar_t pointer returns the string contents +------------------------------------------------------------------------------- +MiscTests.cpp:<line number> +............................................................................... + +MiscTests.cpp:<line number>: +PASSED: + CHECK( result == "\"wide load\"" ) +with expansion: + ""wide load"" == ""wide load"" + +------------------------------------------------------------------------------- +toString on wchar_t const pointer returns the string contents +------------------------------------------------------------------------------- +MiscTests.cpp:<line number> +............................................................................... + +MiscTests.cpp:<line number>: +PASSED: + CHECK( result == "\"wide load\"" ) +with expansion: + ""wide load"" == ""wide load"" + +------------------------------------------------------------------------------- +toString on wchar_t returns the string contents +------------------------------------------------------------------------------- +MiscTests.cpp:<line number> +............................................................................... + +MiscTests.cpp:<line number>: +PASSED: + CHECK( result == "\"wide load\"" ) +with expansion: + ""wide load"" == ""wide load"" + +------------------------------------------------------------------------------- +XmlEncode + normal string +------------------------------------------------------------------------------- +MiscTests.cpp:<line number> +............................................................................... + +MiscTests.cpp:<line number>: +PASSED: + REQUIRE( encode( "normal string" ) == "normal string" ) +with expansion: + "normal string" == "normal string" + +------------------------------------------------------------------------------- +XmlEncode + empty string +------------------------------------------------------------------------------- +MiscTests.cpp:<line number> +............................................................................... + +MiscTests.cpp:<line number>: +PASSED: + REQUIRE( encode( "" ) == "" ) +with expansion: + "" == "" + +------------------------------------------------------------------------------- +XmlEncode + string with ampersand +------------------------------------------------------------------------------- +MiscTests.cpp:<line number> +............................................................................... + +MiscTests.cpp:<line number>: +PASSED: + REQUIRE( encode( "smith & jones" ) == "smith & jones" ) +with expansion: + "smith & jones" == "smith & jones" + +------------------------------------------------------------------------------- +XmlEncode + string with less-than +------------------------------------------------------------------------------- +MiscTests.cpp:<line number> +............................................................................... + +MiscTests.cpp:<line number>: +PASSED: + REQUIRE( encode( "smith < jones" ) == "smith < jones" ) +with expansion: + "smith < jones" == "smith < jones" + +------------------------------------------------------------------------------- +XmlEncode + string with greater-than +------------------------------------------------------------------------------- +MiscTests.cpp:<line number> +............................................................................... + +MiscTests.cpp:<line number>: +PASSED: + REQUIRE( encode( "smith > jones" ) == "smith > jones" ) +with expansion: + "smith > jones" == "smith > jones" + +MiscTests.cpp:<line number>: +PASSED: + REQUIRE( encode( "smith ]]> jones" ) == "smith ]]> jones" ) +with expansion: + "smith ]]> jones" + == + "smith ]]> jones" + +------------------------------------------------------------------------------- +XmlEncode + string with quotes +------------------------------------------------------------------------------- +MiscTests.cpp:<line number> +............................................................................... + +MiscTests.cpp:<line number>: +PASSED: + REQUIRE( encode( stringWithQuotes ) == stringWithQuotes ) +with expansion: + "don't "quote" me on that" + == + "don't "quote" me on that" + +MiscTests.cpp:<line number>: +PASSED: + REQUIRE( encode( stringWithQuotes, Catch::XmlEncode::ForAttributes ) == "don't "quote" me on that" ) +with expansion: + "don't "quote" me on that" + == + "don't "quote" me on that" + +------------------------------------------------------------------------------- +XmlEncode + string with control char (1) +------------------------------------------------------------------------------- +MiscTests.cpp:<line number> +............................................................................... + +MiscTests.cpp:<line number>: +PASSED: + REQUIRE( encode( "[\x01]" ) == "[]" ) +with expansion: + "[]" == "[]" + +------------------------------------------------------------------------------- +XmlEncode + string with control char (x7F) +------------------------------------------------------------------------------- +MiscTests.cpp:<line number> +............................................................................... + +MiscTests.cpp:<line number>: +PASSED: + REQUIRE( encode( "[\x7F]" ) == "[]" ) +with expansion: + "[]" == "[]" + +------------------------------------------------------------------------------- +long long +------------------------------------------------------------------------------- +MiscTests.cpp:<line number> +............................................................................... + +MiscTests.cpp:<line number>: +PASSED: + REQUIRE( l == std::numeric_limits<long long>::max() ) +with expansion: + 9223372036854775807 (0x<hex digits>) + == + 9223372036854775807 (0x<hex digits>) + +------------------------------------------------------------------------------- +Process can be configured on command line + default - no arguments +------------------------------------------------------------------------------- +TestMain.cpp:<line number> +............................................................................... + +TestMain.cpp:<line number>: +PASSED: + CHECK_NOTHROW( parseIntoConfig( argv, config ) ) + +TestMain.cpp:<line number>: +PASSED: + CHECK( config.shouldDebugBreak == false ) +with expansion: + false == false + +TestMain.cpp:<line number>: +PASSED: + CHECK( config.abortAfter == -1 ) +with expansion: + -1 == -1 + +TestMain.cpp:<line number>: +PASSED: + CHECK( config.noThrow == false ) +with expansion: + false == false + +TestMain.cpp:<line number>: +PASSED: + CHECK( config.reporterNames.empty() ) +with expansion: + true + +------------------------------------------------------------------------------- +Process can be configured on command line + test lists + 1 test +------------------------------------------------------------------------------- +TestMain.cpp:<line number> +............................................................................... + +TestMain.cpp:<line number>: +PASSED: + CHECK_NOTHROW( parseIntoConfig( argv, config ) ) + +TestMain.cpp:<line number>: +PASSED: + REQUIRE( cfg.testSpec().matches( fakeTestCase( "notIncluded" ) ) == false ) +with expansion: + false == false + +TestMain.cpp:<line number>: +PASSED: + REQUIRE( cfg.testSpec().matches( fakeTestCase( "test1" ) ) ) +with expansion: + true + +------------------------------------------------------------------------------- +Process can be configured on command line + test lists + Specify one test case exclusion using exclude: +------------------------------------------------------------------------------- +TestMain.cpp:<line number> +............................................................................... + +TestMain.cpp:<line number>: +PASSED: + CHECK_NOTHROW( parseIntoConfig( argv, config ) ) + +TestMain.cpp:<line number>: +PASSED: + REQUIRE( cfg.testSpec().matches( fakeTestCase( "test1" ) ) == false ) +with expansion: + false == false + +TestMain.cpp:<line number>: +PASSED: + REQUIRE( cfg.testSpec().matches( fakeTestCase( "alwaysIncluded" ) ) ) +with expansion: + true + +------------------------------------------------------------------------------- +Process can be configured on command line + test lists + Specify one test case exclusion using ~ +------------------------------------------------------------------------------- +TestMain.cpp:<line number> +............................................................................... + +TestMain.cpp:<line number>: +PASSED: + CHECK_NOTHROW( parseIntoConfig( argv, config ) ) + +TestMain.cpp:<line number>: +PASSED: + REQUIRE( cfg.testSpec().matches( fakeTestCase( "test1" ) ) == false ) +with expansion: + false == false + +TestMain.cpp:<line number>: +PASSED: + REQUIRE( cfg.testSpec().matches( fakeTestCase( "alwaysIncluded" ) ) ) +with expansion: + true + +------------------------------------------------------------------------------- +Process can be configured on command line + reporter + -r/console +------------------------------------------------------------------------------- +TestMain.cpp:<line number> +............................................................................... + +TestMain.cpp:<line number>: +PASSED: + CHECK_NOTHROW( parseIntoConfig( argv, config ) ) + +TestMain.cpp:<line number>: +PASSED: + REQUIRE( config.reporterNames[0] == "console" ) +with expansion: + "console" == "console" + +------------------------------------------------------------------------------- +Process can be configured on command line + reporter + -r/xml +------------------------------------------------------------------------------- +TestMain.cpp:<line number> +............................................................................... + +TestMain.cpp:<line number>: +PASSED: + CHECK_NOTHROW( parseIntoConfig( argv, config ) ) + +TestMain.cpp:<line number>: +PASSED: + REQUIRE( config.reporterNames[0] == "xml" ) +with expansion: + "xml" == "xml" + +------------------------------------------------------------------------------- +Process can be configured on command line + reporter + -r xml and junit +------------------------------------------------------------------------------- +TestMain.cpp:<line number> +............................................................................... + +TestMain.cpp:<line number>: +PASSED: + CHECK_NOTHROW( parseIntoConfig( argv, config ) ) + +TestMain.cpp:<line number>: +PASSED: + REQUIRE( config.reporterNames.size() == 2 ) +with expansion: + 2 == 2 + +TestMain.cpp:<line number>: +PASSED: + REQUIRE( config.reporterNames[0] == "xml" ) +with expansion: + "xml" == "xml" + +TestMain.cpp:<line number>: +PASSED: + REQUIRE( config.reporterNames[1] == "junit" ) +with expansion: + "junit" == "junit" + +------------------------------------------------------------------------------- +Process can be configured on command line + reporter + --reporter/junit +------------------------------------------------------------------------------- +TestMain.cpp:<line number> +............................................................................... + +TestMain.cpp:<line number>: +PASSED: + CHECK_NOTHROW( parseIntoConfig( argv, config ) ) + +TestMain.cpp:<line number>: +PASSED: + REQUIRE( config.reporterNames[0] == "junit" ) +with expansion: + "junit" == "junit" + +------------------------------------------------------------------------------- +Process can be configured on command line + debugger + -b +------------------------------------------------------------------------------- +TestMain.cpp:<line number> +............................................................................... + +TestMain.cpp:<line number>: +PASSED: + CHECK_NOTHROW( parseIntoConfig( argv, config ) ) + +TestMain.cpp:<line number>: +PASSED: + REQUIRE( config.shouldDebugBreak == true ) +with expansion: + true == true + +------------------------------------------------------------------------------- +Process can be configured on command line + debugger + --break +------------------------------------------------------------------------------- +TestMain.cpp:<line number> +............................................................................... + +TestMain.cpp:<line number>: +PASSED: + CHECK_NOTHROW( parseIntoConfig( argv, config ) ) + +TestMain.cpp:<line number>: +PASSED: + REQUIRE( config.shouldDebugBreak ) +with expansion: + true + +------------------------------------------------------------------------------- +Process can be configured on command line + abort + -a aborts after first failure +------------------------------------------------------------------------------- +TestMain.cpp:<line number> +............................................................................... + +TestMain.cpp:<line number>: +PASSED: + CHECK_NOTHROW( parseIntoConfig( argv, config ) ) + +TestMain.cpp:<line number>: +PASSED: + REQUIRE( config.abortAfter == 1 ) +with expansion: + 1 == 1 + +------------------------------------------------------------------------------- +Process can be configured on command line + abort + -x 2 aborts after two failures +------------------------------------------------------------------------------- +TestMain.cpp:<line number> +............................................................................... + +TestMain.cpp:<line number>: +PASSED: + CHECK_NOTHROW( parseIntoConfig( argv, config ) ) + +TestMain.cpp:<line number>: +PASSED: + REQUIRE( config.abortAfter == 2 ) +with expansion: + 2 == 2 + +------------------------------------------------------------------------------- +Process can be configured on command line + abort + -x must be greater than zero +------------------------------------------------------------------------------- +TestMain.cpp:<line number> +............................................................................... + +TestMain.cpp:<line number>: +PASSED: + REQUIRE_THAT( parseIntoConfigAndReturnError( argv, config ), Contains( "greater than zero" ) ) +with expansion: + "Value after -x or --abortAfter must be greater than zero + - while parsing: (-x, --abortx <no. failures>)" contains: "greater than zero" + +------------------------------------------------------------------------------- +Process can be configured on command line + abort + -x must be numeric +------------------------------------------------------------------------------- +TestMain.cpp:<line number> +............................................................................... + +TestMain.cpp:<line number>: +PASSED: + REQUIRE_THAT( parseIntoConfigAndReturnError( argv, config ), Contains( "-x" ) ) +with expansion: + "Unable to convert oops to destination type + - while parsing: (-x, --abortx <no. failures>)" contains: "-x" + +------------------------------------------------------------------------------- +Process can be configured on command line + nothrow + -e +------------------------------------------------------------------------------- +TestMain.cpp:<line number> +............................................................................... + +TestMain.cpp:<line number>: +PASSED: + CHECK_NOTHROW( parseIntoConfig( argv, config ) ) + +TestMain.cpp:<line number>: +PASSED: + REQUIRE( config.noThrow == true ) +with expansion: + true == true + +------------------------------------------------------------------------------- +Process can be configured on command line + nothrow + --nothrow +------------------------------------------------------------------------------- +TestMain.cpp:<line number> +............................................................................... + +TestMain.cpp:<line number>: +PASSED: + CHECK_NOTHROW( parseIntoConfig( argv, config ) ) + +TestMain.cpp:<line number>: +PASSED: + REQUIRE( config.noThrow == true ) +with expansion: + true == true + +------------------------------------------------------------------------------- +Process can be configured on command line + output filename + -o filename +------------------------------------------------------------------------------- +TestMain.cpp:<line number> +............................................................................... + +TestMain.cpp:<line number>: +PASSED: + CHECK_NOTHROW( parseIntoConfig( argv, config ) ) + +TestMain.cpp:<line number>: +PASSED: + REQUIRE( config.outputFilename == "filename.ext" ) +with expansion: + "filename.ext" == "filename.ext" + +------------------------------------------------------------------------------- +Process can be configured on command line + output filename + --out +------------------------------------------------------------------------------- +TestMain.cpp:<line number> +............................................................................... + +TestMain.cpp:<line number>: +PASSED: + CHECK_NOTHROW( parseIntoConfig( argv, config ) ) + +TestMain.cpp:<line number>: +PASSED: + REQUIRE( config.outputFilename == "filename.ext" ) +with expansion: + "filename.ext" == "filename.ext" + +------------------------------------------------------------------------------- +Process can be configured on command line + combinations + Single character flags can be combined +------------------------------------------------------------------------------- +TestMain.cpp:<line number> +............................................................................... + +TestMain.cpp:<line number>: +PASSED: + CHECK_NOTHROW( parseIntoConfig( argv, config ) ) + +TestMain.cpp:<line number>: +PASSED: + CHECK( config.abortAfter == 1 ) +with expansion: + 1 == 1 + +TestMain.cpp:<line number>: +PASSED: + CHECK( config.shouldDebugBreak ) +with expansion: + true + +TestMain.cpp:<line number>: +PASSED: + CHECK( config.noThrow == true ) +with expansion: + true == true + +------------------------------------------------------------------------------- +Process can be configured on command line + use-colour + without option +------------------------------------------------------------------------------- +TestMain.cpp:<line number> +............................................................................... + +TestMain.cpp:<line number>: +PASSED: + CHECK_NOTHROW( parseIntoConfig( argv, config ) ) + +TestMain.cpp:<line number>: +PASSED: + REQUIRE( config.useColour == UseColour::Auto ) +with expansion: + 0 == 0 + +------------------------------------------------------------------------------- +Process can be configured on command line + use-colour + auto +------------------------------------------------------------------------------- +TestMain.cpp:<line number> +............................................................................... + +TestMain.cpp:<line number>: +PASSED: + CHECK_NOTHROW( parseIntoConfig( argv, config ) ) + +TestMain.cpp:<line number>: +PASSED: + REQUIRE( config.useColour == UseColour::Auto ) +with expansion: + 0 == 0 + +------------------------------------------------------------------------------- +Process can be configured on command line + use-colour + yes +------------------------------------------------------------------------------- +TestMain.cpp:<line number> +............................................................................... + +TestMain.cpp:<line number>: +PASSED: + CHECK_NOTHROW( parseIntoConfig( argv, config ) ) + +TestMain.cpp:<line number>: +PASSED: + REQUIRE( config.useColour == UseColour::Yes ) +with expansion: + 1 == 1 + +------------------------------------------------------------------------------- +Process can be configured on command line + use-colour + no +------------------------------------------------------------------------------- +TestMain.cpp:<line number> +............................................................................... + +TestMain.cpp:<line number>: +PASSED: + CHECK_NOTHROW( parseIntoConfig( argv, config ) ) + +TestMain.cpp:<line number>: +PASSED: + REQUIRE( config.useColour == UseColour::No ) +with expansion: + 2 == 2 + +------------------------------------------------------------------------------- +Process can be configured on command line + use-colour + error +------------------------------------------------------------------------------- +TestMain.cpp:<line number> +............................................................................... + +TestMain.cpp:<line number>: +PASSED: + REQUIRE_THROWS_WITH( parseIntoConfig( argv, config ), Contains( "colour mode must be one of" ) ) + +------------------------------------------------------------------------------- +Long strings can be wrapped + plain string + No wrapping +------------------------------------------------------------------------------- +TestMain.cpp:<line number> +............................................................................... + +TestMain.cpp:<line number>: +PASSED: + CHECK( Text( testString, TextAttributes().setWidth( 80 ) ).toString() == testString ) +with expansion: + "one two three four" + == + "one two three four" + +TestMain.cpp:<line number>: +PASSED: + CHECK( Text( testString, TextAttributes().setWidth( 18 ) ).toString() == testString ) +with expansion: + "one two three four" + == + "one two three four" + +------------------------------------------------------------------------------- +Long strings can be wrapped + plain string + Wrapped once +------------------------------------------------------------------------------- +TestMain.cpp:<line number> +............................................................................... + +TestMain.cpp:<line number>: +PASSED: + CHECK( Text( testString, TextAttributes().setWidth( 17 ) ).toString() == "one two three\nfour" ) +with expansion: + "one two three + four" + == + "one two three + four" + +TestMain.cpp:<line number>: +PASSED: + CHECK( Text( testString, TextAttributes().setWidth( 16 ) ).toString() == "one two three\nfour" ) +with expansion: + "one two three + four" + == + "one two three + four" + +TestMain.cpp:<line number>: +PASSED: + CHECK( Text( testString, TextAttributes().setWidth( 14 ) ).toString() == "one two three\nfour" ) +with expansion: + "one two three + four" + == + "one two three + four" + +TestMain.cpp:<line number>: +PASSED: + CHECK( Text( testString, TextAttributes().setWidth( 13 ) ).toString() == "one two three\nfour" ) +with expansion: + "one two three + four" + == + "one two three + four" + +TestMain.cpp:<line number>: +PASSED: + CHECK( Text( testString, TextAttributes().setWidth( 12 ) ).toString() == "one two\nthree four" ) +with expansion: + "one two + three four" + == + "one two + three four" + +------------------------------------------------------------------------------- +Long strings can be wrapped + plain string + Wrapped twice +------------------------------------------------------------------------------- +TestMain.cpp:<line number> +............................................................................... + +TestMain.cpp:<line number>: +PASSED: + CHECK( Text( testString, TextAttributes().setWidth( 9 ) ).toString() == "one two\nthree\nfour" ) +with expansion: + "one two + three + four" + == + "one two + three + four" + +TestMain.cpp:<line number>: +PASSED: + CHECK( Text( testString, TextAttributes().setWidth( 8 ) ).toString() == "one two\nthree\nfour" ) +with expansion: + "one two + three + four" + == + "one two + three + four" + +TestMain.cpp:<line number>: +PASSED: + CHECK( Text( testString, TextAttributes().setWidth( 7 ) ).toString() == "one two\nthree\nfour" ) +with expansion: + "one two + three + four" + == + "one two + three + four" + +------------------------------------------------------------------------------- +Long strings can be wrapped + plain string + Wrapped three times +------------------------------------------------------------------------------- +TestMain.cpp:<line number> +............................................................................... + +TestMain.cpp:<line number>: +PASSED: + CHECK( Text( testString, TextAttributes().setWidth( 6 ) ).toString() == "one\ntwo\nthree\nfour" ) +with expansion: + "one + two + three + four" + == + "one + two + three + four" + +TestMain.cpp:<line number>: +PASSED: + CHECK( Text( testString, TextAttributes().setWidth( 5 ) ).toString() == "one\ntwo\nthree\nfour" ) +with expansion: + "one + two + three + four" + == + "one + two + three + four" + +------------------------------------------------------------------------------- +Long strings can be wrapped + plain string + Short wrap +------------------------------------------------------------------------------- +TestMain.cpp:<line number> +............................................................................... + +TestMain.cpp:<line number>: +PASSED: + CHECK( Text( "abcdef", TextAttributes().setWidth( 4 ) ).toString() == "abc-\ndef" ) +with expansion: + "abc- + def" + == + "abc- + def" + +TestMain.cpp:<line number>: +PASSED: + CHECK( Text( "abcdefg", TextAttributes().setWidth( 4 ) ).toString() == "abc-\ndefg" ) +with expansion: + "abc- + defg" + == + "abc- + defg" + +TestMain.cpp:<line number>: +PASSED: + CHECK( Text( "abcdefgh", TextAttributes().setWidth( 4 ) ).toString() == "abc-\ndef-\ngh" ) +with expansion: + "abc- + def- + gh" + == + "abc- + def- + gh" + +TestMain.cpp:<line number>: +PASSED: + CHECK( Text( testString, TextAttributes().setWidth( 4 ) ).toString() == "one\ntwo\nthr-\nee\nfour" ) +with expansion: + "one + two + thr- + ee + four" + == + "one + two + thr- + ee + four" + +TestMain.cpp:<line number>: +PASSED: + CHECK( Text( testString, TextAttributes().setWidth( 3 ) ).toString() == "one\ntwo\nth-\nree\nfo-\nur" ) +with expansion: + "one + two + th- + ree + fo- + ur" + == + "one + two + th- + ree + fo- + ur" + +------------------------------------------------------------------------------- +Long strings can be wrapped + plain string + As container +------------------------------------------------------------------------------- +TestMain.cpp:<line number> +............................................................................... + +TestMain.cpp:<line number>: +PASSED: + REQUIRE( text.size() == 4 ) +with expansion: + 4 == 4 + +TestMain.cpp:<line number>: +PASSED: + CHECK( text[0] == "one" ) +with expansion: + "one" == "one" + +TestMain.cpp:<line number>: +PASSED: + CHECK( text[1] == "two" ) +with expansion: + "two" == "two" + +TestMain.cpp:<line number>: +PASSED: + CHECK( text[2] == "three" ) +with expansion: + "three" == "three" + +TestMain.cpp:<line number>: +PASSED: + CHECK( text[3] == "four" ) +with expansion: + "four" == "four" + +------------------------------------------------------------------------------- +Long strings can be wrapped + plain string + Indent first line differently +------------------------------------------------------------------------------- +TestMain.cpp:<line number> +............................................................................... + +TestMain.cpp:<line number>: +PASSED: + CHECK( text.toString() == " one two\n three\n four" ) +with expansion: + " one two + three + four" + == + " one two + three + four" + +------------------------------------------------------------------------------- +Long strings can be wrapped + With newlines + No wrapping +------------------------------------------------------------------------------- +TestMain.cpp:<line number> +............................................................................... + +TestMain.cpp:<line number>: +PASSED: + CHECK( Text( testString, TextAttributes().setWidth( 80 ) ).toString() == testString ) +with expansion: + "one two + three four" + == + "one two + three four" + +TestMain.cpp:<line number>: +PASSED: + CHECK( Text( testString, TextAttributes().setWidth( 18 ) ).toString() == testString ) +with expansion: + "one two + three four" + == + "one two + three four" + +TestMain.cpp:<line number>: +PASSED: + CHECK( Text( testString, TextAttributes().setWidth( 10 ) ).toString() == testString ) +with expansion: + "one two + three four" + == + "one two + three four" + +------------------------------------------------------------------------------- +Long strings can be wrapped + With newlines + Trailing newline +------------------------------------------------------------------------------- +TestMain.cpp:<line number> +............................................................................... + +TestMain.cpp:<line number>: +PASSED: + CHECK( Text( "abcdef\n", TextAttributes().setWidth( 10 ) ).toString() == "abcdef\n" ) +with expansion: + "abcdef + " + == + "abcdef + " + +TestMain.cpp:<line number>: +PASSED: + CHECK( Text( "abcdef", TextAttributes().setWidth( 6 ) ).toString() == "abcdef" ) +with expansion: + "abcdef" == "abcdef" + +TestMain.cpp:<line number>: +PASSED: + CHECK( Text( "abcdef\n", TextAttributes().setWidth( 6 ) ).toString() == "abcdef\n" ) +with expansion: + "abcdef + " + == + "abcdef + " + +------------------------------------------------------------------------------- +Long strings can be wrapped + With newlines + Wrapped once +------------------------------------------------------------------------------- +TestMain.cpp:<line number> +............................................................................... + +TestMain.cpp:<line number>: +PASSED: + CHECK( Text( testString, TextAttributes().setWidth( 9 ) ).toString() == "one two\nthree\nfour" ) +with expansion: + "one two + three + four" + == + "one two + three + four" + +TestMain.cpp:<line number>: +PASSED: + CHECK( Text( testString, TextAttributes().setWidth( 8 ) ).toString() == "one two\nthree\nfour" ) +with expansion: + "one two + three + four" + == + "one two + three + four" + +TestMain.cpp:<line number>: +PASSED: + CHECK( Text( testString, TextAttributes().setWidth( 7 ) ).toString() == "one two\nthree\nfour" ) +with expansion: + "one two + three + four" + == + "one two + three + four" + +------------------------------------------------------------------------------- +Long strings can be wrapped + With newlines + Wrapped twice +------------------------------------------------------------------------------- +TestMain.cpp:<line number> +............................................................................... + +TestMain.cpp:<line number>: +PASSED: + CHECK( Text( testString, TextAttributes().setWidth( 6 ) ).toString() == "one\ntwo\nthree\nfour" ) +with expansion: + "one + two + three + four" + == + "one + two + three + four" + +------------------------------------------------------------------------------- +Long strings can be wrapped + With tabs +------------------------------------------------------------------------------- +TestMain.cpp:<line number> +............................................................................... + +TestMain.cpp:<line number>: +PASSED: + CHECK( Text( testString, TextAttributes().setWidth( 15 ) ).toString() == "one two three\n four\n five\n six" ) +with expansion: + "one two three + four + five + six" + == + "one two three + four + five + six" + +------------------------------------------------------------------------------- +replaceInPlace + replace single char +------------------------------------------------------------------------------- +TestMain.cpp:<line number> +............................................................................... + +TestMain.cpp:<line number>: +PASSED: + CHECK( replaceInPlace( letters, "b", "z" ) ) +with expansion: + true + +TestMain.cpp:<line number>: +PASSED: + CHECK( letters == "azcdefcg" ) +with expansion: + "azcdefcg" == "azcdefcg" + +------------------------------------------------------------------------------- +replaceInPlace + replace two chars +------------------------------------------------------------------------------- +TestMain.cpp:<line number> +............................................................................... + +TestMain.cpp:<line number>: +PASSED: + CHECK( replaceInPlace( letters, "c", "z" ) ) +with expansion: + true + +TestMain.cpp:<line number>: +PASSED: + CHECK( letters == "abzdefzg" ) +with expansion: + "abzdefzg" == "abzdefzg" + +------------------------------------------------------------------------------- +replaceInPlace + replace first char +------------------------------------------------------------------------------- +TestMain.cpp:<line number> +............................................................................... + +TestMain.cpp:<line number>: +PASSED: + CHECK( replaceInPlace( letters, "a", "z" ) ) +with expansion: + true + +TestMain.cpp:<line number>: +PASSED: + CHECK( letters == "zbcdefcg" ) +with expansion: + "zbcdefcg" == "zbcdefcg" + +------------------------------------------------------------------------------- +replaceInPlace + replace last char +------------------------------------------------------------------------------- +TestMain.cpp:<line number> +............................................................................... + +TestMain.cpp:<line number>: +PASSED: + CHECK( replaceInPlace( letters, "g", "z" ) ) +with expansion: + true + +TestMain.cpp:<line number>: +PASSED: + CHECK( letters == "abcdefcz" ) +with expansion: + "abcdefcz" == "abcdefcz" + +------------------------------------------------------------------------------- +replaceInPlace + replace all chars +------------------------------------------------------------------------------- +TestMain.cpp:<line number> +............................................................................... + +TestMain.cpp:<line number>: +PASSED: + CHECK( replaceInPlace( letters, letters, "replaced" ) ) +with expansion: + true + +TestMain.cpp:<line number>: +PASSED: + CHECK( letters == "replaced" ) +with expansion: + "replaced" == "replaced" + +------------------------------------------------------------------------------- +replaceInPlace + replace no chars +------------------------------------------------------------------------------- +TestMain.cpp:<line number> +............................................................................... + +TestMain.cpp:<line number>: +PASSED: + CHECK_FALSE( replaceInPlace( letters, "x", "z" ) ) +with expansion: + !false + +TestMain.cpp:<line number>: +PASSED: + CHECK( letters == letters ) +with expansion: + "abcdefcg" == "abcdefcg" + +------------------------------------------------------------------------------- +replaceInPlace + escape ' +------------------------------------------------------------------------------- +TestMain.cpp:<line number> +............................................................................... + +TestMain.cpp:<line number>: +PASSED: + CHECK( replaceInPlace( s, "'", "|'" ) ) +with expansion: + true + +TestMain.cpp:<line number>: +PASSED: + CHECK( s == "didn|'t" ) +with expansion: + "didn|'t" == "didn|'t" + +hello +hello +------------------------------------------------------------------------------- +Text can be formatted using the Text class +------------------------------------------------------------------------------- +TestMain.cpp:<line number> +............................................................................... + +TestMain.cpp:<line number>: +PASSED: + CHECK( Text( "hi there" ).toString() == "hi there" ) +with expansion: + "hi there" == "hi there" + +TestMain.cpp:<line number>: +PASSED: + CHECK( Text( "hi there", narrow ).toString() == "hi\nthere" ) +with expansion: + "hi + there" + == + "hi + there" + +------------------------------------------------------------------------------- +Long text is truncted +------------------------------------------------------------------------------- +TestMain.cpp:<line number> +............................................................................... + +TestMain.cpp:<line number>: +PASSED: + CHECK_THAT( t.toString(), EndsWith( "... message truncated due to excessive size" ) ) +with expansion: + "***************************************************************************- + ***- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ +... message truncated due to excessive size + +------------------------------------------------------------------------------- +ManuallyRegistered +------------------------------------------------------------------------------- +TestMain.cpp:<line number> +............................................................................... + +TestMain.cpp:<line number>: +PASSED: +with message: + was called + +------------------------------------------------------------------------------- +Parsing a std::pair +------------------------------------------------------------------------------- +TrickyTests.cpp:<line number> +............................................................................... + +TrickyTests.cpp:<line number>: +PASSED: + REQUIRE( (std::pair<int, int>( 1, 2 )) == aNicePair ) +with expansion: + std::pair( 1, 2 ) == std::pair( 1, 2 ) + +------------------------------------------------------------------------------- +Where there is more to the expression after the RHS +------------------------------------------------------------------------------- +TrickyTests.cpp:<line number> +............................................................................... + +TrickyTests.cpp:<line number>: +warning: + Uncomment the code in this test to check that it gives a sensible compiler + error + +------------------------------------------------------------------------------- +Where the LHS is not a simple value +------------------------------------------------------------------------------- +TrickyTests.cpp:<line number> +............................................................................... + +TrickyTests.cpp:<line number>: +warning: + Uncomment the code in this test to check that it gives a sensible compiler + error + +------------------------------------------------------------------------------- +A failing expression with a non streamable type is still captured +------------------------------------------------------------------------------- +TrickyTests.cpp:<line number> +............................................................................... + +TrickyTests.cpp:<line number>: FAILED: + CHECK( &o1 == &o2 ) +with expansion: + 0x<hex digits> == 0x<hex digits> + +TrickyTests.cpp:<line number>: FAILED: + CHECK( o1 == o2 ) +with expansion: + {?} == {?} + +------------------------------------------------------------------------------- +string literals of different sizes can be compared +------------------------------------------------------------------------------- +TrickyTests.cpp:<line number> +............................................................................... + +TrickyTests.cpp:<line number>: FAILED: + REQUIRE( std::string( "first" ) == "second" ) +with expansion: + "first" == "second" + +------------------------------------------------------------------------------- +An expression with side-effects should only be evaluated once +------------------------------------------------------------------------------- +TrickyTests.cpp:<line number> +............................................................................... + +TrickyTests.cpp:<line number>: +PASSED: + REQUIRE( i++ == 7 ) +with expansion: + 7 == 7 + +TrickyTests.cpp:<line number>: +PASSED: + REQUIRE( i++ == 8 ) +with expansion: + 8 == 8 + +------------------------------------------------------------------------------- +Operators at different namespace levels not hijacked by Koenig lookup +------------------------------------------------------------------------------- +TrickyTests.cpp:<line number> +............................................................................... + +TrickyTests.cpp:<line number>: +PASSED: + REQUIRE( 0x<hex digits> == o ) +with expansion: + 3221225472 (0x<hex digits>) == {?} + +------------------------------------------------------------------------------- +Demonstrate that a non-const == is not used +------------------------------------------------------------------------------- +TrickyTests.cpp:<line number> +............................................................................... + +TrickyTests.cpp:<line number>: +PASSED: + REQUIRE( t == 1u ) +with expansion: + {?} == 1 + +------------------------------------------------------------------------------- +Test enum bit values +------------------------------------------------------------------------------- +TrickyTests.cpp:<line number> +............................................................................... + +TrickyTests.cpp:<line number>: +PASSED: + REQUIRE( 0x<hex digits> == bit30and31 ) +with expansion: + 3221225472 (0x<hex digits>) == 3221225472 + +------------------------------------------------------------------------------- +boolean member +------------------------------------------------------------------------------- +TrickyTests.cpp:<line number> +............................................................................... + +TrickyTests.cpp:<line number>: +PASSED: + REQUIRE( obj.prop != nullptr ) +with expansion: + 0x<hex digits> != nullptr + +------------------------------------------------------------------------------- +(unimplemented) static bools can be evaluated + compare to true +------------------------------------------------------------------------------- +TrickyTests.cpp:<line number> +............................................................................... + +TrickyTests.cpp:<line number>: +PASSED: + REQUIRE( is_true<true>::value == true ) +with expansion: + true == true + +TrickyTests.cpp:<line number>: +PASSED: + REQUIRE( true == is_true<true>::value ) +with expansion: + true == true + +------------------------------------------------------------------------------- +(unimplemented) static bools can be evaluated + compare to false +------------------------------------------------------------------------------- +TrickyTests.cpp:<line number> +............................................................................... + +TrickyTests.cpp:<line number>: +PASSED: + REQUIRE( is_true<false>::value == false ) +with expansion: + false == false + +TrickyTests.cpp:<line number>: +PASSED: + REQUIRE( false == is_true<false>::value ) +with expansion: + false == false + +------------------------------------------------------------------------------- +(unimplemented) static bools can be evaluated + negation +------------------------------------------------------------------------------- +TrickyTests.cpp:<line number> +............................................................................... + +TrickyTests.cpp:<line number>: +PASSED: + REQUIRE( !is_true<false>::value ) +with expansion: + true + +------------------------------------------------------------------------------- +(unimplemented) static bools can be evaluated + double negation +------------------------------------------------------------------------------- +TrickyTests.cpp:<line number> +............................................................................... + +TrickyTests.cpp:<line number>: +PASSED: + REQUIRE( !!is_true<true>::value ) +with expansion: + true + +------------------------------------------------------------------------------- +(unimplemented) static bools can be evaluated + direct +------------------------------------------------------------------------------- +TrickyTests.cpp:<line number> +............................................................................... + +TrickyTests.cpp:<line number>: +PASSED: + REQUIRE( is_true<true>::value ) +with expansion: + true + +TrickyTests.cpp:<line number>: +PASSED: + REQUIRE_FALSE( is_true<false>::value ) +with expansion: + !false + +------------------------------------------------------------------------------- +Objects that evaluated in boolean contexts can be checked +------------------------------------------------------------------------------- +TrickyTests.cpp:<line number> +............................................................................... + +TrickyTests.cpp:<line number>: +PASSED: + CHECK( True ) +with expansion: + true + +TrickyTests.cpp:<line number>: +PASSED: + CHECK( !False ) +with expansion: + true + +TrickyTests.cpp:<line number>: +PASSED: + CHECK_FALSE( False ) +with expansion: + !false + +------------------------------------------------------------------------------- +Assertions then sections +------------------------------------------------------------------------------- +TrickyTests.cpp:<line number> +............................................................................... + +TrickyTests.cpp:<line number>: +PASSED: + REQUIRE( Catch::alwaysTrue() ) +with expansion: + true + +------------------------------------------------------------------------------- +Assertions then sections + A section +------------------------------------------------------------------------------- +TrickyTests.cpp:<line number> +............................................................................... + +TrickyTests.cpp:<line number>: +PASSED: + REQUIRE( Catch::alwaysTrue() ) +with expansion: + true + +------------------------------------------------------------------------------- +Assertions then sections + A section + Another section +------------------------------------------------------------------------------- +TrickyTests.cpp:<line number> +............................................................................... + +TrickyTests.cpp:<line number>: +PASSED: + REQUIRE( Catch::alwaysTrue() ) +with expansion: + true + +------------------------------------------------------------------------------- +Assertions then sections +------------------------------------------------------------------------------- +TrickyTests.cpp:<line number> +............................................................................... + +TrickyTests.cpp:<line number>: +PASSED: + REQUIRE( Catch::alwaysTrue() ) +with expansion: + true + +------------------------------------------------------------------------------- +Assertions then sections + A section +------------------------------------------------------------------------------- +TrickyTests.cpp:<line number> +............................................................................... + +TrickyTests.cpp:<line number>: +PASSED: + REQUIRE( Catch::alwaysTrue() ) +with expansion: + true + +------------------------------------------------------------------------------- +Assertions then sections + A section + Another other section +------------------------------------------------------------------------------- +TrickyTests.cpp:<line number> +............................................................................... + +TrickyTests.cpp:<line number>: +PASSED: + REQUIRE( Catch::alwaysTrue() ) +with expansion: + true + +------------------------------------------------------------------------------- +non streamable - with conv. op +------------------------------------------------------------------------------- +TrickyTests.cpp:<line number> +............................................................................... + +TrickyTests.cpp:<line number>: +PASSED: + REQUIRE( s == "7" ) +with expansion: + "7" == "7" + +------------------------------------------------------------------------------- +Comparing function pointers +------------------------------------------------------------------------------- +TrickyTests.cpp:<line number> +............................................................................... + +TrickyTests.cpp:<line number>: +PASSED: + REQUIRE( a ) +with expansion: + true + +TrickyTests.cpp:<line number>: +PASSED: + REQUIRE( a == &foo ) +with expansion: + 0x<hex digits> == 0x<hex digits> + +------------------------------------------------------------------------------- +Comparing member function pointers +------------------------------------------------------------------------------- +TrickyTests.cpp:<line number> +............................................................................... + +TrickyTests.cpp:<line number>: +PASSED: + CHECK( m == &S::f ) +with expansion: + 0x<hex digits> + == + 0x<hex digits> + +------------------------------------------------------------------------------- +pointer to class +------------------------------------------------------------------------------- +TrickyTests.cpp:<line number> +............................................................................... + +TrickyTests.cpp:<line number>: +PASSED: + REQUIRE( p == 0 ) +with expansion: + NULL == 0 + +------------------------------------------------------------------------------- +null_ptr +------------------------------------------------------------------------------- +TrickyTests.cpp:<line number> +............................................................................... + +TrickyTests.cpp:<line number>: +PASSED: + REQUIRE( ptr.get() == nullptr ) +with expansion: + NULL == nullptr + +------------------------------------------------------------------------------- +X/level/0/a +------------------------------------------------------------------------------- +TrickyTests.cpp:<line number> +............................................................................... + +TrickyTests.cpp:<line number>: +PASSED: + +------------------------------------------------------------------------------- +X/level/0/b +------------------------------------------------------------------------------- +TrickyTests.cpp:<line number> +............................................................................... + +TrickyTests.cpp:<line number>: +PASSED: + +------------------------------------------------------------------------------- +X/level/1/a +------------------------------------------------------------------------------- +TrickyTests.cpp:<line number> +............................................................................... + +TrickyTests.cpp:<line number>: +PASSED: + +------------------------------------------------------------------------------- +X/level/1/b +------------------------------------------------------------------------------- +TrickyTests.cpp:<line number> +............................................................................... + +TrickyTests.cpp:<line number>: +PASSED: + +------------------------------------------------------------------------------- +toString( has_toString ) +------------------------------------------------------------------------------- +ToStringWhich.cpp:<line number> +............................................................................... + +ToStringWhich.cpp:<line number>: +PASSED: + REQUIRE( Catch::toString( item ) == "toString( has_toString )" ) +with expansion: + "toString( has_toString )" + == + "toString( has_toString )" + +------------------------------------------------------------------------------- +toString( has_maker ) +------------------------------------------------------------------------------- +ToStringWhich.cpp:<line number> +............................................................................... + +ToStringWhich.cpp:<line number>: +PASSED: + REQUIRE( Catch::toString( item ) == "StringMaker<has_maker>" ) +with expansion: + "StringMaker<has_maker>" + == + "StringMaker<has_maker>" + +------------------------------------------------------------------------------- +toString( has_maker_and_toString ) +------------------------------------------------------------------------------- +ToStringWhich.cpp:<line number> +............................................................................... + +ToStringWhich.cpp:<line number>: +PASSED: + REQUIRE( Catch::toString( item ) == "toString( has_maker_and_toString )" ) +with expansion: + "toString( has_maker_and_toString )" + == + "toString( has_maker_and_toString )" + +------------------------------------------------------------------------------- +toString( vectors<has_toString ) +------------------------------------------------------------------------------- +ToStringWhich.cpp:<line number> +............................................................................... + +ToStringWhich.cpp:<line number>: +PASSED: + REQUIRE( Catch::toString( v ) == "{ {?} }" ) +with expansion: + "{ {?} }" == "{ {?} }" + +------------------------------------------------------------------------------- +toString( vectors<has_maker ) +------------------------------------------------------------------------------- +ToStringWhich.cpp:<line number> +............................................................................... + +ToStringWhich.cpp:<line number>: +PASSED: + REQUIRE( Catch::toString( v ) == "{ StringMaker<has_maker> }" ) +with expansion: + "{ StringMaker<has_maker> }" + == + "{ StringMaker<has_maker> }" + +------------------------------------------------------------------------------- +toString( vectors<has_maker_and_toString ) +------------------------------------------------------------------------------- +ToStringWhich.cpp:<line number> +............................................................................... + +ToStringWhich.cpp:<line number>: +PASSED: + REQUIRE( Catch::toString( v ) == "{ StringMaker<has_maker_and_toString> }" ) +with expansion: + "{ StringMaker<has_maker_and_toString> }" + == + "{ StringMaker<has_maker_and_toString> }" + +------------------------------------------------------------------------------- +Tracker +------------------------------------------------------------------------------- +PartTrackerTests.cpp:<line number> +............................................................................... + +PartTrackerTests.cpp:<line number>: +PASSED: + REQUIRE( testCase.isOpen() ) +with expansion: + true + +PartTrackerTests.cpp:<line number>: +PASSED: + REQUIRE( s1.isOpen() ) +with expansion: + true + +------------------------------------------------------------------------------- +Tracker + successfully close one section +------------------------------------------------------------------------------- +PartTrackerTests.cpp:<line number> +............................................................................... + +PartTrackerTests.cpp:<line number>: +PASSED: + REQUIRE( s1.isSuccessfullyCompleted() ) +with expansion: + true + +PartTrackerTests.cpp:<line number>: +PASSED: + REQUIRE( testCase.isComplete() == false ) +with expansion: + false == false + +PartTrackerTests.cpp:<line number>: +PASSED: + REQUIRE( ctx.completedCycle() ) +with expansion: + true + +PartTrackerTests.cpp:<line number>: +PASSED: + REQUIRE( testCase.isSuccessfullyCompleted() ) +with expansion: + true + +------------------------------------------------------------------------------- +Tracker +------------------------------------------------------------------------------- +PartTrackerTests.cpp:<line number> +............................................................................... + +PartTrackerTests.cpp:<line number>: +PASSED: + REQUIRE( testCase.isOpen() ) +with expansion: + true + +PartTrackerTests.cpp:<line number>: +PASSED: + REQUIRE( s1.isOpen() ) +with expansion: + true + +------------------------------------------------------------------------------- +Tracker + fail one section +------------------------------------------------------------------------------- +PartTrackerTests.cpp:<line number> +............................................................................... + +PartTrackerTests.cpp:<line number>: +PASSED: + REQUIRE( s1.isComplete() ) +with expansion: + true + +PartTrackerTests.cpp:<line number>: +PASSED: + REQUIRE( s1.isSuccessfullyCompleted() == false ) +with expansion: + false == false + +PartTrackerTests.cpp:<line number>: +PASSED: + REQUIRE( testCase.isComplete() == false ) +with expansion: + false == false + +PartTrackerTests.cpp:<line number>: +PASSED: + REQUIRE( ctx.completedCycle() ) +with expansion: + true + +PartTrackerTests.cpp:<line number>: +PASSED: + REQUIRE( testCase.isSuccessfullyCompleted() == false ) +with expansion: + false == false + +------------------------------------------------------------------------------- +Tracker + fail one section + re-enter after failed section +------------------------------------------------------------------------------- +PartTrackerTests.cpp:<line number> +............................................................................... + +PartTrackerTests.cpp:<line number>: +PASSED: + REQUIRE( testCase2.isOpen() ) +with expansion: + true + +PartTrackerTests.cpp:<line number>: +PASSED: + REQUIRE( s1b.isOpen() == false ) +with expansion: + false == false + +PartTrackerTests.cpp:<line number>: +PASSED: + REQUIRE( ctx.completedCycle() ) +with expansion: + true + +PartTrackerTests.cpp:<line number>: +PASSED: + REQUIRE( testCase.isComplete() ) +with expansion: + true + +PartTrackerTests.cpp:<line number>: +PASSED: + REQUIRE( testCase.isSuccessfullyCompleted() ) +with expansion: + true + +------------------------------------------------------------------------------- +Tracker +------------------------------------------------------------------------------- +PartTrackerTests.cpp:<line number> +............................................................................... + +PartTrackerTests.cpp:<line number>: +PASSED: + REQUIRE( testCase.isOpen() ) +with expansion: + true + +PartTrackerTests.cpp:<line number>: +PASSED: + REQUIRE( s1.isOpen() ) +with expansion: + true + +------------------------------------------------------------------------------- +Tracker + fail one section +------------------------------------------------------------------------------- +PartTrackerTests.cpp:<line number> +............................................................................... + +PartTrackerTests.cpp:<line number>: +PASSED: + REQUIRE( s1.isComplete() ) +with expansion: + true + +PartTrackerTests.cpp:<line number>: +PASSED: + REQUIRE( s1.isSuccessfullyCompleted() == false ) +with expansion: + false == false + +PartTrackerTests.cpp:<line number>: +PASSED: + REQUIRE( testCase.isComplete() == false ) +with expansion: + false == false + +PartTrackerTests.cpp:<line number>: +PASSED: + REQUIRE( ctx.completedCycle() ) +with expansion: + true + +PartTrackerTests.cpp:<line number>: +PASSED: + REQUIRE( testCase.isSuccessfullyCompleted() == false ) +with expansion: + false == false + +------------------------------------------------------------------------------- +Tracker + fail one section + re-enter after failed section and find next section +------------------------------------------------------------------------------- +PartTrackerTests.cpp:<line number> +............................................................................... + +PartTrackerTests.cpp:<line number>: +PASSED: + REQUIRE( testCase2.isOpen() ) +with expansion: + true + +PartTrackerTests.cpp:<line number>: +PASSED: + REQUIRE( s1b.isOpen() == false ) +with expansion: + false == false + +PartTrackerTests.cpp:<line number>: +PASSED: + REQUIRE( s2.isOpen() ) +with expansion: + true + +PartTrackerTests.cpp:<line number>: +PASSED: + REQUIRE( ctx.completedCycle() ) +with expansion: + true + +PartTrackerTests.cpp:<line number>: +PASSED: + REQUIRE( testCase.isComplete() ) +with expansion: + true + +PartTrackerTests.cpp:<line number>: +PASSED: + REQUIRE( testCase.isSuccessfullyCompleted() ) +with expansion: + true + +------------------------------------------------------------------------------- +Tracker +------------------------------------------------------------------------------- +PartTrackerTests.cpp:<line number> +............................................................................... + +PartTrackerTests.cpp:<line number>: +PASSED: + REQUIRE( testCase.isOpen() ) +with expansion: + true + +PartTrackerTests.cpp:<line number>: +PASSED: + REQUIRE( s1.isOpen() ) +with expansion: + true + +------------------------------------------------------------------------------- +Tracker + successfully close one section, then find another +------------------------------------------------------------------------------- +PartTrackerTests.cpp:<line number> +............................................................................... + +PartTrackerTests.cpp:<line number>: +PASSED: + REQUIRE( s2.isOpen() == false ) +with expansion: + false == false + +PartTrackerTests.cpp:<line number>: +PASSED: + REQUIRE( testCase.isComplete() == false ) +with expansion: + false == false + +------------------------------------------------------------------------------- +Tracker + successfully close one section, then find another + Re-enter - skips S1 and enters S2 +------------------------------------------------------------------------------- +PartTrackerTests.cpp:<line number> +............................................................................... + +PartTrackerTests.cpp:<line number>: +PASSED: + REQUIRE( testCase2.isOpen() ) +with expansion: + true + +PartTrackerTests.cpp:<line number>: +PASSED: + REQUIRE( s1b.isOpen() == false ) +with expansion: + false == false + +PartTrackerTests.cpp:<line number>: +PASSED: + REQUIRE( s2b.isOpen() ) +with expansion: + true + +PartTrackerTests.cpp:<line number>: +PASSED: + REQUIRE( ctx.completedCycle() == false ) +with expansion: + false == false + +------------------------------------------------------------------------------- +Tracker + successfully close one section, then find another + Re-enter - skips S1 and enters S2 + Successfully close S2 +------------------------------------------------------------------------------- +PartTrackerTests.cpp:<line number> +............................................................................... + +PartTrackerTests.cpp:<line number>: +PASSED: + REQUIRE( ctx.completedCycle() ) +with expansion: + true + +PartTrackerTests.cpp:<line number>: +PASSED: + REQUIRE( s2b.isSuccessfullyCompleted() ) +with expansion: + true + +PartTrackerTests.cpp:<line number>: +PASSED: + REQUIRE( testCase2.isComplete() == false ) +with expansion: + false == false + +PartTrackerTests.cpp:<line number>: +PASSED: + REQUIRE( testCase2.isSuccessfullyCompleted() ) +with expansion: + true + +------------------------------------------------------------------------------- +Tracker +------------------------------------------------------------------------------- +PartTrackerTests.cpp:<line number> +............................................................................... + +PartTrackerTests.cpp:<line number>: +PASSED: + REQUIRE( testCase.isOpen() ) +with expansion: + true + +PartTrackerTests.cpp:<line number>: +PASSED: + REQUIRE( s1.isOpen() ) +with expansion: + true + +------------------------------------------------------------------------------- +Tracker + successfully close one section, then find another +------------------------------------------------------------------------------- +PartTrackerTests.cpp:<line number> +............................................................................... + +PartTrackerTests.cpp:<line number>: +PASSED: + REQUIRE( s2.isOpen() == false ) +with expansion: + false == false + +PartTrackerTests.cpp:<line number>: +PASSED: + REQUIRE( testCase.isComplete() == false ) +with expansion: + false == false + +------------------------------------------------------------------------------- +Tracker + successfully close one section, then find another + Re-enter - skips S1 and enters S2 +------------------------------------------------------------------------------- +PartTrackerTests.cpp:<line number> +............................................................................... + +PartTrackerTests.cpp:<line number>: +PASSED: + REQUIRE( testCase2.isOpen() ) +with expansion: + true + +PartTrackerTests.cpp:<line number>: +PASSED: + REQUIRE( s1b.isOpen() == false ) +with expansion: + false == false + +PartTrackerTests.cpp:<line number>: +PASSED: + REQUIRE( s2b.isOpen() ) +with expansion: + true + +PartTrackerTests.cpp:<line number>: +PASSED: + REQUIRE( ctx.completedCycle() == false ) +with expansion: + false == false + +------------------------------------------------------------------------------- +Tracker + successfully close one section, then find another + Re-enter - skips S1 and enters S2 + fail S2 +------------------------------------------------------------------------------- +PartTrackerTests.cpp:<line number> +............................................................................... + +PartTrackerTests.cpp:<line number>: +PASSED: + REQUIRE( ctx.completedCycle() ) +with expansion: + true + +PartTrackerTests.cpp:<line number>: +PASSED: + REQUIRE( s2b.isComplete() ) +with expansion: + true + +PartTrackerTests.cpp:<line number>: +PASSED: + REQUIRE( s2b.isSuccessfullyCompleted() == false ) +with expansion: + false == false + +PartTrackerTests.cpp:<line number>: +PASSED: + REQUIRE( testCase2.isSuccessfullyCompleted() == false ) +with expansion: + false == false + +PartTrackerTests.cpp:<line number>: +PASSED: + REQUIRE( testCase3.isOpen() ) +with expansion: + true + +PartTrackerTests.cpp:<line number>: +PASSED: + REQUIRE( s1c.isOpen() == false ) +with expansion: + false == false + +PartTrackerTests.cpp:<line number>: +PASSED: + REQUIRE( s2c.isOpen() == false ) +with expansion: + false == false + +PartTrackerTests.cpp:<line number>: +PASSED: + REQUIRE( testCase3.isSuccessfullyCompleted() ) +with expansion: + true + +------------------------------------------------------------------------------- +Tracker +------------------------------------------------------------------------------- +PartTrackerTests.cpp:<line number> +............................................................................... + +PartTrackerTests.cpp:<line number>: +PASSED: + REQUIRE( testCase.isOpen() ) +with expansion: + true + +PartTrackerTests.cpp:<line number>: +PASSED: + REQUIRE( s1.isOpen() ) +with expansion: + true + +------------------------------------------------------------------------------- +Tracker + open a nested section +------------------------------------------------------------------------------- +PartTrackerTests.cpp:<line number> +............................................................................... + +PartTrackerTests.cpp:<line number>: +PASSED: + REQUIRE( s2.isOpen() ) +with expansion: + true + +PartTrackerTests.cpp:<line number>: +PASSED: + REQUIRE( s2.isComplete() ) +with expansion: + true + +PartTrackerTests.cpp:<line number>: +PASSED: + REQUIRE( s1.isComplete() == false ) +with expansion: + false == false + +PartTrackerTests.cpp:<line number>: +PASSED: + REQUIRE( s1.isComplete() ) +with expansion: + true + +PartTrackerTests.cpp:<line number>: +PASSED: + REQUIRE( testCase.isComplete() == false ) +with expansion: + false == false + +PartTrackerTests.cpp:<line number>: +PASSED: + REQUIRE( testCase.isComplete() ) +with expansion: + true + +------------------------------------------------------------------------------- +Tracker +------------------------------------------------------------------------------- +PartTrackerTests.cpp:<line number> +............................................................................... + +PartTrackerTests.cpp:<line number>: +PASSED: + REQUIRE( testCase.isOpen() ) +with expansion: + true + +PartTrackerTests.cpp:<line number>: +PASSED: + REQUIRE( s1.isOpen() ) +with expansion: + true + +------------------------------------------------------------------------------- +Tracker + start a generator +------------------------------------------------------------------------------- +PartTrackerTests.cpp:<line number> +............................................................................... + +PartTrackerTests.cpp:<line number>: +PASSED: + REQUIRE( g1.isOpen() ) +with expansion: + true + +PartTrackerTests.cpp:<line number>: +PASSED: + REQUIRE( g1.index() == 0 ) +with expansion: + 0 == 0 + +PartTrackerTests.cpp:<line number>: +PASSED: + REQUIRE( g1.isComplete() == false ) +with expansion: + false == false + +PartTrackerTests.cpp:<line number>: +PASSED: + REQUIRE( s1.isComplete() == false ) +with expansion: + false == false + +------------------------------------------------------------------------------- +Tracker + start a generator + close outer section +------------------------------------------------------------------------------- +PartTrackerTests.cpp:<line number> +............................................................................... + +PartTrackerTests.cpp:<line number>: +PASSED: + REQUIRE( s1.isComplete() == false ) +with expansion: + false == false + +PartTrackerTests.cpp:<line number>: +PASSED: + REQUIRE( testCase.isSuccessfullyCompleted() == false ) +with expansion: + false == false + +------------------------------------------------------------------------------- +Tracker + start a generator + close outer section + Re-enter for second generation +------------------------------------------------------------------------------- +PartTrackerTests.cpp:<line number> +............................................................................... + +PartTrackerTests.cpp:<line number>: +PASSED: + REQUIRE( testCase2.isOpen() ) +with expansion: + true + +PartTrackerTests.cpp:<line number>: +PASSED: + REQUIRE( s1b.isOpen() ) +with expansion: + true + +PartTrackerTests.cpp:<line number>: +PASSED: + REQUIRE( g1b.isOpen() ) +with expansion: + true + +PartTrackerTests.cpp:<line number>: +PASSED: + REQUIRE( g1b.index() == 1 ) +with expansion: + 1 == 1 + +PartTrackerTests.cpp:<line number>: +PASSED: + REQUIRE( s1.isComplete() == false ) +with expansion: + false == false + +PartTrackerTests.cpp:<line number>: +PASSED: + REQUIRE( s1b.isComplete() ) +with expansion: + true + +PartTrackerTests.cpp:<line number>: +PASSED: + REQUIRE( g1b.isComplete() ) +with expansion: + true + +PartTrackerTests.cpp:<line number>: +PASSED: + REQUIRE( testCase2.isComplete() ) +with expansion: + true + +------------------------------------------------------------------------------- +Tracker +------------------------------------------------------------------------------- +PartTrackerTests.cpp:<line number> +............................................................................... + +PartTrackerTests.cpp:<line number>: +PASSED: + REQUIRE( testCase.isOpen() ) +with expansion: + true + +PartTrackerTests.cpp:<line number>: +PASSED: + REQUIRE( s1.isOpen() ) +with expansion: + true + +------------------------------------------------------------------------------- +Tracker + start a generator +------------------------------------------------------------------------------- +PartTrackerTests.cpp:<line number> +............................................................................... + +PartTrackerTests.cpp:<line number>: +PASSED: + REQUIRE( g1.isOpen() ) +with expansion: + true + +PartTrackerTests.cpp:<line number>: +PASSED: + REQUIRE( g1.index() == 0 ) +with expansion: + 0 == 0 + +PartTrackerTests.cpp:<line number>: +PASSED: + REQUIRE( g1.isComplete() == false ) +with expansion: + false == false + +PartTrackerTests.cpp:<line number>: +PASSED: + REQUIRE( s1.isComplete() == false ) +with expansion: + false == false + +------------------------------------------------------------------------------- +Tracker + start a generator + Start a new inner section +------------------------------------------------------------------------------- +PartTrackerTests.cpp:<line number> +............................................................................... + +PartTrackerTests.cpp:<line number>: +PASSED: + REQUIRE( s2.isOpen() ) +with expansion: + true + +PartTrackerTests.cpp:<line number>: +PASSED: + REQUIRE( s2.isComplete() ) +with expansion: + true + +PartTrackerTests.cpp:<line number>: +PASSED: + REQUIRE( s1.isComplete() == false ) +with expansion: + false == false + +PartTrackerTests.cpp:<line number>: +PASSED: + REQUIRE( testCase.isComplete() == false ) +with expansion: + false == false + +------------------------------------------------------------------------------- +Tracker + start a generator + Start a new inner section + Re-enter for second generation +------------------------------------------------------------------------------- +PartTrackerTests.cpp:<line number> +............................................................................... + +PartTrackerTests.cpp:<line number>: +PASSED: + REQUIRE( testCase2.isOpen() ) +with expansion: + true + +PartTrackerTests.cpp:<line number>: +PASSED: + REQUIRE( s1b.isOpen() ) +with expansion: + true + +PartTrackerTests.cpp:<line number>: +PASSED: + REQUIRE( g1b.isOpen() ) +with expansion: + true + +PartTrackerTests.cpp:<line number>: +PASSED: + REQUIRE( g1b.index() == 1 ) +with expansion: + 1 == 1 + +PartTrackerTests.cpp:<line number>: +PASSED: + REQUIRE( s2b.isOpen() ) +with expansion: + true + +PartTrackerTests.cpp:<line number>: +PASSED: + REQUIRE( s2b.isComplete() ) +with expansion: + true + +PartTrackerTests.cpp:<line number>: +PASSED: + REQUIRE( g1b.isComplete() ) +with expansion: + true + +PartTrackerTests.cpp:<line number>: +PASSED: + REQUIRE( s1b.isComplete() ) +with expansion: + true + +PartTrackerTests.cpp:<line number>: +PASSED: + REQUIRE( testCase2.isComplete() ) +with expansion: + true + +------------------------------------------------------------------------------- +Tracker +------------------------------------------------------------------------------- +PartTrackerTests.cpp:<line number> +............................................................................... + +PartTrackerTests.cpp:<line number>: +PASSED: + REQUIRE( testCase.isOpen() ) +with expansion: + true + +PartTrackerTests.cpp:<line number>: +PASSED: + REQUIRE( s1.isOpen() ) +with expansion: + true + +------------------------------------------------------------------------------- +Tracker + start a generator +------------------------------------------------------------------------------- +PartTrackerTests.cpp:<line number> +............................................................................... + +PartTrackerTests.cpp:<line number>: +PASSED: + REQUIRE( g1.isOpen() ) +with expansion: + true + +PartTrackerTests.cpp:<line number>: +PASSED: + REQUIRE( g1.index() == 0 ) +with expansion: + 0 == 0 + +PartTrackerTests.cpp:<line number>: +PASSED: + REQUIRE( g1.isComplete() == false ) +with expansion: + false == false + +PartTrackerTests.cpp:<line number>: +PASSED: + REQUIRE( s1.isComplete() == false ) +with expansion: + false == false + +------------------------------------------------------------------------------- +Tracker + start a generator + Fail an inner section +------------------------------------------------------------------------------- +PartTrackerTests.cpp:<line number> +............................................................................... + +PartTrackerTests.cpp:<line number>: +PASSED: + REQUIRE( s2.isOpen() ) +with expansion: + true + +PartTrackerTests.cpp:<line number>: +PASSED: + REQUIRE( s2.isComplete() ) +with expansion: + true + +PartTrackerTests.cpp:<line number>: +PASSED: + REQUIRE( s2.isSuccessfullyCompleted() == false ) +with expansion: + false == false + +PartTrackerTests.cpp:<line number>: +PASSED: + REQUIRE( s1.isComplete() == false ) +with expansion: + false == false + +PartTrackerTests.cpp:<line number>: +PASSED: + REQUIRE( testCase.isComplete() == false ) +with expansion: + false == false + +------------------------------------------------------------------------------- +Tracker + start a generator + Fail an inner section + Re-enter for second generation +------------------------------------------------------------------------------- +PartTrackerTests.cpp:<line number> +............................................................................... + +PartTrackerTests.cpp:<line number>: +PASSED: + REQUIRE( testCase2.isOpen() ) +with expansion: + true + +PartTrackerTests.cpp:<line number>: +PASSED: + REQUIRE( s1b.isOpen() ) +with expansion: + true + +PartTrackerTests.cpp:<line number>: +PASSED: + REQUIRE( g1b.isOpen() ) +with expansion: + true + +PartTrackerTests.cpp:<line number>: +PASSED: + REQUIRE( g1b.index() == 0 ) +with expansion: + 0 == 0 + +PartTrackerTests.cpp:<line number>: +PASSED: + REQUIRE( s2b.isOpen() == false ) +with expansion: + false == false + +PartTrackerTests.cpp:<line number>: +PASSED: + REQUIRE( g1b.isComplete() == false ) +with expansion: + false == false + +PartTrackerTests.cpp:<line number>: +PASSED: + REQUIRE( s1b.isComplete() == false ) +with expansion: + false == false + +PartTrackerTests.cpp:<line number>: +PASSED: + REQUIRE( testCase2.isComplete() == false ) +with expansion: + false == false + +PartTrackerTests.cpp:<line number>: +PASSED: + REQUIRE( testCase3.isOpen() ) +with expansion: + true + +PartTrackerTests.cpp:<line number>: +PASSED: + REQUIRE( s1c.isOpen() ) +with expansion: + true + +PartTrackerTests.cpp:<line number>: +PASSED: + REQUIRE( g1c.isOpen() ) +with expansion: + true + +PartTrackerTests.cpp:<line number>: +PASSED: + REQUIRE( g1c.index() == 1 ) +with expansion: + 1 == 1 + +PartTrackerTests.cpp:<line number>: +PASSED: + REQUIRE( s2c.isOpen() ) +with expansion: + true + +PartTrackerTests.cpp:<line number>: +PASSED: + REQUIRE( s2c.isComplete() ) +with expansion: + true + +PartTrackerTests.cpp:<line number>: +PASSED: + REQUIRE( g1c.isComplete() ) +with expansion: + true + +PartTrackerTests.cpp:<line number>: +PASSED: + REQUIRE( s1c.isComplete() ) +with expansion: + true + +PartTrackerTests.cpp:<line number>: +PASSED: + REQUIRE( testCase3.isComplete() ) +with expansion: + true + +------------------------------------------------------------------------------- +std::pair<int,std::string> -> toString +------------------------------------------------------------------------------- +ToStringPair.cpp:<line number> +............................................................................... + +ToStringPair.cpp:<line number>: +PASSED: + REQUIRE( Catch::toString( value ) == "{ 34, \"xyzzy\" }" ) +with expansion: + "{ 34, "xyzzy" }" == "{ 34, "xyzzy" }" + +------------------------------------------------------------------------------- +std::pair<int,const std::string> -> toString +------------------------------------------------------------------------------- +ToStringPair.cpp:<line number> +............................................................................... + +ToStringPair.cpp:<line number>: +PASSED: + REQUIRE( Catch::toString(value) == "{ 34, \"xyzzy\" }" ) +with expansion: + "{ 34, "xyzzy" }" == "{ 34, "xyzzy" }" + +------------------------------------------------------------------------------- +std::vector<std::pair<std::string,int> > -> toString +------------------------------------------------------------------------------- +ToStringPair.cpp:<line number> +............................................................................... + +ToStringPair.cpp:<line number>: +PASSED: + REQUIRE( Catch::toString( pr ) == "{ { \"green\", 55 } }" ) +with expansion: + "{ { "green", 55 } }" + == + "{ { "green", 55 } }" + +------------------------------------------------------------------------------- +pair<pair<int,const char *,pair<std::string,int> > -> toString +------------------------------------------------------------------------------- +ToStringPair.cpp:<line number> +............................................................................... + +ToStringPair.cpp:<line number>: +PASSED: + REQUIRE( Catch::toString( pair ) == "{ { 42, \"Arthur\" }, { \"Ford\", 24 } }" ) +with expansion: + "{ { 42, "Arthur" }, { "Ford", 24 } }" + == + "{ { 42, "Arthur" }, { "Ford", 24 } }" + +------------------------------------------------------------------------------- +vector<int> -> toString +------------------------------------------------------------------------------- +ToStringVector.cpp:<line number> +............................................................................... + +ToStringVector.cpp:<line number>: +PASSED: + REQUIRE( Catch::toString(vv) == "{ }" ) +with expansion: + "{ }" == "{ }" + +ToStringVector.cpp:<line number>: +PASSED: + REQUIRE( Catch::toString(vv) == "{ 42 }" ) +with expansion: + "{ 42 }" == "{ 42 }" + +ToStringVector.cpp:<line number>: +PASSED: + REQUIRE( Catch::toString(vv) == "{ 42, 250 }" ) +with expansion: + "{ 42, 250 }" == "{ 42, 250 }" + +------------------------------------------------------------------------------- +vector<string> -> toString +------------------------------------------------------------------------------- +ToStringVector.cpp:<line number> +............................................................................... + +ToStringVector.cpp:<line number>: +PASSED: + REQUIRE( Catch::toString(vv) == "{ }" ) +with expansion: + "{ }" == "{ }" + +ToStringVector.cpp:<line number>: +PASSED: + REQUIRE( Catch::toString(vv) == "{ \"hello\" }" ) +with expansion: + "{ "hello" }" == "{ "hello" }" + +ToStringVector.cpp:<line number>: +PASSED: + REQUIRE( Catch::toString(vv) == "{ \"hello\", \"world\" }" ) +with expansion: + "{ "hello", "world" }" + == + "{ "hello", "world" }" + +------------------------------------------------------------------------------- +vector<int,allocator> -> toString +------------------------------------------------------------------------------- +ToStringVector.cpp:<line number> +............................................................................... + +ToStringVector.cpp:<line number>: +PASSED: + REQUIRE( Catch::toString(vv) == "{ }" ) +with expansion: + "{ }" == "{ }" + +ToStringVector.cpp:<line number>: +PASSED: + REQUIRE( Catch::toString(vv) == "{ 42 }" ) +with expansion: + "{ 42 }" == "{ 42 }" + +ToStringVector.cpp:<line number>: +PASSED: + REQUIRE( Catch::toString(vv) == "{ 42, 250 }" ) +with expansion: + "{ 42, 250 }" == "{ 42, 250 }" + +------------------------------------------------------------------------------- +vec<vec<string,alloc>> -> toString +------------------------------------------------------------------------------- +ToStringVector.cpp:<line number> +............................................................................... + +ToStringVector.cpp:<line number>: +PASSED: + REQUIRE( Catch::toString(v) == "{ }" ) +with expansion: + "{ }" == "{ }" + +ToStringVector.cpp:<line number>: +PASSED: + REQUIRE( Catch::toString(v) == "{ { \"hello\" }, { \"world\" } }" ) +with expansion: + "{ { "hello" }, { "world" } }" + == + "{ { "hello" }, { "world" } }" + +------------------------------------------------------------------------------- +Parse test names and tags + Empty test spec should have no filters +------------------------------------------------------------------------------- +CmdLineTests.cpp:<line number> +............................................................................... + +CmdLineTests.cpp:<line number>: +PASSED: + CHECK( spec.hasFilters() == false ) +with expansion: + false == false + +CmdLineTests.cpp:<line number>: +PASSED: + CHECK( spec.matches( tcA ) == false ) +with expansion: + false == false + +CmdLineTests.cpp:<line number>: +PASSED: + CHECK( spec.matches( tcB ) == false ) +with expansion: + false == false + +------------------------------------------------------------------------------- +Parse test names and tags + Test spec from empty string should have no filters +------------------------------------------------------------------------------- +CmdLineTests.cpp:<line number> +............................................................................... + +CmdLineTests.cpp:<line number>: +PASSED: + CHECK( spec.hasFilters() == false ) +with expansion: + false == false + +CmdLineTests.cpp:<line number>: +PASSED: + CHECK( spec.matches(tcA ) == false ) +with expansion: + false == false + +CmdLineTests.cpp:<line number>: +PASSED: + CHECK( spec.matches( tcB ) == false ) +with expansion: + false == false + +------------------------------------------------------------------------------- +Parse test names and tags + Test spec from just a comma should have no filters +------------------------------------------------------------------------------- +CmdLineTests.cpp:<line number> +............................................................................... + +CmdLineTests.cpp:<line number>: +PASSED: + CHECK( spec.hasFilters() == false ) +with expansion: + false == false + +CmdLineTests.cpp:<line number>: +PASSED: + CHECK( spec.matches( tcA ) == false ) +with expansion: + false == false + +CmdLineTests.cpp:<line number>: +PASSED: + CHECK( spec.matches( tcB ) == false ) +with expansion: + false == false + +------------------------------------------------------------------------------- +Parse test names and tags + Test spec from name should have one filter +------------------------------------------------------------------------------- +CmdLineTests.cpp:<line number> +............................................................................... + +CmdLineTests.cpp:<line number>: +PASSED: + CHECK( spec.hasFilters() == true ) +with expansion: + true == true + +CmdLineTests.cpp:<line number>: +PASSED: + CHECK( spec.matches( tcA ) == false ) +with expansion: + false == false + +CmdLineTests.cpp:<line number>: +PASSED: + CHECK( spec.matches( tcB ) == true ) +with expansion: + true == true + +------------------------------------------------------------------------------- +Parse test names and tags + Test spec from quoted name should have one filter +------------------------------------------------------------------------------- +CmdLineTests.cpp:<line number> +............................................................................... + +CmdLineTests.cpp:<line number>: +PASSED: + CHECK( spec.hasFilters() == true ) +with expansion: + true == true + +CmdLineTests.cpp:<line number>: +PASSED: + CHECK( spec.matches( tcA ) == false ) +with expansion: + false == false + +CmdLineTests.cpp:<line number>: +PASSED: + CHECK( spec.matches( tcB ) == true ) +with expansion: + true == true + +------------------------------------------------------------------------------- +Parse test names and tags + Test spec from name should have one filter +------------------------------------------------------------------------------- +CmdLineTests.cpp:<line number> +............................................................................... + +CmdLineTests.cpp:<line number>: +PASSED: + CHECK( spec.hasFilters() == true ) +with expansion: + true == true + +CmdLineTests.cpp:<line number>: +PASSED: + CHECK( spec.matches( tcA ) == false ) +with expansion: + false == false + +CmdLineTests.cpp:<line number>: +PASSED: + CHECK( spec.matches( tcB ) == true ) +with expansion: + true == true + +CmdLineTests.cpp:<line number>: +PASSED: + CHECK( spec.matches( tcC ) == false ) +with expansion: + false == false + +------------------------------------------------------------------------------- +Parse test names and tags + Wildcard at the start +------------------------------------------------------------------------------- +CmdLineTests.cpp:<line number> +............................................................................... + +CmdLineTests.cpp:<line number>: +PASSED: + CHECK( spec.hasFilters() == true ) +with expansion: + true == true + +CmdLineTests.cpp:<line number>: +PASSED: + CHECK( spec.matches( tcA ) == false ) +with expansion: + false == false + +CmdLineTests.cpp:<line number>: +PASSED: + CHECK( spec.matches( tcB ) == false ) +with expansion: + false == false + +CmdLineTests.cpp:<line number>: +PASSED: + CHECK( spec.matches( tcC ) == true ) +with expansion: + true == true + +CmdLineTests.cpp:<line number>: +PASSED: + CHECK( spec.matches( tcD ) == false ) +with expansion: + false == false + +CmdLineTests.cpp:<line number>: +PASSED: + CHECK( parseTestSpec( "*a" ).matches( tcA ) == true ) +with expansion: + true == true + +------------------------------------------------------------------------------- +Parse test names and tags + Wildcard at the end +------------------------------------------------------------------------------- +CmdLineTests.cpp:<line number> +............................................................................... + +CmdLineTests.cpp:<line number>: +PASSED: + CHECK( spec.hasFilters() == true ) +with expansion: + true == true + +CmdLineTests.cpp:<line number>: +PASSED: + CHECK( spec.matches( tcA ) == false ) +with expansion: + false == false + +CmdLineTests.cpp:<line number>: +PASSED: + CHECK( spec.matches( tcB ) == false ) +with expansion: + false == false + +CmdLineTests.cpp:<line number>: +PASSED: + CHECK( spec.matches( tcC ) == true ) +with expansion: + true == true + +CmdLineTests.cpp:<line number>: +PASSED: + CHECK( spec.matches( tcD ) == false ) +with expansion: + false == false + +CmdLineTests.cpp:<line number>: +PASSED: + CHECK( parseTestSpec( "a*" ).matches( tcA ) == true ) +with expansion: + true == true + +------------------------------------------------------------------------------- +Parse test names and tags + Wildcard at both ends +------------------------------------------------------------------------------- +CmdLineTests.cpp:<line number> +............................................................................... + +CmdLineTests.cpp:<line number>: +PASSED: + CHECK( spec.hasFilters() == true ) +with expansion: + true == true + +CmdLineTests.cpp:<line number>: +PASSED: + CHECK( spec.matches( tcA ) == false ) +with expansion: + false == false + +CmdLineTests.cpp:<line number>: +PASSED: + CHECK( spec.matches( tcB ) == false ) +with expansion: + false == false + +CmdLineTests.cpp:<line number>: +PASSED: + CHECK( spec.matches( tcC ) == true ) +with expansion: + true == true + +CmdLineTests.cpp:<line number>: +PASSED: + CHECK( spec.matches( tcD ) == true ) +with expansion: + true == true + +CmdLineTests.cpp:<line number>: +PASSED: + CHECK( parseTestSpec( "*a*" ).matches( tcA ) == true ) +with expansion: + true == true + +------------------------------------------------------------------------------- +Parse test names and tags + Redundant wildcard at the start +------------------------------------------------------------------------------- +CmdLineTests.cpp:<line number> +............................................................................... + +CmdLineTests.cpp:<line number>: +PASSED: + CHECK( spec.hasFilters() == true ) +with expansion: + true == true + +CmdLineTests.cpp:<line number>: +PASSED: + CHECK( spec.matches( tcA ) == true ) +with expansion: + true == true + +CmdLineTests.cpp:<line number>: +PASSED: + CHECK( spec.matches( tcB ) == false ) +with expansion: + false == false + +------------------------------------------------------------------------------- +Parse test names and tags + Redundant wildcard at the end +------------------------------------------------------------------------------- +CmdLineTests.cpp:<line number> +............................................................................... + +CmdLineTests.cpp:<line number>: +PASSED: + CHECK( spec.hasFilters() == true ) +with expansion: + true == true + +CmdLineTests.cpp:<line number>: +PASSED: + CHECK( spec.matches( tcA ) == true ) +with expansion: + true == true + +CmdLineTests.cpp:<line number>: +PASSED: + CHECK( spec.matches( tcB ) == false ) +with expansion: + false == false + +------------------------------------------------------------------------------- +Parse test names and tags + Redundant wildcard at both ends +------------------------------------------------------------------------------- +CmdLineTests.cpp:<line number> +............................................................................... + +CmdLineTests.cpp:<line number>: +PASSED: + CHECK( spec.hasFilters() == true ) +with expansion: + true == true + +CmdLineTests.cpp:<line number>: +PASSED: + CHECK( spec.matches( tcA ) == true ) +with expansion: + true == true + +CmdLineTests.cpp:<line number>: +PASSED: + CHECK( spec.matches( tcB ) == false ) +with expansion: + false == false + +------------------------------------------------------------------------------- +Parse test names and tags + Wildcard at both ends, redundant at start +------------------------------------------------------------------------------- +CmdLineTests.cpp:<line number> +............................................................................... + +CmdLineTests.cpp:<line number>: +PASSED: + CHECK( spec.hasFilters() == true ) +with expansion: + true == true + +CmdLineTests.cpp:<line number>: +PASSED: + CHECK( spec.matches( tcA ) == false ) +with expansion: + false == false + +CmdLineTests.cpp:<line number>: +PASSED: + CHECK( spec.matches( tcB ) == false ) +with expansion: + false == false + +CmdLineTests.cpp:<line number>: +PASSED: + CHECK( spec.matches( tcC ) == true ) +with expansion: + true == true + +CmdLineTests.cpp:<line number>: +PASSED: + CHECK( spec.matches( tcD ) == true ) +with expansion: + true == true + +------------------------------------------------------------------------------- +Parse test names and tags + Just wildcard +------------------------------------------------------------------------------- +CmdLineTests.cpp:<line number> +............................................................................... + +CmdLineTests.cpp:<line number>: +PASSED: + CHECK( spec.hasFilters() == true ) +with expansion: + true == true + +CmdLineTests.cpp:<line number>: +PASSED: + CHECK( spec.matches( tcA ) == true ) +with expansion: + true == true + +CmdLineTests.cpp:<line number>: +PASSED: + CHECK( spec.matches( tcB ) == true ) +with expansion: + true == true + +CmdLineTests.cpp:<line number>: +PASSED: + CHECK( spec.matches( tcC ) == true ) +with expansion: + true == true + +CmdLineTests.cpp:<line number>: +PASSED: + CHECK( spec.matches( tcD ) == true ) +with expansion: + true == true + +------------------------------------------------------------------------------- +Parse test names and tags + Single tag +------------------------------------------------------------------------------- +CmdLineTests.cpp:<line number> +............................................................................... + +CmdLineTests.cpp:<line number>: +PASSED: + CHECK( spec.hasFilters() == true ) +with expansion: + true == true + +CmdLineTests.cpp:<line number>: +PASSED: + CHECK( spec.matches( tcA ) == false ) +with expansion: + false == false + +CmdLineTests.cpp:<line number>: +PASSED: + CHECK( spec.matches( tcB ) == true ) +with expansion: + true == true + +CmdLineTests.cpp:<line number>: +PASSED: + CHECK( spec.matches( tcC ) == false ) +with expansion: + false == false + +------------------------------------------------------------------------------- +Parse test names and tags + Single tag, two matches +------------------------------------------------------------------------------- +CmdLineTests.cpp:<line number> +............................................................................... + +CmdLineTests.cpp:<line number>: +PASSED: + CHECK( spec.hasFilters() == true ) +with expansion: + true == true + +CmdLineTests.cpp:<line number>: +PASSED: + CHECK( spec.matches( tcA ) == false ) +with expansion: + false == false + +CmdLineTests.cpp:<line number>: +PASSED: + CHECK( spec.matches( tcB ) == true ) +with expansion: + true == true + +CmdLineTests.cpp:<line number>: +PASSED: + CHECK( spec.matches( tcC ) == true ) +with expansion: + true == true + +------------------------------------------------------------------------------- +Parse test names and tags + Two tags +------------------------------------------------------------------------------- +CmdLineTests.cpp:<line number> +............................................................................... + +CmdLineTests.cpp:<line number>: +PASSED: + CHECK( spec.hasFilters() == true ) +with expansion: + true == true + +CmdLineTests.cpp:<line number>: +PASSED: + CHECK( spec.matches( tcA ) == false ) +with expansion: + false == false + +CmdLineTests.cpp:<line number>: +PASSED: + CHECK( spec.matches( tcB ) == false ) +with expansion: + false == false + +CmdLineTests.cpp:<line number>: +PASSED: + CHECK( spec.matches( tcC ) == true ) +with expansion: + true == true + +------------------------------------------------------------------------------- +Parse test names and tags + Two tags, spare separated +------------------------------------------------------------------------------- +CmdLineTests.cpp:<line number> +............................................................................... + +CmdLineTests.cpp:<line number>: +PASSED: + CHECK( spec.hasFilters() == true ) +with expansion: + true == true + +CmdLineTests.cpp:<line number>: +PASSED: + CHECK( spec.matches( tcA ) == false ) +with expansion: + false == false + +CmdLineTests.cpp:<line number>: +PASSED: + CHECK( spec.matches( tcB ) == false ) +with expansion: + false == false + +CmdLineTests.cpp:<line number>: +PASSED: + CHECK( spec.matches( tcC ) == true ) +with expansion: + true == true + +------------------------------------------------------------------------------- +Parse test names and tags + Wildcarded name and tag +------------------------------------------------------------------------------- +CmdLineTests.cpp:<line number> +............................................................................... + +CmdLineTests.cpp:<line number>: +PASSED: + CHECK( spec.hasFilters() == true ) +with expansion: + true == true + +CmdLineTests.cpp:<line number>: +PASSED: + CHECK( spec.matches( tcA ) == false ) +with expansion: + false == false + +CmdLineTests.cpp:<line number>: +PASSED: + CHECK( spec.matches( tcB ) == false ) +with expansion: + false == false + +CmdLineTests.cpp:<line number>: +PASSED: + CHECK( spec.matches( tcC ) == true ) +with expansion: + true == true + +CmdLineTests.cpp:<line number>: +PASSED: + CHECK( spec.matches( tcD ) == false ) +with expansion: + false == false + +------------------------------------------------------------------------------- +Parse test names and tags + Single tag exclusion +------------------------------------------------------------------------------- +CmdLineTests.cpp:<line number> +............................................................................... + +CmdLineTests.cpp:<line number>: +PASSED: + CHECK( spec.hasFilters() == true ) +with expansion: + true == true + +CmdLineTests.cpp:<line number>: +PASSED: + CHECK( spec.matches( tcA ) == true ) +with expansion: + true == true + +CmdLineTests.cpp:<line number>: +PASSED: + CHECK( spec.matches( tcB ) == false ) +with expansion: + false == false + +CmdLineTests.cpp:<line number>: +PASSED: + CHECK( spec.matches( tcC ) == true ) +with expansion: + true == true + +------------------------------------------------------------------------------- +Parse test names and tags + One tag exclusion and one tag inclusion +------------------------------------------------------------------------------- +CmdLineTests.cpp:<line number> +............................................................................... + +CmdLineTests.cpp:<line number>: +PASSED: + CHECK( spec.hasFilters() == true ) +with expansion: + true == true + +CmdLineTests.cpp:<line number>: +PASSED: + CHECK( spec.matches( tcA ) == false ) +with expansion: + false == false + +CmdLineTests.cpp:<line number>: +PASSED: + CHECK( spec.matches( tcB ) == true ) +with expansion: + true == true + +CmdLineTests.cpp:<line number>: +PASSED: + CHECK( spec.matches( tcC ) == false ) +with expansion: + false == false + +------------------------------------------------------------------------------- +Parse test names and tags + One tag exclusion and one wldcarded name inclusion +------------------------------------------------------------------------------- +CmdLineTests.cpp:<line number> +............................................................................... + +CmdLineTests.cpp:<line number>: +PASSED: + CHECK( spec.hasFilters() == true ) +with expansion: + true == true + +CmdLineTests.cpp:<line number>: +PASSED: + CHECK( spec.matches( tcA ) == false ) +with expansion: + false == false + +CmdLineTests.cpp:<line number>: +PASSED: + CHECK( spec.matches( tcB ) == false ) +with expansion: + false == false + +CmdLineTests.cpp:<line number>: +PASSED: + CHECK( spec.matches( tcC ) == false ) +with expansion: + false == false + +CmdLineTests.cpp:<line number>: +PASSED: + CHECK( spec.matches( tcD ) == true ) +with expansion: + true == true + +------------------------------------------------------------------------------- +Parse test names and tags + One tag exclusion, using exclude:, and one wldcarded name inclusion +------------------------------------------------------------------------------- +CmdLineTests.cpp:<line number> +............................................................................... + +CmdLineTests.cpp:<line number>: +PASSED: + CHECK( spec.hasFilters() == true ) +with expansion: + true == true + +CmdLineTests.cpp:<line number>: +PASSED: + CHECK( spec.matches( tcA ) == false ) +with expansion: + false == false + +CmdLineTests.cpp:<line number>: +PASSED: + CHECK( spec.matches( tcB ) == false ) +with expansion: + false == false + +CmdLineTests.cpp:<line number>: +PASSED: + CHECK( spec.matches( tcC ) == false ) +with expansion: + false == false + +CmdLineTests.cpp:<line number>: +PASSED: + CHECK( spec.matches( tcD ) == true ) +with expansion: + true == true + +------------------------------------------------------------------------------- +Parse test names and tags + name exclusion +------------------------------------------------------------------------------- +CmdLineTests.cpp:<line number> +............................................................................... + +CmdLineTests.cpp:<line number>: +PASSED: + CHECK( spec.hasFilters() == true ) +with expansion: + true == true + +CmdLineTests.cpp:<line number>: +PASSED: + CHECK( spec.matches( tcA ) == true ) +with expansion: + true == true + +CmdLineTests.cpp:<line number>: +PASSED: + CHECK( spec.matches( tcB ) == false ) +with expansion: + false == false + +CmdLineTests.cpp:<line number>: +PASSED: + CHECK( spec.matches( tcC ) == true ) +with expansion: + true == true + +CmdLineTests.cpp:<line number>: +PASSED: + CHECK( spec.matches( tcD ) == true ) +with expansion: + true == true + +------------------------------------------------------------------------------- +Parse test names and tags + wildcarded name exclusion +------------------------------------------------------------------------------- +CmdLineTests.cpp:<line number> +............................................................................... + +CmdLineTests.cpp:<line number>: +PASSED: + CHECK( spec.hasFilters() == true ) +with expansion: + true == true + +CmdLineTests.cpp:<line number>: +PASSED: + CHECK( spec.matches( tcA ) == true ) +with expansion: + true == true + +CmdLineTests.cpp:<line number>: +PASSED: + CHECK( spec.matches( tcB ) == true ) +with expansion: + true == true + +CmdLineTests.cpp:<line number>: +PASSED: + CHECK( spec.matches( tcC ) == false ) +with expansion: + false == false + +CmdLineTests.cpp:<line number>: +PASSED: + CHECK( spec.matches( tcD ) == false ) +with expansion: + false == false + +------------------------------------------------------------------------------- +Parse test names and tags + wildcarded name exclusion with tag inclusion +------------------------------------------------------------------------------- +CmdLineTests.cpp:<line number> +............................................................................... + +CmdLineTests.cpp:<line number>: +PASSED: + CHECK( spec.hasFilters() == true ) +with expansion: + true == true + +CmdLineTests.cpp:<line number>: +PASSED: + CHECK( spec.matches( tcA ) == true ) +with expansion: + true == true + +CmdLineTests.cpp:<line number>: +PASSED: + CHECK( spec.matches( tcB ) == true ) +with expansion: + true == true + +CmdLineTests.cpp:<line number>: +PASSED: + CHECK( spec.matches( tcC ) == true ) +with expansion: + true == true + +CmdLineTests.cpp:<line number>: +PASSED: + CHECK( spec.matches( tcD ) == false ) +with expansion: + false == false + +------------------------------------------------------------------------------- +Parse test names and tags + wildcarded name exclusion, using exclude:, with tag inclusion +------------------------------------------------------------------------------- +CmdLineTests.cpp:<line number> +............................................................................... + +CmdLineTests.cpp:<line number>: +PASSED: + CHECK( spec.hasFilters() == true ) +with expansion: + true == true + +CmdLineTests.cpp:<line number>: +PASSED: + CHECK( spec.matches( tcA ) == true ) +with expansion: + true == true + +CmdLineTests.cpp:<line number>: +PASSED: + CHECK( spec.matches( tcB ) == true ) +with expansion: + true == true + +CmdLineTests.cpp:<line number>: +PASSED: + CHECK( spec.matches( tcC ) == true ) +with expansion: + true == true + +CmdLineTests.cpp:<line number>: +PASSED: + CHECK( spec.matches( tcD ) == false ) +with expansion: + false == false + +------------------------------------------------------------------------------- +Parse test names and tags + two wildcarded names +------------------------------------------------------------------------------- +CmdLineTests.cpp:<line number> +............................................................................... + +CmdLineTests.cpp:<line number>: +PASSED: + CHECK( spec.hasFilters() == true ) +with expansion: + true == true + +CmdLineTests.cpp:<line number>: +PASSED: + CHECK( spec.matches( tcA ) == false ) +with expansion: + false == false + +CmdLineTests.cpp:<line number>: +PASSED: + CHECK( spec.matches( tcB ) == false ) +with expansion: + false == false + +CmdLineTests.cpp:<line number>: +PASSED: + CHECK( spec.matches( tcC ) == true ) +with expansion: + true == true + +CmdLineTests.cpp:<line number>: +PASSED: + CHECK( spec.matches( tcD ) == false ) +with expansion: + false == false + +------------------------------------------------------------------------------- +Parse test names and tags + empty tag +------------------------------------------------------------------------------- +CmdLineTests.cpp:<line number> +............................................................................... + +CmdLineTests.cpp:<line number>: +PASSED: + CHECK( spec.hasFilters() == false ) +with expansion: + false == false + +CmdLineTests.cpp:<line number>: +PASSED: + CHECK( spec.matches( tcA ) == false ) +with expansion: + false == false + +CmdLineTests.cpp:<line number>: +PASSED: + CHECK( spec.matches( tcB ) == false ) +with expansion: + false == false + +CmdLineTests.cpp:<line number>: +PASSED: + CHECK( spec.matches( tcC ) == false ) +with expansion: + false == false + +CmdLineTests.cpp:<line number>: +PASSED: + CHECK( spec.matches( tcD ) == false ) +with expansion: + false == false + +------------------------------------------------------------------------------- +Parse test names and tags + empty quoted name +------------------------------------------------------------------------------- +CmdLineTests.cpp:<line number> +............................................................................... + +CmdLineTests.cpp:<line number>: +PASSED: + CHECK( spec.hasFilters() == false ) +with expansion: + false == false + +CmdLineTests.cpp:<line number>: +PASSED: + CHECK( spec.matches( tcA ) == false ) +with expansion: + false == false + +CmdLineTests.cpp:<line number>: +PASSED: + CHECK( spec.matches( tcB ) == false ) +with expansion: + false == false + +CmdLineTests.cpp:<line number>: +PASSED: + CHECK( spec.matches( tcC ) == false ) +with expansion: + false == false + +CmdLineTests.cpp:<line number>: +PASSED: + CHECK( spec.matches( tcD ) == false ) +with expansion: + false == false + +------------------------------------------------------------------------------- +Parse test names and tags + quoted string followed by tag exclusion +------------------------------------------------------------------------------- +CmdLineTests.cpp:<line number> +............................................................................... + +CmdLineTests.cpp:<line number>: +PASSED: + CHECK( spec.hasFilters() == true ) +with expansion: + true == true + +CmdLineTests.cpp:<line number>: +PASSED: + CHECK( spec.matches( tcA ) == false ) +with expansion: + false == false + +CmdLineTests.cpp:<line number>: +PASSED: + CHECK( spec.matches( tcB ) == false ) +with expansion: + false == false + +CmdLineTests.cpp:<line number>: +PASSED: + CHECK( spec.matches( tcC ) == false ) +with expansion: + false == false + +CmdLineTests.cpp:<line number>: +PASSED: + CHECK( spec.matches( tcD ) == true ) +with expansion: + true == true + +------------------------------------------------------------------------------- +tuple<> +------------------------------------------------------------------------------- +ToStringTuple.cpp:<line number> +............................................................................... + +ToStringTuple.cpp:<line number>: +PASSED: + CHECK( "{ }" == Catch::toString(type{}) ) +with expansion: + "{ }" == "{ }" + +ToStringTuple.cpp:<line number>: +PASSED: + CHECK( "{ }" == Catch::toString(value) ) +with expansion: + "{ }" == "{ }" + +------------------------------------------------------------------------------- +tuple<int> +------------------------------------------------------------------------------- +ToStringTuple.cpp:<line number> +............................................................................... + +ToStringTuple.cpp:<line number>: +PASSED: + CHECK( "{ 0 }" == Catch::toString(type{0}) ) +with expansion: + "{ 0 }" == "{ 0 }" + +------------------------------------------------------------------------------- +tuple<float,int> +------------------------------------------------------------------------------- +ToStringTuple.cpp:<line number> +............................................................................... + +ToStringTuple.cpp:<line number>: +PASSED: + CHECK( "1.2f" == Catch::toString(float(1.2)) ) +with expansion: + "1.2f" == "1.2f" + +ToStringTuple.cpp:<line number>: +PASSED: + CHECK( "{ 1.2f, 0 }" == Catch::toString(type{1.2,0}) ) +with expansion: + "{ 1.2f, 0 }" == "{ 1.2f, 0 }" + +------------------------------------------------------------------------------- +tuple<string,string> +------------------------------------------------------------------------------- +ToStringTuple.cpp:<line number> +............................................................................... + +ToStringTuple.cpp:<line number>: +PASSED: + CHECK( "{ \"hello\", \"world\" }" == Catch::toString(type{"hello","world"}) ) +with expansion: + "{ "hello", "world" }" + == + "{ "hello", "world" }" + +------------------------------------------------------------------------------- +tuple<tuple<int>,tuple<>,float> +------------------------------------------------------------------------------- +ToStringTuple.cpp:<line number> +............................................................................... + +ToStringTuple.cpp:<line number>: +PASSED: + CHECK( "{ { 42 }, { }, 1.2f }" == Catch::toString(value) ) +with expansion: + "{ { 42 }, { }, 1.2f }" + == + "{ { 42 }, { }, 1.2f }" + +------------------------------------------------------------------------------- +tuple<nullptr,int,const char *> +------------------------------------------------------------------------------- +ToStringTuple.cpp:<line number> +............................................................................... + +ToStringTuple.cpp:<line number>: +PASSED: + CHECK( "{ nullptr, 42, \"Catch me\" }" == Catch::toString(value) ) +with expansion: + "{ nullptr, 42, "Catch me" }" + == + "{ nullptr, 42, "Catch me" }" + +------------------------------------------------------------------------------- +Tag alias can be registered against tag patterns + The same tag alias can only be registered once +------------------------------------------------------------------------------- +TagAliasTests.cpp:<line number> +............................................................................... + +TagAliasTests.cpp:<line number>: +PASSED: + CHECK_THAT( what, Contains( "[@zzz]" ) ) +with expansion: + "error: tag alias, "[@zzz]" already registered. + First seen at file:2 + Redefined at file:10" contains: " + [@zzz]" + +TagAliasTests.cpp:<line number>: +PASSED: + CHECK_THAT( what, Contains( "file" ) ) +with expansion: + "error: tag alias, "[@zzz]" already registered. + First seen at file:2 + Redefined at file:10" contains: + "file" + +TagAliasTests.cpp:<line number>: +PASSED: + CHECK_THAT( what, Contains( "2" ) ) +with expansion: + "error: tag alias, "[@zzz]" already registered. + First seen at file:2 + Redefined at file:10" contains: + "2" + +TagAliasTests.cpp:<line number>: +PASSED: + CHECK_THAT( what, Contains( "10" ) ) +with expansion: + "error: tag alias, "[@zzz]" already registered. + First seen at file:2 + Redefined at file:10" contains: + "10" + +------------------------------------------------------------------------------- +Tag alias can be registered against tag patterns + Tag aliases must be of the form [@name] +------------------------------------------------------------------------------- +TagAliasTests.cpp:<line number> +............................................................................... + +TagAliasTests.cpp:<line number>: +PASSED: + CHECK_THROWS( registry.add( "[no ampersat]", "", Catch::SourceLineInfo( "file", 3 ) ) ) + +TagAliasTests.cpp:<line number>: +PASSED: + CHECK_THROWS( registry.add( "[the @ is not at the start]", "", Catch::SourceLineInfo( "file", 3 ) ) ) + +TagAliasTests.cpp:<line number>: +PASSED: + CHECK_THROWS( registry.add( "@no square bracket at start]", "", Catch::SourceLineInfo( "file", 3 ) ) ) + +TagAliasTests.cpp:<line number>: +PASSED: + CHECK_THROWS( registry.add( "[@no square bracket at end", "", Catch::SourceLineInfo( "file", 3 ) ) ) + +------------------------------------------------------------------------------- +Anonymous test case 1 +------------------------------------------------------------------------------- +VariadicMacrosTests.cpp:<line number> +............................................................................... + +VariadicMacrosTests.cpp:<line number>: +PASSED: +with message: + anonymous test case + +------------------------------------------------------------------------------- +Test case with one argument +------------------------------------------------------------------------------- +VariadicMacrosTests.cpp:<line number> +............................................................................... + +VariadicMacrosTests.cpp:<line number>: +PASSED: +with message: + no assertions + +------------------------------------------------------------------------------- +Variadic macros + Section with one argument +------------------------------------------------------------------------------- +VariadicMacrosTests.cpp:<line number> +............................................................................... + +VariadicMacrosTests.cpp:<line number>: +PASSED: +with message: + no assertions + +------------------------------------------------------------------------------- +Scenario: Do that thing with the thing + Given: This stuff exists + When: I do this + Then: it should do this +------------------------------------------------------------------------------- +BDDTests.cpp:<line number> +............................................................................... + +BDDTests.cpp:<line number>: +PASSED: + REQUIRE( itDoesThis() ) +with expansion: + true + +------------------------------------------------------------------------------- +Scenario: Do that thing with the thing + Given: This stuff exists + When: I do this + Then: it should do this + And: do that +------------------------------------------------------------------------------- +BDDTests.cpp:<line number> +............................................................................... + +BDDTests.cpp:<line number>: +PASSED: + REQUIRE( itDoesThat() ) +with expansion: + true + +------------------------------------------------------------------------------- +Scenario: Vector resizing affects size and capacity + Given: an empty vector +------------------------------------------------------------------------------- +BDDTests.cpp:<line number> +............................................................................... + +BDDTests.cpp:<line number>: +PASSED: + REQUIRE( v.size() == 0 ) +with expansion: + 0 == 0 + +------------------------------------------------------------------------------- +Scenario: Vector resizing affects size and capacity + Given: an empty vector + When: it is made larger + Then: the size and capacity go up +------------------------------------------------------------------------------- +BDDTests.cpp:<line number> +............................................................................... + +BDDTests.cpp:<line number>: +PASSED: + REQUIRE( v.size() == 10 ) +with expansion: + 10 == 10 + +BDDTests.cpp:<line number>: +PASSED: + REQUIRE( v.capacity() >= 10 ) +with expansion: + 10 >= 10 + +------------------------------------------------------------------------------- +Scenario: Vector resizing affects size and capacity + Given: an empty vector + When: it is made larger + Then: the size and capacity go up + And when: it is made smaller again + Then: the size goes down but the capacity stays the same +------------------------------------------------------------------------------- +BDDTests.cpp:<line number> +............................................................................... + +BDDTests.cpp:<line number>: +PASSED: + REQUIRE( v.size() == 5 ) +with expansion: + 5 == 5 + +BDDTests.cpp:<line number>: +PASSED: + REQUIRE( v.capacity() >= 10 ) +with expansion: + 10 >= 10 + +------------------------------------------------------------------------------- +Scenario: Vector resizing affects size and capacity + Given: an empty vector +------------------------------------------------------------------------------- +BDDTests.cpp:<line number> +............................................................................... + +BDDTests.cpp:<line number>: +PASSED: + REQUIRE( v.size() == 0 ) +with expansion: + 0 == 0 + +------------------------------------------------------------------------------- +Scenario: Vector resizing affects size and capacity + Given: an empty vector + When: we reserve more space + Then: The capacity is increased but the size remains the same +------------------------------------------------------------------------------- +BDDTests.cpp:<line number> +............................................................................... + +BDDTests.cpp:<line number>: +PASSED: + REQUIRE( v.capacity() >= 10 ) +with expansion: + 10 >= 10 + +BDDTests.cpp:<line number>: +PASSED: + REQUIRE( v.size() == 0 ) +with expansion: + 0 == 0 + +------------------------------------------------------------------------------- +Scenario: This is a really long scenario name to see how the list command deals + with wrapping + Given: A section name that is so long that it cannot fit in a single + console width + When: The test headers are printed as part of the normal running of the + scenario + Then: The, deliberately very long and overly verbose (you see what I did + there?) section names must wrap, along with an indent +------------------------------------------------------------------------------- +BDDTests.cpp:<line number> +............................................................................... + +BDDTests.cpp:<line number>: +PASSED: +with message: + boo! + +------------------------------------------------------------------------------- +Scenario: BDD tests requiring Fixtures to provide commonly-accessed data or + methods + Given: No operations precede me +------------------------------------------------------------------------------- +BDDTests.cpp:<line number> +............................................................................... + +BDDTests.cpp:<line number>: +PASSED: + REQUIRE( before == 0 ) +with expansion: + 0 == 0 + +------------------------------------------------------------------------------- +Scenario: BDD tests requiring Fixtures to provide commonly-accessed data or + methods + Given: No operations precede me + When: We get the count + Then: Subsequently values are higher +------------------------------------------------------------------------------- +BDDTests.cpp:<line number> +............................................................................... + +BDDTests.cpp:<line number>: +PASSED: + REQUIRE( after > before ) +with expansion: + 1 > 0 + +=============================================================================== +test cases: 167 | 123 passed | 43 failed | 1 failed as expected +assertions: 921 | 823 passed | 85 failed | 13 failed as expected + diff --git a/unittest/Catch/projects/SelfTest/Baselines/console.swa4.approved.txt b/unittest/Catch/projects/SelfTest/Baselines/console.swa4.approved.txt new file mode 100644 index 0000000..0793f1d --- /dev/null +++ b/unittest/Catch/projects/SelfTest/Baselines/console.swa4.approved.txt @@ -0,0 +1,491 @@ + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +CatchSelfTest is a <version> host application. +Run with -? for options + +------------------------------------------------------------------------------- +toString(enum) +------------------------------------------------------------------------------- +EnumToString.cpp:<line number> +............................................................................... + +EnumToString.cpp:<line number>: +PASSED: + CHECK( Catch::toString(e0) == "0" ) +with expansion: + "0" == "0" + +EnumToString.cpp:<line number>: +PASSED: + CHECK( Catch::toString(e1) == "1" ) +with expansion: + "1" == "1" + +------------------------------------------------------------------------------- +toString(enum w/operator<<) +------------------------------------------------------------------------------- +EnumToString.cpp:<line number> +............................................................................... + +EnumToString.cpp:<line number>: +PASSED: + CHECK( Catch::toString(e0) == "E2{0}" ) +with expansion: + "E2{0}" == "E2{0}" + +EnumToString.cpp:<line number>: +PASSED: + CHECK( Catch::toString(e1) == "E2{1}" ) +with expansion: + "E2{1}" == "E2{1}" + +------------------------------------------------------------------------------- +toString(enum class) +------------------------------------------------------------------------------- +EnumToString.cpp:<line number> +............................................................................... + +EnumToString.cpp:<line number>: +PASSED: + CHECK( Catch::toString(e0) == "0" ) +with expansion: + "0" == "0" + +EnumToString.cpp:<line number>: +PASSED: + CHECK( Catch::toString(e1) == "1" ) +with expansion: + "1" == "1" + +------------------------------------------------------------------------------- +toString(enum class w/operator<<) +------------------------------------------------------------------------------- +EnumToString.cpp:<line number> +............................................................................... + +EnumToString.cpp:<line number>: +PASSED: + CHECK( Catch::toString(e0) == "E2/V0" ) +with expansion: + "E2/V0" == "E2/V0" + +EnumToString.cpp:<line number>: +PASSED: + CHECK( Catch::toString(e1) == "E2/V1" ) +with expansion: + "E2/V1" == "E2/V1" + +EnumToString.cpp:<line number>: +PASSED: + CHECK( Catch::toString(e3) == "Unknown enum value 10" ) +with expansion: + "Unknown enum value 10" + == + "Unknown enum value 10" + +------------------------------------------------------------------------------- +Some simple comparisons between doubles +------------------------------------------------------------------------------- +ApproxTests.cpp:<line number> +............................................................................... + +ApproxTests.cpp:<line number>: +PASSED: + REQUIRE( d == Approx( 1.23 ) ) +with expansion: + 1.23 == Approx( 1.23 ) + +ApproxTests.cpp:<line number>: +PASSED: + REQUIRE( d != Approx( 1.22 ) ) +with expansion: + 1.23 != Approx( 1.22 ) + +ApproxTests.cpp:<line number>: +PASSED: + REQUIRE( d != Approx( 1.24 ) ) +with expansion: + 1.23 != Approx( 1.24 ) + +ApproxTests.cpp:<line number>: +PASSED: + REQUIRE( Approx( d ) == 1.23 ) +with expansion: + Approx( 1.23 ) == 1.23 + +ApproxTests.cpp:<line number>: +PASSED: + REQUIRE( Approx( d ) != 1.22 ) +with expansion: + Approx( 1.23 ) != 1.22 + +ApproxTests.cpp:<line number>: +PASSED: + REQUIRE( Approx( d ) != 1.24 ) +with expansion: + Approx( 1.23 ) != 1.24 + +------------------------------------------------------------------------------- +Approximate comparisons with different epsilons +------------------------------------------------------------------------------- +ApproxTests.cpp:<line number> +............................................................................... + +ApproxTests.cpp:<line number>: +PASSED: + REQUIRE( d != Approx( 1.231 ) ) +with expansion: + 1.23 != Approx( 1.231 ) + +ApproxTests.cpp:<line number>: +PASSED: + REQUIRE( d == Approx( 1.231 ).epsilon( 0.1 ) ) +with expansion: + 1.23 == Approx( 1.231 ) + +------------------------------------------------------------------------------- +Approximate comparisons with floats +------------------------------------------------------------------------------- +ApproxTests.cpp:<line number> +............................................................................... + +ApproxTests.cpp:<line number>: +PASSED: + REQUIRE( 1.23f == Approx( 1.23f ) ) +with expansion: + 1.23f == Approx( 1.2300000191 ) + +ApproxTests.cpp:<line number>: +PASSED: + REQUIRE( 0.0f == Approx( 0.0f ) ) +with expansion: + 0.0f == Approx( 0.0 ) + +------------------------------------------------------------------------------- +Approximate comparisons with ints +------------------------------------------------------------------------------- +ApproxTests.cpp:<line number> +............................................................................... + +ApproxTests.cpp:<line number>: +PASSED: + REQUIRE( 1 == Approx( 1 ) ) +with expansion: + 1 == Approx( 1.0 ) + +ApproxTests.cpp:<line number>: +PASSED: + REQUIRE( 0 == Approx( 0 ) ) +with expansion: + 0 == Approx( 0.0 ) + +------------------------------------------------------------------------------- +Approximate comparisons with mixed numeric types +------------------------------------------------------------------------------- +ApproxTests.cpp:<line number> +............................................................................... + +ApproxTests.cpp:<line number>: +PASSED: + REQUIRE( 1.0f == Approx( 1 ) ) +with expansion: + 1.0f == Approx( 1.0 ) + +ApproxTests.cpp:<line number>: +PASSED: + REQUIRE( 0 == Approx( dZero) ) +with expansion: + 0 == Approx( 0.0 ) + +ApproxTests.cpp:<line number>: +PASSED: + REQUIRE( 0 == Approx( dSmall ).epsilon( 0.001 ) ) +with expansion: + 0 == Approx( 0.00001 ) + +ApproxTests.cpp:<line number>: +PASSED: + REQUIRE( 1.234f == Approx( dMedium ) ) +with expansion: + 1.234f == Approx( 1.234 ) + +ApproxTests.cpp:<line number>: +PASSED: + REQUIRE( dMedium == Approx( 1.234f ) ) +with expansion: + 1.234 == Approx( 1.2339999676 ) + +------------------------------------------------------------------------------- +Use a custom approx +------------------------------------------------------------------------------- +ApproxTests.cpp:<line number> +............................................................................... + +ApproxTests.cpp:<line number>: +PASSED: + REQUIRE( d == approx( 1.23 ) ) +with expansion: + 1.23 == Approx( 1.23 ) + +ApproxTests.cpp:<line number>: +PASSED: + REQUIRE( d == approx( 1.22 ) ) +with expansion: + 1.23 == Approx( 1.22 ) + +ApproxTests.cpp:<line number>: +PASSED: + REQUIRE( d == approx( 1.24 ) ) +with expansion: + 1.23 == Approx( 1.24 ) + +ApproxTests.cpp:<line number>: +PASSED: + REQUIRE( d != approx( 1.25 ) ) +with expansion: + 1.23 != Approx( 1.25 ) + +ApproxTests.cpp:<line number>: +PASSED: + REQUIRE( approx( d ) == 1.23 ) +with expansion: + Approx( 1.23 ) == 1.23 + +ApproxTests.cpp:<line number>: +PASSED: + REQUIRE( approx( d ) == 1.22 ) +with expansion: + Approx( 1.23 ) == 1.22 + +ApproxTests.cpp:<line number>: +PASSED: + REQUIRE( approx( d ) == 1.24 ) +with expansion: + Approx( 1.23 ) == 1.24 + +ApproxTests.cpp:<line number>: +PASSED: + REQUIRE( approx( d ) != 1.25 ) +with expansion: + Approx( 1.23 ) != 1.25 + +------------------------------------------------------------------------------- +Approximate PI +------------------------------------------------------------------------------- +ApproxTests.cpp:<line number> +............................................................................... + +ApproxTests.cpp:<line number>: +PASSED: + REQUIRE( divide( 22, 7 ) == Approx( 3.141 ).epsilon( 0.001 ) ) +with expansion: + 3.1428571429 == Approx( 3.141 ) + +ApproxTests.cpp:<line number>: +PASSED: + REQUIRE( divide( 22, 7 ) != Approx( 3.141 ).epsilon( 0.0001 ) ) +with expansion: + 3.1428571429 != Approx( 3.141 ) + +------------------------------------------------------------------------------- +A METHOD_AS_TEST_CASE based test run that succeeds +------------------------------------------------------------------------------- +ClassTests.cpp:<line number> +............................................................................... + +ClassTests.cpp:<line number>: +PASSED: + REQUIRE( s == "hello" ) +with expansion: + "hello" == "hello" + +------------------------------------------------------------------------------- +A METHOD_AS_TEST_CASE based test run that fails +------------------------------------------------------------------------------- +ClassTests.cpp:<line number> +............................................................................... + +ClassTests.cpp:<line number>: FAILED: + REQUIRE( s == "world" ) +with expansion: + "hello" == "world" + +------------------------------------------------------------------------------- +A TEST_CASE_METHOD based test run that succeeds +------------------------------------------------------------------------------- +ClassTests.cpp:<line number> +............................................................................... + +ClassTests.cpp:<line number>: +PASSED: + REQUIRE( m_a == 1 ) +with expansion: + 1 == 1 + +------------------------------------------------------------------------------- +A TEST_CASE_METHOD based test run that fails +------------------------------------------------------------------------------- +ClassTests.cpp:<line number> +............................................................................... + +ClassTests.cpp:<line number>: FAILED: + REQUIRE( m_a == 2 ) +with expansion: + 1 == 2 + +------------------------------------------------------------------------------- +Equality checks that should succeed +------------------------------------------------------------------------------- +ConditionTests.cpp:<line number> +............................................................................... + +ConditionTests.cpp:<line number>: +PASSED: + REQUIRE( data.int_seven == 7 ) +with expansion: + 7 == 7 + +ConditionTests.cpp:<line number>: +PASSED: + REQUIRE( data.float_nine_point_one == Approx( 9.1f ) ) +with expansion: + 9.1f == Approx( 9.1000003815 ) + +ConditionTests.cpp:<line number>: +PASSED: + REQUIRE( data.double_pi == Approx( 3.1415926535 ) ) +with expansion: + 3.1415926535 == Approx( 3.1415926535 ) + +ConditionTests.cpp:<line number>: +PASSED: + REQUIRE( data.str_hello == "hello" ) +with expansion: + "hello" == "hello" + +ConditionTests.cpp:<line number>: +PASSED: + REQUIRE( "hello" == data.str_hello ) +with expansion: + "hello" == "hello" + +ConditionTests.cpp:<line number>: +PASSED: + REQUIRE( data.str_hello.size() == 5 ) +with expansion: + 5 == 5 + +ConditionTests.cpp:<line number>: +PASSED: + REQUIRE( x == Approx( 1.3 ) ) +with expansion: + 1.3 == Approx( 1.3 ) + +------------------------------------------------------------------------------- +Equality checks that should fail +------------------------------------------------------------------------------- +ConditionTests.cpp:<line number> +............................................................................... + +ConditionTests.cpp:<line number>: FAILED: + CHECK( data.int_seven == 6 ) +with expansion: + 7 == 6 + +ConditionTests.cpp:<line number>: FAILED: + CHECK( data.int_seven == 8 ) +with expansion: + 7 == 8 + +------------------------------------------------------------------------------- +Inequality checks that should succeed +------------------------------------------------------------------------------- +ConditionTests.cpp:<line number> +............................................................................... + +ConditionTests.cpp:<line number>: +PASSED: + REQUIRE( data.int_seven != 6 ) +with expansion: + 7 != 6 + +ConditionTests.cpp:<line number>: +PASSED: + REQUIRE( data.int_seven != 8 ) +with expansion: + 7 != 8 + +ConditionTests.cpp:<line number>: +PASSED: + REQUIRE( data.float_nine_point_one != Approx( 9.11f ) ) +with expansion: + 9.1f != Approx( 9.1099996567 ) + +ConditionTests.cpp:<line number>: +PASSED: + REQUIRE( data.float_nine_point_one != Approx( 9.0f ) ) +with expansion: + 9.1f != Approx( 9.0 ) + +ConditionTests.cpp:<line number>: +PASSED: + REQUIRE( data.float_nine_point_one != Approx( 1 ) ) +with expansion: + 9.1f != Approx( 1.0 ) + +ConditionTests.cpp:<line number>: +PASSED: + REQUIRE( data.float_nine_point_one != Approx( 0 ) ) +with expansion: + 9.1f != Approx( 0.0 ) + +ConditionTests.cpp:<line number>: +PASSED: + REQUIRE( data.double_pi != Approx( 3.1415 ) ) +with expansion: + 3.1415926535 != Approx( 3.1415 ) + +ConditionTests.cpp:<line number>: +PASSED: + REQUIRE( data.str_hello != "goodbye" ) +with expansion: + "hello" != "goodbye" + +ConditionTests.cpp:<line number>: +PASSED: + REQUIRE( data.str_hello != "hell" ) +with expansion: + "hello" != "hell" + +ConditionTests.cpp:<line number>: +PASSED: + REQUIRE( data.str_hello != "hello1" ) +with expansion: + "hello" != "hello1" + +ConditionTests.cpp:<line number>: +PASSED: + REQUIRE( data.str_hello.size() != 6 ) +with expansion: + 5 != 6 + +------------------------------------------------------------------------------- +Inequality checks that should fail +------------------------------------------------------------------------------- +ConditionTests.cpp:<line number> +............................................................................... + +ConditionTests.cpp:<line number>: FAILED: + CHECK( data.int_seven != 7 ) +with expansion: + 7 != 7 + +ConditionTests.cpp:<line number>: FAILED: + CHECK( data.float_nine_point_one != Approx( 9.1f ) ) +with expansion: + 9.1f != Approx( 9.1000003815 ) + +=============================================================================== +test cases: 19 | 15 passed | 3 failed | 1 failed as expected +assertions: 62 | 56 passed | 4 failed | 2 failed as expected + diff --git a/unittest/Catch/projects/SelfTest/Baselines/junit.sw.approved.txt b/unittest/Catch/projects/SelfTest/Baselines/junit.sw.approved.txt new file mode 100644 index 0000000..110ee8c --- /dev/null +++ b/unittest/Catch/projects/SelfTest/Baselines/junit.sw.approved.txt @@ -0,0 +1,687 @@ +<testsuites> + <testsuite name="CatchSelfTest" errors="13" failures="72" tests="921" hostname="tbd" time="{duration}" timestamp="tbd"> + <testcase classname="global" name="toString(enum)" time="{duration}"/> + <testcase classname="global" name="toString(enum w/operator<<)" time="{duration}"/> + <testcase classname="global" name="toString(enum class)" time="{duration}"/> + <testcase classname="global" name="toString(enum class w/operator<<)" time="{duration}"/> + <testcase classname="global" name="Some simple comparisons between doubles" time="{duration}"/> + <testcase classname="global" name="Approximate comparisons with different epsilons" time="{duration}"/> + <testcase classname="global" name="Approximate comparisons with floats" time="{duration}"/> + <testcase classname="global" name="Approximate comparisons with ints" time="{duration}"/> + <testcase classname="global" name="Approximate comparisons with mixed numeric types" time="{duration}"/> + <testcase classname="global" name="Use a custom approx" time="{duration}"/> + <testcase classname="global" name="Approximate PI" time="{duration}"/> + <testcase classname="TestClass" name="A METHOD_AS_TEST_CASE based test run that succeeds" time="{duration}"/> + <testcase classname="TestClass" name="A METHOD_AS_TEST_CASE based test run that fails" time="{duration}"> + <failure message=""hello" == "world"" type="REQUIRE"> +ClassTests.cpp:<line number> + </failure> + </testcase> + <testcase classname="Fixture" name="A TEST_CASE_METHOD based test run that succeeds" time="{duration}"/> + <testcase classname="Fixture" name="A TEST_CASE_METHOD based test run that fails" time="{duration}"> + <failure message="1 == 2" type="REQUIRE"> +ClassTests.cpp:<line number> + </failure> + </testcase> + <testcase classname="global" name="Equality checks that should succeed" time="{duration}"/> + <testcase classname="global" name="Equality checks that should fail" time="{duration}"> + <failure message="7 == 6" type="CHECK"> +ConditionTests.cpp:<line number> + </failure> + <failure message="7 == 8" type="CHECK"> +ConditionTests.cpp:<line number> + </failure> + <failure message="7 == 0" type="CHECK"> +ConditionTests.cpp:<line number> + </failure> + <failure message="9.1f == Approx( 9.1099996567 )" type="CHECK"> +ConditionTests.cpp:<line number> + </failure> + <failure message="9.1f == Approx( 9.0 )" type="CHECK"> +ConditionTests.cpp:<line number> + </failure> + <failure message="9.1f == Approx( 1.0 )" type="CHECK"> +ConditionTests.cpp:<line number> + </failure> + <failure message="9.1f == Approx( 0.0 )" type="CHECK"> +ConditionTests.cpp:<line number> + </failure> + <failure message="3.1415926535 == Approx( 3.1415 )" type="CHECK"> +ConditionTests.cpp:<line number> + </failure> + <failure message=""hello" == "goodbye"" type="CHECK"> +ConditionTests.cpp:<line number> + </failure> + <failure message=""hello" == "hell"" type="CHECK"> +ConditionTests.cpp:<line number> + </failure> + <failure message=""hello" == "hello1"" type="CHECK"> +ConditionTests.cpp:<line number> + </failure> + <failure message="5 == 6" type="CHECK"> +ConditionTests.cpp:<line number> + </failure> + <failure message="1.3 == Approx( 1.301 )" type="CHECK"> +ConditionTests.cpp:<line number> + </failure> + </testcase> + <testcase classname="global" name="Inequality checks that should succeed" time="{duration}"/> + <testcase classname="global" name="Inequality checks that should fail" time="{duration}"> + <failure message="7 != 7" type="CHECK"> +ConditionTests.cpp:<line number> + </failure> + <failure message="9.1f != Approx( 9.1000003815 )" type="CHECK"> +ConditionTests.cpp:<line number> + </failure> + <failure message="3.1415926535 != Approx( 3.1415926535 )" type="CHECK"> +ConditionTests.cpp:<line number> + </failure> + <failure message=""hello" != "hello"" type="CHECK"> +ConditionTests.cpp:<line number> + </failure> + <failure message="5 != 5" type="CHECK"> +ConditionTests.cpp:<line number> + </failure> + </testcase> + <testcase classname="global" name="Ordering comparison checks that should succeed" time="{duration}"/> + <testcase classname="global" name="Ordering comparison checks that should fail" time="{duration}"> + <failure message="7 > 7" type="CHECK"> +ConditionTests.cpp:<line number> + </failure> + <failure message="7 < 7" type="CHECK"> +ConditionTests.cpp:<line number> + </failure> + <failure message="7 > 8" type="CHECK"> +ConditionTests.cpp:<line number> + </failure> + <failure message="7 < 6" type="CHECK"> +ConditionTests.cpp:<line number> + </failure> + <failure message="7 < 0" type="CHECK"> +ConditionTests.cpp:<line number> + </failure> + <failure message="7 < -1" type="CHECK"> +ConditionTests.cpp:<line number> + </failure> + <failure message="7 >= 8" type="CHECK"> +ConditionTests.cpp:<line number> + </failure> + <failure message="7 <= 6" type="CHECK"> +ConditionTests.cpp:<line number> + </failure> + <failure message="9.1f < 9" type="CHECK"> +ConditionTests.cpp:<line number> + </failure> + <failure message="9.1f > 10" type="CHECK"> +ConditionTests.cpp:<line number> + </failure> + <failure message="9.1f > 9.2" type="CHECK"> +ConditionTests.cpp:<line number> + </failure> + <failure message=""hello" > "hello"" type="CHECK"> +ConditionTests.cpp:<line number> + </failure> + <failure message=""hello" < "hello"" type="CHECK"> +ConditionTests.cpp:<line number> + </failure> + <failure message=""hello" > "hellp"" type="CHECK"> +ConditionTests.cpp:<line number> + </failure> + <failure message=""hello" > "z"" type="CHECK"> +ConditionTests.cpp:<line number> + </failure> + <failure message=""hello" < "hellm"" type="CHECK"> +ConditionTests.cpp:<line number> + </failure> + <failure message=""hello" < "a"" type="CHECK"> +ConditionTests.cpp:<line number> + </failure> + <failure message=""hello" >= "z"" type="CHECK"> +ConditionTests.cpp:<line number> + </failure> + <failure message=""hello" <= "a"" type="CHECK"> +ConditionTests.cpp:<line number> + </failure> + </testcase> + <testcase classname="global" name="Comparisons with int literals don't warn when mixing signed/ unsigned" time="{duration}"/> + <testcase classname="global" name="comparisons between int variables" time="{duration}"/> + <testcase classname="global" name="comparisons between const int variables" time="{duration}"/> + <testcase classname="global" name="Comparisons between unsigned ints and negative signed ints match c++ standard behaviour" time="{duration}"/> + <testcase classname="global" name="Comparisons between ints where one side is computed" time="{duration}"/> + <testcase classname="global" name="Pointers can be compared to null" time="{duration}"/> + <testcase classname="global" name="'Not' checks that should succeed" time="{duration}"/> + <testcase classname="global" name="'Not' checks that should fail" time="{duration}"> + <failure message="false != false" type="CHECK"> +ConditionTests.cpp:<line number> + </failure> + <failure message="true != true" type="CHECK"> +ConditionTests.cpp:<line number> + </failure> + <failure message="false" type="CHECK"> +ConditionTests.cpp:<line number> + </failure> + <failure message="!true" type="CHECK_FALSE"> +ConditionTests.cpp:<line number> + </failure> + <failure message="false" type="CHECK"> +ConditionTests.cpp:<line number> + </failure> + <failure message="!true" type="CHECK_FALSE"> +ConditionTests.cpp:<line number> + </failure> + <failure message="false" type="CHECK"> +ConditionTests.cpp:<line number> + </failure> + <failure message="!(1 == 1)" type="CHECK_FALSE"> +ConditionTests.cpp:<line number> + </failure> + </testcase> + <testcase classname="global" name="When checked exceptions are thrown they can be expected or unexpected" time="{duration}"/> + <testcase classname="global" name="Expected exceptions that don't throw or unexpected exceptions fail the test" time="{duration}"> + <error message="thisThrows()" type="CHECK_THROWS_AS"> +expected exception +ExceptionTests.cpp:<line number> + </error> + <failure message="thisDoesntThrow()" type="CHECK_THROWS_AS"> +ExceptionTests.cpp:<line number> + </failure> + <error message="thisThrows()" type="CHECK_NOTHROW"> +expected exception +ExceptionTests.cpp:<line number> + </error> + </testcase> + <testcase classname="global" name="When unchecked exceptions are thrown directly they are always failures" time="{duration}"> + <error type="TEST_CASE"> +unexpected exception +ExceptionTests.cpp:<line number> + </error> + </testcase> + <testcase classname="global" name="An unchecked exception reports the line of the last assertion" time="{duration}"> + <error message="{Unknown expression after the reported line}"> +unexpected exception +ExceptionTests.cpp:<line number> + </error> + </testcase> + <testcase classname="When unchecked exceptions are thrown from sections they are always failures" name="section name" time="{duration}"> + <error type="TEST_CASE"> +unexpected exception +ExceptionTests.cpp:<line number> + </error> + </testcase> + <testcase classname="global" name="When unchecked exceptions are thrown from functions they are always failures" time="{duration}"> + <error message="thisThrows() == 0" type="CHECK"> +expected exception +ExceptionTests.cpp:<line number> + </error> + </testcase> + <testcase classname="global" name="When unchecked exceptions are thrown during a REQUIRE the test should abort fail" time="{duration}"> + <error message="thisThrows() == 0" type="REQUIRE"> +expected exception +ExceptionTests.cpp:<line number> + </error> + </testcase> + <testcase classname="global" name="When unchecked exceptions are thrown during a CHECK the test should abort and fail" time="{duration}"> + <error message="thisThrows() == 0" type="CHECK"> +expected exception +ExceptionTests.cpp:<line number> + </error> + </testcase> + <testcase classname="global" name="Non-std exceptions can be translated" time="{duration}"> + <error type="TEST_CASE"> +custom exception +ExceptionTests.cpp:<line number> + </error> + </testcase> + <testcase classname="global" name="Custom std-exceptions can be custom translated" time="{duration}"> + <error type="TEST_CASE"> +custom std exception +ExceptionTests.cpp:<line number> + </error> + </testcase> + <testcase classname="global" name="Custom exceptions can be translated when testing for nothrow" time="{duration}"> + <error message="throwCustom()" type="REQUIRE_NOTHROW"> +custom exception - not std +ExceptionTests.cpp:<line number> + </error> + </testcase> + <testcase classname="global" name="Custom exceptions can be translated when testing for throwing as something else" time="{duration}"> + <error message="throwCustom()" type="REQUIRE_THROWS_AS"> +custom exception - not std +ExceptionTests.cpp:<line number> + </error> + </testcase> + <testcase classname="global" name="Unexpected exceptions can be translated" time="{duration}"> + <error type="TEST_CASE"> +3.14 +ExceptionTests.cpp:<line number> + </error> + </testcase> + <testcase classname="global" name="NotImplemented exception" time="{duration}"/> + <testcase classname="Exception messages can be tested for" name="exact match" time="{duration}"/> + <testcase classname="Exception messages can be tested for" name="different case" time="{duration}"/> + <testcase classname="Exception messages can be tested for" name="wildcarded" time="{duration}"/> + <testcase classname="global" name="Mismatching exception messages failing the test" time="{duration}"> + <failure message="expected exception" type="REQUIRE_THROWS_WITH"> +ExceptionTests.cpp:<line number> + </failure> + </testcase> + <testcase classname="global" name="Generators over two ranges" time="{duration}"/> + <testcase classname="global" name="Generator over a range of pairs" time="{duration}"/> + <testcase classname="global" name="INFO and WARN do not abort tests" time="{duration}"/> + <testcase classname="global" name="SUCCEED counts as a test pass" time="{duration}"/> + <testcase classname="global" name="INFO gets logged on failure" time="{duration}"> + <failure message="2 == 1" type="REQUIRE"> +this message should be logged +so should this +MessageTests.cpp:<line number> + </failure> + </testcase> + <testcase classname="global" name="INFO gets logged on failure, even if captured before successful assertions" time="{duration}"> + <failure message="2 == 1" type="CHECK"> +this message should be logged +MessageTests.cpp:<line number> + </failure> + <failure message="2 == 0" type="CHECK"> +and this, but later +MessageTests.cpp:<line number> + </failure> + </testcase> + <testcase classname="global" name="FAIL aborts the test" time="{duration}"> + <failure type="FAIL"> +This is a failure +MessageTests.cpp:<line number> + </failure> + </testcase> + <testcase classname="global" name="FAIL does not require an argument" time="{duration}"> + <failure type="FAIL"> +MessageTests.cpp:<line number> + </failure> + </testcase> + <testcase classname="global" name="SUCCESS does not require an argument" time="{duration}"/> + <testcase classname="Output from all sections is reported" name="one" time="{duration}"> + <failure type="FAIL"> +Message from section one +MessageTests.cpp:<line number> + </failure> + </testcase> + <testcase classname="Output from all sections is reported" name="two" time="{duration}"> + <failure type="FAIL"> +Message from section two +MessageTests.cpp:<line number> + </failure> + </testcase> + <testcase classname="Standard output from all sections is reported" name="two" time="{duration}"> + <system-out> +Message from section one +Message from section two + </system-out> + </testcase> + <testcase classname="global" name="SCOPED_INFO is reset for each loop" time="{duration}"> + <failure message="10 < 10" type="REQUIRE"> +current counter 10 +i := 10 +MessageTests.cpp:<line number> + </failure> + </testcase> + <testcase classname="global" name="The NO_FAIL macro reports a failure but does not fail the test" time="{duration}"/> + <testcase classname="global" name="just failure" time="{duration}"> + <failure type="FAIL"> +Previous info should not be seen +MessageTests.cpp:<line number> + </failure> + </testcase> + <testcase classname="global" name="sends information to INFO" time="{duration}"> + <failure message="false" type="REQUIRE"> +hi +i := 7 +MessageTests.cpp:<line number> + </failure> + </testcase> + <testcase classname="global" name="Pointers can be converted to strings" time="{duration}"/> + <testcase classname="random SECTION tests" name="s1" time="{duration}"/> + <testcase classname="random SECTION tests" name="s2" time="{duration}"/> + <testcase classname="nested SECTION tests" name="s1" time="{duration}"/> + <testcase classname="nested SECTION tests" name="s1/s2" time="{duration}"/> + <testcase classname="more nested SECTION tests" name="s2/s1" time="{duration}"> + <failure message="1 == 2" type="REQUIRE"> +MiscTests.cpp:<line number> + </failure> + </testcase> + <testcase classname="more nested SECTION tests" name="s1/s3" time="{duration}"/> + <testcase classname="more nested SECTION tests" name="s1/s4" time="{duration}"/> + <testcase classname="even more nested SECTION tests" name="c/d (leaf)" time="{duration}"/> + <testcase classname="even more nested SECTION tests" name="c/e (leaf)" time="{duration}"/> + <testcase classname="even more nested SECTION tests" name="f (leaf)" time="{duration}"/> + <testcase classname="looped SECTION tests" name="s1" time="{duration}"> + <failure message="0 > 1" type="CHECK"> +MiscTests.cpp:<line number> + </failure> + </testcase> + <testcase classname="global" name="looped tests" time="{duration}"> + <failure message="1 == 0" type="CHECK"> +Testing if fib[0] (1) is even +MiscTests.cpp:<line number> + </failure> + <failure message="1 == 0" type="CHECK"> +Testing if fib[1] (1) is even +MiscTests.cpp:<line number> + </failure> + <failure message="1 == 0" type="CHECK"> +Testing if fib[3] (3) is even +MiscTests.cpp:<line number> + </failure> + <failure message="1 == 0" type="CHECK"> +Testing if fib[4] (5) is even +MiscTests.cpp:<line number> + </failure> + <failure message="1 == 0" type="CHECK"> +Testing if fib[6] (13) is even +MiscTests.cpp:<line number> + </failure> + <failure message="1 == 0" type="CHECK"> +Testing if fib[7] (21) is even +MiscTests.cpp:<line number> + </failure> + </testcase> + <testcase classname="global" name="Sends stuff to stdout and stderr" time="{duration}"> + <system-out> +A string sent directly to stdout + </system-out> + <system-err> +A string sent directly to stderr + </system-err> + </testcase> + <testcase classname="global" name="null strings" time="{duration}"/> + <testcase classname="global" name="checkedIf" time="{duration}"/> + <testcase classname="global" name="checkedIf, failing" time="{duration}"> + <failure message="false" type="CHECKED_IF"> +MiscTests.cpp:<line number> + </failure> + <failure message="false" type="REQUIRE"> +MiscTests.cpp:<line number> + </failure> + </testcase> + <testcase classname="global" name="checkedElse" time="{duration}"/> + <testcase classname="global" name="checkedElse, failing" time="{duration}"> + <failure message="false" type="CHECKED_ELSE"> +MiscTests.cpp:<line number> + </failure> + <failure message="false" type="REQUIRE"> +MiscTests.cpp:<line number> + </failure> + </testcase> + <testcase classname="xmlentitycheck" name="embedded xml" time="{duration}"/> + <testcase classname="xmlentitycheck" name="encoded chars" time="{duration}"/> + <testcase classname="global" name="send a single char to INFO" time="{duration}"> + <failure message="false" type="REQUIRE"> +3 +MiscTests.cpp:<line number> + </failure> + </testcase> + <testcase classname="global" name="atomic if" time="{duration}"/> + <testcase classname="global" name="String matchers" time="{duration}"/> + <testcase classname="global" name="Contains string matcher" time="{duration}"> + <failure message=""this string contains 'abc' as a substring" contains: "not there"" type="CHECK_THAT"> +MiscTests.cpp:<line number> + </failure> + </testcase> + <testcase classname="global" name="StartsWith string matcher" time="{duration}"> + <failure message=""this string contains 'abc' as a substring" starts with: "string"" type="CHECK_THAT"> +MiscTests.cpp:<line number> + </failure> + </testcase> + <testcase classname="global" name="EndsWith string matcher" time="{duration}"> + <failure message=""this string contains 'abc' as a substring" ends with: "this"" type="CHECK_THAT"> +MiscTests.cpp:<line number> + </failure> + </testcase> + <testcase classname="global" name="Equals string matcher" time="{duration}"> + <failure message=""this string contains 'abc' as a substring" equals: "something else"" type="CHECK_THAT"> +MiscTests.cpp:<line number> + </failure> + </testcase> + <testcase classname="global" name="Equals string matcher, with NULL" time="{duration}"/> + <testcase classname="global" name="AllOf matcher" time="{duration}"/> + <testcase classname="global" name="AnyOf matcher" time="{duration}"/> + <testcase classname="global" name="Equals" time="{duration}"/> + <testcase classname="global" name="Matchers can be (AllOf) composed with the && operator" time="{duration}"/> + <testcase classname="global" name="Matchers can be (AnyOf) composed with the || operator" time="{duration}"/> + <testcase classname="global" name="Matchers can be composed with both && and ||" time="{duration}"/> + <testcase classname="global" name="Matchers can be composed with both && and || - failing" time="{duration}"> + <failure message=""this string contains 'abc' as a substring" ( ( contains: "string" or contains: "different" ) and contains: "random" )" type="CHECK_THAT"> +MiscTests.cpp:<line number> + </failure> + </testcase> + <testcase classname="global" name="Matchers can be negated (Not) with the ! operator" time="{duration}"/> + <testcase classname="global" name="Matchers can be negated (Not) with the ! operator - failing" time="{duration}"> + <failure message=""this string contains 'abc' as a substring" not contains: "substring"" type="CHECK_THAT"> +MiscTests.cpp:<line number> + </failure> + </testcase> + <testcase classname="global" name="Factorials are computed" time="{duration}"/> + <testcase classname="global" name="Nice descriptive name" time="{duration}"/> + <testcase classname="vectors can be sized and resized" name="root" time="{duration}"/> + <testcase classname="vectors can be sized and resized" name="resizing bigger changes size and capacity" time="{duration}"/> + <testcase classname="vectors can be sized and resized" name="resizing smaller changes size but not capacity" time="{duration}"/> + <testcase classname="vectors can be sized and resized" name="resizing smaller changes size but not capacity/We can use the 'swap trick' to reset the capacity" time="{duration}"/> + <testcase classname="vectors can be sized and resized" name="reserving bigger changes capacity but not size" time="{duration}"/> + <testcase classname="vectors can be sized and resized" name="reserving smaller does not change size or capacity" time="{duration}"/> + <testcase classname="A couple of nested sections followed by a failure" name="root" time="{duration}"> + <failure type="FAIL"> +to infinity and beyond +MiscTests.cpp:<line number> + </failure> + </testcase> + <testcase classname="A couple of nested sections followed by a failure" name="Outer/Inner" time="{duration}"/> + <testcase classname="global" name="not allowed" time="{duration}"/> + <testcase classname="global" name="Tabs and newlines show in output" time="{duration}"> + <failure message=""if ($b == 10) { + $a = 20; +}" +== +"if ($b == 10) { + $a = 20; +} +"" type="CHECK"> +MiscTests.cpp:<line number> + </failure> + </testcase> + <testcase classname="global" name="toString on const wchar_t const pointer returns the string contents" time="{duration}"/> + <testcase classname="global" name="toString on const wchar_t pointer returns the string contents" time="{duration}"/> + <testcase classname="global" name="toString on wchar_t const pointer returns the string contents" time="{duration}"/> + <testcase classname="global" name="toString on wchar_t returns the string contents" time="{duration}"/> + <testcase classname="XmlEncode" name="normal string" time="{duration}"/> + <testcase classname="XmlEncode" name="empty string" time="{duration}"/> + <testcase classname="XmlEncode" name="string with ampersand" time="{duration}"/> + <testcase classname="XmlEncode" name="string with less-than" time="{duration}"/> + <testcase classname="XmlEncode" name="string with greater-than" time="{duration}"/> + <testcase classname="XmlEncode" name="string with quotes" time="{duration}"/> + <testcase classname="XmlEncode" name="string with control char (1)" time="{duration}"/> + <testcase classname="XmlEncode" name="string with control char (x7F)" time="{duration}"/> + <testcase classname="global" name="long long" time="{duration}"/> + <testcase classname="Process can be configured on command line" name="default - no arguments" time="{duration}"/> + <testcase classname="Process can be configured on command line" name="test lists/1 test" time="{duration}"/> + <testcase classname="Process can be configured on command line" name="test lists/Specify one test case exclusion using exclude:" time="{duration}"/> + <testcase classname="Process can be configured on command line" name="test lists/Specify one test case exclusion using ~" time="{duration}"/> + <testcase classname="Process can be configured on command line" name="reporter/-r/console" time="{duration}"/> + <testcase classname="Process can be configured on command line" name="reporter/-r/xml" time="{duration}"/> + <testcase classname="Process can be configured on command line" name="reporter/-r xml and junit" time="{duration}"/> + <testcase classname="Process can be configured on command line" name="reporter/--reporter/junit" time="{duration}"/> + <testcase classname="Process can be configured on command line" name="debugger/-b" time="{duration}"/> + <testcase classname="Process can be configured on command line" name="debugger/--break" time="{duration}"/> + <testcase classname="Process can be configured on command line" name="abort/-a aborts after first failure" time="{duration}"/> + <testcase classname="Process can be configured on command line" name="abort/-x 2 aborts after two failures" time="{duration}"/> + <testcase classname="Process can be configured on command line" name="abort/-x must be greater than zero" time="{duration}"/> + <testcase classname="Process can be configured on command line" name="abort/-x must be numeric" time="{duration}"/> + <testcase classname="Process can be configured on command line" name="nothrow/-e" time="{duration}"/> + <testcase classname="Process can be configured on command line" name="nothrow/--nothrow" time="{duration}"/> + <testcase classname="Process can be configured on command line" name="output filename/-o filename" time="{duration}"/> + <testcase classname="Process can be configured on command line" name="output filename/--out" time="{duration}"/> + <testcase classname="Process can be configured on command line" name="combinations/Single character flags can be combined" time="{duration}"/> + <testcase classname="Process can be configured on command line" name="use-colour/without option" time="{duration}"/> + <testcase classname="Process can be configured on command line" name="use-colour/auto" time="{duration}"/> + <testcase classname="Process can be configured on command line" name="use-colour/yes" time="{duration}"/> + <testcase classname="Process can be configured on command line" name="use-colour/no" time="{duration}"/> + <testcase classname="Process can be configured on command line" name="use-colour/error" time="{duration}"/> + <testcase classname="Long strings can be wrapped" name="plain string/No wrapping" time="{duration}"/> + <testcase classname="Long strings can be wrapped" name="plain string/Wrapped once" time="{duration}"/> + <testcase classname="Long strings can be wrapped" name="plain string/Wrapped twice" time="{duration}"/> + <testcase classname="Long strings can be wrapped" name="plain string/Wrapped three times" time="{duration}"/> + <testcase classname="Long strings can be wrapped" name="plain string/Short wrap" time="{duration}"/> + <testcase classname="Long strings can be wrapped" name="plain string/As container" time="{duration}"/> + <testcase classname="Long strings can be wrapped" name="plain string/Indent first line differently" time="{duration}"/> + <testcase classname="Long strings can be wrapped" name="With newlines/No wrapping" time="{duration}"/> + <testcase classname="Long strings can be wrapped" name="With newlines/Trailing newline" time="{duration}"/> + <testcase classname="Long strings can be wrapped" name="With newlines/Wrapped once" time="{duration}"/> + <testcase classname="Long strings can be wrapped" name="With newlines/Wrapped twice" time="{duration}"/> + <testcase classname="Long strings can be wrapped" name="With tabs" time="{duration}"/> + <testcase classname="replaceInPlace" name="replace single char" time="{duration}"/> + <testcase classname="replaceInPlace" name="replace two chars" time="{duration}"/> + <testcase classname="replaceInPlace" name="replace first char" time="{duration}"/> + <testcase classname="replaceInPlace" name="replace last char" time="{duration}"/> + <testcase classname="replaceInPlace" name="replace all chars" time="{duration}"/> + <testcase classname="replaceInPlace" name="replace no chars" time="{duration}"/> + <testcase classname="replaceInPlace" name="escape '" time="{duration}"/> + <testcase classname="global" name="Strings can be rendered with colour" time="{duration}"> + <system-out> +hello +hello + </system-out> + </testcase> + <testcase classname="global" name="Text can be formatted using the Text class" time="{duration}"/> + <testcase classname="global" name="Long text is truncted" time="{duration}"/> + <testcase classname="global" name="ManuallyRegistered" time="{duration}"/> + <testcase classname="global" name="Parsing a std::pair" time="{duration}"/> + <testcase classname="global" name="Where there is more to the expression after the RHS" time="{duration}"/> + <testcase classname="global" name="Where the LHS is not a simple value" time="{duration}"/> + <testcase classname="global" name="A failing expression with a non streamable type is still captured" time="{duration}"> + <failure message="0x<hex digits> == 0x<hex digits>" type="CHECK"> +TrickyTests.cpp:<line number> + </failure> + <failure message="{?} == {?}" type="CHECK"> +TrickyTests.cpp:<line number> + </failure> + </testcase> + <testcase classname="global" name="string literals of different sizes can be compared" time="{duration}"> + <failure message=""first" == "second"" type="REQUIRE"> +TrickyTests.cpp:<line number> + </failure> + </testcase> + <testcase classname="global" name="An expression with side-effects should only be evaluated once" time="{duration}"/> + <testcase classname="global" name="Operators at different namespace levels not hijacked by Koenig lookup" time="{duration}"/> + <testcase classname="global" name="Demonstrate that a non-const == is not used" time="{duration}"/> + <testcase classname="global" name="Test enum bit values" time="{duration}"/> + <testcase classname="global" name="boolean member" time="{duration}"/> + <testcase classname="(unimplemented) static bools can be evaluated" name="compare to true" time="{duration}"/> + <testcase classname="(unimplemented) static bools can be evaluated" name="compare to false" time="{duration}"/> + <testcase classname="(unimplemented) static bools can be evaluated" name="negation" time="{duration}"/> + <testcase classname="(unimplemented) static bools can be evaluated" name="double negation" time="{duration}"/> + <testcase classname="(unimplemented) static bools can be evaluated" name="direct" time="{duration}"/> + <testcase classname="global" name="Objects that evaluated in boolean contexts can be checked" time="{duration}"/> + <testcase classname="Assertions then sections" name="root" time="{duration}"/> + <testcase classname="Assertions then sections" name="A section" time="{duration}"/> + <testcase classname="Assertions then sections" name="A section/Another section" time="{duration}"/> + <testcase classname="Assertions then sections" name="A section/Another other section" time="{duration}"/> + <testcase classname="global" name="non streamable - with conv. op" time="{duration}"/> + <testcase classname="global" name="Comparing function pointers" time="{duration}"/> + <testcase classname="global" name="Comparing member function pointers" time="{duration}"/> + <testcase classname="global" name="pointer to class" time="{duration}"/> + <testcase classname="global" name="null_ptr" time="{duration}"/> + <testcase classname="global" name="X/level/0/a" time="{duration}"/> + <testcase classname="global" name="X/level/0/b" time="{duration}"/> + <testcase classname="global" name="X/level/1/a" time="{duration}"/> + <testcase classname="global" name="X/level/1/b" time="{duration}"/> + <testcase classname="global" name="toString( has_toString )" time="{duration}"/> + <testcase classname="global" name="toString( has_maker )" time="{duration}"/> + <testcase classname="global" name="toString( has_maker_and_toString )" time="{duration}"/> + <testcase classname="global" name="toString( vectors<has_toString )" time="{duration}"/> + <testcase classname="global" name="toString( vectors<has_maker )" time="{duration}"/> + <testcase classname="global" name="toString( vectors<has_maker_and_toString )" time="{duration}"/> + <testcase classname="Tracker" name="root" time="{duration}"/> + <testcase classname="Tracker" name="successfully close one section" time="{duration}"/> + <testcase classname="Tracker" name="fail one section" time="{duration}"/> + <testcase classname="Tracker" name="fail one section/re-enter after failed section" time="{duration}"/> + <testcase classname="Tracker" name="fail one section/re-enter after failed section and find next section" time="{duration}"/> + <testcase classname="Tracker" name="successfully close one section, then find another" time="{duration}"/> + <testcase classname="Tracker" name="successfully close one section, then find another/Re-enter - skips S1 and enters S2" time="{duration}"/> + <testcase classname="Tracker" name="successfully close one section, then find another/Re-enter - skips S1 and enters S2/Successfully close S2" time="{duration}"/> + <testcase classname="Tracker" name="successfully close one section, then find another/Re-enter - skips S1 and enters S2/fail S2" time="{duration}"/> + <testcase classname="Tracker" name="open a nested section" time="{duration}"/> + <testcase classname="Tracker" name="start a generator" time="{duration}"/> + <testcase classname="Tracker" name="start a generator/close outer section" time="{duration}"/> + <testcase classname="Tracker" name="start a generator/close outer section/Re-enter for second generation" time="{duration}"/> + <testcase classname="Tracker" name="start a generator/Start a new inner section" time="{duration}"/> + <testcase classname="Tracker" name="start a generator/Start a new inner section/Re-enter for second generation" time="{duration}"/> + <testcase classname="Tracker" name="start a generator/Fail an inner section" time="{duration}"/> + <testcase classname="Tracker" name="start a generator/Fail an inner section/Re-enter for second generation" time="{duration}"/> + <testcase classname="global" name="std::pair<int,std::string> -> toString" time="{duration}"/> + <testcase classname="global" name="std::pair<int,const std::string> -> toString" time="{duration}"/> + <testcase classname="global" name="std::vector<std::pair<std::string,int> > -> toString" time="{duration}"/> + <testcase classname="global" name="pair<pair<int,const char *,pair<std::string,int> > -> toString" time="{duration}"/> + <testcase classname="global" name="vector<int> -> toString" time="{duration}"/> + <testcase classname="global" name="vector<string> -> toString" time="{duration}"/> + <testcase classname="global" name="vector<int,allocator> -> toString" time="{duration}"/> + <testcase classname="global" name="vec<vec<string,alloc>> -> toString" time="{duration}"/> + <testcase classname="Parse test names and tags" name="Empty test spec should have no filters" time="{duration}"/> + <testcase classname="Parse test names and tags" name="Test spec from empty string should have no filters" time="{duration}"/> + <testcase classname="Parse test names and tags" name="Test spec from just a comma should have no filters" time="{duration}"/> + <testcase classname="Parse test names and tags" name="Test spec from name should have one filter" time="{duration}"/> + <testcase classname="Parse test names and tags" name="Test spec from quoted name should have one filter" time="{duration}"/> + <testcase classname="Parse test names and tags" name="Test spec from name should have one filter" time="{duration}"/> + <testcase classname="Parse test names and tags" name="Wildcard at the start" time="{duration}"/> + <testcase classname="Parse test names and tags" name="Wildcard at the end" time="{duration}"/> + <testcase classname="Parse test names and tags" name="Wildcard at both ends" time="{duration}"/> + <testcase classname="Parse test names and tags" name="Redundant wildcard at the start" time="{duration}"/> + <testcase classname="Parse test names and tags" name="Redundant wildcard at the end" time="{duration}"/> + <testcase classname="Parse test names and tags" name="Redundant wildcard at both ends" time="{duration}"/> + <testcase classname="Parse test names and tags" name="Wildcard at both ends, redundant at start" time="{duration}"/> + <testcase classname="Parse test names and tags" name="Just wildcard" time="{duration}"/> + <testcase classname="Parse test names and tags" name="Single tag" time="{duration}"/> + <testcase classname="Parse test names and tags" name="Single tag, two matches" time="{duration}"/> + <testcase classname="Parse test names and tags" name="Two tags" time="{duration}"/> + <testcase classname="Parse test names and tags" name="Two tags, spare separated" time="{duration}"/> + <testcase classname="Parse test names and tags" name="Wildcarded name and tag" time="{duration}"/> + <testcase classname="Parse test names and tags" name="Single tag exclusion" time="{duration}"/> + <testcase classname="Parse test names and tags" name="One tag exclusion and one tag inclusion" time="{duration}"/> + <testcase classname="Parse test names and tags" name="One tag exclusion and one wldcarded name inclusion" time="{duration}"/> + <testcase classname="Parse test names and tags" name="One tag exclusion, using exclude:, and one wldcarded name inclusion" time="{duration}"/> + <testcase classname="Parse test names and tags" name="name exclusion" time="{duration}"/> + <testcase classname="Parse test names and tags" name="wildcarded name exclusion" time="{duration}"/> + <testcase classname="Parse test names and tags" name="wildcarded name exclusion with tag inclusion" time="{duration}"/> + <testcase classname="Parse test names and tags" name="wildcarded name exclusion, using exclude:, with tag inclusion" time="{duration}"/> + <testcase classname="Parse test names and tags" name="two wildcarded names" time="{duration}"/> + <testcase classname="Parse test names and tags" name="empty tag" time="{duration}"/> + <testcase classname="Parse test names and tags" name="empty quoted name" time="{duration}"/> + <testcase classname="Parse test names and tags" name="quoted string followed by tag exclusion" time="{duration}"/> + <testcase classname="global" name="tuple<>" time="{duration}"/> + <testcase classname="global" name="tuple<int>" time="{duration}"/> + <testcase classname="global" name="tuple<float,int>" time="{duration}"/> + <testcase classname="global" name="tuple<string,string>" time="{duration}"/> + <testcase classname="global" name="tuple<tuple<int>,tuple<>,float>" time="{duration}"/> + <testcase classname="global" name="tuple<nullptr,int,const char *>" time="{duration}"/> + <testcase classname="Tag alias can be registered against tag patterns" name="The same tag alias can only be registered once" time="{duration}"/> + <testcase classname="Tag alias can be registered against tag patterns" name="Tag aliases must be of the form [@name]" time="{duration}"/> + <testcase classname="global" name="Anonymous test case 1" time="{duration}"/> + <testcase classname="global" name="Test case with one argument" time="{duration}"/> + <testcase classname="Variadic macros" name="Section with one argument" time="{duration}"/> + <testcase classname="Scenario: Do that thing with the thing" name="Given: This stuff exists/When: I do this/Then: it should do this" time="{duration}"/> + <testcase classname="Scenario: Do that thing with the thing" name="Given: This stuff exists/When: I do this/Then: it should do this/And: do that" time="{duration}"/> + <testcase classname="Scenario: Vector resizing affects size and capacity" name="Given: an empty vector" time="{duration}"/> + <testcase classname="Scenario: Vector resizing affects size and capacity" name="Given: an empty vector/When: it is made larger/Then: the size and capacity go up" time="{duration}"/> + <testcase classname="Scenario: Vector resizing affects size and capacity" name="Given: an empty vector/When: it is made larger/Then: the size and capacity go up/And when: it is made smaller again/Then: the size goes down but the capacity stays the same" time="{duration}"/> + <testcase classname="Scenario: Vector resizing affects size and capacity" name="Given: an empty vector/When: we reserve more space/Then: The capacity is increased but the size remains the same" time="{duration}"/> + <testcase classname="Scenario: This is a really long scenario name to see how the list command deals with wrapping" name="Given: A section name that is so long that it cannot fit in a single console width/When: The test headers are printed as part of the normal running of the scenario/Then: The, deliberately very long and overly verbose (you see what I did there?) section names must wrap, along with an indent" time="{duration}"/> + <testcase classname="Fixture" name="Scenario: BDD tests requiring Fixtures to provide commonly-accessed data or methods/Given: No operations precede me" time="{duration}"/> + <testcase classname="Fixture" name="Scenario: BDD tests requiring Fixtures to provide commonly-accessed data or methods/Given: No operations precede me/When: We get the count/Then: Subsequently values are higher" time="{duration}"/> + <system-out> +Message from section one +Message from section two +A string sent directly to stdout +hello +hello + </system-out> + <system-err> +A string sent directly to stderr + </system-err> + </testsuite> +</testsuites> diff --git a/unittest/Catch/projects/SelfTest/Baselines/xml.sw.approved.txt b/unittest/Catch/projects/SelfTest/Baselines/xml.sw.approved.txt new file mode 100644 index 0000000..c0af02f --- /dev/null +++ b/unittest/Catch/projects/SelfTest/Baselines/xml.sw.approved.txt @@ -0,0 +1,9569 @@ +<Catch name="CatchSelfTest"> + <Group name="CatchSelfTest"> + <TestCase name="toString(enum)"> + <Expression success="true" type="CHECK" filename="projects/SelfTest/EnumToString.cpp" > + <Original> + Catch::toString(e0) == "0" + </Original> + <Expanded> + "0" == "0" + </Expanded> + </Expression> + <Expression success="true" type="CHECK" filename="projects/SelfTest/EnumToString.cpp" > + <Original> + Catch::toString(e1) == "1" + </Original> + <Expanded> + "1" == "1" + </Expanded> + </Expression> + <OverallResult success="true"/> + </TestCase> + <TestCase name="toString(enum w/operator<<)"> + <Expression success="true" type="CHECK" filename="projects/SelfTest/EnumToString.cpp" > + <Original> + Catch::toString(e0) == "E2{0}" + </Original> + <Expanded> + "E2{0}" == "E2{0}" + </Expanded> + </Expression> + <Expression success="true" type="CHECK" filename="projects/SelfTest/EnumToString.cpp" > + <Original> + Catch::toString(e1) == "E2{1}" + </Original> + <Expanded> + "E2{1}" == "E2{1}" + </Expanded> + </Expression> + <OverallResult success="true"/> + </TestCase> + <TestCase name="toString(enum class)"> + <Expression success="true" type="CHECK" filename="projects/SelfTest/EnumToString.cpp" > + <Original> + Catch::toString(e0) == "0" + </Original> + <Expanded> + "0" == "0" + </Expanded> + </Expression> + <Expression success="true" type="CHECK" filename="projects/SelfTest/EnumToString.cpp" > + <Original> + Catch::toString(e1) == "1" + </Original> + <Expanded> + "1" == "1" + </Expanded> + </Expression> + <OverallResult success="true"/> + </TestCase> + <TestCase name="toString(enum class w/operator<<)"> + <Expression success="true" type="CHECK" filename="projects/SelfTest/EnumToString.cpp" > + <Original> + Catch::toString(e0) == "E2/V0" + </Original> + <Expanded> + "E2/V0" == "E2/V0" + </Expanded> + </Expression> + <Expression success="true" type="CHECK" filename="projects/SelfTest/EnumToString.cpp" > + <Original> + Catch::toString(e1) == "E2/V1" + </Original> + <Expanded> + "E2/V1" == "E2/V1" + </Expanded> + </Expression> + <Expression success="true" type="CHECK" filename="projects/SelfTest/EnumToString.cpp" > + <Original> + Catch::toString(e3) == "Unknown enum value 10" + </Original> + <Expanded> + "Unknown enum value 10" +== +"Unknown enum value 10" + </Expanded> + </Expression> + <OverallResult success="true"/> + </TestCase> + <TestCase name="Some simple comparisons between doubles"> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/ApproxTests.cpp" > + <Original> + d == Approx( 1.23 ) + </Original> + <Expanded> + 1.23 == Approx( 1.23 ) + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/ApproxTests.cpp" > + <Original> + d != Approx( 1.22 ) + </Original> + <Expanded> + 1.23 != Approx( 1.22 ) + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/ApproxTests.cpp" > + <Original> + d != Approx( 1.24 ) + </Original> + <Expanded> + 1.23 != Approx( 1.24 ) + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/ApproxTests.cpp" > + <Original> + Approx( d ) == 1.23 + </Original> + <Expanded> + Approx( 1.23 ) == 1.23 + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/ApproxTests.cpp" > + <Original> + Approx( d ) != 1.22 + </Original> + <Expanded> + Approx( 1.23 ) != 1.22 + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/ApproxTests.cpp" > + <Original> + Approx( d ) != 1.24 + </Original> + <Expanded> + Approx( 1.23 ) != 1.24 + </Expanded> + </Expression> + <OverallResult success="true"/> + </TestCase> + <TestCase name="Approximate comparisons with different epsilons"> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/ApproxTests.cpp" > + <Original> + d != Approx( 1.231 ) + </Original> + <Expanded> + 1.23 != Approx( 1.231 ) + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/ApproxTests.cpp" > + <Original> + d == Approx( 1.231 ).epsilon( 0.1 ) + </Original> + <Expanded> + 1.23 == Approx( 1.231 ) + </Expanded> + </Expression> + <OverallResult success="true"/> + </TestCase> + <TestCase name="Approximate comparisons with floats"> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/ApproxTests.cpp" > + <Original> + 1.23f == Approx( 1.23f ) + </Original> + <Expanded> + 1.23f == Approx( 1.2300000191 ) + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/ApproxTests.cpp" > + <Original> + 0.0f == Approx( 0.0f ) + </Original> + <Expanded> + 0.0f == Approx( 0.0 ) + </Expanded> + </Expression> + <OverallResult success="true"/> + </TestCase> + <TestCase name="Approximate comparisons with ints"> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/ApproxTests.cpp" > + <Original> + 1 == Approx( 1 ) + </Original> + <Expanded> + 1 == Approx( 1.0 ) + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/ApproxTests.cpp" > + <Original> + 0 == Approx( 0 ) + </Original> + <Expanded> + 0 == Approx( 0.0 ) + </Expanded> + </Expression> + <OverallResult success="true"/> + </TestCase> + <TestCase name="Approximate comparisons with mixed numeric types"> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/ApproxTests.cpp" > + <Original> + 1.0f == Approx( 1 ) + </Original> + <Expanded> + 1.0f == Approx( 1.0 ) + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/ApproxTests.cpp" > + <Original> + 0 == Approx( dZero) + </Original> + <Expanded> + 0 == Approx( 0.0 ) + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/ApproxTests.cpp" > + <Original> + 0 == Approx( dSmall ).epsilon( 0.001 ) + </Original> + <Expanded> + 0 == Approx( 0.00001 ) + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/ApproxTests.cpp" > + <Original> + 1.234f == Approx( dMedium ) + </Original> + <Expanded> + 1.234f == Approx( 1.234 ) + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/ApproxTests.cpp" > + <Original> + dMedium == Approx( 1.234f ) + </Original> + <Expanded> + 1.234 == Approx( 1.2339999676 ) + </Expanded> + </Expression> + <OverallResult success="true"/> + </TestCase> + <TestCase name="Use a custom approx"> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/ApproxTests.cpp" > + <Original> + d == approx( 1.23 ) + </Original> + <Expanded> + 1.23 == Approx( 1.23 ) + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/ApproxTests.cpp" > + <Original> + d == approx( 1.22 ) + </Original> + <Expanded> + 1.23 == Approx( 1.22 ) + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/ApproxTests.cpp" > + <Original> + d == approx( 1.24 ) + </Original> + <Expanded> + 1.23 == Approx( 1.24 ) + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/ApproxTests.cpp" > + <Original> + d != approx( 1.25 ) + </Original> + <Expanded> + 1.23 != Approx( 1.25 ) + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/ApproxTests.cpp" > + <Original> + approx( d ) == 1.23 + </Original> + <Expanded> + Approx( 1.23 ) == 1.23 + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/ApproxTests.cpp" > + <Original> + approx( d ) == 1.22 + </Original> + <Expanded> + Approx( 1.23 ) == 1.22 + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/ApproxTests.cpp" > + <Original> + approx( d ) == 1.24 + </Original> + <Expanded> + Approx( 1.23 ) == 1.24 + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/ApproxTests.cpp" > + <Original> + approx( d ) != 1.25 + </Original> + <Expanded> + Approx( 1.23 ) != 1.25 + </Expanded> + </Expression> + <OverallResult success="true"/> + </TestCase> + <TestCase name="Approximate PI"> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/ApproxTests.cpp" > + <Original> + divide( 22, 7 ) == Approx( 3.141 ).epsilon( 0.001 ) + </Original> + <Expanded> + 3.1428571429 == Approx( 3.141 ) + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/ApproxTests.cpp" > + <Original> + divide( 22, 7 ) != Approx( 3.141 ).epsilon( 0.0001 ) + </Original> + <Expanded> + 3.1428571429 != Approx( 3.141 ) + </Expanded> + </Expression> + <OverallResult success="true"/> + </TestCase> + <TestCase name="A METHOD_AS_TEST_CASE based test run that succeeds"> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/ClassTests.cpp" > + <Original> + s == "hello" + </Original> + <Expanded> + "hello" == "hello" + </Expanded> + </Expression> + <OverallResult success="true"/> + </TestCase> + <TestCase name="A METHOD_AS_TEST_CASE based test run that fails"> + <Expression success="false" type="REQUIRE" filename="projects/SelfTest/ClassTests.cpp" > + <Original> + s == "world" + </Original> + <Expanded> + "hello" == "world" + </Expanded> + </Expression> + <OverallResult success="false"/> + </TestCase> + <TestCase name="A TEST_CASE_METHOD based test run that succeeds"> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/ClassTests.cpp" > + <Original> + m_a == 1 + </Original> + <Expanded> + 1 == 1 + </Expanded> + </Expression> + <OverallResult success="true"/> + </TestCase> + <TestCase name="A TEST_CASE_METHOD based test run that fails"> + <Expression success="false" type="REQUIRE" filename="projects/SelfTest/ClassTests.cpp" > + <Original> + m_a == 2 + </Original> + <Expanded> + 1 == 2 + </Expanded> + </Expression> + <OverallResult success="false"/> + </TestCase> + <TestCase name="Equality checks that should succeed"> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/ConditionTests.cpp" > + <Original> + data.int_seven == 7 + </Original> + <Expanded> + 7 == 7 + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/ConditionTests.cpp" > + <Original> + data.float_nine_point_one == Approx( 9.1f ) + </Original> + <Expanded> + 9.1f == Approx( 9.1000003815 ) + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/ConditionTests.cpp" > + <Original> + data.double_pi == Approx( 3.1415926535 ) + </Original> + <Expanded> + 3.1415926535 == Approx( 3.1415926535 ) + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/ConditionTests.cpp" > + <Original> + data.str_hello == "hello" + </Original> + <Expanded> + "hello" == "hello" + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/ConditionTests.cpp" > + <Original> + "hello" == data.str_hello + </Original> + <Expanded> + "hello" == "hello" + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/ConditionTests.cpp" > + <Original> + data.str_hello.size() == 5 + </Original> + <Expanded> + 5 == 5 + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/ConditionTests.cpp" > + <Original> + x == Approx( 1.3 ) + </Original> + <Expanded> + 1.3 == Approx( 1.3 ) + </Expanded> + </Expression> + <OverallResult success="true"/> + </TestCase> + <TestCase name="Equality checks that should fail"> + <Expression success="false" type="CHECK" filename="projects/SelfTest/ConditionTests.cpp" > + <Original> + data.int_seven == 6 + </Original> + <Expanded> + 7 == 6 + </Expanded> + </Expression> + <Expression success="false" type="CHECK" filename="projects/SelfTest/ConditionTests.cpp" > + <Original> + data.int_seven == 8 + </Original> + <Expanded> + 7 == 8 + </Expanded> + </Expression> + <Expression success="false" type="CHECK" filename="projects/SelfTest/ConditionTests.cpp" > + <Original> + data.int_seven == 0 + </Original> + <Expanded> + 7 == 0 + </Expanded> + </Expression> + <Expression success="false" type="CHECK" filename="projects/SelfTest/ConditionTests.cpp" > + <Original> + data.float_nine_point_one == Approx( 9.11f ) + </Original> + <Expanded> + 9.1f == Approx( 9.1099996567 ) + </Expanded> + </Expression> + <Expression success="false" type="CHECK" filename="projects/SelfTest/ConditionTests.cpp" > + <Original> + data.float_nine_point_one == Approx( 9.0f ) + </Original> + <Expanded> + 9.1f == Approx( 9.0 ) + </Expanded> + </Expression> + <Expression success="false" type="CHECK" filename="projects/SelfTest/ConditionTests.cpp" > + <Original> + data.float_nine_point_one == Approx( 1 ) + </Original> + <Expanded> + 9.1f == Approx( 1.0 ) + </Expanded> + </Expression> + <Expression success="false" type="CHECK" filename="projects/SelfTest/ConditionTests.cpp" > + <Original> + data.float_nine_point_one == Approx( 0 ) + </Original> + <Expanded> + 9.1f == Approx( 0.0 ) + </Expanded> + </Expression> + <Expression success="false" type="CHECK" filename="projects/SelfTest/ConditionTests.cpp" > + <Original> + data.double_pi == Approx( 3.1415 ) + </Original> + <Expanded> + 3.1415926535 == Approx( 3.1415 ) + </Expanded> + </Expression> + <Expression success="false" type="CHECK" filename="projects/SelfTest/ConditionTests.cpp" > + <Original> + data.str_hello == "goodbye" + </Original> + <Expanded> + "hello" == "goodbye" + </Expanded> + </Expression> + <Expression success="false" type="CHECK" filename="projects/SelfTest/ConditionTests.cpp" > + <Original> + data.str_hello == "hell" + </Original> + <Expanded> + "hello" == "hell" + </Expanded> + </Expression> + <Expression success="false" type="CHECK" filename="projects/SelfTest/ConditionTests.cpp" > + <Original> + data.str_hello == "hello1" + </Original> + <Expanded> + "hello" == "hello1" + </Expanded> + </Expression> + <Expression success="false" type="CHECK" filename="projects/SelfTest/ConditionTests.cpp" > + <Original> + data.str_hello.size() == 6 + </Original> + <Expanded> + 5 == 6 + </Expanded> + </Expression> + <Expression success="false" type="CHECK" filename="projects/SelfTest/ConditionTests.cpp" > + <Original> + x == Approx( 1.301 ) + </Original> + <Expanded> + 1.3 == Approx( 1.301 ) + </Expanded> + </Expression> + <OverallResult success="true"/> + </TestCase> + <TestCase name="Inequality checks that should succeed"> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/ConditionTests.cpp" > + <Original> + data.int_seven != 6 + </Original> + <Expanded> + 7 != 6 + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/ConditionTests.cpp" > + <Original> + data.int_seven != 8 + </Original> + <Expanded> + 7 != 8 + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/ConditionTests.cpp" > + <Original> + data.float_nine_point_one != Approx( 9.11f ) + </Original> + <Expanded> + 9.1f != Approx( 9.1099996567 ) + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/ConditionTests.cpp" > + <Original> + data.float_nine_point_one != Approx( 9.0f ) + </Original> + <Expanded> + 9.1f != Approx( 9.0 ) + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/ConditionTests.cpp" > + <Original> + data.float_nine_point_one != Approx( 1 ) + </Original> + <Expanded> + 9.1f != Approx( 1.0 ) + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/ConditionTests.cpp" > + <Original> + data.float_nine_point_one != Approx( 0 ) + </Original> + <Expanded> + 9.1f != Approx( 0.0 ) + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/ConditionTests.cpp" > + <Original> + data.double_pi != Approx( 3.1415 ) + </Original> + <Expanded> + 3.1415926535 != Approx( 3.1415 ) + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/ConditionTests.cpp" > + <Original> + data.str_hello != "goodbye" + </Original> + <Expanded> + "hello" != "goodbye" + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/ConditionTests.cpp" > + <Original> + data.str_hello != "hell" + </Original> + <Expanded> + "hello" != "hell" + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/ConditionTests.cpp" > + <Original> + data.str_hello != "hello1" + </Original> + <Expanded> + "hello" != "hello1" + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/ConditionTests.cpp" > + <Original> + data.str_hello.size() != 6 + </Original> + <Expanded> + 5 != 6 + </Expanded> + </Expression> + <OverallResult success="true"/> + </TestCase> + <TestCase name="Inequality checks that should fail"> + <Expression success="false" type="CHECK" filename="projects/SelfTest/ConditionTests.cpp" > + <Original> + data.int_seven != 7 + </Original> + <Expanded> + 7 != 7 + </Expanded> + </Expression> + <Expression success="false" type="CHECK" filename="projects/SelfTest/ConditionTests.cpp" > + <Original> + data.float_nine_point_one != Approx( 9.1f ) + </Original> + <Expanded> + 9.1f != Approx( 9.1000003815 ) + </Expanded> + </Expression> + <Expression success="false" type="CHECK" filename="projects/SelfTest/ConditionTests.cpp" > + <Original> + data.double_pi != Approx( 3.1415926535 ) + </Original> + <Expanded> + 3.1415926535 != Approx( 3.1415926535 ) + </Expanded> + </Expression> + <Expression success="false" type="CHECK" filename="projects/SelfTest/ConditionTests.cpp" > + <Original> + data.str_hello != "hello" + </Original> + <Expanded> + "hello" != "hello" + </Expanded> + </Expression> + <Expression success="false" type="CHECK" filename="projects/SelfTest/ConditionTests.cpp" > + <Original> + data.str_hello.size() != 5 + </Original> + <Expanded> + 5 != 5 + </Expanded> + </Expression> + <OverallResult success="false"/> + </TestCase> + <TestCase name="Ordering comparison checks that should succeed"> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/ConditionTests.cpp" > + <Original> + data.int_seven < 8 + </Original> + <Expanded> + 7 < 8 + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/ConditionTests.cpp" > + <Original> + data.int_seven > 6 + </Original> + <Expanded> + 7 > 6 + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/ConditionTests.cpp" > + <Original> + data.int_seven > 0 + </Original> + <Expanded> + 7 > 0 + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/ConditionTests.cpp" > + <Original> + data.int_seven > -1 + </Original> + <Expanded> + 7 > -1 + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/ConditionTests.cpp" > + <Original> + data.int_seven >= 7 + </Original> + <Expanded> + 7 >= 7 + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/ConditionTests.cpp" > + <Original> + data.int_seven >= 6 + </Original> + <Expanded> + 7 >= 6 + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/ConditionTests.cpp" > + <Original> + data.int_seven <= 7 + </Original> + <Expanded> + 7 <= 7 + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/ConditionTests.cpp" > + <Original> + data.int_seven <= 8 + </Original> + <Expanded> + 7 <= 8 + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/ConditionTests.cpp" > + <Original> + data.float_nine_point_one > 9 + </Original> + <Expanded> + 9.1f > 9 + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/ConditionTests.cpp" > + <Original> + data.float_nine_point_one < 10 + </Original> + <Expanded> + 9.1f < 10 + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/ConditionTests.cpp" > + <Original> + data.float_nine_point_one < 9.2 + </Original> + <Expanded> + 9.1f < 9.2 + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/ConditionTests.cpp" > + <Original> + data.str_hello <= "hello" + </Original> + <Expanded> + "hello" <= "hello" + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/ConditionTests.cpp" > + <Original> + data.str_hello >= "hello" + </Original> + <Expanded> + "hello" >= "hello" + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/ConditionTests.cpp" > + <Original> + data.str_hello < "hellp" + </Original> + <Expanded> + "hello" < "hellp" + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/ConditionTests.cpp" > + <Original> + data.str_hello < "zebra" + </Original> + <Expanded> + "hello" < "zebra" + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/ConditionTests.cpp" > + <Original> + data.str_hello > "hellm" + </Original> + <Expanded> + "hello" > "hellm" + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/ConditionTests.cpp" > + <Original> + data.str_hello > "a" + </Original> + <Expanded> + "hello" > "a" + </Expanded> + </Expression> + <OverallResult success="true"/> + </TestCase> + <TestCase name="Ordering comparison checks that should fail"> + <Expression success="false" type="CHECK" filename="projects/SelfTest/ConditionTests.cpp" > + <Original> + data.int_seven > 7 + </Original> + <Expanded> + 7 > 7 + </Expanded> + </Expression> + <Expression success="false" type="CHECK" filename="projects/SelfTest/ConditionTests.cpp" > + <Original> + data.int_seven < 7 + </Original> + <Expanded> + 7 < 7 + </Expanded> + </Expression> + <Expression success="false" type="CHECK" filename="projects/SelfTest/ConditionTests.cpp" > + <Original> + data.int_seven > 8 + </Original> + <Expanded> + 7 > 8 + </Expanded> + </Expression> + <Expression success="false" type="CHECK" filename="projects/SelfTest/ConditionTests.cpp" > + <Original> + data.int_seven < 6 + </Original> + <Expanded> + 7 < 6 + </Expanded> + </Expression> + <Expression success="false" type="CHECK" filename="projects/SelfTest/ConditionTests.cpp" > + <Original> + data.int_seven < 0 + </Original> + <Expanded> + 7 < 0 + </Expanded> + </Expression> + <Expression success="false" type="CHECK" filename="projects/SelfTest/ConditionTests.cpp" > + <Original> + data.int_seven < -1 + </Original> + <Expanded> + 7 < -1 + </Expanded> + </Expression> + <Expression success="false" type="CHECK" filename="projects/SelfTest/ConditionTests.cpp" > + <Original> + data.int_seven >= 8 + </Original> + <Expanded> + 7 >= 8 + </Expanded> + </Expression> + <Expression success="false" type="CHECK" filename="projects/SelfTest/ConditionTests.cpp" > + <Original> + data.int_seven <= 6 + </Original> + <Expanded> + 7 <= 6 + </Expanded> + </Expression> + <Expression success="false" type="CHECK" filename="projects/SelfTest/ConditionTests.cpp" > + <Original> + data.float_nine_point_one < 9 + </Original> + <Expanded> + 9.1f < 9 + </Expanded> + </Expression> + <Expression success="false" type="CHECK" filename="projects/SelfTest/ConditionTests.cpp" > + <Original> + data.float_nine_point_one > 10 + </Original> + <Expanded> + 9.1f > 10 + </Expanded> + </Expression> + <Expression success="false" type="CHECK" filename="projects/SelfTest/ConditionTests.cpp" > + <Original> + data.float_nine_point_one > 9.2 + </Original> + <Expanded> + 9.1f > 9.2 + </Expanded> + </Expression> + <Expression success="false" type="CHECK" filename="projects/SelfTest/ConditionTests.cpp" > + <Original> + data.str_hello > "hello" + </Original> + <Expanded> + "hello" > "hello" + </Expanded> + </Expression> + <Expression success="false" type="CHECK" filename="projects/SelfTest/ConditionTests.cpp" > + <Original> + data.str_hello < "hello" + </Original> + <Expanded> + "hello" < "hello" + </Expanded> + </Expression> + <Expression success="false" type="CHECK" filename="projects/SelfTest/ConditionTests.cpp" > + <Original> + data.str_hello > "hellp" + </Original> + <Expanded> + "hello" > "hellp" + </Expanded> + </Expression> + <Expression success="false" type="CHECK" filename="projects/SelfTest/ConditionTests.cpp" > + <Original> + data.str_hello > "z" + </Original> + <Expanded> + "hello" > "z" + </Expanded> + </Expression> + <Expression success="false" type="CHECK" filename="projects/SelfTest/ConditionTests.cpp" > + <Original> + data.str_hello < "hellm" + </Original> + <Expanded> + "hello" < "hellm" + </Expanded> + </Expression> + <Expression success="false" type="CHECK" filename="projects/SelfTest/ConditionTests.cpp" > + <Original> + data.str_hello < "a" + </Original> + <Expanded> + "hello" < "a" + </Expanded> + </Expression> + <Expression success="false" type="CHECK" filename="projects/SelfTest/ConditionTests.cpp" > + <Original> + data.str_hello >= "z" + </Original> + <Expanded> + "hello" >= "z" + </Expanded> + </Expression> + <Expression success="false" type="CHECK" filename="projects/SelfTest/ConditionTests.cpp" > + <Original> + data.str_hello <= "a" + </Original> + <Expanded> + "hello" <= "a" + </Expanded> + </Expression> + <OverallResult success="false"/> + </TestCase> + <TestCase name="Comparisons with int literals don't warn when mixing signed/ unsigned"> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/ConditionTests.cpp" > + <Original> + i == 1 + </Original> + <Expanded> + 1 == 1 + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/ConditionTests.cpp" > + <Original> + ui == 2 + </Original> + <Expanded> + 2 == 2 + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/ConditionTests.cpp" > + <Original> + l == 3 + </Original> + <Expanded> + 3 == 3 + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/ConditionTests.cpp" > + <Original> + ul == 4 + </Original> + <Expanded> + 4 == 4 + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/ConditionTests.cpp" > + <Original> + c == 5 + </Original> + <Expanded> + 5 == 5 + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/ConditionTests.cpp" > + <Original> + uc == 6 + </Original> + <Expanded> + 6 == 6 + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/ConditionTests.cpp" > + <Original> + 1 == i + </Original> + <Expanded> + 1 == 1 + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/ConditionTests.cpp" > + <Original> + 2 == ui + </Original> + <Expanded> + 2 == 2 + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/ConditionTests.cpp" > + <Original> + 3 == l + </Original> + <Expanded> + 3 == 3 + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/ConditionTests.cpp" > + <Original> + 4 == ul + </Original> + <Expanded> + 4 == 4 + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/ConditionTests.cpp" > + <Original> + 5 == c + </Original> + <Expanded> + 5 == 5 + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/ConditionTests.cpp" > + <Original> + 6 == uc + </Original> + <Expanded> + 6 == 6 + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/ConditionTests.cpp" > + <Original> + (std::numeric_limits<unsigned long>::max)() > ul + </Original> + <Expanded> + 18446744073709551615 (0x<hex digits>) +> +4 + </Expanded> + </Expression> + <OverallResult success="true"/> + </TestCase> + <TestCase name="comparisons between int variables"> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/ConditionTests.cpp" > + <Original> + long_var == unsigned_char_var + </Original> + <Expanded> + 1 == 1 + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/ConditionTests.cpp" > + <Original> + long_var == unsigned_short_var + </Original> + <Expanded> + 1 == 1 + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/ConditionTests.cpp" > + <Original> + long_var == unsigned_int_var + </Original> + <Expanded> + 1 == 1 + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/ConditionTests.cpp" > + <Original> + long_var == unsigned_long_var + </Original> + <Expanded> + 1 == 1 + </Expanded> + </Expression> + <OverallResult success="true"/> + </TestCase> + <TestCase name="comparisons between const int variables"> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/ConditionTests.cpp" > + <Original> + unsigned_char_var == 1 + </Original> + <Expanded> + 1 == 1 + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/ConditionTests.cpp" > + <Original> + unsigned_short_var == 1 + </Original> + <Expanded> + 1 == 1 + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/ConditionTests.cpp" > + <Original> + unsigned_int_var == 1 + </Original> + <Expanded> + 1 == 1 + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/ConditionTests.cpp" > + <Original> + unsigned_long_var == 1 + </Original> + <Expanded> + 1 == 1 + </Expanded> + </Expression> + <OverallResult success="true"/> + </TestCase> + <TestCase name="Comparisons between unsigned ints and negative signed ints match c++ standard behaviour"> + <Expression success="true" type="CHECK" filename="projects/SelfTest/ConditionTests.cpp" > + <Original> + ( -1 > 2u ) + </Original> + <Expanded> + true + </Expanded> + </Expression> + <Expression success="true" type="CHECK" filename="projects/SelfTest/ConditionTests.cpp" > + <Original> + -1 > 2u + </Original> + <Expanded> + -1 > 2 + </Expanded> + </Expression> + <Expression success="true" type="CHECK" filename="projects/SelfTest/ConditionTests.cpp" > + <Original> + ( 2u < -1 ) + </Original> + <Expanded> + true + </Expanded> + </Expression> + <Expression success="true" type="CHECK" filename="projects/SelfTest/ConditionTests.cpp" > + <Original> + 2u < -1 + </Original> + <Expanded> + 2 < -1 + </Expanded> + </Expression> + <Expression success="true" type="CHECK" filename="projects/SelfTest/ConditionTests.cpp" > + <Original> + ( minInt > 2u ) + </Original> + <Expanded> + true + </Expanded> + </Expression> + <Expression success="true" type="CHECK" filename="projects/SelfTest/ConditionTests.cpp" > + <Original> + minInt > 2u + </Original> + <Expanded> + -2147483648 > 2 + </Expanded> + </Expression> + <OverallResult success="true"/> + </TestCase> + <TestCase name="Comparisons between ints where one side is computed"> + <Expression success="true" type="CHECK" filename="projects/SelfTest/ConditionTests.cpp" > + <Original> + 54 == 6*9 + </Original> + <Expanded> + 54 == 54 + </Expanded> + </Expression> + <OverallResult success="true"/> + </TestCase> + <TestCase name="Pointers can be compared to null"> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/ConditionTests.cpp" > + <Original> + p == nullptr + </Original> + <Expanded> + NULL == nullptr + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/ConditionTests.cpp" > + <Original> + p == pNULL + </Original> + <Expanded> + NULL == NULL + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/ConditionTests.cpp" > + <Original> + p != nullptr + </Original> + <Expanded> + 0x<hex digits> != nullptr + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/ConditionTests.cpp" > + <Original> + cp != nullptr + </Original> + <Expanded> + 0x<hex digits> != nullptr + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/ConditionTests.cpp" > + <Original> + cpc != nullptr + </Original> + <Expanded> + 0x<hex digits> != nullptr + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/ConditionTests.cpp" > + <Original> + returnsNull() == nullptr + </Original> + <Expanded> + {null string} == nullptr + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/ConditionTests.cpp" > + <Original> + returnsConstNull() == nullptr + </Original> + <Expanded> + {null string} == nullptr + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/ConditionTests.cpp" > + <Original> + nullptr != p + </Original> + <Expanded> + nullptr != 0x<hex digits> + </Expanded> + </Expression> + <OverallResult success="true"/> + </TestCase> + <TestCase name="'Not' checks that should succeed"> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/ConditionTests.cpp" > + <Original> + false == false + </Original> + <Expanded> + false == false + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/ConditionTests.cpp" > + <Original> + true == true + </Original> + <Expanded> + true == true + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/ConditionTests.cpp" > + <Original> + !false + </Original> + <Expanded> + true + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE_FALSE" filename="projects/SelfTest/ConditionTests.cpp" > + <Original> + !false + </Original> + <Expanded> + !false + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/ConditionTests.cpp" > + <Original> + !falseValue + </Original> + <Expanded> + true + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE_FALSE" filename="projects/SelfTest/ConditionTests.cpp" > + <Original> + !falseValue + </Original> + <Expanded> + !false + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/ConditionTests.cpp" > + <Original> + !(1 == 2) + </Original> + <Expanded> + true + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE_FALSE" filename="projects/SelfTest/ConditionTests.cpp" > + <Original> + !1 == 2 + </Original> + <Expanded> + !(1 == 2) + </Expanded> + </Expression> + <OverallResult success="true"/> + </TestCase> + <TestCase name="'Not' checks that should fail"> + <Expression success="false" type="CHECK" filename="projects/SelfTest/ConditionTests.cpp" > + <Original> + false != false + </Original> + <Expanded> + false != false + </Expanded> + </Expression> + <Expression success="false" type="CHECK" filename="projects/SelfTest/ConditionTests.cpp" > + <Original> + true != true + </Original> + <Expanded> + true != true + </Expanded> + </Expression> + <Expression success="false" type="CHECK" filename="projects/SelfTest/ConditionTests.cpp" > + <Original> + !true + </Original> + <Expanded> + false + </Expanded> + </Expression> + <Expression success="false" type="CHECK_FALSE" filename="projects/SelfTest/ConditionTests.cpp" > + <Original> + !true + </Original> + <Expanded> + !true + </Expanded> + </Expression> + <Expression success="false" type="CHECK" filename="projects/SelfTest/ConditionTests.cpp" > + <Original> + !trueValue + </Original> + <Expanded> + false + </Expanded> + </Expression> + <Expression success="false" type="CHECK_FALSE" filename="projects/SelfTest/ConditionTests.cpp" > + <Original> + !trueValue + </Original> + <Expanded> + !true + </Expanded> + </Expression> + <Expression success="false" type="CHECK" filename="projects/SelfTest/ConditionTests.cpp" > + <Original> + !(1 == 1) + </Original> + <Expanded> + false + </Expanded> + </Expression> + <Expression success="false" type="CHECK_FALSE" filename="projects/SelfTest/ConditionTests.cpp" > + <Original> + !1 == 1 + </Original> + <Expanded> + !(1 == 1) + </Expanded> + </Expression> + <OverallResult success="false"/> + </TestCase> + <TestCase name="When checked exceptions are thrown they can be expected or unexpected"> + <Expression success="true" type="REQUIRE_THROWS_AS" filename="projects/SelfTest/ExceptionTests.cpp" > + <Original> + thisThrows() + </Original> + <Expanded> + thisThrows() + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE_NOTHROW" filename="projects/SelfTest/ExceptionTests.cpp" > + <Original> + thisDoesntThrow() + </Original> + <Expanded> + thisDoesntThrow() + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE_THROWS" filename="projects/SelfTest/ExceptionTests.cpp" > + <Original> + thisThrows() + </Original> + <Expanded> + thisThrows() + </Expanded> + </Expression> + <OverallResult success="true"/> + </TestCase> + <TestCase name="Expected exceptions that don't throw or unexpected exceptions fail the test"> + <Expression success="false" type="CHECK_THROWS_AS" filename="projects/SelfTest/ExceptionTests.cpp" > + <Original> + thisThrows() + </Original> + <Expanded> + thisThrows() + </Expanded> + <Exception filename="projects/SelfTest/ExceptionTests.cpp" > + expected exception + </Exception> + </Expression> + <Expression success="false" type="CHECK_THROWS_AS" filename="projects/SelfTest/ExceptionTests.cpp" > + <Original> + thisDoesntThrow() + </Original> + <Expanded> + thisDoesntThrow() + </Expanded> + </Expression> + <Expression success="false" type="CHECK_NOTHROW" filename="projects/SelfTest/ExceptionTests.cpp" > + <Original> + thisThrows() + </Original> + <Expanded> + thisThrows() + </Expanded> + <Exception filename="projects/SelfTest/ExceptionTests.cpp" > + expected exception + </Exception> + </Expression> + <OverallResult success="false"/> + </TestCase> + <TestCase name="When unchecked exceptions are thrown directly they are always failures"> + <Exception filename="projects/SelfTest/ExceptionTests.cpp" > + unexpected exception + </Exception> + <OverallResult success="false"/> + </TestCase> + <TestCase name="An unchecked exception reports the line of the last assertion"> + <Expression success="true" type="CHECK" filename="projects/SelfTest/ExceptionTests.cpp" > + <Original> + 1 == 1 + </Original> + <Expanded> + 1 == 1 + </Expanded> + </Expression> + <Expression success="false" filename="projects/SelfTest/ExceptionTests.cpp" > + <Original> + {Unknown expression after the reported line} + </Original> + <Expanded> + {Unknown expression after the reported line} + </Expanded> + <Exception filename="projects/SelfTest/ExceptionTests.cpp" > + unexpected exception + </Exception> + </Expression> + <OverallResult success="false"/> + </TestCase> + <TestCase name="When unchecked exceptions are thrown from sections they are always failures"> + <Section name="section name"> + <Exception filename="projects/SelfTest/ExceptionTests.cpp" > + unexpected exception + </Exception> + <OverallResults successes="0" failures="1" expectedFailures="0"/> + </Section> + <OverallResult success="false"/> + </TestCase> + <TestCase name="When unchecked exceptions are thrown from functions they are always failures"> + <Expression success="false" type="CHECK" filename="projects/SelfTest/ExceptionTests.cpp" > + <Original> + thisThrows() == 0 + </Original> + <Expanded> + thisThrows() == 0 + </Expanded> + <Exception filename="projects/SelfTest/ExceptionTests.cpp" > + expected exception + </Exception> + </Expression> + <OverallResult success="false"/> + </TestCase> + <TestCase name="When unchecked exceptions are thrown during a REQUIRE the test should abort fail"> + <Expression success="false" type="REQUIRE" filename="projects/SelfTest/ExceptionTests.cpp" > + <Original> + thisThrows() == 0 + </Original> + <Expanded> + thisThrows() == 0 + </Expanded> + <Exception filename="projects/SelfTest/ExceptionTests.cpp" > + expected exception + </Exception> + </Expression> + <OverallResult success="false"/> + </TestCase> + <TestCase name="When unchecked exceptions are thrown during a CHECK the test should abort and fail"> + <Expression success="false" type="CHECK" filename="projects/SelfTest/ExceptionTests.cpp" > + <Original> + thisThrows() == 0 + </Original> + <Expanded> + thisThrows() == 0 + </Expanded> + <Exception filename="projects/SelfTest/ExceptionTests.cpp" > + expected exception + </Exception> + </Expression> + <OverallResult success="false"/> + </TestCase> + <TestCase name="When unchecked exceptions are thrown, but caught, they do not affect the test"> + <OverallResult success="true"/> + </TestCase> + <TestCase name="Non-std exceptions can be translated"> + <Exception filename="projects/SelfTest/ExceptionTests.cpp" > + custom exception + </Exception> + <OverallResult success="false"/> + </TestCase> + <TestCase name="Custom std-exceptions can be custom translated"> + <Exception filename="projects/SelfTest/ExceptionTests.cpp" > + custom std exception + </Exception> + <OverallResult success="false"/> + </TestCase> + <TestCase name="Custom exceptions can be translated when testing for nothrow"> + <Expression success="false" type="REQUIRE_NOTHROW" filename="projects/SelfTest/ExceptionTests.cpp" > + <Original> + throwCustom() + </Original> + <Expanded> + throwCustom() + </Expanded> + <Exception filename="projects/SelfTest/ExceptionTests.cpp" > + custom exception - not std + </Exception> + </Expression> + <OverallResult success="false"/> + </TestCase> + <TestCase name="Custom exceptions can be translated when testing for throwing as something else"> + <Expression success="false" type="REQUIRE_THROWS_AS" filename="projects/SelfTest/ExceptionTests.cpp" > + <Original> + throwCustom() + </Original> + <Expanded> + throwCustom() + </Expanded> + <Exception filename="projects/SelfTest/ExceptionTests.cpp" > + custom exception - not std + </Exception> + </Expression> + <OverallResult success="false"/> + </TestCase> + <TestCase name="Unexpected exceptions can be translated"> + <Exception filename="projects/SelfTest/ExceptionTests.cpp" > + 3.14 + </Exception> + <OverallResult success="false"/> + </TestCase> + <TestCase name="NotImplemented exception"> + <Expression success="true" type="REQUIRE_THROWS" filename="projects/SelfTest/ExceptionTests.cpp" > + <Original> + thisFunctionNotImplemented( 7 ) + </Original> + <Expanded> + thisFunctionNotImplemented( 7 ) + </Expanded> + </Expression> + <OverallResult success="true"/> + </TestCase> + <TestCase name="Exception messages can be tested for"> + <Section name="exact match"> + <Expression success="true" type="REQUIRE_THROWS_WITH" filename="projects/SelfTest/ExceptionTests.cpp" > + <Original> + thisThrows(), "expected exception" + </Original> + <Expanded> + thisThrows(), "expected exception" + </Expanded> + </Expression> + <OverallResults successes="1" failures="0" expectedFailures="0"/> + </Section> + <Section name="different case"> + <Expression success="true" type="REQUIRE_THROWS_WITH" filename="projects/SelfTest/ExceptionTests.cpp" > + <Original> + thisThrows(), Equals( "expecteD Exception", Catch::CaseSensitive::No ) + </Original> + <Expanded> + thisThrows(), Equals( "expecteD Exception", Catch::CaseSensitive::No ) + </Expanded> + </Expression> + <OverallResults successes="1" failures="0" expectedFailures="0"/> + </Section> + <Section name="wildcarded"> + <Expression success="true" type="REQUIRE_THROWS_WITH" filename="projects/SelfTest/ExceptionTests.cpp" > + <Original> + thisThrows(), StartsWith( "expected" ) + </Original> + <Expanded> + thisThrows(), StartsWith( "expected" ) + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE_THROWS_WITH" filename="projects/SelfTest/ExceptionTests.cpp" > + <Original> + thisThrows(), EndsWith( "exception" ) + </Original> + <Expanded> + thisThrows(), EndsWith( "exception" ) + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE_THROWS_WITH" filename="projects/SelfTest/ExceptionTests.cpp" > + <Original> + thisThrows(), Contains( "except" ) + </Original> + <Expanded> + thisThrows(), Contains( "except" ) + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE_THROWS_WITH" filename="projects/SelfTest/ExceptionTests.cpp" > + <Original> + thisThrows(), Contains( "exCept", Catch::CaseSensitive::No ) + </Original> + <Expanded> + thisThrows(), Contains( "exCept", Catch::CaseSensitive::No ) + </Expanded> + </Expression> + <OverallResults successes="4" failures="0" expectedFailures="0"/> + </Section> + <OverallResult success="true"/> + </TestCase> + <TestCase name="Mismatching exception messages failing the test"> + <Expression success="true" type="REQUIRE_THROWS_WITH" filename="projects/SelfTest/ExceptionTests.cpp" > + <Original> + thisThrows(), "expected exception" + </Original> + <Expanded> + thisThrows(), "expected exception" + </Expanded> + </Expression> + <Expression success="false" type="REQUIRE_THROWS_WITH" filename="projects/SelfTest/ExceptionTests.cpp" > + <Original> + thisThrows(), "should fail" + </Original> + <Expanded> + expected exception + </Expanded> + </Expression> + <OverallResult success="false"/> + </TestCase> + <TestCase name="Generators over two ranges"> + <Expression success="true" type="CATCH_REQUIRE" filename="projects/SelfTest/GeneratorTests.cpp" > + <Original> + multiply( i, 2 ) == i*2 + </Original> + <Expanded> + 2 == 2 + </Expanded> + </Expression> + <Expression success="true" type="CATCH_REQUIRE" filename="projects/SelfTest/GeneratorTests.cpp" > + <Original> + multiply( j, 2 ) == j*2 + </Original> + <Expanded> + 200 == 200 + </Expanded> + </Expression> + <Expression success="true" type="CATCH_REQUIRE" filename="projects/SelfTest/GeneratorTests.cpp" > + <Original> + multiply( i, 2 ) == i*2 + </Original> + <Expanded> + 4 == 4 + </Expanded> + </Expression> + <Expression success="true" type="CATCH_REQUIRE" filename="projects/SelfTest/GeneratorTests.cpp" > + <Original> + multiply( j, 2 ) == j*2 + </Original> + <Expanded> + 200 == 200 + </Expanded> + </Expression> + <Expression success="true" type="CATCH_REQUIRE" filename="projects/SelfTest/GeneratorTests.cpp" > + <Original> + multiply( i, 2 ) == i*2 + </Original> + <Expanded> + 6 == 6 + </Expanded> + </Expression> + <Expression success="true" type="CATCH_REQUIRE" filename="projects/SelfTest/GeneratorTests.cpp" > + <Original> + multiply( j, 2 ) == j*2 + </Original> + <Expanded> + 200 == 200 + </Expanded> + </Expression> + <Expression success="true" type="CATCH_REQUIRE" filename="projects/SelfTest/GeneratorTests.cpp" > + <Original> + multiply( i, 2 ) == i*2 + </Original> + <Expanded> + 8 == 8 + </Expanded> + </Expression> + <Expression success="true" type="CATCH_REQUIRE" filename="projects/SelfTest/GeneratorTests.cpp" > + <Original> + multiply( j, 2 ) == j*2 + </Original> + <Expanded> + 200 == 200 + </Expanded> + </Expression> + <Expression success="true" type="CATCH_REQUIRE" filename="projects/SelfTest/GeneratorTests.cpp" > + <Original> + multiply( i, 2 ) == i*2 + </Original> + <Expanded> + 10 == 10 + </Expanded> + </Expression> + <Expression success="true" type="CATCH_REQUIRE" filename="projects/SelfTest/GeneratorTests.cpp" > + <Original> + multiply( j, 2 ) == j*2 + </Original> + <Expanded> + 200 == 200 + </Expanded> + </Expression> + <Expression success="true" type="CATCH_REQUIRE" filename="projects/SelfTest/GeneratorTests.cpp" > + <Original> + multiply( i, 2 ) == i*2 + </Original> + <Expanded> + 30 == 30 + </Expanded> + </Expression> + <Expression success="true" type="CATCH_REQUIRE" filename="projects/SelfTest/GeneratorTests.cpp" > + <Original> + multiply( j, 2 ) == j*2 + </Original> + <Expanded> + 200 == 200 + </Expanded> + </Expression> + <Expression success="true" type="CATCH_REQUIRE" filename="projects/SelfTest/GeneratorTests.cpp" > + <Original> + multiply( i, 2 ) == i*2 + </Original> + <Expanded> + 40 == 40 + </Expanded> + </Expression> + <Expression success="true" type="CATCH_REQUIRE" filename="projects/SelfTest/GeneratorTests.cpp" > + <Original> + multiply( j, 2 ) == j*2 + </Original> + <Expanded> + 200 == 200 + </Expanded> + </Expression> + <Expression success="true" type="CATCH_REQUIRE" filename="projects/SelfTest/GeneratorTests.cpp" > + <Original> + multiply( i, 2 ) == i*2 + </Original> + <Expanded> + 42 == 42 + </Expanded> + </Expression> + <Expression success="true" type="CATCH_REQUIRE" filename="projects/SelfTest/GeneratorTests.cpp" > + <Original> + multiply( j, 2 ) == j*2 + </Original> + <Expanded> + 200 == 200 + </Expanded> + </Expression> + <Expression success="true" type="CATCH_REQUIRE" filename="projects/SelfTest/GeneratorTests.cpp" > + <Original> + multiply( i, 2 ) == i*2 + </Original> + <Expanded> + 72 == 72 + </Expanded> + </Expression> + <Expression success="true" type="CATCH_REQUIRE" filename="projects/SelfTest/GeneratorTests.cpp" > + <Original> + multiply( j, 2 ) == j*2 + </Original> + <Expanded> + 200 == 200 + </Expanded> + </Expression> + <Expression success="true" type="CATCH_REQUIRE" filename="projects/SelfTest/GeneratorTests.cpp" > + <Original> + multiply( i, 2 ) == i*2 + </Original> + <Expanded> + 2 == 2 + </Expanded> + </Expression> + <Expression success="true" type="CATCH_REQUIRE" filename="projects/SelfTest/GeneratorTests.cpp" > + <Original> + multiply( j, 2 ) == j*2 + </Original> + <Expanded> + 202 == 202 + </Expanded> + </Expression> + <Expression success="true" type="CATCH_REQUIRE" filename="projects/SelfTest/GeneratorTests.cpp" > + <Original> + multiply( i, 2 ) == i*2 + </Original> + <Expanded> + 4 == 4 + </Expanded> + </Expression> + <Expression success="true" type="CATCH_REQUIRE" filename="projects/SelfTest/GeneratorTests.cpp" > + <Original> + multiply( j, 2 ) == j*2 + </Original> + <Expanded> + 202 == 202 + </Expanded> + </Expression> + <Expression success="true" type="CATCH_REQUIRE" filename="projects/SelfTest/GeneratorTests.cpp" > + <Original> + multiply( i, 2 ) == i*2 + </Original> + <Expanded> + 6 == 6 + </Expanded> + </Expression> + <Expression success="true" type="CATCH_REQUIRE" filename="projects/SelfTest/GeneratorTests.cpp" > + <Original> + multiply( j, 2 ) == j*2 + </Original> + <Expanded> + 202 == 202 + </Expanded> + </Expression> + <Expression success="true" type="CATCH_REQUIRE" filename="projects/SelfTest/GeneratorTests.cpp" > + <Original> + multiply( i, 2 ) == i*2 + </Original> + <Expanded> + 8 == 8 + </Expanded> + </Expression> + <Expression success="true" type="CATCH_REQUIRE" filename="projects/SelfTest/GeneratorTests.cpp" > + <Original> + multiply( j, 2 ) == j*2 + </Original> + <Expanded> + 202 == 202 + </Expanded> + </Expression> + <Expression success="true" type="CATCH_REQUIRE" filename="projects/SelfTest/GeneratorTests.cpp" > + <Original> + multiply( i, 2 ) == i*2 + </Original> + <Expanded> + 10 == 10 + </Expanded> + </Expression> + <Expression success="true" type="CATCH_REQUIRE" filename="projects/SelfTest/GeneratorTests.cpp" > + <Original> + multiply( j, 2 ) == j*2 + </Original> + <Expanded> + 202 == 202 + </Expanded> + </Expression> + <Expression success="true" type="CATCH_REQUIRE" filename="projects/SelfTest/GeneratorTests.cpp" > + <Original> + multiply( i, 2 ) == i*2 + </Original> + <Expanded> + 30 == 30 + </Expanded> + </Expression> + <Expression success="true" type="CATCH_REQUIRE" filename="projects/SelfTest/GeneratorTests.cpp" > + <Original> + multiply( j, 2 ) == j*2 + </Original> + <Expanded> + 202 == 202 + </Expanded> + </Expression> + <Expression success="true" type="CATCH_REQUIRE" filename="projects/SelfTest/GeneratorTests.cpp" > + <Original> + multiply( i, 2 ) == i*2 + </Original> + <Expanded> + 40 == 40 + </Expanded> + </Expression> + <Expression success="true" type="CATCH_REQUIRE" filename="projects/SelfTest/GeneratorTests.cpp" > + <Original> + multiply( j, 2 ) == j*2 + </Original> + <Expanded> + 202 == 202 + </Expanded> + </Expression> + <Expression success="true" type="CATCH_REQUIRE" filename="projects/SelfTest/GeneratorTests.cpp" > + <Original> + multiply( i, 2 ) == i*2 + </Original> + <Expanded> + 42 == 42 + </Expanded> + </Expression> + <Expression success="true" type="CATCH_REQUIRE" filename="projects/SelfTest/GeneratorTests.cpp" > + <Original> + multiply( j, 2 ) == j*2 + </Original> + <Expanded> + 202 == 202 + </Expanded> + </Expression> + <Expression success="true" type="CATCH_REQUIRE" filename="projects/SelfTest/GeneratorTests.cpp" > + <Original> + multiply( i, 2 ) == i*2 + </Original> + <Expanded> + 72 == 72 + </Expanded> + </Expression> + <Expression success="true" type="CATCH_REQUIRE" filename="projects/SelfTest/GeneratorTests.cpp" > + <Original> + multiply( j, 2 ) == j*2 + </Original> + <Expanded> + 202 == 202 + </Expanded> + </Expression> + <Expression success="true" type="CATCH_REQUIRE" filename="projects/SelfTest/GeneratorTests.cpp" > + <Original> + multiply( i, 2 ) == i*2 + </Original> + <Expanded> + 2 == 2 + </Expanded> + </Expression> + <Expression success="true" type="CATCH_REQUIRE" filename="projects/SelfTest/GeneratorTests.cpp" > + <Original> + multiply( j, 2 ) == j*2 + </Original> + <Expanded> + 204 == 204 + </Expanded> + </Expression> + <Expression success="true" type="CATCH_REQUIRE" filename="projects/SelfTest/GeneratorTests.cpp" > + <Original> + multiply( i, 2 ) == i*2 + </Original> + <Expanded> + 4 == 4 + </Expanded> + </Expression> + <Expression success="true" type="CATCH_REQUIRE" filename="projects/SelfTest/GeneratorTests.cpp" > + <Original> + multiply( j, 2 ) == j*2 + </Original> + <Expanded> + 204 == 204 + </Expanded> + </Expression> + <Expression success="true" type="CATCH_REQUIRE" filename="projects/SelfTest/GeneratorTests.cpp" > + <Original> + multiply( i, 2 ) == i*2 + </Original> + <Expanded> + 6 == 6 + </Expanded> + </Expression> + <Expression success="true" type="CATCH_REQUIRE" filename="projects/SelfTest/GeneratorTests.cpp" > + <Original> + multiply( j, 2 ) == j*2 + </Original> + <Expanded> + 204 == 204 + </Expanded> + </Expression> + <Expression success="true" type="CATCH_REQUIRE" filename="projects/SelfTest/GeneratorTests.cpp" > + <Original> + multiply( i, 2 ) == i*2 + </Original> + <Expanded> + 8 == 8 + </Expanded> + </Expression> + <Expression success="true" type="CATCH_REQUIRE" filename="projects/SelfTest/GeneratorTests.cpp" > + <Original> + multiply( j, 2 ) == j*2 + </Original> + <Expanded> + 204 == 204 + </Expanded> + </Expression> + <Expression success="true" type="CATCH_REQUIRE" filename="projects/SelfTest/GeneratorTests.cpp" > + <Original> + multiply( i, 2 ) == i*2 + </Original> + <Expanded> + 10 == 10 + </Expanded> + </Expression> + <Expression success="true" type="CATCH_REQUIRE" filename="projects/SelfTest/GeneratorTests.cpp" > + <Original> + multiply( j, 2 ) == j*2 + </Original> + <Expanded> + 204 == 204 + </Expanded> + </Expression> + <Expression success="true" type="CATCH_REQUIRE" filename="projects/SelfTest/GeneratorTests.cpp" > + <Original> + multiply( i, 2 ) == i*2 + </Original> + <Expanded> + 30 == 30 + </Expanded> + </Expression> + <Expression success="true" type="CATCH_REQUIRE" filename="projects/SelfTest/GeneratorTests.cpp" > + <Original> + multiply( j, 2 ) == j*2 + </Original> + <Expanded> + 204 == 204 + </Expanded> + </Expression> + <Expression success="true" type="CATCH_REQUIRE" filename="projects/SelfTest/GeneratorTests.cpp" > + <Original> + multiply( i, 2 ) == i*2 + </Original> + <Expanded> + 40 == 40 + </Expanded> + </Expression> + <Expression success="true" type="CATCH_REQUIRE" filename="projects/SelfTest/GeneratorTests.cpp" > + <Original> + multiply( j, 2 ) == j*2 + </Original> + <Expanded> + 204 == 204 + </Expanded> + </Expression> + <Expression success="true" type="CATCH_REQUIRE" filename="projects/SelfTest/GeneratorTests.cpp" > + <Original> + multiply( i, 2 ) == i*2 + </Original> + <Expanded> + 42 == 42 + </Expanded> + </Expression> + <Expression success="true" type="CATCH_REQUIRE" filename="projects/SelfTest/GeneratorTests.cpp" > + <Original> + multiply( j, 2 ) == j*2 + </Original> + <Expanded> + 204 == 204 + </Expanded> + </Expression> + <Expression success="true" type="CATCH_REQUIRE" filename="projects/SelfTest/GeneratorTests.cpp" > + <Original> + multiply( i, 2 ) == i*2 + </Original> + <Expanded> + 72 == 72 + </Expanded> + </Expression> + <Expression success="true" type="CATCH_REQUIRE" filename="projects/SelfTest/GeneratorTests.cpp" > + <Original> + multiply( j, 2 ) == j*2 + </Original> + <Expanded> + 204 == 204 + </Expanded> + </Expression> + <Expression success="true" type="CATCH_REQUIRE" filename="projects/SelfTest/GeneratorTests.cpp" > + <Original> + multiply( i, 2 ) == i*2 + </Original> + <Expanded> + 2 == 2 + </Expanded> + </Expression> + <Expression success="true" type="CATCH_REQUIRE" filename="projects/SelfTest/GeneratorTests.cpp" > + <Original> + multiply( j, 2 ) == j*2 + </Original> + <Expanded> + 206 == 206 + </Expanded> + </Expression> + <Expression success="true" type="CATCH_REQUIRE" filename="projects/SelfTest/GeneratorTests.cpp" > + <Original> + multiply( i, 2 ) == i*2 + </Original> + <Expanded> + 4 == 4 + </Expanded> + </Expression> + <Expression success="true" type="CATCH_REQUIRE" filename="projects/SelfTest/GeneratorTests.cpp" > + <Original> + multiply( j, 2 ) == j*2 + </Original> + <Expanded> + 206 == 206 + </Expanded> + </Expression> + <Expression success="true" type="CATCH_REQUIRE" filename="projects/SelfTest/GeneratorTests.cpp" > + <Original> + multiply( i, 2 ) == i*2 + </Original> + <Expanded> + 6 == 6 + </Expanded> + </Expression> + <Expression success="true" type="CATCH_REQUIRE" filename="projects/SelfTest/GeneratorTests.cpp" > + <Original> + multiply( j, 2 ) == j*2 + </Original> + <Expanded> + 206 == 206 + </Expanded> + </Expression> + <Expression success="true" type="CATCH_REQUIRE" filename="projects/SelfTest/GeneratorTests.cpp" > + <Original> + multiply( i, 2 ) == i*2 + </Original> + <Expanded> + 8 == 8 + </Expanded> + </Expression> + <Expression success="true" type="CATCH_REQUIRE" filename="projects/SelfTest/GeneratorTests.cpp" > + <Original> + multiply( j, 2 ) == j*2 + </Original> + <Expanded> + 206 == 206 + </Expanded> + </Expression> + <Expression success="true" type="CATCH_REQUIRE" filename="projects/SelfTest/GeneratorTests.cpp" > + <Original> + multiply( i, 2 ) == i*2 + </Original> + <Expanded> + 10 == 10 + </Expanded> + </Expression> + <Expression success="true" type="CATCH_REQUIRE" filename="projects/SelfTest/GeneratorTests.cpp" > + <Original> + multiply( j, 2 ) == j*2 + </Original> + <Expanded> + 206 == 206 + </Expanded> + </Expression> + <Expression success="true" type="CATCH_REQUIRE" filename="projects/SelfTest/GeneratorTests.cpp" > + <Original> + multiply( i, 2 ) == i*2 + </Original> + <Expanded> + 30 == 30 + </Expanded> + </Expression> + <Expression success="true" type="CATCH_REQUIRE" filename="projects/SelfTest/GeneratorTests.cpp" > + <Original> + multiply( j, 2 ) == j*2 + </Original> + <Expanded> + 206 == 206 + </Expanded> + </Expression> + <Expression success="true" type="CATCH_REQUIRE" filename="projects/SelfTest/GeneratorTests.cpp" > + <Original> + multiply( i, 2 ) == i*2 + </Original> + <Expanded> + 40 == 40 + </Expanded> + </Expression> + <Expression success="true" type="CATCH_REQUIRE" filename="projects/SelfTest/GeneratorTests.cpp" > + <Original> + multiply( j, 2 ) == j*2 + </Original> + <Expanded> + 206 == 206 + </Expanded> + </Expression> + <Expression success="true" type="CATCH_REQUIRE" filename="projects/SelfTest/GeneratorTests.cpp" > + <Original> + multiply( i, 2 ) == i*2 + </Original> + <Expanded> + 42 == 42 + </Expanded> + </Expression> + <Expression success="true" type="CATCH_REQUIRE" filename="projects/SelfTest/GeneratorTests.cpp" > + <Original> + multiply( j, 2 ) == j*2 + </Original> + <Expanded> + 206 == 206 + </Expanded> + </Expression> + <Expression success="true" type="CATCH_REQUIRE" filename="projects/SelfTest/GeneratorTests.cpp" > + <Original> + multiply( i, 2 ) == i*2 + </Original> + <Expanded> + 72 == 72 + </Expanded> + </Expression> + <Expression success="true" type="CATCH_REQUIRE" filename="projects/SelfTest/GeneratorTests.cpp" > + <Original> + multiply( j, 2 ) == j*2 + </Original> + <Expanded> + 206 == 206 + </Expanded> + </Expression> + <Expression success="true" type="CATCH_REQUIRE" filename="projects/SelfTest/GeneratorTests.cpp" > + <Original> + multiply( i, 2 ) == i*2 + </Original> + <Expanded> + 2 == 2 + </Expanded> + </Expression> + <Expression success="true" type="CATCH_REQUIRE" filename="projects/SelfTest/GeneratorTests.cpp" > + <Original> + multiply( j, 2 ) == j*2 + </Original> + <Expanded> + 208 == 208 + </Expanded> + </Expression> + <Expression success="true" type="CATCH_REQUIRE" filename="projects/SelfTest/GeneratorTests.cpp" > + <Original> + multiply( i, 2 ) == i*2 + </Original> + <Expanded> + 4 == 4 + </Expanded> + </Expression> + <Expression success="true" type="CATCH_REQUIRE" filename="projects/SelfTest/GeneratorTests.cpp" > + <Original> + multiply( j, 2 ) == j*2 + </Original> + <Expanded> + 208 == 208 + </Expanded> + </Expression> + <Expression success="true" type="CATCH_REQUIRE" filename="projects/SelfTest/GeneratorTests.cpp" > + <Original> + multiply( i, 2 ) == i*2 + </Original> + <Expanded> + 6 == 6 + </Expanded> + </Expression> + <Expression success="true" type="CATCH_REQUIRE" filename="projects/SelfTest/GeneratorTests.cpp" > + <Original> + multiply( j, 2 ) == j*2 + </Original> + <Expanded> + 208 == 208 + </Expanded> + </Expression> + <Expression success="true" type="CATCH_REQUIRE" filename="projects/SelfTest/GeneratorTests.cpp" > + <Original> + multiply( i, 2 ) == i*2 + </Original> + <Expanded> + 8 == 8 + </Expanded> + </Expression> + <Expression success="true" type="CATCH_REQUIRE" filename="projects/SelfTest/GeneratorTests.cpp" > + <Original> + multiply( j, 2 ) == j*2 + </Original> + <Expanded> + 208 == 208 + </Expanded> + </Expression> + <Expression success="true" type="CATCH_REQUIRE" filename="projects/SelfTest/GeneratorTests.cpp" > + <Original> + multiply( i, 2 ) == i*2 + </Original> + <Expanded> + 10 == 10 + </Expanded> + </Expression> + <Expression success="true" type="CATCH_REQUIRE" filename="projects/SelfTest/GeneratorTests.cpp" > + <Original> + multiply( j, 2 ) == j*2 + </Original> + <Expanded> + 208 == 208 + </Expanded> + </Expression> + <Expression success="true" type="CATCH_REQUIRE" filename="projects/SelfTest/GeneratorTests.cpp" > + <Original> + multiply( i, 2 ) == i*2 + </Original> + <Expanded> + 30 == 30 + </Expanded> + </Expression> + <Expression success="true" type="CATCH_REQUIRE" filename="projects/SelfTest/GeneratorTests.cpp" > + <Original> + multiply( j, 2 ) == j*2 + </Original> + <Expanded> + 208 == 208 + </Expanded> + </Expression> + <Expression success="true" type="CATCH_REQUIRE" filename="projects/SelfTest/GeneratorTests.cpp" > + <Original> + multiply( i, 2 ) == i*2 + </Original> + <Expanded> + 40 == 40 + </Expanded> + </Expression> + <Expression success="true" type="CATCH_REQUIRE" filename="projects/SelfTest/GeneratorTests.cpp" > + <Original> + multiply( j, 2 ) == j*2 + </Original> + <Expanded> + 208 == 208 + </Expanded> + </Expression> + <Expression success="true" type="CATCH_REQUIRE" filename="projects/SelfTest/GeneratorTests.cpp" > + <Original> + multiply( i, 2 ) == i*2 + </Original> + <Expanded> + 42 == 42 + </Expanded> + </Expression> + <Expression success="true" type="CATCH_REQUIRE" filename="projects/SelfTest/GeneratorTests.cpp" > + <Original> + multiply( j, 2 ) == j*2 + </Original> + <Expanded> + 208 == 208 + </Expanded> + </Expression> + <Expression success="true" type="CATCH_REQUIRE" filename="projects/SelfTest/GeneratorTests.cpp" > + <Original> + multiply( i, 2 ) == i*2 + </Original> + <Expanded> + 72 == 72 + </Expanded> + </Expression> + <Expression success="true" type="CATCH_REQUIRE" filename="projects/SelfTest/GeneratorTests.cpp" > + <Original> + multiply( j, 2 ) == j*2 + </Original> + <Expanded> + 208 == 208 + </Expanded> + </Expression> + <Expression success="true" type="CATCH_REQUIRE" filename="projects/SelfTest/GeneratorTests.cpp" > + <Original> + multiply( i, 2 ) == i*2 + </Original> + <Expanded> + 2 == 2 + </Expanded> + </Expression> + <Expression success="true" type="CATCH_REQUIRE" filename="projects/SelfTest/GeneratorTests.cpp" > + <Original> + multiply( j, 2 ) == j*2 + </Original> + <Expanded> + 210 == 210 + </Expanded> + </Expression> + <Expression success="true" type="CATCH_REQUIRE" filename="projects/SelfTest/GeneratorTests.cpp" > + <Original> + multiply( i, 2 ) == i*2 + </Original> + <Expanded> + 4 == 4 + </Expanded> + </Expression> + <Expression success="true" type="CATCH_REQUIRE" filename="projects/SelfTest/GeneratorTests.cpp" > + <Original> + multiply( j, 2 ) == j*2 + </Original> + <Expanded> + 210 == 210 + </Expanded> + </Expression> + <Expression success="true" type="CATCH_REQUIRE" filename="projects/SelfTest/GeneratorTests.cpp" > + <Original> + multiply( i, 2 ) == i*2 + </Original> + <Expanded> + 6 == 6 + </Expanded> + </Expression> + <Expression success="true" type="CATCH_REQUIRE" filename="projects/SelfTest/GeneratorTests.cpp" > + <Original> + multiply( j, 2 ) == j*2 + </Original> + <Expanded> + 210 == 210 + </Expanded> + </Expression> + <Expression success="true" type="CATCH_REQUIRE" filename="projects/SelfTest/GeneratorTests.cpp" > + <Original> + multiply( i, 2 ) == i*2 + </Original> + <Expanded> + 8 == 8 + </Expanded> + </Expression> + <Expression success="true" type="CATCH_REQUIRE" filename="projects/SelfTest/GeneratorTests.cpp" > + <Original> + multiply( j, 2 ) == j*2 + </Original> + <Expanded> + 210 == 210 + </Expanded> + </Expression> + <Expression success="true" type="CATCH_REQUIRE" filename="projects/SelfTest/GeneratorTests.cpp" > + <Original> + multiply( i, 2 ) == i*2 + </Original> + <Expanded> + 10 == 10 + </Expanded> + </Expression> + <Expression success="true" type="CATCH_REQUIRE" filename="projects/SelfTest/GeneratorTests.cpp" > + <Original> + multiply( j, 2 ) == j*2 + </Original> + <Expanded> + 210 == 210 + </Expanded> + </Expression> + <Expression success="true" type="CATCH_REQUIRE" filename="projects/SelfTest/GeneratorTests.cpp" > + <Original> + multiply( i, 2 ) == i*2 + </Original> + <Expanded> + 30 == 30 + </Expanded> + </Expression> + <Expression success="true" type="CATCH_REQUIRE" filename="projects/SelfTest/GeneratorTests.cpp" > + <Original> + multiply( j, 2 ) == j*2 + </Original> + <Expanded> + 210 == 210 + </Expanded> + </Expression> + <Expression success="true" type="CATCH_REQUIRE" filename="projects/SelfTest/GeneratorTests.cpp" > + <Original> + multiply( i, 2 ) == i*2 + </Original> + <Expanded> + 40 == 40 + </Expanded> + </Expression> + <Expression success="true" type="CATCH_REQUIRE" filename="projects/SelfTest/GeneratorTests.cpp" > + <Original> + multiply( j, 2 ) == j*2 + </Original> + <Expanded> + 210 == 210 + </Expanded> + </Expression> + <Expression success="true" type="CATCH_REQUIRE" filename="projects/SelfTest/GeneratorTests.cpp" > + <Original> + multiply( i, 2 ) == i*2 + </Original> + <Expanded> + 42 == 42 + </Expanded> + </Expression> + <Expression success="true" type="CATCH_REQUIRE" filename="projects/SelfTest/GeneratorTests.cpp" > + <Original> + multiply( j, 2 ) == j*2 + </Original> + <Expanded> + 210 == 210 + </Expanded> + </Expression> + <Expression success="true" type="CATCH_REQUIRE" filename="projects/SelfTest/GeneratorTests.cpp" > + <Original> + multiply( i, 2 ) == i*2 + </Original> + <Expanded> + 72 == 72 + </Expanded> + </Expression> + <Expression success="true" type="CATCH_REQUIRE" filename="projects/SelfTest/GeneratorTests.cpp" > + <Original> + multiply( j, 2 ) == j*2 + </Original> + <Expanded> + 210 == 210 + </Expanded> + </Expression> + <Expression success="true" type="CATCH_REQUIRE" filename="projects/SelfTest/GeneratorTests.cpp" > + <Original> + multiply( i, 2 ) == i*2 + </Original> + <Expanded> + 2 == 2 + </Expanded> + </Expression> + <Expression success="true" type="CATCH_REQUIRE" filename="projects/SelfTest/GeneratorTests.cpp" > + <Original> + multiply( j, 2 ) == j*2 + </Original> + <Expanded> + 212 == 212 + </Expanded> + </Expression> + <Expression success="true" type="CATCH_REQUIRE" filename="projects/SelfTest/GeneratorTests.cpp" > + <Original> + multiply( i, 2 ) == i*2 + </Original> + <Expanded> + 4 == 4 + </Expanded> + </Expression> + <Expression success="true" type="CATCH_REQUIRE" filename="projects/SelfTest/GeneratorTests.cpp" > + <Original> + multiply( j, 2 ) == j*2 + </Original> + <Expanded> + 212 == 212 + </Expanded> + </Expression> + <Expression success="true" type="CATCH_REQUIRE" filename="projects/SelfTest/GeneratorTests.cpp" > + <Original> + multiply( i, 2 ) == i*2 + </Original> + <Expanded> + 6 == 6 + </Expanded> + </Expression> + <Expression success="true" type="CATCH_REQUIRE" filename="projects/SelfTest/GeneratorTests.cpp" > + <Original> + multiply( j, 2 ) == j*2 + </Original> + <Expanded> + 212 == 212 + </Expanded> + </Expression> + <Expression success="true" type="CATCH_REQUIRE" filename="projects/SelfTest/GeneratorTests.cpp" > + <Original> + multiply( i, 2 ) == i*2 + </Original> + <Expanded> + 8 == 8 + </Expanded> + </Expression> + <Expression success="true" type="CATCH_REQUIRE" filename="projects/SelfTest/GeneratorTests.cpp" > + <Original> + multiply( j, 2 ) == j*2 + </Original> + <Expanded> + 212 == 212 + </Expanded> + </Expression> + <Expression success="true" type="CATCH_REQUIRE" filename="projects/SelfTest/GeneratorTests.cpp" > + <Original> + multiply( i, 2 ) == i*2 + </Original> + <Expanded> + 10 == 10 + </Expanded> + </Expression> + <Expression success="true" type="CATCH_REQUIRE" filename="projects/SelfTest/GeneratorTests.cpp" > + <Original> + multiply( j, 2 ) == j*2 + </Original> + <Expanded> + 212 == 212 + </Expanded> + </Expression> + <Expression success="true" type="CATCH_REQUIRE" filename="projects/SelfTest/GeneratorTests.cpp" > + <Original> + multiply( i, 2 ) == i*2 + </Original> + <Expanded> + 30 == 30 + </Expanded> + </Expression> + <Expression success="true" type="CATCH_REQUIRE" filename="projects/SelfTest/GeneratorTests.cpp" > + <Original> + multiply( j, 2 ) == j*2 + </Original> + <Expanded> + 212 == 212 + </Expanded> + </Expression> + <Expression success="true" type="CATCH_REQUIRE" filename="projects/SelfTest/GeneratorTests.cpp" > + <Original> + multiply( i, 2 ) == i*2 + </Original> + <Expanded> + 40 == 40 + </Expanded> + </Expression> + <Expression success="true" type="CATCH_REQUIRE" filename="projects/SelfTest/GeneratorTests.cpp" > + <Original> + multiply( j, 2 ) == j*2 + </Original> + <Expanded> + 212 == 212 + </Expanded> + </Expression> + <Expression success="true" type="CATCH_REQUIRE" filename="projects/SelfTest/GeneratorTests.cpp" > + <Original> + multiply( i, 2 ) == i*2 + </Original> + <Expanded> + 42 == 42 + </Expanded> + </Expression> + <Expression success="true" type="CATCH_REQUIRE" filename="projects/SelfTest/GeneratorTests.cpp" > + <Original> + multiply( j, 2 ) == j*2 + </Original> + <Expanded> + 212 == 212 + </Expanded> + </Expression> + <Expression success="true" type="CATCH_REQUIRE" filename="projects/SelfTest/GeneratorTests.cpp" > + <Original> + multiply( i, 2 ) == i*2 + </Original> + <Expanded> + 72 == 72 + </Expanded> + </Expression> + <Expression success="true" type="CATCH_REQUIRE" filename="projects/SelfTest/GeneratorTests.cpp" > + <Original> + multiply( j, 2 ) == j*2 + </Original> + <Expanded> + 212 == 212 + </Expanded> + </Expression> + <Expression success="true" type="CATCH_REQUIRE" filename="projects/SelfTest/GeneratorTests.cpp" > + <Original> + multiply( i, 2 ) == i*2 + </Original> + <Expanded> + 2 == 2 + </Expanded> + </Expression> + <Expression success="true" type="CATCH_REQUIRE" filename="projects/SelfTest/GeneratorTests.cpp" > + <Original> + multiply( j, 2 ) == j*2 + </Original> + <Expanded> + 214 == 214 + </Expanded> + </Expression> + <Expression success="true" type="CATCH_REQUIRE" filename="projects/SelfTest/GeneratorTests.cpp" > + <Original> + multiply( i, 2 ) == i*2 + </Original> + <Expanded> + 4 == 4 + </Expanded> + </Expression> + <Expression success="true" type="CATCH_REQUIRE" filename="projects/SelfTest/GeneratorTests.cpp" > + <Original> + multiply( j, 2 ) == j*2 + </Original> + <Expanded> + 214 == 214 + </Expanded> + </Expression> + <Expression success="true" type="CATCH_REQUIRE" filename="projects/SelfTest/GeneratorTests.cpp" > + <Original> + multiply( i, 2 ) == i*2 + </Original> + <Expanded> + 6 == 6 + </Expanded> + </Expression> + <Expression success="true" type="CATCH_REQUIRE" filename="projects/SelfTest/GeneratorTests.cpp" > + <Original> + multiply( j, 2 ) == j*2 + </Original> + <Expanded> + 214 == 214 + </Expanded> + </Expression> + <Expression success="true" type="CATCH_REQUIRE" filename="projects/SelfTest/GeneratorTests.cpp" > + <Original> + multiply( i, 2 ) == i*2 + </Original> + <Expanded> + 8 == 8 + </Expanded> + </Expression> + <Expression success="true" type="CATCH_REQUIRE" filename="projects/SelfTest/GeneratorTests.cpp" > + <Original> + multiply( j, 2 ) == j*2 + </Original> + <Expanded> + 214 == 214 + </Expanded> + </Expression> + <Expression success="true" type="CATCH_REQUIRE" filename="projects/SelfTest/GeneratorTests.cpp" > + <Original> + multiply( i, 2 ) == i*2 + </Original> + <Expanded> + 10 == 10 + </Expanded> + </Expression> + <Expression success="true" type="CATCH_REQUIRE" filename="projects/SelfTest/GeneratorTests.cpp" > + <Original> + multiply( j, 2 ) == j*2 + </Original> + <Expanded> + 214 == 214 + </Expanded> + </Expression> + <Expression success="true" type="CATCH_REQUIRE" filename="projects/SelfTest/GeneratorTests.cpp" > + <Original> + multiply( i, 2 ) == i*2 + </Original> + <Expanded> + 30 == 30 + </Expanded> + </Expression> + <Expression success="true" type="CATCH_REQUIRE" filename="projects/SelfTest/GeneratorTests.cpp" > + <Original> + multiply( j, 2 ) == j*2 + </Original> + <Expanded> + 214 == 214 + </Expanded> + </Expression> + <Expression success="true" type="CATCH_REQUIRE" filename="projects/SelfTest/GeneratorTests.cpp" > + <Original> + multiply( i, 2 ) == i*2 + </Original> + <Expanded> + 40 == 40 + </Expanded> + </Expression> + <Expression success="true" type="CATCH_REQUIRE" filename="projects/SelfTest/GeneratorTests.cpp" > + <Original> + multiply( j, 2 ) == j*2 + </Original> + <Expanded> + 214 == 214 + </Expanded> + </Expression> + <Expression success="true" type="CATCH_REQUIRE" filename="projects/SelfTest/GeneratorTests.cpp" > + <Original> + multiply( i, 2 ) == i*2 + </Original> + <Expanded> + 42 == 42 + </Expanded> + </Expression> + <Expression success="true" type="CATCH_REQUIRE" filename="projects/SelfTest/GeneratorTests.cpp" > + <Original> + multiply( j, 2 ) == j*2 + </Original> + <Expanded> + 214 == 214 + </Expanded> + </Expression> + <Expression success="true" type="CATCH_REQUIRE" filename="projects/SelfTest/GeneratorTests.cpp" > + <Original> + multiply( i, 2 ) == i*2 + </Original> + <Expanded> + 72 == 72 + </Expanded> + </Expression> + <Expression success="true" type="CATCH_REQUIRE" filename="projects/SelfTest/GeneratorTests.cpp" > + <Original> + multiply( j, 2 ) == j*2 + </Original> + <Expanded> + 214 == 214 + </Expanded> + </Expression> + <OverallResult success="true"/> + </TestCase> + <TestCase name="Generator over a range of pairs"> + <Expression success="true" type="CATCH_REQUIRE" filename="projects/SelfTest/GeneratorTests.cpp" > + <Original> + i->first == i->second-1 + </Original> + <Expanded> + 0 == 0 + </Expanded> + </Expression> + <Expression success="true" type="CATCH_REQUIRE" filename="projects/SelfTest/GeneratorTests.cpp" > + <Original> + i->first == i->second-1 + </Original> + <Expanded> + 2 == 2 + </Expanded> + </Expression> + <OverallResult success="true"/> + </TestCase> + <TestCase name="INFO and WARN do not abort tests"> + <Info> + this is a message + </Info> + <Warning> + this is a warning + </Warning> + <OverallResult success="true"/> + </TestCase> + <TestCase name="SUCCEED counts as a test pass"> + <OverallResult success="true"/> + </TestCase> + <TestCase name="INFO gets logged on failure"> + <Info> + this message should be logged + </Info> + <Info> + so should this + </Info> + <Expression success="false" type="REQUIRE" filename="projects/SelfTest/MessageTests.cpp" > + <Original> + a == 1 + </Original> + <Expanded> + 2 == 1 + </Expanded> + </Expression> + <OverallResult success="false"/> + </TestCase> + <TestCase name="INFO gets logged on failure, even if captured before successful assertions"> + <Expression success="true" type="CHECK" filename="projects/SelfTest/MessageTests.cpp" > + <Original> + a == 2 + </Original> + <Expanded> + 2 == 2 + </Expanded> + </Expression> + <Info> + this message should be logged + </Info> + <Expression success="false" type="CHECK" filename="projects/SelfTest/MessageTests.cpp" > + <Original> + a == 1 + </Original> + <Expanded> + 2 == 1 + </Expanded> + </Expression> + <Info> + and this, but later + </Info> + <Expression success="false" type="CHECK" filename="projects/SelfTest/MessageTests.cpp" > + <Original> + a == 0 + </Original> + <Expanded> + 2 == 0 + </Expanded> + </Expression> + <Expression success="true" type="CHECK" filename="projects/SelfTest/MessageTests.cpp" > + <Original> + a == 2 + </Original> + <Expanded> + 2 == 2 + </Expanded> + </Expression> + <OverallResult success="false"/> + </TestCase> + <TestCase name="FAIL aborts the test"> + <Failure> + This is a failure + </Failure> + <OverallResult success="false"/> + </TestCase> + <TestCase name="FAIL does not require an argument"> + <Failure/> + <OverallResult success="false"/> + </TestCase> + <TestCase name="SUCCESS does not require an argument"> + <OverallResult success="true"/> + </TestCase> + <TestCase name="Output from all sections is reported"> + <Section name="one"> + <Failure> + Message from section one + </Failure> + <OverallResults successes="0" failures="1" expectedFailures="0"/> + </Section> + <Section name="two"> + <Failure> + Message from section two + </Failure> + <OverallResults successes="0" failures="1" expectedFailures="0"/> + </Section> + <OverallResult success="false"/> + </TestCase> + <TestCase name="Standard output from all sections is reported"> + <Section name="one"> + <OverallResults successes="0" failures="1" expectedFailures="0"/> + </Section> + <Section name="two"> + <OverallResults successes="0" failures="1" expectedFailures="0"/> + </Section> + <OverallResult success="false"/> + </TestCase> + <TestCase name="SCOPED_INFO is reset for each loop"> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/MessageTests.cpp" > + <Original> + i < 10 + </Original> + <Expanded> + 0 < 10 + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/MessageTests.cpp" > + <Original> + i < 10 + </Original> + <Expanded> + 1 < 10 + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/MessageTests.cpp" > + <Original> + i < 10 + </Original> + <Expanded> + 2 < 10 + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/MessageTests.cpp" > + <Original> + i < 10 + </Original> + <Expanded> + 3 < 10 + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/MessageTests.cpp" > + <Original> + i < 10 + </Original> + <Expanded> + 4 < 10 + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/MessageTests.cpp" > + <Original> + i < 10 + </Original> + <Expanded> + 5 < 10 + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/MessageTests.cpp" > + <Original> + i < 10 + </Original> + <Expanded> + 6 < 10 + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/MessageTests.cpp" > + <Original> + i < 10 + </Original> + <Expanded> + 7 < 10 + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/MessageTests.cpp" > + <Original> + i < 10 + </Original> + <Expanded> + 8 < 10 + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/MessageTests.cpp" > + <Original> + i < 10 + </Original> + <Expanded> + 9 < 10 + </Expanded> + </Expression> + <Info> + current counter 10 + </Info> + <Info> + i := 10 + </Info> + <Expression success="false" type="REQUIRE" filename="projects/SelfTest/MessageTests.cpp" > + <Original> + i < 10 + </Original> + <Expanded> + 10 < 10 + </Expanded> + </Expression> + <OverallResult success="false"/> + </TestCase> + <TestCase name="The NO_FAIL macro reports a failure but does not fail the test"> + <Expression success="false" type="CHECK_NOFAIL" filename="projects/SelfTest/MessageTests.cpp" > + <Original> + 1 == 2 + </Original> + <Expanded> + 1 == 2 + </Expanded> + </Expression> + <OverallResult success="true"/> + </TestCase> + <TestCase name="just info"> + <OverallResult success="true"/> + </TestCase> + <TestCase name="just failure"> + <Failure> + Previous info should not be seen + </Failure> + <OverallResult success="false"/> + </TestCase> + <TestCase name="sends information to INFO"> + <Info> + hi + </Info> + <Info> + i := 7 + </Info> + <Expression success="false" type="REQUIRE" filename="projects/SelfTest/MessageTests.cpp" > + <Original> + false + </Original> + <Expanded> + false + </Expanded> + </Expression> + <OverallResult success="false"/> + </TestCase> + <TestCase name="Pointers can be converted to strings"> + <Warning> + actual address of p: 0x<hex digits> + </Warning> + <Warning> + toString(p): 0x<hex digits> + </Warning> + <OverallResult success="true"/> + </TestCase> + <TestCase name="random SECTION tests"> + <Section name="s1" description="doesn't equal"> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/MiscTests.cpp" > + <Original> + a != b + </Original> + <Expanded> + 1 != 2 + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/MiscTests.cpp" > + <Original> + b != a + </Original> + <Expanded> + 2 != 1 + </Expanded> + </Expression> + <OverallResults successes="2" failures="0" expectedFailures="0"/> + </Section> + <Section name="s2" description="not equal"> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/MiscTests.cpp" > + <Original> + a != b + </Original> + <Expanded> + 1 != 2 + </Expanded> + </Expression> + <OverallResults successes="1" failures="0" expectedFailures="0"/> + </Section> + <OverallResult success="true"/> + </TestCase> + <TestCase name="nested SECTION tests"> + <Section name="s1" description="doesn't equal"> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/MiscTests.cpp" > + <Original> + a != b + </Original> + <Expanded> + 1 != 2 + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/MiscTests.cpp" > + <Original> + b != a + </Original> + <Expanded> + 2 != 1 + </Expanded> + </Expression> + <Section name="s2" description="not equal"> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/MiscTests.cpp" > + <Original> + a != b + </Original> + <Expanded> + 1 != 2 + </Expanded> + </Expression> + <OverallResults successes="1" failures="0" expectedFailures="0"/> + </Section> + <OverallResults successes="3" failures="0" expectedFailures="0"/> + </Section> + <OverallResult success="true"/> + </TestCase> + <TestCase name="more nested SECTION tests"> + <Section name="s1" description="doesn't equal"> + <Section name="s2" description="equal"> + <Expression success="false" type="REQUIRE" filename="projects/SelfTest/MiscTests.cpp" > + <Original> + a == b + </Original> + <Expanded> + 1 == 2 + </Expanded> + </Expression> + <OverallResults successes="0" failures="1" expectedFailures="0"/> + </Section> + <OverallResults successes="0" failures="1" expectedFailures="0"/> + </Section> + <Section name="s1" description="doesn't equal"> + <Section name="s3" description="not equal"> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/MiscTests.cpp" > + <Original> + a != b + </Original> + <Expanded> + 1 != 2 + </Expanded> + </Expression> + <OverallResults successes="1" failures="0" expectedFailures="0"/> + </Section> + <OverallResults successes="1" failures="0" expectedFailures="0"/> + </Section> + <Section name="s1" description="doesn't equal"> + <Section name="s4" description="less than"> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/MiscTests.cpp" > + <Original> + a < b + </Original> + <Expanded> + 1 < 2 + </Expanded> + </Expression> + <OverallResults successes="1" failures="0" expectedFailures="0"/> + </Section> + <OverallResults successes="1" failures="0" expectedFailures="0"/> + </Section> + <OverallResult success="false"/> + </TestCase> + <TestCase name="even more nested SECTION tests"> + <Section name="c"> + <Section name="d (leaf)"> + <OverallResults successes="1" failures="0" expectedFailures="0"/> + </Section> + <OverallResults successes="1" failures="0" expectedFailures="0"/> + </Section> + <Section name="c"> + <Section name="e (leaf)"> + <OverallResults successes="1" failures="0" expectedFailures="0"/> + </Section> + <OverallResults successes="1" failures="0" expectedFailures="0"/> + </Section> + <Section name="f (leaf)"> + <OverallResults successes="1" failures="0" expectedFailures="0"/> + </Section> + <OverallResult success="true"/> + </TestCase> + <TestCase name="looped SECTION tests"> + <Section name="s1" description="b is currently: 0"> + <Expression success="false" type="CHECK" filename="projects/SelfTest/MiscTests.cpp" > + <Original> + b > a + </Original> + <Expanded> + 0 > 1 + </Expanded> + </Expression> + <OverallResults successes="0" failures="1" expectedFailures="0"/> + </Section> + <OverallResult success="false"/> + </TestCase> + <TestCase name="looped tests"> + <Info> + Testing if fib[0] (1) is even + </Info> + <Expression success="false" type="CHECK" filename="projects/SelfTest/MiscTests.cpp" > + <Original> + ( fib[i] % 2 ) == 0 + </Original> + <Expanded> + 1 == 0 + </Expanded> + </Expression> + <Info> + Testing if fib[1] (1) is even + </Info> + <Expression success="false" type="CHECK" filename="projects/SelfTest/MiscTests.cpp" > + <Original> + ( fib[i] % 2 ) == 0 + </Original> + <Expanded> + 1 == 0 + </Expanded> + </Expression> + <Expression success="true" type="CHECK" filename="projects/SelfTest/MiscTests.cpp" > + <Original> + ( fib[i] % 2 ) == 0 + </Original> + <Expanded> + 0 == 0 + </Expanded> + </Expression> + <Info> + Testing if fib[3] (3) is even + </Info> + <Expression success="false" type="CHECK" filename="projects/SelfTest/MiscTests.cpp" > + <Original> + ( fib[i] % 2 ) == 0 + </Original> + <Expanded> + 1 == 0 + </Expanded> + </Expression> + <Info> + Testing if fib[4] (5) is even + </Info> + <Expression success="false" type="CHECK" filename="projects/SelfTest/MiscTests.cpp" > + <Original> + ( fib[i] % 2 ) == 0 + </Original> + <Expanded> + 1 == 0 + </Expanded> + </Expression> + <Expression success="true" type="CHECK" filename="projects/SelfTest/MiscTests.cpp" > + <Original> + ( fib[i] % 2 ) == 0 + </Original> + <Expanded> + 0 == 0 + </Expanded> + </Expression> + <Info> + Testing if fib[6] (13) is even + </Info> + <Expression success="false" type="CHECK" filename="projects/SelfTest/MiscTests.cpp" > + <Original> + ( fib[i] % 2 ) == 0 + </Original> + <Expanded> + 1 == 0 + </Expanded> + </Expression> + <Info> + Testing if fib[7] (21) is even + </Info> + <Expression success="false" type="CHECK" filename="projects/SelfTest/MiscTests.cpp" > + <Original> + ( fib[i] % 2 ) == 0 + </Original> + <Expanded> + 1 == 0 + </Expanded> + </Expression> + <OverallResult success="false"/> + </TestCase> + <TestCase name="Sends stuff to stdout and stderr"> + <OverallResult success="true"/> + </TestCase> + <TestCase name="null strings"> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/MiscTests.cpp" > + <Original> + makeString( false ) != static_cast<char*>(nullptr) + </Original> + <Expanded> + "valid string" != {null string} + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/MiscTests.cpp" > + <Original> + makeString( true ) == static_cast<char*>(nullptr) + </Original> + <Expanded> + {null string} == {null string} + </Expanded> + </Expression> + <OverallResult success="true"/> + </TestCase> + <TestCase name="checkedIf"> + <Expression success="true" type="CHECKED_IF" filename="projects/SelfTest/MiscTests.cpp" > + <Original> + flag + </Original> + <Expanded> + true + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/MiscTests.cpp" > + <Original> + testCheckedIf( true ) + </Original> + <Expanded> + true + </Expanded> + </Expression> + <OverallResult success="true"/> + </TestCase> + <TestCase name="checkedIf, failing"> + <Expression success="false" type="CHECKED_IF" filename="projects/SelfTest/MiscTests.cpp" > + <Original> + flag + </Original> + <Expanded> + false + </Expanded> + </Expression> + <Expression success="false" type="REQUIRE" filename="projects/SelfTest/MiscTests.cpp" > + <Original> + testCheckedIf( false ) + </Original> + <Expanded> + false + </Expanded> + </Expression> + <OverallResult success="false"/> + </TestCase> + <TestCase name="checkedElse"> + <Expression success="true" type="CHECKED_ELSE" filename="projects/SelfTest/MiscTests.cpp" > + <Original> + flag + </Original> + <Expanded> + true + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/MiscTests.cpp" > + <Original> + testCheckedElse( true ) + </Original> + <Expanded> + true + </Expanded> + </Expression> + <OverallResult success="true"/> + </TestCase> + <TestCase name="checkedElse, failing"> + <Expression success="false" type="CHECKED_ELSE" filename="projects/SelfTest/MiscTests.cpp" > + <Original> + flag + </Original> + <Expanded> + false + </Expanded> + </Expression> + <Expression success="false" type="REQUIRE" filename="projects/SelfTest/MiscTests.cpp" > + <Original> + testCheckedElse( false ) + </Original> + <Expanded> + false + </Expanded> + </Expression> + <OverallResult success="false"/> + </TestCase> + <TestCase name="xmlentitycheck"> + <Section name="embedded xml" description="<test>it should be possible to embed xml characters, such as <, " or &, or even whole <xml>documents</xml> within an attribute</test>"> + <OverallResults successes="1" failures="0" expectedFailures="0"/> + </Section> + <Section name="encoded chars" description="these should all be encoded: &&&"""<<<&"<<&""> + <OverallResults successes="1" failures="0" expectedFailures="0"/> + </Section> + <OverallResult success="true"/> + </TestCase> + <TestCase name="send a single char to INFO"> + <Info> + 3 + </Info> + <Expression success="false" type="REQUIRE" filename="projects/SelfTest/MiscTests.cpp" > + <Original> + false + </Original> + <Expanded> + false + </Expanded> + </Expression> + <OverallResult success="false"/> + </TestCase> + <TestCase name="atomic if"> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/MiscTests.cpp" > + <Original> + x == 0 + </Original> + <Expanded> + 0 == 0 + </Expanded> + </Expression> + <OverallResult success="true"/> + </TestCase> + <TestCase name="String matchers"> + <Expression success="true" type="REQUIRE_THAT" filename="projects/SelfTest/MiscTests.cpp" > + <Original> + testStringForMatching(), Contains( "string" ) + </Original> + <Expanded> + "this string contains 'abc' as a substring" contains: "string" + </Expanded> + </Expression> + <Expression success="true" type="CHECK_THAT" filename="projects/SelfTest/MiscTests.cpp" > + <Original> + testStringForMatching(), Contains( "abc" ) + </Original> + <Expanded> + "this string contains 'abc' as a substring" contains: "abc" + </Expanded> + </Expression> + <Expression success="true" type="CHECK_THAT" filename="projects/SelfTest/MiscTests.cpp" > + <Original> + testStringForMatching(), StartsWith( "this" ) + </Original> + <Expanded> + "this string contains 'abc' as a substring" starts with: "this" + </Expanded> + </Expression> + <Expression success="true" type="CHECK_THAT" filename="projects/SelfTest/MiscTests.cpp" > + <Original> + testStringForMatching(), EndsWith( "substring" ) + </Original> + <Expanded> + "this string contains 'abc' as a substring" ends with: "substring" + </Expanded> + </Expression> + <OverallResult success="true"/> + </TestCase> + <TestCase name="Contains string matcher"> + <Expression success="false" type="CHECK_THAT" filename="projects/SelfTest/MiscTests.cpp" > + <Original> + testStringForMatching(), Contains( "not there" ) + </Original> + <Expanded> + "this string contains 'abc' as a substring" contains: "not there" + </Expanded> + </Expression> + <OverallResult success="false"/> + </TestCase> + <TestCase name="StartsWith string matcher"> + <Expression success="false" type="CHECK_THAT" filename="projects/SelfTest/MiscTests.cpp" > + <Original> + testStringForMatching(), StartsWith( "string" ) + </Original> + <Expanded> + "this string contains 'abc' as a substring" starts with: "string" + </Expanded> + </Expression> + <OverallResult success="false"/> + </TestCase> + <TestCase name="EndsWith string matcher"> + <Expression success="false" type="CHECK_THAT" filename="projects/SelfTest/MiscTests.cpp" > + <Original> + testStringForMatching(), EndsWith( "this" ) + </Original> + <Expanded> + "this string contains 'abc' as a substring" ends with: "this" + </Expanded> + </Expression> + <OverallResult success="false"/> + </TestCase> + <TestCase name="Equals string matcher"> + <Expression success="false" type="CHECK_THAT" filename="projects/SelfTest/MiscTests.cpp" > + <Original> + testStringForMatching(), Equals( "something else" ) + </Original> + <Expanded> + "this string contains 'abc' as a substring" equals: "something else" + </Expanded> + </Expression> + <OverallResult success="false"/> + </TestCase> + <TestCase name="Equals string matcher, with NULL"> + <Expression success="true" type="REQUIRE_THAT" filename="projects/SelfTest/MiscTests.cpp" > + <Original> + "", Equals(nullptr) + </Original> + <Expanded> + "" equals: "" + </Expanded> + </Expression> + <OverallResult success="true"/> + </TestCase> + <TestCase name="AllOf matcher"> + <Expression success="true" type="CHECK_THAT" filename="projects/SelfTest/MiscTests.cpp" > + <Original> + testStringForMatching(), AllOf( Catch::Contains( "string" ), Catch::Contains( "abc" ) ) + </Original> + <Expanded> + "this string contains 'abc' as a substring" ( contains: "string" and contains: "abc" ) + </Expanded> + </Expression> + <OverallResult success="true"/> + </TestCase> + <TestCase name="AnyOf matcher"> + <Expression success="true" type="CHECK_THAT" filename="projects/SelfTest/MiscTests.cpp" > + <Original> + testStringForMatching(), AnyOf( Catch::Contains( "string" ), Catch::Contains( "not there" ) ) + </Original> + <Expanded> + "this string contains 'abc' as a substring" ( contains: "string" or contains: "not there" ) + </Expanded> + </Expression> + <Expression success="true" type="CHECK_THAT" filename="projects/SelfTest/MiscTests.cpp" > + <Original> + testStringForMatching(), AnyOf( Catch::Contains( "not there" ), Catch::Contains( "string" ) ) + </Original> + <Expanded> + "this string contains 'abc' as a substring" ( contains: "not there" or contains: "string" ) + </Expanded> + </Expression> + <OverallResult success="true"/> + </TestCase> + <TestCase name="Equals"> + <Expression success="true" type="CHECK_THAT" filename="projects/SelfTest/MiscTests.cpp" > + <Original> + testStringForMatching(), Equals( "this string contains 'abc' as a substring" ) + </Original> + <Expanded> + "this string contains 'abc' as a substring" equals: "this string contains 'abc' as a substring" + </Expanded> + </Expression> + <OverallResult success="true"/> + </TestCase> + <TestCase name="Matchers can be (AllOf) composed with the && operator"> + <Expression success="true" type="CHECK_THAT" filename="projects/SelfTest/MiscTests.cpp" > + <Original> + testStringForMatching(), Contains( "string" ) && Contains( "abc" ) && Contains( "substring" ) && Contains( "contains" ) + </Original> + <Expanded> + "this string contains 'abc' as a substring" ( contains: "string" and contains: "abc" and contains: "substring" and contains: "contains" ) + </Expanded> + </Expression> + <OverallResult success="true"/> + </TestCase> + <TestCase name="Matchers can be (AnyOf) composed with the || operator"> + <Expression success="true" type="CHECK_THAT" filename="projects/SelfTest/MiscTests.cpp" > + <Original> + testStringForMatching(), Contains( "string" ) || Contains( "different" ) || Contains( "random" ) + </Original> + <Expanded> + "this string contains 'abc' as a substring" ( contains: "string" or contains: "different" or contains: "random" ) + </Expanded> + </Expression> + <Expression success="true" type="CHECK_THAT" filename="projects/SelfTest/MiscTests.cpp" > + <Original> + testStringForMatching2(), Contains( "string" ) || Contains( "different" ) || Contains( "random" ) + </Original> + <Expanded> + "some completely different text that contains one common word" ( contains: "string" or contains: "different" or contains: "random" ) + </Expanded> + </Expression> + <OverallResult success="true"/> + </TestCase> + <TestCase name="Matchers can be composed with both && and ||"> + <Expression success="true" type="CHECK_THAT" filename="projects/SelfTest/MiscTests.cpp" > + <Original> + testStringForMatching(), ( Contains( "string" ) || Contains( "different" ) ) && Contains( "substring" ) + </Original> + <Expanded> + "this string contains 'abc' as a substring" ( ( contains: "string" or contains: "different" ) and contains: "substring" ) + </Expanded> + </Expression> + <OverallResult success="true"/> + </TestCase> + <TestCase name="Matchers can be composed with both && and || - failing"> + <Expression success="false" type="CHECK_THAT" filename="projects/SelfTest/MiscTests.cpp" > + <Original> + testStringForMatching(), ( Contains( "string" ) || Contains( "different" ) ) && Contains( "random" ) + </Original> + <Expanded> + "this string contains 'abc' as a substring" ( ( contains: "string" or contains: "different" ) and contains: "random" ) + </Expanded> + </Expression> + <OverallResult success="false"/> + </TestCase> + <TestCase name="Matchers can be negated (Not) with the ! operator"> + <Expression success="true" type="CHECK_THAT" filename="projects/SelfTest/MiscTests.cpp" > + <Original> + testStringForMatching(), !Contains( "different" ) + </Original> + <Expanded> + "this string contains 'abc' as a substring" not contains: "different" + </Expanded> + </Expression> + <OverallResult success="true"/> + </TestCase> + <TestCase name="Matchers can be negated (Not) with the ! operator - failing"> + <Expression success="false" type="CHECK_THAT" filename="projects/SelfTest/MiscTests.cpp" > + <Original> + testStringForMatching(), !Contains( "substring" ) + </Original> + <Expanded> + "this string contains 'abc' as a substring" not contains: "substring" + </Expanded> + </Expression> + <OverallResult success="false"/> + </TestCase> + <TestCase name="Factorials are computed"> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/MiscTests.cpp" > + <Original> + Factorial(0) == 1 + </Original> + <Expanded> + 1 == 1 + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/MiscTests.cpp" > + <Original> + Factorial(1) == 1 + </Original> + <Expanded> + 1 == 1 + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/MiscTests.cpp" > + <Original> + Factorial(2) == 2 + </Original> + <Expanded> + 2 == 2 + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/MiscTests.cpp" > + <Original> + Factorial(3) == 6 + </Original> + <Expanded> + 6 == 6 + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/MiscTests.cpp" > + <Original> + Factorial(10) == 3628800 + </Original> + <Expanded> + 3628800 (0x<hex digits>) == 3628800 (0x<hex digits>) + </Expanded> + </Expression> + <OverallResult success="true"/> + </TestCase> + <TestCase name="An empty test with no assertions"> + <OverallResult success="true"/> + </TestCase> + <TestCase name="Nice descriptive name"> + <Warning> + This one ran + </Warning> + <OverallResult success="true"/> + </TestCase> + <TestCase name="first tag"> + <OverallResult success="true"/> + </TestCase> + <TestCase name="second tag"> + <OverallResult success="true"/> + </TestCase> + <TestCase name="vectors can be sized and resized"> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/MiscTests.cpp" > + <Original> + v.size() == 5 + </Original> + <Expanded> + 5 == 5 + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/MiscTests.cpp" > + <Original> + v.capacity() >= 5 + </Original> + <Expanded> + 5 >= 5 + </Expanded> + </Expression> + <Section name="resizing bigger changes size and capacity"> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/MiscTests.cpp" > + <Original> + v.size() == 10 + </Original> + <Expanded> + 10 == 10 + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/MiscTests.cpp" > + <Original> + v.capacity() >= 10 + </Original> + <Expanded> + 10 >= 10 + </Expanded> + </Expression> + <OverallResults successes="2" failures="0" expectedFailures="0"/> + </Section> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/MiscTests.cpp" > + <Original> + v.size() == 5 + </Original> + <Expanded> + 5 == 5 + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/MiscTests.cpp" > + <Original> + v.capacity() >= 5 + </Original> + <Expanded> + 5 >= 5 + </Expanded> + </Expression> + <Section name="resizing smaller changes size but not capacity"> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/MiscTests.cpp" > + <Original> + v.size() == 0 + </Original> + <Expanded> + 0 == 0 + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/MiscTests.cpp" > + <Original> + v.capacity() >= 5 + </Original> + <Expanded> + 5 >= 5 + </Expanded> + </Expression> + <Section name="We can use the 'swap trick' to reset the capacity"> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/MiscTests.cpp" > + <Original> + v.capacity() == 0 + </Original> + <Expanded> + 0 == 0 + </Expanded> + </Expression> + <OverallResults successes="1" failures="0" expectedFailures="0"/> + </Section> + <OverallResults successes="3" failures="0" expectedFailures="0"/> + </Section> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/MiscTests.cpp" > + <Original> + v.size() == 5 + </Original> + <Expanded> + 5 == 5 + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/MiscTests.cpp" > + <Original> + v.capacity() >= 5 + </Original> + <Expanded> + 5 >= 5 + </Expanded> + </Expression> + <Section name="reserving bigger changes capacity but not size"> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/MiscTests.cpp" > + <Original> + v.size() == 5 + </Original> + <Expanded> + 5 == 5 + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/MiscTests.cpp" > + <Original> + v.capacity() >= 10 + </Original> + <Expanded> + 10 >= 10 + </Expanded> + </Expression> + <OverallResults successes="2" failures="0" expectedFailures="0"/> + </Section> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/MiscTests.cpp" > + <Original> + v.size() == 5 + </Original> + <Expanded> + 5 == 5 + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/MiscTests.cpp" > + <Original> + v.capacity() >= 5 + </Original> + <Expanded> + 5 >= 5 + </Expanded> + </Expression> + <Section name="reserving smaller does not change size or capacity"> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/MiscTests.cpp" > + <Original> + v.size() == 5 + </Original> + <Expanded> + 5 == 5 + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/MiscTests.cpp" > + <Original> + v.capacity() >= 5 + </Original> + <Expanded> + 5 >= 5 + </Expanded> + </Expression> + <OverallResults successes="2" failures="0" expectedFailures="0"/> + </Section> + <OverallResult success="true"/> + </TestCase> + <TestCase name="A couple of nested sections followed by a failure"> + <Section name="Outer"> + <Section name="Inner"> + <OverallResults successes="1" failures="0" expectedFailures="0"/> + </Section> + <OverallResults successes="1" failures="0" expectedFailures="0"/> + </Section> + <Failure> + to infinity and beyond + </Failure> + <OverallResult success="false"/> + </TestCase> + <TestCase name="not allowed"> + <OverallResult success="true"/> + </TestCase> + <TestCase name="Tabs and newlines show in output"> + <Expression success="false" type="CHECK" filename="projects/SelfTest/MiscTests.cpp" > + <Original> + s1 == s2 + </Original> + <Expanded> + "if ($b == 10) { + $a = 20; +}" +== +"if ($b == 10) { + $a = 20; +} +" + </Expanded> + </Expression> + <OverallResult success="false"/> + </TestCase> + <TestCase name="toString on const wchar_t const pointer returns the string contents"> + <Expression success="true" type="CHECK" filename="projects/SelfTest/MiscTests.cpp" > + <Original> + result == "\"wide load\"" + </Original> + <Expanded> + ""wide load"" == ""wide load"" + </Expanded> + </Expression> + <OverallResult success="true"/> + </TestCase> + <TestCase name="toString on const wchar_t pointer returns the string contents"> + <Expression success="true" type="CHECK" filename="projects/SelfTest/MiscTests.cpp" > + <Original> + result == "\"wide load\"" + </Original> + <Expanded> + ""wide load"" == ""wide load"" + </Expanded> + </Expression> + <OverallResult success="true"/> + </TestCase> + <TestCase name="toString on wchar_t const pointer returns the string contents"> + <Expression success="true" type="CHECK" filename="projects/SelfTest/MiscTests.cpp" > + <Original> + result == "\"wide load\"" + </Original> + <Expanded> + ""wide load"" == ""wide load"" + </Expanded> + </Expression> + <OverallResult success="true"/> + </TestCase> + <TestCase name="toString on wchar_t returns the string contents"> + <Expression success="true" type="CHECK" filename="projects/SelfTest/MiscTests.cpp" > + <Original> + result == "\"wide load\"" + </Original> + <Expanded> + ""wide load"" == ""wide load"" + </Expanded> + </Expression> + <OverallResult success="true"/> + </TestCase> + <TestCase name="XmlEncode"> + <Section name="normal string"> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/MiscTests.cpp" > + <Original> + encode( "normal string" ) == "normal string" + </Original> + <Expanded> + "normal string" == "normal string" + </Expanded> + </Expression> + <OverallResults successes="1" failures="0" expectedFailures="0"/> + </Section> + <Section name="empty string"> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/MiscTests.cpp" > + <Original> + encode( "" ) == "" + </Original> + <Expanded> + "" == "" + </Expanded> + </Expression> + <OverallResults successes="1" failures="0" expectedFailures="0"/> + </Section> + <Section name="string with ampersand"> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/MiscTests.cpp" > + <Original> + encode( "smith & jones" ) == "smith &amp; jones" + </Original> + <Expanded> + "smith &amp; jones" == "smith &amp; jones" + </Expanded> + </Expression> + <OverallResults successes="1" failures="0" expectedFailures="0"/> + </Section> + <Section name="string with less-than"> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/MiscTests.cpp" > + <Original> + encode( "smith < jones" ) == "smith &lt; jones" + </Original> + <Expanded> + "smith &lt; jones" == "smith &lt; jones" + </Expanded> + </Expression> + <OverallResults successes="1" failures="0" expectedFailures="0"/> + </Section> + <Section name="string with greater-than"> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/MiscTests.cpp" > + <Original> + encode( "smith > jones" ) == "smith > jones" + </Original> + <Expanded> + "smith > jones" == "smith > jones" + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/MiscTests.cpp" > + <Original> + encode( "smith ]]> jones" ) == "smith ]]&gt; jones" + </Original> + <Expanded> + "smith ]]&gt; jones" +== +"smith ]]&gt; jones" + </Expanded> + </Expression> + <OverallResults successes="2" failures="0" expectedFailures="0"/> + </Section> + <Section name="string with quotes"> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/MiscTests.cpp" > + <Original> + encode( stringWithQuotes ) == stringWithQuotes + </Original> + <Expanded> + "don't "quote" me on that" +== +"don't "quote" me on that" + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/MiscTests.cpp" > + <Original> + encode( stringWithQuotes, Catch::XmlEncode::ForAttributes ) == "don't &quot;quote&quot; me on that" + </Original> + <Expanded> + "don't &quot;quote&quot; me on that" +== +"don't &quot;quote&quot; me on that" + </Expanded> + </Expression> + <OverallResults successes="2" failures="0" expectedFailures="0"/> + </Section> + <Section name="string with control char (1)"> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/MiscTests.cpp" > + <Original> + encode( "[\x01]" ) == "[&#x1]" + </Original> + <Expanded> + "[&#x1]" == "[&#x1]" + </Expanded> + </Expression> + <OverallResults successes="1" failures="0" expectedFailures="0"/> + </Section> + <Section name="string with control char (x7F)"> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/MiscTests.cpp" > + <Original> + encode( "[\x7F]" ) == "[&#x7F]" + </Original> + <Expanded> + "[&#x7F]" == "[&#x7F]" + </Expanded> + </Expression> + <OverallResults successes="1" failures="0" expectedFailures="0"/> + </Section> + <OverallResult success="true"/> + </TestCase> + <TestCase name="long long"> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/MiscTests.cpp" > + <Original> + l == std::numeric_limits<long long>::max() + </Original> + <Expanded> + 9223372036854775807 (0x<hex digits>) +== +9223372036854775807 (0x<hex digits>) + </Expanded> + </Expression> + <OverallResult success="true"/> + </TestCase> + <TestCase name="Process can be configured on command line"> + <Section name="default - no arguments"> + <Expression success="true" type="CHECK_NOTHROW" filename="projects/SelfTest/TestMain.cpp" > + <Original> + parseIntoConfig( argv, config ) + </Original> + <Expanded> + parseIntoConfig( argv, config ) + </Expanded> + </Expression> + <Expression success="true" type="CHECK" filename="projects/SelfTest/TestMain.cpp" > + <Original> + config.shouldDebugBreak == false + </Original> + <Expanded> + false == false + </Expanded> + </Expression> + <Expression success="true" type="CHECK" filename="projects/SelfTest/TestMain.cpp" > + <Original> + config.abortAfter == -1 + </Original> + <Expanded> + -1 == -1 + </Expanded> + </Expression> + <Expression success="true" type="CHECK" filename="projects/SelfTest/TestMain.cpp" > + <Original> + config.noThrow == false + </Original> + <Expanded> + false == false + </Expanded> + </Expression> + <Expression success="true" type="CHECK" filename="projects/SelfTest/TestMain.cpp" > + <Original> + config.reporterNames.empty() + </Original> + <Expanded> + true + </Expanded> + </Expression> + <OverallResults successes="5" failures="0" expectedFailures="0"/> + </Section> + <Section name="test lists"> + <Section name="1 test" description="Specify one test case using"> + <Expression success="true" type="CHECK_NOTHROW" filename="projects/SelfTest/TestMain.cpp" > + <Original> + parseIntoConfig( argv, config ) + </Original> + <Expanded> + parseIntoConfig( argv, config ) + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/TestMain.cpp" > + <Original> + cfg.testSpec().matches( fakeTestCase( "notIncluded" ) ) == false + </Original> + <Expanded> + false == false + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/TestMain.cpp" > + <Original> + cfg.testSpec().matches( fakeTestCase( "test1" ) ) + </Original> + <Expanded> + true + </Expanded> + </Expression> + <OverallResults successes="3" failures="0" expectedFailures="0"/> + </Section> + <OverallResults successes="3" failures="0" expectedFailures="0"/> + </Section> + <Section name="test lists"> + <Section name="Specify one test case exclusion using exclude:"> + <Expression success="true" type="CHECK_NOTHROW" filename="projects/SelfTest/TestMain.cpp" > + <Original> + parseIntoConfig( argv, config ) + </Original> + <Expanded> + parseIntoConfig( argv, config ) + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/TestMain.cpp" > + <Original> + cfg.testSpec().matches( fakeTestCase( "test1" ) ) == false + </Original> + <Expanded> + false == false + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/TestMain.cpp" > + <Original> + cfg.testSpec().matches( fakeTestCase( "alwaysIncluded" ) ) + </Original> + <Expanded> + true + </Expanded> + </Expression> + <OverallResults successes="3" failures="0" expectedFailures="0"/> + </Section> + <OverallResults successes="3" failures="0" expectedFailures="0"/> + </Section> + <Section name="test lists"> + <Section name="Specify one test case exclusion using ~"> + <Expression success="true" type="CHECK_NOTHROW" filename="projects/SelfTest/TestMain.cpp" > + <Original> + parseIntoConfig( argv, config ) + </Original> + <Expanded> + parseIntoConfig( argv, config ) + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/TestMain.cpp" > + <Original> + cfg.testSpec().matches( fakeTestCase( "test1" ) ) == false + </Original> + <Expanded> + false == false + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/TestMain.cpp" > + <Original> + cfg.testSpec().matches( fakeTestCase( "alwaysIncluded" ) ) + </Original> + <Expanded> + true + </Expanded> + </Expression> + <OverallResults successes="3" failures="0" expectedFailures="0"/> + </Section> + <OverallResults successes="3" failures="0" expectedFailures="0"/> + </Section> + <Section name="reporter"> + <Section name="-r/console"> + <Expression success="true" type="CHECK_NOTHROW" filename="projects/SelfTest/TestMain.cpp" > + <Original> + parseIntoConfig( argv, config ) + </Original> + <Expanded> + parseIntoConfig( argv, config ) + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/TestMain.cpp" > + <Original> + config.reporterNames[0] == "console" + </Original> + <Expanded> + "console" == "console" + </Expanded> + </Expression> + <OverallResults successes="2" failures="0" expectedFailures="0"/> + </Section> + <OverallResults successes="2" failures="0" expectedFailures="0"/> + </Section> + <Section name="reporter"> + <Section name="-r/xml"> + <Expression success="true" type="CHECK_NOTHROW" filename="projects/SelfTest/TestMain.cpp" > + <Original> + parseIntoConfig( argv, config ) + </Original> + <Expanded> + parseIntoConfig( argv, config ) + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/TestMain.cpp" > + <Original> + config.reporterNames[0] == "xml" + </Original> + <Expanded> + "xml" == "xml" + </Expanded> + </Expression> + <OverallResults successes="2" failures="0" expectedFailures="0"/> + </Section> + <OverallResults successes="2" failures="0" expectedFailures="0"/> + </Section> + <Section name="reporter"> + <Section name="-r xml and junit"> + <Expression success="true" type="CHECK_NOTHROW" filename="projects/SelfTest/TestMain.cpp" > + <Original> + parseIntoConfig( argv, config ) + </Original> + <Expanded> + parseIntoConfig( argv, config ) + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/TestMain.cpp" > + <Original> + config.reporterNames.size() == 2 + </Original> + <Expanded> + 2 == 2 + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/TestMain.cpp" > + <Original> + config.reporterNames[0] == "xml" + </Original> + <Expanded> + "xml" == "xml" + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/TestMain.cpp" > + <Original> + config.reporterNames[1] == "junit" + </Original> + <Expanded> + "junit" == "junit" + </Expanded> + </Expression> + <OverallResults successes="4" failures="0" expectedFailures="0"/> + </Section> + <OverallResults successes="4" failures="0" expectedFailures="0"/> + </Section> + <Section name="reporter"> + <Section name="--reporter/junit"> + <Expression success="true" type="CHECK_NOTHROW" filename="projects/SelfTest/TestMain.cpp" > + <Original> + parseIntoConfig( argv, config ) + </Original> + <Expanded> + parseIntoConfig( argv, config ) + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/TestMain.cpp" > + <Original> + config.reporterNames[0] == "junit" + </Original> + <Expanded> + "junit" == "junit" + </Expanded> + </Expression> + <OverallResults successes="2" failures="0" expectedFailures="0"/> + </Section> + <OverallResults successes="2" failures="0" expectedFailures="0"/> + </Section> + <Section name="debugger"> + <Section name="-b"> + <Expression success="true" type="CHECK_NOTHROW" filename="projects/SelfTest/TestMain.cpp" > + <Original> + parseIntoConfig( argv, config ) + </Original> + <Expanded> + parseIntoConfig( argv, config ) + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/TestMain.cpp" > + <Original> + config.shouldDebugBreak == true + </Original> + <Expanded> + true == true + </Expanded> + </Expression> + <OverallResults successes="2" failures="0" expectedFailures="0"/> + </Section> + <OverallResults successes="2" failures="0" expectedFailures="0"/> + </Section> + <Section name="debugger"> + <Section name="--break"> + <Expression success="true" type="CHECK_NOTHROW" filename="projects/SelfTest/TestMain.cpp" > + <Original> + parseIntoConfig( argv, config ) + </Original> + <Expanded> + parseIntoConfig( argv, config ) + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/TestMain.cpp" > + <Original> + config.shouldDebugBreak + </Original> + <Expanded> + true + </Expanded> + </Expression> + <OverallResults successes="2" failures="0" expectedFailures="0"/> + </Section> + <OverallResults successes="2" failures="0" expectedFailures="0"/> + </Section> + <Section name="abort"> + <Section name="-a aborts after first failure"> + <Expression success="true" type="CHECK_NOTHROW" filename="projects/SelfTest/TestMain.cpp" > + <Original> + parseIntoConfig( argv, config ) + </Original> + <Expanded> + parseIntoConfig( argv, config ) + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/TestMain.cpp" > + <Original> + config.abortAfter == 1 + </Original> + <Expanded> + 1 == 1 + </Expanded> + </Expression> + <OverallResults successes="2" failures="0" expectedFailures="0"/> + </Section> + <OverallResults successes="2" failures="0" expectedFailures="0"/> + </Section> + <Section name="abort"> + <Section name="-x 2 aborts after two failures"> + <Expression success="true" type="CHECK_NOTHROW" filename="projects/SelfTest/TestMain.cpp" > + <Original> + parseIntoConfig( argv, config ) + </Original> + <Expanded> + parseIntoConfig( argv, config ) + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/TestMain.cpp" > + <Original> + config.abortAfter == 2 + </Original> + <Expanded> + 2 == 2 + </Expanded> + </Expression> + <OverallResults successes="2" failures="0" expectedFailures="0"/> + </Section> + <OverallResults successes="2" failures="0" expectedFailures="0"/> + </Section> + <Section name="abort"> + <Section name="-x must be greater than zero"> + <Expression success="true" type="REQUIRE_THAT" filename="projects/SelfTest/TestMain.cpp" > + <Original> + parseIntoConfigAndReturnError( argv, config ), Contains( "greater than zero" ) + </Original> + <Expanded> + "Value after -x or --abortAfter must be greater than zero +- while parsing: (-x, --abortx <no. failures>)" contains: "greater than zero" + </Expanded> + </Expression> + <OverallResults successes="1" failures="0" expectedFailures="0"/> + </Section> + <OverallResults successes="1" failures="0" expectedFailures="0"/> + </Section> + <Section name="abort"> + <Section name="-x must be numeric"> + <Expression success="true" type="REQUIRE_THAT" filename="projects/SelfTest/TestMain.cpp" > + <Original> + parseIntoConfigAndReturnError( argv, config ), Contains( "-x" ) + </Original> + <Expanded> + "Unable to convert oops to destination type +- while parsing: (-x, --abortx <no. failures>)" contains: "-x" + </Expanded> + </Expression> + <OverallResults successes="1" failures="0" expectedFailures="0"/> + </Section> + <OverallResults successes="1" failures="0" expectedFailures="0"/> + </Section> + <Section name="nothrow"> + <Section name="-e"> + <Expression success="true" type="CHECK_NOTHROW" filename="projects/SelfTest/TestMain.cpp" > + <Original> + parseIntoConfig( argv, config ) + </Original> + <Expanded> + parseIntoConfig( argv, config ) + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/TestMain.cpp" > + <Original> + config.noThrow == true + </Original> + <Expanded> + true == true + </Expanded> + </Expression> + <OverallResults successes="2" failures="0" expectedFailures="0"/> + </Section> + <OverallResults successes="2" failures="0" expectedFailures="0"/> + </Section> + <Section name="nothrow"> + <Section name="--nothrow"> + <Expression success="true" type="CHECK_NOTHROW" filename="projects/SelfTest/TestMain.cpp" > + <Original> + parseIntoConfig( argv, config ) + </Original> + <Expanded> + parseIntoConfig( argv, config ) + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/TestMain.cpp" > + <Original> + config.noThrow == true + </Original> + <Expanded> + true == true + </Expanded> + </Expression> + <OverallResults successes="2" failures="0" expectedFailures="0"/> + </Section> + <OverallResults successes="2" failures="0" expectedFailures="0"/> + </Section> + <Section name="output filename"> + <Section name="-o filename"> + <Expression success="true" type="CHECK_NOTHROW" filename="projects/SelfTest/TestMain.cpp" > + <Original> + parseIntoConfig( argv, config ) + </Original> + <Expanded> + parseIntoConfig( argv, config ) + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/TestMain.cpp" > + <Original> + config.outputFilename == "filename.ext" + </Original> + <Expanded> + "filename.ext" == "filename.ext" + </Expanded> + </Expression> + <OverallResults successes="2" failures="0" expectedFailures="0"/> + </Section> + <OverallResults successes="2" failures="0" expectedFailures="0"/> + </Section> + <Section name="output filename"> + <Section name="--out"> + <Expression success="true" type="CHECK_NOTHROW" filename="projects/SelfTest/TestMain.cpp" > + <Original> + parseIntoConfig( argv, config ) + </Original> + <Expanded> + parseIntoConfig( argv, config ) + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/TestMain.cpp" > + <Original> + config.outputFilename == "filename.ext" + </Original> + <Expanded> + "filename.ext" == "filename.ext" + </Expanded> + </Expression> + <OverallResults successes="2" failures="0" expectedFailures="0"/> + </Section> + <OverallResults successes="2" failures="0" expectedFailures="0"/> + </Section> + <Section name="combinations"> + <Section name="Single character flags can be combined"> + <Expression success="true" type="CHECK_NOTHROW" filename="projects/SelfTest/TestMain.cpp" > + <Original> + parseIntoConfig( argv, config ) + </Original> + <Expanded> + parseIntoConfig( argv, config ) + </Expanded> + </Expression> + <Expression success="true" type="CHECK" filename="projects/SelfTest/TestMain.cpp" > + <Original> + config.abortAfter == 1 + </Original> + <Expanded> + 1 == 1 + </Expanded> + </Expression> + <Expression success="true" type="CHECK" filename="projects/SelfTest/TestMain.cpp" > + <Original> + config.shouldDebugBreak + </Original> + <Expanded> + true + </Expanded> + </Expression> + <Expression success="true" type="CHECK" filename="projects/SelfTest/TestMain.cpp" > + <Original> + config.noThrow == true + </Original> + <Expanded> + true == true + </Expanded> + </Expression> + <OverallResults successes="4" failures="0" expectedFailures="0"/> + </Section> + <OverallResults successes="4" failures="0" expectedFailures="0"/> + </Section> + <Section name="use-colour"> + <Section name="without option"> + <Expression success="true" type="CHECK_NOTHROW" filename="projects/SelfTest/TestMain.cpp" > + <Original> + parseIntoConfig( argv, config ) + </Original> + <Expanded> + parseIntoConfig( argv, config ) + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/TestMain.cpp" > + <Original> + config.useColour == UseColour::Auto + </Original> + <Expanded> + 0 == 0 + </Expanded> + </Expression> + <OverallResults successes="2" failures="0" expectedFailures="0"/> + </Section> + <OverallResults successes="2" failures="0" expectedFailures="0"/> + </Section> + <Section name="use-colour"> + <Section name="auto"> + <Expression success="true" type="CHECK_NOTHROW" filename="projects/SelfTest/TestMain.cpp" > + <Original> + parseIntoConfig( argv, config ) + </Original> + <Expanded> + parseIntoConfig( argv, config ) + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/TestMain.cpp" > + <Original> + config.useColour == UseColour::Auto + </Original> + <Expanded> + 0 == 0 + </Expanded> + </Expression> + <OverallResults successes="2" failures="0" expectedFailures="0"/> + </Section> + <OverallResults successes="2" failures="0" expectedFailures="0"/> + </Section> + <Section name="use-colour"> + <Section name="yes"> + <Expression success="true" type="CHECK_NOTHROW" filename="projects/SelfTest/TestMain.cpp" > + <Original> + parseIntoConfig( argv, config ) + </Original> + <Expanded> + parseIntoConfig( argv, config ) + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/TestMain.cpp" > + <Original> + config.useColour == UseColour::Yes + </Original> + <Expanded> + 1 == 1 + </Expanded> + </Expression> + <OverallResults successes="2" failures="0" expectedFailures="0"/> + </Section> + <OverallResults successes="2" failures="0" expectedFailures="0"/> + </Section> + <Section name="use-colour"> + <Section name="no"> + <Expression success="true" type="CHECK_NOTHROW" filename="projects/SelfTest/TestMain.cpp" > + <Original> + parseIntoConfig( argv, config ) + </Original> + <Expanded> + parseIntoConfig( argv, config ) + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/TestMain.cpp" > + <Original> + config.useColour == UseColour::No + </Original> + <Expanded> + 2 == 2 + </Expanded> + </Expression> + <OverallResults successes="2" failures="0" expectedFailures="0"/> + </Section> + <OverallResults successes="2" failures="0" expectedFailures="0"/> + </Section> + <Section name="use-colour"> + <Section name="error"> + <Expression success="true" type="REQUIRE_THROWS_WITH" filename="projects/SelfTest/TestMain.cpp" > + <Original> + parseIntoConfig( argv, config ), Contains( "colour mode must be one of" ) + </Original> + <Expanded> + parseIntoConfig( argv, config ), Contains( "colour mode must be one of" ) + </Expanded> + </Expression> + <OverallResults successes="1" failures="0" expectedFailures="0"/> + </Section> + <OverallResults successes="1" failures="0" expectedFailures="0"/> + </Section> + <OverallResult success="true"/> + </TestCase> + <TestCase name="Long strings can be wrapped"> + <Section name="plain string"> + <Section name="No wrapping"> + <Expression success="true" type="CHECK" filename="projects/SelfTest/TestMain.cpp" > + <Original> + Text( testString, TextAttributes().setWidth( 80 ) ).toString() == testString + </Original> + <Expanded> + "one two three four" +== +"one two three four" + </Expanded> + </Expression> + <Expression success="true" type="CHECK" filename="projects/SelfTest/TestMain.cpp" > + <Original> + Text( testString, TextAttributes().setWidth( 18 ) ).toString() == testString + </Original> + <Expanded> + "one two three four" +== +"one two three four" + </Expanded> + </Expression> + <OverallResults successes="2" failures="0" expectedFailures="0"/> + </Section> + <OverallResults successes="2" failures="0" expectedFailures="0"/> + </Section> + <Section name="plain string"> + <Section name="Wrapped once"> + <Expression success="true" type="CHECK" filename="projects/SelfTest/TestMain.cpp" > + <Original> + Text( testString, TextAttributes().setWidth( 17 ) ).toString() == "one two three\nfour" + </Original> + <Expanded> + "one two three +four" +== +"one two three +four" + </Expanded> + </Expression> + <Expression success="true" type="CHECK" filename="projects/SelfTest/TestMain.cpp" > + <Original> + Text( testString, TextAttributes().setWidth( 16 ) ).toString() == "one two three\nfour" + </Original> + <Expanded> + "one two three +four" +== +"one two three +four" + </Expanded> + </Expression> + <Expression success="true" type="CHECK" filename="projects/SelfTest/TestMain.cpp" > + <Original> + Text( testString, TextAttributes().setWidth( 14 ) ).toString() == "one two three\nfour" + </Original> + <Expanded> + "one two three +four" +== +"one two three +four" + </Expanded> + </Expression> + <Expression success="true" type="CHECK" filename="projects/SelfTest/TestMain.cpp" > + <Original> + Text( testString, TextAttributes().setWidth( 13 ) ).toString() == "one two three\nfour" + </Original> + <Expanded> + "one two three +four" +== +"one two three +four" + </Expanded> + </Expression> + <Expression success="true" type="CHECK" filename="projects/SelfTest/TestMain.cpp" > + <Original> + Text( testString, TextAttributes().setWidth( 12 ) ).toString() == "one two\nthree four" + </Original> + <Expanded> + "one two +three four" +== +"one two +three four" + </Expanded> + </Expression> + <OverallResults successes="5" failures="0" expectedFailures="0"/> + </Section> + <OverallResults successes="5" failures="0" expectedFailures="0"/> + </Section> + <Section name="plain string"> + <Section name="Wrapped twice"> + <Expression success="true" type="CHECK" filename="projects/SelfTest/TestMain.cpp" > + <Original> + Text( testString, TextAttributes().setWidth( 9 ) ).toString() == "one two\nthree\nfour" + </Original> + <Expanded> + "one two +three +four" +== +"one two +three +four" + </Expanded> + </Expression> + <Expression success="true" type="CHECK" filename="projects/SelfTest/TestMain.cpp" > + <Original> + Text( testString, TextAttributes().setWidth( 8 ) ).toString() == "one two\nthree\nfour" + </Original> + <Expanded> + "one two +three +four" +== +"one two +three +four" + </Expanded> + </Expression> + <Expression success="true" type="CHECK" filename="projects/SelfTest/TestMain.cpp" > + <Original> + Text( testString, TextAttributes().setWidth( 7 ) ).toString() == "one two\nthree\nfour" + </Original> + <Expanded> + "one two +three +four" +== +"one two +three +four" + </Expanded> + </Expression> + <OverallResults successes="3" failures="0" expectedFailures="0"/> + </Section> + <OverallResults successes="3" failures="0" expectedFailures="0"/> + </Section> + <Section name="plain string"> + <Section name="Wrapped three times"> + <Expression success="true" type="CHECK" filename="projects/SelfTest/TestMain.cpp" > + <Original> + Text( testString, TextAttributes().setWidth( 6 ) ).toString() == "one\ntwo\nthree\nfour" + </Original> + <Expanded> + "one +two +three +four" +== +"one +two +three +four" + </Expanded> + </Expression> + <Expression success="true" type="CHECK" filename="projects/SelfTest/TestMain.cpp" > + <Original> + Text( testString, TextAttributes().setWidth( 5 ) ).toString() == "one\ntwo\nthree\nfour" + </Original> + <Expanded> + "one +two +three +four" +== +"one +two +three +four" + </Expanded> + </Expression> + <OverallResults successes="2" failures="0" expectedFailures="0"/> + </Section> + <OverallResults successes="2" failures="0" expectedFailures="0"/> + </Section> + <Section name="plain string"> + <Section name="Short wrap"> + <Expression success="true" type="CHECK" filename="projects/SelfTest/TestMain.cpp" > + <Original> + Text( "abcdef", TextAttributes().setWidth( 4 ) ).toString() == "abc-\ndef" + </Original> + <Expanded> + "abc- +def" +== +"abc- +def" + </Expanded> + </Expression> + <Expression success="true" type="CHECK" filename="projects/SelfTest/TestMain.cpp" > + <Original> + Text( "abcdefg", TextAttributes().setWidth( 4 ) ).toString() == "abc-\ndefg" + </Original> + <Expanded> + "abc- +defg" +== +"abc- +defg" + </Expanded> + </Expression> + <Expression success="true" type="CHECK" filename="projects/SelfTest/TestMain.cpp" > + <Original> + Text( "abcdefgh", TextAttributes().setWidth( 4 ) ).toString() == "abc-\ndef-\ngh" + </Original> + <Expanded> + "abc- +def- +gh" +== +"abc- +def- +gh" + </Expanded> + </Expression> + <Expression success="true" type="CHECK" filename="projects/SelfTest/TestMain.cpp" > + <Original> + Text( testString, TextAttributes().setWidth( 4 ) ).toString() == "one\ntwo\nthr-\nee\nfour" + </Original> + <Expanded> + "one +two +thr- +ee +four" +== +"one +two +thr- +ee +four" + </Expanded> + </Expression> + <Expression success="true" type="CHECK" filename="projects/SelfTest/TestMain.cpp" > + <Original> + Text( testString, TextAttributes().setWidth( 3 ) ).toString() == "one\ntwo\nth-\nree\nfo-\nur" + </Original> + <Expanded> + "one +two +th- +ree +fo- +ur" +== +"one +two +th- +ree +fo- +ur" + </Expanded> + </Expression> + <OverallResults successes="5" failures="0" expectedFailures="0"/> + </Section> + <OverallResults successes="5" failures="0" expectedFailures="0"/> + </Section> + <Section name="plain string"> + <Section name="As container"> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/TestMain.cpp" > + <Original> + text.size() == 4 + </Original> + <Expanded> + 4 == 4 + </Expanded> + </Expression> + <Expression success="true" type="CHECK" filename="projects/SelfTest/TestMain.cpp" > + <Original> + text[0] == "one" + </Original> + <Expanded> + "one" == "one" + </Expanded> + </Expression> + <Expression success="true" type="CHECK" filename="projects/SelfTest/TestMain.cpp" > + <Original> + text[1] == "two" + </Original> + <Expanded> + "two" == "two" + </Expanded> + </Expression> + <Expression success="true" type="CHECK" filename="projects/SelfTest/TestMain.cpp" > + <Original> + text[2] == "three" + </Original> + <Expanded> + "three" == "three" + </Expanded> + </Expression> + <Expression success="true" type="CHECK" filename="projects/SelfTest/TestMain.cpp" > + <Original> + text[3] == "four" + </Original> + <Expanded> + "four" == "four" + </Expanded> + </Expression> + <OverallResults successes="5" failures="0" expectedFailures="0"/> + </Section> + <OverallResults successes="5" failures="0" expectedFailures="0"/> + </Section> + <Section name="plain string"> + <Section name="Indent first line differently"> + <Expression success="true" type="CHECK" filename="projects/SelfTest/TestMain.cpp" > + <Original> + text.toString() == " one two\n three\n four" + </Original> + <Expanded> + " one two + three + four" +== +" one two + three + four" + </Expanded> + </Expression> + <OverallResults successes="1" failures="0" expectedFailures="0"/> + </Section> + <OverallResults successes="1" failures="0" expectedFailures="0"/> + </Section> + <Section name="With newlines"> + <Section name="No wrapping"> + <Expression success="true" type="CHECK" filename="projects/SelfTest/TestMain.cpp" > + <Original> + Text( testString, TextAttributes().setWidth( 80 ) ).toString() == testString + </Original> + <Expanded> + "one two +three four" +== +"one two +three four" + </Expanded> + </Expression> + <Expression success="true" type="CHECK" filename="projects/SelfTest/TestMain.cpp" > + <Original> + Text( testString, TextAttributes().setWidth( 18 ) ).toString() == testString + </Original> + <Expanded> + "one two +three four" +== +"one two +three four" + </Expanded> + </Expression> + <Expression success="true" type="CHECK" filename="projects/SelfTest/TestMain.cpp" > + <Original> + Text( testString, TextAttributes().setWidth( 10 ) ).toString() == testString + </Original> + <Expanded> + "one two +three four" +== +"one two +three four" + </Expanded> + </Expression> + <OverallResults successes="3" failures="0" expectedFailures="0"/> + </Section> + <OverallResults successes="3" failures="0" expectedFailures="0"/> + </Section> + <Section name="With newlines"> + <Section name="Trailing newline"> + <Expression success="true" type="CHECK" filename="projects/SelfTest/TestMain.cpp" > + <Original> + Text( "abcdef\n", TextAttributes().setWidth( 10 ) ).toString() == "abcdef\n" + </Original> + <Expanded> + "abcdef +" +== +"abcdef +" + </Expanded> + </Expression> + <Expression success="true" type="CHECK" filename="projects/SelfTest/TestMain.cpp" > + <Original> + Text( "abcdef", TextAttributes().setWidth( 6 ) ).toString() == "abcdef" + </Original> + <Expanded> + "abcdef" == "abcdef" + </Expanded> + </Expression> + <Expression success="true" type="CHECK" filename="projects/SelfTest/TestMain.cpp" > + <Original> + Text( "abcdef\n", TextAttributes().setWidth( 6 ) ).toString() == "abcdef\n" + </Original> + <Expanded> + "abcdef +" +== +"abcdef +" + </Expanded> + </Expression> + <OverallResults successes="3" failures="0" expectedFailures="0"/> + </Section> + <OverallResults successes="3" failures="0" expectedFailures="0"/> + </Section> + <Section name="With newlines"> + <Section name="Wrapped once"> + <Expression success="true" type="CHECK" filename="projects/SelfTest/TestMain.cpp" > + <Original> + Text( testString, TextAttributes().setWidth( 9 ) ).toString() == "one two\nthree\nfour" + </Original> + <Expanded> + "one two +three +four" +== +"one two +three +four" + </Expanded> + </Expression> + <Expression success="true" type="CHECK" filename="projects/SelfTest/TestMain.cpp" > + <Original> + Text( testString, TextAttributes().setWidth( 8 ) ).toString() == "one two\nthree\nfour" + </Original> + <Expanded> + "one two +three +four" +== +"one two +three +four" + </Expanded> + </Expression> + <Expression success="true" type="CHECK" filename="projects/SelfTest/TestMain.cpp" > + <Original> + Text( testString, TextAttributes().setWidth( 7 ) ).toString() == "one two\nthree\nfour" + </Original> + <Expanded> + "one two +three +four" +== +"one two +three +four" + </Expanded> + </Expression> + <OverallResults successes="3" failures="0" expectedFailures="0"/> + </Section> + <OverallResults successes="3" failures="0" expectedFailures="0"/> + </Section> + <Section name="With newlines"> + <Section name="Wrapped twice"> + <Expression success="true" type="CHECK" filename="projects/SelfTest/TestMain.cpp" > + <Original> + Text( testString, TextAttributes().setWidth( 6 ) ).toString() == "one\ntwo\nthree\nfour" + </Original> + <Expanded> + "one +two +three +four" +== +"one +two +three +four" + </Expanded> + </Expression> + <OverallResults successes="1" failures="0" expectedFailures="0"/> + </Section> + <OverallResults successes="1" failures="0" expectedFailures="0"/> + </Section> + <Section name="With tabs"> + <Expression success="true" type="CHECK" filename="projects/SelfTest/TestMain.cpp" > + <Original> + Text( testString, TextAttributes().setWidth( 15 ) ).toString() == "one two three\n four\n five\n six" + </Original> + <Expanded> + "one two three + four + five + six" +== +"one two three + four + five + six" + </Expanded> + </Expression> + <OverallResults successes="1" failures="0" expectedFailures="0"/> + </Section> + <OverallResult success="true"/> + </TestCase> + <TestCase name="replaceInPlace"> + <Section name="replace single char"> + <Expression success="true" type="CHECK" filename="projects/SelfTest/TestMain.cpp" > + <Original> + replaceInPlace( letters, "b", "z" ) + </Original> + <Expanded> + true + </Expanded> + </Expression> + <Expression success="true" type="CHECK" filename="projects/SelfTest/TestMain.cpp" > + <Original> + letters == "azcdefcg" + </Original> + <Expanded> + "azcdefcg" == "azcdefcg" + </Expanded> + </Expression> + <OverallResults successes="2" failures="0" expectedFailures="0"/> + </Section> + <Section name="replace two chars"> + <Expression success="true" type="CHECK" filename="projects/SelfTest/TestMain.cpp" > + <Original> + replaceInPlace( letters, "c", "z" ) + </Original> + <Expanded> + true + </Expanded> + </Expression> + <Expression success="true" type="CHECK" filename="projects/SelfTest/TestMain.cpp" > + <Original> + letters == "abzdefzg" + </Original> + <Expanded> + "abzdefzg" == "abzdefzg" + </Expanded> + </Expression> + <OverallResults successes="2" failures="0" expectedFailures="0"/> + </Section> + <Section name="replace first char"> + <Expression success="true" type="CHECK" filename="projects/SelfTest/TestMain.cpp" > + <Original> + replaceInPlace( letters, "a", "z" ) + </Original> + <Expanded> + true + </Expanded> + </Expression> + <Expression success="true" type="CHECK" filename="projects/SelfTest/TestMain.cpp" > + <Original> + letters == "zbcdefcg" + </Original> + <Expanded> + "zbcdefcg" == "zbcdefcg" + </Expanded> + </Expression> + <OverallResults successes="2" failures="0" expectedFailures="0"/> + </Section> + <Section name="replace last char"> + <Expression success="true" type="CHECK" filename="projects/SelfTest/TestMain.cpp" > + <Original> + replaceInPlace( letters, "g", "z" ) + </Original> + <Expanded> + true + </Expanded> + </Expression> + <Expression success="true" type="CHECK" filename="projects/SelfTest/TestMain.cpp" > + <Original> + letters == "abcdefcz" + </Original> + <Expanded> + "abcdefcz" == "abcdefcz" + </Expanded> + </Expression> + <OverallResults successes="2" failures="0" expectedFailures="0"/> + </Section> + <Section name="replace all chars"> + <Expression success="true" type="CHECK" filename="projects/SelfTest/TestMain.cpp" > + <Original> + replaceInPlace( letters, letters, "replaced" ) + </Original> + <Expanded> + true + </Expanded> + </Expression> + <Expression success="true" type="CHECK" filename="projects/SelfTest/TestMain.cpp" > + <Original> + letters == "replaced" + </Original> + <Expanded> + "replaced" == "replaced" + </Expanded> + </Expression> + <OverallResults successes="2" failures="0" expectedFailures="0"/> + </Section> + <Section name="replace no chars"> + <Expression success="true" type="CHECK_FALSE" filename="projects/SelfTest/TestMain.cpp" > + <Original> + !replaceInPlace( letters, "x", "z" ) + </Original> + <Expanded> + !false + </Expanded> + </Expression> + <Expression success="true" type="CHECK" filename="projects/SelfTest/TestMain.cpp" > + <Original> + letters == letters + </Original> + <Expanded> + "abcdefcg" == "abcdefcg" + </Expanded> + </Expression> + <OverallResults successes="2" failures="0" expectedFailures="0"/> + </Section> + <Section name="escape '"> + <Expression success="true" type="CHECK" filename="projects/SelfTest/TestMain.cpp" > + <Original> + replaceInPlace( s, "'", "|'" ) + </Original> + <Expanded> + true + </Expanded> + </Expression> + <Expression success="true" type="CHECK" filename="projects/SelfTest/TestMain.cpp" > + <Original> + s == "didn|'t" + </Original> + <Expanded> + "didn|'t" == "didn|'t" + </Expanded> + </Expression> + <OverallResults successes="2" failures="0" expectedFailures="0"/> + </Section> + <OverallResult success="true"/> + </TestCase> + <TestCase name="Strings can be rendered with colour"> + <OverallResult success="true"/> + </TestCase> + <TestCase name="Text can be formatted using the Text class"> + <Expression success="true" type="CHECK" filename="projects/SelfTest/TestMain.cpp" > + <Original> + Text( "hi there" ).toString() == "hi there" + </Original> + <Expanded> + "hi there" == "hi there" + </Expanded> + </Expression> + <Expression success="true" type="CHECK" filename="projects/SelfTest/TestMain.cpp" > + <Original> + Text( "hi there", narrow ).toString() == "hi\nthere" + </Original> + <Expanded> + "hi +there" +== +"hi +there" + </Expanded> + </Expression> + <OverallResult success="true"/> + </TestCase> + <TestCase name="Long text is truncted"> + <Expression success="true" type="CHECK_THAT" filename="projects/SelfTest/TestMain.cpp" > + <Original> + t.toString(), EndsWith( "... message truncated due to excessive size" ) + </Original> + <Expanded> + "******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +... message truncated due to excessive size" ends with: "... message truncated due to excessive size" + </Expanded> + </Expression> + <OverallResult success="true"/> + </TestCase> + <TestCase name="ManuallyRegistered"> + <OverallResult success="true"/> + </TestCase> + <TestCase name="Parsing a std::pair"> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/TrickyTests.cpp" > + <Original> + (std::pair<int, int>( 1, 2 )) == aNicePair + </Original> + <Expanded> + std::pair( 1, 2 ) == std::pair( 1, 2 ) + </Expanded> + </Expression> + <OverallResult success="true"/> + </TestCase> + <TestCase name="Where there is more to the expression after the RHS"> + <Warning> + Uncomment the code in this test to check that it gives a sensible compiler error + </Warning> + <OverallResult success="true"/> + </TestCase> + <TestCase name="Where the LHS is not a simple value"> + <Warning> + Uncomment the code in this test to check that it gives a sensible compiler error + </Warning> + <OverallResult success="true"/> + </TestCase> + <TestCase name="A failing expression with a non streamable type is still captured"> + <Expression success="false" type="CHECK" filename="projects/SelfTest/TrickyTests.cpp" > + <Original> + &o1 == &o2 + </Original> + <Expanded> + 0x<hex digits> == 0x<hex digits> + </Expanded> + </Expression> + <Expression success="false" type="CHECK" filename="projects/SelfTest/TrickyTests.cpp" > + <Original> + o1 == o2 + </Original> + <Expanded> + {?} == {?} + </Expanded> + </Expression> + <OverallResult success="false"/> + </TestCase> + <TestCase name="string literals of different sizes can be compared"> + <Expression success="false" type="REQUIRE" filename="projects/SelfTest/TrickyTests.cpp" > + <Original> + std::string( "first" ) == "second" + </Original> + <Expanded> + "first" == "second" + </Expanded> + </Expression> + <OverallResult success="false"/> + </TestCase> + <TestCase name="An expression with side-effects should only be evaluated once"> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/TrickyTests.cpp" > + <Original> + i++ == 7 + </Original> + <Expanded> + 7 == 7 + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/TrickyTests.cpp" > + <Original> + i++ == 8 + </Original> + <Expanded> + 8 == 8 + </Expanded> + </Expression> + <OverallResult success="true"/> + </TestCase> + <TestCase name="Operators at different namespace levels not hijacked by Koenig lookup"> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/TrickyTests.cpp" > + <Original> + 0x<hex digits> == o + </Original> + <Expanded> + 3221225472 (0x<hex digits>) == {?} + </Expanded> + </Expression> + <OverallResult success="true"/> + </TestCase> + <TestCase name="Demonstrate that a non-const == is not used"> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/TrickyTests.cpp" > + <Original> + t == 1u + </Original> + <Expanded> + {?} == 1 + </Expanded> + </Expression> + <OverallResult success="true"/> + </TestCase> + <TestCase name="Test enum bit values"> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/TrickyTests.cpp" > + <Original> + 0x<hex digits> == bit30and31 + </Original> + <Expanded> + 3221225472 (0x<hex digits>) == 3221225472 + </Expanded> + </Expression> + <OverallResult success="true"/> + </TestCase> + <TestCase name="boolean member"> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/TrickyTests.cpp" > + <Original> + obj.prop != nullptr + </Original> + <Expanded> + 0x<hex digits> != nullptr + </Expanded> + </Expression> + <OverallResult success="true"/> + </TestCase> + <TestCase name="(unimplemented) static bools can be evaluated"> + <Section name="compare to true"> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/TrickyTests.cpp" > + <Original> + is_true<true>::value == true + </Original> + <Expanded> + true == true + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/TrickyTests.cpp" > + <Original> + true == is_true<true>::value + </Original> + <Expanded> + true == true + </Expanded> + </Expression> + <OverallResults successes="2" failures="0" expectedFailures="0"/> + </Section> + <Section name="compare to false"> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/TrickyTests.cpp" > + <Original> + is_true<false>::value == false + </Original> + <Expanded> + false == false + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/TrickyTests.cpp" > + <Original> + false == is_true<false>::value + </Original> + <Expanded> + false == false + </Expanded> + </Expression> + <OverallResults successes="2" failures="0" expectedFailures="0"/> + </Section> + <Section name="negation"> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/TrickyTests.cpp" > + <Original> + !is_true<false>::value + </Original> + <Expanded> + true + </Expanded> + </Expression> + <OverallResults successes="1" failures="0" expectedFailures="0"/> + </Section> + <Section name="double negation"> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/TrickyTests.cpp" > + <Original> + !!is_true<true>::value + </Original> + <Expanded> + true + </Expanded> + </Expression> + <OverallResults successes="1" failures="0" expectedFailures="0"/> + </Section> + <Section name="direct"> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/TrickyTests.cpp" > + <Original> + is_true<true>::value + </Original> + <Expanded> + true + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE_FALSE" filename="projects/SelfTest/TrickyTests.cpp" > + <Original> + !is_true<false>::value + </Original> + <Expanded> + !false + </Expanded> + </Expression> + <OverallResults successes="2" failures="0" expectedFailures="0"/> + </Section> + <OverallResult success="true"/> + </TestCase> + <TestCase name="Objects that evaluated in boolean contexts can be checked"> + <Expression success="true" type="CHECK" filename="projects/SelfTest/TrickyTests.cpp" > + <Original> + True + </Original> + <Expanded> + true + </Expanded> + </Expression> + <Expression success="true" type="CHECK" filename="projects/SelfTest/TrickyTests.cpp" > + <Original> + !False + </Original> + <Expanded> + true + </Expanded> + </Expression> + <Expression success="true" type="CHECK_FALSE" filename="projects/SelfTest/TrickyTests.cpp" > + <Original> + !False + </Original> + <Expanded> + !false + </Expanded> + </Expression> + <OverallResult success="true"/> + </TestCase> + <TestCase name="Assertions then sections"> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/TrickyTests.cpp" > + <Original> + Catch::alwaysTrue() + </Original> + <Expanded> + true + </Expanded> + </Expression> + <Section name="A section"> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/TrickyTests.cpp" > + <Original> + Catch::alwaysTrue() + </Original> + <Expanded> + true + </Expanded> + </Expression> + <Section name="Another section"> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/TrickyTests.cpp" > + <Original> + Catch::alwaysTrue() + </Original> + <Expanded> + true + </Expanded> + </Expression> + <OverallResults successes="1" failures="0" expectedFailures="0"/> + </Section> + <OverallResults successes="2" failures="0" expectedFailures="0"/> + </Section> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/TrickyTests.cpp" > + <Original> + Catch::alwaysTrue() + </Original> + <Expanded> + true + </Expanded> + </Expression> + <Section name="A section"> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/TrickyTests.cpp" > + <Original> + Catch::alwaysTrue() + </Original> + <Expanded> + true + </Expanded> + </Expression> + <Section name="Another other section"> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/TrickyTests.cpp" > + <Original> + Catch::alwaysTrue() + </Original> + <Expanded> + true + </Expanded> + </Expression> + <OverallResults successes="1" failures="0" expectedFailures="0"/> + </Section> + <OverallResults successes="2" failures="0" expectedFailures="0"/> + </Section> + <OverallResult success="true"/> + </TestCase> + <TestCase name="non streamable - with conv. op"> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/TrickyTests.cpp" > + <Original> + s == "7" + </Original> + <Expanded> + "7" == "7" + </Expanded> + </Expression> + <OverallResult success="true"/> + </TestCase> + <TestCase name="Comparing function pointers"> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/TrickyTests.cpp" > + <Original> + a + </Original> + <Expanded> + true + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/TrickyTests.cpp" > + <Original> + a == &foo + </Original> + <Expanded> + 0x<hex digits> == 0x<hex digits> + </Expanded> + </Expression> + <OverallResult success="true"/> + </TestCase> + <TestCase name="Comparing member function pointers"> + <Expression success="true" type="CHECK" filename="projects/SelfTest/TrickyTests.cpp" > + <Original> + m == &S::f + </Original> + <Expanded> + 0x<hex digits> +== +0x<hex digits> + </Expanded> + </Expression> + <OverallResult success="true"/> + </TestCase> + <TestCase name="pointer to class"> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/TrickyTests.cpp" > + <Original> + p == 0 + </Original> + <Expanded> + NULL == 0 + </Expanded> + </Expression> + <OverallResult success="true"/> + </TestCase> + <TestCase name="null_ptr"> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/TrickyTests.cpp" > + <Original> + ptr.get() == nullptr + </Original> + <Expanded> + NULL == nullptr + </Expanded> + </Expression> + <OverallResult success="true"/> + </TestCase> + <TestCase name="X/level/0/a"> + <OverallResult success="true"/> + </TestCase> + <TestCase name="X/level/0/b"> + <OverallResult success="true"/> + </TestCase> + <TestCase name="X/level/1/a"> + <OverallResult success="true"/> + </TestCase> + <TestCase name="X/level/1/b"> + <OverallResult success="true"/> + </TestCase> + <TestCase name="toString( has_toString )"> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/ToStringWhich.cpp" > + <Original> + Catch::toString( item ) == "toString( has_toString )" + </Original> + <Expanded> + "toString( has_toString )" +== +"toString( has_toString )" + </Expanded> + </Expression> + <OverallResult success="true"/> + </TestCase> + <TestCase name="toString( has_maker )"> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/ToStringWhich.cpp" > + <Original> + Catch::toString( item ) == "StringMaker<has_maker>" + </Original> + <Expanded> + "StringMaker<has_maker>" +== +"StringMaker<has_maker>" + </Expanded> + </Expression> + <OverallResult success="true"/> + </TestCase> + <TestCase name="toString( has_maker_and_toString )"> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/ToStringWhich.cpp" > + <Original> + Catch::toString( item ) == "toString( has_maker_and_toString )" + </Original> + <Expanded> + "toString( has_maker_and_toString )" +== +"toString( has_maker_and_toString )" + </Expanded> + </Expression> + <OverallResult success="true"/> + </TestCase> + <TestCase name="toString( vectors<has_toString )"> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/ToStringWhich.cpp" > + <Original> + Catch::toString( v ) == "{ {?} }" + </Original> + <Expanded> + "{ {?} }" == "{ {?} }" + </Expanded> + </Expression> + <OverallResult success="true"/> + </TestCase> + <TestCase name="toString( vectors<has_maker )"> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/ToStringWhich.cpp" > + <Original> + Catch::toString( v ) == "{ StringMaker<has_maker> }" + </Original> + <Expanded> + "{ StringMaker<has_maker> }" +== +"{ StringMaker<has_maker> }" + </Expanded> + </Expression> + <OverallResult success="true"/> + </TestCase> + <TestCase name="toString( vectors<has_maker_and_toString )"> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/ToStringWhich.cpp" > + <Original> + Catch::toString( v ) == "{ StringMaker<has_maker_and_toString> }" + </Original> + <Expanded> + "{ StringMaker<has_maker_and_toString> }" +== +"{ StringMaker<has_maker_and_toString> }" + </Expanded> + </Expression> + <OverallResult success="true"/> + </TestCase> + <TestCase name="Tracker"> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/PartTrackerTests.cpp" > + <Original> + testCase.isOpen() + </Original> + <Expanded> + true + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/PartTrackerTests.cpp" > + <Original> + s1.isOpen() + </Original> + <Expanded> + true + </Expanded> + </Expression> + <Section name="successfully close one section"> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/PartTrackerTests.cpp" > + <Original> + s1.isSuccessfullyCompleted() + </Original> + <Expanded> + true + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/PartTrackerTests.cpp" > + <Original> + testCase.isComplete() == false + </Original> + <Expanded> + false == false + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/PartTrackerTests.cpp" > + <Original> + ctx.completedCycle() + </Original> + <Expanded> + true + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/PartTrackerTests.cpp" > + <Original> + testCase.isSuccessfullyCompleted() + </Original> + <Expanded> + true + </Expanded> + </Expression> + <OverallResults successes="4" failures="0" expectedFailures="0"/> + </Section> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/PartTrackerTests.cpp" > + <Original> + testCase.isOpen() + </Original> + <Expanded> + true + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/PartTrackerTests.cpp" > + <Original> + s1.isOpen() + </Original> + <Expanded> + true + </Expanded> + </Expression> + <Section name="fail one section"> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/PartTrackerTests.cpp" > + <Original> + s1.isComplete() + </Original> + <Expanded> + true + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/PartTrackerTests.cpp" > + <Original> + s1.isSuccessfullyCompleted() == false + </Original> + <Expanded> + false == false + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/PartTrackerTests.cpp" > + <Original> + testCase.isComplete() == false + </Original> + <Expanded> + false == false + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/PartTrackerTests.cpp" > + <Original> + ctx.completedCycle() + </Original> + <Expanded> + true + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/PartTrackerTests.cpp" > + <Original> + testCase.isSuccessfullyCompleted() == false + </Original> + <Expanded> + false == false + </Expanded> + </Expression> + <Section name="re-enter after failed section"> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/PartTrackerTests.cpp" > + <Original> + testCase2.isOpen() + </Original> + <Expanded> + true + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/PartTrackerTests.cpp" > + <Original> + s1b.isOpen() == false + </Original> + <Expanded> + false == false + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/PartTrackerTests.cpp" > + <Original> + ctx.completedCycle() + </Original> + <Expanded> + true + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/PartTrackerTests.cpp" > + <Original> + testCase.isComplete() + </Original> + <Expanded> + true + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/PartTrackerTests.cpp" > + <Original> + testCase.isSuccessfullyCompleted() + </Original> + <Expanded> + true + </Expanded> + </Expression> + <OverallResults successes="5" failures="0" expectedFailures="0"/> + </Section> + <OverallResults successes="10" failures="0" expectedFailures="0"/> + </Section> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/PartTrackerTests.cpp" > + <Original> + testCase.isOpen() + </Original> + <Expanded> + true + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/PartTrackerTests.cpp" > + <Original> + s1.isOpen() + </Original> + <Expanded> + true + </Expanded> + </Expression> + <Section name="fail one section"> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/PartTrackerTests.cpp" > + <Original> + s1.isComplete() + </Original> + <Expanded> + true + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/PartTrackerTests.cpp" > + <Original> + s1.isSuccessfullyCompleted() == false + </Original> + <Expanded> + false == false + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/PartTrackerTests.cpp" > + <Original> + testCase.isComplete() == false + </Original> + <Expanded> + false == false + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/PartTrackerTests.cpp" > + <Original> + ctx.completedCycle() + </Original> + <Expanded> + true + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/PartTrackerTests.cpp" > + <Original> + testCase.isSuccessfullyCompleted() == false + </Original> + <Expanded> + false == false + </Expanded> + </Expression> + <Section name="re-enter after failed section and find next section"> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/PartTrackerTests.cpp" > + <Original> + testCase2.isOpen() + </Original> + <Expanded> + true + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/PartTrackerTests.cpp" > + <Original> + s1b.isOpen() == false + </Original> + <Expanded> + false == false + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/PartTrackerTests.cpp" > + <Original> + s2.isOpen() + </Original> + <Expanded> + true + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/PartTrackerTests.cpp" > + <Original> + ctx.completedCycle() + </Original> + <Expanded> + true + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/PartTrackerTests.cpp" > + <Original> + testCase.isComplete() + </Original> + <Expanded> + true + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/PartTrackerTests.cpp" > + <Original> + testCase.isSuccessfullyCompleted() + </Original> + <Expanded> + true + </Expanded> + </Expression> + <OverallResults successes="6" failures="0" expectedFailures="0"/> + </Section> + <OverallResults successes="11" failures="0" expectedFailures="0"/> + </Section> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/PartTrackerTests.cpp" > + <Original> + testCase.isOpen() + </Original> + <Expanded> + true + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/PartTrackerTests.cpp" > + <Original> + s1.isOpen() + </Original> + <Expanded> + true + </Expanded> + </Expression> + <Section name="successfully close one section, then find another"> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/PartTrackerTests.cpp" > + <Original> + s2.isOpen() == false + </Original> + <Expanded> + false == false + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/PartTrackerTests.cpp" > + <Original> + testCase.isComplete() == false + </Original> + <Expanded> + false == false + </Expanded> + </Expression> + <Section name="Re-enter - skips S1 and enters S2"> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/PartTrackerTests.cpp" > + <Original> + testCase2.isOpen() + </Original> + <Expanded> + true + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/PartTrackerTests.cpp" > + <Original> + s1b.isOpen() == false + </Original> + <Expanded> + false == false + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/PartTrackerTests.cpp" > + <Original> + s2b.isOpen() + </Original> + <Expanded> + true + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/PartTrackerTests.cpp" > + <Original> + ctx.completedCycle() == false + </Original> + <Expanded> + false == false + </Expanded> + </Expression> + <Section name="Successfully close S2"> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/PartTrackerTests.cpp" > + <Original> + ctx.completedCycle() + </Original> + <Expanded> + true + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/PartTrackerTests.cpp" > + <Original> + s2b.isSuccessfullyCompleted() + </Original> + <Expanded> + true + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/PartTrackerTests.cpp" > + <Original> + testCase2.isComplete() == false + </Original> + <Expanded> + false == false + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/PartTrackerTests.cpp" > + <Original> + testCase2.isSuccessfullyCompleted() + </Original> + <Expanded> + true + </Expanded> + </Expression> + <OverallResults successes="4" failures="0" expectedFailures="0"/> + </Section> + <OverallResults successes="8" failures="0" expectedFailures="0"/> + </Section> + <OverallResults successes="10" failures="0" expectedFailures="0"/> + </Section> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/PartTrackerTests.cpp" > + <Original> + testCase.isOpen() + </Original> + <Expanded> + true + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/PartTrackerTests.cpp" > + <Original> + s1.isOpen() + </Original> + <Expanded> + true + </Expanded> + </Expression> + <Section name="successfully close one section, then find another"> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/PartTrackerTests.cpp" > + <Original> + s2.isOpen() == false + </Original> + <Expanded> + false == false + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/PartTrackerTests.cpp" > + <Original> + testCase.isComplete() == false + </Original> + <Expanded> + false == false + </Expanded> + </Expression> + <Section name="Re-enter - skips S1 and enters S2"> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/PartTrackerTests.cpp" > + <Original> + testCase2.isOpen() + </Original> + <Expanded> + true + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/PartTrackerTests.cpp" > + <Original> + s1b.isOpen() == false + </Original> + <Expanded> + false == false + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/PartTrackerTests.cpp" > + <Original> + s2b.isOpen() + </Original> + <Expanded> + true + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/PartTrackerTests.cpp" > + <Original> + ctx.completedCycle() == false + </Original> + <Expanded> + false == false + </Expanded> + </Expression> + <Section name="fail S2"> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/PartTrackerTests.cpp" > + <Original> + ctx.completedCycle() + </Original> + <Expanded> + true + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/PartTrackerTests.cpp" > + <Original> + s2b.isComplete() + </Original> + <Expanded> + true + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/PartTrackerTests.cpp" > + <Original> + s2b.isSuccessfullyCompleted() == false + </Original> + <Expanded> + false == false + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/PartTrackerTests.cpp" > + <Original> + testCase2.isSuccessfullyCompleted() == false + </Original> + <Expanded> + false == false + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/PartTrackerTests.cpp" > + <Original> + testCase3.isOpen() + </Original> + <Expanded> + true + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/PartTrackerTests.cpp" > + <Original> + s1c.isOpen() == false + </Original> + <Expanded> + false == false + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/PartTrackerTests.cpp" > + <Original> + s2c.isOpen() == false + </Original> + <Expanded> + false == false + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/PartTrackerTests.cpp" > + <Original> + testCase3.isSuccessfullyCompleted() + </Original> + <Expanded> + true + </Expanded> + </Expression> + <OverallResults successes="8" failures="0" expectedFailures="0"/> + </Section> + <OverallResults successes="12" failures="0" expectedFailures="0"/> + </Section> + <OverallResults successes="14" failures="0" expectedFailures="0"/> + </Section> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/PartTrackerTests.cpp" > + <Original> + testCase.isOpen() + </Original> + <Expanded> + true + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/PartTrackerTests.cpp" > + <Original> + s1.isOpen() + </Original> + <Expanded> + true + </Expanded> + </Expression> + <Section name="open a nested section"> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/PartTrackerTests.cpp" > + <Original> + s2.isOpen() + </Original> + <Expanded> + true + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/PartTrackerTests.cpp" > + <Original> + s2.isComplete() + </Original> + <Expanded> + true + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/PartTrackerTests.cpp" > + <Original> + s1.isComplete() == false + </Original> + <Expanded> + false == false + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/PartTrackerTests.cpp" > + <Original> + s1.isComplete() + </Original> + <Expanded> + true + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/PartTrackerTests.cpp" > + <Original> + testCase.isComplete() == false + </Original> + <Expanded> + false == false + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/PartTrackerTests.cpp" > + <Original> + testCase.isComplete() + </Original> + <Expanded> + true + </Expanded> + </Expression> + <OverallResults successes="6" failures="0" expectedFailures="0"/> + </Section> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/PartTrackerTests.cpp" > + <Original> + testCase.isOpen() + </Original> + <Expanded> + true + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/PartTrackerTests.cpp" > + <Original> + s1.isOpen() + </Original> + <Expanded> + true + </Expanded> + </Expression> + <Section name="start a generator"> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/PartTrackerTests.cpp" > + <Original> + g1.isOpen() + </Original> + <Expanded> + true + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/PartTrackerTests.cpp" > + <Original> + g1.index() == 0 + </Original> + <Expanded> + 0 == 0 + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/PartTrackerTests.cpp" > + <Original> + g1.isComplete() == false + </Original> + <Expanded> + false == false + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/PartTrackerTests.cpp" > + <Original> + s1.isComplete() == false + </Original> + <Expanded> + false == false + </Expanded> + </Expression> + <Section name="close outer section"> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/PartTrackerTests.cpp" > + <Original> + s1.isComplete() == false + </Original> + <Expanded> + false == false + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/PartTrackerTests.cpp" > + <Original> + testCase.isSuccessfullyCompleted() == false + </Original> + <Expanded> + false == false + </Expanded> + </Expression> + <Section name="Re-enter for second generation"> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/PartTrackerTests.cpp" > + <Original> + testCase2.isOpen() + </Original> + <Expanded> + true + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/PartTrackerTests.cpp" > + <Original> + s1b.isOpen() + </Original> + <Expanded> + true + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/PartTrackerTests.cpp" > + <Original> + g1b.isOpen() + </Original> + <Expanded> + true + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/PartTrackerTests.cpp" > + <Original> + g1b.index() == 1 + </Original> + <Expanded> + 1 == 1 + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/PartTrackerTests.cpp" > + <Original> + s1.isComplete() == false + </Original> + <Expanded> + false == false + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/PartTrackerTests.cpp" > + <Original> + s1b.isComplete() + </Original> + <Expanded> + true + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/PartTrackerTests.cpp" > + <Original> + g1b.isComplete() + </Original> + <Expanded> + true + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/PartTrackerTests.cpp" > + <Original> + testCase2.isComplete() + </Original> + <Expanded> + true + </Expanded> + </Expression> + <OverallResults successes="8" failures="0" expectedFailures="0"/> + </Section> + <OverallResults successes="10" failures="0" expectedFailures="0"/> + </Section> + <OverallResults successes="14" failures="0" expectedFailures="0"/> + </Section> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/PartTrackerTests.cpp" > + <Original> + testCase.isOpen() + </Original> + <Expanded> + true + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/PartTrackerTests.cpp" > + <Original> + s1.isOpen() + </Original> + <Expanded> + true + </Expanded> + </Expression> + <Section name="start a generator"> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/PartTrackerTests.cpp" > + <Original> + g1.isOpen() + </Original> + <Expanded> + true + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/PartTrackerTests.cpp" > + <Original> + g1.index() == 0 + </Original> + <Expanded> + 0 == 0 + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/PartTrackerTests.cpp" > + <Original> + g1.isComplete() == false + </Original> + <Expanded> + false == false + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/PartTrackerTests.cpp" > + <Original> + s1.isComplete() == false + </Original> + <Expanded> + false == false + </Expanded> + </Expression> + <Section name="Start a new inner section"> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/PartTrackerTests.cpp" > + <Original> + s2.isOpen() + </Original> + <Expanded> + true + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/PartTrackerTests.cpp" > + <Original> + s2.isComplete() + </Original> + <Expanded> + true + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/PartTrackerTests.cpp" > + <Original> + s1.isComplete() == false + </Original> + <Expanded> + false == false + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/PartTrackerTests.cpp" > + <Original> + testCase.isComplete() == false + </Original> + <Expanded> + false == false + </Expanded> + </Expression> + <Section name="Re-enter for second generation"> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/PartTrackerTests.cpp" > + <Original> + testCase2.isOpen() + </Original> + <Expanded> + true + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/PartTrackerTests.cpp" > + <Original> + s1b.isOpen() + </Original> + <Expanded> + true + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/PartTrackerTests.cpp" > + <Original> + g1b.isOpen() + </Original> + <Expanded> + true + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/PartTrackerTests.cpp" > + <Original> + g1b.index() == 1 + </Original> + <Expanded> + 1 == 1 + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/PartTrackerTests.cpp" > + <Original> + s2b.isOpen() + </Original> + <Expanded> + true + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/PartTrackerTests.cpp" > + <Original> + s2b.isComplete() + </Original> + <Expanded> + true + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/PartTrackerTests.cpp" > + <Original> + g1b.isComplete() + </Original> + <Expanded> + true + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/PartTrackerTests.cpp" > + <Original> + s1b.isComplete() + </Original> + <Expanded> + true + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/PartTrackerTests.cpp" > + <Original> + testCase2.isComplete() + </Original> + <Expanded> + true + </Expanded> + </Expression> + <OverallResults successes="9" failures="0" expectedFailures="0"/> + </Section> + <OverallResults successes="13" failures="0" expectedFailures="0"/> + </Section> + <OverallResults successes="17" failures="0" expectedFailures="0"/> + </Section> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/PartTrackerTests.cpp" > + <Original> + testCase.isOpen() + </Original> + <Expanded> + true + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/PartTrackerTests.cpp" > + <Original> + s1.isOpen() + </Original> + <Expanded> + true + </Expanded> + </Expression> + <Section name="start a generator"> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/PartTrackerTests.cpp" > + <Original> + g1.isOpen() + </Original> + <Expanded> + true + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/PartTrackerTests.cpp" > + <Original> + g1.index() == 0 + </Original> + <Expanded> + 0 == 0 + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/PartTrackerTests.cpp" > + <Original> + g1.isComplete() == false + </Original> + <Expanded> + false == false + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/PartTrackerTests.cpp" > + <Original> + s1.isComplete() == false + </Original> + <Expanded> + false == false + </Expanded> + </Expression> + <Section name="Fail an inner section"> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/PartTrackerTests.cpp" > + <Original> + s2.isOpen() + </Original> + <Expanded> + true + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/PartTrackerTests.cpp" > + <Original> + s2.isComplete() + </Original> + <Expanded> + true + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/PartTrackerTests.cpp" > + <Original> + s2.isSuccessfullyCompleted() == false + </Original> + <Expanded> + false == false + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/PartTrackerTests.cpp" > + <Original> + s1.isComplete() == false + </Original> + <Expanded> + false == false + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/PartTrackerTests.cpp" > + <Original> + testCase.isComplete() == false + </Original> + <Expanded> + false == false + </Expanded> + </Expression> + <Section name="Re-enter for second generation"> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/PartTrackerTests.cpp" > + <Original> + testCase2.isOpen() + </Original> + <Expanded> + true + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/PartTrackerTests.cpp" > + <Original> + s1b.isOpen() + </Original> + <Expanded> + true + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/PartTrackerTests.cpp" > + <Original> + g1b.isOpen() + </Original> + <Expanded> + true + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/PartTrackerTests.cpp" > + <Original> + g1b.index() == 0 + </Original> + <Expanded> + 0 == 0 + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/PartTrackerTests.cpp" > + <Original> + s2b.isOpen() == false + </Original> + <Expanded> + false == false + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/PartTrackerTests.cpp" > + <Original> + g1b.isComplete() == false + </Original> + <Expanded> + false == false + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/PartTrackerTests.cpp" > + <Original> + s1b.isComplete() == false + </Original> + <Expanded> + false == false + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/PartTrackerTests.cpp" > + <Original> + testCase2.isComplete() == false + </Original> + <Expanded> + false == false + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/PartTrackerTests.cpp" > + <Original> + testCase3.isOpen() + </Original> + <Expanded> + true + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/PartTrackerTests.cpp" > + <Original> + s1c.isOpen() + </Original> + <Expanded> + true + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/PartTrackerTests.cpp" > + <Original> + g1c.isOpen() + </Original> + <Expanded> + true + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/PartTrackerTests.cpp" > + <Original> + g1c.index() == 1 + </Original> + <Expanded> + 1 == 1 + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/PartTrackerTests.cpp" > + <Original> + s2c.isOpen() + </Original> + <Expanded> + true + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/PartTrackerTests.cpp" > + <Original> + s2c.isComplete() + </Original> + <Expanded> + true + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/PartTrackerTests.cpp" > + <Original> + g1c.isComplete() + </Original> + <Expanded> + true + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/PartTrackerTests.cpp" > + <Original> + s1c.isComplete() + </Original> + <Expanded> + true + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/PartTrackerTests.cpp" > + <Original> + testCase3.isComplete() + </Original> + <Expanded> + true + </Expanded> + </Expression> + <OverallResults successes="17" failures="0" expectedFailures="0"/> + </Section> + <OverallResults successes="22" failures="0" expectedFailures="0"/> + </Section> + <OverallResults successes="26" failures="0" expectedFailures="0"/> + </Section> + <OverallResult success="true"/> + </TestCase> + <TestCase name="std::pair<int,std::string> -> toString"> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/ToStringPair.cpp" > + <Original> + Catch::toString( value ) == "{ 34, \"xyzzy\" }" + </Original> + <Expanded> + "{ 34, "xyzzy" }" == "{ 34, "xyzzy" }" + </Expanded> + </Expression> + <OverallResult success="true"/> + </TestCase> + <TestCase name="std::pair<int,const std::string> -> toString"> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/ToStringPair.cpp" > + <Original> + Catch::toString(value) == "{ 34, \"xyzzy\" }" + </Original> + <Expanded> + "{ 34, "xyzzy" }" == "{ 34, "xyzzy" }" + </Expanded> + </Expression> + <OverallResult success="true"/> + </TestCase> + <TestCase name="std::vector<std::pair<std::string,int> > -> toString"> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/ToStringPair.cpp" > + <Original> + Catch::toString( pr ) == "{ { \"green\", 55 } }" + </Original> + <Expanded> + "{ { "green", 55 } }" +== +"{ { "green", 55 } }" + </Expanded> + </Expression> + <OverallResult success="true"/> + </TestCase> + <TestCase name="pair<pair<int,const char *,pair<std::string,int> > -> toString"> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/ToStringPair.cpp" > + <Original> + Catch::toString( pair ) == "{ { 42, \"Arthur\" }, { \"Ford\", 24 } }" + </Original> + <Expanded> + "{ { 42, "Arthur" }, { "Ford", 24 } }" +== +"{ { 42, "Arthur" }, { "Ford", 24 } }" + </Expanded> + </Expression> + <OverallResult success="true"/> + </TestCase> + <TestCase name="vector<int> -> toString"> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/ToStringVector.cpp" > + <Original> + Catch::toString(vv) == "{ }" + </Original> + <Expanded> + "{ }" == "{ }" + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/ToStringVector.cpp" > + <Original> + Catch::toString(vv) == "{ 42 }" + </Original> + <Expanded> + "{ 42 }" == "{ 42 }" + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/ToStringVector.cpp" > + <Original> + Catch::toString(vv) == "{ 42, 250 }" + </Original> + <Expanded> + "{ 42, 250 }" == "{ 42, 250 }" + </Expanded> + </Expression> + <OverallResult success="true"/> + </TestCase> + <TestCase name="vector<string> -> toString"> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/ToStringVector.cpp" > + <Original> + Catch::toString(vv) == "{ }" + </Original> + <Expanded> + "{ }" == "{ }" + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/ToStringVector.cpp" > + <Original> + Catch::toString(vv) == "{ \"hello\" }" + </Original> + <Expanded> + "{ "hello" }" == "{ "hello" }" + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/ToStringVector.cpp" > + <Original> + Catch::toString(vv) == "{ \"hello\", \"world\" }" + </Original> + <Expanded> + "{ "hello", "world" }" +== +"{ "hello", "world" }" + </Expanded> + </Expression> + <OverallResult success="true"/> + </TestCase> + <TestCase name="vector<int,allocator> -> toString"> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/ToStringVector.cpp" > + <Original> + Catch::toString(vv) == "{ }" + </Original> + <Expanded> + "{ }" == "{ }" + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/ToStringVector.cpp" > + <Original> + Catch::toString(vv) == "{ 42 }" + </Original> + <Expanded> + "{ 42 }" == "{ 42 }" + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/ToStringVector.cpp" > + <Original> + Catch::toString(vv) == "{ 42, 250 }" + </Original> + <Expanded> + "{ 42, 250 }" == "{ 42, 250 }" + </Expanded> + </Expression> + <OverallResult success="true"/> + </TestCase> + <TestCase name="vec<vec<string,alloc>> -> toString"> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/ToStringVector.cpp" > + <Original> + Catch::toString(v) == "{ }" + </Original> + <Expanded> + "{ }" == "{ }" + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/ToStringVector.cpp" > + <Original> + Catch::toString(v) == "{ { \"hello\" }, { \"world\" } }" + </Original> + <Expanded> + "{ { "hello" }, { "world" } }" +== +"{ { "hello" }, { "world" } }" + </Expanded> + </Expression> + <OverallResult success="true"/> + </TestCase> + <TestCase name="Parse test names and tags"> + <Section name="Empty test spec should have no filters"> + <Expression success="true" type="CHECK" filename="projects/SelfTest/CmdLineTests.cpp" > + <Original> + spec.hasFilters() == false + </Original> + <Expanded> + false == false + </Expanded> + </Expression> + <Expression success="true" type="CHECK" filename="projects/SelfTest/CmdLineTests.cpp" > + <Original> + spec.matches( tcA ) == false + </Original> + <Expanded> + false == false + </Expanded> + </Expression> + <Expression success="true" type="CHECK" filename="projects/SelfTest/CmdLineTests.cpp" > + <Original> + spec.matches( tcB ) == false + </Original> + <Expanded> + false == false + </Expanded> + </Expression> + <OverallResults successes="3" failures="0" expectedFailures="0"/> + </Section> + <Section name="Test spec from empty string should have no filters"> + <Expression success="true" type="CHECK" filename="projects/SelfTest/CmdLineTests.cpp" > + <Original> + spec.hasFilters() == false + </Original> + <Expanded> + false == false + </Expanded> + </Expression> + <Expression success="true" type="CHECK" filename="projects/SelfTest/CmdLineTests.cpp" > + <Original> + spec.matches(tcA ) == false + </Original> + <Expanded> + false == false + </Expanded> + </Expression> + <Expression success="true" type="CHECK" filename="projects/SelfTest/CmdLineTests.cpp" > + <Original> + spec.matches( tcB ) == false + </Original> + <Expanded> + false == false + </Expanded> + </Expression> + <OverallResults successes="3" failures="0" expectedFailures="0"/> + </Section> + <Section name="Test spec from just a comma should have no filters"> + <Expression success="true" type="CHECK" filename="projects/SelfTest/CmdLineTests.cpp" > + <Original> + spec.hasFilters() == false + </Original> + <Expanded> + false == false + </Expanded> + </Expression> + <Expression success="true" type="CHECK" filename="projects/SelfTest/CmdLineTests.cpp" > + <Original> + spec.matches( tcA ) == false + </Original> + <Expanded> + false == false + </Expanded> + </Expression> + <Expression success="true" type="CHECK" filename="projects/SelfTest/CmdLineTests.cpp" > + <Original> + spec.matches( tcB ) == false + </Original> + <Expanded> + false == false + </Expanded> + </Expression> + <OverallResults successes="3" failures="0" expectedFailures="0"/> + </Section> + <Section name="Test spec from name should have one filter"> + <Expression success="true" type="CHECK" filename="projects/SelfTest/CmdLineTests.cpp" > + <Original> + spec.hasFilters() == true + </Original> + <Expanded> + true == true + </Expanded> + </Expression> + <Expression success="true" type="CHECK" filename="projects/SelfTest/CmdLineTests.cpp" > + <Original> + spec.matches( tcA ) == false + </Original> + <Expanded> + false == false + </Expanded> + </Expression> + <Expression success="true" type="CHECK" filename="projects/SelfTest/CmdLineTests.cpp" > + <Original> + spec.matches( tcB ) == true + </Original> + <Expanded> + true == true + </Expanded> + </Expression> + <OverallResults successes="3" failures="0" expectedFailures="0"/> + </Section> + <Section name="Test spec from quoted name should have one filter"> + <Expression success="true" type="CHECK" filename="projects/SelfTest/CmdLineTests.cpp" > + <Original> + spec.hasFilters() == true + </Original> + <Expanded> + true == true + </Expanded> + </Expression> + <Expression success="true" type="CHECK" filename="projects/SelfTest/CmdLineTests.cpp" > + <Original> + spec.matches( tcA ) == false + </Original> + <Expanded> + false == false + </Expanded> + </Expression> + <Expression success="true" type="CHECK" filename="projects/SelfTest/CmdLineTests.cpp" > + <Original> + spec.matches( tcB ) == true + </Original> + <Expanded> + true == true + </Expanded> + </Expression> + <OverallResults successes="3" failures="0" expectedFailures="0"/> + </Section> + <Section name="Test spec from name should have one filter"> + <Expression success="true" type="CHECK" filename="projects/SelfTest/CmdLineTests.cpp" > + <Original> + spec.hasFilters() == true + </Original> + <Expanded> + true == true + </Expanded> + </Expression> + <Expression success="true" type="CHECK" filename="projects/SelfTest/CmdLineTests.cpp" > + <Original> + spec.matches( tcA ) == false + </Original> + <Expanded> + false == false + </Expanded> + </Expression> + <Expression success="true" type="CHECK" filename="projects/SelfTest/CmdLineTests.cpp" > + <Original> + spec.matches( tcB ) == true + </Original> + <Expanded> + true == true + </Expanded> + </Expression> + <Expression success="true" type="CHECK" filename="projects/SelfTest/CmdLineTests.cpp" > + <Original> + spec.matches( tcC ) == false + </Original> + <Expanded> + false == false + </Expanded> + </Expression> + <OverallResults successes="4" failures="0" expectedFailures="0"/> + </Section> + <Section name="Wildcard at the start"> + <Expression success="true" type="CHECK" filename="projects/SelfTest/CmdLineTests.cpp" > + <Original> + spec.hasFilters() == true + </Original> + <Expanded> + true == true + </Expanded> + </Expression> + <Expression success="true" type="CHECK" filename="projects/SelfTest/CmdLineTests.cpp" > + <Original> + spec.matches( tcA ) == false + </Original> + <Expanded> + false == false + </Expanded> + </Expression> + <Expression success="true" type="CHECK" filename="projects/SelfTest/CmdLineTests.cpp" > + <Original> + spec.matches( tcB ) == false + </Original> + <Expanded> + false == false + </Expanded> + </Expression> + <Expression success="true" type="CHECK" filename="projects/SelfTest/CmdLineTests.cpp" > + <Original> + spec.matches( tcC ) == true + </Original> + <Expanded> + true == true + </Expanded> + </Expression> + <Expression success="true" type="CHECK" filename="projects/SelfTest/CmdLineTests.cpp" > + <Original> + spec.matches( tcD ) == false + </Original> + <Expanded> + false == false + </Expanded> + </Expression> + <Expression success="true" type="CHECK" filename="projects/SelfTest/CmdLineTests.cpp" > + <Original> + parseTestSpec( "*a" ).matches( tcA ) == true + </Original> + <Expanded> + true == true + </Expanded> + </Expression> + <OverallResults successes="6" failures="0" expectedFailures="0"/> + </Section> + <Section name="Wildcard at the end"> + <Expression success="true" type="CHECK" filename="projects/SelfTest/CmdLineTests.cpp" > + <Original> + spec.hasFilters() == true + </Original> + <Expanded> + true == true + </Expanded> + </Expression> + <Expression success="true" type="CHECK" filename="projects/SelfTest/CmdLineTests.cpp" > + <Original> + spec.matches( tcA ) == false + </Original> + <Expanded> + false == false + </Expanded> + </Expression> + <Expression success="true" type="CHECK" filename="projects/SelfTest/CmdLineTests.cpp" > + <Original> + spec.matches( tcB ) == false + </Original> + <Expanded> + false == false + </Expanded> + </Expression> + <Expression success="true" type="CHECK" filename="projects/SelfTest/CmdLineTests.cpp" > + <Original> + spec.matches( tcC ) == true + </Original> + <Expanded> + true == true + </Expanded> + </Expression> + <Expression success="true" type="CHECK" filename="projects/SelfTest/CmdLineTests.cpp" > + <Original> + spec.matches( tcD ) == false + </Original> + <Expanded> + false == false + </Expanded> + </Expression> + <Expression success="true" type="CHECK" filename="projects/SelfTest/CmdLineTests.cpp" > + <Original> + parseTestSpec( "a*" ).matches( tcA ) == true + </Original> + <Expanded> + true == true + </Expanded> + </Expression> + <OverallResults successes="6" failures="0" expectedFailures="0"/> + </Section> + <Section name="Wildcard at both ends"> + <Expression success="true" type="CHECK" filename="projects/SelfTest/CmdLineTests.cpp" > + <Original> + spec.hasFilters() == true + </Original> + <Expanded> + true == true + </Expanded> + </Expression> + <Expression success="true" type="CHECK" filename="projects/SelfTest/CmdLineTests.cpp" > + <Original> + spec.matches( tcA ) == false + </Original> + <Expanded> + false == false + </Expanded> + </Expression> + <Expression success="true" type="CHECK" filename="projects/SelfTest/CmdLineTests.cpp" > + <Original> + spec.matches( tcB ) == false + </Original> + <Expanded> + false == false + </Expanded> + </Expression> + <Expression success="true" type="CHECK" filename="projects/SelfTest/CmdLineTests.cpp" > + <Original> + spec.matches( tcC ) == true + </Original> + <Expanded> + true == true + </Expanded> + </Expression> + <Expression success="true" type="CHECK" filename="projects/SelfTest/CmdLineTests.cpp" > + <Original> + spec.matches( tcD ) == true + </Original> + <Expanded> + true == true + </Expanded> + </Expression> + <Expression success="true" type="CHECK" filename="projects/SelfTest/CmdLineTests.cpp" > + <Original> + parseTestSpec( "*a*" ).matches( tcA ) == true + </Original> + <Expanded> + true == true + </Expanded> + </Expression> + <OverallResults successes="6" failures="0" expectedFailures="0"/> + </Section> + <Section name="Redundant wildcard at the start"> + <Expression success="true" type="CHECK" filename="projects/SelfTest/CmdLineTests.cpp" > + <Original> + spec.hasFilters() == true + </Original> + <Expanded> + true == true + </Expanded> + </Expression> + <Expression success="true" type="CHECK" filename="projects/SelfTest/CmdLineTests.cpp" > + <Original> + spec.matches( tcA ) == true + </Original> + <Expanded> + true == true + </Expanded> + </Expression> + <Expression success="true" type="CHECK" filename="projects/SelfTest/CmdLineTests.cpp" > + <Original> + spec.matches( tcB ) == false + </Original> + <Expanded> + false == false + </Expanded> + </Expression> + <OverallResults successes="3" failures="0" expectedFailures="0"/> + </Section> + <Section name="Redundant wildcard at the end"> + <Expression success="true" type="CHECK" filename="projects/SelfTest/CmdLineTests.cpp" > + <Original> + spec.hasFilters() == true + </Original> + <Expanded> + true == true + </Expanded> + </Expression> + <Expression success="true" type="CHECK" filename="projects/SelfTest/CmdLineTests.cpp" > + <Original> + spec.matches( tcA ) == true + </Original> + <Expanded> + true == true + </Expanded> + </Expression> + <Expression success="true" type="CHECK" filename="projects/SelfTest/CmdLineTests.cpp" > + <Original> + spec.matches( tcB ) == false + </Original> + <Expanded> + false == false + </Expanded> + </Expression> + <OverallResults successes="3" failures="0" expectedFailures="0"/> + </Section> + <Section name="Redundant wildcard at both ends"> + <Expression success="true" type="CHECK" filename="projects/SelfTest/CmdLineTests.cpp" > + <Original> + spec.hasFilters() == true + </Original> + <Expanded> + true == true + </Expanded> + </Expression> + <Expression success="true" type="CHECK" filename="projects/SelfTest/CmdLineTests.cpp" > + <Original> + spec.matches( tcA ) == true + </Original> + <Expanded> + true == true + </Expanded> + </Expression> + <Expression success="true" type="CHECK" filename="projects/SelfTest/CmdLineTests.cpp" > + <Original> + spec.matches( tcB ) == false + </Original> + <Expanded> + false == false + </Expanded> + </Expression> + <OverallResults successes="3" failures="0" expectedFailures="0"/> + </Section> + <Section name="Wildcard at both ends, redundant at start"> + <Expression success="true" type="CHECK" filename="projects/SelfTest/CmdLineTests.cpp" > + <Original> + spec.hasFilters() == true + </Original> + <Expanded> + true == true + </Expanded> + </Expression> + <Expression success="true" type="CHECK" filename="projects/SelfTest/CmdLineTests.cpp" > + <Original> + spec.matches( tcA ) == false + </Original> + <Expanded> + false == false + </Expanded> + </Expression> + <Expression success="true" type="CHECK" filename="projects/SelfTest/CmdLineTests.cpp" > + <Original> + spec.matches( tcB ) == false + </Original> + <Expanded> + false == false + </Expanded> + </Expression> + <Expression success="true" type="CHECK" filename="projects/SelfTest/CmdLineTests.cpp" > + <Original> + spec.matches( tcC ) == true + </Original> + <Expanded> + true == true + </Expanded> + </Expression> + <Expression success="true" type="CHECK" filename="projects/SelfTest/CmdLineTests.cpp" > + <Original> + spec.matches( tcD ) == true + </Original> + <Expanded> + true == true + </Expanded> + </Expression> + <OverallResults successes="5" failures="0" expectedFailures="0"/> + </Section> + <Section name="Just wildcard"> + <Expression success="true" type="CHECK" filename="projects/SelfTest/CmdLineTests.cpp" > + <Original> + spec.hasFilters() == true + </Original> + <Expanded> + true == true + </Expanded> + </Expression> + <Expression success="true" type="CHECK" filename="projects/SelfTest/CmdLineTests.cpp" > + <Original> + spec.matches( tcA ) == true + </Original> + <Expanded> + true == true + </Expanded> + </Expression> + <Expression success="true" type="CHECK" filename="projects/SelfTest/CmdLineTests.cpp" > + <Original> + spec.matches( tcB ) == true + </Original> + <Expanded> + true == true + </Expanded> + </Expression> + <Expression success="true" type="CHECK" filename="projects/SelfTest/CmdLineTests.cpp" > + <Original> + spec.matches( tcC ) == true + </Original> + <Expanded> + true == true + </Expanded> + </Expression> + <Expression success="true" type="CHECK" filename="projects/SelfTest/CmdLineTests.cpp" > + <Original> + spec.matches( tcD ) == true + </Original> + <Expanded> + true == true + </Expanded> + </Expression> + <OverallResults successes="5" failures="0" expectedFailures="0"/> + </Section> + <Section name="Single tag"> + <Expression success="true" type="CHECK" filename="projects/SelfTest/CmdLineTests.cpp" > + <Original> + spec.hasFilters() == true + </Original> + <Expanded> + true == true + </Expanded> + </Expression> + <Expression success="true" type="CHECK" filename="projects/SelfTest/CmdLineTests.cpp" > + <Original> + spec.matches( tcA ) == false + </Original> + <Expanded> + false == false + </Expanded> + </Expression> + <Expression success="true" type="CHECK" filename="projects/SelfTest/CmdLineTests.cpp" > + <Original> + spec.matches( tcB ) == true + </Original> + <Expanded> + true == true + </Expanded> + </Expression> + <Expression success="true" type="CHECK" filename="projects/SelfTest/CmdLineTests.cpp" > + <Original> + spec.matches( tcC ) == false + </Original> + <Expanded> + false == false + </Expanded> + </Expression> + <OverallResults successes="4" failures="0" expectedFailures="0"/> + </Section> + <Section name="Single tag, two matches"> + <Expression success="true" type="CHECK" filename="projects/SelfTest/CmdLineTests.cpp" > + <Original> + spec.hasFilters() == true + </Original> + <Expanded> + true == true + </Expanded> + </Expression> + <Expression success="true" type="CHECK" filename="projects/SelfTest/CmdLineTests.cpp" > + <Original> + spec.matches( tcA ) == false + </Original> + <Expanded> + false == false + </Expanded> + </Expression> + <Expression success="true" type="CHECK" filename="projects/SelfTest/CmdLineTests.cpp" > + <Original> + spec.matches( tcB ) == true + </Original> + <Expanded> + true == true + </Expanded> + </Expression> + <Expression success="true" type="CHECK" filename="projects/SelfTest/CmdLineTests.cpp" > + <Original> + spec.matches( tcC ) == true + </Original> + <Expanded> + true == true + </Expanded> + </Expression> + <OverallResults successes="4" failures="0" expectedFailures="0"/> + </Section> + <Section name="Two tags"> + <Expression success="true" type="CHECK" filename="projects/SelfTest/CmdLineTests.cpp" > + <Original> + spec.hasFilters() == true + </Original> + <Expanded> + true == true + </Expanded> + </Expression> + <Expression success="true" type="CHECK" filename="projects/SelfTest/CmdLineTests.cpp" > + <Original> + spec.matches( tcA ) == false + </Original> + <Expanded> + false == false + </Expanded> + </Expression> + <Expression success="true" type="CHECK" filename="projects/SelfTest/CmdLineTests.cpp" > + <Original> + spec.matches( tcB ) == false + </Original> + <Expanded> + false == false + </Expanded> + </Expression> + <Expression success="true" type="CHECK" filename="projects/SelfTest/CmdLineTests.cpp" > + <Original> + spec.matches( tcC ) == true + </Original> + <Expanded> + true == true + </Expanded> + </Expression> + <OverallResults successes="4" failures="0" expectedFailures="0"/> + </Section> + <Section name="Two tags, spare separated"> + <Expression success="true" type="CHECK" filename="projects/SelfTest/CmdLineTests.cpp" > + <Original> + spec.hasFilters() == true + </Original> + <Expanded> + true == true + </Expanded> + </Expression> + <Expression success="true" type="CHECK" filename="projects/SelfTest/CmdLineTests.cpp" > + <Original> + spec.matches( tcA ) == false + </Original> + <Expanded> + false == false + </Expanded> + </Expression> + <Expression success="true" type="CHECK" filename="projects/SelfTest/CmdLineTests.cpp" > + <Original> + spec.matches( tcB ) == false + </Original> + <Expanded> + false == false + </Expanded> + </Expression> + <Expression success="true" type="CHECK" filename="projects/SelfTest/CmdLineTests.cpp" > + <Original> + spec.matches( tcC ) == true + </Original> + <Expanded> + true == true + </Expanded> + </Expression> + <OverallResults successes="4" failures="0" expectedFailures="0"/> + </Section> + <Section name="Wildcarded name and tag"> + <Expression success="true" type="CHECK" filename="projects/SelfTest/CmdLineTests.cpp" > + <Original> + spec.hasFilters() == true + </Original> + <Expanded> + true == true + </Expanded> + </Expression> + <Expression success="true" type="CHECK" filename="projects/SelfTest/CmdLineTests.cpp" > + <Original> + spec.matches( tcA ) == false + </Original> + <Expanded> + false == false + </Expanded> + </Expression> + <Expression success="true" type="CHECK" filename="projects/SelfTest/CmdLineTests.cpp" > + <Original> + spec.matches( tcB ) == false + </Original> + <Expanded> + false == false + </Expanded> + </Expression> + <Expression success="true" type="CHECK" filename="projects/SelfTest/CmdLineTests.cpp" > + <Original> + spec.matches( tcC ) == true + </Original> + <Expanded> + true == true + </Expanded> + </Expression> + <Expression success="true" type="CHECK" filename="projects/SelfTest/CmdLineTests.cpp" > + <Original> + spec.matches( tcD ) == false + </Original> + <Expanded> + false == false + </Expanded> + </Expression> + <OverallResults successes="5" failures="0" expectedFailures="0"/> + </Section> + <Section name="Single tag exclusion"> + <Expression success="true" type="CHECK" filename="projects/SelfTest/CmdLineTests.cpp" > + <Original> + spec.hasFilters() == true + </Original> + <Expanded> + true == true + </Expanded> + </Expression> + <Expression success="true" type="CHECK" filename="projects/SelfTest/CmdLineTests.cpp" > + <Original> + spec.matches( tcA ) == true + </Original> + <Expanded> + true == true + </Expanded> + </Expression> + <Expression success="true" type="CHECK" filename="projects/SelfTest/CmdLineTests.cpp" > + <Original> + spec.matches( tcB ) == false + </Original> + <Expanded> + false == false + </Expanded> + </Expression> + <Expression success="true" type="CHECK" filename="projects/SelfTest/CmdLineTests.cpp" > + <Original> + spec.matches( tcC ) == true + </Original> + <Expanded> + true == true + </Expanded> + </Expression> + <OverallResults successes="4" failures="0" expectedFailures="0"/> + </Section> + <Section name="One tag exclusion and one tag inclusion"> + <Expression success="true" type="CHECK" filename="projects/SelfTest/CmdLineTests.cpp" > + <Original> + spec.hasFilters() == true + </Original> + <Expanded> + true == true + </Expanded> + </Expression> + <Expression success="true" type="CHECK" filename="projects/SelfTest/CmdLineTests.cpp" > + <Original> + spec.matches( tcA ) == false + </Original> + <Expanded> + false == false + </Expanded> + </Expression> + <Expression success="true" type="CHECK" filename="projects/SelfTest/CmdLineTests.cpp" > + <Original> + spec.matches( tcB ) == true + </Original> + <Expanded> + true == true + </Expanded> + </Expression> + <Expression success="true" type="CHECK" filename="projects/SelfTest/CmdLineTests.cpp" > + <Original> + spec.matches( tcC ) == false + </Original> + <Expanded> + false == false + </Expanded> + </Expression> + <OverallResults successes="4" failures="0" expectedFailures="0"/> + </Section> + <Section name="One tag exclusion and one wldcarded name inclusion"> + <Expression success="true" type="CHECK" filename="projects/SelfTest/CmdLineTests.cpp" > + <Original> + spec.hasFilters() == true + </Original> + <Expanded> + true == true + </Expanded> + </Expression> + <Expression success="true" type="CHECK" filename="projects/SelfTest/CmdLineTests.cpp" > + <Original> + spec.matches( tcA ) == false + </Original> + <Expanded> + false == false + </Expanded> + </Expression> + <Expression success="true" type="CHECK" filename="projects/SelfTest/CmdLineTests.cpp" > + <Original> + spec.matches( tcB ) == false + </Original> + <Expanded> + false == false + </Expanded> + </Expression> + <Expression success="true" type="CHECK" filename="projects/SelfTest/CmdLineTests.cpp" > + <Original> + spec.matches( tcC ) == false + </Original> + <Expanded> + false == false + </Expanded> + </Expression> + <Expression success="true" type="CHECK" filename="projects/SelfTest/CmdLineTests.cpp" > + <Original> + spec.matches( tcD ) == true + </Original> + <Expanded> + true == true + </Expanded> + </Expression> + <OverallResults successes="5" failures="0" expectedFailures="0"/> + </Section> + <Section name="One tag exclusion, using exclude:, and one wldcarded name inclusion"> + <Expression success="true" type="CHECK" filename="projects/SelfTest/CmdLineTests.cpp" > + <Original> + spec.hasFilters() == true + </Original> + <Expanded> + true == true + </Expanded> + </Expression> + <Expression success="true" type="CHECK" filename="projects/SelfTest/CmdLineTests.cpp" > + <Original> + spec.matches( tcA ) == false + </Original> + <Expanded> + false == false + </Expanded> + </Expression> + <Expression success="true" type="CHECK" filename="projects/SelfTest/CmdLineTests.cpp" > + <Original> + spec.matches( tcB ) == false + </Original> + <Expanded> + false == false + </Expanded> + </Expression> + <Expression success="true" type="CHECK" filename="projects/SelfTest/CmdLineTests.cpp" > + <Original> + spec.matches( tcC ) == false + </Original> + <Expanded> + false == false + </Expanded> + </Expression> + <Expression success="true" type="CHECK" filename="projects/SelfTest/CmdLineTests.cpp" > + <Original> + spec.matches( tcD ) == true + </Original> + <Expanded> + true == true + </Expanded> + </Expression> + <OverallResults successes="5" failures="0" expectedFailures="0"/> + </Section> + <Section name="name exclusion"> + <Expression success="true" type="CHECK" filename="projects/SelfTest/CmdLineTests.cpp" > + <Original> + spec.hasFilters() == true + </Original> + <Expanded> + true == true + </Expanded> + </Expression> + <Expression success="true" type="CHECK" filename="projects/SelfTest/CmdLineTests.cpp" > + <Original> + spec.matches( tcA ) == true + </Original> + <Expanded> + true == true + </Expanded> + </Expression> + <Expression success="true" type="CHECK" filename="projects/SelfTest/CmdLineTests.cpp" > + <Original> + spec.matches( tcB ) == false + </Original> + <Expanded> + false == false + </Expanded> + </Expression> + <Expression success="true" type="CHECK" filename="projects/SelfTest/CmdLineTests.cpp" > + <Original> + spec.matches( tcC ) == true + </Original> + <Expanded> + true == true + </Expanded> + </Expression> + <Expression success="true" type="CHECK" filename="projects/SelfTest/CmdLineTests.cpp" > + <Original> + spec.matches( tcD ) == true + </Original> + <Expanded> + true == true + </Expanded> + </Expression> + <OverallResults successes="5" failures="0" expectedFailures="0"/> + </Section> + <Section name="wildcarded name exclusion"> + <Expression success="true" type="CHECK" filename="projects/SelfTest/CmdLineTests.cpp" > + <Original> + spec.hasFilters() == true + </Original> + <Expanded> + true == true + </Expanded> + </Expression> + <Expression success="true" type="CHECK" filename="projects/SelfTest/CmdLineTests.cpp" > + <Original> + spec.matches( tcA ) == true + </Original> + <Expanded> + true == true + </Expanded> + </Expression> + <Expression success="true" type="CHECK" filename="projects/SelfTest/CmdLineTests.cpp" > + <Original> + spec.matches( tcB ) == true + </Original> + <Expanded> + true == true + </Expanded> + </Expression> + <Expression success="true" type="CHECK" filename="projects/SelfTest/CmdLineTests.cpp" > + <Original> + spec.matches( tcC ) == false + </Original> + <Expanded> + false == false + </Expanded> + </Expression> + <Expression success="true" type="CHECK" filename="projects/SelfTest/CmdLineTests.cpp" > + <Original> + spec.matches( tcD ) == false + </Original> + <Expanded> + false == false + </Expanded> + </Expression> + <OverallResults successes="5" failures="0" expectedFailures="0"/> + </Section> + <Section name="wildcarded name exclusion with tag inclusion"> + <Expression success="true" type="CHECK" filename="projects/SelfTest/CmdLineTests.cpp" > + <Original> + spec.hasFilters() == true + </Original> + <Expanded> + true == true + </Expanded> + </Expression> + <Expression success="true" type="CHECK" filename="projects/SelfTest/CmdLineTests.cpp" > + <Original> + spec.matches( tcA ) == true + </Original> + <Expanded> + true == true + </Expanded> + </Expression> + <Expression success="true" type="CHECK" filename="projects/SelfTest/CmdLineTests.cpp" > + <Original> + spec.matches( tcB ) == true + </Original> + <Expanded> + true == true + </Expanded> + </Expression> + <Expression success="true" type="CHECK" filename="projects/SelfTest/CmdLineTests.cpp" > + <Original> + spec.matches( tcC ) == true + </Original> + <Expanded> + true == true + </Expanded> + </Expression> + <Expression success="true" type="CHECK" filename="projects/SelfTest/CmdLineTests.cpp" > + <Original> + spec.matches( tcD ) == false + </Original> + <Expanded> + false == false + </Expanded> + </Expression> + <OverallResults successes="5" failures="0" expectedFailures="0"/> + </Section> + <Section name="wildcarded name exclusion, using exclude:, with tag inclusion"> + <Expression success="true" type="CHECK" filename="projects/SelfTest/CmdLineTests.cpp" > + <Original> + spec.hasFilters() == true + </Original> + <Expanded> + true == true + </Expanded> + </Expression> + <Expression success="true" type="CHECK" filename="projects/SelfTest/CmdLineTests.cpp" > + <Original> + spec.matches( tcA ) == true + </Original> + <Expanded> + true == true + </Expanded> + </Expression> + <Expression success="true" type="CHECK" filename="projects/SelfTest/CmdLineTests.cpp" > + <Original> + spec.matches( tcB ) == true + </Original> + <Expanded> + true == true + </Expanded> + </Expression> + <Expression success="true" type="CHECK" filename="projects/SelfTest/CmdLineTests.cpp" > + <Original> + spec.matches( tcC ) == true + </Original> + <Expanded> + true == true + </Expanded> + </Expression> + <Expression success="true" type="CHECK" filename="projects/SelfTest/CmdLineTests.cpp" > + <Original> + spec.matches( tcD ) == false + </Original> + <Expanded> + false == false + </Expanded> + </Expression> + <OverallResults successes="5" failures="0" expectedFailures="0"/> + </Section> + <Section name="two wildcarded names"> + <Expression success="true" type="CHECK" filename="projects/SelfTest/CmdLineTests.cpp" > + <Original> + spec.hasFilters() == true + </Original> + <Expanded> + true == true + </Expanded> + </Expression> + <Expression success="true" type="CHECK" filename="projects/SelfTest/CmdLineTests.cpp" > + <Original> + spec.matches( tcA ) == false + </Original> + <Expanded> + false == false + </Expanded> + </Expression> + <Expression success="true" type="CHECK" filename="projects/SelfTest/CmdLineTests.cpp" > + <Original> + spec.matches( tcB ) == false + </Original> + <Expanded> + false == false + </Expanded> + </Expression> + <Expression success="true" type="CHECK" filename="projects/SelfTest/CmdLineTests.cpp" > + <Original> + spec.matches( tcC ) == true + </Original> + <Expanded> + true == true + </Expanded> + </Expression> + <Expression success="true" type="CHECK" filename="projects/SelfTest/CmdLineTests.cpp" > + <Original> + spec.matches( tcD ) == false + </Original> + <Expanded> + false == false + </Expanded> + </Expression> + <OverallResults successes="5" failures="0" expectedFailures="0"/> + </Section> + <Section name="empty tag"> + <Expression success="true" type="CHECK" filename="projects/SelfTest/CmdLineTests.cpp" > + <Original> + spec.hasFilters() == false + </Original> + <Expanded> + false == false + </Expanded> + </Expression> + <Expression success="true" type="CHECK" filename="projects/SelfTest/CmdLineTests.cpp" > + <Original> + spec.matches( tcA ) == false + </Original> + <Expanded> + false == false + </Expanded> + </Expression> + <Expression success="true" type="CHECK" filename="projects/SelfTest/CmdLineTests.cpp" > + <Original> + spec.matches( tcB ) == false + </Original> + <Expanded> + false == false + </Expanded> + </Expression> + <Expression success="true" type="CHECK" filename="projects/SelfTest/CmdLineTests.cpp" > + <Original> + spec.matches( tcC ) == false + </Original> + <Expanded> + false == false + </Expanded> + </Expression> + <Expression success="true" type="CHECK" filename="projects/SelfTest/CmdLineTests.cpp" > + <Original> + spec.matches( tcD ) == false + </Original> + <Expanded> + false == false + </Expanded> + </Expression> + <OverallResults successes="5" failures="0" expectedFailures="0"/> + </Section> + <Section name="empty quoted name"> + <Expression success="true" type="CHECK" filename="projects/SelfTest/CmdLineTests.cpp" > + <Original> + spec.hasFilters() == false + </Original> + <Expanded> + false == false + </Expanded> + </Expression> + <Expression success="true" type="CHECK" filename="projects/SelfTest/CmdLineTests.cpp" > + <Original> + spec.matches( tcA ) == false + </Original> + <Expanded> + false == false + </Expanded> + </Expression> + <Expression success="true" type="CHECK" filename="projects/SelfTest/CmdLineTests.cpp" > + <Original> + spec.matches( tcB ) == false + </Original> + <Expanded> + false == false + </Expanded> + </Expression> + <Expression success="true" type="CHECK" filename="projects/SelfTest/CmdLineTests.cpp" > + <Original> + spec.matches( tcC ) == false + </Original> + <Expanded> + false == false + </Expanded> + </Expression> + <Expression success="true" type="CHECK" filename="projects/SelfTest/CmdLineTests.cpp" > + <Original> + spec.matches( tcD ) == false + </Original> + <Expanded> + false == false + </Expanded> + </Expression> + <OverallResults successes="5" failures="0" expectedFailures="0"/> + </Section> + <Section name="quoted string followed by tag exclusion"> + <Expression success="true" type="CHECK" filename="projects/SelfTest/CmdLineTests.cpp" > + <Original> + spec.hasFilters() == true + </Original> + <Expanded> + true == true + </Expanded> + </Expression> + <Expression success="true" type="CHECK" filename="projects/SelfTest/CmdLineTests.cpp" > + <Original> + spec.matches( tcA ) == false + </Original> + <Expanded> + false == false + </Expanded> + </Expression> + <Expression success="true" type="CHECK" filename="projects/SelfTest/CmdLineTests.cpp" > + <Original> + spec.matches( tcB ) == false + </Original> + <Expanded> + false == false + </Expanded> + </Expression> + <Expression success="true" type="CHECK" filename="projects/SelfTest/CmdLineTests.cpp" > + <Original> + spec.matches( tcC ) == false + </Original> + <Expanded> + false == false + </Expanded> + </Expression> + <Expression success="true" type="CHECK" filename="projects/SelfTest/CmdLineTests.cpp" > + <Original> + spec.matches( tcD ) == true + </Original> + <Expanded> + true == true + </Expanded> + </Expression> + <OverallResults successes="5" failures="0" expectedFailures="0"/> + </Section> + <OverallResult success="true"/> + </TestCase> + <TestCase name="tuple<>"> + <Expression success="true" type="CHECK" filename="projects/SelfTest/ToStringTuple.cpp" > + <Original> + "{ }" == Catch::toString(type{}) + </Original> + <Expanded> + "{ }" == "{ }" + </Expanded> + </Expression> + <Expression success="true" type="CHECK" filename="projects/SelfTest/ToStringTuple.cpp" > + <Original> + "{ }" == Catch::toString(value) + </Original> + <Expanded> + "{ }" == "{ }" + </Expanded> + </Expression> + <OverallResult success="true"/> + </TestCase> + <TestCase name="tuple<int>"> + <Expression success="true" type="CHECK" filename="projects/SelfTest/ToStringTuple.cpp" > + <Original> + "{ 0 }" == Catch::toString(type{0}) + </Original> + <Expanded> + "{ 0 }" == "{ 0 }" + </Expanded> + </Expression> + <OverallResult success="true"/> + </TestCase> + <TestCase name="tuple<float,int>"> + <Expression success="true" type="CHECK" filename="projects/SelfTest/ToStringTuple.cpp" > + <Original> + "1.2f" == Catch::toString(float(1.2)) + </Original> + <Expanded> + "1.2f" == "1.2f" + </Expanded> + </Expression> + <Expression success="true" type="CHECK" filename="projects/SelfTest/ToStringTuple.cpp" > + <Original> + "{ 1.2f, 0 }" == Catch::toString(type{1.2,0}) + </Original> + <Expanded> + "{ 1.2f, 0 }" == "{ 1.2f, 0 }" + </Expanded> + </Expression> + <OverallResult success="true"/> + </TestCase> + <TestCase name="tuple<string,string>"> + <Expression success="true" type="CHECK" filename="projects/SelfTest/ToStringTuple.cpp" > + <Original> + "{ \"hello\", \"world\" }" == Catch::toString(type{"hello","world"}) + </Original> + <Expanded> + "{ "hello", "world" }" +== +"{ "hello", "world" }" + </Expanded> + </Expression> + <OverallResult success="true"/> + </TestCase> + <TestCase name="tuple<tuple<int>,tuple<>,float>"> + <Expression success="true" type="CHECK" filename="projects/SelfTest/ToStringTuple.cpp" > + <Original> + "{ { 42 }, { }, 1.2f }" == Catch::toString(value) + </Original> + <Expanded> + "{ { 42 }, { }, 1.2f }" +== +"{ { 42 }, { }, 1.2f }" + </Expanded> + </Expression> + <OverallResult success="true"/> + </TestCase> + <TestCase name="tuple<nullptr,int,const char *>"> + <Expression success="true" type="CHECK" filename="projects/SelfTest/ToStringTuple.cpp" > + <Original> + "{ nullptr, 42, \"Catch me\" }" == Catch::toString(value) + </Original> + <Expanded> + "{ nullptr, 42, "Catch me" }" +== +"{ nullptr, 42, "Catch me" }" + </Expanded> + </Expression> + <OverallResult success="true"/> + </TestCase> + <TestCase name="Tag alias can be registered against tag patterns"> + <Section name="The same tag alias can only be registered once"> + <Expression success="true" type="CHECK_THAT" filename="projects/SelfTest/TagAliasTests.cpp" > + <Original> + what, Contains( "[@zzz]" ) + </Original> + <Expanded> + "error: tag alias, "[@zzz]" already registered. + First seen at file:2 + Redefined at file:10" contains: "[@zzz]" + </Expanded> + </Expression> + <Expression success="true" type="CHECK_THAT" filename="projects/SelfTest/TagAliasTests.cpp" > + <Original> + what, Contains( "file" ) + </Original> + <Expanded> + "error: tag alias, "[@zzz]" already registered. + First seen at file:2 + Redefined at file:10" contains: "file" + </Expanded> + </Expression> + <Expression success="true" type="CHECK_THAT" filename="projects/SelfTest/TagAliasTests.cpp" > + <Original> + what, Contains( "2" ) + </Original> + <Expanded> + "error: tag alias, "[@zzz]" already registered. + First seen at file:2 + Redefined at file:10" contains: "2" + </Expanded> + </Expression> + <Expression success="true" type="CHECK_THAT" filename="projects/SelfTest/TagAliasTests.cpp" > + <Original> + what, Contains( "10" ) + </Original> + <Expanded> + "error: tag alias, "[@zzz]" already registered. + First seen at file:2 + Redefined at file:10" contains: "10" + </Expanded> + </Expression> + <OverallResults successes="4" failures="0" expectedFailures="0"/> + </Section> + <Section name="Tag aliases must be of the form [@name]"> + <Expression success="true" type="CHECK_THROWS" filename="projects/SelfTest/TagAliasTests.cpp" > + <Original> + registry.add( "[no ampersat]", "", Catch::SourceLineInfo( "file", 3 ) ) + </Original> + <Expanded> + registry.add( "[no ampersat]", "", Catch::SourceLineInfo( "file", 3 ) ) + </Expanded> + </Expression> + <Expression success="true" type="CHECK_THROWS" filename="projects/SelfTest/TagAliasTests.cpp" > + <Original> + registry.add( "[the @ is not at the start]", "", Catch::SourceLineInfo( "file", 3 ) ) + </Original> + <Expanded> + registry.add( "[the @ is not at the start]", "", Catch::SourceLineInfo( "file", 3 ) ) + </Expanded> + </Expression> + <Expression success="true" type="CHECK_THROWS" filename="projects/SelfTest/TagAliasTests.cpp" > + <Original> + registry.add( "@no square bracket at start]", "", Catch::SourceLineInfo( "file", 3 ) ) + </Original> + <Expanded> + registry.add( "@no square bracket at start]", "", Catch::SourceLineInfo( "file", 3 ) ) + </Expanded> + </Expression> + <Expression success="true" type="CHECK_THROWS" filename="projects/SelfTest/TagAliasTests.cpp" > + <Original> + registry.add( "[@no square bracket at end", "", Catch::SourceLineInfo( "file", 3 ) ) + </Original> + <Expanded> + registry.add( "[@no square bracket at end", "", Catch::SourceLineInfo( "file", 3 ) ) + </Expanded> + </Expression> + <OverallResults successes="4" failures="0" expectedFailures="0"/> + </Section> + <OverallResult success="true"/> + </TestCase> + <TestCase name="Anonymous test case 1"> + <OverallResult success="true"/> + </TestCase> + <TestCase name="Test case with one argument"> + <OverallResult success="true"/> + </TestCase> + <TestCase name="Variadic macros"> + <Section name="Section with one argument"> + <OverallResults successes="1" failures="0" expectedFailures="0"/> + </Section> + <OverallResult success="true"/> + </TestCase> + <TestCase name="Scenario: Do that thing with the thing"> + <Section name="Given: This stuff exists"> + <Section name="When: I do this"> + <Section name="Then: it should do this"> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/BDDTests.cpp" > + <Original> + itDoesThis() + </Original> + <Expanded> + true + </Expanded> + </Expression> + <Section name="And: do that"> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/BDDTests.cpp" > + <Original> + itDoesThat() + </Original> + <Expanded> + true + </Expanded> + </Expression> + <OverallResults successes="1" failures="0" expectedFailures="0"/> + </Section> + <OverallResults successes="2" failures="0" expectedFailures="0"/> + </Section> + <OverallResults successes="2" failures="0" expectedFailures="0"/> + </Section> + <OverallResults successes="2" failures="0" expectedFailures="0"/> + </Section> + <OverallResult success="true"/> + </TestCase> + <TestCase name="Scenario: Vector resizing affects size and capacity"> + <Section name="Given: an empty vector"> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/BDDTests.cpp" > + <Original> + v.size() == 0 + </Original> + <Expanded> + 0 == 0 + </Expanded> + </Expression> + <Section name="When: it is made larger"> + <Section name="Then: the size and capacity go up"> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/BDDTests.cpp" > + <Original> + v.size() == 10 + </Original> + <Expanded> + 10 == 10 + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/BDDTests.cpp" > + <Original> + v.capacity() >= 10 + </Original> + <Expanded> + 10 >= 10 + </Expanded> + </Expression> + <Section name="And when: it is made smaller again"> + <Section name="Then: the size goes down but the capacity stays the same"> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/BDDTests.cpp" > + <Original> + v.size() == 5 + </Original> + <Expanded> + 5 == 5 + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/BDDTests.cpp" > + <Original> + v.capacity() >= 10 + </Original> + <Expanded> + 10 >= 10 + </Expanded> + </Expression> + <OverallResults successes="2" failures="0" expectedFailures="0"/> + </Section> + <OverallResults successes="2" failures="0" expectedFailures="0"/> + </Section> + <OverallResults successes="4" failures="0" expectedFailures="0"/> + </Section> + <OverallResults successes="4" failures="0" expectedFailures="0"/> + </Section> + <OverallResults successes="5" failures="0" expectedFailures="0"/> + </Section> + <Section name="Given: an empty vector"> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/BDDTests.cpp" > + <Original> + v.size() == 0 + </Original> + <Expanded> + 0 == 0 + </Expanded> + </Expression> + <Section name="When: we reserve more space"> + <Section name="Then: The capacity is increased but the size remains the same"> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/BDDTests.cpp" > + <Original> + v.capacity() >= 10 + </Original> + <Expanded> + 10 >= 10 + </Expanded> + </Expression> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/BDDTests.cpp" > + <Original> + v.size() == 0 + </Original> + <Expanded> + 0 == 0 + </Expanded> + </Expression> + <OverallResults successes="2" failures="0" expectedFailures="0"/> + </Section> + <OverallResults successes="2" failures="0" expectedFailures="0"/> + </Section> + <OverallResults successes="3" failures="0" expectedFailures="0"/> + </Section> + <OverallResult success="true"/> + </TestCase> + <TestCase name="Scenario: This is a really long scenario name to see how the list command deals with wrapping"> + <Section name="Given: A section name that is so long that it cannot fit in a single console width"> + <Section name="When: The test headers are printed as part of the normal running of the scenario"> + <Section name="Then: The, deliberately very long and overly verbose (you see what I did there?) section names must wrap, along with an indent"> + <OverallResults successes="1" failures="0" expectedFailures="0"/> + </Section> + <OverallResults successes="1" failures="0" expectedFailures="0"/> + </Section> + <OverallResults successes="1" failures="0" expectedFailures="0"/> + </Section> + <OverallResult success="true"/> + </TestCase> + <TestCase name="Scenario: BDD tests requiring Fixtures to provide commonly-accessed data or methods"> + <Section name="Given: No operations precede me"> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/BDDTests.cpp" > + <Original> + before == 0 + </Original> + <Expanded> + 0 == 0 + </Expanded> + </Expression> + <Section name="When: We get the count"> + <Section name="Then: Subsequently values are higher"> + <Expression success="true" type="REQUIRE" filename="projects/SelfTest/BDDTests.cpp" > + <Original> + after > before + </Original> + <Expanded> + 1 > 0 + </Expanded> + </Expression> + <OverallResults successes="1" failures="0" expectedFailures="0"/> + </Section> + <OverallResults successes="1" failures="0" expectedFailures="0"/> + </Section> + <OverallResults successes="2" failures="0" expectedFailures="0"/> + </Section> + <OverallResult success="true"/> + </TestCase> + <OverallResults successes="823" failures="85" expectedFailures="13"/> + </Group> + <OverallResults successes="823" failures="85" expectedFailures="13"/> +</Catch> diff --git a/unittest/Catch/projects/SelfTest/ClassTests.cpp b/unittest/Catch/projects/SelfTest/ClassTests.cpp new file mode 100644 index 0000000..a470784 --- /dev/null +++ b/unittest/Catch/projects/SelfTest/ClassTests.cpp @@ -0,0 +1,57 @@ +/* + * Created by Phil on 09/11/2010. + * Copyright 2010 Two Blue Cubes Ltd. All rights reserved. + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + */ + +#include "catch.hpp" + +namespace +{ + class TestClass + { + std::string s; + + public: + TestClass() + : s( "hello" ) + {} + + void succeedingCase() + { + REQUIRE( s == "hello" ); + } + void failingCase() + { + REQUIRE( s == "world" ); + } + }; +} + + +METHOD_AS_TEST_CASE( TestClass::succeedingCase, "A METHOD_AS_TEST_CASE based test run that succeeds", "[class]" ) +METHOD_AS_TEST_CASE( TestClass::failingCase, "A METHOD_AS_TEST_CASE based test run that fails", "[.][class][failing]" ) + + +struct Fixture +{ + Fixture() : m_a( 1 ) {} + + int m_a; +}; + +TEST_CASE_METHOD( Fixture, "A TEST_CASE_METHOD based test run that succeeds", "[class]" ) +{ + REQUIRE( m_a == 1 ); +} + +// We should be able to write our tests within a different namespace +namespace Inner +{ + TEST_CASE_METHOD( Fixture, "A TEST_CASE_METHOD based test run that fails", "[.][class][failing]" ) + { + REQUIRE( m_a == 2 ); + } +} diff --git a/unittest/Catch/projects/SelfTest/CmdLineTests.cpp b/unittest/Catch/projects/SelfTest/CmdLineTests.cpp new file mode 100644 index 0000000..719c89b --- /dev/null +++ b/unittest/Catch/projects/SelfTest/CmdLineTests.cpp @@ -0,0 +1,264 @@ +/* + * Created by Phil on 13/5/2013. + * Copyright 2014 Two Blue Cubes Ltd. All rights reserved. + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + */ + +#include "catch.hpp" +#include "catch_test_spec_parser.hpp" + +#ifdef __clang__ +# pragma clang diagnostic ignored "-Wc++98-compat" +#endif + +inline Catch::TestCase fakeTestCase( const char* name, const char* desc = "" ){ return Catch::makeTestCase( CATCH_NULL, "", name, desc, CATCH_INTERNAL_LINEINFO ); } + +TEST_CASE( "Parse test names and tags", "" ) { + + using Catch::parseTestSpec; + using Catch::TestSpec; + + Catch::TestCase tcA = fakeTestCase( "a", "" ); + Catch::TestCase tcB = fakeTestCase( "b", "[one][x]" ); + Catch::TestCase tcC = fakeTestCase( "longer name with spaces", "[two][three][.][x]" ); + Catch::TestCase tcD = fakeTestCase( "zlonger name with spacesz", "" ); + + SECTION( "Empty test spec should have no filters", "" ) { + TestSpec spec; + CHECK( spec.hasFilters() == false ); + CHECK( spec.matches( tcA ) == false ); + CHECK( spec.matches( tcB ) == false ); + } + + SECTION( "Test spec from empty string should have no filters", "" ) { + TestSpec spec = parseTestSpec( "" ); + CHECK( spec.hasFilters() == false ); + CHECK( spec.matches(tcA ) == false ); + CHECK( spec.matches( tcB ) == false ); + } + + SECTION( "Test spec from just a comma should have no filters", "" ) { + TestSpec spec = parseTestSpec( "," ); + CHECK( spec.hasFilters() == false ); + CHECK( spec.matches( tcA ) == false ); + CHECK( spec.matches( tcB ) == false ); + } + + SECTION( "Test spec from name should have one filter", "" ) { + TestSpec spec = parseTestSpec( "b" ); + CHECK( spec.hasFilters() == true ); + CHECK( spec.matches( tcA ) == false ); + CHECK( spec.matches( tcB ) == true ); + } + + SECTION( "Test spec from quoted name should have one filter", "" ) { + TestSpec spec = parseTestSpec( "\"b\"" ); + CHECK( spec.hasFilters() == true ); + CHECK( spec.matches( tcA ) == false ); + CHECK( spec.matches( tcB ) == true ); + } + + SECTION( "Test spec from name should have one filter", "" ) { + TestSpec spec = parseTestSpec( "b" ); + CHECK( spec.hasFilters() == true ); + CHECK( spec.matches( tcA ) == false ); + CHECK( spec.matches( tcB ) == true ); + CHECK( spec.matches( tcC ) == false ); + } + + SECTION( "Wildcard at the start", "" ) { + TestSpec spec = parseTestSpec( "*spaces" ); + CHECK( spec.hasFilters() == true ); + CHECK( spec.matches( tcA ) == false ); + CHECK( spec.matches( tcB ) == false ); + CHECK( spec.matches( tcC ) == true ); + CHECK( spec.matches( tcD ) == false ); + CHECK( parseTestSpec( "*a" ).matches( tcA ) == true ); + } + SECTION( "Wildcard at the end", "" ) { + TestSpec spec = parseTestSpec( "long*" ); + CHECK( spec.hasFilters() == true ); + CHECK( spec.matches( tcA ) == false ); + CHECK( spec.matches( tcB ) == false ); + CHECK( spec.matches( tcC ) == true ); + CHECK( spec.matches( tcD ) == false ); + CHECK( parseTestSpec( "a*" ).matches( tcA ) == true ); + } + SECTION( "Wildcard at both ends", "" ) { + TestSpec spec = parseTestSpec( "*name*" ); + CHECK( spec.hasFilters() == true ); + CHECK( spec.matches( tcA ) == false ); + CHECK( spec.matches( tcB ) == false ); + CHECK( spec.matches( tcC ) == true ); + CHECK( spec.matches( tcD ) == true ); + CHECK( parseTestSpec( "*a*" ).matches( tcA ) == true ); + } + SECTION( "Redundant wildcard at the start", "" ) { + TestSpec spec = parseTestSpec( "*a" ); + CHECK( spec.hasFilters() == true ); + CHECK( spec.matches( tcA ) == true ); + CHECK( spec.matches( tcB ) == false ); + } + SECTION( "Redundant wildcard at the end", "" ) { + TestSpec spec = parseTestSpec( "a*" ); + CHECK( spec.hasFilters() == true ); + CHECK( spec.matches( tcA ) == true ); + CHECK( spec.matches( tcB ) == false ); + } + SECTION( "Redundant wildcard at both ends", "" ) { + TestSpec spec = parseTestSpec( "*a*" ); + CHECK( spec.hasFilters() == true ); + CHECK( spec.matches( tcA ) == true ); + CHECK( spec.matches( tcB ) == false ); + } + SECTION( "Wildcard at both ends, redundant at start", "" ) { + TestSpec spec = parseTestSpec( "*longer*" ); + CHECK( spec.hasFilters() == true ); + CHECK( spec.matches( tcA ) == false ); + CHECK( spec.matches( tcB ) == false ); + CHECK( spec.matches( tcC ) == true ); + CHECK( spec.matches( tcD ) == true ); + } + SECTION( "Just wildcard", "" ) { + TestSpec spec = parseTestSpec( "*" ); + CHECK( spec.hasFilters() == true ); + CHECK( spec.matches( tcA ) == true ); + CHECK( spec.matches( tcB ) == true ); + CHECK( spec.matches( tcC ) == true ); + CHECK( spec.matches( tcD ) == true ); + } + + SECTION( "Single tag", "" ) { + TestSpec spec = parseTestSpec( "[one]" ); + CHECK( spec.hasFilters() == true ); + CHECK( spec.matches( tcA ) == false ); + CHECK( spec.matches( tcB ) == true ); + CHECK( spec.matches( tcC ) == false ); + } + SECTION( "Single tag, two matches", "" ) { + TestSpec spec = parseTestSpec( "[x]" ); + CHECK( spec.hasFilters() == true ); + CHECK( spec.matches( tcA ) == false ); + CHECK( spec.matches( tcB ) == true ); + CHECK( spec.matches( tcC ) == true ); + } + SECTION( "Two tags", "" ) { + TestSpec spec = parseTestSpec( "[two][x]" ); + CHECK( spec.hasFilters() == true ); + CHECK( spec.matches( tcA ) == false ); + CHECK( spec.matches( tcB ) == false ); + CHECK( spec.matches( tcC ) == true ); + } + SECTION( "Two tags, spare separated", "" ) { + TestSpec spec = parseTestSpec( "[two] [x]" ); + CHECK( spec.hasFilters() == true ); + CHECK( spec.matches( tcA ) == false ); + CHECK( spec.matches( tcB ) == false ); + CHECK( spec.matches( tcC ) == true ); + } + SECTION( "Wildcarded name and tag", "" ) { + TestSpec spec = parseTestSpec( "*name*[x]" ); + CHECK( spec.hasFilters() == true ); + CHECK( spec.matches( tcA ) == false ); + CHECK( spec.matches( tcB ) == false ); + CHECK( spec.matches( tcC ) == true ); + CHECK( spec.matches( tcD ) == false ); + } + SECTION( "Single tag exclusion", "" ) { + TestSpec spec = parseTestSpec( "~[one]" ); + CHECK( spec.hasFilters() == true ); + CHECK( spec.matches( tcA ) == true ); + CHECK( spec.matches( tcB ) == false ); + CHECK( spec.matches( tcC ) == true ); + } + SECTION( "One tag exclusion and one tag inclusion", "" ) { + TestSpec spec = parseTestSpec( "~[two][x]" ); + CHECK( spec.hasFilters() == true ); + CHECK( spec.matches( tcA ) == false ); + CHECK( spec.matches( tcB ) == true ); + CHECK( spec.matches( tcC ) == false ); + } + SECTION( "One tag exclusion and one wldcarded name inclusion", "" ) { + TestSpec spec = parseTestSpec( "~[two]*name*" ); + CHECK( spec.hasFilters() == true ); + CHECK( spec.matches( tcA ) == false ); + CHECK( spec.matches( tcB ) == false ); + CHECK( spec.matches( tcC ) == false ); + CHECK( spec.matches( tcD ) == true ); + } + SECTION( "One tag exclusion, using exclude:, and one wldcarded name inclusion", "" ) { + TestSpec spec = parseTestSpec( "exclude:[two]*name*" ); + CHECK( spec.hasFilters() == true ); + CHECK( spec.matches( tcA ) == false ); + CHECK( spec.matches( tcB ) == false ); + CHECK( spec.matches( tcC ) == false ); + CHECK( spec.matches( tcD ) == true ); + } + SECTION( "name exclusion", "" ) { + TestSpec spec = parseTestSpec( "~b" ); + CHECK( spec.hasFilters() == true ); + CHECK( spec.matches( tcA ) == true ); + CHECK( spec.matches( tcB ) == false ); + CHECK( spec.matches( tcC ) == true ); + CHECK( spec.matches( tcD ) == true ); + } + SECTION( "wildcarded name exclusion", "" ) { + TestSpec spec = parseTestSpec( "~*name*" ); + CHECK( spec.hasFilters() == true ); + CHECK( spec.matches( tcA ) == true ); + CHECK( spec.matches( tcB ) == true ); + CHECK( spec.matches( tcC ) == false ); + CHECK( spec.matches( tcD ) == false ); + } + SECTION( "wildcarded name exclusion with tag inclusion", "" ) { + TestSpec spec = parseTestSpec( "~*name*,[three]" ); + CHECK( spec.hasFilters() == true ); + CHECK( spec.matches( tcA ) == true ); + CHECK( spec.matches( tcB ) == true ); + CHECK( spec.matches( tcC ) == true ); + CHECK( spec.matches( tcD ) == false ); + } + SECTION( "wildcarded name exclusion, using exclude:, with tag inclusion", "" ) { + TestSpec spec = parseTestSpec( "exclude:*name*,[three]" ); + CHECK( spec.hasFilters() == true ); + CHECK( spec.matches( tcA ) == true ); + CHECK( spec.matches( tcB ) == true ); + CHECK( spec.matches( tcC ) == true ); + CHECK( spec.matches( tcD ) == false ); + } + SECTION( "two wildcarded names", "" ) { + TestSpec spec = parseTestSpec( "\"longer*\"\"*spaces\"" ); + CHECK( spec.hasFilters() == true ); + CHECK( spec.matches( tcA ) == false ); + CHECK( spec.matches( tcB ) == false ); + CHECK( spec.matches( tcC ) == true ); + CHECK( spec.matches( tcD ) == false ); + } + SECTION( "empty tag", "" ) { + TestSpec spec = parseTestSpec( "[]" ); + CHECK( spec.hasFilters() == false ); + CHECK( spec.matches( tcA ) == false ); + CHECK( spec.matches( tcB ) == false ); + CHECK( spec.matches( tcC ) == false ); + CHECK( spec.matches( tcD ) == false ); + } + SECTION( "empty quoted name", "" ) { + TestSpec spec = parseTestSpec( "\"\"" ); + CHECK( spec.hasFilters() == false ); + CHECK( spec.matches( tcA ) == false ); + CHECK( spec.matches( tcB ) == false ); + CHECK( spec.matches( tcC ) == false ); + CHECK( spec.matches( tcD ) == false ); + } + SECTION( "quoted string followed by tag exclusion", "" ) { + TestSpec spec = parseTestSpec( "\"*name*\"~[.]" ); + CHECK( spec.hasFilters() == true ); + CHECK( spec.matches( tcA ) == false ); + CHECK( spec.matches( tcB ) == false ); + CHECK( spec.matches( tcC ) == false ); + CHECK( spec.matches( tcD ) == true ); + } + +} diff --git a/unittest/Catch/projects/SelfTest/ConditionTests.cpp b/unittest/Catch/projects/SelfTest/ConditionTests.cpp new file mode 100644 index 0000000..d1b7ed2 --- /dev/null +++ b/unittest/Catch/projects/SelfTest/ConditionTests.cpp @@ -0,0 +1,335 @@ +/* + * Created by Phil on 08/11/2010. + * Copyright 2010 Two Blue Cubes Ltd. All rights reserved. + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + */ +#ifdef __clang__ +# pragma clang diagnostic ignored "-Wpadded" +# pragma clang diagnostic ignored "-Wc++98-compat" +#endif + +#include "catch.hpp" + +#include <string> +#include <limits> + +struct TestData { + TestData() + : int_seven( 7 ), + str_hello( "hello" ), + float_nine_point_one( 9.1f ), + double_pi( 3.1415926535 ) + {} + + int int_seven; + std::string str_hello; + float float_nine_point_one; + double double_pi; +}; + + +struct TestDef { + TestDef& operator + ( const std::string& ) { + return *this; + } + TestDef& operator[]( const std::string& ) { + return *this; + } + +}; + +// The "failing" tests all use the CHECK macro, which continues if the specific test fails. +// This allows us to see all results, even if an earlier check fails + +// Equality tests +TEST_CASE( "Equality checks that should succeed", "" ) +{ + + TestDef td; + td + "hello" + "hello"; + + TestData data; + + REQUIRE( data.int_seven == 7 ); + REQUIRE( data.float_nine_point_one == Approx( 9.1f ) ); + REQUIRE( data.double_pi == Approx( 3.1415926535 ) ); + REQUIRE( data.str_hello == "hello" ); + REQUIRE( "hello" == data.str_hello ); + REQUIRE( data.str_hello.size() == 5 ); + + double x = 1.1 + 0.1 + 0.1; + REQUIRE( x == Approx( 1.3 ) ); +} + +TEST_CASE( "Equality checks that should fail", "[.][failing][!mayfail]" ) +{ + TestData data; + + CHECK( data.int_seven == 6 ); + CHECK( data.int_seven == 8 ); + CHECK( data.int_seven == 0 ); + CHECK( data.float_nine_point_one == Approx( 9.11f ) ); + CHECK( data.float_nine_point_one == Approx( 9.0f ) ); + CHECK( data.float_nine_point_one == Approx( 1 ) ); + CHECK( data.float_nine_point_one == Approx( 0 ) ); + CHECK( data.double_pi == Approx( 3.1415 ) ); + CHECK( data.str_hello == "goodbye" ); + CHECK( data.str_hello == "hell" ); + CHECK( data.str_hello == "hello1" ); + CHECK( data.str_hello.size() == 6 ); + + double x = 1.1 + 0.1 + 0.1; + CHECK( x == Approx( 1.301 ) ); +} + +TEST_CASE( "Inequality checks that should succeed", "" ) +{ + TestData data; + + REQUIRE( data.int_seven != 6 ); + REQUIRE( data.int_seven != 8 ); + REQUIRE( data.float_nine_point_one != Approx( 9.11f ) ); + REQUIRE( data.float_nine_point_one != Approx( 9.0f ) ); + REQUIRE( data.float_nine_point_one != Approx( 1 ) ); + REQUIRE( data.float_nine_point_one != Approx( 0 ) ); + REQUIRE( data.double_pi != Approx( 3.1415 ) ); + REQUIRE( data.str_hello != "goodbye" ); + REQUIRE( data.str_hello != "hell" ); + REQUIRE( data.str_hello != "hello1" ); + REQUIRE( data.str_hello.size() != 6 ); +} + +TEST_CASE( "Inequality checks that should fail", "[.][failing]" ) +{ + TestData data; + + CHECK( data.int_seven != 7 ); + CHECK( data.float_nine_point_one != Approx( 9.1f ) ); + CHECK( data.double_pi != Approx( 3.1415926535 ) ); + CHECK( data.str_hello != "hello" ); + CHECK( data.str_hello.size() != 5 ); +} + +// Ordering comparison tests +TEST_CASE( "Ordering comparison checks that should succeed", "" ) +{ + TestData data; + + REQUIRE( data.int_seven < 8 ); + REQUIRE( data.int_seven > 6 ); + REQUIRE( data.int_seven > 0 ); + REQUIRE( data.int_seven > -1 ); + + REQUIRE( data.int_seven >= 7 ); + REQUIRE( data.int_seven >= 6 ); + REQUIRE( data.int_seven <= 7 ); + REQUIRE( data.int_seven <= 8 ); + + REQUIRE( data.float_nine_point_one > 9 ); + REQUIRE( data.float_nine_point_one < 10 ); + REQUIRE( data.float_nine_point_one < 9.2 ); + + REQUIRE( data.str_hello <= "hello" ); + REQUIRE( data.str_hello >= "hello" ); + + REQUIRE( data.str_hello < "hellp" ); + REQUIRE( data.str_hello < "zebra" ); + REQUIRE( data.str_hello > "hellm" ); + REQUIRE( data.str_hello > "a" ); +} + +TEST_CASE( "Ordering comparison checks that should fail", "[.][failing]" ) +{ + TestData data; + + CHECK( data.int_seven > 7 ); + CHECK( data.int_seven < 7 ); + CHECK( data.int_seven > 8 ); + CHECK( data.int_seven < 6 ); + CHECK( data.int_seven < 0 ); + CHECK( data.int_seven < -1 ); + + CHECK( data.int_seven >= 8 ); + CHECK( data.int_seven <= 6 ); + + CHECK( data.float_nine_point_one < 9 ); + CHECK( data.float_nine_point_one > 10 ); + CHECK( data.float_nine_point_one > 9.2 ); + + CHECK( data.str_hello > "hello" ); + CHECK( data.str_hello < "hello" ); + CHECK( data.str_hello > "hellp" ); + CHECK( data.str_hello > "z" ); + CHECK( data.str_hello < "hellm" ); + CHECK( data.str_hello < "a" ); + + CHECK( data.str_hello >= "z" ); + CHECK( data.str_hello <= "a" ); +} + +// Comparisons with int literals +TEST_CASE( "Comparisons with int literals don't warn when mixing signed/ unsigned", "" ) +{ + int i = 1; + unsigned int ui = 2; + long l = 3; + unsigned long ul = 4; + char c = 5; + unsigned char uc = 6; + + REQUIRE( i == 1 ); + REQUIRE( ui == 2 ); + REQUIRE( l == 3 ); + REQUIRE( ul == 4 ); + REQUIRE( c == 5 ); + REQUIRE( uc == 6 ); + + REQUIRE( 1 == i ); + REQUIRE( 2 == ui ); + REQUIRE( 3 == l ); + REQUIRE( 4 == ul ); + REQUIRE( 5 == c ); + REQUIRE( 6 == uc ); + + REQUIRE( (std::numeric_limits<unsigned long>::max)() > ul ); +} + +// Disable warnings about sign conversions for the next two tests +// (as we are deliberately invoking them) +// - Currently only disabled for GCC/ LLVM. Should add VC++ too +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wsign-compare" +#pragma GCC diagnostic ignored "-Wsign-conversion" +#endif +#ifdef _MSC_VER +#pragma warning(disable:4389) // '==' : signed/unsigned mismatch +#endif + +TEST_CASE( "comparisons between int variables", "" ) +{ + long long_var = 1L; + unsigned char unsigned_char_var = 1; + unsigned short unsigned_short_var = 1; + unsigned int unsigned_int_var = 1; + unsigned long unsigned_long_var = 1L; + + REQUIRE( long_var == unsigned_char_var ); + REQUIRE( long_var == unsigned_short_var ); + REQUIRE( long_var == unsigned_int_var ); + REQUIRE( long_var == unsigned_long_var ); +} + +TEST_CASE( "comparisons between const int variables", "" ) +{ + const unsigned char unsigned_char_var = 1; + const unsigned short unsigned_short_var = 1; + const unsigned int unsigned_int_var = 1; + const unsigned long unsigned_long_var = 1L; + + REQUIRE( unsigned_char_var == 1 ); + REQUIRE( unsigned_short_var == 1 ); + REQUIRE( unsigned_int_var == 1 ); + REQUIRE( unsigned_long_var == 1 ); +} + +TEST_CASE( "Comparisons between unsigned ints and negative signed ints match c++ standard behaviour", "" ) +{ + CHECK( ( -1 > 2u ) ); + CHECK( -1 > 2u ); + + CHECK( ( 2u < -1 ) ); + CHECK( 2u < -1 ); + + const int minInt = (std::numeric_limits<int>::min)(); + CHECK( ( minInt > 2u ) ); + CHECK( minInt > 2u ); +} + +template<typename T> +struct Ex +{ + Ex( T ){} + + bool operator == ( const T& ) const { return true; } + T operator * ( const T& ) const { return T(); } +}; + +TEST_CASE( "Comparisons between ints where one side is computed", "" ) +{ + CHECK( 54 == 6*9 ); +} + +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif + +inline const char* returnsConstNull(){ return CATCH_NULL; } +inline char* returnsNull(){ return CATCH_NULL; } + +TEST_CASE( "Pointers can be compared to null", "" ) +{ + TestData* p = CATCH_NULL; + TestData* pNULL = CATCH_NULL; + + REQUIRE( p == CATCH_NULL ); + REQUIRE( p == pNULL ); + + TestData data; + p = &data; + + REQUIRE( p != CATCH_NULL ); + + const TestData* cp = p; + REQUIRE( cp != CATCH_NULL ); + + const TestData* const cpc = p; + REQUIRE( cpc != CATCH_NULL ); + + REQUIRE( returnsNull() == CATCH_NULL ); + REQUIRE( returnsConstNull() == CATCH_NULL ); + + REQUIRE( CATCH_NULL != p ); +} + +// Not (!) tests +// The problem with the ! operator is that it has right-to-left associativity. +// This means we can't isolate it when we decompose. The simple REQUIRE( !false ) form, therefore, +// cannot have the operand value extracted. The test will work correctly, and the situation +// is detected and a warning issued. +// An alternative form of the macros (CHECK_FALSE and REQUIRE_FALSE) can be used instead to capture +// the operand value. +TEST_CASE( "'Not' checks that should succeed", "" ) +{ + bool falseValue = false; + + REQUIRE( false == false ); + REQUIRE( true == true ); + REQUIRE( !false ); + REQUIRE_FALSE( false ); + + REQUIRE( !falseValue ); + REQUIRE_FALSE( falseValue ); + + REQUIRE( !(1 == 2) ); + REQUIRE_FALSE( 1 == 2 ); +} + +TEST_CASE( "'Not' checks that should fail", "[.][failing]" ) +{ + bool trueValue = true; + + CHECK( false != false ); + CHECK( true != true ); + CHECK( !true ); + CHECK_FALSE( true ); + + CHECK( !trueValue ); + CHECK_FALSE( trueValue ); + + CHECK( !(1 == 1) ); + CHECK_FALSE( 1 == 1 ); +} + diff --git a/unittest/Catch/projects/SelfTest/EnumToString.cpp b/unittest/Catch/projects/SelfTest/EnumToString.cpp new file mode 100644 index 0000000..6917d8a --- /dev/null +++ b/unittest/Catch/projects/SelfTest/EnumToString.cpp @@ -0,0 +1,76 @@ +#include "catch.hpp" + +/* + TODO: maybe ought to check that user-provided specialisations of + Catch::toString also do the right thing +*/ + +// Enum without user-provided stream operator +enum Enum1 { Enum1Value0, Enum1Value1 }; + +TEST_CASE( "toString(enum)", "[toString][enum]" ) { + Enum1 e0 = Enum1Value0; + CHECK( Catch::toString(e0) == "0" ); + Enum1 e1 = Enum1Value1; + CHECK( Catch::toString(e1) == "1" ); +} + +// Enum with user-provided stream operator +enum Enum2 { Enum2Value0, Enum2Value1 }; + +inline std::ostream& operator<<( std::ostream& os, Enum2 v ) { + return os << "E2{" << static_cast<int>(v) << "}"; +} + +TEST_CASE( "toString(enum w/operator<<)", "[toString][enum]" ) { + Enum2 e0 = Enum2Value0; + CHECK( Catch::toString(e0) == "E2{0}" ); + Enum2 e1 = Enum2Value1; + CHECK( Catch::toString(e1) == "E2{1}" ); +} + +#if defined(CATCH_CPP11_OR_GREATER) +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wc++98-compat" +#endif + +// Enum class without user-provided stream operator +enum class EnumClass1 { EnumClass1Value0, EnumClass1Value1 }; + +TEST_CASE( "toString(enum class)", "[toString][enum][enumClass]" ) { + EnumClass1 e0 = EnumClass1::EnumClass1Value0; + CHECK( Catch::toString(e0) == "0" ); + EnumClass1 e1 = EnumClass1::EnumClass1Value1; + CHECK( Catch::toString(e1) == "1" ); +} + +// Enum class with user-provided stream operator +enum class EnumClass2 : short { EnumClass2Value0, EnumClass2Value1 }; + +inline std::ostream& operator<<( std::ostream& os, EnumClass2 e2 ) { + switch( static_cast<int>( e2 ) ) { + case static_cast<int>( EnumClass2::EnumClass2Value0 ): + return os << "E2/V0"; + case static_cast<int>( EnumClass2::EnumClass2Value1 ): + return os << "E2/V1"; + default: + return os << "Unknown enum value " << static_cast<int>( e2 ); + } +} + +TEST_CASE( "toString(enum class w/operator<<)", "[toString][enum][enumClass]" ) { + EnumClass2 e0 = EnumClass2::EnumClass2Value0; + CHECK( Catch::toString(e0) == "E2/V0" ); + EnumClass2 e1 = EnumClass2::EnumClass2Value1; + CHECK( Catch::toString(e1) == "E2/V1" ); + + EnumClass2 e3 = static_cast<EnumClass2>(10); + CHECK( Catch::toString(e3) == "Unknown enum value 10" ); +} + +#ifdef __clang__ +#pragma clang diagnostic pop +#endif +#endif // CATCH_CPP11_OR_GREATER + diff --git a/unittest/Catch/projects/SelfTest/ExceptionTests.cpp b/unittest/Catch/projects/SelfTest/ExceptionTests.cpp new file mode 100644 index 0000000..5ef91a1 --- /dev/null +++ b/unittest/Catch/projects/SelfTest/ExceptionTests.cpp @@ -0,0 +1,203 @@ +/* + * Created by Phil on 09/11/2010. + * Copyright 2010 Two Blue Cubes Ltd. All rights reserved. + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + */ + +#include "catch.hpp" + +#include <string> +#include <stdexcept> + +namespace +{ + inline int thisThrows() + { + if( Catch::alwaysTrue() ) + throw std::domain_error( "expected exception" ); + return 1; + } + + int thisDoesntThrow() + { + return 0; + } +} + +TEST_CASE( "When checked exceptions are thrown they can be expected or unexpected", "" ) +{ + REQUIRE_THROWS_AS( thisThrows(), std::domain_error ); + REQUIRE_NOTHROW( thisDoesntThrow() ); + REQUIRE_THROWS( thisThrows() ); +} + +TEST_CASE( "Expected exceptions that don't throw or unexpected exceptions fail the test", "[.][failing]" ) +{ + CHECK_THROWS_AS( thisThrows(), std::string ); + CHECK_THROWS_AS( thisDoesntThrow(), std::domain_error ); + CHECK_NOTHROW( thisThrows() ); +} + +TEST_CASE( "When unchecked exceptions are thrown directly they are always failures", "[.][failing]" ) +{ + if( Catch::alwaysTrue() ) + throw std::domain_error( "unexpected exception" ); +} + +TEST_CASE( "An unchecked exception reports the line of the last assertion", "[.][failing]" ) +{ + CHECK( 1 == 1 ); + if( Catch::alwaysTrue() ) + throw std::domain_error( "unexpected exception" ); +} + +TEST_CASE( "When unchecked exceptions are thrown from sections they are always failures", "[.][failing]" ) +{ + SECTION( "section name", "" ) + { + if( Catch::alwaysTrue() ) + throw std::domain_error( "unexpected exception" ); + } +} + +TEST_CASE( "When unchecked exceptions are thrown from functions they are always failures", "[.][failing]" ) +{ + CHECK( thisThrows() == 0 ); +} + +TEST_CASE( "When unchecked exceptions are thrown during a REQUIRE the test should abort fail", "[.][failing]" ) +{ + REQUIRE( thisThrows() == 0 ); + FAIL( "This should never happen" ); +} + +TEST_CASE( "When unchecked exceptions are thrown during a CHECK the test should abort and fail", "[.][failing]" ) +{ + CHECK( thisThrows() == 0 ); + FAIL( "This should never happen" ); +} + +TEST_CASE( "When unchecked exceptions are thrown, but caught, they do not affect the test", "" ) +{ + try + { + throw std::domain_error( "unexpected exception" ); + } + catch(...) + { + } +} + +class CustomException +{ +public: + CustomException( const std::string& msg ) + : m_msg( msg ) + {} + + std::string getMessage() const + { + return m_msg; + } + +private: + std::string m_msg; +}; + +class CustomStdException : public std::exception +{ +public: + CustomStdException( const std::string& msg ) + : m_msg( msg ) + {} + ~CustomStdException() CATCH_NOEXCEPT {} + + std::string getMessage() const + { + return m_msg; + } + +private: + std::string m_msg; +}; + + +CATCH_TRANSLATE_EXCEPTION( CustomException& ex ) +{ + return ex.getMessage(); +} + +CATCH_TRANSLATE_EXCEPTION( CustomStdException& ex ) +{ + return ex.getMessage(); +} + +CATCH_TRANSLATE_EXCEPTION( double& ex ) +{ + return Catch::toString( ex ); +} + +TEST_CASE("Non-std exceptions can be translated", "[.][failing]" ) +{ + if( Catch::alwaysTrue() ) + throw CustomException( "custom exception" ); +} + +TEST_CASE("Custom std-exceptions can be custom translated", "[.][failing]" ) +{ + if( Catch::alwaysTrue() ) + throw CustomException( "custom std exception" ); +} + +inline void throwCustom() { + if( Catch::alwaysTrue() ) + throw CustomException( "custom exception - not std" ); +} + +TEST_CASE( "Custom exceptions can be translated when testing for nothrow", "[.][failing]" ) +{ + REQUIRE_NOTHROW( throwCustom() ); +} + +TEST_CASE( "Custom exceptions can be translated when testing for throwing as something else", "[.][failing]" ) +{ + REQUIRE_THROWS_AS( throwCustom(), std::exception ); +} + + +TEST_CASE( "Unexpected exceptions can be translated", "[.][failing]" ) +{ + if( Catch::alwaysTrue() ) + throw double( 3.14 ); +} + +inline int thisFunctionNotImplemented( int ) { + CATCH_NOT_IMPLEMENTED; +} + +TEST_CASE( "NotImplemented exception", "" ) +{ + REQUIRE_THROWS( thisFunctionNotImplemented( 7 ) ); +} + +TEST_CASE( "Exception messages can be tested for", "" ) { + using namespace Catch::Matchers; + SECTION( "exact match" ) + REQUIRE_THROWS_WITH( thisThrows(), "expected exception" ); + SECTION( "different case" ) + REQUIRE_THROWS_WITH( thisThrows(), Equals( "expecteD Exception", Catch::CaseSensitive::No ) ); + SECTION( "wildcarded" ) { + REQUIRE_THROWS_WITH( thisThrows(), StartsWith( "expected" ) ); + REQUIRE_THROWS_WITH( thisThrows(), EndsWith( "exception" ) ); + REQUIRE_THROWS_WITH( thisThrows(), Contains( "except" ) ); + REQUIRE_THROWS_WITH( thisThrows(), Contains( "exCept", Catch::CaseSensitive::No ) ); + } +} + +TEST_CASE( "Mismatching exception messages failing the test", "[.][failing]" ) { + REQUIRE_THROWS_WITH( thisThrows(), "expected exception" ); + REQUIRE_THROWS_WITH( thisThrows(), "should fail" ); + REQUIRE_THROWS_WITH( thisThrows(), "expected exception" ); +} diff --git a/unittest/Catch/projects/SelfTest/GeneratorTests.cpp b/unittest/Catch/projects/SelfTest/GeneratorTests.cpp new file mode 100644 index 0000000..af08b1d --- /dev/null +++ b/unittest/Catch/projects/SelfTest/GeneratorTests.cpp @@ -0,0 +1,42 @@ +/* + * Created by Phil on 28/01/2011. + * Copyright 2011 Two Blue Cubes Ltd. All rights reserved. + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + */ + +// This define means we have to prefix all the CATCH macros with CATCH_ +// We're using it here to test it out +#define CATCH_CONFIG_PREFIX_ALL +#include "catch.hpp" + +inline int multiply( int a, int b ) +{ + return a*b; +} + +CATCH_TEST_CASE( "Generators over two ranges", "[generators]" ) +{ + using namespace Catch::Generators; + + int i = CATCH_GENERATE( between( 1, 5 ).then( values( 15, 20, 21 ).then( 36 ) ) ); + int j = CATCH_GENERATE( between( 100, 107 ) ); + + CATCH_REQUIRE( multiply( i, 2 ) == i*2 ); + CATCH_REQUIRE( multiply( j, 2 ) == j*2 ); +} + +struct IntPair { int first, second; }; + +CATCH_TEST_CASE( "Generator over a range of pairs", "[generators]" ) +{ + using namespace Catch::Generators; + + IntPair p[] = { { 0, 1 }, { 2, 3 } }; + + IntPair* i = CATCH_GENERATE( between( p, &p[1] ) ); + + CATCH_REQUIRE( i->first == i->second-1 ); + +} diff --git a/unittest/Catch/projects/SelfTest/MessageTests.cpp b/unittest/Catch/projects/SelfTest/MessageTests.cpp new file mode 100644 index 0000000..87a85a8 --- /dev/null +++ b/unittest/Catch/projects/SelfTest/MessageTests.cpp @@ -0,0 +1,133 @@ +/* + * Created by Phil on 09/11/2010. + * Copyright 2010 Two Blue Cubes Ltd. All rights reserved. + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + */ + +#include "catch.hpp" +#include <iostream> + +#ifdef __clang__ +#pragma clang diagnostic ignored "-Wc++98-compat-pedantic" +#endif + +TEST_CASE( "INFO and WARN do not abort tests", "[messages][.]" ) +{ + INFO( "this is a " << "message" ); // This should output the message if a failure occurs + WARN( "this is a " << "warning" ); // This should always output the message but then continue +} +TEST_CASE( "SUCCEED counts as a test pass", "[messages]" ) +{ + SUCCEED( "this is a " << "success" ); +} + +TEST_CASE( "INFO gets logged on failure", "[failing][messages][.]" ) +{ + INFO( "this message should be logged" ); + INFO( "so should this" ); + int a = 2; + REQUIRE( a == 1 ); +} + +TEST_CASE( "INFO gets logged on failure, even if captured before successful assertions", "[failing][messages][.]" ) +{ + INFO( "this message may be logged later" ); + int a = 2; + CHECK( a == 2 ); + + INFO( "this message should be logged" ); + + CHECK( a == 1 ); + + INFO( "and this, but later" ); + + CHECK( a == 0 ); + + INFO( "but not this" ); + + CHECK( a == 2 ); +} + +TEST_CASE( "FAIL aborts the test", "[failing][messages][.]" ) +{ + FAIL( "This is a " << "failure" ); // This should output the message and abort +} + +#ifdef CATCH_CONFIG_VARIADIC_MACROS +TEST_CASE( "FAIL does not require an argument", "[failing][messages][.]" ) +{ + FAIL(); +} +TEST_CASE( "SUCCESS does not require an argument", "[messages][.]" ) +{ + SUCCEED(); +} +#endif + +TEST_CASE( "Output from all sections is reported", "[failing][messages][.]" ) +{ + SECTION( "one", "" ) + { + FAIL( "Message from section one" ); + } + + SECTION( "two", "" ) + { + FAIL( "Message from section two" ); + } +} + +TEST_CASE( "Standard output from all sections is reported", "[messages][.]" ) +{ + SECTION( "one", "" ) + { + std::cout << "Message from section one" << std::endl; + } + + SECTION( "two", "" ) + { + std::cout << "Message from section two" << std::endl; + } +} + +TEST_CASE( "SCOPED_INFO is reset for each loop", "[messages][failing][.]" ) +{ + for( int i=0; i<100; i++ ) + { + SCOPED_INFO( "current counter " << i ); + SCOPED_CAPTURE( i ); + REQUIRE( i < 10 ); + } +} + +TEST_CASE( "The NO_FAIL macro reports a failure but does not fail the test", "[messages]" ) +{ + CHECK_NOFAIL( 1 == 2 ); +} + +TEST_CASE( "just info", "[info][isolated info][messages]" ) +{ + INFO( "this should never be seen" ); +} +TEST_CASE( "just failure", "[fail][isolated info][.][messages]" ) +{ + FAIL( "Previous info should not be seen" ); +} + + +TEST_CASE( "sends information to INFO", "[.][failing]" ) +{ + INFO( "hi" ); + int i = 7; + CAPTURE( i ); + REQUIRE( false ); +} + +TEST_CASE( "Pointers can be converted to strings", "[messages][.]" ) +{ + int p; + WARN( "actual address of p: " << &p ); + WARN( "toString(p): " << Catch::toString( &p ) ); +} diff --git a/unittest/Catch/projects/SelfTest/MiscTests.cpp b/unittest/Catch/projects/SelfTest/MiscTests.cpp new file mode 100644 index 0000000..cf7f48c --- /dev/null +++ b/unittest/Catch/projects/SelfTest/MiscTests.cpp @@ -0,0 +1,480 @@ +/* + * Created by Phil on 29/11/2010. + * Copyright 2010 Two Blue Cubes Ltd. All rights reserved. + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + */ + +#include "catch.hpp" + +#ifdef __clang__ +# pragma clang diagnostic ignored "-Wc++98-compat" +# pragma clang diagnostic ignored "-Wc++98-compat-pedantic" +#endif + +#include "../include/internal/catch_xmlwriter.hpp" + +#include <iostream> + +TEST_CASE( "random SECTION tests", "[.][sections][failing]" ) +{ + int a = 1; + int b = 2; + + SECTION( "s1", "doesn't equal" ) + { + REQUIRE( a != b ); + REQUIRE( b != a ); + } + + SECTION( "s2", "not equal" ) + { + REQUIRE( a != b); + } +} + +TEST_CASE( "nested SECTION tests", "[.][sections][failing]" ) +{ + int a = 1; + int b = 2; + + SECTION( "s1", "doesn't equal" ) + { + REQUIRE( a != b ); + REQUIRE( b != a ); + + SECTION( "s2", "not equal" ) + { + REQUIRE( a != b); + } + } +} + +TEST_CASE( "more nested SECTION tests", "[sections][failing][.]" ) +{ + int a = 1; + int b = 2; + + SECTION( "s1", "doesn't equal" ) + { + SECTION( "s2", "equal" ) + { + REQUIRE( a == b ); + } + + SECTION( "s3", "not equal" ) + { + REQUIRE( a != b ); + } + SECTION( "s4", "less than" ) + { + REQUIRE( a < b ); + } + } +} + +TEST_CASE( "even more nested SECTION tests", "[sections]" ) +{ + SECTION( "c", "" ) + { + SECTION( "d (leaf)", "" ) + { + SUCCEED(""); // avoid failing due to no tests + } + + SECTION( "e (leaf)", "" ) + { + SUCCEED(""); // avoid failing due to no tests + } + } + + SECTION( "f (leaf)", "" ) + { + SUCCEED(""); // avoid failing due to no tests + } +} + +TEST_CASE( "looped SECTION tests", "[.][failing][sections]" ) +{ + int a = 1; + + for( int b = 0; b < 10; ++b ) + { + std::ostringstream oss; + oss << "b is currently: " << b; + SECTION( "s1", oss.str() ) + { + CHECK( b > a ); + } + } +} + +TEST_CASE( "looped tests", "[.][failing]" ) +{ + static const int fib[] = { 1, 1, 2, 3, 5, 8, 13, 21 }; + + for( size_t i=0; i < sizeof(fib)/sizeof(int); ++i ) + { + INFO( "Testing if fib[" << i << "] (" << fib[i] << ") is even" ); + CHECK( ( fib[i] % 2 ) == 0 ); + } +} + +TEST_CASE( "Sends stuff to stdout and stderr", "[.]" ) +{ + std::cout << "A string sent directly to stdout" << std::endl; + + std::cerr << "A string sent directly to stderr" << std::endl; +} + +inline const char* makeString( bool makeNull ) +{ + return makeNull ? CATCH_NULL : "valid string"; +} + +TEST_CASE( "null strings", "" ) +{ + REQUIRE( makeString( false ) != static_cast<char*>(CATCH_NULL)); + REQUIRE( makeString( true ) == static_cast<char*>(CATCH_NULL)); +} + + +inline bool testCheckedIf( bool flag ) +{ + CHECKED_IF( flag ) + return true; + else + return false; +} + +TEST_CASE( "checkedIf", "" ) +{ + REQUIRE( testCheckedIf( true ) ); +} + +TEST_CASE( "checkedIf, failing", "[failing][.]" ) +{ + REQUIRE( testCheckedIf( false ) ); +} + +inline bool testCheckedElse( bool flag ) +{ + CHECKED_ELSE( flag ) + return false; + + return true; +} + +TEST_CASE( "checkedElse", "" ) +{ + REQUIRE( testCheckedElse( true ) ); +} + +TEST_CASE( "checkedElse, failing", "[failing][.]" ) +{ + REQUIRE( testCheckedElse( false ) ); +} + +TEST_CASE( "xmlentitycheck", "" ) +{ + SECTION( "embedded xml", "<test>it should be possible to embed xml characters, such as <, \" or &, or even whole <xml>documents</xml> within an attribute</test>" ) + { + SUCCEED(""); // We need this here to stop it failing due to no tests + } + SECTION( "encoded chars", "these should all be encoded: &&&\"\"\"<<<&\"<<&\"" ) + { + SUCCEED(""); // We need this here to stop it failing due to no tests + } +} + +TEST_CASE( "send a single char to INFO", "[failing][.]" ) +{ + INFO(3); + REQUIRE(false); +} + +TEST_CASE( "atomic if", "[failing][0]") +{ + size_t x = 0; + + if( x ) + REQUIRE(x > 0); + else + REQUIRE(x == 0); +} + +inline const char* testStringForMatching() +{ + return "this string contains 'abc' as a substring"; +} +inline const char* testStringForMatching2() +{ + return "some completely different text that contains one common word"; +} + +using namespace Catch::Matchers; + +TEST_CASE("String matchers", "[matchers]" ) +{ + REQUIRE_THAT( testStringForMatching(), Contains( "string" ) ); + CHECK_THAT( testStringForMatching(), Contains( "abc" ) ); + + CHECK_THAT( testStringForMatching(), StartsWith( "this" ) ); + CHECK_THAT( testStringForMatching(), EndsWith( "substring" ) ); +} + +TEST_CASE("Contains string matcher", "[.][failing][matchers]") +{ + CHECK_THAT( testStringForMatching(), Contains( "not there" ) ); +} + +TEST_CASE("StartsWith string matcher", "[.][failing][matchers]") +{ + CHECK_THAT( testStringForMatching(), StartsWith( "string" ) ); +} + +TEST_CASE("EndsWith string matcher", "[.][failing][matchers]") +{ + CHECK_THAT( testStringForMatching(), EndsWith( "this" ) ); +} + +TEST_CASE("Equals string matcher", "[.][failing][matchers]") +{ + CHECK_THAT( testStringForMatching(), Equals( "something else" ) ); +} +TEST_CASE("Equals string matcher, with NULL", "[matchers]") +{ + REQUIRE_THAT("", Equals(CATCH_NULL)); +} +TEST_CASE("AllOf matcher", "[matchers]") +{ + CHECK_THAT( testStringForMatching(), AllOf( Catch::Contains( "string" ), Catch::Contains( "abc" ) ) ); +} +TEST_CASE("AnyOf matcher", "[matchers]") +{ + CHECK_THAT( testStringForMatching(), AnyOf( Catch::Contains( "string" ), Catch::Contains( "not there" ) ) ); + CHECK_THAT( testStringForMatching(), AnyOf( Catch::Contains( "not there" ), Catch::Contains( "string" ) ) ); +} + +TEST_CASE("Equals", "[matchers]") +{ + CHECK_THAT( testStringForMatching(), Equals( "this string contains 'abc' as a substring" ) ); +} + +TEST_CASE("Matchers can be (AllOf) composed with the && operator", "[matchers][operators][operator&&]") +{ + CHECK_THAT( testStringForMatching(), + Contains( "string" ) && + Contains( "abc" ) && + Contains( "substring" ) && + Contains( "contains" ) ); +} + +TEST_CASE("Matchers can be (AnyOf) composed with the || operator", "[matchers][operators][operator||]") +{ + CHECK_THAT( testStringForMatching(), Contains( "string" ) || Contains( "different" ) || Contains( "random" ) ); + CHECK_THAT( testStringForMatching2(), Contains( "string" ) || Contains( "different" ) || Contains( "random" ) ); +} + +TEST_CASE("Matchers can be composed with both && and ||", "[matchers][operators][operator||][operator&&]") +{ + CHECK_THAT( testStringForMatching(), ( Contains( "string" ) || Contains( "different" ) ) && Contains( "substring" ) ); +} + +TEST_CASE("Matchers can be composed with both && and || - failing", "[matchers][operators][operator||][operator&&][.failing]") +{ + CHECK_THAT( testStringForMatching(), ( Contains( "string" ) || Contains( "different" ) ) && Contains( "random" ) ); +} + +TEST_CASE("Matchers can be negated (Not) with the ! operator", "[matchers][operators][not]") +{ + CHECK_THAT( testStringForMatching(), !Contains( "different" ) ); +} + +TEST_CASE("Matchers can be negated (Not) with the ! operator - failing", "[matchers][operators][not][.failing]") +{ + CHECK_THAT( testStringForMatching(), !Contains( "substring" ) ); +} + + +inline unsigned int Factorial( unsigned int number ) +{ +// return number <= 1 ? number : Factorial(number-1)*number; + return number > 1 ? Factorial(number-1)*number : 1; +} + +TEST_CASE( "Factorials are computed", "[factorial]" ) { + REQUIRE( Factorial(0) == 1 ); + REQUIRE( Factorial(1) == 1 ); + REQUIRE( Factorial(2) == 2 ); + REQUIRE( Factorial(3) == 6 ); + REQUIRE( Factorial(10) == 3628800 ); +} + +TEST_CASE( "An empty test with no assertions", "[empty]" ) +{ +} + +TEST_CASE( "Nice descriptive name", "[tag1][tag2][tag3][.]" ) +{ + WARN( "This one ran" ); +} +TEST_CASE( "first tag", "[tag1]" ) +{ +} +TEST_CASE( "second tag", "[tag2]" ) +{ +} +// +//TEST_CASE( "spawn a new process", "[.]" ) +//{ +// // !TBD Work in progress +// char line[200]; +// FILE* output = popen("./CatchSelfTest ./failing/matchers/StartsWith", "r"); +// while ( fgets(line, 199, output) ) +// std::cout << line; +//} + +TEST_CASE( "vectors can be sized and resized", "[vector]" ) { + + std::vector<int> v( 5 ); + + REQUIRE( v.size() == 5 ); + REQUIRE( v.capacity() >= 5 ); + + SECTION( "resizing bigger changes size and capacity", "" ) { + v.resize( 10 ); + + REQUIRE( v.size() == 10 ); + REQUIRE( v.capacity() >= 10 ); + } + SECTION( "resizing smaller changes size but not capacity", "" ) { + v.resize( 0 ); + + REQUIRE( v.size() == 0 ); + REQUIRE( v.capacity() >= 5 ); + + SECTION( "We can use the 'swap trick' to reset the capacity", "" ) { + std::vector<int> empty; + empty.swap( v ); + + REQUIRE( v.capacity() == 0 ); + } + } + SECTION( "reserving bigger changes capacity but not size", "" ) { + v.reserve( 10 ); + + REQUIRE( v.size() == 5 ); + REQUIRE( v.capacity() >= 10 ); + } + SECTION( "reserving smaller does not change size or capacity", "" ) { + v.reserve( 0 ); + + REQUIRE( v.size() == 5 ); + REQUIRE( v.capacity() >= 5 ); + } +} + +// https://github.com/philsquared/Catch/issues/166 +TEST_CASE("A couple of nested sections followed by a failure", "[failing][.]") +{ + SECTION("Outer", "") + SECTION("Inner", "") + SUCCEED("that's not flying - that's failing in style"); + + FAIL("to infinity and beyond"); +} + +TEST_CASE("not allowed", "[!throws]") +{ + // This test case should not be included if you run with -e on the command line + SUCCEED( "" ); +} + +//TEST_CASE( "Is big endian" ) { +// CHECK( Catch::Detail::Endianness::which() == Catch::Detail::Endianness::Little ); +//} + +TEST_CASE( "Tabs and newlines show in output", "[.][whitespace][failing]" ) { + + // Based on issue #242 + std::string s1 = "if ($b == 10) {\n\t\t$a\t= 20;\n}"; + std::string s2 = "if ($b == 10) {\n\t$a = 20;\n}\n"; + CHECK( s1 == s2 ); +} + + +TEST_CASE( "toString on const wchar_t const pointer returns the string contents", "[toString]" ) { + const wchar_t * const s = L"wide load"; + std::string result = Catch::toString( s ); + CHECK( result == "\"wide load\"" ); +} + +TEST_CASE( "toString on const wchar_t pointer returns the string contents", "[toString]" ) { + const wchar_t * s = L"wide load"; + std::string result = Catch::toString( s ); + CHECK( result == "\"wide load\"" ); +} + +TEST_CASE( "toString on wchar_t const pointer returns the string contents", "[toString]" ) { + wchar_t * const s = const_cast<wchar_t* const>( L"wide load" ); + std::string result = Catch::toString( s ); + CHECK( result == "\"wide load\"" ); +} + +TEST_CASE( "toString on wchar_t returns the string contents", "[toString]" ) { + wchar_t * s = const_cast<wchar_t*>( L"wide load" ); + std::string result = Catch::toString( s ); + CHECK( result == "\"wide load\"" ); +} + +inline std::string encode( std::string const& str, Catch::XmlEncode::ForWhat forWhat = Catch::XmlEncode::ForTextNodes ) { + std::ostringstream oss; + oss << Catch::XmlEncode( str, forWhat ); + return oss.str(); +} + +TEST_CASE( "XmlEncode" ) { + SECTION( "normal string" ) { + REQUIRE( encode( "normal string" ) == "normal string" ); + } + SECTION( "empty string" ) { + REQUIRE( encode( "" ) == "" ); + } + SECTION( "string with ampersand" ) { + REQUIRE( encode( "smith & jones" ) == "smith & jones" ); + } + SECTION( "string with less-than" ) { + REQUIRE( encode( "smith < jones" ) == "smith < jones" ); + } + SECTION( "string with greater-than" ) { + REQUIRE( encode( "smith > jones" ) == "smith > jones" ); + REQUIRE( encode( "smith ]]> jones" ) == "smith ]]> jones" ); + } + SECTION( "string with quotes" ) { + std::string stringWithQuotes = "don't \"quote\" me on that"; + REQUIRE( encode( stringWithQuotes ) == stringWithQuotes ); + REQUIRE( encode( stringWithQuotes, Catch::XmlEncode::ForAttributes ) == "don't "quote" me on that" ); + } + SECTION( "string with control char (1)" ) { + REQUIRE( encode( "[\x01]" ) == "[]" ); + } + SECTION( "string with control char (x7F)" ) { + REQUIRE( encode( "[\x7F]" ) == "[]" ); + } +} + +#ifdef CATCH_CONFIG_CPP11_LONG_LONG +TEST_CASE( "long long" ) { + long long l = std::numeric_limits<long long>::max(); + + REQUIRE( l == std::numeric_limits<long long>::max() ); +} +#endif + +//TEST_CASE( "Divide by Zero signal handler", "[.][sig]" ) { +// int i = 0; +// int x = 10/i; // This should cause the signal to fire +// CHECK( x == 0 ); +//} diff --git a/unittest/Catch/projects/SelfTest/PartTrackerTests.cpp b/unittest/Catch/projects/SelfTest/PartTrackerTests.cpp new file mode 100644 index 0000000..2925635 --- /dev/null +++ b/unittest/Catch/projects/SelfTest/PartTrackerTests.cpp @@ -0,0 +1,328 @@ +/* + * Created by Phil on 1/10/2015. + * Copyright 2015 Two Blue Cubes Ltd + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + */ +#include "internal/catch_suppress_warnings.h" +#include "internal/catch_test_case_tracker.hpp" + + +namespace Catch +{ + class LocalContext { + + public: + TrackerContext& operator()() const { + return TrackerContext::instance(); + } + }; + +} // namespace Catch + +inline Catch::TrackerContext& C_A_T_C_H_Context() { + return Catch::TrackerContext::instance(); +} + +// ------------------- + +#include "catch.hpp" + +using namespace Catch; + +//inline void testCase( Catch::LocalContext const& C_A_T_C_H_Context ) { +// +// REQUIRE( C_A_T_C_H_Context().i() == 42 ); +//} + +TEST_CASE( "Tracker", "" ) { + + TrackerContext ctx; + ctx.startRun(); + ctx.startCycle(); + + ITracker& testCase = SectionTracker::acquire( ctx, "Testcase" ); + REQUIRE( testCase.isOpen() ); + + ITracker& s1 = SectionTracker::acquire( ctx, "S1" ); + REQUIRE( s1.isOpen() ); + + SECTION( "successfully close one section", "" ) { + s1.close(); + REQUIRE( s1.isSuccessfullyCompleted() ); + REQUIRE( testCase.isComplete() == false ); + + testCase.close(); + REQUIRE( ctx.completedCycle() ); + REQUIRE( testCase.isSuccessfullyCompleted() ); + } + + SECTION( "fail one section", "" ) { + s1.fail(); + REQUIRE( s1.isComplete() ); + REQUIRE( s1.isSuccessfullyCompleted() == false ); + REQUIRE( testCase.isComplete() == false ); + + testCase.close(); + REQUIRE( ctx.completedCycle() ); + REQUIRE( testCase.isSuccessfullyCompleted() == false ); + + SECTION( "re-enter after failed section", "" ) { + ctx.startCycle(); + ITracker& testCase2 = SectionTracker::acquire( ctx, "Testcase" ); + REQUIRE( testCase2.isOpen() ); + + ITracker& s1b = SectionTracker::acquire( ctx, "S1" ); + REQUIRE( s1b.isOpen() == false ); + + testCase2.close(); + REQUIRE( ctx.completedCycle() ); + REQUIRE( testCase.isComplete() ); + REQUIRE( testCase.isSuccessfullyCompleted() ); + } + SECTION( "re-enter after failed section and find next section", "" ) { + ctx.startCycle(); + ITracker& testCase2 = SectionTracker::acquire( ctx, "Testcase" ); + REQUIRE( testCase2.isOpen() ); + + ITracker& s1b = SectionTracker::acquire( ctx, "S1" ); + REQUIRE( s1b.isOpen() == false ); + + ITracker& s2 = SectionTracker::acquire( ctx, "S2" ); + REQUIRE( s2.isOpen() ); + + s2.close(); + REQUIRE( ctx.completedCycle() ); + + testCase2.close(); + REQUIRE( testCase.isComplete() ); + REQUIRE( testCase.isSuccessfullyCompleted() ); + } + } + + SECTION( "successfully close one section, then find another", "" ) { + s1.close(); + + ITracker& s2 = SectionTracker::acquire( ctx, "S2" ); + REQUIRE( s2.isOpen() == false ); + + testCase.close(); + REQUIRE( testCase.isComplete() == false ); + + SECTION( "Re-enter - skips S1 and enters S2", "" ) { + ctx.startCycle(); + ITracker& testCase2 = SectionTracker::acquire( ctx, "Testcase" ); + REQUIRE( testCase2.isOpen() ); + + ITracker& s1b = SectionTracker::acquire( ctx, "S1" ); + REQUIRE( s1b.isOpen() == false ); + + ITracker& s2b = SectionTracker::acquire( ctx, "S2" ); + REQUIRE( s2b.isOpen() ); + + REQUIRE( ctx.completedCycle() == false ); + + SECTION ("Successfully close S2") { + s2b.close(); + REQUIRE( ctx.completedCycle() ); + + REQUIRE( s2b.isSuccessfullyCompleted() ); + REQUIRE( testCase2.isComplete() == false ); + + testCase2.close(); + REQUIRE( testCase2.isSuccessfullyCompleted() ); + } + SECTION ("fail S2") { + s2b.fail(); + REQUIRE( ctx.completedCycle() ); + + REQUIRE( s2b.isComplete() ); + REQUIRE( s2b.isSuccessfullyCompleted() == false ); + + testCase2.close(); + REQUIRE( testCase2.isSuccessfullyCompleted() == false ); + + // Need a final cycle + ctx.startCycle(); + ITracker& testCase3 = SectionTracker::acquire( ctx, "Testcase" ); + REQUIRE( testCase3.isOpen() ); + + ITracker& s1c = SectionTracker::acquire( ctx, "S1" ); + REQUIRE( s1c.isOpen() == false ); + + ITracker& s2c = SectionTracker::acquire( ctx, "S2" ); + REQUIRE( s2c.isOpen() == false ); + + testCase3.close(); + REQUIRE( testCase3.isSuccessfullyCompleted() ); + } + } + } + + SECTION( "open a nested section", "" ) { + ITracker& s2 = SectionTracker::acquire( ctx, "S2" ); + REQUIRE( s2.isOpen() ); + + s2.close(); + REQUIRE( s2.isComplete() ); + REQUIRE( s1.isComplete() == false ); + + s1.close(); + REQUIRE( s1.isComplete() ); + REQUIRE( testCase.isComplete() == false ); + + testCase.close(); + REQUIRE( testCase.isComplete() ); + } + + SECTION( "start a generator", "" ) { + IndexTracker& g1 = IndexTracker::acquire( ctx, "G1", 2 ); + REQUIRE( g1.isOpen() ); + REQUIRE( g1.index() == 0 ); + + REQUIRE( g1.isComplete() == false ); + REQUIRE( s1.isComplete() == false ); + + SECTION( "close outer section" ) + { + s1.close(); + REQUIRE( s1.isComplete() == false ); + testCase.close(); + REQUIRE( testCase.isSuccessfullyCompleted() == false ); + + SECTION( "Re-enter for second generation", "" ) { + ctx.startCycle(); + ITracker& testCase2 = SectionTracker::acquire( ctx, "Testcase" ); + REQUIRE( testCase2.isOpen() ); + + ITracker& s1b = SectionTracker::acquire( ctx, "S1" ); + REQUIRE( s1b.isOpen() ); + + + IndexTracker& g1b = IndexTracker::acquire( ctx, "G1", 2 ); + REQUIRE( g1b.isOpen() ); + REQUIRE( g1b.index() == 1 ); + + REQUIRE( s1.isComplete() == false ); + + s1b.close(); + REQUIRE( s1b.isComplete() ); + REQUIRE( g1b.isComplete() ); + testCase2.close(); + REQUIRE( testCase2.isComplete() ); + } + } + SECTION( "Start a new inner section", "" ) { + ITracker& s2 = SectionTracker::acquire( ctx, "S2" ); + REQUIRE( s2.isOpen() ); + + s2.close(); + REQUIRE( s2.isComplete() ); + + s1.close(); + REQUIRE( s1.isComplete() == false ); + + testCase.close(); + REQUIRE( testCase.isComplete() == false ); + + SECTION( "Re-enter for second generation", "" ) { + ctx.startCycle(); + ITracker& testCase2 = SectionTracker::acquire( ctx, "Testcase" ); + REQUIRE( testCase2.isOpen() ); + + ITracker& s1b = SectionTracker::acquire( ctx, "S1" ); + REQUIRE( s1b.isOpen() ); + + // generator - next value + IndexTracker& g1b = IndexTracker::acquire( ctx, "G1", 2 ); + REQUIRE( g1b.isOpen() ); + REQUIRE( g1b.index() == 1 ); + + // inner section again + ITracker& s2b = SectionTracker::acquire( ctx, "S2" ); + REQUIRE( s2b.isOpen() ); + + s2b.close(); + REQUIRE( s2b.isComplete() ); + + s1b.close(); + REQUIRE( g1b.isComplete() ); + REQUIRE( s1b.isComplete() ); + + testCase2.close(); + REQUIRE( testCase2.isComplete() ); + } + } + + SECTION( "Fail an inner section", "" ) { + ITracker& s2 = SectionTracker::acquire( ctx, "S2" ); + REQUIRE( s2.isOpen() ); + + s2.fail(); + REQUIRE( s2.isComplete() ); + REQUIRE( s2.isSuccessfullyCompleted() == false ); + + s1.close(); + REQUIRE( s1.isComplete() == false ); + + testCase.close(); + REQUIRE( testCase.isComplete() == false ); + + SECTION( "Re-enter for second generation", "" ) { + ctx.startCycle(); + ITracker& testCase2 = SectionTracker::acquire( ctx, "Testcase" ); + REQUIRE( testCase2.isOpen() ); + + ITracker& s1b = SectionTracker::acquire( ctx, "S1" ); + REQUIRE( s1b.isOpen() ); + + // generator - still same value + IndexTracker& g1b = IndexTracker::acquire( ctx, "G1", 2 ); + REQUIRE( g1b.isOpen() ); + REQUIRE( g1b.index() == 0 ); + + // inner section again - this time won't open + ITracker& s2b = SectionTracker::acquire( ctx, "S2" ); + REQUIRE( s2b.isOpen() == false ); + + s1b.close(); + REQUIRE( g1b.isComplete() == false ); + REQUIRE( s1b.isComplete() == false ); + + testCase2.close(); + REQUIRE( testCase2.isComplete() == false ); + + // Another cycle - now should complete + ctx.startCycle(); + ITracker& testCase3 = SectionTracker::acquire( ctx, "Testcase" ); + REQUIRE( testCase3.isOpen() ); + + ITracker& s1c = SectionTracker::acquire( ctx, "S1" ); + REQUIRE( s1c.isOpen() ); + + // generator - now next value + IndexTracker& g1c = IndexTracker::acquire( ctx, "G1", 2 ); + REQUIRE( g1c.isOpen() ); + REQUIRE( g1c.index() == 1 ); + + // inner section - now should open again + ITracker& s2c = SectionTracker::acquire( ctx, "S2" ); + REQUIRE( s2c.isOpen() ); + + s2c.close(); + REQUIRE( s2c.isComplete() ); + + s1c.close(); + REQUIRE( g1c.isComplete() ); + REQUIRE( s1c.isComplete() ); + + testCase3.close(); + REQUIRE( testCase3.isComplete() ); + } + } + // !TBD" + // nested generator + // two sections within a generator + } +} diff --git a/unittest/Catch/projects/SelfTest/SurrogateCpps/catch_common.cpp b/unittest/Catch/projects/SelfTest/SurrogateCpps/catch_common.cpp new file mode 100644 index 0000000..72f90bd --- /dev/null +++ b/unittest/Catch/projects/SelfTest/SurrogateCpps/catch_common.cpp @@ -0,0 +1,3 @@ +// This file is only here to verify (to the extent possible) the self sufficiency of the header +#include "catch_suppress_warnings.h" +#include "catch_common.h" diff --git a/unittest/Catch/projects/SelfTest/SurrogateCpps/catch_console_colour.cpp b/unittest/Catch/projects/SelfTest/SurrogateCpps/catch_console_colour.cpp new file mode 100644 index 0000000..e7378c0 --- /dev/null +++ b/unittest/Catch/projects/SelfTest/SurrogateCpps/catch_console_colour.cpp @@ -0,0 +1,3 @@ +// This file is only here to verify (to the extent possible) the self sufficiency of the header +#include "catch_suppress_warnings.h" +#include "catch_console_colour.hpp" diff --git a/unittest/Catch/projects/SelfTest/SurrogateCpps/catch_debugger.cpp b/unittest/Catch/projects/SelfTest/SurrogateCpps/catch_debugger.cpp new file mode 100644 index 0000000..33f76ae --- /dev/null +++ b/unittest/Catch/projects/SelfTest/SurrogateCpps/catch_debugger.cpp @@ -0,0 +1,2 @@ +// This file is only here to verify (to the extent possible) the self sufficiency of the header +#include "catch_debugger.h" diff --git a/unittest/Catch/projects/SelfTest/SurrogateCpps/catch_interfaces_capture.cpp b/unittest/Catch/projects/SelfTest/SurrogateCpps/catch_interfaces_capture.cpp new file mode 100644 index 0000000..2d1c8f3 --- /dev/null +++ b/unittest/Catch/projects/SelfTest/SurrogateCpps/catch_interfaces_capture.cpp @@ -0,0 +1,3 @@ +// This file is only here to verify (to the extent possible) the self sufficiency of the header +#include "catch_suppress_warnings.h" +#include "catch_interfaces_capture.h" diff --git a/unittest/Catch/projects/SelfTest/SurrogateCpps/catch_interfaces_config.cpp b/unittest/Catch/projects/SelfTest/SurrogateCpps/catch_interfaces_config.cpp new file mode 100644 index 0000000..de0f18d --- /dev/null +++ b/unittest/Catch/projects/SelfTest/SurrogateCpps/catch_interfaces_config.cpp @@ -0,0 +1,2 @@ +#include "catch_suppress_warnings.h" +#include "catch_interfaces_config.h" diff --git a/unittest/Catch/projects/SelfTest/SurrogateCpps/catch_interfaces_exception.cpp b/unittest/Catch/projects/SelfTest/SurrogateCpps/catch_interfaces_exception.cpp new file mode 100644 index 0000000..183d87d --- /dev/null +++ b/unittest/Catch/projects/SelfTest/SurrogateCpps/catch_interfaces_exception.cpp @@ -0,0 +1,2 @@ +#include "catch_suppress_warnings.h" +#include "catch_interfaces_exception.h" diff --git a/unittest/Catch/projects/SelfTest/SurrogateCpps/catch_interfaces_generators.cpp b/unittest/Catch/projects/SelfTest/SurrogateCpps/catch_interfaces_generators.cpp new file mode 100644 index 0000000..271b1bc --- /dev/null +++ b/unittest/Catch/projects/SelfTest/SurrogateCpps/catch_interfaces_generators.cpp @@ -0,0 +1 @@ +#include "catch_interfaces_generators.h" diff --git a/unittest/Catch/projects/SelfTest/SurrogateCpps/catch_interfaces_registry_hub.cpp b/unittest/Catch/projects/SelfTest/SurrogateCpps/catch_interfaces_registry_hub.cpp new file mode 100644 index 0000000..ffece3b --- /dev/null +++ b/unittest/Catch/projects/SelfTest/SurrogateCpps/catch_interfaces_registry_hub.cpp @@ -0,0 +1,3 @@ +// This file is only here to verify (to the extent possible) the self sufficiency of the header +#include "catch_suppress_warnings.h" +#include "catch_interfaces_registry_hub.h" diff --git a/unittest/Catch/projects/SelfTest/SurrogateCpps/catch_interfaces_reporter.cpp b/unittest/Catch/projects/SelfTest/SurrogateCpps/catch_interfaces_reporter.cpp new file mode 100644 index 0000000..544f9d0 --- /dev/null +++ b/unittest/Catch/projects/SelfTest/SurrogateCpps/catch_interfaces_reporter.cpp @@ -0,0 +1,2 @@ +#include "catch_suppress_warnings.h" +#include "catch_interfaces_reporter.h" diff --git a/unittest/Catch/projects/SelfTest/SurrogateCpps/catch_interfaces_runner.cpp b/unittest/Catch/projects/SelfTest/SurrogateCpps/catch_interfaces_runner.cpp new file mode 100644 index 0000000..401de26 --- /dev/null +++ b/unittest/Catch/projects/SelfTest/SurrogateCpps/catch_interfaces_runner.cpp @@ -0,0 +1 @@ +#include "catch_interfaces_runner.h" diff --git a/unittest/Catch/projects/SelfTest/SurrogateCpps/catch_interfaces_testcase.cpp b/unittest/Catch/projects/SelfTest/SurrogateCpps/catch_interfaces_testcase.cpp new file mode 100644 index 0000000..733dcb4 --- /dev/null +++ b/unittest/Catch/projects/SelfTest/SurrogateCpps/catch_interfaces_testcase.cpp @@ -0,0 +1,2 @@ +#include "catch_suppress_warnings.h" +#include "catch_interfaces_testcase.h" diff --git a/unittest/Catch/projects/SelfTest/SurrogateCpps/catch_message.cpp b/unittest/Catch/projects/SelfTest/SurrogateCpps/catch_message.cpp new file mode 100644 index 0000000..ad2f5e7 --- /dev/null +++ b/unittest/Catch/projects/SelfTest/SurrogateCpps/catch_message.cpp @@ -0,0 +1,3 @@ +// This file is only here to verify (to the extent possible) the self sufficiency of the header +#include "catch_suppress_warnings.h" +#include "catch_message.h" diff --git a/unittest/Catch/projects/SelfTest/SurrogateCpps/catch_option.cpp b/unittest/Catch/projects/SelfTest/SurrogateCpps/catch_option.cpp new file mode 100644 index 0000000..35e3282 --- /dev/null +++ b/unittest/Catch/projects/SelfTest/SurrogateCpps/catch_option.cpp @@ -0,0 +1,3 @@ +// This file is only here to verify (to the extent possible) the self sufficiency of the header +#include "catch_suppress_warnings.h" +#include "catch_option.hpp" diff --git a/unittest/Catch/projects/SelfTest/SurrogateCpps/catch_ptr.cpp b/unittest/Catch/projects/SelfTest/SurrogateCpps/catch_ptr.cpp new file mode 100644 index 0000000..a25ad66 --- /dev/null +++ b/unittest/Catch/projects/SelfTest/SurrogateCpps/catch_ptr.cpp @@ -0,0 +1,3 @@ +// This file is only here to verify (to the extent possible) the self sufficiency of the header +#include "catch_suppress_warnings.h" +#include "catch_ptr.hpp" diff --git a/unittest/Catch/projects/SelfTest/SurrogateCpps/catch_stream.cpp b/unittest/Catch/projects/SelfTest/SurrogateCpps/catch_stream.cpp new file mode 100644 index 0000000..7aaffa1 --- /dev/null +++ b/unittest/Catch/projects/SelfTest/SurrogateCpps/catch_stream.cpp @@ -0,0 +1,3 @@ +// This file is only here to verify (to the extent possible) the self sufficiency of the header +#include "catch_suppress_warnings.h" +#include "catch_stream.h" diff --git a/unittest/Catch/projects/SelfTest/SurrogateCpps/catch_streambuf.cpp b/unittest/Catch/projects/SelfTest/SurrogateCpps/catch_streambuf.cpp new file mode 100644 index 0000000..5c0043c --- /dev/null +++ b/unittest/Catch/projects/SelfTest/SurrogateCpps/catch_streambuf.cpp @@ -0,0 +1,3 @@ +// This file is only here to verify (to the extent possible) the self sufficiency of the header +#include "catch_suppress_warnings.h" +#include "catch_streambuf.h" diff --git a/unittest/Catch/projects/SelfTest/SurrogateCpps/catch_test_spec.cpp b/unittest/Catch/projects/SelfTest/SurrogateCpps/catch_test_spec.cpp new file mode 100644 index 0000000..46bf89f --- /dev/null +++ b/unittest/Catch/projects/SelfTest/SurrogateCpps/catch_test_spec.cpp @@ -0,0 +1,3 @@ +// This file is only here to verify (to the extent possible) the self sufficiency of the header +#include "catch_suppress_warnings.h" +#include "catch_test_spec.hpp" diff --git a/unittest/Catch/projects/SelfTest/SurrogateCpps/catch_xmlwriter.cpp b/unittest/Catch/projects/SelfTest/SurrogateCpps/catch_xmlwriter.cpp new file mode 100644 index 0000000..15328ef --- /dev/null +++ b/unittest/Catch/projects/SelfTest/SurrogateCpps/catch_xmlwriter.cpp @@ -0,0 +1,4 @@ +// This file is only here to verify (to the extent possible) the self sufficiency of the header +#include "catch_suppress_warnings.h" +#include "catch_xmlwriter.hpp" +#include "catch_reenable_warnings.h" diff --git a/unittest/Catch/projects/SelfTest/TagAliasTests.cpp b/unittest/Catch/projects/SelfTest/TagAliasTests.cpp new file mode 100644 index 0000000..002a93c --- /dev/null +++ b/unittest/Catch/projects/SelfTest/TagAliasTests.cpp @@ -0,0 +1,41 @@ +/* + * Created by Phil on 27/06/2014. + * Copyright 2014 Two Blue Cubes Ltd. All rights reserved. + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + */ + +#include "catch.hpp" +#include "internal/catch_tag_alias_registry.h" + +TEST_CASE( "Tag alias can be registered against tag patterns", "" ) { + + using namespace Catch::Matchers; + + Catch::TagAliasRegistry registry; + + registry.add( "[@zzz]", "[one][two]", Catch::SourceLineInfo( "file", 2 ) ); + + SECTION( "The same tag alias can only be registered once", "" ) { + + try { + registry.add( "[@zzz]", "[one][two]", Catch::SourceLineInfo( "file", 10 ) ); + FAIL( "expected exception" ); + } + catch( std::exception& ex ) { + std::string what = ex.what(); + CHECK_THAT( what, Contains( "[@zzz]" ) ); + CHECK_THAT( what, Contains( "file" ) ); + CHECK_THAT( what, Contains( "2" ) ); + CHECK_THAT( what, Contains( "10" ) ); + } + } + + SECTION( "Tag aliases must be of the form [@name]", "" ) { + CHECK_THROWS( registry.add( "[no ampersat]", "", Catch::SourceLineInfo( "file", 3 ) ) ); + CHECK_THROWS( registry.add( "[the @ is not at the start]", "", Catch::SourceLineInfo( "file", 3 ) ) ); + CHECK_THROWS( registry.add( "@no square bracket at start]", "", Catch::SourceLineInfo( "file", 3 ) ) ); + CHECK_THROWS( registry.add( "[@no square bracket at end", "", Catch::SourceLineInfo( "file", 3 ) ) ); + } +} diff --git a/unittest/Catch/projects/SelfTest/TestMain.cpp b/unittest/Catch/projects/SelfTest/TestMain.cpp new file mode 100644 index 0000000..c63f469 --- /dev/null +++ b/unittest/Catch/projects/SelfTest/TestMain.cpp @@ -0,0 +1,483 @@ +/* + * Created by Phil on 22/10/2010. + * Copyright 2010 Two Blue Cubes Ltd + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + */ + +#define CATCH_CONFIG_MAIN +#include "catch.hpp" +#include "../include/reporters/catch_reporter_teamcity.hpp" + +// Some example tag aliases +CATCH_REGISTER_TAG_ALIAS( "[@nhf]", "[failing]~[.]" ) +CATCH_REGISTER_TAG_ALIAS( "[@tricky]", "[tricky]~[.]" ) + + +#ifdef __clang__ +# pragma clang diagnostic ignored "-Wpadded" +# pragma clang diagnostic ignored "-Wweak-vtables" +# pragma clang diagnostic ignored "-Wc++98-compat" +#endif + + +template<size_t size> +void parseIntoConfig( const char * (&argv)[size], Catch::ConfigData& config ) { + Catch::Clara::CommandLine<Catch::ConfigData> parser = Catch::makeCommandLineParser(); + parser.parseInto( size, argv, config ); +} + +template<size_t size> +std::string parseIntoConfigAndReturnError( const char * (&argv)[size], Catch::ConfigData& config ) { + try { + parseIntoConfig( argv, config ); + FAIL( "expected exception" ); + } + catch( std::exception& ex ) { + return ex.what(); + } + return ""; +} + +inline Catch::TestCase fakeTestCase( const char* name, const char* desc = "" ){ return Catch::makeTestCase( CATCH_NULL, "", name, desc, CATCH_INTERNAL_LINEINFO ); } + +TEST_CASE( "Process can be configured on command line", "[config][command-line]" ) { + + using namespace Catch::Matchers; + + Catch::ConfigData config; + + SECTION( "default - no arguments", "" ) { + const char* argv[] = { "test" }; + CHECK_NOTHROW( parseIntoConfig( argv, config ) ); + + CHECK( config.shouldDebugBreak == false ); + CHECK( config.abortAfter == -1 ); + CHECK( config.noThrow == false ); + CHECK( config.reporterNames.empty() ); + } + + SECTION( "test lists", "" ) { + SECTION( "1 test", "Specify one test case using" ) { + const char* argv[] = { "test", "test1" }; + CHECK_NOTHROW( parseIntoConfig( argv, config ) ); + + Catch::Config cfg( config ); + REQUIRE( cfg.testSpec().matches( fakeTestCase( "notIncluded" ) ) == false ); + REQUIRE( cfg.testSpec().matches( fakeTestCase( "test1" ) ) ); + } + SECTION( "Specify one test case exclusion using exclude:", "" ) { + const char* argv[] = { "test", "exclude:test1" }; + CHECK_NOTHROW( parseIntoConfig( argv, config ) ); + + Catch::Config cfg( config ); + REQUIRE( cfg.testSpec().matches( fakeTestCase( "test1" ) ) == false ); + REQUIRE( cfg.testSpec().matches( fakeTestCase( "alwaysIncluded" ) ) ); + } + + SECTION( "Specify one test case exclusion using ~", "" ) { + const char* argv[] = { "test", "~test1" }; + CHECK_NOTHROW( parseIntoConfig( argv, config ) ); + + Catch::Config cfg( config ); + REQUIRE( cfg.testSpec().matches( fakeTestCase( "test1" ) ) == false ); + REQUIRE( cfg.testSpec().matches( fakeTestCase( "alwaysIncluded" ) ) ); + } + + } + + SECTION( "reporter", "" ) { + SECTION( "-r/console", "" ) { + const char* argv[] = { "test", "-r", "console" }; + CHECK_NOTHROW( parseIntoConfig( argv, config ) ); + + REQUIRE( config.reporterNames[0] == "console" ); + } + SECTION( "-r/xml", "" ) { + const char* argv[] = { "test", "-r", "xml" }; + CHECK_NOTHROW( parseIntoConfig( argv, config ) ); + + REQUIRE( config.reporterNames[0] == "xml" ); + } + SECTION( "-r xml and junit", "" ) { + const char* argv[] = { "test", "-r", "xml", "-r", "junit" }; + CHECK_NOTHROW( parseIntoConfig( argv, config ) ); + + REQUIRE( config.reporterNames.size() == 2 ); + REQUIRE( config.reporterNames[0] == "xml" ); + REQUIRE( config.reporterNames[1] == "junit" ); + } + SECTION( "--reporter/junit", "" ) { + const char* argv[] = { "test", "--reporter", "junit" }; + CHECK_NOTHROW( parseIntoConfig( argv, config ) ); + + REQUIRE( config.reporterNames[0] == "junit" ); + } + } + + SECTION( "debugger", "" ) { + SECTION( "-b", "" ) { + const char* argv[] = { "test", "-b" }; + CHECK_NOTHROW( parseIntoConfig( argv, config ) ); + + REQUIRE( config.shouldDebugBreak == true ); + } + SECTION( "--break", "" ) { + const char* argv[] = { "test", "--break" }; + CHECK_NOTHROW( parseIntoConfig( argv, config ) ); + + REQUIRE( config.shouldDebugBreak ); + } + } + + SECTION( "abort", "" ) { + SECTION( "-a aborts after first failure", "" ) { + const char* argv[] = { "test", "-a" }; + CHECK_NOTHROW( parseIntoConfig( argv, config ) ); + + REQUIRE( config.abortAfter == 1 ); + } + SECTION( "-x 2 aborts after two failures", "" ) { + const char* argv[] = { "test", "-x", "2" }; + CHECK_NOTHROW( parseIntoConfig( argv, config ) ); + + REQUIRE( config.abortAfter == 2 ); + } + SECTION( "-x must be greater than zero", "" ) { + const char* argv[] = { "test", "-x", "0" }; + REQUIRE_THAT( parseIntoConfigAndReturnError( argv, config ), Contains( "greater than zero" ) ); + } + SECTION( "-x must be numeric", "" ) { + const char* argv[] = { "test", "-x", "oops" }; + REQUIRE_THAT( parseIntoConfigAndReturnError( argv, config ), Contains( "-x" ) ); + } + } + + SECTION( "nothrow", "" ) { + SECTION( "-e", "" ) { + const char* argv[] = { "test", "-e" }; + CHECK_NOTHROW( parseIntoConfig( argv, config ) ); + + REQUIRE( config.noThrow == true ); + } + SECTION( "--nothrow", "" ) { + const char* argv[] = { "test", "--nothrow" }; + CHECK_NOTHROW( parseIntoConfig( argv, config ) ); + + REQUIRE( config.noThrow == true ); + } + } + + SECTION( "output filename", "" ) { + SECTION( "-o filename", "" ) { + const char* argv[] = { "test", "-o", "filename.ext" }; + CHECK_NOTHROW( parseIntoConfig( argv, config ) ); + + REQUIRE( config.outputFilename == "filename.ext" ); + } + SECTION( "--out", "" ) { + const char* argv[] = { "test", "--out", "filename.ext" }; + CHECK_NOTHROW( parseIntoConfig( argv, config ) ); + + REQUIRE( config.outputFilename == "filename.ext" ); + } + } + + SECTION( "combinations", "" ) { + SECTION( "Single character flags can be combined", "" ) { + const char* argv[] = { "test", "-abe" }; + CHECK_NOTHROW( parseIntoConfig( argv, config ) ); + + CHECK( config.abortAfter == 1 ); + CHECK( config.shouldDebugBreak ); + CHECK( config.noThrow == true ); + } + } + + SECTION( "use-colour", "") { + + using Catch::UseColour; + + SECTION( "without option", "" ) { + const char* argv[] = { "test" }; + CHECK_NOTHROW( parseIntoConfig( argv, config ) ); + + REQUIRE( config.useColour == UseColour::Auto ); + } + + SECTION( "auto", "" ) { + const char* argv[] = { "test", "--use-colour", "auto" }; + CHECK_NOTHROW( parseIntoConfig( argv, config ) ); + + REQUIRE( config.useColour == UseColour::Auto ); + } + + SECTION( "yes", "" ) { + const char* argv[] = { "test", "--use-colour", "yes" }; + CHECK_NOTHROW( parseIntoConfig( argv, config ) ); + + REQUIRE( config.useColour == UseColour::Yes ); + } + + SECTION( "no", "" ) { + const char* argv[] = { "test", "--use-colour", "no" }; + CHECK_NOTHROW( parseIntoConfig( argv, config ) ); + + REQUIRE( config.useColour == UseColour::No ); + } + + SECTION( "error", "" ) { + const char* argv[] = { "test", "--use-colour", "wrong" }; + REQUIRE_THROWS_WITH( parseIntoConfig( argv, config ), Contains( "colour mode must be one of" ) ); + } + } +} + + +TEST_CASE( "Long strings can be wrapped", "[wrap]" ) { + + using namespace Catch; + SECTION( "plain string", "" ) { + // guide: 123456789012345678 + std::string testString = "one two three four"; + + SECTION( "No wrapping", "" ) { + CHECK( Text( testString, TextAttributes().setWidth( 80 ) ).toString() == testString ); + CHECK( Text( testString, TextAttributes().setWidth( 18 ) ).toString() == testString ); + } + SECTION( "Wrapped once", "" ) { + CHECK( Text( testString, TextAttributes().setWidth( 17 ) ).toString() == "one two three\nfour" ); + CHECK( Text( testString, TextAttributes().setWidth( 16 ) ).toString() == "one two three\nfour" ); + CHECK( Text( testString, TextAttributes().setWidth( 14 ) ).toString() == "one two three\nfour" ); + CHECK( Text( testString, TextAttributes().setWidth( 13 ) ).toString() == "one two three\nfour" ); + CHECK( Text( testString, TextAttributes().setWidth( 12 ) ).toString() == "one two\nthree four" ); + } + SECTION( "Wrapped twice", "" ) { + CHECK( Text( testString, TextAttributes().setWidth( 9 ) ).toString() == "one two\nthree\nfour" ); + CHECK( Text( testString, TextAttributes().setWidth( 8 ) ).toString() == "one two\nthree\nfour" ); + CHECK( Text( testString, TextAttributes().setWidth( 7 ) ).toString() == "one two\nthree\nfour" ); + } + SECTION( "Wrapped three times", "" ) { + CHECK( Text( testString, TextAttributes().setWidth( 6 ) ).toString() == "one\ntwo\nthree\nfour" ); + CHECK( Text( testString, TextAttributes().setWidth( 5 ) ).toString() == "one\ntwo\nthree\nfour" ); + } + SECTION( "Short wrap", "" ) { + CHECK( Text( "abcdef", TextAttributes().setWidth( 4 ) ).toString() == "abc-\ndef" ); + CHECK( Text( "abcdefg", TextAttributes().setWidth( 4 ) ).toString() == "abc-\ndefg" ); + CHECK( Text( "abcdefgh", TextAttributes().setWidth( 4 ) ).toString() == "abc-\ndef-\ngh" ); + + CHECK( Text( testString, TextAttributes().setWidth( 4 ) ).toString() == "one\ntwo\nthr-\nee\nfour" ); + CHECK( Text( testString, TextAttributes().setWidth( 3 ) ).toString() == "one\ntwo\nth-\nree\nfo-\nur" ); + } + SECTION( "As container", "" ) { + Text text( testString, TextAttributes().setWidth( 6 ) ); + REQUIRE( text.size() == 4 ); + CHECK( text[0] == "one" ); + CHECK( text[1] == "two" ); + CHECK( text[2] == "three" ); + CHECK( text[3] == "four" ); + } + SECTION( "Indent first line differently", "" ) { + Text text( testString, TextAttributes() + .setWidth( 10 ) + .setIndent( 4 ) + .setInitialIndent( 1 ) ); + CHECK( text.toString() == " one two\n three\n four" ); + } + + } + + SECTION( "With newlines", "" ) { + + // guide: 1234567890123456789 + std::string testString = "one two\nthree four"; + + SECTION( "No wrapping" , "" ) { + CHECK( Text( testString, TextAttributes().setWidth( 80 ) ).toString() == testString ); + CHECK( Text( testString, TextAttributes().setWidth( 18 ) ).toString() == testString ); + CHECK( Text( testString, TextAttributes().setWidth( 10 ) ).toString() == testString ); + } + SECTION( "Trailing newline" , "" ) { + CHECK( Text( "abcdef\n", TextAttributes().setWidth( 10 ) ).toString() == "abcdef\n" ); + CHECK( Text( "abcdef", TextAttributes().setWidth( 6 ) ).toString() == "abcdef" ); + CHECK( Text( "abcdef\n", TextAttributes().setWidth( 6 ) ).toString() == "abcdef\n" ); + } + SECTION( "Wrapped once", "" ) { + CHECK( Text( testString, TextAttributes().setWidth( 9 ) ).toString() == "one two\nthree\nfour" ); + CHECK( Text( testString, TextAttributes().setWidth( 8 ) ).toString() == "one two\nthree\nfour" ); + CHECK( Text( testString, TextAttributes().setWidth( 7 ) ).toString() == "one two\nthree\nfour" ); + } + SECTION( "Wrapped twice", "" ) { + CHECK( Text( testString, TextAttributes().setWidth( 6 ) ).toString() == "one\ntwo\nthree\nfour" ); + } + } + + SECTION( "With tabs", "" ) { + + // guide: 1234567890123456789 + std::string testString = "one two \tthree four five six"; + + CHECK( Text( testString, TextAttributes().setWidth( 15 ) ).toString() + == "one two three\n four\n five\n six" ); + } + + +} + +using namespace Catch; + +class ColourString { +public: + + struct ColourIndex { + ColourIndex( Colour::Code _colour, std::size_t _fromIndex, std::size_t _toIndex ) + : colour( _colour ), + fromIndex( _fromIndex ), + toIndex( _toIndex ) + {} + + Colour::Code colour; + std::size_t fromIndex; + std::size_t toIndex; + }; + + ColourString( std::string const& _string ) + : string( _string ) + {} + ColourString( std::string const& _string, std::vector<ColourIndex> const& _colours ) + : string( _string ), colours( _colours ) + {} + + ColourString& addColour( Colour::Code colour, int _index ) { + colours.push_back( ColourIndex( colour, + resolveRelativeIndex( _index ), + resolveRelativeIndex( _index )+1 ) ); + return *this; + } + ColourString& addColour( Colour::Code colour, int _fromIndex, int _toIndex ) { + colours.push_back( ColourIndex( colour, + resolveRelativeIndex(_fromIndex), + resolveLastRelativeIndex( _toIndex ) ) ); + return *this; + } + + void writeToStream( std::ostream& _stream ) const { + std::size_t last = 0; + for( std::size_t i = 0; i < colours.size(); ++i ) { + ColourIndex const& index = colours[i]; + if( index.fromIndex > last ) + _stream << string.substr( last, index.fromIndex-last ); + { + Colour colourGuard( index.colour ); + _stream << string.substr( index.fromIndex, index.toIndex-index.fromIndex ); + } + last = index.toIndex; + } + if( last < string.size() ) + _stream << string.substr( last ); + } + friend std::ostream& operator << ( std::ostream& _stream, ColourString const& _colourString ) { + _colourString.writeToStream( _stream ); + return _stream; + } + +private: + + std::size_t resolveLastRelativeIndex( int _index ) { + std::size_t index = resolveRelativeIndex( _index ); + return index == 0 ? string.size() : index; + } + std::size_t resolveRelativeIndex( int _index ) { + return static_cast<std::size_t>( _index >= 0 + ? _index + : static_cast<int>( string.size() )+_index ); + } + std::string string; + std::vector<ColourIndex> colours; +}; + +TEST_CASE( "replaceInPlace", "" ) { + std::string letters = "abcdefcg"; + SECTION( "replace single char" ) { + CHECK( replaceInPlace( letters, "b", "z" ) ); + CHECK( letters == "azcdefcg" ); + } + SECTION( "replace two chars" ) { + CHECK( replaceInPlace( letters, "c", "z" ) ); + CHECK( letters == "abzdefzg" ); + } + SECTION( "replace first char" ) { + CHECK( replaceInPlace( letters, "a", "z" ) ); + CHECK( letters == "zbcdefcg" ); + } + SECTION( "replace last char" ) { + CHECK( replaceInPlace( letters, "g", "z" ) ); + CHECK( letters == "abcdefcz" ); + } + SECTION( "replace all chars" ) { + CHECK( replaceInPlace( letters, letters, "replaced" ) ); + CHECK( letters == "replaced" ); + } + SECTION( "replace no chars" ) { + CHECK_FALSE( replaceInPlace( letters, "x", "z" ) ); + CHECK( letters == letters ); + } + SECTION( "escape '" ) { + std::string s = "didn't"; + CHECK( replaceInPlace( s, "'", "|'" ) ); + CHECK( s == "didn|'t" ); + } +} + +// !TBD: This will be folded into Text class +TEST_CASE( "Strings can be rendered with colour", "[.colour]" ) { + + { + ColourString cs( "hello" ); + cs .addColour( Colour::Red, 0 ) + .addColour( Colour::Green, -1 ); + + Catch::cout() << cs << std::endl; + } + + { + ColourString cs( "hello" ); + cs .addColour( Colour::Blue, 1, -2 ); + + Catch::cout() << cs << std::endl; + } + +} + +TEST_CASE( "Text can be formatted using the Text class", "" ) { + + CHECK( Text( "hi there" ).toString() == "hi there" ); + + TextAttributes narrow; + narrow.setWidth( 6 ); + + CHECK( Text( "hi there", narrow ).toString() == "hi\nthere" ); +} + +TEST_CASE( "Long text is truncted", "[Text][Truncated]" ) { + + std::string longLine( 90, '*' ); + + std::ostringstream oss; + for(int i = 0; i < 600; ++i ) + oss << longLine << longLine << "\n"; + Text t( oss.str() ); + CHECK_THAT( t.toString(), EndsWith( "... message truncated due to excessive size" ) ); + +} + +inline void manuallyRegisteredTestFunction() { + SUCCEED( "was called" ); +} +struct AutoTestReg { + AutoTestReg() { + REGISTER_TEST_CASE( manuallyRegisteredTestFunction, "ManuallyRegistered", "" ); + } +}; +AutoTestReg autoTestReg; diff --git a/unittest/Catch/projects/SelfTest/ToStringPair.cpp b/unittest/Catch/projects/SelfTest/ToStringPair.cpp new file mode 100644 index 0000000..8f51070 --- /dev/null +++ b/unittest/Catch/projects/SelfTest/ToStringPair.cpp @@ -0,0 +1,47 @@ +#include "catch.hpp" + +// === Pair === +namespace Catch { + // Note: If we put this in the right place in catch_tostring, then + // we can make it an overload of Catch::toString + template<typename T1, typename T2> + struct StringMaker<std::pair<T1,T2> > { + static std::string convert( const std::pair<T1,T2>& pair ) { + std::ostringstream oss; + oss << "{ " + << toString( pair.first ) + << ", " + << toString( pair.second ) + << " }"; + return oss.str(); + } + }; +} + +TEST_CASE( "std::pair<int,std::string> -> toString", "[toString][pair]" ) { + std::pair<int,std::string> value( 34, "xyzzy" ); + REQUIRE( Catch::toString( value ) == "{ 34, \"xyzzy\" }" ); +} + +TEST_CASE( "std::pair<int,const std::string> -> toString", "[toString][pair]" ) { + std::pair<int,const std::string> value( 34, "xyzzy" ); + REQUIRE( Catch::toString(value) == "{ 34, \"xyzzy\" }" ); +} + +TEST_CASE( "std::vector<std::pair<std::string,int> > -> toString", "[toString][pair]" ) { + std::vector<std::pair<std::string,int> > pr; + pr.push_back( std::make_pair("green", 55 ) ); + REQUIRE( Catch::toString( pr ) == "{ { \"green\", 55 } }" ); +} + +// This is pretty contrived - I figure if this works, anything will... +TEST_CASE( "pair<pair<int,const char *,pair<std::string,int> > -> toString", "[toString][pair]" ) { + typedef std::pair<int,const char *> left_t; + typedef std::pair<std::string,int> right_t; + + left_t left( 42, "Arthur" ); + right_t right( "Ford", 24 ); + + std::pair<left_t,right_t> pair( left, right ); + REQUIRE( Catch::toString( pair ) == "{ { 42, \"Arthur\" }, { \"Ford\", 24 } }" ); +} diff --git a/unittest/Catch/projects/SelfTest/ToStringTuple.cpp b/unittest/Catch/projects/SelfTest/ToStringTuple.cpp new file mode 100644 index 0000000..80e5453 --- /dev/null +++ b/unittest/Catch/projects/SelfTest/ToStringTuple.cpp @@ -0,0 +1,59 @@ +#include "catch.hpp" + +#ifdef CATCH_CPP11_OR_GREATER + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wc++98-compat" +#endif + +TEST_CASE( "tuple<>", "[toString][tuple]" ) +{ + typedef std::tuple<> type; + CHECK( "{ }" == Catch::toString(type{}) ); + type value {}; + CHECK( "{ }" == Catch::toString(value) ); +} + +TEST_CASE( "tuple<int>", "[toString][tuple]" ) +{ + typedef std::tuple<int> type; + CHECK( "{ 0 }" == Catch::toString(type{0}) ); +} + + +TEST_CASE( "tuple<float,int>", "[toString][tuple]" ) +{ + typedef std::tuple<float,int> type; + CHECK( "1.2f" == Catch::toString(float(1.2)) ); + CHECK( "{ 1.2f, 0 }" == Catch::toString(type{1.2,0}) ); +} + +TEST_CASE( "tuple<string,string>", "[toString][tuple]" ) +{ + typedef std::tuple<std::string,std::string> type; + CHECK( "{ \"hello\", \"world\" }" == Catch::toString(type{"hello","world"}) ); +} + +TEST_CASE( "tuple<tuple<int>,tuple<>,float>", "[toString][tuple]" ) +{ + typedef std::tuple<std::tuple<int>,std::tuple<>,float> type; + type value { std::tuple<int>{42}, {}, 1.2f }; + CHECK( "{ { 42 }, { }, 1.2f }" == Catch::toString(value) ); +} + +#ifdef CATCH_CONFIG_CPP11_NULLPTR +TEST_CASE( "tuple<nullptr,int,const char *>", "[toString][tuple]" ) +{ + typedef std::tuple<std::nullptr_t,int,const char *> type; + type value { nullptr, 42, "Catch me" }; + CHECK( "{ nullptr, 42, \"Catch me\" }" == Catch::toString(value) ); +} +#endif + +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + +#endif /* #ifdef CATCH_CPP11_OR_GREATER */ + diff --git a/unittest/Catch/projects/SelfTest/ToStringVector.cpp b/unittest/Catch/projects/SelfTest/ToStringVector.cpp new file mode 100644 index 0000000..c3a8d4e --- /dev/null +++ b/unittest/Catch/projects/SelfTest/ToStringVector.cpp @@ -0,0 +1,77 @@ +#include "catch.hpp" +#include <vector> + + +// vedctor +TEST_CASE( "vector<int> -> toString", "[toString][vector]" ) +{ + std::vector<int> vv; + REQUIRE( Catch::toString(vv) == "{ }" ); + vv.push_back( 42 ); + REQUIRE( Catch::toString(vv) == "{ 42 }" ); + vv.push_back( 250 ); + REQUIRE( Catch::toString(vv) == "{ 42, 250 }" ); +} + +TEST_CASE( "vector<string> -> toString", "[toString][vector]" ) +{ + std::vector<std::string> vv; + REQUIRE( Catch::toString(vv) == "{ }" ); + vv.push_back( "hello" ); + REQUIRE( Catch::toString(vv) == "{ \"hello\" }" ); + vv.push_back( "world" ); + REQUIRE( Catch::toString(vv) == "{ \"hello\", \"world\" }" ); +} + +#if defined(CATCH_CPP11_OR_GREATER) +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wc++98-compat" +#endif + +/* + Note: These tests *can* be made to work with C++ < 11, but the + allocator is a lot more work... +*/ +namespace { + /* Minimal Allocator */ + template<typename T> + struct minimal_allocator { + typedef T value_type; + typedef std::size_t size_type; + T *allocate( size_type n ) { + return static_cast<T *>( ::operator new( n * sizeof(T) ) ); + } + void deallocate( T *p, size_type /*n*/ ) { + ::operator delete( static_cast<void *>(p) ); + } + template<typename U> + bool operator==( const minimal_allocator<U>& ) const { return true; } + template<typename U> + bool operator!=( const minimal_allocator<U>& ) const { return false; } + }; +} + +TEST_CASE( "vector<int,allocator> -> toString", "[toString][vector,allocator]" ) { + std::vector<int,minimal_allocator<int> > vv; + REQUIRE( Catch::toString(vv) == "{ }" ); + vv.push_back( 42 ); + REQUIRE( Catch::toString(vv) == "{ 42 }" ); + vv.push_back( 250 ); + REQUIRE( Catch::toString(vv) == "{ 42, 250 }" ); +} + +TEST_CASE( "vec<vec<string,alloc>> -> toString", "[toString][vector,allocator]" ) { + typedef std::vector<std::string,minimal_allocator<std::string> > inner; + typedef std::vector<inner> vector; + vector v; + REQUIRE( Catch::toString(v) == "{ }" ); + v.push_back( inner { "hello" } ); + v.push_back( inner { "world" } ); + REQUIRE( Catch::toString(v) == "{ { \"hello\" }, { \"world\" } }" ); +} + +#ifdef __clang__ +#pragma clang diagnostic pop +#endif +#endif // CATCH_CPP11_OR_GREATER diff --git a/unittest/Catch/projects/SelfTest/ToStringWhich.cpp b/unittest/Catch/projects/SelfTest/ToStringWhich.cpp new file mode 100644 index 0000000..1d4aa89 --- /dev/null +++ b/unittest/Catch/projects/SelfTest/ToStringWhich.cpp @@ -0,0 +1,68 @@ +#include "catch.hpp" +/* + Demonstrate which version of toString/StringMaker is being used + for various types +*/ + + +struct has_toString { }; +struct has_maker {}; +struct has_maker_and_toString {}; + +namespace Catch { + inline std::string toString( const has_toString& ) { + return "toString( has_toString )"; + } + inline std::string toString( const has_maker_and_toString& ) { + return "toString( has_maker_and_toString )"; + } + template<> + struct StringMaker<has_maker> { + static std::string convert( const has_maker& ) { + return "StringMaker<has_maker>"; + } + }; + template<> + struct StringMaker<has_maker_and_toString> { + static std::string convert( const has_maker_and_toString& ) { + return "StringMaker<has_maker_and_toString>"; + } + }; +} + +// Call the overload +TEST_CASE( "toString( has_toString )", "[toString]" ) { + has_toString item; + REQUIRE( Catch::toString( item ) == "toString( has_toString )" ); +} + +// Call the overload +TEST_CASE( "toString( has_maker )", "[toString]" ) { + has_maker item; + REQUIRE( Catch::toString( item ) == "StringMaker<has_maker>" ); +} + +// Call the overload +TEST_CASE( "toString( has_maker_and_toString )", "[toString]" ) { + has_maker_and_toString item; + REQUIRE( Catch::toString( item ) == "toString( has_maker_and_toString )" ); +} + +// Vectors... +TEST_CASE( "toString( vectors<has_toString )", "[toString]" ) { + std::vector<has_toString> v(1); + // This invokes template<T> toString which actually gives us '{ ? }' + REQUIRE( Catch::toString( v ) == "{ {?} }" ); +} + +TEST_CASE( "toString( vectors<has_maker )", "[toString]" ) { + std::vector<has_maker> v(1); + REQUIRE( Catch::toString( v ) == "{ StringMaker<has_maker> }" ); +} + + +TEST_CASE( "toString( vectors<has_maker_and_toString )", "[toString]" ) { + std::vector<has_maker_and_toString> v(1); + // Note: This invokes the template<T> toString -> StringMaker + REQUIRE( Catch::toString( v ) == "{ StringMaker<has_maker_and_toString> }" ); +} diff --git a/unittest/Catch/projects/SelfTest/TrickyTests.cpp b/unittest/Catch/projects/SelfTest/TrickyTests.cpp new file mode 100644 index 0000000..eb53e42 --- /dev/null +++ b/unittest/Catch/projects/SelfTest/TrickyTests.cpp @@ -0,0 +1,401 @@ +/* + * Created by Phil on 09/11/2010. + * Copyright 2010 Two Blue Cubes Ltd. All rights reserved. + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + */ + +#ifdef __clang__ +#pragma clang diagnostic ignored "-Wpadded" +#endif + +#include "catch.hpp" + +#ifdef __clang__ +#pragma clang diagnostic ignored "-Wc++98-compat" +#pragma clang diagnostic ignored "-Wc++98-compat-pedantic" +#endif + +namespace Catch +{ + template<> + std::string toString<std::pair<int, int> >( const std::pair<int, int>& value ) + { + std::ostringstream oss; + oss << "std::pair( " << value.first << ", " << value.second << " )"; + return oss.str(); + + } +} + +/////////////////////////////////////////////////////////////////////////////// +TEST_CASE +( + "Parsing a std::pair", + "[Tricky][std::pair]" +) +{ + std::pair<int, int> aNicePair( 1, 2 ); + + REQUIRE( (std::pair<int, int>( 1, 2 )) == aNicePair ); +} + +/////////////////////////////////////////////////////////////////////////////// +TEST_CASE +( + "Where there is more to the expression after the RHS", + "[Tricky][failing][.]" +) +{ +// int a = 1, b = 2; +// REQUIRE( a == 2 || b == 2 ); + WARN( "Uncomment the code in this test to check that it gives a sensible compiler error" ); +} +/////////////////////////////////////////////////////////////////////////////// +TEST_CASE +( + "Where the LHS is not a simple value", + "[Tricky][failing][.]" +) +{ + /* + int a = 1; + int b = 2; + + // This only captures part of the expression, but issues a warning about the rest + REQUIRE( a+1 == b-1 ); + */ + WARN( "Uncomment the code in this test to check that it gives a sensible compiler error" ); +} + +struct Opaque +{ + int val; + bool operator ==( const Opaque& o ) const + { + return val == o.val; + } +}; + +/////////////////////////////////////////////////////////////////////////////// +TEST_CASE +( + "A failing expression with a non streamable type is still captured", + "[Tricky][failing][.]" +) +{ + + Opaque o1, o2; + o1.val = 7; + o2.val = 8; + + CHECK( &o1 == &o2 ); + CHECK( o1 == o2 ); +} + +/////////////////////////////////////////////////////////////////////////////// +TEST_CASE +( + "string literals of different sizes can be compared", + "[Tricky][failing][.]" +) +{ + REQUIRE( std::string( "first" ) == "second" ); + +} + +/////////////////////////////////////////////////////////////////////////////// +TEST_CASE +( + "An expression with side-effects should only be evaluated once", + "[Tricky]" +) +{ + int i = 7; + + REQUIRE( i++ == 7 ); + REQUIRE( i++ == 8 ); + +} + +namespace A { + struct X + { + X() : a(4), b(2), c(7) {} + X(int v) : a(v), b(2), c(7) {} + int a; + int b; + int c; + }; +} + +namespace B { + struct Y + { + Y() : a(4), b(2), c(7) {} + Y(int v) : a(v), b(2), c(7) {} + int a; + int b; + int c; + }; +} + +inline bool operator==(const A::X& lhs, const B::Y& rhs) +{ + return (lhs.a == rhs.a); +} + +inline bool operator==(const B::Y& lhs, const A::X& rhs) +{ + return (lhs.a == rhs.a); +} + + +/////////////////////////////////////////////////////////////////////////////// +/* This, currently, does not compile with LLVM +TEST_CASE +( + "Operators at different namespace levels not hijacked by Koenig lookup" + "[Tricky]" +) +{ + A::X x; + B::Y y; + REQUIRE( x == y ); +} +*/ + +namespace ObjectWithConversions +{ + struct Object + { + operator unsigned int() {return 0xc0000000;} + }; + + /////////////////////////////////////////////////////////////////////////////// + TEST_CASE + ( + "Operators at different namespace levels not hijacked by Koenig lookup", + "[Tricky]" + ) + { + Object o; + REQUIRE(0xc0000000 == o ); + } +} + +namespace ObjectWithNonConstEqualityOperator +{ + struct Test + { + Test( unsigned int v ) + : m_value(v) + {} + + bool operator==( const Test&rhs ) + { + return (m_value == rhs.m_value); + } + bool operator==( const Test&rhs ) const + { + return (m_value != rhs.m_value); + } + unsigned int m_value; + }; + + TEST_CASE("Demonstrate that a non-const == is not used", "[Tricky]" ) + { + Test t( 1 ); + REQUIRE( t == 1u ); + } +} + +namespace EnumBitFieldTests +{ + enum Bits {bit0 = 0x0001, bit1 = 0x0002, bit2 = 0x0004, bit3 = 0x0008, bit1and2 = 0x0006, + bit30 = 0x40000000, bit31 = 0x80000000, + bit30and31 = 0xc0000000}; + + TEST_CASE( "Test enum bit values", "[Tricky]" ) + { + REQUIRE( 0xc0000000 == bit30and31 ); + } +} + +struct Obj +{ + Obj():prop(&p){} + + int p; + int* prop; +}; + +TEST_CASE("boolean member", "[Tricky]") +{ + Obj obj; + REQUIRE( obj.prop != CATCH_NULL ); +} + +// Tests for a problem submitted by Ralph McArdell +// +// The static bool value should not need to be defined outside the +// struct it is declared in - but when evaluating it in a deduced +// context it appears to require the extra definition. +// The issue was fixed by adding bool overloads to bypass the +// templates that were there to deduce it. +template <bool B> +struct is_true +{ + static const bool value = B; +}; + +TEST_CASE( "(unimplemented) static bools can be evaluated", "[Tricky]" ) +{ + SECTION("compare to true","") + { + REQUIRE( is_true<true>::value == true ); + REQUIRE( true == is_true<true>::value ); + } + SECTION("compare to false","") + { + REQUIRE( is_true<false>::value == false ); + REQUIRE( false == is_true<false>::value ); + } + + SECTION("negation", "") + { + REQUIRE( !is_true<false>::value ); + } + + SECTION("double negation","") + { + REQUIRE( !!is_true<true>::value ); + } + + SECTION("direct","") + { + REQUIRE( is_true<true>::value ); + REQUIRE_FALSE( is_true<false>::value ); + } +} + +// Uncomment these tests to produce an error at test registration time +/* +TEST_CASE( "Tests with the same name are not allowed", "[Tricky]" ) +{ + +} +TEST_CASE( "Tests with the same name are not allowed", "[Tricky]" ) +{ + +} +*/ + +struct Boolable +{ + explicit Boolable( bool value ) : m_value( value ) {} + + operator Catch::SafeBool::type() const { + return Catch::SafeBool::makeSafe( m_value ); + } + + bool m_value; +}; + +TEST_CASE( "Objects that evaluated in boolean contexts can be checked", "[Tricky][SafeBool]" ) +{ + Boolable True( true ); + Boolable False( false ); + + CHECK( True ); + CHECK( !False ); + CHECK_FALSE( False ); +} + +TEST_CASE( "Assertions then sections", "[Tricky]" ) +{ + // This was causing a failure due to the way the console reporter was handling + // the current section + + REQUIRE( Catch::alwaysTrue() ); + + SECTION( "A section", "" ) + { + REQUIRE( Catch::alwaysTrue() ); + + SECTION( "Another section", "" ) + { + REQUIRE( Catch::alwaysTrue() ); + } + SECTION( "Another other section", "" ) + { + REQUIRE( Catch::alwaysTrue() ); + } + } +} + +struct Awkward +{ + operator int() const { return 7; } +}; + +TEST_CASE( "non streamable - with conv. op", "[Tricky]" ) +{ + Awkward awkward; + std::string s = Catch::toString( awkward ); + REQUIRE( s == "7" ); +} + +inline void foo() {} + +typedef void (*fooptr_t)(); + +TEST_CASE( "Comparing function pointers", "[Tricky][function pointer]" ) +{ + // This was giving a warning in VS2010 + // #179 + fooptr_t a = foo; + + REQUIRE( a ); + REQUIRE( a == &foo ); +} + +struct S +{ + void f() {} +}; + + +TEST_CASE( "Comparing member function pointers", "[Tricky][member function pointer]" ) +{ + typedef void (S::*MF)(); + MF m = &S::f; + + CHECK( m == &S::f ); +} + +class ClassName {}; + +TEST_CASE( "pointer to class", "[Tricky]" ) +{ + ClassName *p = 0; + REQUIRE( p == 0 ); +} + +#ifdef CATCH_CONFIG_CPP11_NULLPTR + +#include <memory> + +TEST_CASE( "null_ptr", "[Tricky][c++11]" ) +{ + std::unique_ptr<int> ptr; + REQUIRE(ptr.get() == nullptr); +} + +#endif + +TEST_CASE( "X/level/0/a", "[Tricky]" ) { SUCCEED(""); } +TEST_CASE( "X/level/0/b", "[Tricky][fizz]" ){ SUCCEED(""); } +TEST_CASE( "X/level/1/a", "[Tricky]" ) { SUCCEED(""); } +TEST_CASE( "X/level/1/b", "[Tricky]" ) { SUCCEED(""); } diff --git a/unittest/Catch/projects/SelfTest/VariadicMacrosTests.cpp b/unittest/Catch/projects/SelfTest/VariadicMacrosTests.cpp new file mode 100644 index 0000000..b784076 --- /dev/null +++ b/unittest/Catch/projects/SelfTest/VariadicMacrosTests.cpp @@ -0,0 +1,31 @@ +/* + * Created by Phil on 15/03/2013. + * Copyright 2013 Two Blue Cubes Ltd. All rights reserved. + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + */ + +#include "catch.hpp" + +#ifdef CATCH_CONFIG_VARIADIC_MACROS + +TEST_CASE() +{ + SUCCEED( "anonymous test case" ); +} + +TEST_CASE( "Test case with one argument" ) +{ + SUCCEED( "no assertions" ); +} + +TEST_CASE( "Variadic macros", "[variadic][sections]" ) +{ + SECTION( "Section with one argument" ) + { + SUCCEED( "no assertions" ); + } +} + +#endif diff --git a/unittest/Catch/projects/SelfTest/makefile b/unittest/Catch/projects/SelfTest/makefile new file mode 100644 index 0000000..0a29372 --- /dev/null +++ b/unittest/Catch/projects/SelfTest/makefile @@ -0,0 +1,30 @@ +SOURCES = ApproxTests.cpp \ + ClassTests.cpp \ + ConditionTests.cpp \ + ExceptionTests.cpp \ + GeneratorTests.cpp \ + MessageTests.cpp \ + MiscTests.cpp \ + TestMain.cpp \ + TrickyTests.cpp \ + BDDTests.cpp \ + VariadicMacrosTests.cpp \ + EnumToString.cpp \ + ToStringPair.cpp \ + ToStringVector.cpp \ + ToStringWhich.cpp + + +OBJECTS = $(patsubst %.cpp, %.o, $(SOURCES)) +CXX = g++ +CXXFLAGS = -I../../include -std=c++11 + +CatchSelfTest: $(OBJECTS) + $(CXX) -o $@ $^ + +test: CatchSelfTest + ./CatchSelfTest + +clean: + rm -f $(OBJECTS) CatchSelfTest + diff --git a/unittest/Catch/projects/VS2008/TestCatch/TestCatch.sln b/unittest/Catch/projects/VS2008/TestCatch/TestCatch.sln new file mode 100644 index 0000000..bd85bbe --- /dev/null +++ b/unittest/Catch/projects/VS2008/TestCatch/TestCatch.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 10.00 +# Visual Studio 2008 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TestCatch", "TestCatch\TestCatch.vcproj", "{A2F23B19-9CF7-4246-AE58-BC65E39C6F7E}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {A2F23B19-9CF7-4246-AE58-BC65E39C6F7E}.Debug|Win32.ActiveCfg = Debug|Win32 + {A2F23B19-9CF7-4246-AE58-BC65E39C6F7E}.Debug|Win32.Build.0 = Debug|Win32 + {A2F23B19-9CF7-4246-AE58-BC65E39C6F7E}.Release|Win32.ActiveCfg = Release|Win32 + {A2F23B19-9CF7-4246-AE58-BC65E39C6F7E}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/unittest/Catch/projects/VS2008/TestCatch/TestCatch/TestCatch.cpp b/unittest/Catch/projects/VS2008/TestCatch/TestCatch/TestCatch.cpp new file mode 100644 index 0000000..8dd2067 --- /dev/null +++ b/unittest/Catch/projects/VS2008/TestCatch/TestCatch/TestCatch.cpp @@ -0,0 +1,8 @@ +// TestCatch.cpp : Defines the entry point for the console application. +// + +int main(int argc, char* argv[]) +{ + return 0; +} + diff --git a/unittest/Catch/projects/VS2008/TestCatch/TestCatch/TestCatch.vcproj b/unittest/Catch/projects/VS2008/TestCatch/TestCatch/TestCatch.vcproj new file mode 100644 index 0000000..d4cb0c9 --- /dev/null +++ b/unittest/Catch/projects/VS2008/TestCatch/TestCatch/TestCatch.vcproj @@ -0,0 +1,390 @@ +<?xml version="1.0" encoding="Windows-1252"?> +<VisualStudioProject + ProjectType="Visual C++" + Version="9.00" + Name="TestCatch" + ProjectGUID="{A2F23B19-9CF7-4246-AE58-BC65E39C6F7E}" + RootNamespace="TestCatch" + Keyword="Win32Proj" + TargetFrameworkVersion="196613" + > + <Platforms> + <Platform + Name="Win32" + /> + </Platforms> + <ToolFiles> + </ToolFiles> + <Configurations> + <Configuration + Name="Debug|Win32" + OutputDirectory="$(SolutionDir)$(ConfigurationName)" + IntermediateDirectory="$(ConfigurationName)" + ConfigurationType="1" + CharacterSet="1" + > + <Tool + Name="VCPreBuildEventTool" + /> + <Tool + Name="VCCustomBuildTool" + /> + <Tool + Name="VCXMLDataGeneratorTool" + /> + <Tool + Name="VCWebServiceProxyGeneratorTool" + /> + <Tool + Name="VCMIDLTool" + /> + <Tool + Name="VCCLCompilerTool" + Optimization="0" + AdditionalIncludeDirectories="..\..\..\..\include" + PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE" + MinimalRebuild="true" + BasicRuntimeChecks="3" + RuntimeLibrary="3" + UsePrecompiledHeader="0" + WarningLevel="4" + DebugInformationFormat="4" + /> + <Tool + Name="VCManagedResourceCompilerTool" + /> + <Tool + Name="VCResourceCompilerTool" + /> + <Tool + Name="VCPreLinkEventTool" + /> + <Tool + Name="VCLinkerTool" + LinkIncremental="2" + GenerateDebugInformation="true" + SubSystem="1" + TargetMachine="1" + /> + <Tool + Name="VCALinkTool" + /> + <Tool + Name="VCManifestTool" + /> + <Tool + Name="VCXDCMakeTool" + /> + <Tool + Name="VCBscMakeTool" + /> + <Tool + Name="VCFxCopTool" + /> + <Tool + Name="VCAppVerifierTool" + /> + <Tool + Name="VCPostBuildEventTool" + /> + </Configuration> + <Configuration + Name="Release|Win32" + OutputDirectory="$(SolutionDir)$(ConfigurationName)" + IntermediateDirectory="$(ConfigurationName)" + ConfigurationType="1" + CharacterSet="1" + WholeProgramOptimization="1" + > + <Tool + Name="VCPreBuildEventTool" + /> + <Tool + Name="VCCustomBuildTool" + /> + <Tool + Name="VCXMLDataGeneratorTool" + /> + <Tool + Name="VCWebServiceProxyGeneratorTool" + /> + <Tool + Name="VCMIDLTool" + /> + <Tool + Name="VCCLCompilerTool" + Optimization="2" + EnableIntrinsicFunctions="true" + PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE" + RuntimeLibrary="2" + EnableFunctionLevelLinking="true" + UsePrecompiledHeader="0" + WarningLevel="3" + DebugInformationFormat="3" + /> + <Tool + Name="VCManagedResourceCompilerTool" + /> + <Tool + Name="VCResourceCompilerTool" + /> + <Tool + Name="VCPreLinkEventTool" + /> + <Tool + Name="VCLinkerTool" + LinkIncremental="1" + GenerateDebugInformation="true" + SubSystem="1" + OptimizeReferences="2" + EnableCOMDATFolding="2" + TargetMachine="1" + /> + <Tool + Name="VCALinkTool" + /> + <Tool + Name="VCManifestTool" + /> + <Tool + Name="VCXDCMakeTool" + /> + <Tool + Name="VCBscMakeTool" + /> + <Tool + Name="VCFxCopTool" + /> + <Tool + Name="VCAppVerifierTool" + /> + <Tool + Name="VCPostBuildEventTool" + /> + </Configuration> + </Configurations> + <References> + </References> + <Files> + <Filter + Name="Source Files" + Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx" + UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}" + > + <File + RelativePath="..\..\..\SelfTest\TestMain.cpp" + > + </File> + </Filter> + <Filter + Name="Include" + Filter="h;hpp;hxx;hm;inl;inc;xsd" + UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}" + > + <File + RelativePath="..\..\..\..\include\catch.hpp" + > + </File> + <File + RelativePath="..\..\..\..\include\catch_objc.hpp" + > + </File> + <File + RelativePath="..\..\..\..\include\catch_objc_main.hpp" + > + </File> + <File + RelativePath="..\..\..\..\include\catch_runner.hpp" + > + </File> + <File + RelativePath="..\..\..\..\include\catch_with_main.hpp" + > + </File> + <Filter + Name="Internal" + > + <File + RelativePath="..\..\..\..\include\internal\catch_capture.hpp" + > + </File> + <File + RelativePath="..\..\..\..\include\internal\catch_commandline.hpp" + > + </File> + <File + RelativePath="..\..\..\..\include\internal\catch_common.h" + > + </File> + <File + RelativePath="..\..\..\..\include\internal\catch_config.hpp" + > + </File> + <File + RelativePath="..\..\..\..\include\internal\catch_debugger.hpp" + > + </File> + <File + RelativePath="..\..\..\..\include\internal\catch_evaluate.hpp" + > + </File> + <File + RelativePath="..\..\..\..\include\internal\catch_exception_translator_registry.hpp" + > + </File> + <File + RelativePath="..\..\..\..\include\internal\catch_generators.hpp" + > + </File> + <File + RelativePath="..\..\..\..\include\internal\catch_generators_impl.hpp" + > + </File> + <File + RelativePath="..\..\..\..\include\internal\catch_hub.h" + > + </File> + <File + RelativePath="..\..\..\..\include\internal\catch_hub_impl.hpp" + > + </File> + <File + RelativePath="..\..\..\..\include\internal\catch_interfaces_capture.h" + > + </File> + <File + RelativePath="..\..\..\..\include\internal\catch_interfaces_exception.h" + > + </File> + <File + RelativePath="..\..\..\..\include\internal\catch_interfaces_reporter.h" + > + </File> + <File + RelativePath="..\..\..\..\include\internal\catch_interfaces_runner.h" + > + </File> + <File + RelativePath="..\..\..\..\include\internal\catch_interfaces_testcase.h" + > + </File> + <File + RelativePath="..\..\..\..\include\internal\catch_list.hpp" + > + </File> + <File + RelativePath="..\..\..\..\include\internal\catch_reporter_registrars.hpp" + > + </File> + <File + RelativePath="..\..\..\..\include\internal\catch_reporter_registry.hpp" + > + </File> + <File + RelativePath="..\..\..\..\include\internal\catch_result_type.h" + > + </File> + <File + RelativePath="..\..\..\..\include\internal\catch_resultinfo.hpp" + > + </File> + <File + RelativePath="..\..\..\..\include\internal\catch_runner_impl.hpp" + > + </File> + <File + RelativePath="..\..\..\..\include\internal\catch_section.hpp" + > + </File> + <File + RelativePath="..\..\..\..\include\internal\catch_stream.hpp" + > + </File> + <File + RelativePath="..\..\..\..\include\internal\catch_test_case_info.hpp" + > + </File> + <File + RelativePath="..\..\..\..\include\internal\catch_test_case_registry_impl.hpp" + > + </File> + <File + RelativePath="..\..\..\..\include\internal\catch_test_registry.hpp" + > + </File> + <File + RelativePath="..\..\..\..\include\internal\catch_xmlwriter.hpp" + > + </File> + </Filter> + <Filter + Name="Reporters" + Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav" + UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}" + > + <File + RelativePath="..\..\..\..\include\reporters\catch_reporter_basic.hpp" + > + </File> + <File + RelativePath="..\..\..\..\include\reporters\catch_reporter_junit.hpp" + > + </File> + <File + RelativePath="..\..\..\..\include\reporters\catch_reporter_xml.hpp" + > + </File> + </Filter> + </Filter> + <Filter + Name="TestCases" + > + <File + RelativePath="..\..\..\SelfTest\ApproxTests.cpp" + > + </File> + <File + RelativePath="..\..\..\SelfTest\BDDTests.cpp" + > + </File> + <File + RelativePath="..\..\..\SelfTest\ClassTests.cpp" + > + </File> + <File + RelativePath="..\..\..\SelfTest\ConditionTests.cpp" + > + </File> + <File + RelativePath="..\..\..\SelfTest\ExceptionTests.cpp" + > + </File> + <File + RelativePath="..\..\..\SelfTest\GeneratorTests.cpp" + > + </File> + <File + RelativePath="..\..\..\SelfTest\MessageTests.cpp" + > + </File> + <File + RelativePath="..\..\..\SelfTest\MiscTests.cpp" + > + </File> + <File + RelativePath="..\..\..\SelfTest\SectionTrackerTests.cpp" + > + </File> + <File + RelativePath="..\..\..\SelfTest\TrickyTests.cpp" + > + </File> + <File + RelativePath="..\..\..\SelfTest\VariadicMacrosTests.cpp" + > + </File> + </Filter> + </Files> + <Globals> + </Globals> +</VisualStudioProject> diff --git a/unittest/Catch/projects/VS2010/TestCatch/TestCatch.sln b/unittest/Catch/projects/VS2010/TestCatch/TestCatch.sln new file mode 100644 index 0000000..efb4502 --- /dev/null +++ b/unittest/Catch/projects/VS2010/TestCatch/TestCatch.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 11.00 +# Visual Studio 2010 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TestCatch", "TestCatch\TestCatch.vcxproj", "{A2F23B19-9CF7-4246-AE58-BC65E39C6F7E}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {A2F23B19-9CF7-4246-AE58-BC65E39C6F7E}.Debug|Win32.ActiveCfg = Debug|Win32 + {A2F23B19-9CF7-4246-AE58-BC65E39C6F7E}.Debug|Win32.Build.0 = Debug|Win32 + {A2F23B19-9CF7-4246-AE58-BC65E39C6F7E}.Release|Win32.ActiveCfg = Release|Win32 + {A2F23B19-9CF7-4246-AE58-BC65E39C6F7E}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/unittest/Catch/projects/VS2010/TestCatch/TestCatch/TestCatch.vcxproj b/unittest/Catch/projects/VS2010/TestCatch/TestCatch/TestCatch.vcxproj new file mode 100644 index 0000000..52bcea1 --- /dev/null +++ b/unittest/Catch/projects/VS2010/TestCatch/TestCatch/TestCatch.vcxproj @@ -0,0 +1,148 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup Label="ProjectConfigurations"> + <ProjectConfiguration Include="Debug|Win32"> + <Configuration>Debug</Configuration> + <Platform>Win32</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|Win32"> + <Configuration>Release</Configuration> + <Platform>Win32</Platform> + </ProjectConfiguration> + </ItemGroup> + <PropertyGroup Label="Globals"> + <ProjectGuid>{A2F23B19-9CF7-4246-AE58-BC65E39C6F7E}</ProjectGuid> + <RootNamespace>TestCatch</RootNamespace> + <Keyword>Win32Proj</Keyword> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration"> + <ConfigurationType>Application</ConfigurationType> + <CharacterSet>Unicode</CharacterSet> + <WholeProgramOptimization>true</WholeProgramOptimization> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration"> + <ConfigurationType>Application</ConfigurationType> + <CharacterSet>Unicode</CharacterSet> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> + <ImportGroup Label="ExtensionSettings"> + </ImportGroup> + <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <PropertyGroup Label="UserMacros" /> + <PropertyGroup> + <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion> + <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)$(Configuration)\</OutDir> + <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(Configuration)\</IntDir> + <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</LinkIncremental> + <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)$(Configuration)\</OutDir> + <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(Configuration)\</IntDir> + <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkIncremental> + <CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">AllRules.ruleset</CodeAnalysisRuleSet> + <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" /> + <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" /> + <CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">AllRules.ruleset</CodeAnalysisRuleSet> + <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" /> + <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" /> + </PropertyGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <ClCompile> + <Optimization>Disabled</Optimization> + <AdditionalIncludeDirectories>..\..\..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <MinimalRebuild>true</MinimalRebuild> + <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks> + <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary> + <PrecompiledHeader> + </PrecompiledHeader> + <WarningLevel>Level4</WarningLevel> + <DebugInformationFormat>EditAndContinue</DebugInformationFormat> + </ClCompile> + <Link> + <GenerateDebugInformation>true</GenerateDebugInformation> + <SubSystem>Console</SubSystem> + <TargetMachine>MachineX86</TargetMachine> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <ClCompile> + <Optimization>MaxSpeed</Optimization> + <IntrinsicFunctions>true</IntrinsicFunctions> + <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary> + <FunctionLevelLinking>true</FunctionLevelLinking> + <PrecompiledHeader> + </PrecompiledHeader> + <WarningLevel>Level3</WarningLevel> + <DebugInformationFormat>ProgramDatabase</DebugInformationFormat> + <AdditionalIncludeDirectories>..\..\..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + </ClCompile> + <Link> + <GenerateDebugInformation>true</GenerateDebugInformation> + <SubSystem>Console</SubSystem> + <OptimizeReferences>true</OptimizeReferences> + <EnableCOMDATFolding>true</EnableCOMDATFolding> + <TargetMachine>MachineX86</TargetMachine> + </Link> + </ItemDefinitionGroup> + <ItemGroup> + <ClCompile Include="..\..\..\SelfTest\ApproxTests.cpp" /> + <ClCompile Include="..\..\..\SelfTest\BDDTests.cpp" /> + <ClCompile Include="..\..\..\SelfTest\PartTrackerTests.cpp" /> + <ClCompile Include="..\..\..\SelfTest\TestMain.cpp" /> + <ClCompile Include="..\..\..\SelfTest\ClassTests.cpp" /> + <ClCompile Include="..\..\..\SelfTest\ConditionTests.cpp" /> + <ClCompile Include="..\..\..\SelfTest\ExceptionTests.cpp" /> + <ClCompile Include="..\..\..\SelfTest\GeneratorTests.cpp" /> + <ClCompile Include="..\..\..\SelfTest\MessageTests.cpp" /> + <ClCompile Include="..\..\..\SelfTest\MiscTests.cpp" /> + <ClCompile Include="..\..\..\SelfTest\TrickyTests.cpp" /> + <ClCompile Include="..\..\..\SelfTest\VariadicMacrosTests.cpp" /> + </ItemGroup> + <ItemGroup> + <ClInclude Include="..\..\..\..\include\catch.hpp" /> + <ClInclude Include="..\..\..\..\include\catch_objc.hpp" /> + <ClInclude Include="..\..\..\..\include\catch_objc_main.hpp" /> + <ClInclude Include="..\..\..\..\include\catch_runner.hpp" /> + <ClInclude Include="..\..\..\..\include\catch_with_main.hpp" /> + <ClInclude Include="..\..\..\..\include\internal\catch_capture.hpp" /> + <ClInclude Include="..\..\..\..\include\internal\catch_commandline.hpp" /> + <ClInclude Include="..\..\..\..\include\internal\catch_common.h" /> + <ClInclude Include="..\..\..\..\include\internal\catch_config.hpp" /> + <ClInclude Include="..\..\..\..\include\internal\catch_debugger.hpp" /> + <ClInclude Include="..\..\..\..\include\internal\catch_evaluate.hpp" /> + <ClInclude Include="..\..\..\..\include\internal\catch_exception_translator_registry.hpp" /> + <ClInclude Include="..\..\..\..\include\internal\catch_generators.hpp" /> + <ClInclude Include="..\..\..\..\include\internal\catch_generators_impl.hpp" /> + <ClInclude Include="..\..\..\..\include\internal\catch_hub.h" /> + <ClInclude Include="..\..\..\..\include\internal\catch_hub_impl.hpp" /> + <ClInclude Include="..\..\..\..\include\internal\catch_interfaces_capture.h" /> + <ClInclude Include="..\..\..\..\include\internal\catch_interfaces_exception.h" /> + <ClInclude Include="..\..\..\..\include\internal\catch_interfaces_reporter.h" /> + <ClInclude Include="..\..\..\..\include\internal\catch_interfaces_runner.h" /> + <ClInclude Include="..\..\..\..\include\internal\catch_interfaces_testcase.h" /> + <ClInclude Include="..\..\..\..\include\internal\catch_list.hpp" /> + <ClInclude Include="..\..\..\..\include\internal\catch_reporter_registrars.hpp" /> + <ClInclude Include="..\..\..\..\include\internal\catch_reporter_registry.hpp" /> + <ClInclude Include="..\..\..\..\include\internal\catch_result_type.h" /> + <ClInclude Include="..\..\..\..\include\internal\catch_resultinfo.hpp" /> + <ClInclude Include="..\..\..\..\include\internal\catch_runner_impl.hpp" /> + <ClInclude Include="..\..\..\..\include\internal\catch_section.hpp" /> + <ClInclude Include="..\..\..\..\include\internal\catch_stream.hpp" /> + <ClInclude Include="..\..\..\..\include\internal\catch_test_case_info.hpp" /> + <ClInclude Include="..\..\..\..\include\internal\catch_test_case_registry_impl.hpp" /> + <ClInclude Include="..\..\..\..\include\internal\catch_test_registry.hpp" /> + <ClInclude Include="..\..\..\..\include\internal\catch_xmlwriter.hpp" /> + <ClInclude Include="..\..\..\..\include\reporters\catch_reporter_basic.hpp" /> + <ClInclude Include="..\..\..\..\include\reporters\catch_reporter_junit.hpp" /> + <ClInclude Include="..\..\..\..\include\reporters\catch_reporter_xml.hpp" /> + </ItemGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> + <ImportGroup Label="ExtensionTargets"> + </ImportGroup> +</Project>
\ No newline at end of file diff --git a/unittest/Catch/projects/XCode/CatchSelfTest/CatchSelfTest.xcodeproj/project.pbxproj b/unittest/Catch/projects/XCode/CatchSelfTest/CatchSelfTest.xcodeproj/project.pbxproj new file mode 100644 index 0000000..a26df53 --- /dev/null +++ b/unittest/Catch/projects/XCode/CatchSelfTest/CatchSelfTest.xcodeproj/project.pbxproj @@ -0,0 +1,742 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 26059AF21BD4B94C003D575C /* PartTrackerTests.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26059AF11BD4B94C003D575C /* PartTrackerTests.cpp */; }; + 263F7A4719B6FCBF009474C2 /* EnumToString.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 263F7A4619B6FCBF009474C2 /* EnumToString.cpp */; }; + 263F7A4B19B6FE1E009474C2 /* ToStringPair.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 263F7A4819B6FE1E009474C2 /* ToStringPair.cpp */; }; + 263F7A4C19B6FE1E009474C2 /* ToStringVector.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 263F7A4919B6FE1E009474C2 /* ToStringVector.cpp */; }; + 263F7A4D19B6FE1E009474C2 /* ToStringWhich.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 263F7A4A19B6FE1E009474C2 /* ToStringWhich.cpp */; }; + 2656C2211925E7330040DB02 /* catch_test_spec.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2656C2201925E7330040DB02 /* catch_test_spec.cpp */; }; + 266B06B816F3A60A004ED264 /* VariadicMacrosTests.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 266B06B616F3A60A004ED264 /* VariadicMacrosTests.cpp */; }; + 266ECD74170F3C620030D735 /* BDDTests.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 266ECD73170F3C620030D735 /* BDDTests.cpp */; }; + 26711C8F195D465C0033EDA2 /* TagAliasTests.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26711C8D195D465C0033EDA2 /* TagAliasTests.cpp */; }; + 26847E5F16BBADB40043B9C1 /* catch_message.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26847E5D16BBADB40043B9C1 /* catch_message.cpp */; }; + 2691574C1A532A280054F1ED /* ToStringTuple.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2691574B1A532A280054F1ED /* ToStringTuple.cpp */; }; + 2694A1FD16A0000E004816E3 /* catch_text.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2694A1FB16A0000E004816E3 /* catch_text.cpp */; }; + 26E1B7D319213BC900812682 /* CmdLineTests.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26E1B7D119213BC900812682 /* CmdLineTests.cpp */; }; + 4A45DA2416161EF9004F8D6B /* catch_console_colour.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4A45DA2316161EF9004F8D6B /* catch_console_colour.cpp */; }; + 4A45DA2716161F1F004F8D6B /* catch_ptr.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4A45DA2616161F1F004F8D6B /* catch_ptr.cpp */; }; + 4A45DA2916161F3D004F8D6B /* catch_streambuf.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4A45DA2816161F3D004F8D6B /* catch_streambuf.cpp */; }; + 4A45DA2B16161F79004F8D6B /* catch_interfaces_registry_hub.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4A45DA2A16161F79004F8D6B /* catch_interfaces_registry_hub.cpp */; }; + 4A45DA2D16161FA2004F8D6B /* catch_interfaces_capture.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4A45DA2C16161FA2004F8D6B /* catch_interfaces_capture.cpp */; }; + 4A45DA3116161FFC004F8D6B /* catch_interfaces_reporter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4A45DA3016161FFB004F8D6B /* catch_interfaces_reporter.cpp */; }; + 4A45DA3316162047004F8D6B /* catch_interfaces_exception.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4A45DA3216162047004F8D6B /* catch_interfaces_exception.cpp */; }; + 4A45DA3516162071004F8D6B /* catch_interfaces_runner.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4A45DA3416162071004F8D6B /* catch_interfaces_runner.cpp */; }; + 4A6D0C27149B3D3B00DB3EAA /* CatchSelfTest.1 in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4A6D0C26149B3D3B00DB3EAA /* CatchSelfTest.1 */; }; + 4A6D0C37149B3D9E00DB3EAA /* ApproxTests.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4A6D0C2D149B3D9E00DB3EAA /* ApproxTests.cpp */; }; + 4A6D0C38149B3D9E00DB3EAA /* ClassTests.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4A6D0C2F149B3D9E00DB3EAA /* ClassTests.cpp */; }; + 4A6D0C39149B3D9E00DB3EAA /* ConditionTests.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4A6D0C30149B3D9E00DB3EAA /* ConditionTests.cpp */; }; + 4A6D0C3A149B3D9E00DB3EAA /* ExceptionTests.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4A6D0C31149B3D9E00DB3EAA /* ExceptionTests.cpp */; }; + 4A6D0C3B149B3D9E00DB3EAA /* GeneratorTests.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4A6D0C32149B3D9E00DB3EAA /* GeneratorTests.cpp */; }; + 4A6D0C3C149B3D9E00DB3EAA /* MessageTests.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4A6D0C33149B3D9E00DB3EAA /* MessageTests.cpp */; }; + 4A6D0C3D149B3D9E00DB3EAA /* MiscTests.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4A6D0C34149B3D9E00DB3EAA /* MiscTests.cpp */; }; + 4A6D0C3E149B3D9E00DB3EAA /* TestMain.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4A6D0C35149B3D9E00DB3EAA /* TestMain.cpp */; }; + 4A6D0C3F149B3D9E00DB3EAA /* TrickyTests.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4A6D0C36149B3D9E00DB3EAA /* TrickyTests.cpp */; }; + 4AB3D99D1616216500C9A0F8 /* catch_interfaces_testcase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4AB3D99C1616216500C9A0F8 /* catch_interfaces_testcase.cpp */; }; + 4AB3D9A01616219100C9A0F8 /* catch_interfaces_config.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4AB3D99F1616219100C9A0F8 /* catch_interfaces_config.cpp */; }; + 4AB3D9A2161621B500C9A0F8 /* catch_interfaces_generators.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4AB3D9A1161621B500C9A0F8 /* catch_interfaces_generators.cpp */; }; + 4ACE21CC166CA1B300FB5509 /* catch_option.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4ACE21CA166CA1B300FB5509 /* catch_option.cpp */; }; + 4AEE032016142F910071E950 /* catch_common.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4AEE031F16142F910071E950 /* catch_common.cpp */; }; + 4AEE032316142FC70071E950 /* catch_debugger.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4AEE032216142FC70071E950 /* catch_debugger.cpp */; }; + 4AEE032516142FF10071E950 /* catch_stream.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4AEE032416142FF10071E950 /* catch_stream.cpp */; }; + 4AEE0328161434FD0071E950 /* catch_xmlwriter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4AEE0327161434FD0071E950 /* catch_xmlwriter.cpp */; }; +/* End PBXBuildFile section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 4A6D0C1E149B3D3B00DB3EAA /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = /usr/share/man/man1/; + dstSubfolderSpec = 0; + files = ( + 4A6D0C27149B3D3B00DB3EAA /* CatchSelfTest.1 in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 1; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 26059AF11BD4B94C003D575C /* PartTrackerTests.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = PartTrackerTests.cpp; path = ../../../SelfTest/PartTrackerTests.cpp; sourceTree = "<group>"; }; + 261488FA184C81130041FBEB /* catch_test_spec.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = catch_test_spec.hpp; sourceTree = "<group>"; }; + 261488FC184D1DC10041FBEB /* catch_stream.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = catch_stream.h; sourceTree = "<group>"; }; + 261488FD184D21290041FBEB /* catch_section_info.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = catch_section_info.h; sourceTree = "<group>"; }; + 261488FE184DC32F0041FBEB /* catch_section.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = catch_section.h; sourceTree = "<group>"; }; + 261488FF184DC4A20041FBEB /* catch_debugger.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = catch_debugger.h; sourceTree = "<group>"; }; + 2627F7051935B16F009BCE2D /* catch_result_builder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = catch_result_builder.h; sourceTree = "<group>"; }; + 2627F7061935B55F009BCE2D /* catch_result_builder.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = catch_result_builder.hpp; sourceTree = "<group>"; }; + 262E7399184673A800CAC268 /* catch_reporter_bases.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = catch_reporter_bases.hpp; sourceTree = "<group>"; }; + 262E739A1846759000CAC268 /* catch_common.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = catch_common.hpp; sourceTree = "<group>"; }; + 263F7A4519A66608009474C2 /* catch_fatal_condition.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = catch_fatal_condition.hpp; sourceTree = "<group>"; }; + 263F7A4619B6FCBF009474C2 /* EnumToString.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = EnumToString.cpp; path = ../../../SelfTest/EnumToString.cpp; sourceTree = "<group>"; }; + 263F7A4819B6FE1E009474C2 /* ToStringPair.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ToStringPair.cpp; path = ../../../SelfTest/ToStringPair.cpp; sourceTree = "<group>"; }; + 263F7A4919B6FE1E009474C2 /* ToStringVector.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ToStringVector.cpp; path = ../../../SelfTest/ToStringVector.cpp; sourceTree = "<group>"; }; + 263F7A4A19B6FE1E009474C2 /* ToStringWhich.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ToStringWhich.cpp; path = ../../../SelfTest/ToStringWhich.cpp; sourceTree = "<group>"; }; + 263FD06017AF8DF200988A20 /* catch_timer.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = catch_timer.hpp; sourceTree = "<group>"; }; + 263FD06117AF8DF200988A20 /* catch_timer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = catch_timer.h; sourceTree = "<group>"; }; + 2656C21F1925E5100040DB02 /* catch_test_spec_parser.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = catch_test_spec_parser.hpp; sourceTree = "<group>"; }; + 2656C2201925E7330040DB02 /* catch_test_spec.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_test_spec.cpp; path = ../../../SelfTest/SurrogateCpps/catch_test_spec.cpp; sourceTree = "<group>"; }; + 2656C226192A77EF0040DB02 /* catch_suppress_warnings.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = catch_suppress_warnings.h; sourceTree = "<group>"; }; + 2656C227192A78410040DB02 /* catch_reenable_warnings.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = catch_reenable_warnings.h; sourceTree = "<group>"; }; + 266B06B616F3A60A004ED264 /* VariadicMacrosTests.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = VariadicMacrosTests.cpp; path = ../../../SelfTest/VariadicMacrosTests.cpp; sourceTree = "<group>"; }; + 266ECD73170F3C620030D735 /* BDDTests.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = BDDTests.cpp; path = ../../../SelfTest/BDDTests.cpp; sourceTree = "<group>"; }; + 266ECD8C1713614B0030D735 /* catch_legacy_reporter_adapter.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = catch_legacy_reporter_adapter.hpp; sourceTree = "<group>"; }; + 266ECD8D1713614B0030D735 /* catch_legacy_reporter_adapter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = catch_legacy_reporter_adapter.h; sourceTree = "<group>"; }; + 26711C8D195D465C0033EDA2 /* TagAliasTests.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = TagAliasTests.cpp; path = ../../../SelfTest/TagAliasTests.cpp; sourceTree = "<group>"; }; + 26711C90195D46CD0033EDA2 /* catch_interfaces_tag_alias_registry.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = catch_interfaces_tag_alias_registry.h; sourceTree = "<group>"; }; + 26711C91195D47820033EDA2 /* catch_tag_alias.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = catch_tag_alias.h; sourceTree = "<group>"; }; + 26711C92195D48F60033EDA2 /* catch_tag_alias_registry.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = catch_tag_alias_registry.hpp; sourceTree = "<group>"; }; + 26711C94195D4B120033EDA2 /* catch_tag_alias_registry.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = catch_tag_alias_registry.h; sourceTree = "<group>"; }; + 26759473171C74C200A84BD1 /* catch_compiler_capabilities.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = catch_compiler_capabilities.h; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; }; + 26847E5B16BBAB790043B9C1 /* catch_message.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = catch_message.h; sourceTree = "<group>"; }; + 26847E5C16BBACB60043B9C1 /* catch_message.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = catch_message.hpp; sourceTree = "<group>"; }; + 26847E5D16BBADB40043B9C1 /* catch_message.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_message.cpp; path = ../../../SelfTest/SurrogateCpps/catch_message.cpp; sourceTree = "<group>"; }; + 268F47B018A93F7800D8C14F /* catch_clara.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = catch_clara.h; sourceTree = "<group>"; }; + 2691574A1A4480C50054F1ED /* catch_reporter_teamcity.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = catch_reporter_teamcity.hpp; sourceTree = "<group>"; }; + 2691574B1A532A280054F1ED /* ToStringTuple.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ToStringTuple.cpp; path = ../../../SelfTest/ToStringTuple.cpp; sourceTree = "<group>"; }; + 26926E8318D7777D004E10F2 /* clara.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = clara.h; path = ../../../../include/external/clara.h; sourceTree = "<group>"; }; + 26926E8418D77809004E10F2 /* tbc_text_format.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = tbc_text_format.h; path = ../../../../include/external/tbc_text_format.h; sourceTree = "<group>"; }; + 26948287179EF7F900ED166E /* catch_test_case_tracker.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = catch_test_case_tracker.hpp; sourceTree = "<group>"; }; + 2694A1FB16A0000E004816E3 /* catch_text.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = catch_text.cpp; sourceTree = "<group>"; }; + 269831E519078C1600BB0CE0 /* catch_tostring.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = catch_tostring.h; sourceTree = "<group>"; }; + 269831E619078CA200BB0CE0 /* catch_tostring.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = catch_tostring.hpp; sourceTree = "<group>"; }; + 269831E719121CA500BB0CE0 /* catch_reporter_compact.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = catch_reporter_compact.hpp; sourceTree = "<group>"; }; + 26AEAF1617BEA18E009E32C9 /* catch_platform.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = catch_platform.h; sourceTree = "<group>"; }; + 26DACF2F17206D3400A21326 /* catch_text.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = catch_text.h; sourceTree = "<group>"; }; + 26DFD3B11B53F84700FD6F16 /* catch_wildcard_pattern.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = catch_wildcard_pattern.hpp; sourceTree = "<group>"; }; + 26E1B7D119213BC900812682 /* CmdLineTests.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CmdLineTests.cpp; path = ../../../SelfTest/CmdLineTests.cpp; sourceTree = "<group>"; }; + 26EDFBD91B72011F00B1873C /* catch_reporter_multi.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = catch_reporter_multi.hpp; sourceTree = "<group>"; }; + 4A084F1C15DACEEA0027E631 /* catch_test_case_info.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = catch_test_case_info.hpp; sourceTree = "<group>"; }; + 4A3D7DD01503869D005F9203 /* catch_matchers.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = catch_matchers.hpp; sourceTree = "<group>"; }; + 4A45DA2316161EF9004F8D6B /* catch_console_colour.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_console_colour.cpp; path = ../../../SelfTest/SurrogateCpps/catch_console_colour.cpp; sourceTree = "<group>"; }; + 4A45DA2616161F1F004F8D6B /* catch_ptr.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_ptr.cpp; path = ../../../SelfTest/SurrogateCpps/catch_ptr.cpp; sourceTree = "<group>"; }; + 4A45DA2816161F3D004F8D6B /* catch_streambuf.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_streambuf.cpp; path = ../../../SelfTest/SurrogateCpps/catch_streambuf.cpp; sourceTree = "<group>"; }; + 4A45DA2A16161F79004F8D6B /* catch_interfaces_registry_hub.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_interfaces_registry_hub.cpp; path = ../../../SelfTest/SurrogateCpps/catch_interfaces_registry_hub.cpp; sourceTree = "<group>"; }; + 4A45DA2C16161FA2004F8D6B /* catch_interfaces_capture.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_interfaces_capture.cpp; path = ../../../SelfTest/SurrogateCpps/catch_interfaces_capture.cpp; sourceTree = "<group>"; }; + 4A45DA3016161FFB004F8D6B /* catch_interfaces_reporter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_interfaces_reporter.cpp; path = ../../../SelfTest/SurrogateCpps/catch_interfaces_reporter.cpp; sourceTree = "<group>"; }; + 4A45DA3216162047004F8D6B /* catch_interfaces_exception.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_interfaces_exception.cpp; path = ../../../SelfTest/SurrogateCpps/catch_interfaces_exception.cpp; sourceTree = "<group>"; }; + 4A45DA3416162071004F8D6B /* catch_interfaces_runner.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_interfaces_runner.cpp; path = ../../../SelfTest/SurrogateCpps/catch_interfaces_runner.cpp; sourceTree = "<group>"; }; + 4A4B0F9715CE6CFB00AE2392 /* catch_registry_hub.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; lineEnding = 0; path = catch_registry_hub.hpp; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; + 4A4B0F9915CE6EC100AE2392 /* catch_interfaces_registry_hub.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = catch_interfaces_registry_hub.h; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; }; + 4A4B0F9A15CEF84800AE2392 /* catch_notimplemented_exception.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = catch_notimplemented_exception.h; sourceTree = "<group>"; }; + 4A4B0F9B15CEF8C400AE2392 /* catch_notimplemented_exception.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = catch_notimplemented_exception.hpp; sourceTree = "<group>"; }; + 4A4B0F9C15CEFA8300AE2392 /* catch_impl.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; lineEnding = 0; path = catch_impl.hpp; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; + 4A6D0C20149B3D3B00DB3EAA /* CatchSelfTest */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = CatchSelfTest; sourceTree = BUILT_PRODUCTS_DIR; }; + 4A6D0C26149B3D3B00DB3EAA /* CatchSelfTest.1 */ = {isa = PBXFileReference; lastKnownFileType = text.man; path = CatchSelfTest.1; sourceTree = "<group>"; }; + 4A6D0C2D149B3D9E00DB3EAA /* ApproxTests.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ApproxTests.cpp; path = ../../../SelfTest/ApproxTests.cpp; sourceTree = "<group>"; }; + 4A6D0C2F149B3D9E00DB3EAA /* ClassTests.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ClassTests.cpp; path = ../../../SelfTest/ClassTests.cpp; sourceTree = "<group>"; }; + 4A6D0C30149B3D9E00DB3EAA /* ConditionTests.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ConditionTests.cpp; path = ../../../SelfTest/ConditionTests.cpp; sourceTree = "<group>"; }; + 4A6D0C31149B3D9E00DB3EAA /* ExceptionTests.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ExceptionTests.cpp; path = ../../../SelfTest/ExceptionTests.cpp; sourceTree = "<group>"; }; + 4A6D0C32149B3D9E00DB3EAA /* GeneratorTests.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = GeneratorTests.cpp; path = ../../../SelfTest/GeneratorTests.cpp; sourceTree = "<group>"; }; + 4A6D0C33149B3D9E00DB3EAA /* MessageTests.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = MessageTests.cpp; path = ../../../SelfTest/MessageTests.cpp; sourceTree = "<group>"; }; + 4A6D0C34149B3D9E00DB3EAA /* MiscTests.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = MiscTests.cpp; path = ../../../SelfTest/MiscTests.cpp; sourceTree = "<group>"; }; + 4A6D0C35149B3D9E00DB3EAA /* TestMain.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = TestMain.cpp; path = ../../../SelfTest/TestMain.cpp; sourceTree = "<group>"; }; + 4A6D0C36149B3D9E00DB3EAA /* TrickyTests.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = TrickyTests.cpp; path = ../../../SelfTest/TrickyTests.cpp; sourceTree = "<group>"; }; + 4A6D0C42149B3E1500DB3EAA /* catch_session.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; lineEnding = 0; name = catch_session.hpp; path = ../../../../include/catch_session.hpp; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; + 4A6D0C43149B3E1500DB3EAA /* catch_with_main.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = catch_with_main.hpp; path = ../../../../include/catch_with_main.hpp; sourceTree = "<group>"; }; + 4A6D0C44149B3E1500DB3EAA /* catch.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = catch.hpp; path = ../../../../include/catch.hpp; sourceTree = "<group>"; }; + 4A6D0C46149B3E3D00DB3EAA /* catch_approx.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = catch_approx.hpp; sourceTree = "<group>"; }; + 4A6D0C47149B3E3D00DB3EAA /* catch_capture.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; lineEnding = 0; path = catch_capture.hpp; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; + 4A6D0C48149B3E3D00DB3EAA /* catch_commandline.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = catch_commandline.hpp; sourceTree = "<group>"; }; + 4A6D0C49149B3E3D00DB3EAA /* catch_common.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = catch_common.h; sourceTree = "<group>"; }; + 4A6D0C4A149B3E3D00DB3EAA /* catch_config.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = catch_config.hpp; sourceTree = "<group>"; }; + 4A6D0C4B149B3E3D00DB3EAA /* catch_debugger.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = catch_debugger.hpp; sourceTree = "<group>"; }; + 4A6D0C4C149B3E3D00DB3EAA /* catch_default_main.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = catch_default_main.hpp; sourceTree = "<group>"; }; + 4A6D0C4D149B3E3D00DB3EAA /* catch_evaluate.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; lineEnding = 0; path = catch_evaluate.hpp; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; + 4A6D0C4E149B3E3D00DB3EAA /* catch_exception_translator_registry.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = catch_exception_translator_registry.hpp; sourceTree = "<group>"; }; + 4A6D0C4F149B3E3D00DB3EAA /* catch_generators.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = catch_generators.hpp; sourceTree = "<group>"; }; + 4A6D0C50149B3E3D00DB3EAA /* catch_generators_impl.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = catch_generators_impl.hpp; sourceTree = "<group>"; }; + 4A6D0C51149B3E3D00DB3EAA /* catch_context.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = catch_context.h; sourceTree = "<group>"; }; + 4A6D0C52149B3E3D00DB3EAA /* catch_context_impl.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = catch_context_impl.hpp; sourceTree = "<group>"; }; + 4A6D0C53149B3E3D00DB3EAA /* catch_interfaces_capture.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = catch_interfaces_capture.h; sourceTree = "<group>"; }; + 4A6D0C54149B3E3D00DB3EAA /* catch_interfaces_exception.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = catch_interfaces_exception.h; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; }; + 4A6D0C55149B3E3D00DB3EAA /* catch_interfaces_reporter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = catch_interfaces_reporter.h; sourceTree = "<group>"; }; + 4A6D0C56149B3E3D00DB3EAA /* catch_interfaces_runner.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = catch_interfaces_runner.h; sourceTree = "<group>"; }; + 4A6D0C57149B3E3D00DB3EAA /* catch_interfaces_testcase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = catch_interfaces_testcase.h; sourceTree = "<group>"; }; + 4A6D0C58149B3E3D00DB3EAA /* catch_list.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; lineEnding = 0; path = catch_list.hpp; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; + 4A6D0C59149B3E3D00DB3EAA /* catch_objc.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = catch_objc.hpp; sourceTree = "<group>"; }; + 4A6D0C5A149B3E3D00DB3EAA /* catch_reporter_registrars.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; lineEnding = 0; path = catch_reporter_registrars.hpp; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; + 4A6D0C5B149B3E3D00DB3EAA /* catch_reporter_registry.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = catch_reporter_registry.hpp; sourceTree = "<group>"; }; + 4A6D0C5C149B3E3D00DB3EAA /* catch_result_type.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = catch_result_type.h; sourceTree = "<group>"; }; + 4A6D0C5D149B3E3D00DB3EAA /* catch_assertionresult.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = catch_assertionresult.h; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; }; + 4A6D0C5E149B3E3D00DB3EAA /* catch_run_context.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; lineEnding = 0; path = catch_run_context.hpp; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; + 4A6D0C5F149B3E3D00DB3EAA /* catch_section.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = catch_section.hpp; sourceTree = "<group>"; }; + 4A6D0C60149B3E3D00DB3EAA /* catch_stream.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = catch_stream.hpp; sourceTree = "<group>"; }; + 4A6D0C61149B3E3D00DB3EAA /* catch_test_case_info.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = catch_test_case_info.h; sourceTree = "<group>"; }; + 4A6D0C62149B3E3D00DB3EAA /* catch_test_case_registry_impl.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; lineEnding = 0; path = catch_test_case_registry_impl.hpp; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; + 4A6D0C63149B3E3D00DB3EAA /* catch_test_registry.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = catch_test_registry.hpp; sourceTree = "<group>"; }; + 4A6D0C64149B3E3D00DB3EAA /* catch_xmlwriter.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = catch_xmlwriter.hpp; sourceTree = "<group>"; }; + 4A6D0C67149B3E3D00DB3EAA /* catch_reporter_junit.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = catch_reporter_junit.hpp; sourceTree = "<group>"; }; + 4A6D0C68149B3E3D00DB3EAA /* catch_reporter_xml.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = catch_reporter_xml.hpp; sourceTree = "<group>"; }; + 4A7ADB4314F631E10094FE10 /* catch_totals.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = catch_totals.hpp; sourceTree = "<group>"; }; + 4A7DB2CD1652FE4B00FA6523 /* catch_version.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = catch_version.h; path = ../../../../include/internal/catch_version.h; sourceTree = "<group>"; }; + 4A90B59B15D0F61A00EF71BC /* catch_interfaces_generators.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = catch_interfaces_generators.h; sourceTree = "<group>"; }; + 4A90B59D15D24FE900EF71BC /* catch_assertionresult.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; lineEnding = 0; path = catch_assertionresult.hpp; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; + 4AA7B8B4165428BA003155F6 /* catch_version.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; name = catch_version.hpp; path = ../../../../include/internal/catch_version.hpp; sourceTree = "<group>"; }; + 4AB1C73514F97BDA00F31DF7 /* catch_console_colour_impl.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; lineEnding = 0; path = catch_console_colour_impl.hpp; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; + 4AB1C73714F97C1300F31DF7 /* catch_console_colour.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; lineEnding = 0; path = catch_console_colour.hpp; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; + 4AB3D99C1616216500C9A0F8 /* catch_interfaces_testcase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_interfaces_testcase.cpp; path = ../../../SelfTest/SurrogateCpps/catch_interfaces_testcase.cpp; sourceTree = "<group>"; }; + 4AB3D99F1616219100C9A0F8 /* catch_interfaces_config.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_interfaces_config.cpp; path = ../../../SelfTest/SurrogateCpps/catch_interfaces_config.cpp; sourceTree = "<group>"; }; + 4AB3D9A1161621B500C9A0F8 /* catch_interfaces_generators.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_interfaces_generators.cpp; path = ../../../SelfTest/SurrogateCpps/catch_interfaces_generators.cpp; sourceTree = "<group>"; }; + 4AB42F84166F3E1A0099F2C8 /* catch_reporter_console.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = catch_reporter_console.hpp; sourceTree = "<group>"; }; + 4AB77CB51551AEA200857BF0 /* catch_ptr.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = catch_ptr.hpp; sourceTree = "<group>"; }; + 4AB77CB71553B72B00857BF0 /* catch_section_info.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = catch_section_info.hpp; sourceTree = "<group>"; }; + 4ABEA80415C90D2B009F0424 /* catch_objc_arc.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = catch_objc_arc.hpp; sourceTree = "<group>"; }; + 4AC91CCE155CF02800DC5117 /* catch_expression_lhs.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; lineEnding = 0; path = catch_expression_lhs.hpp; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; + 4ACE21C8166CA19700FB5509 /* catch_option.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = catch_option.hpp; sourceTree = "<group>"; }; + 4ACE21CA166CA1B300FB5509 /* catch_option.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_option.cpp; path = ../../../SelfTest/SurrogateCpps/catch_option.cpp; sourceTree = "<group>"; }; + 4AEE031F16142F910071E950 /* catch_common.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_common.cpp; path = ../../../SelfTest/SurrogateCpps/catch_common.cpp; sourceTree = "<group>"; }; + 4AEE032216142FC70071E950 /* catch_debugger.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_debugger.cpp; path = ../../../SelfTest/SurrogateCpps/catch_debugger.cpp; sourceTree = "<group>"; }; + 4AEE032416142FF10071E950 /* catch_stream.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_stream.cpp; path = ../../../SelfTest/SurrogateCpps/catch_stream.cpp; sourceTree = "<group>"; }; + 4AEE0326161431070071E950 /* catch_streambuf.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = catch_streambuf.h; sourceTree = "<group>"; }; + 4AEE0327161434FD0071E950 /* catch_xmlwriter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_xmlwriter.cpp; path = ../../../SelfTest/SurrogateCpps/catch_xmlwriter.cpp; sourceTree = "<group>"; }; + 4AFC661D157E96A7009D58CF /* catch_interfaces_config.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = catch_interfaces_config.h; sourceTree = "<group>"; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 4A6D0C1D149B3D3B00DB3EAA /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 266E9AD317290E710061DAB2 /* Introspective Tests */ = { + isa = PBXGroup; + children = ( + 26059AF11BD4B94C003D575C /* PartTrackerTests.cpp */, + 26E1B7D119213BC900812682 /* CmdLineTests.cpp */, + 26711C8D195D465C0033EDA2 /* TagAliasTests.cpp */, + ); + name = "Introspective Tests"; + sourceTree = "<group>"; + }; + 26C5F3EB17514B670056FB3C /* External */ = { + isa = PBXGroup; + children = ( + 26926E8418D77809004E10F2 /* tbc_text_format.h */, + 26926E8318D7777D004E10F2 /* clara.h */, + ); + name = External; + sourceTree = "<group>"; + }; + 4A6D0C15149B3D3B00DB3EAA = { + isa = PBXGroup; + children = ( + 4A6D0C23149B3D3B00DB3EAA /* CatchSelfTest */, + 4A6D0C21149B3D3B00DB3EAA /* Products */, + ); + sourceTree = "<group>"; + }; + 4A6D0C21149B3D3B00DB3EAA /* Products */ = { + isa = PBXGroup; + children = ( + 4A6D0C20149B3D3B00DB3EAA /* CatchSelfTest */, + ); + name = Products; + sourceTree = "<group>"; + }; + 4A6D0C23149B3D3B00DB3EAA /* CatchSelfTest */ = { + isa = PBXGroup; + children = ( + 4A6D0C35149B3D9E00DB3EAA /* TestMain.cpp */, + 266E9AD317290E710061DAB2 /* Introspective Tests */, + 4A6D0C40149B3DAB00DB3EAA /* Tests */, + 4A6D0C41149B3DE900DB3EAA /* Catch */, + 4A6D0C26149B3D3B00DB3EAA /* CatchSelfTest.1 */, + ); + path = CatchSelfTest; + sourceTree = "<group>"; + }; + 4A6D0C40149B3DAB00DB3EAA /* Tests */ = { + isa = PBXGroup; + children = ( + 2691574B1A532A280054F1ED /* ToStringTuple.cpp */, + 263F7A4819B6FE1E009474C2 /* ToStringPair.cpp */, + 263F7A4919B6FE1E009474C2 /* ToStringVector.cpp */, + 263F7A4A19B6FE1E009474C2 /* ToStringWhich.cpp */, + 263F7A4619B6FCBF009474C2 /* EnumToString.cpp */, + 266ECD73170F3C620030D735 /* BDDTests.cpp */, + 4A6D0C36149B3D9E00DB3EAA /* TrickyTests.cpp */, + 4A6D0C2D149B3D9E00DB3EAA /* ApproxTests.cpp */, + 4A6D0C2F149B3D9E00DB3EAA /* ClassTests.cpp */, + 4A6D0C30149B3D9E00DB3EAA /* ConditionTests.cpp */, + 4A6D0C31149B3D9E00DB3EAA /* ExceptionTests.cpp */, + 4A6D0C32149B3D9E00DB3EAA /* GeneratorTests.cpp */, + 4A6D0C33149B3D9E00DB3EAA /* MessageTests.cpp */, + 4A6D0C34149B3D9E00DB3EAA /* MiscTests.cpp */, + 266B06B616F3A60A004ED264 /* VariadicMacrosTests.cpp */, + ); + name = Tests; + sourceTree = "<group>"; + }; + 4A6D0C41149B3DE900DB3EAA /* Catch */ = { + isa = PBXGroup; + children = ( + 26C5F3EB17514B670056FB3C /* External */, + 4A7DB2CD1652FE4B00FA6523 /* catch_version.h */, + 4AA7B8B4165428BA003155F6 /* catch_version.hpp */, + 4A8E4DCF160A34E200194CBD /* SurrogateCpps */, + 4A6D0C44149B3E1500DB3EAA /* catch.hpp */, + 4A6D0C42149B3E1500DB3EAA /* catch_session.hpp */, + 4A6D0C43149B3E1500DB3EAA /* catch_with_main.hpp */, + 4A6D0C45149B3E3D00DB3EAA /* internal */, + 4A6D0C65149B3E3D00DB3EAA /* reporters */, + ); + name = Catch; + sourceTree = "<group>"; + }; + 4A6D0C45149B3E3D00DB3EAA /* internal */ = { + isa = PBXGroup; + children = ( + 4AC91CC3155C38D300DC5117 /* Objective-C */, + 4AC91CC2155C388300DC5117 /* Infrastructure */, + 4AC91CC1155C387400DC5117 /* Interfaces */, + 4AC91CC0155C384400DC5117 /* Process */, + 4AC91CBF155C381600DC5117 /* Test execution */, + 4AC91CBE155C37F800DC5117 /* Registries */, + 4AC91CBD155C37B500DC5117 /* Assertions */, + 4AC91CB4155B9EBF00DC5117 /* impl */, + ); + name = internal; + path = ../../../../include/internal; + sourceTree = "<group>"; + }; + 4A6D0C65149B3E3D00DB3EAA /* reporters */ = { + isa = PBXGroup; + children = ( + 269831E719121CA500BB0CE0 /* catch_reporter_compact.hpp */, + 262E7399184673A800CAC268 /* catch_reporter_bases.hpp */, + 4A6D0C67149B3E3D00DB3EAA /* catch_reporter_junit.hpp */, + 4A6D0C68149B3E3D00DB3EAA /* catch_reporter_xml.hpp */, + 4AB42F84166F3E1A0099F2C8 /* catch_reporter_console.hpp */, + 2691574A1A4480C50054F1ED /* catch_reporter_teamcity.hpp */, + 26EDFBD91B72011F00B1873C /* catch_reporter_multi.hpp */, + ); + name = reporters; + path = ../../../../include/reporters; + sourceTree = "<group>"; + }; + 4A8E4DCF160A34E200194CBD /* SurrogateCpps */ = { + isa = PBXGroup; + children = ( + 2656C2201925E7330040DB02 /* catch_test_spec.cpp */, + 4AEE031F16142F910071E950 /* catch_common.cpp */, + 4AEE032216142FC70071E950 /* catch_debugger.cpp */, + 4AEE032416142FF10071E950 /* catch_stream.cpp */, + 4AEE0327161434FD0071E950 /* catch_xmlwriter.cpp */, + 4A45DA2316161EF9004F8D6B /* catch_console_colour.cpp */, + 4A45DA2616161F1F004F8D6B /* catch_ptr.cpp */, + 4A45DA2816161F3D004F8D6B /* catch_streambuf.cpp */, + 4A45DA2A16161F79004F8D6B /* catch_interfaces_registry_hub.cpp */, + 4A45DA2C16161FA2004F8D6B /* catch_interfaces_capture.cpp */, + 4A45DA3216162047004F8D6B /* catch_interfaces_exception.cpp */, + 4A45DA3016161FFB004F8D6B /* catch_interfaces_reporter.cpp */, + 4A45DA3416162071004F8D6B /* catch_interfaces_runner.cpp */, + 4AB3D99C1616216500C9A0F8 /* catch_interfaces_testcase.cpp */, + 4AB3D99F1616219100C9A0F8 /* catch_interfaces_config.cpp */, + 4AB3D9A1161621B500C9A0F8 /* catch_interfaces_generators.cpp */, + 4ACE21CA166CA1B300FB5509 /* catch_option.cpp */, + 2694A1FB16A0000E004816E3 /* catch_text.cpp */, + 26847E5D16BBADB40043B9C1 /* catch_message.cpp */, + ); + name = SurrogateCpps; + sourceTree = "<group>"; + }; + 4AC91CB4155B9EBF00DC5117 /* impl */ = { + isa = PBXGroup; + children = ( + 4A6D0C5F149B3E3D00DB3EAA /* catch_section.hpp */, + 263FD06017AF8DF200988A20 /* catch_timer.hpp */, + 4A4B0F9C15CEFA8300AE2392 /* catch_impl.hpp */, + 4A4B0F9715CE6CFB00AE2392 /* catch_registry_hub.hpp */, + 4A6D0C50149B3E3D00DB3EAA /* catch_generators_impl.hpp */, + 4A6D0C52149B3E3D00DB3EAA /* catch_context_impl.hpp */, + 4A6D0C5E149B3E3D00DB3EAA /* catch_run_context.hpp */, + 4A6D0C62149B3E3D00DB3EAA /* catch_test_case_registry_impl.hpp */, + 4AB1C73514F97BDA00F31DF7 /* catch_console_colour_impl.hpp */, + 4A4B0F9B15CEF8C400AE2392 /* catch_notimplemented_exception.hpp */, + 4A90B59D15D24FE900EF71BC /* catch_assertionresult.hpp */, + 4A084F1C15DACEEA0027E631 /* catch_test_case_info.hpp */, + 26847E5C16BBACB60043B9C1 /* catch_message.hpp */, + 2627F7061935B55F009BCE2D /* catch_result_builder.hpp */, + 26711C92195D48F60033EDA2 /* catch_tag_alias_registry.hpp */, + ); + name = impl; + sourceTree = "<group>"; + }; + 4AC91CBD155C37B500DC5117 /* Assertions */ = { + isa = PBXGroup; + children = ( + 269831E519078C1600BB0CE0 /* catch_tostring.h */, + 269831E619078CA200BB0CE0 /* catch_tostring.hpp */, + 4A6D0C4D149B3E3D00DB3EAA /* catch_evaluate.hpp */, + 4A6D0C4F149B3E3D00DB3EAA /* catch_generators.hpp */, + 4A6D0C5C149B3E3D00DB3EAA /* catch_result_type.h */, + 4A6D0C5D149B3E3D00DB3EAA /* catch_assertionresult.h */, + 261488FE184DC32F0041FBEB /* catch_section.h */, + 4A3D7DD01503869D005F9203 /* catch_matchers.hpp */, + 4A6D0C46149B3E3D00DB3EAA /* catch_approx.hpp */, + 4A6D0C47149B3E3D00DB3EAA /* catch_capture.hpp */, + 4AC91CCE155CF02800DC5117 /* catch_expression_lhs.hpp */, + 4A4B0F9A15CEF84800AE2392 /* catch_notimplemented_exception.h */, + 26847E5B16BBAB790043B9C1 /* catch_message.h */, + 261488FD184D21290041FBEB /* catch_section_info.h */, + 2627F7051935B16F009BCE2D /* catch_result_builder.h */, + ); + name = Assertions; + sourceTree = "<group>"; + }; + 4AC91CBE155C37F800DC5117 /* Registries */ = { + isa = PBXGroup; + children = ( + 4A6D0C4E149B3E3D00DB3EAA /* catch_exception_translator_registry.hpp */, + 4A6D0C5A149B3E3D00DB3EAA /* catch_reporter_registrars.hpp */, + 4A6D0C5B149B3E3D00DB3EAA /* catch_reporter_registry.hpp */, + 4A6D0C63149B3E3D00DB3EAA /* catch_test_registry.hpp */, + ); + name = Registries; + sourceTree = "<group>"; + }; + 4AC91CBF155C381600DC5117 /* Test execution */ = { + isa = PBXGroup; + children = ( + 261488FA184C81130041FBEB /* catch_test_spec.hpp */, + 2656C21F1925E5100040DB02 /* catch_test_spec_parser.hpp */, + 4A6D0C4A149B3E3D00DB3EAA /* catch_config.hpp */, + 4A6D0C51149B3E3D00DB3EAA /* catch_context.h */, + 4A6D0C61149B3E3D00DB3EAA /* catch_test_case_info.h */, + 4A7ADB4314F631E10094FE10 /* catch_totals.hpp */, + 4AB77CB71553B72B00857BF0 /* catch_section_info.hpp */, + 26948287179EF7F900ED166E /* catch_test_case_tracker.hpp */, + 26711C91195D47820033EDA2 /* catch_tag_alias.h */, + 26711C94195D4B120033EDA2 /* catch_tag_alias_registry.h */, + ); + name = "Test execution"; + sourceTree = "<group>"; + }; + 4AC91CC0155C384400DC5117 /* Process */ = { + isa = PBXGroup; + children = ( + 4A6D0C58149B3E3D00DB3EAA /* catch_list.hpp */, + 4A6D0C48149B3E3D00DB3EAA /* catch_commandline.hpp */, + 4A6D0C4C149B3E3D00DB3EAA /* catch_default_main.hpp */, + ); + name = Process; + sourceTree = "<group>"; + }; + 4AC91CC1155C387400DC5117 /* Interfaces */ = { + isa = PBXGroup; + children = ( + 4A4B0F9915CE6EC100AE2392 /* catch_interfaces_registry_hub.h */, + 4A6D0C53149B3E3D00DB3EAA /* catch_interfaces_capture.h */, + 4A6D0C54149B3E3D00DB3EAA /* catch_interfaces_exception.h */, + 4A6D0C55149B3E3D00DB3EAA /* catch_interfaces_reporter.h */, + 4A6D0C56149B3E3D00DB3EAA /* catch_interfaces_runner.h */, + 4A6D0C57149B3E3D00DB3EAA /* catch_interfaces_testcase.h */, + 4AFC661D157E96A7009D58CF /* catch_interfaces_config.h */, + 4A90B59B15D0F61A00EF71BC /* catch_interfaces_generators.h */, + 26711C90195D46CD0033EDA2 /* catch_interfaces_tag_alias_registry.h */, + ); + name = Interfaces; + sourceTree = "<group>"; + }; + 4AC91CC2155C388300DC5117 /* Infrastructure */ = { + isa = PBXGroup; + children = ( + 266ECD8C1713614B0030D735 /* catch_legacy_reporter_adapter.hpp */, + 266ECD8D1713614B0030D735 /* catch_legacy_reporter_adapter.h */, + 4A6D0C49149B3E3D00DB3EAA /* catch_common.h */, + 262E739A1846759000CAC268 /* catch_common.hpp */, + 4A6D0C4B149B3E3D00DB3EAA /* catch_debugger.hpp */, + 261488FF184DC4A20041FBEB /* catch_debugger.h */, + 4A6D0C60149B3E3D00DB3EAA /* catch_stream.hpp */, + 4A6D0C64149B3E3D00DB3EAA /* catch_xmlwriter.hpp */, + 4AB1C73714F97C1300F31DF7 /* catch_console_colour.hpp */, + 4AB77CB51551AEA200857BF0 /* catch_ptr.hpp */, + 4AEE0326161431070071E950 /* catch_streambuf.h */, + 4ACE21C8166CA19700FB5509 /* catch_option.hpp */, + 26759473171C74C200A84BD1 /* catch_compiler_capabilities.h */, + 26DACF2F17206D3400A21326 /* catch_text.h */, + 263FD06117AF8DF200988A20 /* catch_timer.h */, + 26AEAF1617BEA18E009E32C9 /* catch_platform.h */, + 261488FC184D1DC10041FBEB /* catch_stream.h */, + 268F47B018A93F7800D8C14F /* catch_clara.h */, + 2656C226192A77EF0040DB02 /* catch_suppress_warnings.h */, + 2656C227192A78410040DB02 /* catch_reenable_warnings.h */, + 263F7A4519A66608009474C2 /* catch_fatal_condition.hpp */, + 26DFD3B11B53F84700FD6F16 /* catch_wildcard_pattern.hpp */, + ); + name = Infrastructure; + sourceTree = "<group>"; + }; + 4AC91CC3155C38D300DC5117 /* Objective-C */ = { + isa = PBXGroup; + children = ( + 4A6D0C59149B3E3D00DB3EAA /* catch_objc.hpp */, + 4ABEA80415C90D2B009F0424 /* catch_objc_arc.hpp */, + ); + name = "Objective-C"; + sourceTree = "<group>"; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 4A6D0C1F149B3D3B00DB3EAA /* CatchSelfTest */ = { + isa = PBXNativeTarget; + buildConfigurationList = 4A6D0C2A149B3D3B00DB3EAA /* Build configuration list for PBXNativeTarget "CatchSelfTest" */; + buildPhases = ( + 4A6D0C1C149B3D3B00DB3EAA /* Sources */, + 4A6D0C1D149B3D3B00DB3EAA /* Frameworks */, + 4A6D0C1E149B3D3B00DB3EAA /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = CatchSelfTest; + productName = CatchSelfTest; + productReference = 4A6D0C20149B3D3B00DB3EAA /* CatchSelfTest */; + productType = "com.apple.product-type.tool"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 4A6D0C17149B3D3B00DB3EAA /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0710; + }; + buildConfigurationList = 4A6D0C1A149B3D3B00DB3EAA /* Build configuration list for PBXProject "CatchSelfTest" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + ); + mainGroup = 4A6D0C15149B3D3B00DB3EAA; + productRefGroup = 4A6D0C21149B3D3B00DB3EAA /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 4A6D0C1F149B3D3B00DB3EAA /* CatchSelfTest */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXSourcesBuildPhase section */ + 4A6D0C1C149B3D3B00DB3EAA /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 263F7A4719B6FCBF009474C2 /* EnumToString.cpp in Sources */, + 4A6D0C37149B3D9E00DB3EAA /* ApproxTests.cpp in Sources */, + 4A6D0C38149B3D9E00DB3EAA /* ClassTests.cpp in Sources */, + 4A6D0C39149B3D9E00DB3EAA /* ConditionTests.cpp in Sources */, + 4A6D0C3A149B3D9E00DB3EAA /* ExceptionTests.cpp in Sources */, + 4A6D0C3B149B3D9E00DB3EAA /* GeneratorTests.cpp in Sources */, + 4A6D0C3C149B3D9E00DB3EAA /* MessageTests.cpp in Sources */, + 4A6D0C3D149B3D9E00DB3EAA /* MiscTests.cpp in Sources */, + 4A6D0C3E149B3D9E00DB3EAA /* TestMain.cpp in Sources */, + 4A6D0C3F149B3D9E00DB3EAA /* TrickyTests.cpp in Sources */, + 263F7A4D19B6FE1E009474C2 /* ToStringWhich.cpp in Sources */, + 26059AF21BD4B94C003D575C /* PartTrackerTests.cpp in Sources */, + 263F7A4B19B6FE1E009474C2 /* ToStringPair.cpp in Sources */, + 4AEE032016142F910071E950 /* catch_common.cpp in Sources */, + 263F7A4C19B6FE1E009474C2 /* ToStringVector.cpp in Sources */, + 4AEE032316142FC70071E950 /* catch_debugger.cpp in Sources */, + 4AEE032516142FF10071E950 /* catch_stream.cpp in Sources */, + 4AEE0328161434FD0071E950 /* catch_xmlwriter.cpp in Sources */, + 4A45DA2416161EF9004F8D6B /* catch_console_colour.cpp in Sources */, + 4A45DA2716161F1F004F8D6B /* catch_ptr.cpp in Sources */, + 26E1B7D319213BC900812682 /* CmdLineTests.cpp in Sources */, + 2656C2211925E7330040DB02 /* catch_test_spec.cpp in Sources */, + 4A45DA2916161F3D004F8D6B /* catch_streambuf.cpp in Sources */, + 4A45DA2B16161F79004F8D6B /* catch_interfaces_registry_hub.cpp in Sources */, + 4A45DA2D16161FA2004F8D6B /* catch_interfaces_capture.cpp in Sources */, + 4A45DA3116161FFC004F8D6B /* catch_interfaces_reporter.cpp in Sources */, + 4A45DA3316162047004F8D6B /* catch_interfaces_exception.cpp in Sources */, + 2691574C1A532A280054F1ED /* ToStringTuple.cpp in Sources */, + 26711C8F195D465C0033EDA2 /* TagAliasTests.cpp in Sources */, + 4A45DA3516162071004F8D6B /* catch_interfaces_runner.cpp in Sources */, + 4AB3D99D1616216500C9A0F8 /* catch_interfaces_testcase.cpp in Sources */, + 4AB3D9A01616219100C9A0F8 /* catch_interfaces_config.cpp in Sources */, + 4AB3D9A2161621B500C9A0F8 /* catch_interfaces_generators.cpp in Sources */, + 4ACE21CC166CA1B300FB5509 /* catch_option.cpp in Sources */, + 2694A1FD16A0000E004816E3 /* catch_text.cpp in Sources */, + 26847E5F16BBADB40043B9C1 /* catch_message.cpp in Sources */, + 266B06B816F3A60A004ED264 /* VariadicMacrosTests.cpp in Sources */, + 266ECD74170F3C620030D735 /* BDDTests.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + 4A6D0C28149B3D3B00DB3EAA /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_CXX_LANGUAGE_STANDARD = "c++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_WARN_CXX0X_EXTENSIONS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_IMPLICIT_SIGN_CONVERSION = YES; + CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CLANG_WARN__EXIT_TIME_DESTRUCTORS = NO; + COPY_PHASE_STRIP = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_ENABLE_OBJC_EXCEPTIONS = YES; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_TREAT_IMPLICIT_FUNCTION_DECLARATIONS_AS_ERRORS = YES; + GCC_TREAT_INCOMPATIBLE_POINTER_TYPE_WARNINGS_AS_ERRORS = YES; + GCC_VERSION = com.apple.compilers.llvm.clang.1_0; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_MISSING_FIELD_INITIALIZERS = YES; + GCC_WARN_ABOUT_MISSING_NEWLINE = YES; + GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_FOUR_CHARACTER_CONSTANTS = YES; + GCC_WARN_HIDDEN_VIRTUAL_FUNCTIONS = YES; + GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES; + GCC_WARN_NON_VIRTUAL_DESTRUCTOR = YES; + GCC_WARN_PEDANTIC = YES; + GCC_WARN_SHADOW = YES; + GCC_WARN_SIGN_COMPARE = YES; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_LABEL = YES; + GCC_WARN_UNUSED_PARAMETER = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = ""; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + USER_HEADER_SEARCH_PATHS = "\"$(PROJECT_DIR)/../../../include\""; + }; + name = Debug; + }; + 4A6D0C29149B3D3B00DB3EAA /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_CXX_LANGUAGE_STANDARD = "c++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_WARN_CXX0X_EXTENSIONS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_IMPLICIT_SIGN_CONVERSION = YES; + CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CLANG_WARN__EXIT_TIME_DESTRUCTORS = NO; + COPY_PHASE_STRIP = YES; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_ENABLE_OBJC_EXCEPTIONS = YES; + GCC_NO_COMMON_BLOCKS = YES; + GCC_TREAT_IMPLICIT_FUNCTION_DECLARATIONS_AS_ERRORS = YES; + GCC_TREAT_INCOMPATIBLE_POINTER_TYPE_WARNINGS_AS_ERRORS = YES; + GCC_VERSION = com.apple.compilers.llvm.clang.1_0; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_MISSING_FIELD_INITIALIZERS = YES; + GCC_WARN_ABOUT_MISSING_NEWLINE = YES; + GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_FOUR_CHARACTER_CONSTANTS = YES; + GCC_WARN_HIDDEN_VIRTUAL_FUNCTIONS = YES; + GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES; + GCC_WARN_NON_VIRTUAL_DESTRUCTOR = YES; + GCC_WARN_PEDANTIC = YES; + GCC_WARN_SHADOW = YES; + GCC_WARN_SIGN_COMPARE = YES; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_LABEL = YES; + GCC_WARN_UNUSED_PARAMETER = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = ""; + SDKROOT = macosx; + USER_HEADER_SEARCH_PATHS = "\"$(PROJECT_DIR)/../../../include\""; + }; + name = Release; + }; + 4A6D0C2B149B3D3B00DB3EAA /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ANALYZER_SECURITY_FLOATLOOPCOUNTER = YES; + CLANG_CXX_LANGUAGE_STANDARD = "c++0x"; + CLANG_CXX_LIBRARY = "compiler-default"; + CLANG_WARN__DUPLICATE_METHOD_MATCH = NO; + GCC_VERSION = com.apple.compilers.llvm.clang.1_0; + OTHER_CPLUSPLUSFLAGS = "$(OTHER_CFLAGS)"; + PRODUCT_NAME = "$(TARGET_NAME)"; + WARNING_CFLAGS = ( + "-Weverything", + "-Wparentheses", + "-Wno-disabled-macro-expansion", + ); + }; + name = Debug; + }; + 4A6D0C2C149B3D3B00DB3EAA /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ANALYZER_SECURITY_FLOATLOOPCOUNTER = YES; + CLANG_CXX_LANGUAGE_STANDARD = "c++0x"; + CLANG_CXX_LIBRARY = "compiler-default"; + CLANG_WARN__DUPLICATE_METHOD_MATCH = NO; + GCC_VERSION = com.apple.compilers.llvm.clang.1_0; + OTHER_CPLUSPLUSFLAGS = "$(OTHER_CFLAGS)"; + PRODUCT_NAME = "$(TARGET_NAME)"; + WARNING_CFLAGS = ( + "-Weverything", + "-Wparentheses", + "-Wno-disabled-macro-expansion", + ); + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 4A6D0C1A149B3D3B00DB3EAA /* Build configuration list for PBXProject "CatchSelfTest" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 4A6D0C28149B3D3B00DB3EAA /* Debug */, + 4A6D0C29149B3D3B00DB3EAA /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 4A6D0C2A149B3D3B00DB3EAA /* Build configuration list for PBXNativeTarget "CatchSelfTest" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 4A6D0C2B149B3D3B00DB3EAA /* Debug */, + 4A6D0C2C149B3D3B00DB3EAA /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 4A6D0C17149B3D3B00DB3EAA /* Project object */; +} diff --git a/unittest/Catch/projects/XCode/CatchSelfTest/CatchSelfTest.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/unittest/Catch/projects/XCode/CatchSelfTest/CatchSelfTest.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..804437d --- /dev/null +++ b/unittest/Catch/projects/XCode/CatchSelfTest/CatchSelfTest.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="UTF-8"?> +<Workspace + version = "1.0"> + <FileRef + location = "self:CatchSelfTest.xcodeproj"> + </FileRef> +</Workspace> diff --git a/unittest/Catch/projects/XCode/CatchSelfTest/CatchSelfTest/CatchSelfTest.1 b/unittest/Catch/projects/XCode/CatchSelfTest/CatchSelfTest/CatchSelfTest.1 new file mode 100644 index 0000000..28b36e2 --- /dev/null +++ b/unittest/Catch/projects/XCode/CatchSelfTest/CatchSelfTest/CatchSelfTest.1 @@ -0,0 +1,79 @@ +.\"Modified from man(1) of FreeBSD, the NetBSD mdoc.template, and mdoc.samples. +.\"See Also: +.\"man mdoc.samples for a complete listing of options +.\"man mdoc for the short list of editing options +.\"/usr/share/misc/mdoc.template +.Dd 16/12/2011 \" DATE +.Dt CatchSelfTest 1 \" Program name and manual section number +.Os Darwin +.Sh NAME \" Section Header - required - don't modify +.Nm CatchSelfTest, +.\" The following lines are read in generating the apropos(man -k) database. Use only key +.\" words here as the database is built based on the words here and in the .ND line. +.Nm Other_name_for_same_program(), +.Nm Yet another name for the same program. +.\" Use .Nm macro to designate other names for the documented program. +.Nd This line parsed for whatis database. +.Sh SYNOPSIS \" Section Header - required - don't modify +.Nm +.Op Fl abcd \" [-abcd] +.Op Fl a Ar path \" [-a path] +.Op Ar file \" [file] +.Op Ar \" [file ...] +.Ar arg0 \" Underlined argument - use .Ar anywhere to underline +arg2 ... \" Arguments +.Sh DESCRIPTION \" Section Header - required - don't modify +Use the .Nm macro to refer to your program throughout the man page like such: +.Nm +Underlining is accomplished with the .Ar macro like this: +.Ar underlined text . +.Pp \" Inserts a space +A list of items with descriptions: +.Bl -tag -width -indent \" Begins a tagged list +.It item a \" Each item preceded by .It macro +Description of item a +.It item b +Description of item b +.El \" Ends the list +.Pp +A list of flags and their descriptions: +.Bl -tag -width -indent \" Differs from above in tag removed +.It Fl a \"-a flag as a list item +Description of -a flag +.It Fl b +Description of -b flag +.El \" Ends the list +.Pp +.\" .Sh ENVIRONMENT \" May not be needed +.\" .Bl -tag -width "ENV_VAR_1" -indent \" ENV_VAR_1 is width of the string ENV_VAR_1 +.\" .It Ev ENV_VAR_1 +.\" Description of ENV_VAR_1 +.\" .It Ev ENV_VAR_2 +.\" Description of ENV_VAR_2 +.\" .El +.Sh FILES \" File used or created by the topic of the man page +.Bl -tag -width "/Users/joeuser/Library/really_long_file_name" -compact +.It Pa /usr/share/file_name +FILE_1 description +.It Pa /Users/joeuser/Library/really_long_file_name +FILE_2 description +.El \" Ends the list +.\" .Sh DIAGNOSTICS \" May not be needed +.\" .Bl -diag +.\" .It Diagnostic Tag +.\" Diagnostic informtion here. +.\" .It Diagnostic Tag +.\" Diagnostic informtion here. +.\" .El +.Sh SEE ALSO +.\" List links in ascending order by section, alphabetically within a section. +.\" Please do not reference files that do not exist without filing a bug report +.Xr a 1 , +.Xr b 1 , +.Xr c 1 , +.Xr a 2 , +.Xr b 2 , +.Xr a 3 , +.Xr b 3 +.\" .Sh BUGS \" Document known, unremedied bugs +.\" .Sh HISTORY \" Document history if command behaves in a unique manner
\ No newline at end of file diff --git a/unittest/Catch/projects/XCode/CatchSelfTest/CatchSelfTest/catch_text.cpp b/unittest/Catch/projects/XCode/CatchSelfTest/CatchSelfTest/catch_text.cpp new file mode 100644 index 0000000..a08e67b --- /dev/null +++ b/unittest/Catch/projects/XCode/CatchSelfTest/CatchSelfTest/catch_text.cpp @@ -0,0 +1,3 @@ +// This file is only here to verify (to the extent possible) the self sufficiency of the header +#include "catch_suppress_warnings.h" +#include "catch_text.h" diff --git a/unittest/Catch/projects/XCode/CatchSelfTest/CatchSelfTestSingle.xcodeproj/project.pbxproj b/unittest/Catch/projects/XCode/CatchSelfTest/CatchSelfTestSingle.xcodeproj/project.pbxproj new file mode 100644 index 0000000..1eee6eb --- /dev/null +++ b/unittest/Catch/projects/XCode/CatchSelfTest/CatchSelfTestSingle.xcodeproj/project.pbxproj @@ -0,0 +1,258 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 4A2894D615D3956000E20735 /* ApproxTests.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4A2894D515D3956000E20735 /* ApproxTests.cpp */; }; + 4AB735FA15D396F400F9F7C3 /* TestMain.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4A2894E015D3957500E20735 /* TestMain.cpp */; }; + 4AB735FB15D3970C00F9F7C3 /* ClassTests.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4A2894DA15D3957500E20735 /* ClassTests.cpp */; }; + 4AB735FC15D3971100F9F7C3 /* ConditionTests.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4A2894DB15D3957500E20735 /* ConditionTests.cpp */; }; + 4AB735FD15D3971600F9F7C3 /* ExceptionTests.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4A2894DC15D3957500E20735 /* ExceptionTests.cpp */; }; + 4AB735FE15D3971600F9F7C3 /* GeneratorTests.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4A2894DD15D3957500E20735 /* GeneratorTests.cpp */; }; + 4AB735FF15D3971600F9F7C3 /* MessageTests.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4A2894DE15D3957500E20735 /* MessageTests.cpp */; }; + 4AB7360015D3971600F9F7C3 /* MiscTests.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4A2894DF15D3957500E20735 /* MiscTests.cpp */; }; + 4AB7360115D3971600F9F7C3 /* TrickyTests.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4A2894E115D3957500E20735 /* TrickyTests.cpp */; }; +/* End PBXBuildFile section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 4A90B5D415D2E3E900EF71BC /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = /usr/share/man/man1/; + dstSubfolderSpec = 0; + files = ( + ); + runOnlyForDeploymentPostprocessing = 1; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 4A2894D515D3956000E20735 /* ApproxTests.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ApproxTests.cpp; path = ../../../SelfTest/ApproxTests.cpp; sourceTree = "<group>"; }; + 4A2894DA15D3957500E20735 /* ClassTests.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = ClassTests.cpp; path = ../../../SelfTest/ClassTests.cpp; sourceTree = "<group>"; }; + 4A2894DB15D3957500E20735 /* ConditionTests.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = ConditionTests.cpp; path = ../../../SelfTest/ConditionTests.cpp; sourceTree = "<group>"; }; + 4A2894DC15D3957500E20735 /* ExceptionTests.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = ExceptionTests.cpp; path = ../../../SelfTest/ExceptionTests.cpp; sourceTree = "<group>"; }; + 4A2894DD15D3957500E20735 /* GeneratorTests.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = GeneratorTests.cpp; path = ../../../SelfTest/GeneratorTests.cpp; sourceTree = "<group>"; }; + 4A2894DE15D3957500E20735 /* MessageTests.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = MessageTests.cpp; path = ../../../SelfTest/MessageTests.cpp; sourceTree = "<group>"; }; + 4A2894DF15D3957500E20735 /* MiscTests.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = MiscTests.cpp; path = ../../../SelfTest/MiscTests.cpp; sourceTree = "<group>"; }; + 4A2894E015D3957500E20735 /* TestMain.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = TestMain.cpp; path = ../../../SelfTest/TestMain.cpp; sourceTree = "<group>"; }; + 4A2894E115D3957500E20735 /* TrickyTests.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = TrickyTests.cpp; path = ../../../SelfTest/TrickyTests.cpp; sourceTree = "<group>"; }; + 4A90B5D615D2E3E900EF71BC /* CatchSelfTestSingle */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = CatchSelfTestSingle; sourceTree = BUILT_PRODUCTS_DIR; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 4A90B5D315D2E3E900EF71BC /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 4A2894E215D3957D00E20735 /* Self Test */ = { + isa = PBXGroup; + children = ( + 4A2894E015D3957500E20735 /* TestMain.cpp */, + ); + name = "Self Test"; + sourceTree = "<group>"; + }; + 4A2894E315D3959800E20735 /* Test Cases */ = { + isa = PBXGroup; + children = ( + 4A2894DA15D3957500E20735 /* ClassTests.cpp */, + 4A2894DB15D3957500E20735 /* ConditionTests.cpp */, + 4A2894DC15D3957500E20735 /* ExceptionTests.cpp */, + 4A2894DD15D3957500E20735 /* GeneratorTests.cpp */, + 4A2894DE15D3957500E20735 /* MessageTests.cpp */, + 4A2894DF15D3957500E20735 /* MiscTests.cpp */, + 4A2894E115D3957500E20735 /* TrickyTests.cpp */, + 4A2894D515D3956000E20735 /* ApproxTests.cpp */, + ); + name = "Test Cases"; + sourceTree = "<group>"; + }; + 4A90B5CB15D2E3E900EF71BC = { + isa = PBXGroup; + children = ( + 4A90B5D915D2E3E900EF71BC /* CatchSelfTestSingle */, + 4A90B5D715D2E3E900EF71BC /* Products */, + ); + sourceTree = "<group>"; + }; + 4A90B5D715D2E3E900EF71BC /* Products */ = { + isa = PBXGroup; + children = ( + 4A90B5D615D2E3E900EF71BC /* CatchSelfTestSingle */, + ); + name = Products; + sourceTree = "<group>"; + }; + 4A90B5D915D2E3E900EF71BC /* CatchSelfTestSingle */ = { + isa = PBXGroup; + children = ( + 4A2894E315D3959800E20735 /* Test Cases */, + 4A2894E215D3957D00E20735 /* Self Test */, + ); + path = CatchSelfTestSingle; + sourceTree = "<group>"; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 4A90B5D515D2E3E900EF71BC /* CatchSelfTestSingle */ = { + isa = PBXNativeTarget; + buildConfigurationList = 4A90B5E015D2E3E900EF71BC /* Build configuration list for PBXNativeTarget "CatchSelfTestSingle" */; + buildPhases = ( + 4A90B5D215D2E3E900EF71BC /* Sources */, + 4A90B5D315D2E3E900EF71BC /* Frameworks */, + 4A90B5D415D2E3E900EF71BC /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = CatchSelfTestSingle; + productName = CatchSelfTestSingle; + productReference = 4A90B5D615D2E3E900EF71BC /* CatchSelfTestSingle */; + productType = "com.apple.product-type.tool"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 4A90B5CD15D2E3E900EF71BC /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0500; + ORGANIZATIONNAME = "Phil Nash"; + }; + buildConfigurationList = 4A90B5D015D2E3E900EF71BC /* Build configuration list for PBXProject "CatchSelfTestSingle" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + ); + mainGroup = 4A90B5CB15D2E3E900EF71BC; + productRefGroup = 4A90B5D715D2E3E900EF71BC /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 4A90B5D515D2E3E900EF71BC /* CatchSelfTestSingle */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXSourcesBuildPhase section */ + 4A90B5D215D2E3E900EF71BC /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 4A2894D615D3956000E20735 /* ApproxTests.cpp in Sources */, + 4AB735FA15D396F400F9F7C3 /* TestMain.cpp in Sources */, + 4AB735FB15D3970C00F9F7C3 /* ClassTests.cpp in Sources */, + 4AB735FC15D3971100F9F7C3 /* ConditionTests.cpp in Sources */, + 4AB735FD15D3971600F9F7C3 /* ExceptionTests.cpp in Sources */, + 4AB735FE15D3971600F9F7C3 /* GeneratorTests.cpp in Sources */, + 4AB735FF15D3971600F9F7C3 /* MessageTests.cpp in Sources */, + 4AB7360015D3971600F9F7C3 /* MiscTests.cpp in Sources */, + 4AB7360115D3971600F9F7C3 /* TrickyTests.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + 4A90B5DE15D2E3E900EF71BC /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_ENABLE_OBJC_EXCEPTIONS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.8; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + }; + name = Debug; + }; + 4A90B5DF15D2E3E900EF71BC /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = YES; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_ENABLE_OBJC_EXCEPTIONS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.8; + SDKROOT = macosx; + }; + name = Release; + }; + 4A90B5E115D2E3E900EF71BC /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_CXX_LIBRARY = "libc++"; + HEADER_SEARCH_PATHS = "../../../single_include/**"; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 4A90B5E215D2E3E900EF71BC /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_CXX_LIBRARY = "libc++"; + HEADER_SEARCH_PATHS = "../../../single_include/**"; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 4A90B5D015D2E3E900EF71BC /* Build configuration list for PBXProject "CatchSelfTestSingle" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 4A90B5DE15D2E3E900EF71BC /* Debug */, + 4A90B5DF15D2E3E900EF71BC /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 4A90B5E015D2E3E900EF71BC /* Build configuration list for PBXNativeTarget "CatchSelfTestSingle" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 4A90B5E115D2E3E900EF71BC /* Debug */, + 4A90B5E215D2E3E900EF71BC /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 4A90B5CD15D2E3E900EF71BC /* Project object */; +} diff --git a/unittest/Catch/projects/XCode/CatchSelfTest/CatchSelfTestSingle.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/unittest/Catch/projects/XCode/CatchSelfTest/CatchSelfTestSingle.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..4fcfc0e --- /dev/null +++ b/unittest/Catch/projects/XCode/CatchSelfTest/CatchSelfTestSingle.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="UTF-8"?> +<Workspace + version = "1.0"> + <FileRef + location = "self:CatchSelfTestSingle.xcodeproj"> + </FileRef> +</Workspace> diff --git a/unittest/Catch/projects/XCode/CatchSelfTest/CatchSelfTestSingle.xcodeproj/project.xcworkspace/xcshareddata/CatchSelfTestSingle.xccheckout b/unittest/Catch/projects/XCode/CatchSelfTest/CatchSelfTestSingle.xcodeproj/project.xcworkspace/xcshareddata/CatchSelfTestSingle.xccheckout new file mode 100644 index 0000000..cce7052 --- /dev/null +++ b/unittest/Catch/projects/XCode/CatchSelfTest/CatchSelfTestSingle.xcodeproj/project.xcworkspace/xcshareddata/CatchSelfTestSingle.xccheckout @@ -0,0 +1,41 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<dict> + <key>IDESourceControlProjectFavoriteDictionaryKey</key> + <false/> + <key>IDESourceControlProjectIdentifier</key> + <string>3A514CAE-B659-4429-93A3-39F9C0349EC4</string> + <key>IDESourceControlProjectName</key> + <string>CatchSelfTestSingle</string> + <key>IDESourceControlProjectOriginsDictionary</key> + <dict> + <key>90C00904F36E6ADB57A7313E998815D255B0DEAF</key> + <string>https://github.com/philsquared/Catch.git</string> + </dict> + <key>IDESourceControlProjectPath</key> + <string>projects/XCode/CatchSelfTest/CatchSelfTestSingle.xcodeproj</string> + <key>IDESourceControlProjectRelativeInstallPathDictionary</key> + <dict> + <key>90C00904F36E6ADB57A7313E998815D255B0DEAF</key> + <string>../../../../..</string> + </dict> + <key>IDESourceControlProjectURL</key> + <string>https://github.com/philsquared/Catch.git</string> + <key>IDESourceControlProjectVersion</key> + <integer>111</integer> + <key>IDESourceControlProjectWCCIdentifier</key> + <string>90C00904F36E6ADB57A7313E998815D255B0DEAF</string> + <key>IDESourceControlProjectWCConfigurations</key> + <array> + <dict> + <key>IDESourceControlRepositoryExtensionIdentifierKey</key> + <string>public.vcs.git</string> + <key>IDESourceControlWCCIdentifierKey</key> + <string>90C00904F36E6ADB57A7313E998815D255B0DEAF</string> + <key>IDESourceControlWCCName</key> + <string>Catch-Develop</string> + </dict> + </array> +</dict> +</plist> diff --git a/unittest/Catch/projects/XCode/CatchSelfTest/CatchSelfTestSingle/dummy.txt b/unittest/Catch/projects/XCode/CatchSelfTest/CatchSelfTestSingle/dummy.txt new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/unittest/Catch/projects/XCode/CatchSelfTest/CatchSelfTestSingle/dummy.txt diff --git a/unittest/Catch/projects/XCode/OCTest/OCTest.xcodeproj/project.pbxproj b/unittest/Catch/projects/XCode/OCTest/OCTest.xcodeproj/project.pbxproj new file mode 100644 index 0000000..6777e8e --- /dev/null +++ b/unittest/Catch/projects/XCode/OCTest/OCTest.xcodeproj/project.pbxproj @@ -0,0 +1,265 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 4A63D2AC14E3C1A900F615CB /* OCTest.1 in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4A63D2AB14E3C1A900F615CB /* OCTest.1 */; }; + 4A63D2B314E3C1E600F615CB /* Main.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4A63D2B214E3C1E600F615CB /* Main.mm */; }; + 4A63D2C014E4544700F615CB /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4A63D2BF14E4544700F615CB /* Foundation.framework */; }; + 4A63D2C614E454CC00F615CB /* CatchOCTestCase.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4A63D2C214E454CC00F615CB /* CatchOCTestCase.mm */; }; + 4A63D2C714E454CC00F615CB /* OCTest.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4A63D2C314E454CC00F615CB /* OCTest.mm */; }; + 4A63D2C814E454CC00F615CB /* TestObj.m in Sources */ = {isa = PBXBuildFile; fileRef = 4A63D2C514E454CC00F615CB /* TestObj.m */; }; +/* End PBXBuildFile section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 4A63D2A314E3C1A900F615CB /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = /usr/share/man/man1/; + dstSubfolderSpec = 0; + files = ( + 4A63D2AC14E3C1A900F615CB /* OCTest.1 in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 1; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 4A63D2A514E3C1A900F615CB /* OCTest */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = OCTest; sourceTree = BUILT_PRODUCTS_DIR; }; + 4A63D2AB14E3C1A900F615CB /* OCTest.1 */ = {isa = PBXFileReference; lastKnownFileType = text.man; path = OCTest.1; sourceTree = "<group>"; }; + 4A63D2B214E3C1E600F615CB /* Main.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = Main.mm; sourceTree = "<group>"; }; + 4A63D2BF14E4544700F615CB /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; + 4A63D2C114E454CC00F615CB /* CatchOCTestCase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CatchOCTestCase.h; sourceTree = "<group>"; }; + 4A63D2C214E454CC00F615CB /* CatchOCTestCase.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = CatchOCTestCase.mm; sourceTree = "<group>"; }; + 4A63D2C314E454CC00F615CB /* OCTest.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = OCTest.mm; sourceTree = "<group>"; }; + 4A63D2C414E454CC00F615CB /* TestObj.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TestObj.h; sourceTree = "<group>"; }; + 4A63D2C514E454CC00F615CB /* TestObj.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TestObj.m; sourceTree = "<group>"; }; + 4AA0D951154C0A7A004B4193 /* catch_objc.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = catch_objc.hpp; path = ../../../include/internal/catch_objc.hpp; sourceTree = "<group>"; }; + 4ABEA80615C90E10009F0424 /* catch_objc_arc.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = catch_objc_arc.hpp; path = ../../../include/internal/catch_objc_arc.hpp; sourceTree = "<group>"; }; + 4ABEA80815C90E38009F0424 /* catch_tostring.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = catch_tostring.hpp; path = ../../../include/internal/catch_tostring.hpp; sourceTree = "<group>"; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 4A63D2A214E3C1A900F615CB /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 4A63D2C014E4544700F615CB /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 4A63D29A14E3C1A900F615CB = { + isa = PBXGroup; + children = ( + 4AA0D94F154C0A63004B4193 /* Catch */, + 4A63D2BF14E4544700F615CB /* Foundation.framework */, + 4A63D2A814E3C1A900F615CB /* OCTest */, + 4A63D2A614E3C1A900F615CB /* Products */, + ); + sourceTree = "<group>"; + }; + 4A63D2A614E3C1A900F615CB /* Products */ = { + isa = PBXGroup; + children = ( + 4A63D2A514E3C1A900F615CB /* OCTest */, + ); + name = Products; + sourceTree = "<group>"; + }; + 4A63D2A814E3C1A900F615CB /* OCTest */ = { + isa = PBXGroup; + children = ( + 4A63D2C114E454CC00F615CB /* CatchOCTestCase.h */, + 4A63D2C214E454CC00F615CB /* CatchOCTestCase.mm */, + 4A63D2C314E454CC00F615CB /* OCTest.mm */, + 4A63D2C414E454CC00F615CB /* TestObj.h */, + 4A63D2C514E454CC00F615CB /* TestObj.m */, + 4A63D2B214E3C1E600F615CB /* Main.mm */, + 4A63D2AB14E3C1A900F615CB /* OCTest.1 */, + ); + path = OCTest; + sourceTree = "<group>"; + }; + 4AA0D94F154C0A63004B4193 /* Catch */ = { + isa = PBXGroup; + children = ( + 4ABEA80815C90E38009F0424 /* catch_tostring.hpp */, + 4ABEA80615C90E10009F0424 /* catch_objc_arc.hpp */, + 4AA0D951154C0A7A004B4193 /* catch_objc.hpp */, + ); + name = Catch; + sourceTree = "<group>"; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 4A63D2A414E3C1A900F615CB /* OCTest */ = { + isa = PBXNativeTarget; + buildConfigurationList = 4A63D2AF14E3C1A900F615CB /* Build configuration list for PBXNativeTarget "OCTest" */; + buildPhases = ( + 4A63D2A114E3C1A900F615CB /* Sources */, + 4A63D2A214E3C1A900F615CB /* Frameworks */, + 4A63D2A314E3C1A900F615CB /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = OCTest; + productName = OCTest; + productReference = 4A63D2A514E3C1A900F615CB /* OCTest */; + productType = "com.apple.product-type.tool"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 4A63D29C14E3C1A900F615CB /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0500; + }; + buildConfigurationList = 4A63D29F14E3C1A900F615CB /* Build configuration list for PBXProject "OCTest" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + ); + mainGroup = 4A63D29A14E3C1A900F615CB; + productRefGroup = 4A63D2A614E3C1A900F615CB /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 4A63D2A414E3C1A900F615CB /* OCTest */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXSourcesBuildPhase section */ + 4A63D2A114E3C1A900F615CB /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 4A63D2B314E3C1E600F615CB /* Main.mm in Sources */, + 4A63D2C614E454CC00F615CB /* CatchOCTestCase.mm in Sources */, + 4A63D2C714E454CC00F615CB /* OCTest.mm in Sources */, + 4A63D2C814E454CC00F615CB /* TestObj.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + 4A63D2AD14E3C1A900F615CB /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_ENABLE_OBJC_EXCEPTIONS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_VERSION = com.apple.compilers.llvm.clang.1_0; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + HEADER_SEARCH_PATHS = ../../../include; + MACOSX_DEPLOYMENT_TARGET = 10.7; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + }; + name = Debug; + }; + 4A63D2AE14E3C1A900F615CB /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = YES; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_ENABLE_OBJC_EXCEPTIONS = YES; + GCC_VERSION = com.apple.compilers.llvm.clang.1_0; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + HEADER_SEARCH_PATHS = ../../../include; + MACOSX_DEPLOYMENT_TARGET = 10.7; + SDKROOT = macosx; + }; + name = Release; + }; + 4A63D2B014E3C1A900F615CB /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ENABLE_OBJC_ARC = YES; + HEADER_SEARCH_PATHS = ../../../include; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 4A63D2B114E3C1A900F615CB /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ENABLE_OBJC_ARC = YES; + HEADER_SEARCH_PATHS = ../../../include; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 4A63D29F14E3C1A900F615CB /* Build configuration list for PBXProject "OCTest" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 4A63D2AD14E3C1A900F615CB /* Debug */, + 4A63D2AE14E3C1A900F615CB /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 4A63D2AF14E3C1A900F615CB /* Build configuration list for PBXNativeTarget "OCTest" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 4A63D2B014E3C1A900F615CB /* Debug */, + 4A63D2B114E3C1A900F615CB /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 4A63D29C14E3C1A900F615CB /* Project object */; +} diff --git a/unittest/Catch/projects/XCode/OCTest/OCTest.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/unittest/Catch/projects/XCode/OCTest/OCTest.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..119e61c --- /dev/null +++ b/unittest/Catch/projects/XCode/OCTest/OCTest.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="UTF-8"?> +<Workspace + version = "1.0"> + <FileRef + location = "self:OCTest.xcodeproj"> + </FileRef> +</Workspace> diff --git a/unittest/Catch/projects/XCode/OCTest/OCTest.xcodeproj/project.xcworkspace/xcshareddata/OCTest.xccheckout b/unittest/Catch/projects/XCode/OCTest/OCTest.xcodeproj/project.xcworkspace/xcshareddata/OCTest.xccheckout new file mode 100644 index 0000000..2480364 --- /dev/null +++ b/unittest/Catch/projects/XCode/OCTest/OCTest.xcodeproj/project.xcworkspace/xcshareddata/OCTest.xccheckout @@ -0,0 +1,41 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<dict> + <key>IDESourceControlProjectFavoriteDictionaryKey</key> + <false/> + <key>IDESourceControlProjectIdentifier</key> + <string>2F99C19E-ADF6-4D99-86C7-7A7830677E7D</string> + <key>IDESourceControlProjectName</key> + <string>OCTest</string> + <key>IDESourceControlProjectOriginsDictionary</key> + <dict> + <key>DE66138E-2FC7-4C1B-9901-82CBF6694223</key> + <string>ssh://github.com/philsquared/Catch.git</string> + </dict> + <key>IDESourceControlProjectPath</key> + <string>projects/XCode4/OCTest/OCTest.xcodeproj/project.xcworkspace</string> + <key>IDESourceControlProjectRelativeInstallPathDictionary</key> + <dict> + <key>DE66138E-2FC7-4C1B-9901-82CBF6694223</key> + <string>../../../../..</string> + </dict> + <key>IDESourceControlProjectURL</key> + <string>ssh://github.com/philsquared/Catch.git</string> + <key>IDESourceControlProjectVersion</key> + <integer>110</integer> + <key>IDESourceControlProjectWCCIdentifier</key> + <string>DE66138E-2FC7-4C1B-9901-82CBF6694223</string> + <key>IDESourceControlProjectWCConfigurations</key> + <array> + <dict> + <key>IDESourceControlRepositoryExtensionIdentifierKey</key> + <string>public.vcs.git</string> + <key>IDESourceControlWCCIdentifierKey</key> + <string>DE66138E-2FC7-4C1B-9901-82CBF6694223</string> + <key>IDESourceControlWCCName</key> + <string>Catch</string> + </dict> + </array> +</dict> +</plist> diff --git a/unittest/Catch/projects/XCode/OCTest/OCTest/CatchOCTestCase.h b/unittest/Catch/projects/XCode/OCTest/OCTest/CatchOCTestCase.h new file mode 100644 index 0000000..bd26239 --- /dev/null +++ b/unittest/Catch/projects/XCode/OCTest/OCTest/CatchOCTestCase.h @@ -0,0 +1,25 @@ +// +// CatchOCTestCase.h +// OCTest +// +// Created by Phil on 13/11/2010. +// Copyright 2010 Two Blue Cubes Ltd. All rights reserved. +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +#ifndef TWOBLUECUBES_CATCHOCTESTCASE_H_INCLUDED +#define TWOBLUECUBES_CATCHOCTESTCASE_H_INCLUDED + +#include "catch.hpp" + +#import <Cocoa/Cocoa.h> +#import "TestObj.h" + +@interface TestFixture : NSObject <OcFixture> +{ + TestObj* obj; +} + +@end + +#endif // TWOBLUECUBES_CATCHOCTESTCASE_H_INCLUDED diff --git a/unittest/Catch/projects/XCode/OCTest/OCTest/CatchOCTestCase.mm b/unittest/Catch/projects/XCode/OCTest/OCTest/CatchOCTestCase.mm new file mode 100644 index 0000000..fb20287 --- /dev/null +++ b/unittest/Catch/projects/XCode/OCTest/OCTest/CatchOCTestCase.mm @@ -0,0 +1,83 @@ +// +// CatchOCTestCase.mm +// OCTest +// +// Created by Phil Nash on 13/11/2010. +// Copyright 2010 Two Blue Cubes Ltd. All rights reserved. +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#import "CatchOCTestCase.h" + + +@implementation TestFixture + + +-(void) setUp +{ + obj = [[TestObj alloc] init]; +} + +-(void) tearDown +{ + arcSafeRelease( obj ); +} + +OC_TEST_CASE( "OCTest/test1", "This is a test case" ) +{ + REQUIRE( obj.int_val == 0 ); + + obj.int_val = 1; + + REQUIRE( obj.int_val == 1 ); +} + +OC_TEST_CASE( "OCTest/test2", "This is another test case" ) +{ + REQUIRE( obj.int_val == 0 ); + + obj.int_val = 2; + + REQUIRE( obj.int_val == 2 ); +} + +OC_TEST_CASE( "OCTest/BOOL", "tests a boolean value" ) +{ + CHECK( [obj isTrue] == NO ); + CHECK( [obj isFalse] == YES ); +} + +OC_TEST_CASE( "OCTest/throws/objc", "throws an Objective-C exception" ) +{ + @throw [[NSException alloc] initWithName: NSGenericException + reason: @"Objective-C exception" + userInfo: nil]; +} +OC_TEST_CASE( "OCTest/throws/stdc++", "throws a std c++ exception" ) +{ + throw std::domain_error( "std C++ exception" ); +} + +/////////////////////////////////////////////////////////////////////////// +template<typename T> +void useObject( const T& object ){} + +template<typename T> +void useObject( const T* object ){} + +OC_TEST_CASE( "OCTest/matchers", "Matches work with OC types (NSString so far)" ) +{ + REQUIRE_THAT( @"This is a string", Equals( @"This isnt a string" ) ); + REQUIRE_THAT( @"This is a string", Contains( @"is a" ) ); + REQUIRE_THAT( @"This is a string", StartsWith( @"This" ) ); + REQUIRE_THAT( @"This is a string", EndsWith( @"string" ) ); +} + +OC_TEST_CASE( "OCTest/matchers/nil", "nil NSString should not crash the test" ) +{ + CHECK_THAT( (NSString*)nil, Equals( @"This should fail, but not crash" ) ); + CHECK_THAT( (NSString*)nil, StartsWith( @"anything" ) ); +} + +@end diff --git a/unittest/Catch/projects/XCode/OCTest/OCTest/Main.mm b/unittest/Catch/projects/XCode/OCTest/OCTest/Main.mm new file mode 100644 index 0000000..569dc4d --- /dev/null +++ b/unittest/Catch/projects/XCode/OCTest/OCTest/Main.mm @@ -0,0 +1,2 @@ +#define CATCH_CONFIG_MAIN +#import "catch.hpp" diff --git a/unittest/Catch/projects/XCode/OCTest/OCTest/OCTest.1 b/unittest/Catch/projects/XCode/OCTest/OCTest/OCTest.1 new file mode 100644 index 0000000..7915d02 --- /dev/null +++ b/unittest/Catch/projects/XCode/OCTest/OCTest/OCTest.1 @@ -0,0 +1,79 @@ +.\"Modified from man(1) of FreeBSD, the NetBSD mdoc.template, and mdoc.samples. +.\"See Also: +.\"man mdoc.samples for a complete listing of options +.\"man mdoc for the short list of editing options +.\"/usr/share/misc/mdoc.template +.Dd 09/02/2012 \" DATE +.Dt OCTest 1 \" Program name and manual section number +.Os Darwin +.Sh NAME \" Section Header - required - don't modify +.Nm OCTest, +.\" The following lines are read in generating the apropos(man -k) database. Use only key +.\" words here as the database is built based on the words here and in the .ND line. +.Nm Other_name_for_same_program(), +.Nm Yet another name for the same program. +.\" Use .Nm macro to designate other names for the documented program. +.Nd This line parsed for whatis database. +.Sh SYNOPSIS \" Section Header - required - don't modify +.Nm +.Op Fl abcd \" [-abcd] +.Op Fl a Ar path \" [-a path] +.Op Ar file \" [file] +.Op Ar \" [file ...] +.Ar arg0 \" Underlined argument - use .Ar anywhere to underline +arg2 ... \" Arguments +.Sh DESCRIPTION \" Section Header - required - don't modify +Use the .Nm macro to refer to your program throughout the man page like such: +.Nm +Underlining is accomplished with the .Ar macro like this: +.Ar underlined text . +.Pp \" Inserts a space +A list of items with descriptions: +.Bl -tag -width -indent \" Begins a tagged list +.It item a \" Each item preceded by .It macro +Description of item a +.It item b +Description of item b +.El \" Ends the list +.Pp +A list of flags and their descriptions: +.Bl -tag -width -indent \" Differs from above in tag removed +.It Fl a \"-a flag as a list item +Description of -a flag +.It Fl b +Description of -b flag +.El \" Ends the list +.Pp +.\" .Sh ENVIRONMENT \" May not be needed +.\" .Bl -tag -width "ENV_VAR_1" -indent \" ENV_VAR_1 is width of the string ENV_VAR_1 +.\" .It Ev ENV_VAR_1 +.\" Description of ENV_VAR_1 +.\" .It Ev ENV_VAR_2 +.\" Description of ENV_VAR_2 +.\" .El +.Sh FILES \" File used or created by the topic of the man page +.Bl -tag -width "/Users/joeuser/Library/really_long_file_name" -compact +.It Pa /usr/share/file_name +FILE_1 description +.It Pa /Users/joeuser/Library/really_long_file_name +FILE_2 description +.El \" Ends the list +.\" .Sh DIAGNOSTICS \" May not be needed +.\" .Bl -diag +.\" .It Diagnostic Tag +.\" Diagnostic informtion here. +.\" .It Diagnostic Tag +.\" Diagnostic informtion here. +.\" .El +.Sh SEE ALSO +.\" List links in ascending order by section, alphabetically within a section. +.\" Please do not reference files that do not exist without filing a bug report +.Xr a 1 , +.Xr b 1 , +.Xr c 1 , +.Xr a 2 , +.Xr b 2 , +.Xr a 3 , +.Xr b 3 +.\" .Sh BUGS \" Document known, unremedied bugs +.\" .Sh HISTORY \" Document history if command behaves in a unique manner
\ No newline at end of file diff --git a/unittest/Catch/projects/XCode/OCTest/OCTest/OCTest.mm b/unittest/Catch/projects/XCode/OCTest/OCTest/OCTest.mm new file mode 100644 index 0000000..bfb2ca2 --- /dev/null +++ b/unittest/Catch/projects/XCode/OCTest/OCTest/OCTest.mm @@ -0,0 +1,28 @@ +/* + * OCTest.mm + * OCTest + * + * Created by Phil on 13/11/2010. + * Copyright 2010 Two Blue Cubes Ltd. All rights reserved. + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + * + */ + +#import "catch.hpp" + +#import "TestObj.h" + +TEST_CASE( "OCTest/TestObj", "tests TestObj" ) +{ + TestObj* obj = [[TestObj alloc] init]; + + REQUIRE( obj.int_val == 0 ); + + obj.int_val = 1; + + REQUIRE( obj.int_val == 1 ); + + arcSafeRelease( obj ); +} diff --git a/unittest/Catch/projects/XCode/OCTest/OCTest/TestObj.h b/unittest/Catch/projects/XCode/OCTest/OCTest/TestObj.h new file mode 100644 index 0000000..8443921 --- /dev/null +++ b/unittest/Catch/projects/XCode/OCTest/OCTest/TestObj.h @@ -0,0 +1,28 @@ +// +// TestObj.h +// OCTest +// +// Created by Phil on 13/11/2010. +// Copyright 2010 Two Blue Cubes Ltd. All rights reserved. +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +#ifndef TWOBLUECUBES_TESTOBJ_H_INCLUDED +#define TWOBLUECUBES_TESTOBJ_H_INCLUDED + +#import <Foundation/Foundation.h> + + +@interface TestObj : NSObject { + + int int_val; +} + +-(BOOL) isTrue; +-(BOOL) isFalse; + +@property (nonatomic, assign ) int int_val; + +@end + +#endif // TWOBLUECUBES_TESTOBJ_H_INCLUDED diff --git a/unittest/Catch/projects/XCode/OCTest/OCTest/TestObj.m b/unittest/Catch/projects/XCode/OCTest/OCTest/TestObj.m new file mode 100644 index 0000000..2c7dc99 --- /dev/null +++ b/unittest/Catch/projects/XCode/OCTest/OCTest/TestObj.m @@ -0,0 +1,25 @@ +// +// TestObj.m +// OCTest +// +// Created by Phil on 13/11/2010. +// Copyright 2010 Two Blue Cubes Ltd. All rights reserved. +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#import "TestObj.h" + + +@implementation TestObj + +@synthesize int_val; + +-(BOOL) isTrue { + return YES; +} +-(BOOL) isFalse { + return NO; +} + +@end diff --git a/unittest/Catch/projects/XCode/iOSTest/iOSTest.xcodeproj/project.pbxproj b/unittest/Catch/projects/XCode/iOSTest/iOSTest.xcodeproj/project.pbxproj new file mode 100644 index 0000000..e968cf6 --- /dev/null +++ b/unittest/Catch/projects/XCode/iOSTest/iOSTest.xcodeproj/project.pbxproj @@ -0,0 +1,299 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 4A73280A14E66CFC0044823F /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4A73280914E66CFC0044823F /* UIKit.framework */; }; + 4A73280C14E66CFC0044823F /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4A73280B14E66CFC0044823F /* Foundation.framework */; }; + 4A73280E14E66CFC0044823F /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4A73280D14E66CFC0044823F /* CoreGraphics.framework */; }; + 4A73281414E66CFC0044823F /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 4A73281214E66CFC0044823F /* InfoPlist.strings */; }; + 4A73282614E66D8B0044823F /* itChRunnerMain.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4A73282514E66D8B0044823F /* itChRunnerMain.mm */; }; + 4AB1C74F14FCC74900F31DF7 /* OCTest.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4AB1C74C14FCC74900F31DF7 /* OCTest.mm */; }; + 4AB1C75014FCC74900F31DF7 /* TestObj.m in Sources */ = {isa = PBXBuildFile; fileRef = 4AB1C74E14FCC74900F31DF7 /* TestObj.m */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 4A73280514E66CFC0044823F /* iOSTest.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = iOSTest.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 4A73280914E66CFC0044823F /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; + 4A73280B14E66CFC0044823F /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; + 4A73280D14E66CFC0044823F /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; + 4A73281114E66CFC0044823F /* iOSTest-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "iOSTest-Info.plist"; sourceTree = "<group>"; }; + 4A73281314E66CFC0044823F /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = "<group>"; }; + 4A73281714E66CFC0044823F /* iOSTest-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "iOSTest-Prefix.pch"; sourceTree = "<group>"; }; + 4A73282214E66D8B0044823F /* iTchRunnerAppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = iTchRunnerAppDelegate.h; sourceTree = "<group>"; }; + 4A73282314E66D8B0044823F /* iTchRunnerMainView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = iTchRunnerMainView.h; sourceTree = "<group>"; }; + 4A73282414E66D8B0044823F /* iTchRunnerReporter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = iTchRunnerReporter.h; sourceTree = "<group>"; }; + 4A73282514E66D8B0044823F /* itChRunnerMain.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = itChRunnerMain.mm; path = ../../../runners/iTchRunner/itChRunnerMain.mm; sourceTree = "<group>"; }; + 4AB1C74C14FCC74900F31DF7 /* OCTest.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = OCTest.mm; sourceTree = "<group>"; }; + 4AB1C74D14FCC74900F31DF7 /* TestObj.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TestObj.h; sourceTree = "<group>"; }; + 4AB1C74E14FCC74900F31DF7 /* TestObj.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TestObj.m; sourceTree = "<group>"; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 4A73280214E66CFC0044823F /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 4A73280A14E66CFC0044823F /* UIKit.framework in Frameworks */, + 4A73280C14E66CFC0044823F /* Foundation.framework in Frameworks */, + 4A73280E14E66CFC0044823F /* CoreGraphics.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 4A7327FA14E66CFC0044823F = { + isa = PBXGroup; + children = ( + 4A73280F14E66CFC0044823F /* iOSTest */, + 4A73280814E66CFC0044823F /* Frameworks */, + 4A73280614E66CFC0044823F /* Products */, + ); + sourceTree = "<group>"; + }; + 4A73280614E66CFC0044823F /* Products */ = { + isa = PBXGroup; + children = ( + 4A73280514E66CFC0044823F /* iOSTest.app */, + ); + name = Products; + sourceTree = "<group>"; + }; + 4A73280814E66CFC0044823F /* Frameworks */ = { + isa = PBXGroup; + children = ( + 4A73280914E66CFC0044823F /* UIKit.framework */, + 4A73280B14E66CFC0044823F /* Foundation.framework */, + 4A73280D14E66CFC0044823F /* CoreGraphics.framework */, + ); + name = Frameworks; + sourceTree = "<group>"; + }; + 4A73280F14E66CFC0044823F /* iOSTest */ = { + isa = PBXGroup; + children = ( + 4A73282014E66D6C0044823F /* iTch */, + 4A73281014E66CFC0044823F /* Supporting Files */, + ); + path = iOSTest; + sourceTree = "<group>"; + }; + 4A73281014E66CFC0044823F /* Supporting Files */ = { + isa = PBXGroup; + children = ( + 4A73281114E66CFC0044823F /* iOSTest-Info.plist */, + 4A73281214E66CFC0044823F /* InfoPlist.strings */, + 4A73281714E66CFC0044823F /* iOSTest-Prefix.pch */, + ); + name = "Supporting Files"; + sourceTree = "<group>"; + }; + 4A73282014E66D6C0044823F /* iTch */ = { + isa = PBXGroup; + children = ( + 4AB1C74C14FCC74900F31DF7 /* OCTest.mm */, + 4AB1C74D14FCC74900F31DF7 /* TestObj.h */, + 4AB1C74E14FCC74900F31DF7 /* TestObj.m */, + 4A73282114E66D8B0044823F /* internal */, + 4A73282514E66D8B0044823F /* itChRunnerMain.mm */, + ); + name = iTch; + sourceTree = "<group>"; + }; + 4A73282114E66D8B0044823F /* internal */ = { + isa = PBXGroup; + children = ( + 4A73282214E66D8B0044823F /* iTchRunnerAppDelegate.h */, + 4A73282314E66D8B0044823F /* iTchRunnerMainView.h */, + 4A73282414E66D8B0044823F /* iTchRunnerReporter.h */, + ); + name = internal; + path = ../../../runners/iTchRunner/internal; + sourceTree = "<group>"; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 4A73280414E66CFC0044823F /* iOSTest */ = { + isa = PBXNativeTarget; + buildConfigurationList = 4A73281D14E66CFC0044823F /* Build configuration list for PBXNativeTarget "iOSTest" */; + buildPhases = ( + 4A73280114E66CFC0044823F /* Sources */, + 4A73280214E66CFC0044823F /* Frameworks */, + 4A73280314E66CFC0044823F /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = iOSTest; + productName = iOSTest; + productReference = 4A73280514E66CFC0044823F /* iOSTest.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 4A7327FC14E66CFC0044823F /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0420; + }; + buildConfigurationList = 4A7327FF14E66CFC0044823F /* Build configuration list for PBXProject "iOSTest" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + ); + mainGroup = 4A7327FA14E66CFC0044823F; + productRefGroup = 4A73280614E66CFC0044823F /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 4A73280414E66CFC0044823F /* iOSTest */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 4A73280314E66CFC0044823F /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 4A73281414E66CFC0044823F /* InfoPlist.strings in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 4A73280114E66CFC0044823F /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 4A73282614E66D8B0044823F /* itChRunnerMain.mm in Sources */, + 4AB1C74F14FCC74900F31DF7 /* OCTest.mm in Sources */, + 4AB1C75014FCC74900F31DF7 /* TestObj.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 4A73281214E66CFC0044823F /* InfoPlist.strings */ = { + isa = PBXVariantGroup; + children = ( + 4A73281314E66CFC0044823F /* en */, + ); + name = InfoPlist.strings; + sourceTree = "<group>"; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 4A73281B14E66CFC0044823F /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ARCHS = "$(ARCHS_STANDARD_32_BIT)"; + CLANG_ENABLE_OBJC_ARC = YES; + CODE_SIGN_IDENTITY = "iPhone Developer: Phil Nash (4KJCM5XSVL)"; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_VERSION = com.apple.compilers.llvm.clang.1_0; + GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 5.0; + PROVISIONING_PROFILE = "95C4758A-E0B8-4714-9DA3-C7E1284444A4"; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + USER_HEADER_SEARCH_PATHS = ../../../include; + }; + name = Debug; + }; + 4A73281C14E66CFC0044823F /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ARCHS = "$(ARCHS_STANDARD_32_BIT)"; + CLANG_ENABLE_OBJC_ARC = YES; + CODE_SIGN_IDENTITY = "iPhone Developer: Phil Nash (4KJCM5XSVL)"; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_VERSION = com.apple.compilers.llvm.clang.1_0; + GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 5.0; + OTHER_CFLAGS = "-DNS_BLOCK_ASSERTIONS=1"; + PROVISIONING_PROFILE = "95C4758A-E0B8-4714-9DA3-C7E1284444A4"; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + USER_HEADER_SEARCH_PATHS = ../../../include; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 4A73281E14E66CFC0044823F /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "iOSTest/iOSTest-Prefix.pch"; + INFOPLIST_FILE = "iOSTest/iOSTest-Info.plist"; + PRODUCT_NAME = "$(TARGET_NAME)"; + WRAPPER_EXTENSION = app; + }; + name = Debug; + }; + 4A73281F14E66CFC0044823F /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "iOSTest/iOSTest-Prefix.pch"; + INFOPLIST_FILE = "iOSTest/iOSTest-Info.plist"; + PRODUCT_NAME = "$(TARGET_NAME)"; + WRAPPER_EXTENSION = app; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 4A7327FF14E66CFC0044823F /* Build configuration list for PBXProject "iOSTest" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 4A73281B14E66CFC0044823F /* Debug */, + 4A73281C14E66CFC0044823F /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 4A73281D14E66CFC0044823F /* Build configuration list for PBXNativeTarget "iOSTest" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 4A73281E14E66CFC0044823F /* Debug */, + 4A73281F14E66CFC0044823F /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 4A7327FC14E66CFC0044823F /* Project object */; +} diff --git a/unittest/Catch/projects/XCode/iOSTest/iOSTest.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/unittest/Catch/projects/XCode/iOSTest/iOSTest.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..aaadc7d --- /dev/null +++ b/unittest/Catch/projects/XCode/iOSTest/iOSTest.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="UTF-8"?> +<Workspace + version = "1.0"> + <FileRef + location = "self:iOSTest.xcodeproj"> + </FileRef> +</Workspace> diff --git a/unittest/Catch/projects/XCode/iOSTest/iOSTest/OCTest.mm b/unittest/Catch/projects/XCode/iOSTest/iOSTest/OCTest.mm new file mode 100644 index 0000000..d476cb4 --- /dev/null +++ b/unittest/Catch/projects/XCode/iOSTest/iOSTest/OCTest.mm @@ -0,0 +1,27 @@ +/* + * OCTest.mm + * OCTest + * + * Created by Phil on 13/11/2010. + * Copyright 2010 Two Blue Cubes Ltd. All rights reserved. + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + * + */ +#include "catch.hpp" + +#import "TestObj.h" + +TEST_CASE( "OCTest/TestObj", "tests TestObj" ) +{ + TestObj* obj = [[TestObj alloc] init]; + + REQUIRE( obj.int_val == 0 ); + + obj.int_val = 1; + + REQUIRE( obj.int_val == 1 ); + + arcSafeRelease( obj ); +} diff --git a/unittest/Catch/projects/XCode/iOSTest/iOSTest/TestObj.h b/unittest/Catch/projects/XCode/iOSTest/iOSTest/TestObj.h new file mode 100644 index 0000000..de67250 --- /dev/null +++ b/unittest/Catch/projects/XCode/iOSTest/iOSTest/TestObj.h @@ -0,0 +1,25 @@ +// +// TestObj.h +// OCTest +// +// Created by Phil on 13/11/2010. +// Copyright 2010 Two Blue Cubes Ltd. All rights reserved. +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +#ifndef TWOBLUECUBES_TESTOBJ_H_INCLUDED +#define TWOBLUECUBES_TESTOBJ_H_INCLUDED + +#import <Foundation/Foundation.h> + + +@interface TestObj : NSObject { + + int int_val; +} + +@property (nonatomic, assign ) int int_val; + +@end + +#endif // TWOBLUECUBES_TESTOBJ_H_INCLUDED diff --git a/unittest/Catch/projects/XCode/iOSTest/iOSTest/TestObj.m b/unittest/Catch/projects/XCode/iOSTest/iOSTest/TestObj.m new file mode 100644 index 0000000..943f445 --- /dev/null +++ b/unittest/Catch/projects/XCode/iOSTest/iOSTest/TestObj.m @@ -0,0 +1,18 @@ +// +// TestObj.m +// OCTest +// +// Created by Phil on 13/11/2010. +// Copyright 2010 Two Blue Cubes Ltd. All rights reserved. +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#import "TestObj.h" + + +@implementation TestObj + +@synthesize int_val; + +@end diff --git a/unittest/Catch/projects/XCode/iOSTest/iOSTest/en.lproj/InfoPlist.strings b/unittest/Catch/projects/XCode/iOSTest/iOSTest/en.lproj/InfoPlist.strings new file mode 100644 index 0000000..477b28f --- /dev/null +++ b/unittest/Catch/projects/XCode/iOSTest/iOSTest/en.lproj/InfoPlist.strings @@ -0,0 +1,2 @@ +/* Localized versions of Info.plist keys */ + diff --git a/unittest/Catch/projects/XCode/iOSTest/iOSTest/iOSTest-Info.plist b/unittest/Catch/projects/XCode/iOSTest/iOSTest/iOSTest-Info.plist new file mode 100644 index 0000000..f74b6db --- /dev/null +++ b/unittest/Catch/projects/XCode/iOSTest/iOSTest/iOSTest-Info.plist @@ -0,0 +1,47 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<dict> + <key>CFBundleDevelopmentRegion</key> + <string>en</string> + <key>CFBundleDisplayName</key> + <string>${PRODUCT_NAME}</string> + <key>CFBundleExecutable</key> + <string>${EXECUTABLE_NAME}</string> + <key>CFBundleIconFiles</key> + <array/> + <key>CFBundleIdentifier</key> + <string>twobluecubes.${PRODUCT_NAME:rfc1034identifier}</string> + <key>CFBundleInfoDictionaryVersion</key> + <string>6.0</string> + <key>CFBundleName</key> + <string>${PRODUCT_NAME}</string> + <key>CFBundlePackageType</key> + <string>APPL</string> + <key>CFBundleShortVersionString</key> + <string>1.0</string> + <key>CFBundleSignature</key> + <string>????</string> + <key>CFBundleVersion</key> + <string>1.0</string> + <key>LSRequiresIPhoneOS</key> + <true/> + <key>UIRequiredDeviceCapabilities</key> + <array> + <string>armv7</string> + </array> + <key>UISupportedInterfaceOrientations</key> + <array> + <string>UIInterfaceOrientationPortrait</string> + <string>UIInterfaceOrientationLandscapeLeft</string> + <string>UIInterfaceOrientationLandscapeRight</string> + </array> + <key>UISupportedInterfaceOrientations~ipad</key> + <array> + <string>UIInterfaceOrientationPortrait</string> + <string>UIInterfaceOrientationPortraitUpsideDown</string> + <string>UIInterfaceOrientationLandscapeLeft</string> + <string>UIInterfaceOrientationLandscapeRight</string> + </array> +</dict> +</plist> diff --git a/unittest/Catch/projects/XCode/iOSTest/iOSTest/iOSTest-Prefix.pch b/unittest/Catch/projects/XCode/iOSTest/iOSTest/iOSTest-Prefix.pch new file mode 100644 index 0000000..403e8e4 --- /dev/null +++ b/unittest/Catch/projects/XCode/iOSTest/iOSTest/iOSTest-Prefix.pch @@ -0,0 +1,14 @@ +// +// Prefix header for all source files of the 'iOSTest' target in the 'iOSTest' project +// + +#import <Availability.h> + +#ifndef __IPHONE_3_0 +#warning "This project uses features only available in iOS SDK 3.0 and later." +#endif + +#ifdef __OBJC__ + #import <UIKit/UIKit.h> + #import <Foundation/Foundation.h> +#endif diff --git a/unittest/Catch/projects/runners/iTchRunner/internal/iTchRunnerAppDelegate.h b/unittest/Catch/projects/runners/iTchRunner/internal/iTchRunnerAppDelegate.h new file mode 100644 index 0000000..522291a --- /dev/null +++ b/unittest/Catch/projects/runners/iTchRunner/internal/iTchRunnerAppDelegate.h @@ -0,0 +1,114 @@ +/* + * iTchRunnerAppDelegate.h + * iTchRunner + * + * Created by Phil on 07/02/2011. + * Copyright 2011 Two Blue Cubes Ltd. All rights reserved. + * + */ +#ifndef TWOBLUECUBES_ITCHRUNNERAPPDELEGATE_H_INCLUDED +#define TWOBLUECUBES_ITCHRUNNERAPPDELEGATE_H_INCLUDED + +#import "iTchRunnerMainView.h" + + + +@interface iTchRunnerAppDelegate : NSObject <UIApplicationDelegate> +{ + UIWindow *window; +} + +@end + + +@implementation iTchRunnerAppDelegate + + +/////////////////////////////////////////////////////////////////////////////// +- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions +{ + window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; + [window setUserInteractionEnabled:YES]; + [window setMultipleTouchEnabled:YES]; + + CGRect screenRect = [[UIScreen mainScreen] applicationFrame]; + iTchRunnerMainView* view = [[iTchRunnerMainView alloc] initWithFrame:screenRect]; + + [window addSubview:view]; + [window makeKeyAndVisible]; + arcSafeRelease( view ); + + return YES; +} + +/////////////////////////////////////////////////////////////////////////////// +- (void)dealloc +{ +#if !CATCH_ARC_ENABLED + [window release]; + [super dealloc]; +#endif +} + + +/////////////////////////////////////////////////////////////////////////////// +- (void)applicationWillResignActive:(UIApplication *)application +{ + /* + Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. + Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. + */ +} + + +/////////////////////////////////////////////////////////////////////////////// +- (void)applicationDidEnterBackground:(UIApplication *)application +{ + /* + Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. + If your application supports background execution, called instead of applicationWillTerminate: when the user quits. + */ +} + + +/////////////////////////////////////////////////////////////////////////////// +- (void)applicationWillEnterForeground:(UIApplication *)application +{ + /* + Called as part of transition from the background to the inactive state: here you can undo many of the changes made on entering the background. + */ +} + + +/////////////////////////////////////////////////////////////////////////////// +- (void)applicationDidBecomeActive:(UIApplication *)application +{ + /* + Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. + */ +} + + +/////////////////////////////////////////////////////////////////////////////// +- (void)applicationWillTerminate:(UIApplication *)application +{ + /* + Called when the application is about to terminate. + See also applicationDidEnterBackground:. + */ +} + + +/////////////////////////////////////////////////////////////////////////////// +- (void)applicationDidReceiveMemoryWarning:(UIApplication *)application +{ + /* + Free up as much memory as possible by purging cached data objects that can be recreated (or reloaded from disk) later. + */ +} + + + +@end + +#endif // TWOBLUECUBES_ITCHRUNNERAPPDELEGATE_H_INCLUDED diff --git a/unittest/Catch/projects/runners/iTchRunner/internal/iTchRunnerMainView.h b/unittest/Catch/projects/runners/iTchRunner/internal/iTchRunnerMainView.h new file mode 100644 index 0000000..c6a6394 --- /dev/null +++ b/unittest/Catch/projects/runners/iTchRunner/internal/iTchRunnerMainView.h @@ -0,0 +1,189 @@ +/* + * iTchRunnerMainView.h + * iTchRunner + * + * Created by Phil on 07/02/2011. + * Copyright 2011 Two Blue Cubes Ltd. All rights reserved. + * + */ +#ifndef TWOBLUECUBES_ITCHRUNNERMAINVIEW_H_INCLUDED +#define TWOBLUECUBES_ITCHRUNNERMAINVIEW_H_INCLUDED + +#include "internal/catch_config.hpp" +#include "internal/catch_runner_impl.hpp" +#include "internal/catch_context_impl.hpp" +#include "catch.hpp" + +#include "iTchRunnerReporter.h" + +#import <UIKit/UIKit.h> + +@interface iTchRunnerMainView : UIView<iTchRunnerDelegate, UIActionSheetDelegate> +{ + UITextField* appName; +} + +-(void) showAlert; + +@end + +@implementation iTchRunnerMainView + + +/////////////////////////////////////////////////////////////////////////////// +-(id) initWithFrame:(CGRect)frame +{ + if ((self = [super initWithFrame:frame])) + { + // Initialization code + self.backgroundColor = [UIColor blackColor]; + + appName = [[UITextField alloc] initWithFrame: CGRectMake( 0, 50, 320, 50 )]; + [self addSubview: appName]; + arcSafeRelease( appName ); + appName.textColor = [[UIColor alloc] initWithRed:0.35 green:0.35 blue:1 alpha:1]; + arcSafeRelease( appName.textColor ); + appName.textAlignment = NSTextAlignmentCenter; + + appName.text = [NSString stringWithFormat:@"CATCH tests"]; +// [self performSelector: @selector(showAlert) withObject:nil afterDelay:0.1]; + [self performSelectorOnMainThread:@selector(showAlert) withObject:nil waitUntilDone:NO]; + + } + return self; +} + +/////////////////////////////////////////////////////////////////////////////// +-(void) dealloc +{ + [appName removeFromSuperview]; +#if !CATCH_ARC_ENABLED + [super dealloc]; +#endif +} + +/////////////////////////////////////////////////////////////////////////////// +-(void) showAlert +{ + UIActionSheet* menu = [[UIActionSheet alloc] initWithTitle:@"Options" + delegate:self + cancelButtonTitle:nil + destructiveButtonTitle:nil + otherButtonTitles:@"Run all tests", nil]; + [menu showInView: self]; + arcSafeRelease( menu ); + +} + +// This is a copy & paste from Catch::Runner2 to get us bootstrapped (this is due to all be +// replaced anyway) +inline Catch::Totals runTestsForGroup( Catch::RunContext& context, const Catch::TestCaseFilters& filterGroup ) { + using namespace Catch; + Totals totals; + std::vector<TestCase>::const_iterator it = getRegistryHub().getTestCaseRegistry().getAllTests().begin(); + std::vector<TestCase>::const_iterator itEnd = getRegistryHub().getTestCaseRegistry().getAllTests().end(); + int testsRunForGroup = 0; + for(; it != itEnd; ++it ) { + if( filterGroup.shouldInclude( *it ) ) { + testsRunForGroup++; + + if( context.aborting() ) + break; + + totals += context.runTest( *it ); + } + } + if( testsRunForGroup == 0 ) + std::cerr << "\n[No test cases matched with: " << filterGroup.getName() << "]" << std::endl; + return totals; + +} + +/////////////////////////////////////////////////////////////////////////////// +-(void) actionSheet: (UIActionSheet*) sheet clickedButtonAtIndex: (NSInteger) index +{ + Catch::Ptr<Catch::Config> config = new Catch::Config(); + Catch::IReporter* reporter = new Catch::iTchRunnerReporter( self ); + Catch::LegacyReporterAdapter* reporterAdapter = new Catch::LegacyReporterAdapter( reporter ); + Catch::RunContext runner( config.get(), reporterAdapter ); + + + std::vector<Catch::TestCaseFilters> filterGroups; + Catch::TestCaseFilters filterGroup( "" ); + filterGroups.push_back( filterGroup ); + + Catch::Totals totals; + + std::vector<Catch::TestCaseFilters>::const_iterator it = filterGroups.begin(); + std::vector<Catch::TestCaseFilters>::const_iterator itEnd = filterGroups.end(); + + std::size_t groupCount = filterGroups.size(); + std::size_t groupIndex = 0; + for(; it != itEnd && !runner.aborting(); ++it, ++index ) { + runner.testGroupStarting( it->getName(), groupIndex, groupCount ); + totals += runTestsForGroup( runner, *it ); + runner.testGroupEnded( it->getName(), totals, groupIndex, groupCount ); + } + + + if( totals.assertions.failed == 0 ) + { + NSLog( @"no failures" ); + if( totals.assertions.passed > 0 ) + appName.textColor = [[UIColor alloc] initWithRed:0.35 green:1 blue:0.35 alpha:1]; + } + else + { + NSLog( @"%lu failures", totals.assertions.failed ); + appName.textColor = [[UIColor alloc] initWithRed:1 green:0.35 blue:0.35 alpha:1]; + } +} + +/////////////////////////////////////////////////////////////////////////////// +-(void) testWasRun: (const Catch::AssertionResult*) pResultInfo +{ + const Catch::AssertionResult& resultInfo = *pResultInfo; + std::ostringstream oss; + + if( resultInfo.hasExpression() ) + { + oss << resultInfo.getExpression(); + if( resultInfo.isOk() ) + oss << " succeeded"; + else + oss << " failed"; + } + switch( resultInfo.getResultType() ) + { + case Catch::ResultWas::ThrewException: + if( resultInfo.hasExpression() ) + oss << " with unexpected"; + else + oss << "Unexpected"; + oss << " exception with message: '" << resultInfo.getMessage() << "'"; + break; + case Catch::ResultWas::Info: + oss << "info: '" << resultInfo.getMessage() << "'"; + break; + case Catch::ResultWas::Warning: + oss << "warning: '" << resultInfo.getMessage() << "'"; + break; + case Catch::ResultWas::ExplicitFailure: + oss << "failed with message: '" << resultInfo.getMessage() << "'"; + break; + default: + break; + } + + if( resultInfo.hasExpression() ) + { + oss << " for: " << resultInfo.getExpandedExpression(); + } + oss << std::endl; + NSLog( @"%s", oss.str().c_str() ); +} + + +@end + +#endif // TWOBLUECUBES_ITCHRUNNERMAINVIEW_H_INCLUDED diff --git a/unittest/Catch/projects/runners/iTchRunner/internal/iTchRunnerReporter.h b/unittest/Catch/projects/runners/iTchRunner/internal/iTchRunnerReporter.h new file mode 100644 index 0000000..d262886 --- /dev/null +++ b/unittest/Catch/projects/runners/iTchRunner/internal/iTchRunnerReporter.h @@ -0,0 +1,115 @@ +/* + * iTchRunnerReporter.h + * iTchRunner + * + * Created by Phil on 07/02/2011. + * Copyright 2011 Two Blue Cubes Ltd. All rights reserved. + * + */ +#ifndef TWOBLUECUBES_ITCHRUNNERREPORTER_H_INCLUDED +#define TWOBLUECUBES_ITCHRUNNERREPORTER_H_INCLUDED + +#include "catch.hpp" + +@protocol iTchRunnerDelegate + +-(void) testWasRun: (const Catch::AssertionResult*) result; + +@end + +namespace Catch +{ + class iTchRunnerReporter : public SharedImpl<IReporter> + { + public: + /////////////////////////////////////////////////////////////////////////// + iTchRunnerReporter + ( + id<iTchRunnerDelegate> delegate + ) + : m_delegate( delegate ) + { + } + + /////////////////////////////////////////////////////////////////////////// + virtual bool shouldRedirectStdout + () + const + { + return true; + } + + /////////////////////////////////////////////////////////////////////////// + static std::string getDescription + () + { + return "Captures results for iOS runner"; + } + + /////////////////////////////////////////////////////////////////////////// + size_t getSucceeded + () + const + { + return m_totals.assertions.passed; + } + + /////////////////////////////////////////////////////////////////////////// + size_t getFailed + () + const + { + return m_totals.assertions.failed; + } + + /////////////////////////////////////////////////////////////////////////// + void reset() + { + m_totals = Totals(); + } + + private: // IReporter + + /////////////////////////////////////////////////////////////////////////// + virtual void StartTesting + () + {} + + /////////////////////////////////////////////////////////////////////////// + virtual void EndTesting + ( + const Totals& totals + ) + { + m_totals = totals; + } + + /////////////////////////////////////////////////////////////////////////// + virtual void Result + ( + const AssertionResult& result + ) + { + [m_delegate testWasRun: &result]; + } + + /////////////////////////////////////////////////////////////////////////// + // Deliberately unimplemented: + virtual void StartGroup( const std::string& ){} + virtual void EndGroup( const std::string&, const Totals& ){} + virtual void StartTestCase( const TestCaseInfo& ){} + virtual void StartSection( const std::string& sectionName, const std::string& description ) {} + virtual void EndSection( const std::string&, const Counts& ){} + virtual void EndTestCase( const TestCaseInfo&, const Totals&, const std::string&, const std::string& ){} + virtual void Aborted() {} + virtual void NoAssertionsInSection( std::string const& sectionName ) {} + virtual void NoAssertionsInTestCase( std::string const& testName ) {} + + private: + Totals m_totals; + + id<iTchRunnerDelegate> m_delegate; + }; +} + +#endif // TWOBLUECUBES_ITCHRUNNERREPORTER_H_INCLUDED diff --git a/unittest/Catch/projects/runners/iTchRunner/itChRunnerMain.mm b/unittest/Catch/projects/runners/iTchRunner/itChRunnerMain.mm new file mode 100644 index 0000000..cac5fae --- /dev/null +++ b/unittest/Catch/projects/runners/iTchRunner/itChRunnerMain.mm @@ -0,0 +1,27 @@ +// +// iTchRunnerMain.mm +// iTchRunner +// +// Created by Phil on 04/02/2011. +// Copyright Two Blue Cubes Ltd 2011. All rights reserved. +// + +#define CATCH_CONFIG_RUNNER +#include "catch.hpp" +#import "internal/iTchRunnerAppDelegate.h" + +int main(int argc, char *argv[]) +{ +#if !CATCH_ARC_ENABLED + NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; +#endif + + Catch::registerTestMethods(); + int retVal = UIApplicationMain(argc, argv, nil, @"iTchRunnerAppDelegate"); + +#if !CATCH_ARC_ENABLED + [pool release]; +#endif + + return retVal; +} diff --git a/unittest/Catch/projects/runners/iTchRunner/readme b/unittest/Catch/projects/runners/iTchRunner/readme new file mode 100644 index 0000000..2b25491 --- /dev/null +++ b/unittest/Catch/projects/runners/iTchRunner/readme @@ -0,0 +1,6 @@ +* Select Project -> New Target. Select Cocoa Touch -> Application. Click next and name it something like "Unit Tests" +* While the target info is displayed, find: 'User Header Search Paths' and add a path to the Catch folder +* Open the plist file for the target (Unit Test-Info.plist, if you used that name). Delete the entry for "Main nib file base name: MainWindow" +* From the overview drop-down select the new target. +* Add the file Catch/Runner/iTchRunnerMain.mm into your project - but only in the new target +* Write tests (adding files under test into the target as necessary)
\ No newline at end of file diff --git a/unittest/Catch/scripts/approvalTests.py b/unittest/Catch/scripts/approvalTests.py new file mode 100644 index 0000000..618812f --- /dev/null +++ b/unittest/Catch/scripts/approvalTests.py @@ -0,0 +1,115 @@ +from __future__ import print_function + +import os +import sys +import subprocess +import re + +from scriptCommon import catchPath + +rootPath = os.path.join( catchPath, 'projects/SelfTest/Baselines' ) + +filenameParser = re.compile( r'(.*)/(.*\..pp:)(.*)' ) +filelineParser = re.compile( r'(.*\..pp:)([0-9]*)(.*)' ) +pathParser = re.compile( r'(.*?)/(.*\..pp)(.*)' ) +lineNumberParser = re.compile( r'(.*)line="[0-9]*"(.*)' ) +hexParser = re.compile( r'(.*)\b(0[xX][0-9a-fA-F]+)\b(.*)' ) +durationsParser = re.compile( r'(.*)time="[0-9]*\.[0-9]*"(.*)' ) +versionParser = re.compile( r'(.*?)Catch v[0-9]*\.[0-9]*\.[0-9]*(.*)' ) +devVersionParser = re.compile( r'(.*?)Catch v[0-9]*\.[0-9]*\.[0-9]*-develop\.[0-9]*(.*)' ) + +if len(sys.argv) == 2: + cmdPath = sys.argv[1] +else: + cmdPath = os.path.join( catchPath, 'projects/XCode/CatchSelfTest/DerivedData/CatchSelfTest/Build/Products/Debug/CatchSelfTest' ) + +overallResult = 0 + +def filterLine( line ): + m = filenameParser.match( line ) + if m: + line = m.group(2) + m.group(3) + m2 = filelineParser.match( line ) + if m2: + line = m2.group(1) + "<line number>" + m2.group(3) + else: + m2 = lineNumberParser.match( line ) + if m2: + line = m2.group(1) + m2.group(2) + m = pathParser.match( line ) + if m: + path = "/" + m.group(2) + if path.startswith( catchPath ): + path = path[1+len(catchPath):] + line = m.group(1) + path + m.group(3) + m = devVersionParser.match( line ) + if m: + line = m.group(1) + "<version>" + m.group(2) + else: + m = versionParser.match( line ) + if m: + line = m.group(1) + "<version>" + m.group(2) + + while True: + m = hexParser.match( line ) + if m: + line = m.group(1) + "0x<hex digits>" + m.group(3) + else: + break + m = durationsParser.match( line ) + if m: + line = m.group(1) + 'time="{duration}"' + m.group(2) + return line + +def approve( baseName, args ): + global overallResult + args[0:0] = [cmdPath] + if not os.path.exists( cmdPath ): + raise Exception( "Executable doesn't exist at " + cmdPath ) + baselinesPath = os.path.join( rootPath, '{0}.approved.txt'.format( baseName ) ) + rawResultsPath = os.path.join( rootPath, '_{0}.tmp'.format( baseName ) ) + filteredResultsPath = os.path.join( rootPath, '{0}.unapproved.txt'.format( baseName ) ) + + f = open( rawResultsPath, 'w' ) + subprocess.call( args, stdout=f, stderr=f ) + f.close() + + rawFile = open( rawResultsPath, 'r' ) + filteredFile = open( filteredResultsPath, 'w' ) + for line in rawFile: + filteredFile.write( filterLine( line ).rstrip() + "\n" ) + filteredFile.close() + rawFile.close() + + os.remove( rawResultsPath ) + print() + print( baseName + ":" ) + if os.path.exists( baselinesPath ): + diffResult = subprocess.call([ "diff", baselinesPath, filteredResultsPath ] ) + if diffResult == 0: + os.remove( filteredResultsPath ) + print( " \033[92mResults matched" ) + else: + print( " \n****************************\n \033[91mResults differed" ) + if diffResult > overallResult: + overallResult = diffResult + print( "\033[0m" ) + else: + print( " first approval" ) + if overallResult == 0: + overallResult = 1 + +# Standard console reporter +approve( "console.std", ["~_"] ) +# console reporter, include passes, warn about No Assertions +approve( "console.sw", ["~_", "-s", "-w", "NoAssertions"] ) +# console reporter, include passes, warn about No Assertions, limit failures to first 4 +approve( "console.swa4", ["~_", "-s", "-w", "NoAssertions", "-x", "4"] ) +# junit reporter, include passes, warn about No Assertions +approve( "junit.sw", ["~_", "-s", "-w", "NoAssertions", "-r", "junit"] ) +# xml reporter, include passes, warn about No Assertions +approve( "xml.sw", ["~_", "-s", "-w", "NoAssertions", "-r", "xml"] ) + +if overallResult != 0: + print( "run approve.py to approve new baselines" ) +exit( overallResult) diff --git a/unittest/Catch/scripts/approve.py b/unittest/Catch/scripts/approve.py new file mode 100644 index 0000000..f4b66aa --- /dev/null +++ b/unittest/Catch/scripts/approve.py @@ -0,0 +1,31 @@ +from __future__ import print_function + +import os +import sys +import shutil +import glob +from scriptCommon import catchPath + +rootPath = os.path.join( catchPath, 'projects/SelfTest/Baselines' ) + +if len(sys.argv) > 1: + files = [os.path.join( rootPath, f ) for f in sys.argv[1:]] +else: + files = glob.glob( os.path.join( rootPath, "*.unapproved.txt" ) ) + + +def approveFile( approvedFile, unapprovedFile ): + justFilename = unapprovedFile[len(rootPath)+1:] + if os.path.exists( unapprovedFile ): + if os.path.exists( approvedFile ): + os.remove( approvedFile ) + os.rename( unapprovedFile, approvedFile ) + print( "approved " + justFilename ) + else: + print( "approval file " + justFilename + " does not exist" ) + +if len(files) > 0: + for unapprovedFile in files: + approveFile( unapprovedFile.replace( "unapproved.txt", "approved.txt" ), unapprovedFile ) +else: + print( "no files to approve" ) diff --git a/unittest/Catch/scripts/developBuild.py b/unittest/Catch/scripts/developBuild.py new file mode 100644 index 0000000..c244871 --- /dev/null +++ b/unittest/Catch/scripts/developBuild.py @@ -0,0 +1,9 @@ +from __future__ import print_function +from releaseCommon import Version + +v = Version() +v.incrementBuildNumber() +v.updateVersionFile() +v.updateReadmeFile() + +print( "Updated Version.hpp and README to v{0}".format( v.getVersionString() ) )
\ No newline at end of file diff --git a/unittest/Catch/scripts/fixTrailingWhitespace.py b/unittest/Catch/scripts/fixTrailingWhitespace.py new file mode 100644 index 0000000..a1b6bbe --- /dev/null +++ b/unittest/Catch/scripts/fixTrailingWhitespace.py @@ -0,0 +1,46 @@ +from __future__ import print_function +import os +from scriptCommon import catchPath + +changedFiles = 0 + +def isSourceFile( path ): + return path.endswith( ".cpp" ) or path.endswith( ".h" ) or path.endswith( ".hpp" ) + +def fixAllFilesInDir( dir ): + for f in os.listdir( dir ): + path = os.path.join( dir,f ) + if os.path.isfile( path ): + if isSourceFile( path ): + fixFile( path ) + else: + fixAllFilesInDir( path ) + +def fixFile( path ): + f = open( path, 'r' ) + lines = [] + changed = 0 + for line in f: + trimmed = line.rstrip() + "\n" + if trimmed != line: + changed = changed +1 + lines.append( trimmed ) + f.close() + if changed > 0: + global changedFiles + changedFiles = changedFiles + 1 + print( path + ":" ) + print( " - fixed " + str(changed) + " line(s)" ) + altPath = path + ".backup" + os.rename( path, altPath ) + f2 = open( path, 'w' ) + for line in lines: + f2.write( line ) + f2.close() + os.remove( altPath ) + +fixAllFilesInDir(catchPath) +if changedFiles > 0: + print( "Fixed " + str(changedFiles) + " file(s)" ) +else: + print( "No trailing whitespace found" ) diff --git a/unittest/Catch/scripts/generateSingleHeader.py b/unittest/Catch/scripts/generateSingleHeader.py new file mode 100644 index 0000000..419633f --- /dev/null +++ b/unittest/Catch/scripts/generateSingleHeader.py @@ -0,0 +1,103 @@ +from __future__ import print_function + +import os +import sys +import re +import datetime +import string + +from scriptCommon import catchPath +from releaseCommon import Version + + +includesParser = re.compile( r'\s*#include\s*"(.*)"' ) +guardParser = re.compile( r'\s*#.*TWOBLUECUBES_CATCH_.*_INCLUDED') +defineParser = re.compile( r'\s*#define') +ifParser = re.compile( r'\s*#ifndef TWOBLUECUBES_CATCH_.*_INCLUDED') +endIfParser = re.compile( r'\s*#endif // TWOBLUECUBES_CATCH_.*_INCLUDED') +ifImplParser = re.compile( r'\s*#ifdef CATCH_CONFIG_RUNNER' ) +commentParser1 = re.compile( r'^\s*/\*') +commentParser2 = re.compile( r'^ \*') +blankParser = re.compile( r'^\s*$') +seenHeaders = set([]) +rootPath = os.path.join( catchPath, 'include/' ) +outputPath = os.path.join( catchPath, 'single_include/catch.hpp' ) + +includeImpl = True + +for arg in sys.argv[1:]: + arg = string.lower(arg) + if arg == "noimpl": + includeImpl = False + print( "Not including impl code" ) + else: + print( "\n** Unrecognised argument: " + arg + " **\n" ) + exit(1) + +out = open( outputPath, 'w' ) +ifdefs = 0 +implIfDefs = -1 + +def write( line ): + if includeImpl or implIfDefs == -1: + out.write( line ) + +def parseFile( path, filename ): + global ifdefs + global implIfDefs + + f = open( path + filename, 'r' ) + blanks = 0 + for line in f: + if ifParser.match( line ): + ifdefs = ifdefs + 1 + elif endIfParser.match( line ): + ifdefs = ifdefs - 1 + if ifdefs == implIfDefs: + implIfDefs = -1 + m = includesParser.match( line ) + if m: + header = m.group(1) + headerPath, sep, headerFile = header.rpartition( "/" ) + if not headerFile in seenHeaders: + if headerFile != "tbc_text_format.h" and headerFile != "clara.h": + seenHeaders.add( headerFile ) + write( "// #included from: {0}\n".format( header ) ) + if( headerPath == "internal" and path.endswith( "internal/" ) ): + headerPath = "" + sep = "" + if os.path.exists( path + headerPath + sep + headerFile ): + parseFile( path + headerPath + sep, headerFile ) + else: + parseFile( rootPath + headerPath + sep, headerFile ) + else: + if ifImplParser.match(line): + implIfDefs = ifdefs + if (not guardParser.match( line ) or defineParser.match( line ) ) and not commentParser1.match( line )and not commentParser2.match( line ): + if blankParser.match( line ): + blanks = blanks + 1 + else: + blanks = 0 + if blanks < 2: + write( line.rstrip() + "\n" ) + + +v = Version() +out.write( "/*\n" ) +out.write( " * Catch v{0}\n".format( v.getVersionString() ) ) +out.write( " * Generated: {0}\n".format( datetime.datetime.now() ) ) +out.write( " * ----------------------------------------------------------\n" ) +out.write( " * This file has been merged from multiple headers. Please don't edit it directly\n" ) +out.write( " * Copyright (c) 2012 Two Blue Cubes Ltd. All rights reserved.\n" ) +out.write( " *\n" ) +out.write( " * Distributed under the Boost Software License, Version 1.0. (See accompanying\n" ) +out.write( " * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)\n" ) +out.write( " */\n" ) +out.write( "#ifndef TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED\n" ) +out.write( "#define TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED\n" ) + +parseFile( rootPath, 'catch.hpp' ) + +out.write( "#endif // TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED\n\n" ) + +print ("Generated single include for Catch v{0}\n".format( v.getVersionString() ) ) diff --git a/unittest/Catch/scripts/majorRelease.py b/unittest/Catch/scripts/majorRelease.py new file mode 100644 index 0000000..03b7e78 --- /dev/null +++ b/unittest/Catch/scripts/majorRelease.py @@ -0,0 +1,9 @@ +from __future__ import print_function +from releaseCommon import Version + +v = Version() +v.incrementMajorVersion() +v.updateVersionFile() +v.updateReadmeFile() + +print( "Updated Version.hpp and README to v{0}".format( v.getVersionString() ) )
\ No newline at end of file diff --git a/unittest/Catch/scripts/minorRelease.py b/unittest/Catch/scripts/minorRelease.py new file mode 100644 index 0000000..bbd97ed --- /dev/null +++ b/unittest/Catch/scripts/minorRelease.py @@ -0,0 +1,9 @@ +from __future__ import print_function +from releaseCommon import Version + +v = Version() +v.incrementMinorVersion() +v.updateVersionFile() +v.updateReadmeFile() + +print( "Updated Version.hpp and README to v{0}".format( v.getVersionString() ) )
\ No newline at end of file diff --git a/unittest/Catch/scripts/patchRelease.py b/unittest/Catch/scripts/patchRelease.py new file mode 100644 index 0000000..6abf87a --- /dev/null +++ b/unittest/Catch/scripts/patchRelease.py @@ -0,0 +1,9 @@ +from __future__ import print_function +from releaseCommon import Version + +v = Version() +v.incrementPatchNumber() +v.updateVersionFile() +v.updateReadmeFile() + +print( "Updated Version.hpp and README to v{0}".format( v.getVersionString() ) )
\ No newline at end of file diff --git a/unittest/Catch/scripts/releaseCommon.py b/unittest/Catch/scripts/releaseCommon.py new file mode 100644 index 0000000..14eb235 --- /dev/null +++ b/unittest/Catch/scripts/releaseCommon.py @@ -0,0 +1,89 @@ +from __future__ import print_function + +import os +import sys +import re +import string + +from scriptCommon import catchPath + +versionParser = re.compile( r'(\s*Version\slibraryVersion)\s*\(\s*(.*)\s*,\s*(.*)\s*,\s*(.*)\s*,\s*\"(.*)\"\s*,\s*(.*)\s*\).*' ) +rootPath = os.path.join( catchPath, 'include/' ) +versionPath = os.path.join( rootPath, "internal/catch_version.hpp" ) +readmePath = os.path.join( catchPath, "README.md" ) + +class Version: + def __init__(self): + f = open( versionPath, 'r' ) + for line in f: + m = versionParser.match( line ) + if m: + self.variableDecl = m.group(1) + self.majorVersion = int(m.group(2)) + self.minorVersion = int(m.group(3)) + self.patchNumber = int(m.group(4)) + self.branchName = m.group(5) + self.buildNumber = int(m.group(6)) + f.close() + + def nonDevelopRelease(self): + if self.branchName != "": + self.branchName = "" + self.buildNumber = 0 + def developBuild(self): + if self.branchName == "": + self.branchName = "develop" + self.buildNumber = 0 + + def incrementBuildNumber(self): + self.developBuild() + self.buildNumber = self.buildNumber+1 + + def incrementPatchNumber(self): + self.nonDevelopRelease() + self.patchNumber = self.patchNumber+1 + + def incrementMinorVersion(self): + self.nonDevelopRelease() + self.patchNumber = 0 + self.minorVersion = self.minorVersion+1 + + def incrementMajorVersion(self): + self.nonDevelopRelease() + self.patchNumber = 0 + self.minorVersion = 0 + self.majorVersion = self.majorVersion+1 + + def getVersionString(self): + versionString = '{0}.{1}.{2}'.format( self.majorVersion, self.minorVersion, self.patchNumber ) + if self.branchName != "": + versionString = versionString + '-{0}.{1}'.format( self.branchName, self.buildNumber ) + return versionString + + def updateVersionFile(self): + f = open( versionPath, 'r' ) + lines = [] + for line in f: + m = versionParser.match( line ) + if m: + lines.append( '{0}( {1}, {2}, {3}, "{4}", {5} );'.format( self.variableDecl, self.majorVersion, self.minorVersion, self.patchNumber, self.branchName, self.buildNumber ) ) + else: + lines.append( line.rstrip() ) + f.close() + f = open( versionPath, 'w' ) + for line in lines: + f.write( line + "\n" ) + + def updateReadmeFile(self): + f = open( readmePath, 'r' ) + lines = [] + for line in f: + lines.append( line.rstrip() ) + f.close() + f = open( readmePath, 'w' ) + for line in lines: + if line.startswith( "*v" ): + f.write( '*v{0}*\n'.format( self.getVersionString() ) ) + else: + f.write( line + "\n" ) + diff --git a/unittest/Catch/scripts/releaseNotes.py b/unittest/Catch/scripts/releaseNotes.py new file mode 100644 index 0000000..e083ec9 --- /dev/null +++ b/unittest/Catch/scripts/releaseNotes.py @@ -0,0 +1,62 @@ +import os +import re +import urllib2 +import json + +from scriptCommon import catchPath +from scriptCommon import runAndCapture + +issueNumberRe = re.compile( r'(.*?)#([0-9]*)([^0-9]?.*)' ) + +rootPath = os.path.join( catchPath, 'include/' ) +versionPath = os.path.join( rootPath, "internal/catch_version.hpp" ) + + +hashes = runAndCapture( ['git', 'log', '-2', '--format="%H"', versionPath] ) +lines = runAndCapture( ['git', 'log', hashes[1] + ".." + hashes[0], catchPath] ) + +prevLine = "" +messages = [] +dates = [] +issues = {} + +def getIssueTitle( issueNumber ): + try: + s = urllib2.urlopen("https://api.github.com/repos/philsquared/catch/issues/" + issueNumber ).read() + except e: + return "#HTTP Error#" + + try: + j = json.loads( s ) + return j["title"] + except e: + return "#JSON Error#" + +for line in lines: + if line.startswith( "commit"): + pass + elif line.startswith( "Author:"): + pass + elif line.startswith( "Date:"): + dates.append( line[5:].lstrip() ) + pass + elif line == "" and prevLine == "": + pass + else: + prevLine = line + match = issueNumberRe.match( line ) + line2 = "" + while match: + issueNumber = match.group(2) + issue = '#{0} ("{1}")'.format( issueNumber, getIssueTitle( issueNumber ) ) + line2 = line2 + match.group(1) + issue + match = issueNumberRe.match( match.group(3) ) + if line2 == "": + messages.append( line ) + else: + messages.append( line2 ) + +print "All changes between {0} and {1}:\n".format( dates[-1], dates[0] ) + +for line in messages: + print line diff --git a/unittest/Catch/scripts/scriptCommon.py b/unittest/Catch/scripts/scriptCommon.py new file mode 100644 index 0000000..6ac381a --- /dev/null +++ b/unittest/Catch/scripts/scriptCommon.py @@ -0,0 +1,21 @@ +import os +import sys +import subprocess + +catchPath = os.path.dirname(os.path.realpath( os.path.dirname(sys.argv[0]))) + +def runAndCapture( args ): + child = subprocess.Popen(" ".join( args ), shell=True, stdout=subprocess.PIPE) + lines = [] + line = "" + while True: + out = child.stdout.read(1) + if out == '' and child.poll() != None: + break + if out != '': + if out == '\n': + lines.append( line ) + line = "" + else: + line = line + out + return lines
\ No newline at end of file diff --git a/unittest/Catch/single_include/catch.hpp b/unittest/Catch/single_include/catch.hpp new file mode 100644 index 0000000..5b9bfc2 --- /dev/null +++ b/unittest/Catch/single_include/catch.hpp @@ -0,0 +1,10414 @@ +/* + * Catch v1.3.5 + * Generated: 2016-02-29 08:16:42.342094 + * ---------------------------------------------------------- + * This file has been merged from multiple headers. Please don't edit it directly + * Copyright (c) 2012 Two Blue Cubes Ltd. All rights reserved. + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + */ +#ifndef TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED +#define TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED + +#define TWOBLUECUBES_CATCH_HPP_INCLUDED + +#ifdef __clang__ +# pragma clang system_header +#elif defined __GNUC__ +# pragma GCC system_header +#endif + +// #included from: internal/catch_suppress_warnings.h + +#ifdef __clang__ +# ifdef __ICC // icpc defines the __clang__ macro +# pragma warning(push) +# pragma warning(disable: 161 1682) +# else // __ICC +# pragma clang diagnostic ignored "-Wglobal-constructors" +# pragma clang diagnostic ignored "-Wvariadic-macros" +# pragma clang diagnostic ignored "-Wc99-extensions" +# pragma clang diagnostic ignored "-Wunused-variable" +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wpadded" +# pragma clang diagnostic ignored "-Wc++98-compat" +# pragma clang diagnostic ignored "-Wc++98-compat-pedantic" +# pragma clang diagnostic ignored "-Wswitch-enum" +# pragma clang diagnostic ignored "-Wcovered-switch-default" +# endif +#elif defined __GNUC__ +# pragma GCC diagnostic ignored "-Wvariadic-macros" +# pragma GCC diagnostic ignored "-Wunused-variable" +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wpadded" +#endif +#if defined(CATCH_CONFIG_MAIN) || defined(CATCH_CONFIG_RUNNER) +# define CATCH_IMPL +#endif + +#ifdef CATCH_IMPL +# ifndef CLARA_CONFIG_MAIN +# define CLARA_CONFIG_MAIN_NOT_DEFINED +# define CLARA_CONFIG_MAIN +# endif +#endif + +// #included from: internal/catch_notimplemented_exception.h +#define TWOBLUECUBES_CATCH_NOTIMPLEMENTED_EXCEPTION_H_INCLUDED + +// #included from: catch_common.h +#define TWOBLUECUBES_CATCH_COMMON_H_INCLUDED + +#define INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) name##line +#define INTERNAL_CATCH_UNIQUE_NAME_LINE( name, line ) INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) +#define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __LINE__ ) + +#define INTERNAL_CATCH_STRINGIFY2( expr ) #expr +#define INTERNAL_CATCH_STRINGIFY( expr ) INTERNAL_CATCH_STRINGIFY2( expr ) + +#include <sstream> +#include <stdexcept> +#include <algorithm> + +// #included from: catch_compiler_capabilities.h +#define TWOBLUECUBES_CATCH_COMPILER_CAPABILITIES_HPP_INCLUDED + +// Detect a number of compiler features - mostly C++11/14 conformance - by compiler +// The following features are defined: +// +// CATCH_CONFIG_CPP11_NULLPTR : is nullptr supported? +// CATCH_CONFIG_CPP11_NOEXCEPT : is noexcept supported? +// CATCH_CONFIG_CPP11_GENERATED_METHODS : The delete and default keywords for compiler generated methods +// CATCH_CONFIG_CPP11_IS_ENUM : std::is_enum is supported? +// CATCH_CONFIG_CPP11_TUPLE : std::tuple is supported +// CATCH_CONFIG_CPP11_LONG_LONG : is long long supported? +// CATCH_CONFIG_CPP11_OVERRIDE : is override supported? +// CATCH_CONFIG_CPP11_UNIQUE_PTR : is unique_ptr supported (otherwise use auto_ptr) + +// CATCH_CONFIG_CPP11_OR_GREATER : Is C++11 supported? + +// CATCH_CONFIG_VARIADIC_MACROS : are variadic macros supported? + +// **************** +// Note to maintainers: if new toggles are added please document them +// in configuration.md, too +// **************** + +// In general each macro has a _NO_<feature name> form +// (e.g. CATCH_CONFIG_CPP11_NO_NULLPTR) which disables the feature. +// Many features, at point of detection, define an _INTERNAL_ macro, so they +// can be combined, en-mass, with the _NO_ forms later. + +// All the C++11 features can be disabled with CATCH_CONFIG_NO_CPP11 + +#if defined(__cplusplus) && __cplusplus >= 201103L +# define CATCH_CPP11_OR_GREATER +#endif + +#ifdef __clang__ + +# if __has_feature(cxx_nullptr) +# define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR +# endif + +# if __has_feature(cxx_noexcept) +# define CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT +# endif + +# if defined(CATCH_CPP11_OR_GREATER) +# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS _Pragma( "clang diagnostic ignored \"-Wparentheses\"" ) +# endif + +#endif // __clang__ + +//////////////////////////////////////////////////////////////////////////////// +// Borland +#ifdef __BORLANDC__ + +#endif // __BORLANDC__ + +//////////////////////////////////////////////////////////////////////////////// +// EDG +#ifdef __EDG_VERSION__ + +#endif // __EDG_VERSION__ + +//////////////////////////////////////////////////////////////////////////////// +// Digital Mars +#ifdef __DMC__ + +#endif // __DMC__ + +//////////////////////////////////////////////////////////////////////////////// +// GCC +#ifdef __GNUC__ + +# if __GNUC__ == 4 && __GNUC_MINOR__ >= 6 && defined(__GXX_EXPERIMENTAL_CXX0X__) +# define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR +# endif + +# if !defined(CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS) && defined(CATCH_CPP11_OR_GREATER) +# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS _Pragma( "gcc diagnostic ignored \"-Wparentheses\"" ) +# endif + +// - otherwise more recent versions define __cplusplus >= 201103L +// and will get picked up below + +#endif // __GNUC__ + +//////////////////////////////////////////////////////////////////////////////// +// Visual C++ +#ifdef _MSC_VER + +#if (_MSC_VER >= 1600) +# define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR +# define CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR +#endif + +#if (_MSC_VER >= 1900 ) // (VC++ 13 (VS2015)) +#define CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT +#define CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS +#endif + +#endif // _MSC_VER + +//////////////////////////////////////////////////////////////////////////////// + +// Use variadic macros if the compiler supports them +#if ( defined _MSC_VER && _MSC_VER > 1400 && !defined __EDGE__) || \ + ( defined __WAVE__ && __WAVE_HAS_VARIADICS ) || \ + ( defined __GNUC__ && __GNUC__ >= 3 ) || \ + ( !defined __cplusplus && __STDC_VERSION__ >= 199901L || __cplusplus >= 201103L ) + +#define CATCH_INTERNAL_CONFIG_VARIADIC_MACROS + +#endif + +//////////////////////////////////////////////////////////////////////////////// +// C++ language feature support + +// catch all support for C++11 +#if defined(CATCH_CPP11_OR_GREATER) + +# if !defined(CATCH_INTERNAL_CONFIG_CPP11_NULLPTR) +# define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR +# endif + +# ifndef CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT +# define CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT +# endif + +# ifndef CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS +# define CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS +# endif + +# ifndef CATCH_INTERNAL_CONFIG_CPP11_IS_ENUM +# define CATCH_INTERNAL_CONFIG_CPP11_IS_ENUM +# endif + +# ifndef CATCH_INTERNAL_CONFIG_CPP11_TUPLE +# define CATCH_INTERNAL_CONFIG_CPP11_TUPLE +# endif + +# ifndef CATCH_INTERNAL_CONFIG_VARIADIC_MACROS +# define CATCH_INTERNAL_CONFIG_VARIADIC_MACROS +# endif + +# if !defined(CATCH_INTERNAL_CONFIG_CPP11_LONG_LONG) +# define CATCH_INTERNAL_CONFIG_CPP11_LONG_LONG +# endif + +# if !defined(CATCH_INTERNAL_CONFIG_CPP11_OVERRIDE) +# define CATCH_INTERNAL_CONFIG_CPP11_OVERRIDE +# endif +# if !defined(CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR) +# define CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR +# endif + +#endif // __cplusplus >= 201103L + +// Now set the actual defines based on the above + anything the user has configured +#if defined(CATCH_INTERNAL_CONFIG_CPP11_NULLPTR) && !defined(CATCH_CONFIG_CPP11_NO_NULLPTR) && !defined(CATCH_CONFIG_CPP11_NULLPTR) && !defined(CATCH_CONFIG_NO_CPP11) +# define CATCH_CONFIG_CPP11_NULLPTR +#endif +#if defined(CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT) && !defined(CATCH_CONFIG_CPP11_NO_NOEXCEPT) && !defined(CATCH_CONFIG_CPP11_NOEXCEPT) && !defined(CATCH_CONFIG_NO_CPP11) +# define CATCH_CONFIG_CPP11_NOEXCEPT +#endif +#if defined(CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS) && !defined(CATCH_CONFIG_CPP11_NO_GENERATED_METHODS) && !defined(CATCH_CONFIG_CPP11_GENERATED_METHODS) && !defined(CATCH_CONFIG_NO_CPP11) +# define CATCH_CONFIG_CPP11_GENERATED_METHODS +#endif +#if defined(CATCH_INTERNAL_CONFIG_CPP11_IS_ENUM) && !defined(CATCH_CONFIG_CPP11_NO_IS_ENUM) && !defined(CATCH_CONFIG_CPP11_IS_ENUM) && !defined(CATCH_CONFIG_NO_CPP11) +# define CATCH_CONFIG_CPP11_IS_ENUM +#endif +#if defined(CATCH_INTERNAL_CONFIG_CPP11_TUPLE) && !defined(CATCH_CONFIG_CPP11_NO_TUPLE) && !defined(CATCH_CONFIG_CPP11_TUPLE) && !defined(CATCH_CONFIG_NO_CPP11) +# define CATCH_CONFIG_CPP11_TUPLE +#endif +#if defined(CATCH_INTERNAL_CONFIG_VARIADIC_MACROS) && !defined(CATCH_CONFIG_NO_VARIADIC_MACROS) && !defined(CATCH_CONFIG_VARIADIC_MACROS) +# define CATCH_CONFIG_VARIADIC_MACROS +#endif +#if defined(CATCH_INTERNAL_CONFIG_CPP11_LONG_LONG) && !defined(CATCH_CONFIG_NO_LONG_LONG) && !defined(CATCH_CONFIG_CPP11_LONG_LONG) && !defined(CATCH_CONFIG_NO_CPP11) +# define CATCH_CONFIG_CPP11_LONG_LONG +#endif +#if defined(CATCH_INTERNAL_CONFIG_CPP11_OVERRIDE) && !defined(CATCH_CONFIG_NO_OVERRIDE) && !defined(CATCH_CONFIG_CPP11_OVERRIDE) && !defined(CATCH_CONFIG_NO_CPP11) +# define CATCH_CONFIG_CPP11_OVERRIDE +#endif +#if defined(CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR) && !defined(CATCH_CONFIG_NO_UNIQUE_PTR) && !defined(CATCH_CONFIG_CPP11_UNIQUE_PTR) && !defined(CATCH_CONFIG_NO_CPP11) +# define CATCH_CONFIG_CPP11_UNIQUE_PTR +#endif + +#if !defined(CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS) +# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS +#endif + +// noexcept support: +#if defined(CATCH_CONFIG_CPP11_NOEXCEPT) && !defined(CATCH_NOEXCEPT) +# define CATCH_NOEXCEPT noexcept +# define CATCH_NOEXCEPT_IS(x) noexcept(x) +#else +# define CATCH_NOEXCEPT throw() +# define CATCH_NOEXCEPT_IS(x) +#endif + +// nullptr support +#ifdef CATCH_CONFIG_CPP11_NULLPTR +# define CATCH_NULL nullptr +#else +# define CATCH_NULL NULL +#endif + +// override support +#ifdef CATCH_CONFIG_CPP11_OVERRIDE +# define CATCH_OVERRIDE override +#else +# define CATCH_OVERRIDE +#endif + +// unique_ptr support +#ifdef CATCH_CONFIG_CPP11_UNIQUE_PTR +# define CATCH_AUTO_PTR( T ) std::unique_ptr<T> +#else +# define CATCH_AUTO_PTR( T ) std::auto_ptr<T> +#endif + +namespace Catch { + + struct IConfig; + + struct CaseSensitive { enum Choice { + Yes, + No + }; }; + + class NonCopyable { +#ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS + NonCopyable( NonCopyable const& ) = delete; + NonCopyable( NonCopyable && ) = delete; + NonCopyable& operator = ( NonCopyable const& ) = delete; + NonCopyable& operator = ( NonCopyable && ) = delete; +#else + NonCopyable( NonCopyable const& info ); + NonCopyable& operator = ( NonCopyable const& ); +#endif + + protected: + NonCopyable() {} + virtual ~NonCopyable(); + }; + + class SafeBool { + public: + typedef void (SafeBool::*type)() const; + + static type makeSafe( bool value ) { + return value ? &SafeBool::trueValue : 0; + } + private: + void trueValue() const {} + }; + + template<typename ContainerT> + inline void deleteAll( ContainerT& container ) { + typename ContainerT::const_iterator it = container.begin(); + typename ContainerT::const_iterator itEnd = container.end(); + for(; it != itEnd; ++it ) + delete *it; + } + template<typename AssociativeContainerT> + inline void deleteAllValues( AssociativeContainerT& container ) { + typename AssociativeContainerT::const_iterator it = container.begin(); + typename AssociativeContainerT::const_iterator itEnd = container.end(); + for(; it != itEnd; ++it ) + delete it->second; + } + + bool startsWith( std::string const& s, std::string const& prefix ); + bool endsWith( std::string const& s, std::string const& suffix ); + bool contains( std::string const& s, std::string const& infix ); + void toLowerInPlace( std::string& s ); + std::string toLower( std::string const& s ); + std::string trim( std::string const& str ); + bool replaceInPlace( std::string& str, std::string const& replaceThis, std::string const& withThis ); + + struct pluralise { + pluralise( std::size_t count, std::string const& label ); + + friend std::ostream& operator << ( std::ostream& os, pluralise const& pluraliser ); + + std::size_t m_count; + std::string m_label; + }; + + struct SourceLineInfo { + + SourceLineInfo(); + SourceLineInfo( char const* _file, std::size_t _line ); + SourceLineInfo( SourceLineInfo const& other ); +# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS + SourceLineInfo( SourceLineInfo && ) = default; + SourceLineInfo& operator = ( SourceLineInfo const& ) = default; + SourceLineInfo& operator = ( SourceLineInfo && ) = default; +# endif + bool empty() const; + bool operator == ( SourceLineInfo const& other ) const; + bool operator < ( SourceLineInfo const& other ) const; + + std::string file; + std::size_t line; + }; + + std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info ); + + // This is just here to avoid compiler warnings with macro constants and boolean literals + inline bool isTrue( bool value ){ return value; } + inline bool alwaysTrue() { return true; } + inline bool alwaysFalse() { return false; } + + void throwLogicError( std::string const& message, SourceLineInfo const& locationInfo ); + + void seedRng( IConfig const& config ); + unsigned int rngSeed(); + + // Use this in variadic streaming macros to allow + // >> +StreamEndStop + // as well as + // >> stuff +StreamEndStop + struct StreamEndStop { + std::string operator+() { + return std::string(); + } + }; + template<typename T> + T const& operator + ( T const& value, StreamEndStop ) { + return value; + } +} + +#define CATCH_INTERNAL_LINEINFO ::Catch::SourceLineInfo( __FILE__, static_cast<std::size_t>( __LINE__ ) ) +#define CATCH_INTERNAL_ERROR( msg ) ::Catch::throwLogicError( msg, CATCH_INTERNAL_LINEINFO ); + +#include <ostream> + +namespace Catch { + + class NotImplementedException : public std::exception + { + public: + NotImplementedException( SourceLineInfo const& lineInfo ); + NotImplementedException( NotImplementedException const& ) {} + + virtual ~NotImplementedException() CATCH_NOEXCEPT {} + + virtual const char* what() const CATCH_NOEXCEPT; + + private: + std::string m_what; + SourceLineInfo m_lineInfo; + }; + +} // end namespace Catch + +/////////////////////////////////////////////////////////////////////////////// +#define CATCH_NOT_IMPLEMENTED throw Catch::NotImplementedException( CATCH_INTERNAL_LINEINFO ) + +// #included from: internal/catch_context.h +#define TWOBLUECUBES_CATCH_CONTEXT_H_INCLUDED + +// #included from: catch_interfaces_generators.h +#define TWOBLUECUBES_CATCH_INTERFACES_GENERATORS_H_INCLUDED + +#include <string> + +namespace Catch { + + struct IGeneratorInfo { + virtual ~IGeneratorInfo(); + virtual bool moveNext() = 0; + virtual std::size_t getCurrentIndex() const = 0; + }; + + struct IGeneratorsForTest { + virtual ~IGeneratorsForTest(); + + virtual IGeneratorInfo& getGeneratorInfo( std::string const& fileInfo, std::size_t size ) = 0; + virtual bool moveNext() = 0; + }; + + IGeneratorsForTest* createGeneratorsForTest(); + +} // end namespace Catch + +// #included from: catch_ptr.hpp +#define TWOBLUECUBES_CATCH_PTR_HPP_INCLUDED + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wpadded" +#endif + +namespace Catch { + + // An intrusive reference counting smart pointer. + // T must implement addRef() and release() methods + // typically implementing the IShared interface + template<typename T> + class Ptr { + public: + Ptr() : m_p( CATCH_NULL ){} + Ptr( T* p ) : m_p( p ){ + if( m_p ) + m_p->addRef(); + } + Ptr( Ptr const& other ) : m_p( other.m_p ){ + if( m_p ) + m_p->addRef(); + } + ~Ptr(){ + if( m_p ) + m_p->release(); + } + void reset() { + if( m_p ) + m_p->release(); + m_p = CATCH_NULL; + } + Ptr& operator = ( T* p ){ + Ptr temp( p ); + swap( temp ); + return *this; + } + Ptr& operator = ( Ptr const& other ){ + Ptr temp( other ); + swap( temp ); + return *this; + } + void swap( Ptr& other ) { std::swap( m_p, other.m_p ); } + T* get() const{ return m_p; } + T& operator*() const { return *m_p; } + T* operator->() const { return m_p; } + bool operator !() const { return m_p == CATCH_NULL; } + operator SafeBool::type() const { return SafeBool::makeSafe( m_p != CATCH_NULL ); } + + private: + T* m_p; + }; + + struct IShared : NonCopyable { + virtual ~IShared(); + virtual void addRef() const = 0; + virtual void release() const = 0; + }; + + template<typename T = IShared> + struct SharedImpl : T { + + SharedImpl() : m_rc( 0 ){} + + virtual void addRef() const { + ++m_rc; + } + virtual void release() const { + if( --m_rc == 0 ) + delete this; + } + + mutable unsigned int m_rc; + }; + +} // end namespace Catch + +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + +#include <memory> +#include <vector> +#include <stdlib.h> + +namespace Catch { + + class TestCase; + class Stream; + struct IResultCapture; + struct IRunner; + struct IGeneratorsForTest; + struct IConfig; + + struct IContext + { + virtual ~IContext(); + + virtual IResultCapture* getResultCapture() = 0; + virtual IRunner* getRunner() = 0; + virtual size_t getGeneratorIndex( std::string const& fileInfo, size_t totalSize ) = 0; + virtual bool advanceGeneratorsForCurrentTest() = 0; + virtual Ptr<IConfig const> getConfig() const = 0; + }; + + struct IMutableContext : IContext + { + virtual ~IMutableContext(); + virtual void setResultCapture( IResultCapture* resultCapture ) = 0; + virtual void setRunner( IRunner* runner ) = 0; + virtual void setConfig( Ptr<IConfig const> const& config ) = 0; + }; + + IContext& getCurrentContext(); + IMutableContext& getCurrentMutableContext(); + void cleanUpContext(); + Stream createStream( std::string const& streamName ); + +} + +// #included from: internal/catch_test_registry.hpp +#define TWOBLUECUBES_CATCH_TEST_REGISTRY_HPP_INCLUDED + +// #included from: catch_interfaces_testcase.h +#define TWOBLUECUBES_CATCH_INTERFACES_TESTCASE_H_INCLUDED + +#include <vector> + +namespace Catch { + + class TestSpec; + + struct ITestCase : IShared { + virtual void invoke () const = 0; + protected: + virtual ~ITestCase(); + }; + + class TestCase; + struct IConfig; + + struct ITestCaseRegistry { + virtual ~ITestCaseRegistry(); + virtual std::vector<TestCase> const& getAllTests() const = 0; + virtual std::vector<TestCase> const& getAllTestsSorted( IConfig const& config ) const = 0; + }; + + bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config ); + std::vector<TestCase> filterTests( std::vector<TestCase> const& testCases, TestSpec const& testSpec, IConfig const& config ); + std::vector<TestCase> const& getAllTestCasesSorted( IConfig const& config ); + +} + +namespace Catch { + +template<typename C> +class MethodTestCase : public SharedImpl<ITestCase> { + +public: + MethodTestCase( void (C::*method)() ) : m_method( method ) {} + + virtual void invoke() const { + C obj; + (obj.*m_method)(); + } + +private: + virtual ~MethodTestCase() {} + + void (C::*m_method)(); +}; + +typedef void(*TestFunction)(); + +struct NameAndDesc { + NameAndDesc( const char* _name = "", const char* _description= "" ) + : name( _name ), description( _description ) + {} + + const char* name; + const char* description; +}; + +void registerTestCase + ( ITestCase* testCase, + char const* className, + NameAndDesc const& nameAndDesc, + SourceLineInfo const& lineInfo ); + +struct AutoReg { + + AutoReg + ( TestFunction function, + SourceLineInfo const& lineInfo, + NameAndDesc const& nameAndDesc ); + + template<typename C> + AutoReg + ( void (C::*method)(), + char const* className, + NameAndDesc const& nameAndDesc, + SourceLineInfo const& lineInfo ) { + + registerTestCase + ( new MethodTestCase<C>( method ), + className, + nameAndDesc, + lineInfo ); + } + + ~AutoReg(); + +private: + AutoReg( AutoReg const& ); + void operator= ( AutoReg const& ); +}; + +void registerTestCaseFunction + ( TestFunction function, + SourceLineInfo const& lineInfo, + NameAndDesc const& nameAndDesc ); + +} // end namespace Catch + +#ifdef CATCH_CONFIG_VARIADIC_MACROS + /////////////////////////////////////////////////////////////////////////////// + #define INTERNAL_CATCH_TESTCASE( ... ) \ + static void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )(); \ + namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( __VA_ARGS__ ) ); }\ + static void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )() + + /////////////////////////////////////////////////////////////////////////////// + #define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, ... ) \ + namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &QualifiedMethod, "&" #QualifiedMethod, Catch::NameAndDesc( __VA_ARGS__ ), CATCH_INTERNAL_LINEINFO ); } + + /////////////////////////////////////////////////////////////////////////////// + #define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, ... )\ + namespace{ \ + struct INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ) : ClassName{ \ + void test(); \ + }; \ + Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( &INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )::test, #ClassName, Catch::NameAndDesc( __VA_ARGS__ ), CATCH_INTERNAL_LINEINFO ); \ + } \ + void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )::test() + + /////////////////////////////////////////////////////////////////////////////// + #define INTERNAL_CATCH_REGISTER_TESTCASE( Function, ... ) \ + Catch::AutoReg( Function, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( __VA_ARGS__ ) ); + +#else + /////////////////////////////////////////////////////////////////////////////// + #define INTERNAL_CATCH_TESTCASE( Name, Desc ) \ + static void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )(); \ + namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( Name, Desc ) ); }\ + static void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )() + + /////////////////////////////////////////////////////////////////////////////// + #define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, Name, Desc ) \ + namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &QualifiedMethod, "&" #QualifiedMethod, Catch::NameAndDesc( Name, Desc ), CATCH_INTERNAL_LINEINFO ); } + + /////////////////////////////////////////////////////////////////////////////// + #define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, TestName, Desc )\ + namespace{ \ + struct INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ) : ClassName{ \ + void test(); \ + }; \ + Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( &INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )::test, #ClassName, Catch::NameAndDesc( TestName, Desc ), CATCH_INTERNAL_LINEINFO ); \ + } \ + void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )::test() + + /////////////////////////////////////////////////////////////////////////////// + #define INTERNAL_CATCH_REGISTER_TESTCASE( Function, Name, Desc ) \ + Catch::AutoReg( Function, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( Name, Desc ) ); +#endif + +// #included from: internal/catch_capture.hpp +#define TWOBLUECUBES_CATCH_CAPTURE_HPP_INCLUDED + +// #included from: catch_result_builder.h +#define TWOBLUECUBES_CATCH_RESULT_BUILDER_H_INCLUDED + +// #included from: catch_result_type.h +#define TWOBLUECUBES_CATCH_RESULT_TYPE_H_INCLUDED + +namespace Catch { + + // ResultWas::OfType enum + struct ResultWas { enum OfType { + Unknown = -1, + Ok = 0, + Info = 1, + Warning = 2, + + FailureBit = 0x10, + + ExpressionFailed = FailureBit | 1, + ExplicitFailure = FailureBit | 2, + + Exception = 0x100 | FailureBit, + + ThrewException = Exception | 1, + DidntThrowException = Exception | 2, + + FatalErrorCondition = 0x200 | FailureBit + + }; }; + + inline bool isOk( ResultWas::OfType resultType ) { + return ( resultType & ResultWas::FailureBit ) == 0; + } + inline bool isJustInfo( int flags ) { + return flags == ResultWas::Info; + } + + // ResultDisposition::Flags enum + struct ResultDisposition { enum Flags { + Normal = 0x01, + + ContinueOnFailure = 0x02, // Failures fail test, but execution continues + FalseTest = 0x04, // Prefix expression with ! + SuppressFail = 0x08 // Failures are reported but do not fail the test + }; }; + + inline ResultDisposition::Flags operator | ( ResultDisposition::Flags lhs, ResultDisposition::Flags rhs ) { + return static_cast<ResultDisposition::Flags>( static_cast<int>( lhs ) | static_cast<int>( rhs ) ); + } + + inline bool shouldContinueOnFailure( int flags ) { return ( flags & ResultDisposition::ContinueOnFailure ) != 0; } + inline bool isFalseTest( int flags ) { return ( flags & ResultDisposition::FalseTest ) != 0; } + inline bool shouldSuppressFailure( int flags ) { return ( flags & ResultDisposition::SuppressFail ) != 0; } + +} // end namespace Catch + +// #included from: catch_assertionresult.h +#define TWOBLUECUBES_CATCH_ASSERTIONRESULT_H_INCLUDED + +#include <string> + +namespace Catch { + + struct AssertionInfo + { + AssertionInfo() {} + AssertionInfo( std::string const& _macroName, + SourceLineInfo const& _lineInfo, + std::string const& _capturedExpression, + ResultDisposition::Flags _resultDisposition ); + + std::string macroName; + SourceLineInfo lineInfo; + std::string capturedExpression; + ResultDisposition::Flags resultDisposition; + }; + + struct AssertionResultData + { + AssertionResultData() : resultType( ResultWas::Unknown ) {} + + std::string reconstructedExpression; + std::string message; + ResultWas::OfType resultType; + }; + + class AssertionResult { + public: + AssertionResult(); + AssertionResult( AssertionInfo const& info, AssertionResultData const& data ); + ~AssertionResult(); +# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS + AssertionResult( AssertionResult const& ) = default; + AssertionResult( AssertionResult && ) = default; + AssertionResult& operator = ( AssertionResult const& ) = default; + AssertionResult& operator = ( AssertionResult && ) = default; +# endif + + bool isOk() const; + bool succeeded() const; + ResultWas::OfType getResultType() const; + bool hasExpression() const; + bool hasMessage() const; + std::string getExpression() const; + std::string getExpressionInMacro() const; + bool hasExpandedExpression() const; + std::string getExpandedExpression() const; + std::string getMessage() const; + SourceLineInfo getSourceInfo() const; + std::string getTestMacroName() const; + + protected: + AssertionInfo m_info; + AssertionResultData m_resultData; + }; + +} // end namespace Catch + +// #included from: catch_matchers.hpp +#define TWOBLUECUBES_CATCH_MATCHERS_HPP_INCLUDED + +namespace Catch { +namespace Matchers { + namespace Impl { + + namespace Generic { + template<typename ExpressionT> class AllOf; + template<typename ExpressionT> class AnyOf; + template<typename ExpressionT> class Not; + } + + template<typename ExpressionT> + struct Matcher : SharedImpl<IShared> + { + typedef ExpressionT ExpressionType; + + virtual ~Matcher() {} + virtual Ptr<Matcher> clone() const = 0; + virtual bool match( ExpressionT const& expr ) const = 0; + virtual std::string toString() const = 0; + + Generic::AllOf<ExpressionT> operator && ( Matcher<ExpressionT> const& other ) const; + Generic::AnyOf<ExpressionT> operator || ( Matcher<ExpressionT> const& other ) const; + Generic::Not<ExpressionT> operator ! () const; + }; + + template<typename DerivedT, typename ExpressionT> + struct MatcherImpl : Matcher<ExpressionT> { + + virtual Ptr<Matcher<ExpressionT> > clone() const { + return Ptr<Matcher<ExpressionT> >( new DerivedT( static_cast<DerivedT const&>( *this ) ) ); + } + }; + + namespace Generic { + template<typename ExpressionT> + class Not : public MatcherImpl<Not<ExpressionT>, ExpressionT> { + public: + explicit Not( Matcher<ExpressionT> const& matcher ) : m_matcher(matcher.clone()) {} + Not( Not const& other ) : m_matcher( other.m_matcher ) {} + + virtual bool match( ExpressionT const& expr ) const CATCH_OVERRIDE { + return !m_matcher->match( expr ); + } + + virtual std::string toString() const CATCH_OVERRIDE { + return "not " + m_matcher->toString(); + } + private: + Ptr< Matcher<ExpressionT> > m_matcher; + }; + + template<typename ExpressionT> + class AllOf : public MatcherImpl<AllOf<ExpressionT>, ExpressionT> { + public: + + AllOf() {} + AllOf( AllOf const& other ) : m_matchers( other.m_matchers ) {} + + AllOf& add( Matcher<ExpressionT> const& matcher ) { + m_matchers.push_back( matcher.clone() ); + return *this; + } + virtual bool match( ExpressionT const& expr ) const + { + for( std::size_t i = 0; i < m_matchers.size(); ++i ) + if( !m_matchers[i]->match( expr ) ) + return false; + return true; + } + virtual std::string toString() const { + std::ostringstream oss; + oss << "( "; + for( std::size_t i = 0; i < m_matchers.size(); ++i ) { + if( i != 0 ) + oss << " and "; + oss << m_matchers[i]->toString(); + } + oss << " )"; + return oss.str(); + } + + AllOf operator && ( Matcher<ExpressionT> const& other ) const { + AllOf allOfExpr( *this ); + allOfExpr.add( other ); + return allOfExpr; + } + + private: + std::vector<Ptr<Matcher<ExpressionT> > > m_matchers; + }; + + template<typename ExpressionT> + class AnyOf : public MatcherImpl<AnyOf<ExpressionT>, ExpressionT> { + public: + + AnyOf() {} + AnyOf( AnyOf const& other ) : m_matchers( other.m_matchers ) {} + + AnyOf& add( Matcher<ExpressionT> const& matcher ) { + m_matchers.push_back( matcher.clone() ); + return *this; + } + virtual bool match( ExpressionT const& expr ) const + { + for( std::size_t i = 0; i < m_matchers.size(); ++i ) + if( m_matchers[i]->match( expr ) ) + return true; + return false; + } + virtual std::string toString() const { + std::ostringstream oss; + oss << "( "; + for( std::size_t i = 0; i < m_matchers.size(); ++i ) { + if( i != 0 ) + oss << " or "; + oss << m_matchers[i]->toString(); + } + oss << " )"; + return oss.str(); + } + + AnyOf operator || ( Matcher<ExpressionT> const& other ) const { + AnyOf anyOfExpr( *this ); + anyOfExpr.add( other ); + return anyOfExpr; + } + + private: + std::vector<Ptr<Matcher<ExpressionT> > > m_matchers; + }; + + } // namespace Generic + + template<typename ExpressionT> + Generic::AllOf<ExpressionT> Matcher<ExpressionT>::operator && ( Matcher<ExpressionT> const& other ) const { + Generic::AllOf<ExpressionT> allOfExpr; + allOfExpr.add( *this ); + allOfExpr.add( other ); + return allOfExpr; + } + + template<typename ExpressionT> + Generic::AnyOf<ExpressionT> Matcher<ExpressionT>::operator || ( Matcher<ExpressionT> const& other ) const { + Generic::AnyOf<ExpressionT> anyOfExpr; + anyOfExpr.add( *this ); + anyOfExpr.add( other ); + return anyOfExpr; + } + + template<typename ExpressionT> + Generic::Not<ExpressionT> Matcher<ExpressionT>::operator ! () const { + return Generic::Not<ExpressionT>( *this ); + } + + namespace StdString { + + inline std::string makeString( std::string const& str ) { return str; } + inline std::string makeString( const char* str ) { return str ? std::string( str ) : std::string(); } + + struct CasedString + { + CasedString( std::string const& str, CaseSensitive::Choice caseSensitivity ) + : m_caseSensitivity( caseSensitivity ), + m_str( adjustString( str ) ) + {} + std::string adjustString( std::string const& str ) const { + return m_caseSensitivity == CaseSensitive::No + ? toLower( str ) + : str; + + } + std::string toStringSuffix() const + { + return m_caseSensitivity == CaseSensitive::No + ? " (case insensitive)" + : ""; + } + CaseSensitive::Choice m_caseSensitivity; + std::string m_str; + }; + + struct Equals : MatcherImpl<Equals, std::string> { + Equals( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) + : m_data( str, caseSensitivity ) + {} + Equals( Equals const& other ) : m_data( other.m_data ){} + + virtual ~Equals(); + + virtual bool match( std::string const& expr ) const { + return m_data.m_str == m_data.adjustString( expr );; + } + virtual std::string toString() const { + return "equals: \"" + m_data.m_str + "\"" + m_data.toStringSuffix(); + } + + CasedString m_data; + }; + + struct Contains : MatcherImpl<Contains, std::string> { + Contains( std::string const& substr, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) + : m_data( substr, caseSensitivity ){} + Contains( Contains const& other ) : m_data( other.m_data ){} + + virtual ~Contains(); + + virtual bool match( std::string const& expr ) const { + return m_data.adjustString( expr ).find( m_data.m_str ) != std::string::npos; + } + virtual std::string toString() const { + return "contains: \"" + m_data.m_str + "\"" + m_data.toStringSuffix(); + } + + CasedString m_data; + }; + + struct StartsWith : MatcherImpl<StartsWith, std::string> { + StartsWith( std::string const& substr, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) + : m_data( substr, caseSensitivity ){} + + StartsWith( StartsWith const& other ) : m_data( other.m_data ){} + + virtual ~StartsWith(); + + virtual bool match( std::string const& expr ) const { + return startsWith( m_data.adjustString( expr ), m_data.m_str ); + } + virtual std::string toString() const { + return "starts with: \"" + m_data.m_str + "\"" + m_data.toStringSuffix(); + } + + CasedString m_data; + }; + + struct EndsWith : MatcherImpl<EndsWith, std::string> { + EndsWith( std::string const& substr, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) + : m_data( substr, caseSensitivity ){} + EndsWith( EndsWith const& other ) : m_data( other.m_data ){} + + virtual ~EndsWith(); + + virtual bool match( std::string const& expr ) const { + return endsWith( m_data.adjustString( expr ), m_data.m_str ); + } + virtual std::string toString() const { + return "ends with: \"" + m_data.m_str + "\"" + m_data.toStringSuffix(); + } + + CasedString m_data; + }; + } // namespace StdString + } // namespace Impl + + // The following functions create the actual matcher objects. + // This allows the types to be inferred + template<typename ExpressionT> + inline Impl::Generic::Not<ExpressionT> Not( Impl::Matcher<ExpressionT> const& m ) { + return Impl::Generic::Not<ExpressionT>( m ); + } + + template<typename ExpressionT> + inline Impl::Generic::AllOf<ExpressionT> AllOf( Impl::Matcher<ExpressionT> const& m1, + Impl::Matcher<ExpressionT> const& m2 ) { + return Impl::Generic::AllOf<ExpressionT>().add( m1 ).add( m2 ); + } + template<typename ExpressionT> + inline Impl::Generic::AllOf<ExpressionT> AllOf( Impl::Matcher<ExpressionT> const& m1, + Impl::Matcher<ExpressionT> const& m2, + Impl::Matcher<ExpressionT> const& m3 ) { + return Impl::Generic::AllOf<ExpressionT>().add( m1 ).add( m2 ).add( m3 ); + } + template<typename ExpressionT> + inline Impl::Generic::AnyOf<ExpressionT> AnyOf( Impl::Matcher<ExpressionT> const& m1, + Impl::Matcher<ExpressionT> const& m2 ) { + return Impl::Generic::AnyOf<ExpressionT>().add( m1 ).add( m2 ); + } + template<typename ExpressionT> + inline Impl::Generic::AnyOf<ExpressionT> AnyOf( Impl::Matcher<ExpressionT> const& m1, + Impl::Matcher<ExpressionT> const& m2, + Impl::Matcher<ExpressionT> const& m3 ) { + return Impl::Generic::AnyOf<ExpressionT>().add( m1 ).add( m2 ).add( m3 ); + } + + inline Impl::StdString::Equals Equals( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) { + return Impl::StdString::Equals( str, caseSensitivity ); + } + inline Impl::StdString::Equals Equals( const char* str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) { + return Impl::StdString::Equals( Impl::StdString::makeString( str ), caseSensitivity ); + } + inline Impl::StdString::Contains Contains( std::string const& substr, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) { + return Impl::StdString::Contains( substr, caseSensitivity ); + } + inline Impl::StdString::Contains Contains( const char* substr, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) { + return Impl::StdString::Contains( Impl::StdString::makeString( substr ), caseSensitivity ); + } + inline Impl::StdString::StartsWith StartsWith( std::string const& substr ) { + return Impl::StdString::StartsWith( substr ); + } + inline Impl::StdString::StartsWith StartsWith( const char* substr ) { + return Impl::StdString::StartsWith( Impl::StdString::makeString( substr ) ); + } + inline Impl::StdString::EndsWith EndsWith( std::string const& substr ) { + return Impl::StdString::EndsWith( substr ); + } + inline Impl::StdString::EndsWith EndsWith( const char* substr ) { + return Impl::StdString::EndsWith( Impl::StdString::makeString( substr ) ); + } + +} // namespace Matchers + +using namespace Matchers; + +} // namespace Catch + +namespace Catch { + + struct TestFailureException{}; + + template<typename T> class ExpressionLhs; + + struct STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison; + + struct CopyableStream { + CopyableStream() {} + CopyableStream( CopyableStream const& other ) { + oss << other.oss.str(); + } + CopyableStream& operator=( CopyableStream const& other ) { + oss.str(""); + oss << other.oss.str(); + return *this; + } + std::ostringstream oss; + }; + + class ResultBuilder { + public: + ResultBuilder( char const* macroName, + SourceLineInfo const& lineInfo, + char const* capturedExpression, + ResultDisposition::Flags resultDisposition, + char const* secondArg = "" ); + + template<typename T> + ExpressionLhs<T const&> operator <= ( T const& operand ); + ExpressionLhs<bool> operator <= ( bool value ); + + template<typename T> + ResultBuilder& operator << ( T const& value ) { + m_stream.oss << value; + return *this; + } + + template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator && ( RhsT const& ); + template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator || ( RhsT const& ); + + ResultBuilder& setResultType( ResultWas::OfType result ); + ResultBuilder& setResultType( bool result ); + ResultBuilder& setLhs( std::string const& lhs ); + ResultBuilder& setRhs( std::string const& rhs ); + ResultBuilder& setOp( std::string const& op ); + + void endExpression(); + + std::string reconstructExpression() const; + AssertionResult build() const; + + void useActiveException( ResultDisposition::Flags resultDisposition = ResultDisposition::Normal ); + void captureResult( ResultWas::OfType resultType ); + void captureExpression(); + void captureExpectedException( std::string const& expectedMessage ); + void captureExpectedException( Matchers::Impl::Matcher<std::string> const& matcher ); + void handleResult( AssertionResult const& result ); + void react(); + bool shouldDebugBreak() const; + bool allowThrows() const; + + private: + AssertionInfo m_assertionInfo; + AssertionResultData m_data; + struct ExprComponents { + ExprComponents() : testFalse( false ) {} + bool testFalse; + std::string lhs, rhs, op; + } m_exprComponents; + CopyableStream m_stream; + + bool m_shouldDebugBreak; + bool m_shouldThrow; + }; + +} // namespace Catch + +// Include after due to circular dependency: +// #included from: catch_expression_lhs.hpp +#define TWOBLUECUBES_CATCH_EXPRESSION_LHS_HPP_INCLUDED + +// #included from: catch_evaluate.hpp +#define TWOBLUECUBES_CATCH_EVALUATE_HPP_INCLUDED + +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable:4389) // '==' : signed/unsigned mismatch +#endif + +#include <cstddef> + +namespace Catch { +namespace Internal { + + enum Operator { + IsEqualTo, + IsNotEqualTo, + IsLessThan, + IsGreaterThan, + IsLessThanOrEqualTo, + IsGreaterThanOrEqualTo + }; + + template<Operator Op> struct OperatorTraits { static const char* getName(){ return "*error*"; } }; + template<> struct OperatorTraits<IsEqualTo> { static const char* getName(){ return "=="; } }; + template<> struct OperatorTraits<IsNotEqualTo> { static const char* getName(){ return "!="; } }; + template<> struct OperatorTraits<IsLessThan> { static const char* getName(){ return "<"; } }; + template<> struct OperatorTraits<IsGreaterThan> { static const char* getName(){ return ">"; } }; + template<> struct OperatorTraits<IsLessThanOrEqualTo> { static const char* getName(){ return "<="; } }; + template<> struct OperatorTraits<IsGreaterThanOrEqualTo>{ static const char* getName(){ return ">="; } }; + + template<typename T> + inline T& opCast(T const& t) { return const_cast<T&>(t); } + +// nullptr_t support based on pull request #154 from Konstantin Baumann +#ifdef CATCH_CONFIG_CPP11_NULLPTR + inline std::nullptr_t opCast(std::nullptr_t) { return nullptr; } +#endif // CATCH_CONFIG_CPP11_NULLPTR + + // So the compare overloads can be operator agnostic we convey the operator as a template + // enum, which is used to specialise an Evaluator for doing the comparison. + template<typename T1, typename T2, Operator Op> + class Evaluator{}; + + template<typename T1, typename T2> + struct Evaluator<T1, T2, IsEqualTo> { + static bool evaluate( T1 const& lhs, T2 const& rhs) { + return bool( opCast( lhs ) == opCast( rhs ) ); + } + }; + template<typename T1, typename T2> + struct Evaluator<T1, T2, IsNotEqualTo> { + static bool evaluate( T1 const& lhs, T2 const& rhs ) { + return bool( opCast( lhs ) != opCast( rhs ) ); + } + }; + template<typename T1, typename T2> + struct Evaluator<T1, T2, IsLessThan> { + static bool evaluate( T1 const& lhs, T2 const& rhs ) { + return bool( opCast( lhs ) < opCast( rhs ) ); + } + }; + template<typename T1, typename T2> + struct Evaluator<T1, T2, IsGreaterThan> { + static bool evaluate( T1 const& lhs, T2 const& rhs ) { + return bool( opCast( lhs ) > opCast( rhs ) ); + } + }; + template<typename T1, typename T2> + struct Evaluator<T1, T2, IsGreaterThanOrEqualTo> { + static bool evaluate( T1 const& lhs, T2 const& rhs ) { + return bool( opCast( lhs ) >= opCast( rhs ) ); + } + }; + template<typename T1, typename T2> + struct Evaluator<T1, T2, IsLessThanOrEqualTo> { + static bool evaluate( T1 const& lhs, T2 const& rhs ) { + return bool( opCast( lhs ) <= opCast( rhs ) ); + } + }; + + template<Operator Op, typename T1, typename T2> + bool applyEvaluator( T1 const& lhs, T2 const& rhs ) { + return Evaluator<T1, T2, Op>::evaluate( lhs, rhs ); + } + + // This level of indirection allows us to specialise for integer types + // to avoid signed/ unsigned warnings + + // "base" overload + template<Operator Op, typename T1, typename T2> + bool compare( T1 const& lhs, T2 const& rhs ) { + return Evaluator<T1, T2, Op>::evaluate( lhs, rhs ); + } + + // unsigned X to int + template<Operator Op> bool compare( unsigned int lhs, int rhs ) { + return applyEvaluator<Op>( lhs, static_cast<unsigned int>( rhs ) ); + } + template<Operator Op> bool compare( unsigned long lhs, int rhs ) { + return applyEvaluator<Op>( lhs, static_cast<unsigned int>( rhs ) ); + } + template<Operator Op> bool compare( unsigned char lhs, int rhs ) { + return applyEvaluator<Op>( lhs, static_cast<unsigned int>( rhs ) ); + } + + // unsigned X to long + template<Operator Op> bool compare( unsigned int lhs, long rhs ) { + return applyEvaluator<Op>( lhs, static_cast<unsigned long>( rhs ) ); + } + template<Operator Op> bool compare( unsigned long lhs, long rhs ) { + return applyEvaluator<Op>( lhs, static_cast<unsigned long>( rhs ) ); + } + template<Operator Op> bool compare( unsigned char lhs, long rhs ) { + return applyEvaluator<Op>( lhs, static_cast<unsigned long>( rhs ) ); + } + + // int to unsigned X + template<Operator Op> bool compare( int lhs, unsigned int rhs ) { + return applyEvaluator<Op>( static_cast<unsigned int>( lhs ), rhs ); + } + template<Operator Op> bool compare( int lhs, unsigned long rhs ) { + return applyEvaluator<Op>( static_cast<unsigned int>( lhs ), rhs ); + } + template<Operator Op> bool compare( int lhs, unsigned char rhs ) { + return applyEvaluator<Op>( static_cast<unsigned int>( lhs ), rhs ); + } + + // long to unsigned X + template<Operator Op> bool compare( long lhs, unsigned int rhs ) { + return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs ); + } + template<Operator Op> bool compare( long lhs, unsigned long rhs ) { + return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs ); + } + template<Operator Op> bool compare( long lhs, unsigned char rhs ) { + return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs ); + } + + // pointer to long (when comparing against NULL) + template<Operator Op, typename T> bool compare( long lhs, T* rhs ) { + return Evaluator<T*, T*, Op>::evaluate( reinterpret_cast<T*>( lhs ), rhs ); + } + template<Operator Op, typename T> bool compare( T* lhs, long rhs ) { + return Evaluator<T*, T*, Op>::evaluate( lhs, reinterpret_cast<T*>( rhs ) ); + } + + // pointer to int (when comparing against NULL) + template<Operator Op, typename T> bool compare( int lhs, T* rhs ) { + return Evaluator<T*, T*, Op>::evaluate( reinterpret_cast<T*>( lhs ), rhs ); + } + template<Operator Op, typename T> bool compare( T* lhs, int rhs ) { + return Evaluator<T*, T*, Op>::evaluate( lhs, reinterpret_cast<T*>( rhs ) ); + } + +#ifdef CATCH_CONFIG_CPP11_LONG_LONG + // long long to unsigned X + template<Operator Op> bool compare( long long lhs, unsigned int rhs ) { + return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs ); + } + template<Operator Op> bool compare( long long lhs, unsigned long rhs ) { + return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs ); + } + template<Operator Op> bool compare( long long lhs, unsigned long long rhs ) { + return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs ); + } + template<Operator Op> bool compare( long long lhs, unsigned char rhs ) { + return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs ); + } + + // unsigned long long to X + template<Operator Op> bool compare( unsigned long long lhs, int rhs ) { + return applyEvaluator<Op>( static_cast<long>( lhs ), rhs ); + } + template<Operator Op> bool compare( unsigned long long lhs, long rhs ) { + return applyEvaluator<Op>( static_cast<long>( lhs ), rhs ); + } + template<Operator Op> bool compare( unsigned long long lhs, long long rhs ) { + return applyEvaluator<Op>( static_cast<long>( lhs ), rhs ); + } + template<Operator Op> bool compare( unsigned long long lhs, char rhs ) { + return applyEvaluator<Op>( static_cast<long>( lhs ), rhs ); + } + + // pointer to long long (when comparing against NULL) + template<Operator Op, typename T> bool compare( long long lhs, T* rhs ) { + return Evaluator<T*, T*, Op>::evaluate( reinterpret_cast<T*>( lhs ), rhs ); + } + template<Operator Op, typename T> bool compare( T* lhs, long long rhs ) { + return Evaluator<T*, T*, Op>::evaluate( lhs, reinterpret_cast<T*>( rhs ) ); + } +#endif // CATCH_CONFIG_CPP11_LONG_LONG + +#ifdef CATCH_CONFIG_CPP11_NULLPTR + // pointer to nullptr_t (when comparing against nullptr) + template<Operator Op, typename T> bool compare( std::nullptr_t, T* rhs ) { + return Evaluator<T*, T*, Op>::evaluate( nullptr, rhs ); + } + template<Operator Op, typename T> bool compare( T* lhs, std::nullptr_t ) { + return Evaluator<T*, T*, Op>::evaluate( lhs, nullptr ); + } +#endif // CATCH_CONFIG_CPP11_NULLPTR + +} // end of namespace Internal +} // end of namespace Catch + +#ifdef _MSC_VER +#pragma warning(pop) +#endif + +// #included from: catch_tostring.h +#define TWOBLUECUBES_CATCH_TOSTRING_H_INCLUDED + +#include <sstream> +#include <iomanip> +#include <limits> +#include <vector> +#include <cstddef> + +#ifdef __OBJC__ +// #included from: catch_objc_arc.hpp +#define TWOBLUECUBES_CATCH_OBJC_ARC_HPP_INCLUDED + +#import <Foundation/Foundation.h> + +#ifdef __has_feature +#define CATCH_ARC_ENABLED __has_feature(objc_arc) +#else +#define CATCH_ARC_ENABLED 0 +#endif + +void arcSafeRelease( NSObject* obj ); +id performOptionalSelector( id obj, SEL sel ); + +#if !CATCH_ARC_ENABLED +inline void arcSafeRelease( NSObject* obj ) { + [obj release]; +} +inline id performOptionalSelector( id obj, SEL sel ) { + if( [obj respondsToSelector: sel] ) + return [obj performSelector: sel]; + return nil; +} +#define CATCH_UNSAFE_UNRETAINED +#define CATCH_ARC_STRONG +#else +inline void arcSafeRelease( NSObject* ){} +inline id performOptionalSelector( id obj, SEL sel ) { +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Warc-performSelector-leaks" +#endif + if( [obj respondsToSelector: sel] ) + return [obj performSelector: sel]; +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + return nil; +} +#define CATCH_UNSAFE_UNRETAINED __unsafe_unretained +#define CATCH_ARC_STRONG __strong +#endif + +#endif + +#ifdef CATCH_CONFIG_CPP11_TUPLE +#include <tuple> +#endif + +#ifdef CATCH_CONFIG_CPP11_IS_ENUM +#include <type_traits> +#endif + +namespace Catch { + +// Why we're here. +template<typename T> +std::string toString( T const& value ); + +// Built in overloads + +std::string toString( std::string const& value ); +std::string toString( std::wstring const& value ); +std::string toString( const char* const value ); +std::string toString( char* const value ); +std::string toString( const wchar_t* const value ); +std::string toString( wchar_t* const value ); +std::string toString( int value ); +std::string toString( unsigned long value ); +std::string toString( unsigned int value ); +std::string toString( const double value ); +std::string toString( const float value ); +std::string toString( bool value ); +std::string toString( char value ); +std::string toString( signed char value ); +std::string toString( unsigned char value ); + +#ifdef CATCH_CONFIG_CPP11_LONG_LONG +std::string toString( long long value ); +std::string toString( unsigned long long value ); +#endif + +#ifdef CATCH_CONFIG_CPP11_NULLPTR +std::string toString( std::nullptr_t ); +#endif + +#ifdef __OBJC__ + std::string toString( NSString const * const& nsstring ); + std::string toString( NSString * CATCH_ARC_STRONG const& nsstring ); + std::string toString( NSObject* const& nsObject ); +#endif + +namespace Detail { + + extern const std::string unprintableString; + + struct BorgType { + template<typename T> BorgType( T const& ); + }; + + struct TrueType { char sizer[1]; }; + struct FalseType { char sizer[2]; }; + + TrueType& testStreamable( std::ostream& ); + FalseType testStreamable( FalseType ); + + FalseType operator<<( std::ostream const&, BorgType const& ); + + template<typename T> + struct IsStreamInsertable { + static std::ostream &s; + static T const&t; + enum { value = sizeof( testStreamable(s << t) ) == sizeof( TrueType ) }; + }; + +#if defined(CATCH_CONFIG_CPP11_IS_ENUM) + template<typename T, + bool IsEnum = std::is_enum<T>::value + > + struct EnumStringMaker + { + static std::string convert( T const& ) { return unprintableString; } + }; + + template<typename T> + struct EnumStringMaker<T,true> + { + static std::string convert( T const& v ) + { + return ::Catch::toString( + static_cast<typename std::underlying_type<T>::type>(v) + ); + } + }; +#endif + template<bool C> + struct StringMakerBase { +#if defined(CATCH_CONFIG_CPP11_IS_ENUM) + template<typename T> + static std::string convert( T const& v ) + { + return EnumStringMaker<T>::convert( v ); + } +#else + template<typename T> + static std::string convert( T const& ) { return unprintableString; } +#endif + }; + + template<> + struct StringMakerBase<true> { + template<typename T> + static std::string convert( T const& _value ) { + std::ostringstream oss; + oss << _value; + return oss.str(); + } + }; + + std::string rawMemoryToString( const void *object, std::size_t size ); + + template<typename T> + inline std::string rawMemoryToString( const T& object ) { + return rawMemoryToString( &object, sizeof(object) ); + } + +} // end namespace Detail + +template<typename T> +struct StringMaker : + Detail::StringMakerBase<Detail::IsStreamInsertable<T>::value> {}; + +template<typename T> +struct StringMaker<T*> { + template<typename U> + static std::string convert( U* p ) { + if( !p ) + return "NULL"; + else + return Detail::rawMemoryToString( p ); + } +}; + +template<typename R, typename C> +struct StringMaker<R C::*> { + static std::string convert( R C::* p ) { + if( !p ) + return "NULL"; + else + return Detail::rawMemoryToString( p ); + } +}; + +namespace Detail { + template<typename InputIterator> + std::string rangeToString( InputIterator first, InputIterator last ); +} + +//template<typename T, typename Allocator> +//struct StringMaker<std::vector<T, Allocator> > { +// static std::string convert( std::vector<T,Allocator> const& v ) { +// return Detail::rangeToString( v.begin(), v.end() ); +// } +//}; + +template<typename T, typename Allocator> +std::string toString( std::vector<T,Allocator> const& v ) { + return Detail::rangeToString( v.begin(), v.end() ); +} + +#ifdef CATCH_CONFIG_CPP11_TUPLE + +// toString for tuples +namespace TupleDetail { + template< + typename Tuple, + std::size_t N = 0, + bool = (N < std::tuple_size<Tuple>::value) + > + struct ElementPrinter { + static void print( const Tuple& tuple, std::ostream& os ) + { + os << ( N ? ", " : " " ) + << Catch::toString(std::get<N>(tuple)); + ElementPrinter<Tuple,N+1>::print(tuple,os); + } + }; + + template< + typename Tuple, + std::size_t N + > + struct ElementPrinter<Tuple,N,false> { + static void print( const Tuple&, std::ostream& ) {} + }; + +} + +template<typename ...Types> +struct StringMaker<std::tuple<Types...>> { + + static std::string convert( const std::tuple<Types...>& tuple ) + { + std::ostringstream os; + os << '{'; + TupleDetail::ElementPrinter<std::tuple<Types...>>::print( tuple, os ); + os << " }"; + return os.str(); + } +}; +#endif // CATCH_CONFIG_CPP11_TUPLE + +namespace Detail { + template<typename T> + std::string makeString( T const& value ) { + return StringMaker<T>::convert( value ); + } +} // end namespace Detail + +/// \brief converts any type to a string +/// +/// The default template forwards on to ostringstream - except when an +/// ostringstream overload does not exist - in which case it attempts to detect +/// that and writes {?}. +/// Overload (not specialise) this template for custom typs that you don't want +/// to provide an ostream overload for. +template<typename T> +std::string toString( T const& value ) { + return StringMaker<T>::convert( value ); +} + + namespace Detail { + template<typename InputIterator> + std::string rangeToString( InputIterator first, InputIterator last ) { + std::ostringstream oss; + oss << "{ "; + if( first != last ) { + oss << Catch::toString( *first ); + for( ++first ; first != last ; ++first ) + oss << ", " << Catch::toString( *first ); + } + oss << " }"; + return oss.str(); + } +} + +} // end namespace Catch + +namespace Catch { + +// Wraps the LHS of an expression and captures the operator and RHS (if any) - +// wrapping them all in a ResultBuilder object +template<typename T> +class ExpressionLhs { + ExpressionLhs& operator = ( ExpressionLhs const& ); +# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS + ExpressionLhs& operator = ( ExpressionLhs && ) = delete; +# endif + +public: + ExpressionLhs( ResultBuilder& rb, T lhs ) : m_rb( rb ), m_lhs( lhs ) {} +# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS + ExpressionLhs( ExpressionLhs const& ) = default; + ExpressionLhs( ExpressionLhs && ) = default; +# endif + + template<typename RhsT> + ResultBuilder& operator == ( RhsT const& rhs ) { + return captureExpression<Internal::IsEqualTo>( rhs ); + } + + template<typename RhsT> + ResultBuilder& operator != ( RhsT const& rhs ) { + return captureExpression<Internal::IsNotEqualTo>( rhs ); + } + + template<typename RhsT> + ResultBuilder& operator < ( RhsT const& rhs ) { + return captureExpression<Internal::IsLessThan>( rhs ); + } + + template<typename RhsT> + ResultBuilder& operator > ( RhsT const& rhs ) { + return captureExpression<Internal::IsGreaterThan>( rhs ); + } + + template<typename RhsT> + ResultBuilder& operator <= ( RhsT const& rhs ) { + return captureExpression<Internal::IsLessThanOrEqualTo>( rhs ); + } + + template<typename RhsT> + ResultBuilder& operator >= ( RhsT const& rhs ) { + return captureExpression<Internal::IsGreaterThanOrEqualTo>( rhs ); + } + + ResultBuilder& operator == ( bool rhs ) { + return captureExpression<Internal::IsEqualTo>( rhs ); + } + + ResultBuilder& operator != ( bool rhs ) { + return captureExpression<Internal::IsNotEqualTo>( rhs ); + } + + void endExpression() { + bool value = m_lhs ? true : false; + m_rb + .setLhs( Catch::toString( value ) ) + .setResultType( value ) + .endExpression(); + } + + // Only simple binary expressions are allowed on the LHS. + // If more complex compositions are required then place the sub expression in parentheses + template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator + ( RhsT const& ); + template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator - ( RhsT const& ); + template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator / ( RhsT const& ); + template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator * ( RhsT const& ); + template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator && ( RhsT const& ); + template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator || ( RhsT const& ); + +private: + template<Internal::Operator Op, typename RhsT> + ResultBuilder& captureExpression( RhsT const& rhs ) { + return m_rb + .setResultType( Internal::compare<Op>( m_lhs, rhs ) ) + .setLhs( Catch::toString( m_lhs ) ) + .setRhs( Catch::toString( rhs ) ) + .setOp( Internal::OperatorTraits<Op>::getName() ); + } + +private: + ResultBuilder& m_rb; + T m_lhs; +}; + +} // end namespace Catch + + +namespace Catch { + + template<typename T> + inline ExpressionLhs<T const&> ResultBuilder::operator <= ( T const& operand ) { + return ExpressionLhs<T const&>( *this, operand ); + } + + inline ExpressionLhs<bool> ResultBuilder::operator <= ( bool value ) { + return ExpressionLhs<bool>( *this, value ); + } + +} // namespace Catch + +// #included from: catch_message.h +#define TWOBLUECUBES_CATCH_MESSAGE_H_INCLUDED + +#include <string> + +namespace Catch { + + struct MessageInfo { + MessageInfo( std::string const& _macroName, + SourceLineInfo const& _lineInfo, + ResultWas::OfType _type ); + + std::string macroName; + SourceLineInfo lineInfo; + ResultWas::OfType type; + std::string message; + unsigned int sequence; + + bool operator == ( MessageInfo const& other ) const { + return sequence == other.sequence; + } + bool operator < ( MessageInfo const& other ) const { + return sequence < other.sequence; + } + private: + static unsigned int globalCount; + }; + + struct MessageBuilder { + MessageBuilder( std::string const& macroName, + SourceLineInfo const& lineInfo, + ResultWas::OfType type ) + : m_info( macroName, lineInfo, type ) + {} + + template<typename T> + MessageBuilder& operator << ( T const& value ) { + m_stream << value; + return *this; + } + + MessageInfo m_info; + std::ostringstream m_stream; + }; + + class ScopedMessage { + public: + ScopedMessage( MessageBuilder const& builder ); + ScopedMessage( ScopedMessage const& other ); + ~ScopedMessage(); + + MessageInfo m_info; + }; + +} // end namespace Catch + +// #included from: catch_interfaces_capture.h +#define TWOBLUECUBES_CATCH_INTERFACES_CAPTURE_H_INCLUDED + +#include <string> + +namespace Catch { + + class TestCase; + class AssertionResult; + struct AssertionInfo; + struct SectionInfo; + struct SectionEndInfo; + struct MessageInfo; + class ScopedMessageBuilder; + struct Counts; + + struct IResultCapture { + + virtual ~IResultCapture(); + + virtual void assertionEnded( AssertionResult const& result ) = 0; + virtual bool sectionStarted( SectionInfo const& sectionInfo, + Counts& assertions ) = 0; + virtual void sectionEnded( SectionEndInfo const& endInfo ) = 0; + virtual void sectionEndedEarly( SectionEndInfo const& endInfo ) = 0; + virtual void pushScopedMessage( MessageInfo const& message ) = 0; + virtual void popScopedMessage( MessageInfo const& message ) = 0; + + virtual std::string getCurrentTestName() const = 0; + virtual const AssertionResult* getLastResult() const = 0; + + virtual void handleFatalErrorCondition( std::string const& message ) = 0; + }; + + IResultCapture& getResultCapture(); +} + +// #included from: catch_debugger.h +#define TWOBLUECUBES_CATCH_DEBUGGER_H_INCLUDED + +// #included from: catch_platform.h +#define TWOBLUECUBES_CATCH_PLATFORM_H_INCLUDED + +#if defined(__MAC_OS_X_VERSION_MIN_REQUIRED) +#define CATCH_PLATFORM_MAC +#elif defined(__IPHONE_OS_VERSION_MIN_REQUIRED) +#define CATCH_PLATFORM_IPHONE +#elif defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) +#define CATCH_PLATFORM_WINDOWS +#endif + +#include <string> + +namespace Catch{ + + bool isDebuggerActive(); + void writeToDebugConsole( std::string const& text ); +} + +#ifdef CATCH_PLATFORM_MAC + + // The following code snippet based on: + // http://cocoawithlove.com/2008/03/break-into-debugger.html + #ifdef DEBUG + #if defined(__ppc64__) || defined(__ppc__) + #define CATCH_BREAK_INTO_DEBUGGER() \ + if( Catch::isDebuggerActive() ) { \ + __asm__("li r0, 20\nsc\nnop\nli r0, 37\nli r4, 2\nsc\nnop\n" \ + : : : "memory","r0","r3","r4" ); \ + } + #else + #define CATCH_BREAK_INTO_DEBUGGER() if( Catch::isDebuggerActive() ) {__asm__("int $3\n" : : );} + #endif + #endif + +#elif defined(_MSC_VER) + #define CATCH_BREAK_INTO_DEBUGGER() if( Catch::isDebuggerActive() ) { __debugbreak(); } +#elif defined(__MINGW32__) + extern "C" __declspec(dllimport) void __stdcall DebugBreak(); + #define CATCH_BREAK_INTO_DEBUGGER() if( Catch::isDebuggerActive() ) { DebugBreak(); } +#endif + +#ifndef CATCH_BREAK_INTO_DEBUGGER +#define CATCH_BREAK_INTO_DEBUGGER() Catch::alwaysTrue(); +#endif + +// #included from: catch_interfaces_runner.h +#define TWOBLUECUBES_CATCH_INTERFACES_RUNNER_H_INCLUDED + +namespace Catch { + class TestCase; + + struct IRunner { + virtual ~IRunner(); + virtual bool aborting() const = 0; + }; +} + +/////////////////////////////////////////////////////////////////////////////// +// In the event of a failure works out if the debugger needs to be invoked +// and/or an exception thrown and takes appropriate action. +// This needs to be done as a macro so the debugger will stop in the user +// source code rather than in Catch library code +#define INTERNAL_CATCH_REACT( resultBuilder ) \ + if( resultBuilder.shouldDebugBreak() ) CATCH_BREAK_INTO_DEBUGGER(); \ + resultBuilder.react(); + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_TEST( expr, resultDisposition, macroName ) \ + do { \ + Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \ + try { \ + CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \ + ( __catchResult <= expr ).endExpression(); \ + } \ + catch( ... ) { \ + __catchResult.useActiveException( Catch::ResultDisposition::Normal ); \ + } \ + INTERNAL_CATCH_REACT( __catchResult ) \ + } while( Catch::isTrue( false && static_cast<bool>(expr) ) ) // expr here is never evaluated at runtime but it forces the compiler to give it a look + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_IF( expr, resultDisposition, macroName ) \ + INTERNAL_CATCH_TEST( expr, resultDisposition, macroName ); \ + if( Catch::getResultCapture().getLastResult()->succeeded() ) + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_ELSE( expr, resultDisposition, macroName ) \ + INTERNAL_CATCH_TEST( expr, resultDisposition, macroName ); \ + if( !Catch::getResultCapture().getLastResult()->succeeded() ) + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_NO_THROW( expr, resultDisposition, macroName ) \ + do { \ + Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \ + try { \ + expr; \ + __catchResult.captureResult( Catch::ResultWas::Ok ); \ + } \ + catch( ... ) { \ + __catchResult.useActiveException( resultDisposition ); \ + } \ + INTERNAL_CATCH_REACT( __catchResult ) \ + } while( Catch::alwaysFalse() ) + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_THROWS( expr, resultDisposition, matcher, macroName ) \ + do { \ + Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition, #matcher ); \ + if( __catchResult.allowThrows() ) \ + try { \ + expr; \ + __catchResult.captureResult( Catch::ResultWas::DidntThrowException ); \ + } \ + catch( ... ) { \ + __catchResult.captureExpectedException( matcher ); \ + } \ + else \ + __catchResult.captureResult( Catch::ResultWas::Ok ); \ + INTERNAL_CATCH_REACT( __catchResult ) \ + } while( Catch::alwaysFalse() ) + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_THROWS_AS( expr, exceptionType, resultDisposition, macroName ) \ + do { \ + Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \ + if( __catchResult.allowThrows() ) \ + try { \ + expr; \ + __catchResult.captureResult( Catch::ResultWas::DidntThrowException ); \ + } \ + catch( exceptionType ) { \ + __catchResult.captureResult( Catch::ResultWas::Ok ); \ + } \ + catch( ... ) { \ + __catchResult.useActiveException( resultDisposition ); \ + } \ + else \ + __catchResult.captureResult( Catch::ResultWas::Ok ); \ + INTERNAL_CATCH_REACT( __catchResult ) \ + } while( Catch::alwaysFalse() ) + +/////////////////////////////////////////////////////////////////////////////// +#ifdef CATCH_CONFIG_VARIADIC_MACROS + #define INTERNAL_CATCH_MSG( messageType, resultDisposition, macroName, ... ) \ + do { \ + Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, "", resultDisposition ); \ + __catchResult << __VA_ARGS__ + ::Catch::StreamEndStop(); \ + __catchResult.captureResult( messageType ); \ + INTERNAL_CATCH_REACT( __catchResult ) \ + } while( Catch::alwaysFalse() ) +#else + #define INTERNAL_CATCH_MSG( messageType, resultDisposition, macroName, log ) \ + do { \ + Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, "", resultDisposition ); \ + __catchResult << log + ::Catch::StreamEndStop(); \ + __catchResult.captureResult( messageType ); \ + INTERNAL_CATCH_REACT( __catchResult ) \ + } while( Catch::alwaysFalse() ) +#endif + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_INFO( log, macroName ) \ + Catch::ScopedMessage INTERNAL_CATCH_UNIQUE_NAME( scopedMessage ) = Catch::MessageBuilder( macroName, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info ) << log; + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CHECK_THAT( arg, matcher, resultDisposition, macroName ) \ + do { \ + Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #arg ", " #matcher, resultDisposition ); \ + try { \ + std::string matcherAsString = (matcher).toString(); \ + __catchResult \ + .setLhs( Catch::toString( arg ) ) \ + .setRhs( matcherAsString == Catch::Detail::unprintableString ? #matcher : matcherAsString ) \ + .setOp( "matches" ) \ + .setResultType( (matcher).match( arg ) ); \ + __catchResult.captureExpression(); \ + } catch( ... ) { \ + __catchResult.useActiveException( resultDisposition | Catch::ResultDisposition::ContinueOnFailure ); \ + } \ + INTERNAL_CATCH_REACT( __catchResult ) \ + } while( Catch::alwaysFalse() ) + +// #included from: internal/catch_section.h +#define TWOBLUECUBES_CATCH_SECTION_H_INCLUDED + +// #included from: catch_section_info.h +#define TWOBLUECUBES_CATCH_SECTION_INFO_H_INCLUDED + +// #included from: catch_totals.hpp +#define TWOBLUECUBES_CATCH_TOTALS_HPP_INCLUDED + +#include <cstddef> + +namespace Catch { + + struct Counts { + Counts() : passed( 0 ), failed( 0 ), failedButOk( 0 ) {} + + Counts operator - ( Counts const& other ) const { + Counts diff; + diff.passed = passed - other.passed; + diff.failed = failed - other.failed; + diff.failedButOk = failedButOk - other.failedButOk; + return diff; + } + Counts& operator += ( Counts const& other ) { + passed += other.passed; + failed += other.failed; + failedButOk += other.failedButOk; + return *this; + } + + std::size_t total() const { + return passed + failed + failedButOk; + } + bool allPassed() const { + return failed == 0 && failedButOk == 0; + } + bool allOk() const { + return failed == 0; + } + + std::size_t passed; + std::size_t failed; + std::size_t failedButOk; + }; + + struct Totals { + + Totals operator - ( Totals const& other ) const { + Totals diff; + diff.assertions = assertions - other.assertions; + diff.testCases = testCases - other.testCases; + return diff; + } + + Totals delta( Totals const& prevTotals ) const { + Totals diff = *this - prevTotals; + if( diff.assertions.failed > 0 ) + ++diff.testCases.failed; + else if( diff.assertions.failedButOk > 0 ) + ++diff.testCases.failedButOk; + else + ++diff.testCases.passed; + return diff; + } + + Totals& operator += ( Totals const& other ) { + assertions += other.assertions; + testCases += other.testCases; + return *this; + } + + Counts assertions; + Counts testCases; + }; +} + +namespace Catch { + + struct SectionInfo { + SectionInfo + ( SourceLineInfo const& _lineInfo, + std::string const& _name, + std::string const& _description = std::string() ); + + std::string name; + std::string description; + SourceLineInfo lineInfo; + }; + + struct SectionEndInfo { + SectionEndInfo( SectionInfo const& _sectionInfo, Counts const& _prevAssertions, double _durationInSeconds ) + : sectionInfo( _sectionInfo ), prevAssertions( _prevAssertions ), durationInSeconds( _durationInSeconds ) + {} + + SectionInfo sectionInfo; + Counts prevAssertions; + double durationInSeconds; + }; + +} // end namespace Catch + +// #included from: catch_timer.h +#define TWOBLUECUBES_CATCH_TIMER_H_INCLUDED + +#ifdef CATCH_PLATFORM_WINDOWS +typedef unsigned long long uint64_t; +#else +#include <stdint.h> +#endif + +namespace Catch { + + class Timer { + public: + Timer() : m_ticks( 0 ) {} + void start(); + unsigned int getElapsedMicroseconds() const; + unsigned int getElapsedMilliseconds() const; + double getElapsedSeconds() const; + + private: + uint64_t m_ticks; + }; + +} // namespace Catch + +#include <string> + +namespace Catch { + + class Section : NonCopyable { + public: + Section( SectionInfo const& info ); + ~Section(); + + // This indicates whether the section should be executed or not + operator bool() const; + + private: + SectionInfo m_info; + + std::string m_name; + Counts m_assertions; + bool m_sectionIncluded; + Timer m_timer; + }; + +} // end namespace Catch + +#ifdef CATCH_CONFIG_VARIADIC_MACROS + #define INTERNAL_CATCH_SECTION( ... ) \ + if( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::SectionInfo( CATCH_INTERNAL_LINEINFO, __VA_ARGS__ ) ) +#else + #define INTERNAL_CATCH_SECTION( name, desc ) \ + if( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::SectionInfo( CATCH_INTERNAL_LINEINFO, name, desc ) ) +#endif + +// #included from: internal/catch_generators.hpp +#define TWOBLUECUBES_CATCH_GENERATORS_HPP_INCLUDED + +#include <iterator> +#include <vector> +#include <string> +#include <stdlib.h> + +namespace Catch { + +template<typename T> +struct IGenerator { + virtual ~IGenerator() {} + virtual T getValue( std::size_t index ) const = 0; + virtual std::size_t size () const = 0; +}; + +template<typename T> +class BetweenGenerator : public IGenerator<T> { +public: + BetweenGenerator( T from, T to ) : m_from( from ), m_to( to ){} + + virtual T getValue( std::size_t index ) const { + return m_from+static_cast<int>( index ); + } + + virtual std::size_t size() const { + return static_cast<std::size_t>( 1+m_to-m_from ); + } + +private: + + T m_from; + T m_to; +}; + +template<typename T> +class ValuesGenerator : public IGenerator<T> { +public: + ValuesGenerator(){} + + void add( T value ) { + m_values.push_back( value ); + } + + virtual T getValue( std::size_t index ) const { + return m_values[index]; + } + + virtual std::size_t size() const { + return m_values.size(); + } + +private: + std::vector<T> m_values; +}; + +template<typename T> +class CompositeGenerator { +public: + CompositeGenerator() : m_totalSize( 0 ) {} + + // *** Move semantics, similar to auto_ptr *** + CompositeGenerator( CompositeGenerator& other ) + : m_fileInfo( other.m_fileInfo ), + m_totalSize( 0 ) + { + move( other ); + } + + CompositeGenerator& setFileInfo( const char* fileInfo ) { + m_fileInfo = fileInfo; + return *this; + } + + ~CompositeGenerator() { + deleteAll( m_composed ); + } + + operator T () const { + size_t overallIndex = getCurrentContext().getGeneratorIndex( m_fileInfo, m_totalSize ); + + typename std::vector<const IGenerator<T>*>::const_iterator it = m_composed.begin(); + typename std::vector<const IGenerator<T>*>::const_iterator itEnd = m_composed.end(); + for( size_t index = 0; it != itEnd; ++it ) + { + const IGenerator<T>* generator = *it; + if( overallIndex >= index && overallIndex < index + generator->size() ) + { + return generator->getValue( overallIndex-index ); + } + index += generator->size(); + } + CATCH_INTERNAL_ERROR( "Indexed past end of generated range" ); + return T(); // Suppress spurious "not all control paths return a value" warning in Visual Studio - if you know how to fix this please do so + } + + void add( const IGenerator<T>* generator ) { + m_totalSize += generator->size(); + m_composed.push_back( generator ); + } + + CompositeGenerator& then( CompositeGenerator& other ) { + move( other ); + return *this; + } + + CompositeGenerator& then( T value ) { + ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>(); + valuesGen->add( value ); + add( valuesGen ); + return *this; + } + +private: + + void move( CompositeGenerator& other ) { + std::copy( other.m_composed.begin(), other.m_composed.end(), std::back_inserter( m_composed ) ); + m_totalSize += other.m_totalSize; + other.m_composed.clear(); + } + + std::vector<const IGenerator<T>*> m_composed; + std::string m_fileInfo; + size_t m_totalSize; +}; + +namespace Generators +{ + template<typename T> + CompositeGenerator<T> between( T from, T to ) { + CompositeGenerator<T> generators; + generators.add( new BetweenGenerator<T>( from, to ) ); + return generators; + } + + template<typename T> + CompositeGenerator<T> values( T val1, T val2 ) { + CompositeGenerator<T> generators; + ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>(); + valuesGen->add( val1 ); + valuesGen->add( val2 ); + generators.add( valuesGen ); + return generators; + } + + template<typename T> + CompositeGenerator<T> values( T val1, T val2, T val3 ){ + CompositeGenerator<T> generators; + ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>(); + valuesGen->add( val1 ); + valuesGen->add( val2 ); + valuesGen->add( val3 ); + generators.add( valuesGen ); + return generators; + } + + template<typename T> + CompositeGenerator<T> values( T val1, T val2, T val3, T val4 ) { + CompositeGenerator<T> generators; + ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>(); + valuesGen->add( val1 ); + valuesGen->add( val2 ); + valuesGen->add( val3 ); + valuesGen->add( val4 ); + generators.add( valuesGen ); + return generators; + } + +} // end namespace Generators + +using namespace Generators; + +} // end namespace Catch + +#define INTERNAL_CATCH_LINESTR2( line ) #line +#define INTERNAL_CATCH_LINESTR( line ) INTERNAL_CATCH_LINESTR2( line ) + +#define INTERNAL_CATCH_GENERATE( expr ) expr.setFileInfo( __FILE__ "(" INTERNAL_CATCH_LINESTR( __LINE__ ) ")" ) + +// #included from: internal/catch_interfaces_exception.h +#define TWOBLUECUBES_CATCH_INTERFACES_EXCEPTION_H_INCLUDED + +#include <string> +#include <vector> + +// #included from: catch_interfaces_registry_hub.h +#define TWOBLUECUBES_CATCH_INTERFACES_REGISTRY_HUB_H_INCLUDED + +#include <string> + +namespace Catch { + + class TestCase; + struct ITestCaseRegistry; + struct IExceptionTranslatorRegistry; + struct IExceptionTranslator; + struct IReporterRegistry; + struct IReporterFactory; + + struct IRegistryHub { + virtual ~IRegistryHub(); + + virtual IReporterRegistry const& getReporterRegistry() const = 0; + virtual ITestCaseRegistry const& getTestCaseRegistry() const = 0; + virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() = 0; + }; + + struct IMutableRegistryHub { + virtual ~IMutableRegistryHub(); + virtual void registerReporter( std::string const& name, Ptr<IReporterFactory> const& factory ) = 0; + virtual void registerListener( Ptr<IReporterFactory> const& factory ) = 0; + virtual void registerTest( TestCase const& testInfo ) = 0; + virtual void registerTranslator( const IExceptionTranslator* translator ) = 0; + }; + + IRegistryHub& getRegistryHub(); + IMutableRegistryHub& getMutableRegistryHub(); + void cleanUp(); + std::string translateActiveException(); + +} + +namespace Catch { + + typedef std::string(*exceptionTranslateFunction)(); + + struct IExceptionTranslator; + typedef std::vector<const IExceptionTranslator*> ExceptionTranslators; + + struct IExceptionTranslator { + virtual ~IExceptionTranslator(); + virtual std::string translate( ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd ) const = 0; + }; + + struct IExceptionTranslatorRegistry { + virtual ~IExceptionTranslatorRegistry(); + + virtual std::string translateActiveException() const = 0; + }; + + class ExceptionTranslatorRegistrar { + template<typename T> + class ExceptionTranslator : public IExceptionTranslator { + public: + + ExceptionTranslator( std::string(*translateFunction)( T& ) ) + : m_translateFunction( translateFunction ) + {} + + virtual std::string translate( ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd ) const CATCH_OVERRIDE { + try { + if( it == itEnd ) + throw; + else + return (*it)->translate( it+1, itEnd ); + } + catch( T& ex ) { + return m_translateFunction( ex ); + } + } + + protected: + std::string(*m_translateFunction)( T& ); + }; + + public: + template<typename T> + ExceptionTranslatorRegistrar( std::string(*translateFunction)( T& ) ) { + getMutableRegistryHub().registerTranslator + ( new ExceptionTranslator<T>( translateFunction ) ); + } + }; +} + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) \ + static std::string INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator )( signature ); \ + namespace{ Catch::ExceptionTranslatorRegistrar INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionRegistrar )( &INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator ) ); }\ + static std::string INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator )( signature ) + +// #included from: internal/catch_approx.hpp +#define TWOBLUECUBES_CATCH_APPROX_HPP_INCLUDED + +#include <cmath> +#include <limits> + +namespace Catch { +namespace Detail { + + class Approx { + public: + explicit Approx ( double value ) + : m_epsilon( std::numeric_limits<float>::epsilon()*100 ), + m_scale( 1.0 ), + m_value( value ) + {} + + Approx( Approx const& other ) + : m_epsilon( other.m_epsilon ), + m_scale( other.m_scale ), + m_value( other.m_value ) + {} + + static Approx custom() { + return Approx( 0 ); + } + + Approx operator()( double value ) { + Approx approx( value ); + approx.epsilon( m_epsilon ); + approx.scale( m_scale ); + return approx; + } + + friend bool operator == ( double lhs, Approx const& rhs ) { + // Thanks to Richard Harris for his help refining this formula + return fabs( lhs - rhs.m_value ) < rhs.m_epsilon * (rhs.m_scale + (std::max)( fabs(lhs), fabs(rhs.m_value) ) ); + } + + friend bool operator == ( Approx const& lhs, double rhs ) { + return operator==( rhs, lhs ); + } + + friend bool operator != ( double lhs, Approx const& rhs ) { + return !operator==( lhs, rhs ); + } + + friend bool operator != ( Approx const& lhs, double rhs ) { + return !operator==( rhs, lhs ); + } + + Approx& epsilon( double newEpsilon ) { + m_epsilon = newEpsilon; + return *this; + } + + Approx& scale( double newScale ) { + m_scale = newScale; + return *this; + } + + std::string toString() const { + std::ostringstream oss; + oss << "Approx( " << Catch::toString( m_value ) << " )"; + return oss.str(); + } + + private: + double m_epsilon; + double m_scale; + double m_value; + }; +} + +template<> +inline std::string toString<Detail::Approx>( Detail::Approx const& value ) { + return value.toString(); +} + +} // end namespace Catch + +// #included from: internal/catch_interfaces_tag_alias_registry.h +#define TWOBLUECUBES_CATCH_INTERFACES_TAG_ALIAS_REGISTRY_H_INCLUDED + +// #included from: catch_tag_alias.h +#define TWOBLUECUBES_CATCH_TAG_ALIAS_H_INCLUDED + +#include <string> + +namespace Catch { + + struct TagAlias { + TagAlias( std::string _tag, SourceLineInfo _lineInfo ) : tag( _tag ), lineInfo( _lineInfo ) {} + + std::string tag; + SourceLineInfo lineInfo; + }; + + struct RegistrarForTagAliases { + RegistrarForTagAliases( char const* alias, char const* tag, SourceLineInfo const& lineInfo ); + }; + +} // end namespace Catch + +#define CATCH_REGISTER_TAG_ALIAS( alias, spec ) namespace{ Catch::RegistrarForTagAliases INTERNAL_CATCH_UNIQUE_NAME( AutoRegisterTagAlias )( alias, spec, CATCH_INTERNAL_LINEINFO ); } +// #included from: catch_option.hpp +#define TWOBLUECUBES_CATCH_OPTION_HPP_INCLUDED + +namespace Catch { + + // An optional type + template<typename T> + class Option { + public: + Option() : nullableValue( CATCH_NULL ) {} + Option( T const& _value ) + : nullableValue( new( storage ) T( _value ) ) + {} + Option( Option const& _other ) + : nullableValue( _other ? new( storage ) T( *_other ) : CATCH_NULL ) + {} + + ~Option() { + reset(); + } + + Option& operator= ( Option const& _other ) { + if( &_other != this ) { + reset(); + if( _other ) + nullableValue = new( storage ) T( *_other ); + } + return *this; + } + Option& operator = ( T const& _value ) { + reset(); + nullableValue = new( storage ) T( _value ); + return *this; + } + + void reset() { + if( nullableValue ) + nullableValue->~T(); + nullableValue = CATCH_NULL; + } + + T& operator*() { return *nullableValue; } + T const& operator*() const { return *nullableValue; } + T* operator->() { return nullableValue; } + const T* operator->() const { return nullableValue; } + + T valueOr( T const& defaultValue ) const { + return nullableValue ? *nullableValue : defaultValue; + } + + bool some() const { return nullableValue != CATCH_NULL; } + bool none() const { return nullableValue == CATCH_NULL; } + + bool operator !() const { return nullableValue == CATCH_NULL; } + operator SafeBool::type() const { + return SafeBool::makeSafe( some() ); + } + + private: + T* nullableValue; + char storage[sizeof(T)]; + }; + +} // end namespace Catch + +namespace Catch { + + struct ITagAliasRegistry { + virtual ~ITagAliasRegistry(); + virtual Option<TagAlias> find( std::string const& alias ) const = 0; + virtual std::string expandAliases( std::string const& unexpandedTestSpec ) const = 0; + + static ITagAliasRegistry const& get(); + }; + +} // end namespace Catch + +// These files are included here so the single_include script doesn't put them +// in the conditionally compiled sections +// #included from: internal/catch_test_case_info.h +#define TWOBLUECUBES_CATCH_TEST_CASE_INFO_H_INCLUDED + +#include <string> +#include <set> + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wpadded" +#endif + +namespace Catch { + + struct ITestCase; + + struct TestCaseInfo { + enum SpecialProperties{ + None = 0, + IsHidden = 1 << 1, + ShouldFail = 1 << 2, + MayFail = 1 << 3, + Throws = 1 << 4 + }; + + TestCaseInfo( std::string const& _name, + std::string const& _className, + std::string const& _description, + std::set<std::string> const& _tags, + SourceLineInfo const& _lineInfo ); + + TestCaseInfo( TestCaseInfo const& other ); + + friend void setTags( TestCaseInfo& testCaseInfo, std::set<std::string> const& tags ); + + bool isHidden() const; + bool throws() const; + bool okToFail() const; + bool expectedToFail() const; + + std::string name; + std::string className; + std::string description; + std::set<std::string> tags; + std::set<std::string> lcaseTags; + std::string tagsAsString; + SourceLineInfo lineInfo; + SpecialProperties properties; + }; + + class TestCase : public TestCaseInfo { + public: + + TestCase( ITestCase* testCase, TestCaseInfo const& info ); + TestCase( TestCase const& other ); + + TestCase withName( std::string const& _newName ) const; + + void invoke() const; + + TestCaseInfo const& getTestCaseInfo() const; + + void swap( TestCase& other ); + bool operator == ( TestCase const& other ) const; + bool operator < ( TestCase const& other ) const; + TestCase& operator = ( TestCase const& other ); + + private: + Ptr<ITestCase> test; + }; + + TestCase makeTestCase( ITestCase* testCase, + std::string const& className, + std::string const& name, + std::string const& description, + SourceLineInfo const& lineInfo ); +} + +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + + +#ifdef __OBJC__ +// #included from: internal/catch_objc.hpp +#define TWOBLUECUBES_CATCH_OBJC_HPP_INCLUDED + +#import <objc/runtime.h> + +#include <string> + +// NB. Any general catch headers included here must be included +// in catch.hpp first to make sure they are included by the single +// header for non obj-usage + +/////////////////////////////////////////////////////////////////////////////// +// This protocol is really only here for (self) documenting purposes, since +// all its methods are optional. +@protocol OcFixture + +@optional + +-(void) setUp; +-(void) tearDown; + +@end + +namespace Catch { + + class OcMethod : public SharedImpl<ITestCase> { + + public: + OcMethod( Class cls, SEL sel ) : m_cls( cls ), m_sel( sel ) {} + + virtual void invoke() const { + id obj = [[m_cls alloc] init]; + + performOptionalSelector( obj, @selector(setUp) ); + performOptionalSelector( obj, m_sel ); + performOptionalSelector( obj, @selector(tearDown) ); + + arcSafeRelease( obj ); + } + private: + virtual ~OcMethod() {} + + Class m_cls; + SEL m_sel; + }; + + namespace Detail{ + + inline std::string getAnnotation( Class cls, + std::string const& annotationName, + std::string const& testCaseName ) { + NSString* selStr = [[NSString alloc] initWithFormat:@"Catch_%s_%s", annotationName.c_str(), testCaseName.c_str()]; + SEL sel = NSSelectorFromString( selStr ); + arcSafeRelease( selStr ); + id value = performOptionalSelector( cls, sel ); + if( value ) + return [(NSString*)value UTF8String]; + return ""; + } + } + + inline size_t registerTestMethods() { + size_t noTestMethods = 0; + int noClasses = objc_getClassList( CATCH_NULL, 0 ); + + Class* classes = (CATCH_UNSAFE_UNRETAINED Class *)malloc( sizeof(Class) * noClasses); + objc_getClassList( classes, noClasses ); + + for( int c = 0; c < noClasses; c++ ) { + Class cls = classes[c]; + { + u_int count; + Method* methods = class_copyMethodList( cls, &count ); + for( u_int m = 0; m < count ; m++ ) { + SEL selector = method_getName(methods[m]); + std::string methodName = sel_getName(selector); + if( startsWith( methodName, "Catch_TestCase_" ) ) { + std::string testCaseName = methodName.substr( 15 ); + std::string name = Detail::getAnnotation( cls, "Name", testCaseName ); + std::string desc = Detail::getAnnotation( cls, "Description", testCaseName ); + const char* className = class_getName( cls ); + + getMutableRegistryHub().registerTest( makeTestCase( new OcMethod( cls, selector ), className, name.c_str(), desc.c_str(), SourceLineInfo() ) ); + noTestMethods++; + } + } + free(methods); + } + } + return noTestMethods; + } + + namespace Matchers { + namespace Impl { + namespace NSStringMatchers { + + template<typename MatcherT> + struct StringHolder : MatcherImpl<MatcherT, NSString*>{ + StringHolder( NSString* substr ) : m_substr( [substr copy] ){} + StringHolder( StringHolder const& other ) : m_substr( [other.m_substr copy] ){} + StringHolder() { + arcSafeRelease( m_substr ); + } + + NSString* m_substr; + }; + + struct Equals : StringHolder<Equals> { + Equals( NSString* substr ) : StringHolder( substr ){} + + virtual bool match( ExpressionType const& str ) const { + return (str != nil || m_substr == nil ) && + [str isEqualToString:m_substr]; + } + + virtual std::string toString() const { + return "equals string: " + Catch::toString( m_substr ); + } + }; + + struct Contains : StringHolder<Contains> { + Contains( NSString* substr ) : StringHolder( substr ){} + + virtual bool match( ExpressionType const& str ) const { + return (str != nil || m_substr == nil ) && + [str rangeOfString:m_substr].location != NSNotFound; + } + + virtual std::string toString() const { + return "contains string: " + Catch::toString( m_substr ); + } + }; + + struct StartsWith : StringHolder<StartsWith> { + StartsWith( NSString* substr ) : StringHolder( substr ){} + + virtual bool match( ExpressionType const& str ) const { + return (str != nil || m_substr == nil ) && + [str rangeOfString:m_substr].location == 0; + } + + virtual std::string toString() const { + return "starts with: " + Catch::toString( m_substr ); + } + }; + struct EndsWith : StringHolder<EndsWith> { + EndsWith( NSString* substr ) : StringHolder( substr ){} + + virtual bool match( ExpressionType const& str ) const { + return (str != nil || m_substr == nil ) && + [str rangeOfString:m_substr].location == [str length] - [m_substr length]; + } + + virtual std::string toString() const { + return "ends with: " + Catch::toString( m_substr ); + } + }; + + } // namespace NSStringMatchers + } // namespace Impl + + inline Impl::NSStringMatchers::Equals + Equals( NSString* substr ){ return Impl::NSStringMatchers::Equals( substr ); } + + inline Impl::NSStringMatchers::Contains + Contains( NSString* substr ){ return Impl::NSStringMatchers::Contains( substr ); } + + inline Impl::NSStringMatchers::StartsWith + StartsWith( NSString* substr ){ return Impl::NSStringMatchers::StartsWith( substr ); } + + inline Impl::NSStringMatchers::EndsWith + EndsWith( NSString* substr ){ return Impl::NSStringMatchers::EndsWith( substr ); } + + } // namespace Matchers + + using namespace Matchers; + +} // namespace Catch + +/////////////////////////////////////////////////////////////////////////////// +#define OC_TEST_CASE( name, desc )\ ++(NSString*) INTERNAL_CATCH_UNIQUE_NAME( Catch_Name_test ) \ +{\ +return @ name; \ +}\ ++(NSString*) INTERNAL_CATCH_UNIQUE_NAME( Catch_Description_test ) \ +{ \ +return @ desc; \ +} \ +-(void) INTERNAL_CATCH_UNIQUE_NAME( Catch_TestCase_test ) + +#endif + +#ifdef CATCH_IMPL +// #included from: internal/catch_impl.hpp +#define TWOBLUECUBES_CATCH_IMPL_HPP_INCLUDED + +// Collect all the implementation files together here +// These are the equivalent of what would usually be cpp files + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wweak-vtables" +#endif + +// #included from: ../catch_session.hpp +#define TWOBLUECUBES_CATCH_RUNNER_HPP_INCLUDED + +// #included from: internal/catch_commandline.hpp +#define TWOBLUECUBES_CATCH_COMMANDLINE_HPP_INCLUDED + +// #included from: catch_config.hpp +#define TWOBLUECUBES_CATCH_CONFIG_HPP_INCLUDED + +// #included from: catch_test_spec_parser.hpp +#define TWOBLUECUBES_CATCH_TEST_SPEC_PARSER_HPP_INCLUDED + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wpadded" +#endif + +// #included from: catch_test_spec.hpp +#define TWOBLUECUBES_CATCH_TEST_SPEC_HPP_INCLUDED + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wpadded" +#endif + +// #included from: catch_wildcard_pattern.hpp +#define TWOBLUECUBES_CATCH_WILDCARD_PATTERN_HPP_INCLUDED + +namespace Catch +{ + class WildcardPattern { + enum WildcardPosition { + NoWildcard = 0, + WildcardAtStart = 1, + WildcardAtEnd = 2, + WildcardAtBothEnds = WildcardAtStart | WildcardAtEnd + }; + + public: + + WildcardPattern( std::string const& pattern, CaseSensitive::Choice caseSensitivity ) + : m_caseSensitivity( caseSensitivity ), + m_wildcard( NoWildcard ), + m_pattern( adjustCase( pattern ) ) + { + if( startsWith( m_pattern, "*" ) ) { + m_pattern = m_pattern.substr( 1 ); + m_wildcard = WildcardAtStart; + } + if( endsWith( m_pattern, "*" ) ) { + m_pattern = m_pattern.substr( 0, m_pattern.size()-1 ); + m_wildcard = static_cast<WildcardPosition>( m_wildcard | WildcardAtEnd ); + } + } + virtual ~WildcardPattern(); + virtual bool matches( std::string const& str ) const { + switch( m_wildcard ) { + case NoWildcard: + return m_pattern == adjustCase( str ); + case WildcardAtStart: + return endsWith( adjustCase( str ), m_pattern ); + case WildcardAtEnd: + return startsWith( adjustCase( str ), m_pattern ); + case WildcardAtBothEnds: + return contains( adjustCase( str ), m_pattern ); + } + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunreachable-code" +#endif + throw std::logic_error( "Unknown enum" ); +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + } + private: + std::string adjustCase( std::string const& str ) const { + return m_caseSensitivity == CaseSensitive::No ? toLower( str ) : str; + } + CaseSensitive::Choice m_caseSensitivity; + WildcardPosition m_wildcard; + std::string m_pattern; + }; +} + +#include <string> +#include <vector> + +namespace Catch { + + class TestSpec { + struct Pattern : SharedImpl<> { + virtual ~Pattern(); + virtual bool matches( TestCaseInfo const& testCase ) const = 0; + }; + class NamePattern : public Pattern { + public: + NamePattern( std::string const& name ) + : m_wildcardPattern( toLower( name ), CaseSensitive::No ) + {} + virtual ~NamePattern(); + virtual bool matches( TestCaseInfo const& testCase ) const { + return m_wildcardPattern.matches( toLower( testCase.name ) ); + } + private: + WildcardPattern m_wildcardPattern; + }; + + class TagPattern : public Pattern { + public: + TagPattern( std::string const& tag ) : m_tag( toLower( tag ) ) {} + virtual ~TagPattern(); + virtual bool matches( TestCaseInfo const& testCase ) const { + return testCase.lcaseTags.find( m_tag ) != testCase.lcaseTags.end(); + } + private: + std::string m_tag; + }; + + class ExcludedPattern : public Pattern { + public: + ExcludedPattern( Ptr<Pattern> const& underlyingPattern ) : m_underlyingPattern( underlyingPattern ) {} + virtual ~ExcludedPattern(); + virtual bool matches( TestCaseInfo const& testCase ) const { return !m_underlyingPattern->matches( testCase ); } + private: + Ptr<Pattern> m_underlyingPattern; + }; + + struct Filter { + std::vector<Ptr<Pattern> > m_patterns; + + bool matches( TestCaseInfo const& testCase ) const { + // All patterns in a filter must match for the filter to be a match + for( std::vector<Ptr<Pattern> >::const_iterator it = m_patterns.begin(), itEnd = m_patterns.end(); it != itEnd; ++it ) + if( !(*it)->matches( testCase ) ) + return false; + return true; + } + }; + + public: + bool hasFilters() const { + return !m_filters.empty(); + } + bool matches( TestCaseInfo const& testCase ) const { + // A TestSpec matches if any filter matches + for( std::vector<Filter>::const_iterator it = m_filters.begin(), itEnd = m_filters.end(); it != itEnd; ++it ) + if( it->matches( testCase ) ) + return true; + return false; + } + + private: + std::vector<Filter> m_filters; + + friend class TestSpecParser; + }; +} + +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + +namespace Catch { + + class TestSpecParser { + enum Mode{ None, Name, QuotedName, Tag }; + Mode m_mode; + bool m_exclusion; + std::size_t m_start, m_pos; + std::string m_arg; + TestSpec::Filter m_currentFilter; + TestSpec m_testSpec; + ITagAliasRegistry const* m_tagAliases; + + public: + TestSpecParser( ITagAliasRegistry const& tagAliases ) : m_tagAliases( &tagAliases ) {} + + TestSpecParser& parse( std::string const& arg ) { + m_mode = None; + m_exclusion = false; + m_start = std::string::npos; + m_arg = m_tagAliases->expandAliases( arg ); + for( m_pos = 0; m_pos < m_arg.size(); ++m_pos ) + visitChar( m_arg[m_pos] ); + if( m_mode == Name ) + addPattern<TestSpec::NamePattern>(); + return *this; + } + TestSpec testSpec() { + addFilter(); + return m_testSpec; + } + private: + void visitChar( char c ) { + if( m_mode == None ) { + switch( c ) { + case ' ': return; + case '~': m_exclusion = true; return; + case '[': return startNewMode( Tag, ++m_pos ); + case '"': return startNewMode( QuotedName, ++m_pos ); + default: startNewMode( Name, m_pos ); break; + } + } + if( m_mode == Name ) { + if( c == ',' ) { + addPattern<TestSpec::NamePattern>(); + addFilter(); + } + else if( c == '[' ) { + if( subString() == "exclude:" ) + m_exclusion = true; + else + addPattern<TestSpec::NamePattern>(); + startNewMode( Tag, ++m_pos ); + } + } + else if( m_mode == QuotedName && c == '"' ) + addPattern<TestSpec::NamePattern>(); + else if( m_mode == Tag && c == ']' ) + addPattern<TestSpec::TagPattern>(); + } + void startNewMode( Mode mode, std::size_t start ) { + m_mode = mode; + m_start = start; + } + std::string subString() const { return m_arg.substr( m_start, m_pos - m_start ); } + template<typename T> + void addPattern() { + std::string token = subString(); + if( startsWith( token, "exclude:" ) ) { + m_exclusion = true; + token = token.substr( 8 ); + } + if( !token.empty() ) { + Ptr<TestSpec::Pattern> pattern = new T( token ); + if( m_exclusion ) + pattern = new TestSpec::ExcludedPattern( pattern ); + m_currentFilter.m_patterns.push_back( pattern ); + } + m_exclusion = false; + m_mode = None; + } + void addFilter() { + if( !m_currentFilter.m_patterns.empty() ) { + m_testSpec.m_filters.push_back( m_currentFilter ); + m_currentFilter = TestSpec::Filter(); + } + } + }; + inline TestSpec parseTestSpec( std::string const& arg ) { + return TestSpecParser( ITagAliasRegistry::get() ).parse( arg ).testSpec(); + } + +} // namespace Catch + +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + +// #included from: catch_interfaces_config.h +#define TWOBLUECUBES_CATCH_INTERFACES_CONFIG_H_INCLUDED + +#include <iostream> +#include <string> +#include <vector> + +namespace Catch { + + struct Verbosity { enum Level { + NoOutput = 0, + Quiet, + Normal + }; }; + + struct WarnAbout { enum What { + Nothing = 0x00, + NoAssertions = 0x01 + }; }; + + struct ShowDurations { enum OrNot { + DefaultForReporter, + Always, + Never + }; }; + struct RunTests { enum InWhatOrder { + InDeclarationOrder, + InLexicographicalOrder, + InRandomOrder + }; }; + struct UseColour { enum YesOrNo { + Auto, + Yes, + No + }; }; + + class TestSpec; + + struct IConfig : IShared { + + virtual ~IConfig(); + + virtual bool allowThrows() const = 0; + virtual std::ostream& stream() const = 0; + virtual std::string name() const = 0; + virtual bool includeSuccessfulResults() const = 0; + virtual bool shouldDebugBreak() const = 0; + virtual bool warnAboutMissingAssertions() const = 0; + virtual int abortAfter() const = 0; + virtual bool showInvisibles() const = 0; + virtual ShowDurations::OrNot showDurations() const = 0; + virtual TestSpec const& testSpec() const = 0; + virtual RunTests::InWhatOrder runOrder() const = 0; + virtual unsigned int rngSeed() const = 0; + virtual UseColour::YesOrNo useColour() const = 0; + }; +} + +// #included from: catch_stream.h +#define TWOBLUECUBES_CATCH_STREAM_H_INCLUDED + +// #included from: catch_streambuf.h +#define TWOBLUECUBES_CATCH_STREAMBUF_H_INCLUDED + +#include <streambuf> + +namespace Catch { + + class StreamBufBase : public std::streambuf { + public: + virtual ~StreamBufBase() CATCH_NOEXCEPT; + }; +} + +#include <streambuf> +#include <ostream> +#include <fstream> + +namespace Catch { + + std::ostream& cout(); + std::ostream& cerr(); + + struct IStream { + virtual ~IStream() CATCH_NOEXCEPT; + virtual std::ostream& stream() const = 0; + }; + + class FileStream : public IStream { + mutable std::ofstream m_ofs; + public: + FileStream( std::string const& filename ); + virtual ~FileStream() CATCH_NOEXCEPT; + public: // IStream + virtual std::ostream& stream() const CATCH_OVERRIDE; + }; + + class CoutStream : public IStream { + mutable std::ostream m_os; + public: + CoutStream(); + virtual ~CoutStream() CATCH_NOEXCEPT; + + public: // IStream + virtual std::ostream& stream() const CATCH_OVERRIDE; + }; + + class DebugOutStream : public IStream { + std::auto_ptr<StreamBufBase> m_streamBuf; + mutable std::ostream m_os; + public: + DebugOutStream(); + virtual ~DebugOutStream() CATCH_NOEXCEPT; + + public: // IStream + virtual std::ostream& stream() const CATCH_OVERRIDE; + }; +} + +#include <memory> +#include <vector> +#include <string> +#include <iostream> +#include <ctime> + +#ifndef CATCH_CONFIG_CONSOLE_WIDTH +#define CATCH_CONFIG_CONSOLE_WIDTH 80 +#endif + +namespace Catch { + + struct ConfigData { + + ConfigData() + : listTests( false ), + listTags( false ), + listReporters( false ), + listTestNamesOnly( false ), + showSuccessfulTests( false ), + shouldDebugBreak( false ), + noThrow( false ), + showHelp( false ), + showInvisibles( false ), + filenamesAsTags( false ), + abortAfter( -1 ), + rngSeed( 0 ), + verbosity( Verbosity::Normal ), + warnings( WarnAbout::Nothing ), + showDurations( ShowDurations::DefaultForReporter ), + runOrder( RunTests::InDeclarationOrder ), + useColour( UseColour::Auto ) + {} + + bool listTests; + bool listTags; + bool listReporters; + bool listTestNamesOnly; + + bool showSuccessfulTests; + bool shouldDebugBreak; + bool noThrow; + bool showHelp; + bool showInvisibles; + bool filenamesAsTags; + + int abortAfter; + unsigned int rngSeed; + + Verbosity::Level verbosity; + WarnAbout::What warnings; + ShowDurations::OrNot showDurations; + RunTests::InWhatOrder runOrder; + UseColour::YesOrNo useColour; + + std::string outputFilename; + std::string name; + std::string processName; + + std::vector<std::string> reporterNames; + std::vector<std::string> testsOrTags; + }; + + class Config : public SharedImpl<IConfig> { + private: + Config( Config const& other ); + Config& operator = ( Config const& other ); + virtual void dummy(); + public: + + Config() + {} + + Config( ConfigData const& data ) + : m_data( data ), + m_stream( openStream() ) + { + if( !data.testsOrTags.empty() ) { + TestSpecParser parser( ITagAliasRegistry::get() ); + for( std::size_t i = 0; i < data.testsOrTags.size(); ++i ) + parser.parse( data.testsOrTags[i] ); + m_testSpec = parser.testSpec(); + } + } + + virtual ~Config() { + } + + std::string const& getFilename() const { + return m_data.outputFilename ; + } + + bool listTests() const { return m_data.listTests; } + bool listTestNamesOnly() const { return m_data.listTestNamesOnly; } + bool listTags() const { return m_data.listTags; } + bool listReporters() const { return m_data.listReporters; } + + std::string getProcessName() const { return m_data.processName; } + + bool shouldDebugBreak() const { return m_data.shouldDebugBreak; } + + std::vector<std::string> getReporterNames() const { return m_data.reporterNames; } + + int abortAfter() const { return m_data.abortAfter; } + + TestSpec const& testSpec() const { return m_testSpec; } + + bool showHelp() const { return m_data.showHelp; } + bool showInvisibles() const { return m_data.showInvisibles; } + + // IConfig interface + virtual bool allowThrows() const { return !m_data.noThrow; } + virtual std::ostream& stream() const { return m_stream->stream(); } + virtual std::string name() const { return m_data.name.empty() ? m_data.processName : m_data.name; } + virtual bool includeSuccessfulResults() const { return m_data.showSuccessfulTests; } + virtual bool warnAboutMissingAssertions() const { return m_data.warnings & WarnAbout::NoAssertions; } + virtual ShowDurations::OrNot showDurations() const { return m_data.showDurations; } + virtual RunTests::InWhatOrder runOrder() const { return m_data.runOrder; } + virtual unsigned int rngSeed() const { return m_data.rngSeed; } + virtual UseColour::YesOrNo useColour() const { return m_data.useColour; } + + private: + + IStream const* openStream() { + if( m_data.outputFilename.empty() ) + return new CoutStream(); + else if( m_data.outputFilename[0] == '%' ) { + if( m_data.outputFilename == "%debug" ) + return new DebugOutStream(); + else + throw std::domain_error( "Unrecognised stream: " + m_data.outputFilename ); + } + else + return new FileStream( m_data.outputFilename ); + } + ConfigData m_data; + + std::auto_ptr<IStream const> m_stream; + TestSpec m_testSpec; + }; + +} // end namespace Catch + +// #included from: catch_clara.h +#define TWOBLUECUBES_CATCH_CLARA_H_INCLUDED + +// Use Catch's value for console width (store Clara's off to the side, if present) +#ifdef CLARA_CONFIG_CONSOLE_WIDTH +#define CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH CLARA_CONFIG_CONSOLE_WIDTH +#undef CLARA_CONFIG_CONSOLE_WIDTH +#endif +#define CLARA_CONFIG_CONSOLE_WIDTH CATCH_CONFIG_CONSOLE_WIDTH + +// Declare Clara inside the Catch namespace +#define STITCH_CLARA_OPEN_NAMESPACE namespace Catch { +// #included from: ../external/clara.h + +// Version 0.0.1.1 + +// Only use header guard if we are not using an outer namespace +#if !defined(TWOBLUECUBES_CLARA_H_INCLUDED) || defined(STITCH_CLARA_OPEN_NAMESPACE) + +#ifndef STITCH_CLARA_OPEN_NAMESPACE +#define TWOBLUECUBES_CLARA_H_INCLUDED +#define STITCH_CLARA_OPEN_NAMESPACE +#define STITCH_CLARA_CLOSE_NAMESPACE +#else +#define STITCH_CLARA_CLOSE_NAMESPACE } +#endif + +#define STITCH_TBC_TEXT_FORMAT_OPEN_NAMESPACE STITCH_CLARA_OPEN_NAMESPACE + +// ----------- #included from tbc_text_format.h ----------- + +// Only use header guard if we are not using an outer namespace +#if !defined(TBC_TEXT_FORMAT_H_INCLUDED) || defined(STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE) +#ifndef STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE +#define TBC_TEXT_FORMAT_H_INCLUDED +#endif + +#include <string> +#include <vector> +#include <sstream> +#include <algorithm> + +// Use optional outer namespace +#ifdef STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE +namespace STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE { +#endif + +namespace Tbc { + +#ifdef TBC_TEXT_FORMAT_CONSOLE_WIDTH + const unsigned int consoleWidth = TBC_TEXT_FORMAT_CONSOLE_WIDTH; +#else + const unsigned int consoleWidth = 80; +#endif + + struct TextAttributes { + TextAttributes() + : initialIndent( std::string::npos ), + indent( 0 ), + width( consoleWidth-1 ), + tabChar( '\t' ) + {} + + TextAttributes& setInitialIndent( std::size_t _value ) { initialIndent = _value; return *this; } + TextAttributes& setIndent( std::size_t _value ) { indent = _value; return *this; } + TextAttributes& setWidth( std::size_t _value ) { width = _value; return *this; } + TextAttributes& setTabChar( char _value ) { tabChar = _value; return *this; } + + std::size_t initialIndent; // indent of first line, or npos + std::size_t indent; // indent of subsequent lines, or all if initialIndent is npos + std::size_t width; // maximum width of text, including indent. Longer text will wrap + char tabChar; // If this char is seen the indent is changed to current pos + }; + + class Text { + public: + Text( std::string const& _str, TextAttributes const& _attr = TextAttributes() ) + : attr( _attr ) + { + std::string wrappableChars = " [({.,/|\\-"; + std::size_t indent = _attr.initialIndent != std::string::npos + ? _attr.initialIndent + : _attr.indent; + std::string remainder = _str; + + while( !remainder.empty() ) { + if( lines.size() >= 1000 ) { + lines.push_back( "... message truncated due to excessive size" ); + return; + } + std::size_t tabPos = std::string::npos; + std::size_t width = (std::min)( remainder.size(), _attr.width - indent ); + std::size_t pos = remainder.find_first_of( '\n' ); + if( pos <= width ) { + width = pos; + } + pos = remainder.find_last_of( _attr.tabChar, width ); + if( pos != std::string::npos ) { + tabPos = pos; + if( remainder[width] == '\n' ) + width--; + remainder = remainder.substr( 0, tabPos ) + remainder.substr( tabPos+1 ); + } + + if( width == remainder.size() ) { + spliceLine( indent, remainder, width ); + } + else if( remainder[width] == '\n' ) { + spliceLine( indent, remainder, width ); + if( width <= 1 || remainder.size() != 1 ) + remainder = remainder.substr( 1 ); + indent = _attr.indent; + } + else { + pos = remainder.find_last_of( wrappableChars, width ); + if( pos != std::string::npos && pos > 0 ) { + spliceLine( indent, remainder, pos ); + if( remainder[0] == ' ' ) + remainder = remainder.substr( 1 ); + } + else { + spliceLine( indent, remainder, width-1 ); + lines.back() += "-"; + } + if( lines.size() == 1 ) + indent = _attr.indent; + if( tabPos != std::string::npos ) + indent += tabPos; + } + } + } + + void spliceLine( std::size_t _indent, std::string& _remainder, std::size_t _pos ) { + lines.push_back( std::string( _indent, ' ' ) + _remainder.substr( 0, _pos ) ); + _remainder = _remainder.substr( _pos ); + } + + typedef std::vector<std::string>::const_iterator const_iterator; + + const_iterator begin() const { return lines.begin(); } + const_iterator end() const { return lines.end(); } + std::string const& last() const { return lines.back(); } + std::size_t size() const { return lines.size(); } + std::string const& operator[]( std::size_t _index ) const { return lines[_index]; } + std::string toString() const { + std::ostringstream oss; + oss << *this; + return oss.str(); + } + + inline friend std::ostream& operator << ( std::ostream& _stream, Text const& _text ) { + for( Text::const_iterator it = _text.begin(), itEnd = _text.end(); + it != itEnd; ++it ) { + if( it != _text.begin() ) + _stream << "\n"; + _stream << *it; + } + return _stream; + } + + private: + std::string str; + TextAttributes attr; + std::vector<std::string> lines; + }; + +} // end namespace Tbc + +#ifdef STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE +} // end outer namespace +#endif + +#endif // TBC_TEXT_FORMAT_H_INCLUDED + +// ----------- end of #include from tbc_text_format.h ----------- +// ........... back in clara.h + +#undef STITCH_TBC_TEXT_FORMAT_OPEN_NAMESPACE + +// ----------- #included from clara_compilers.h ----------- + +#ifndef TWOBLUECUBES_CLARA_COMPILERS_H_INCLUDED +#define TWOBLUECUBES_CLARA_COMPILERS_H_INCLUDED + +// Detect a number of compiler features - mostly C++11/14 conformance - by compiler +// The following features are defined: +// +// CLARA_CONFIG_CPP11_NULLPTR : is nullptr supported? +// CLARA_CONFIG_CPP11_NOEXCEPT : is noexcept supported? +// CLARA_CONFIG_CPP11_GENERATED_METHODS : The delete and default keywords for compiler generated methods +// CLARA_CONFIG_CPP11_OVERRIDE : is override supported? +// CLARA_CONFIG_CPP11_UNIQUE_PTR : is unique_ptr supported (otherwise use auto_ptr) + +// CLARA_CONFIG_CPP11_OR_GREATER : Is C++11 supported? + +// CLARA_CONFIG_VARIADIC_MACROS : are variadic macros supported? + +// In general each macro has a _NO_<feature name> form +// (e.g. CLARA_CONFIG_CPP11_NO_NULLPTR) which disables the feature. +// Many features, at point of detection, define an _INTERNAL_ macro, so they +// can be combined, en-mass, with the _NO_ forms later. + +// All the C++11 features can be disabled with CLARA_CONFIG_NO_CPP11 + +#ifdef __clang__ + +#if __has_feature(cxx_nullptr) +#define CLARA_INTERNAL_CONFIG_CPP11_NULLPTR +#endif + +#if __has_feature(cxx_noexcept) +#define CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT +#endif + +#endif // __clang__ + +//////////////////////////////////////////////////////////////////////////////// +// GCC +#ifdef __GNUC__ + +#if __GNUC__ == 4 && __GNUC_MINOR__ >= 6 && defined(__GXX_EXPERIMENTAL_CXX0X__) +#define CLARA_INTERNAL_CONFIG_CPP11_NULLPTR +#endif + +// - otherwise more recent versions define __cplusplus >= 201103L +// and will get picked up below + +#endif // __GNUC__ + +//////////////////////////////////////////////////////////////////////////////// +// Visual C++ +#ifdef _MSC_VER + +#if (_MSC_VER >= 1600) +#define CLARA_INTERNAL_CONFIG_CPP11_NULLPTR +#define CLARA_INTERNAL_CONFIG_CPP11_UNIQUE_PTR +#endif + +#if (_MSC_VER >= 1900 ) // (VC++ 13 (VS2015)) +#define CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT +#define CLARA_INTERNAL_CONFIG_CPP11_GENERATED_METHODS +#endif + +#endif // _MSC_VER + +//////////////////////////////////////////////////////////////////////////////// +// C++ language feature support + +// catch all support for C++11 +#if defined(__cplusplus) && __cplusplus >= 201103L + +#define CLARA_CPP11_OR_GREATER + +#if !defined(CLARA_INTERNAL_CONFIG_CPP11_NULLPTR) +#define CLARA_INTERNAL_CONFIG_CPP11_NULLPTR +#endif + +#ifndef CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT +#define CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT +#endif + +#ifndef CLARA_INTERNAL_CONFIG_CPP11_GENERATED_METHODS +#define CLARA_INTERNAL_CONFIG_CPP11_GENERATED_METHODS +#endif + +#if !defined(CLARA_INTERNAL_CONFIG_CPP11_OVERRIDE) +#define CLARA_INTERNAL_CONFIG_CPP11_OVERRIDE +#endif +#if !defined(CLARA_INTERNAL_CONFIG_CPP11_UNIQUE_PTR) +#define CLARA_INTERNAL_CONFIG_CPP11_UNIQUE_PTR +#endif + +#endif // __cplusplus >= 201103L + +// Now set the actual defines based on the above + anything the user has configured +#if defined(CLARA_INTERNAL_CONFIG_CPP11_NULLPTR) && !defined(CLARA_CONFIG_CPP11_NO_NULLPTR) && !defined(CLARA_CONFIG_CPP11_NULLPTR) && !defined(CLARA_CONFIG_NO_CPP11) +#define CLARA_CONFIG_CPP11_NULLPTR +#endif +#if defined(CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT) && !defined(CLARA_CONFIG_CPP11_NO_NOEXCEPT) && !defined(CLARA_CONFIG_CPP11_NOEXCEPT) && !defined(CLARA_CONFIG_NO_CPP11) +#define CLARA_CONFIG_CPP11_NOEXCEPT +#endif +#if defined(CLARA_INTERNAL_CONFIG_CPP11_GENERATED_METHODS) && !defined(CLARA_CONFIG_CPP11_NO_GENERATED_METHODS) && !defined(CLARA_CONFIG_CPP11_GENERATED_METHODS) && !defined(CLARA_CONFIG_NO_CPP11) +#define CLARA_CONFIG_CPP11_GENERATED_METHODS +#endif +#if defined(CLARA_INTERNAL_CONFIG_CPP11_OVERRIDE) && !defined(CLARA_CONFIG_NO_OVERRIDE) && !defined(CLARA_CONFIG_CPP11_OVERRIDE) && !defined(CLARA_CONFIG_NO_CPP11) +#define CLARA_CONFIG_CPP11_OVERRIDE +#endif +#if defined(CLARA_INTERNAL_CONFIG_CPP11_UNIQUE_PTR) && !defined(CLARA_CONFIG_NO_UNIQUE_PTR) && !defined(CLARA_CONFIG_CPP11_UNIQUE_PTR) && !defined(CLARA_CONFIG_NO_CPP11) +#define CLARA_CONFIG_CPP11_UNIQUE_PTR +#endif + +// noexcept support: +#if defined(CLARA_CONFIG_CPP11_NOEXCEPT) && !defined(CLARA_NOEXCEPT) +#define CLARA_NOEXCEPT noexcept +# define CLARA_NOEXCEPT_IS(x) noexcept(x) +#else +#define CLARA_NOEXCEPT throw() +# define CLARA_NOEXCEPT_IS(x) +#endif + +// nullptr support +#ifdef CLARA_CONFIG_CPP11_NULLPTR +#define CLARA_NULL nullptr +#else +#define CLARA_NULL NULL +#endif + +// override support +#ifdef CLARA_CONFIG_CPP11_OVERRIDE +#define CLARA_OVERRIDE override +#else +#define CLARA_OVERRIDE +#endif + +// unique_ptr support +#ifdef CLARA_CONFIG_CPP11_UNIQUE_PTR +# define CLARA_AUTO_PTR( T ) std::unique_ptr<T> +#else +# define CLARA_AUTO_PTR( T ) std::auto_ptr<T> +#endif + +#endif // TWOBLUECUBES_CLARA_COMPILERS_H_INCLUDED + +// ----------- end of #include from clara_compilers.h ----------- +// ........... back in clara.h + +#include <map> +#include <stdexcept> +#include <memory> + +// Use optional outer namespace +#ifdef STITCH_CLARA_OPEN_NAMESPACE +STITCH_CLARA_OPEN_NAMESPACE +#endif + +namespace Clara { + + struct UnpositionalTag {}; + + extern UnpositionalTag _; + +#ifdef CLARA_CONFIG_MAIN + UnpositionalTag _; +#endif + + namespace Detail { + +#ifdef CLARA_CONSOLE_WIDTH + const unsigned int consoleWidth = CLARA_CONFIG_CONSOLE_WIDTH; +#else + const unsigned int consoleWidth = 80; +#endif + + // Use this to try and stop compiler from warning about unreachable code + inline bool isTrue( bool value ) { return value; } + + using namespace Tbc; + + inline bool startsWith( std::string const& str, std::string const& prefix ) { + return str.size() >= prefix.size() && str.substr( 0, prefix.size() ) == prefix; + } + + template<typename T> struct RemoveConstRef{ typedef T type; }; + template<typename T> struct RemoveConstRef<T&>{ typedef T type; }; + template<typename T> struct RemoveConstRef<T const&>{ typedef T type; }; + template<typename T> struct RemoveConstRef<T const>{ typedef T type; }; + + template<typename T> struct IsBool { static const bool value = false; }; + template<> struct IsBool<bool> { static const bool value = true; }; + + template<typename T> + void convertInto( std::string const& _source, T& _dest ) { + std::stringstream ss; + ss << _source; + ss >> _dest; + if( ss.fail() ) + throw std::runtime_error( "Unable to convert " + _source + " to destination type" ); + } + inline void convertInto( std::string const& _source, std::string& _dest ) { + _dest = _source; + } + inline void convertInto( std::string const& _source, bool& _dest ) { + std::string sourceLC = _source; + std::transform( sourceLC.begin(), sourceLC.end(), sourceLC.begin(), ::tolower ); + if( sourceLC == "y" || sourceLC == "1" || sourceLC == "true" || sourceLC == "yes" || sourceLC == "on" ) + _dest = true; + else if( sourceLC == "n" || sourceLC == "0" || sourceLC == "false" || sourceLC == "no" || sourceLC == "off" ) + _dest = false; + else + throw std::runtime_error( "Expected a boolean value but did not recognise:\n '" + _source + "'" ); + } + inline void convertInto( bool _source, bool& _dest ) { + _dest = _source; + } + template<typename T> + inline void convertInto( bool, T& ) { + if( isTrue( true ) ) + throw std::runtime_error( "Invalid conversion" ); + } + + template<typename ConfigT> + struct IArgFunction { + virtual ~IArgFunction() {} +#ifdef CLARA_CONFIG_CPP11_GENERATED_METHODS + IArgFunction() = default; + IArgFunction( IArgFunction const& ) = default; +#endif + virtual void set( ConfigT& config, std::string const& value ) const = 0; + virtual void setFlag( ConfigT& config ) const = 0; + virtual bool takesArg() const = 0; + virtual IArgFunction* clone() const = 0; + }; + + template<typename ConfigT> + class BoundArgFunction { + public: + BoundArgFunction() : functionObj( CLARA_NULL ) {} + BoundArgFunction( IArgFunction<ConfigT>* _functionObj ) : functionObj( _functionObj ) {} + BoundArgFunction( BoundArgFunction const& other ) : functionObj( other.functionObj ? other.functionObj->clone() : CLARA_NULL ) {} + BoundArgFunction& operator = ( BoundArgFunction const& other ) { + IArgFunction<ConfigT>* newFunctionObj = other.functionObj ? other.functionObj->clone() : CLARA_NULL; + delete functionObj; + functionObj = newFunctionObj; + return *this; + } + ~BoundArgFunction() { delete functionObj; } + + void set( ConfigT& config, std::string const& value ) const { + functionObj->set( config, value ); + } + void setFlag( ConfigT& config ) const { + functionObj->setFlag( config ); + } + bool takesArg() const { return functionObj->takesArg(); } + + bool isSet() const { + return functionObj != CLARA_NULL; + } + private: + IArgFunction<ConfigT>* functionObj; + }; + + template<typename C> + struct NullBinder : IArgFunction<C>{ + virtual void set( C&, std::string const& ) const {} + virtual void setFlag( C& ) const {} + virtual bool takesArg() const { return true; } + virtual IArgFunction<C>* clone() const { return new NullBinder( *this ); } + }; + + template<typename C, typename M> + struct BoundDataMember : IArgFunction<C>{ + BoundDataMember( M C::* _member ) : member( _member ) {} + virtual void set( C& p, std::string const& stringValue ) const { + convertInto( stringValue, p.*member ); + } + virtual void setFlag( C& p ) const { + convertInto( true, p.*member ); + } + virtual bool takesArg() const { return !IsBool<M>::value; } + virtual IArgFunction<C>* clone() const { return new BoundDataMember( *this ); } + M C::* member; + }; + template<typename C, typename M> + struct BoundUnaryMethod : IArgFunction<C>{ + BoundUnaryMethod( void (C::*_member)( M ) ) : member( _member ) {} + virtual void set( C& p, std::string const& stringValue ) const { + typename RemoveConstRef<M>::type value; + convertInto( stringValue, value ); + (p.*member)( value ); + } + virtual void setFlag( C& p ) const { + typename RemoveConstRef<M>::type value; + convertInto( true, value ); + (p.*member)( value ); + } + virtual bool takesArg() const { return !IsBool<M>::value; } + virtual IArgFunction<C>* clone() const { return new BoundUnaryMethod( *this ); } + void (C::*member)( M ); + }; + template<typename C> + struct BoundNullaryMethod : IArgFunction<C>{ + BoundNullaryMethod( void (C::*_member)() ) : member( _member ) {} + virtual void set( C& p, std::string const& stringValue ) const { + bool value; + convertInto( stringValue, value ); + if( value ) + (p.*member)(); + } + virtual void setFlag( C& p ) const { + (p.*member)(); + } + virtual bool takesArg() const { return false; } + virtual IArgFunction<C>* clone() const { return new BoundNullaryMethod( *this ); } + void (C::*member)(); + }; + + template<typename C> + struct BoundUnaryFunction : IArgFunction<C>{ + BoundUnaryFunction( void (*_function)( C& ) ) : function( _function ) {} + virtual void set( C& obj, std::string const& stringValue ) const { + bool value; + convertInto( stringValue, value ); + if( value ) + function( obj ); + } + virtual void setFlag( C& p ) const { + function( p ); + } + virtual bool takesArg() const { return false; } + virtual IArgFunction<C>* clone() const { return new BoundUnaryFunction( *this ); } + void (*function)( C& ); + }; + + template<typename C, typename T> + struct BoundBinaryFunction : IArgFunction<C>{ + BoundBinaryFunction( void (*_function)( C&, T ) ) : function( _function ) {} + virtual void set( C& obj, std::string const& stringValue ) const { + typename RemoveConstRef<T>::type value; + convertInto( stringValue, value ); + function( obj, value ); + } + virtual void setFlag( C& obj ) const { + typename RemoveConstRef<T>::type value; + convertInto( true, value ); + function( obj, value ); + } + virtual bool takesArg() const { return !IsBool<T>::value; } + virtual IArgFunction<C>* clone() const { return new BoundBinaryFunction( *this ); } + void (*function)( C&, T ); + }; + + } // namespace Detail + + struct Parser { + Parser() : separators( " \t=:" ) {} + + struct Token { + enum Type { Positional, ShortOpt, LongOpt }; + Token( Type _type, std::string const& _data ) : type( _type ), data( _data ) {} + Type type; + std::string data; + }; + + void parseIntoTokens( int argc, char const* const argv[], std::vector<Parser::Token>& tokens ) const { + const std::string doubleDash = "--"; + for( int i = 1; i < argc && argv[i] != doubleDash; ++i ) + parseIntoTokens( argv[i] , tokens); + } + void parseIntoTokens( std::string arg, std::vector<Parser::Token>& tokens ) const { + while( !arg.empty() ) { + Parser::Token token( Parser::Token::Positional, arg ); + arg = ""; + if( token.data[0] == '-' ) { + if( token.data.size() > 1 && token.data[1] == '-' ) { + token = Parser::Token( Parser::Token::LongOpt, token.data.substr( 2 ) ); + } + else { + token = Parser::Token( Parser::Token::ShortOpt, token.data.substr( 1 ) ); + if( token.data.size() > 1 && separators.find( token.data[1] ) == std::string::npos ) { + arg = "-" + token.data.substr( 1 ); + token.data = token.data.substr( 0, 1 ); + } + } + } + if( token.type != Parser::Token::Positional ) { + std::size_t pos = token.data.find_first_of( separators ); + if( pos != std::string::npos ) { + arg = token.data.substr( pos+1 ); + token.data = token.data.substr( 0, pos ); + } + } + tokens.push_back( token ); + } + } + std::string separators; + }; + + template<typename ConfigT> + struct CommonArgProperties { + CommonArgProperties() {} + CommonArgProperties( Detail::BoundArgFunction<ConfigT> const& _boundField ) : boundField( _boundField ) {} + + Detail::BoundArgFunction<ConfigT> boundField; + std::string description; + std::string detail; + std::string placeholder; // Only value if boundField takes an arg + + bool takesArg() const { + return !placeholder.empty(); + } + void validate() const { + if( !boundField.isSet() ) + throw std::logic_error( "option not bound" ); + } + }; + struct OptionArgProperties { + std::vector<std::string> shortNames; + std::string longName; + + bool hasShortName( std::string const& shortName ) const { + return std::find( shortNames.begin(), shortNames.end(), shortName ) != shortNames.end(); + } + bool hasLongName( std::string const& _longName ) const { + return _longName == longName; + } + }; + struct PositionalArgProperties { + PositionalArgProperties() : position( -1 ) {} + int position; // -1 means non-positional (floating) + + bool isFixedPositional() const { + return position != -1; + } + }; + + template<typename ConfigT> + class CommandLine { + + struct Arg : CommonArgProperties<ConfigT>, OptionArgProperties, PositionalArgProperties { + Arg() {} + Arg( Detail::BoundArgFunction<ConfigT> const& _boundField ) : CommonArgProperties<ConfigT>( _boundField ) {} + + using CommonArgProperties<ConfigT>::placeholder; // !TBD + + std::string dbgName() const { + if( !longName.empty() ) + return "--" + longName; + if( !shortNames.empty() ) + return "-" + shortNames[0]; + return "positional args"; + } + std::string commands() const { + std::ostringstream oss; + bool first = true; + std::vector<std::string>::const_iterator it = shortNames.begin(), itEnd = shortNames.end(); + for(; it != itEnd; ++it ) { + if( first ) + first = false; + else + oss << ", "; + oss << "-" << *it; + } + if( !longName.empty() ) { + if( !first ) + oss << ", "; + oss << "--" << longName; + } + if( !placeholder.empty() ) + oss << " <" << placeholder << ">"; + return oss.str(); + } + }; + + typedef CLARA_AUTO_PTR( Arg ) ArgAutoPtr; + + friend void addOptName( Arg& arg, std::string const& optName ) + { + if( optName.empty() ) + return; + if( Detail::startsWith( optName, "--" ) ) { + if( !arg.longName.empty() ) + throw std::logic_error( "Only one long opt may be specified. '" + + arg.longName + + "' already specified, now attempting to add '" + + optName + "'" ); + arg.longName = optName.substr( 2 ); + } + else if( Detail::startsWith( optName, "-" ) ) + arg.shortNames.push_back( optName.substr( 1 ) ); + else + throw std::logic_error( "option must begin with - or --. Option was: '" + optName + "'" ); + } + friend void setPositionalArg( Arg& arg, int position ) + { + arg.position = position; + } + + class ArgBuilder { + public: + ArgBuilder( Arg* arg ) : m_arg( arg ) {} + + // Bind a non-boolean data member (requires placeholder string) + template<typename C, typename M> + void bind( M C::* field, std::string const& placeholder ) { + m_arg->boundField = new Detail::BoundDataMember<C,M>( field ); + m_arg->placeholder = placeholder; + } + // Bind a boolean data member (no placeholder required) + template<typename C> + void bind( bool C::* field ) { + m_arg->boundField = new Detail::BoundDataMember<C,bool>( field ); + } + + // Bind a method taking a single, non-boolean argument (requires a placeholder string) + template<typename C, typename M> + void bind( void (C::* unaryMethod)( M ), std::string const& placeholder ) { + m_arg->boundField = new Detail::BoundUnaryMethod<C,M>( unaryMethod ); + m_arg->placeholder = placeholder; + } + + // Bind a method taking a single, boolean argument (no placeholder string required) + template<typename C> + void bind( void (C::* unaryMethod)( bool ) ) { + m_arg->boundField = new Detail::BoundUnaryMethod<C,bool>( unaryMethod ); + } + + // Bind a method that takes no arguments (will be called if opt is present) + template<typename C> + void bind( void (C::* nullaryMethod)() ) { + m_arg->boundField = new Detail::BoundNullaryMethod<C>( nullaryMethod ); + } + + // Bind a free function taking a single argument - the object to operate on (no placeholder string required) + template<typename C> + void bind( void (* unaryFunction)( C& ) ) { + m_arg->boundField = new Detail::BoundUnaryFunction<C>( unaryFunction ); + } + + // Bind a free function taking a single argument - the object to operate on (requires a placeholder string) + template<typename C, typename T> + void bind( void (* binaryFunction)( C&, T ), std::string const& placeholder ) { + m_arg->boundField = new Detail::BoundBinaryFunction<C, T>( binaryFunction ); + m_arg->placeholder = placeholder; + } + + ArgBuilder& describe( std::string const& description ) { + m_arg->description = description; + return *this; + } + ArgBuilder& detail( std::string const& detail ) { + m_arg->detail = detail; + return *this; + } + + protected: + Arg* m_arg; + }; + + class OptBuilder : public ArgBuilder { + public: + OptBuilder( Arg* arg ) : ArgBuilder( arg ) {} + OptBuilder( OptBuilder& other ) : ArgBuilder( other ) {} + + OptBuilder& operator[]( std::string const& optName ) { + addOptName( *ArgBuilder::m_arg, optName ); + return *this; + } + }; + + public: + + CommandLine() + : m_boundProcessName( new Detail::NullBinder<ConfigT>() ), + m_highestSpecifiedArgPosition( 0 ), + m_throwOnUnrecognisedTokens( false ) + {} + CommandLine( CommandLine const& other ) + : m_boundProcessName( other.m_boundProcessName ), + m_options ( other.m_options ), + m_positionalArgs( other.m_positionalArgs ), + m_highestSpecifiedArgPosition( other.m_highestSpecifiedArgPosition ), + m_throwOnUnrecognisedTokens( other.m_throwOnUnrecognisedTokens ) + { + if( other.m_floatingArg.get() ) + m_floatingArg.reset( new Arg( *other.m_floatingArg ) ); + } + + CommandLine& setThrowOnUnrecognisedTokens( bool shouldThrow = true ) { + m_throwOnUnrecognisedTokens = shouldThrow; + return *this; + } + + OptBuilder operator[]( std::string const& optName ) { + m_options.push_back( Arg() ); + addOptName( m_options.back(), optName ); + OptBuilder builder( &m_options.back() ); + return builder; + } + + ArgBuilder operator[]( int position ) { + m_positionalArgs.insert( std::make_pair( position, Arg() ) ); + if( position > m_highestSpecifiedArgPosition ) + m_highestSpecifiedArgPosition = position; + setPositionalArg( m_positionalArgs[position], position ); + ArgBuilder builder( &m_positionalArgs[position] ); + return builder; + } + + // Invoke this with the _ instance + ArgBuilder operator[]( UnpositionalTag ) { + if( m_floatingArg.get() ) + throw std::logic_error( "Only one unpositional argument can be added" ); + m_floatingArg.reset( new Arg() ); + ArgBuilder builder( m_floatingArg.get() ); + return builder; + } + + template<typename C, typename M> + void bindProcessName( M C::* field ) { + m_boundProcessName = new Detail::BoundDataMember<C,M>( field ); + } + template<typename C, typename M> + void bindProcessName( void (C::*_unaryMethod)( M ) ) { + m_boundProcessName = new Detail::BoundUnaryMethod<C,M>( _unaryMethod ); + } + + void optUsage( std::ostream& os, std::size_t indent = 0, std::size_t width = Detail::consoleWidth ) const { + typename std::vector<Arg>::const_iterator itBegin = m_options.begin(), itEnd = m_options.end(), it; + std::size_t maxWidth = 0; + for( it = itBegin; it != itEnd; ++it ) + maxWidth = (std::max)( maxWidth, it->commands().size() ); + + for( it = itBegin; it != itEnd; ++it ) { + Detail::Text usage( it->commands(), Detail::TextAttributes() + .setWidth( maxWidth+indent ) + .setIndent( indent ) ); + Detail::Text desc( it->description, Detail::TextAttributes() + .setWidth( width - maxWidth - 3 ) ); + + for( std::size_t i = 0; i < (std::max)( usage.size(), desc.size() ); ++i ) { + std::string usageCol = i < usage.size() ? usage[i] : ""; + os << usageCol; + + if( i < desc.size() && !desc[i].empty() ) + os << std::string( indent + 2 + maxWidth - usageCol.size(), ' ' ) + << desc[i]; + os << "\n"; + } + } + } + std::string optUsage() const { + std::ostringstream oss; + optUsage( oss ); + return oss.str(); + } + + void argSynopsis( std::ostream& os ) const { + for( int i = 1; i <= m_highestSpecifiedArgPosition; ++i ) { + if( i > 1 ) + os << " "; + typename std::map<int, Arg>::const_iterator it = m_positionalArgs.find( i ); + if( it != m_positionalArgs.end() ) + os << "<" << it->second.placeholder << ">"; + else if( m_floatingArg.get() ) + os << "<" << m_floatingArg->placeholder << ">"; + else + throw std::logic_error( "non consecutive positional arguments with no floating args" ); + } + // !TBD No indication of mandatory args + if( m_floatingArg.get() ) { + if( m_highestSpecifiedArgPosition > 1 ) + os << " "; + os << "[<" << m_floatingArg->placeholder << "> ...]"; + } + } + std::string argSynopsis() const { + std::ostringstream oss; + argSynopsis( oss ); + return oss.str(); + } + + void usage( std::ostream& os, std::string const& procName ) const { + validate(); + os << "usage:\n " << procName << " "; + argSynopsis( os ); + if( !m_options.empty() ) { + os << " [options]\n\nwhere options are: \n"; + optUsage( os, 2 ); + } + os << "\n"; + } + std::string usage( std::string const& procName ) const { + std::ostringstream oss; + usage( oss, procName ); + return oss.str(); + } + + ConfigT parse( int argc, char const* const argv[] ) const { + ConfigT config; + parseInto( argc, argv, config ); + return config; + } + + std::vector<Parser::Token> parseInto( int argc, char const* argv[], ConfigT& config ) const { + std::string processName = argv[0]; + std::size_t lastSlash = processName.find_last_of( "/\\" ); + if( lastSlash != std::string::npos ) + processName = processName.substr( lastSlash+1 ); + m_boundProcessName.set( config, processName ); + std::vector<Parser::Token> tokens; + Parser parser; + parser.parseIntoTokens( argc, argv, tokens ); + return populate( tokens, config ); + } + + std::vector<Parser::Token> populate( std::vector<Parser::Token> const& tokens, ConfigT& config ) const { + validate(); + std::vector<Parser::Token> unusedTokens = populateOptions( tokens, config ); + unusedTokens = populateFixedArgs( unusedTokens, config ); + unusedTokens = populateFloatingArgs( unusedTokens, config ); + return unusedTokens; + } + + std::vector<Parser::Token> populateOptions( std::vector<Parser::Token> const& tokens, ConfigT& config ) const { + std::vector<Parser::Token> unusedTokens; + std::vector<std::string> errors; + for( std::size_t i = 0; i < tokens.size(); ++i ) { + Parser::Token const& token = tokens[i]; + typename std::vector<Arg>::const_iterator it = m_options.begin(), itEnd = m_options.end(); + for(; it != itEnd; ++it ) { + Arg const& arg = *it; + + try { + if( ( token.type == Parser::Token::ShortOpt && arg.hasShortName( token.data ) ) || + ( token.type == Parser::Token::LongOpt && arg.hasLongName( token.data ) ) ) { + if( arg.takesArg() ) { + if( i == tokens.size()-1 || tokens[i+1].type != Parser::Token::Positional ) + errors.push_back( "Expected argument to option: " + token.data ); + else + arg.boundField.set( config, tokens[++i].data ); + } + else { + arg.boundField.setFlag( config ); + } + break; + } + } + catch( std::exception& ex ) { + errors.push_back( std::string( ex.what() ) + "\n- while parsing: (" + arg.commands() + ")" ); + } + } + if( it == itEnd ) { + if( token.type == Parser::Token::Positional || !m_throwOnUnrecognisedTokens ) + unusedTokens.push_back( token ); + else if( errors.empty() && m_throwOnUnrecognisedTokens ) + errors.push_back( "unrecognised option: " + token.data ); + } + } + if( !errors.empty() ) { + std::ostringstream oss; + for( std::vector<std::string>::const_iterator it = errors.begin(), itEnd = errors.end(); + it != itEnd; + ++it ) { + if( it != errors.begin() ) + oss << "\n"; + oss << *it; + } + throw std::runtime_error( oss.str() ); + } + return unusedTokens; + } + std::vector<Parser::Token> populateFixedArgs( std::vector<Parser::Token> const& tokens, ConfigT& config ) const { + std::vector<Parser::Token> unusedTokens; + int position = 1; + for( std::size_t i = 0; i < tokens.size(); ++i ) { + Parser::Token const& token = tokens[i]; + typename std::map<int, Arg>::const_iterator it = m_positionalArgs.find( position ); + if( it != m_positionalArgs.end() ) + it->second.boundField.set( config, token.data ); + else + unusedTokens.push_back( token ); + if( token.type == Parser::Token::Positional ) + position++; + } + return unusedTokens; + } + std::vector<Parser::Token> populateFloatingArgs( std::vector<Parser::Token> const& tokens, ConfigT& config ) const { + if( !m_floatingArg.get() ) + return tokens; + std::vector<Parser::Token> unusedTokens; + for( std::size_t i = 0; i < tokens.size(); ++i ) { + Parser::Token const& token = tokens[i]; + if( token.type == Parser::Token::Positional ) + m_floatingArg->boundField.set( config, token.data ); + else + unusedTokens.push_back( token ); + } + return unusedTokens; + } + + void validate() const + { + if( m_options.empty() && m_positionalArgs.empty() && !m_floatingArg.get() ) + throw std::logic_error( "No options or arguments specified" ); + + for( typename std::vector<Arg>::const_iterator it = m_options.begin(), + itEnd = m_options.end(); + it != itEnd; ++it ) + it->validate(); + } + + private: + Detail::BoundArgFunction<ConfigT> m_boundProcessName; + std::vector<Arg> m_options; + std::map<int, Arg> m_positionalArgs; + ArgAutoPtr m_floatingArg; + int m_highestSpecifiedArgPosition; + bool m_throwOnUnrecognisedTokens; + }; + +} // end namespace Clara + +STITCH_CLARA_CLOSE_NAMESPACE +#undef STITCH_CLARA_OPEN_NAMESPACE +#undef STITCH_CLARA_CLOSE_NAMESPACE + +#endif // TWOBLUECUBES_CLARA_H_INCLUDED +#undef STITCH_CLARA_OPEN_NAMESPACE + +// Restore Clara's value for console width, if present +#ifdef CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH +#define CLARA_CONFIG_CONSOLE_WIDTH CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH +#undef CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH +#endif + +#include <fstream> + +namespace Catch { + + inline void abortAfterFirst( ConfigData& config ) { config.abortAfter = 1; } + inline void abortAfterX( ConfigData& config, int x ) { + if( x < 1 ) + throw std::runtime_error( "Value after -x or --abortAfter must be greater than zero" ); + config.abortAfter = x; + } + inline void addTestOrTags( ConfigData& config, std::string const& _testSpec ) { config.testsOrTags.push_back( _testSpec ); } + inline void addReporterName( ConfigData& config, std::string const& _reporterName ) { config.reporterNames.push_back( _reporterName ); } + + inline void addWarning( ConfigData& config, std::string const& _warning ) { + if( _warning == "NoAssertions" ) + config.warnings = static_cast<WarnAbout::What>( config.warnings | WarnAbout::NoAssertions ); + else + throw std::runtime_error( "Unrecognised warning: '" + _warning + "'" ); + } + inline void setOrder( ConfigData& config, std::string const& order ) { + if( startsWith( "declared", order ) ) + config.runOrder = RunTests::InDeclarationOrder; + else if( startsWith( "lexical", order ) ) + config.runOrder = RunTests::InLexicographicalOrder; + else if( startsWith( "random", order ) ) + config.runOrder = RunTests::InRandomOrder; + else + throw std::runtime_error( "Unrecognised ordering: '" + order + "'" ); + } + inline void setRngSeed( ConfigData& config, std::string const& seed ) { + if( seed == "time" ) { + config.rngSeed = static_cast<unsigned int>( std::time(0) ); + } + else { + std::stringstream ss; + ss << seed; + ss >> config.rngSeed; + if( ss.fail() ) + throw std::runtime_error( "Argment to --rng-seed should be the word 'time' or a number" ); + } + } + inline void setVerbosity( ConfigData& config, int level ) { + // !TBD: accept strings? + config.verbosity = static_cast<Verbosity::Level>( level ); + } + inline void setShowDurations( ConfigData& config, bool _showDurations ) { + config.showDurations = _showDurations + ? ShowDurations::Always + : ShowDurations::Never; + } + inline void setUseColour( ConfigData& config, std::string const& value ) { + std::string mode = toLower( value ); + + if( mode == "yes" ) + config.useColour = UseColour::Yes; + else if( mode == "no" ) + config.useColour = UseColour::No; + else if( mode == "auto" ) + config.useColour = UseColour::Auto; + else + throw std::runtime_error( "colour mode must be one of: auto, yes or no" ); + } + inline void forceColour( ConfigData& config ) { + config.useColour = UseColour::Yes; + } + inline void loadTestNamesFromFile( ConfigData& config, std::string const& _filename ) { + std::ifstream f( _filename.c_str() ); + if( !f.is_open() ) + throw std::domain_error( "Unable to load input file: " + _filename ); + + std::string line; + while( std::getline( f, line ) ) { + line = trim(line); + if( !line.empty() && !startsWith( line, "#" ) ) + addTestOrTags( config, "\"" + line + "\"," ); + } + } + + inline Clara::CommandLine<ConfigData> makeCommandLineParser() { + + using namespace Clara; + CommandLine<ConfigData> cli; + + cli.bindProcessName( &ConfigData::processName ); + + cli["-?"]["-h"]["--help"] + .describe( "display usage information" ) + .bind( &ConfigData::showHelp ); + + cli["-l"]["--list-tests"] + .describe( "list all/matching test cases" ) + .bind( &ConfigData::listTests ); + + cli["-t"]["--list-tags"] + .describe( "list all/matching tags" ) + .bind( &ConfigData::listTags ); + + cli["-s"]["--success"] + .describe( "include successful tests in output" ) + .bind( &ConfigData::showSuccessfulTests ); + + cli["-b"]["--break"] + .describe( "break into debugger on failure" ) + .bind( &ConfigData::shouldDebugBreak ); + + cli["-e"]["--nothrow"] + .describe( "skip exception tests" ) + .bind( &ConfigData::noThrow ); + + cli["-i"]["--invisibles"] + .describe( "show invisibles (tabs, newlines)" ) + .bind( &ConfigData::showInvisibles ); + + cli["-o"]["--out"] + .describe( "output filename" ) + .bind( &ConfigData::outputFilename, "filename" ); + + cli["-r"]["--reporter"] +// .placeholder( "name[:filename]" ) + .describe( "reporter to use (defaults to console)" ) + .bind( &addReporterName, "name" ); + + cli["-n"]["--name"] + .describe( "suite name" ) + .bind( &ConfigData::name, "name" ); + + cli["-a"]["--abort"] + .describe( "abort at first failure" ) + .bind( &abortAfterFirst ); + + cli["-x"]["--abortx"] + .describe( "abort after x failures" ) + .bind( &abortAfterX, "no. failures" ); + + cli["-w"]["--warn"] + .describe( "enable warnings" ) + .bind( &addWarning, "warning name" ); + +// - needs updating if reinstated +// cli.into( &setVerbosity ) +// .describe( "level of verbosity (0=no output)" ) +// .shortOpt( "v") +// .longOpt( "verbosity" ) +// .placeholder( "level" ); + + cli[_] + .describe( "which test or tests to use" ) + .bind( &addTestOrTags, "test name, pattern or tags" ); + + cli["-d"]["--durations"] + .describe( "show test durations" ) + .bind( &setShowDurations, "yes|no" ); + + cli["-f"]["--input-file"] + .describe( "load test names to run from a file" ) + .bind( &loadTestNamesFromFile, "filename" ); + + cli["-#"]["--filenames-as-tags"] + .describe( "adds a tag for the filename" ) + .bind( &ConfigData::filenamesAsTags ); + + // Less common commands which don't have a short form + cli["--list-test-names-only"] + .describe( "list all/matching test cases names only" ) + .bind( &ConfigData::listTestNamesOnly ); + + cli["--list-reporters"] + .describe( "list all reporters" ) + .bind( &ConfigData::listReporters ); + + cli["--order"] + .describe( "test case order (defaults to decl)" ) + .bind( &setOrder, "decl|lex|rand" ); + + cli["--rng-seed"] + .describe( "set a specific seed for random numbers" ) + .bind( &setRngSeed, "'time'|number" ); + + cli["--force-colour"] + .describe( "force colourised output (deprecated)" ) + .bind( &forceColour ); + + cli["--use-colour"] + .describe( "should output be colourised" ) + .bind( &setUseColour, "yes|no" ); + + return cli; + } + +} // end namespace Catch + +// #included from: internal/catch_list.hpp +#define TWOBLUECUBES_CATCH_LIST_HPP_INCLUDED + +// #included from: catch_text.h +#define TWOBLUECUBES_CATCH_TEXT_H_INCLUDED + +#define TBC_TEXT_FORMAT_CONSOLE_WIDTH CATCH_CONFIG_CONSOLE_WIDTH + +#define CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE Catch +// #included from: ../external/tbc_text_format.h +// Only use header guard if we are not using an outer namespace +#ifndef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE +# ifdef TWOBLUECUBES_TEXT_FORMAT_H_INCLUDED +# ifndef TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED +# define TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED +# endif +# else +# define TWOBLUECUBES_TEXT_FORMAT_H_INCLUDED +# endif +#endif +#ifndef TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED +#include <string> +#include <vector> +#include <sstream> + +// Use optional outer namespace +#ifdef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE +namespace CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE { +#endif + +namespace Tbc { + +#ifdef TBC_TEXT_FORMAT_CONSOLE_WIDTH + const unsigned int consoleWidth = TBC_TEXT_FORMAT_CONSOLE_WIDTH; +#else + const unsigned int consoleWidth = 80; +#endif + + struct TextAttributes { + TextAttributes() + : initialIndent( std::string::npos ), + indent( 0 ), + width( consoleWidth-1 ), + tabChar( '\t' ) + {} + + TextAttributes& setInitialIndent( std::size_t _value ) { initialIndent = _value; return *this; } + TextAttributes& setIndent( std::size_t _value ) { indent = _value; return *this; } + TextAttributes& setWidth( std::size_t _value ) { width = _value; return *this; } + TextAttributes& setTabChar( char _value ) { tabChar = _value; return *this; } + + std::size_t initialIndent; // indent of first line, or npos + std::size_t indent; // indent of subsequent lines, or all if initialIndent is npos + std::size_t width; // maximum width of text, including indent. Longer text will wrap + char tabChar; // If this char is seen the indent is changed to current pos + }; + + class Text { + public: + Text( std::string const& _str, TextAttributes const& _attr = TextAttributes() ) + : attr( _attr ) + { + std::string wrappableChars = " [({.,/|\\-"; + std::size_t indent = _attr.initialIndent != std::string::npos + ? _attr.initialIndent + : _attr.indent; + std::string remainder = _str; + + while( !remainder.empty() ) { + if( lines.size() >= 1000 ) { + lines.push_back( "... message truncated due to excessive size" ); + return; + } + std::size_t tabPos = std::string::npos; + std::size_t width = (std::min)( remainder.size(), _attr.width - indent ); + std::size_t pos = remainder.find_first_of( '\n' ); + if( pos <= width ) { + width = pos; + } + pos = remainder.find_last_of( _attr.tabChar, width ); + if( pos != std::string::npos ) { + tabPos = pos; + if( remainder[width] == '\n' ) + width--; + remainder = remainder.substr( 0, tabPos ) + remainder.substr( tabPos+1 ); + } + + if( width == remainder.size() ) { + spliceLine( indent, remainder, width ); + } + else if( remainder[width] == '\n' ) { + spliceLine( indent, remainder, width ); + if( width <= 1 || remainder.size() != 1 ) + remainder = remainder.substr( 1 ); + indent = _attr.indent; + } + else { + pos = remainder.find_last_of( wrappableChars, width ); + if( pos != std::string::npos && pos > 0 ) { + spliceLine( indent, remainder, pos ); + if( remainder[0] == ' ' ) + remainder = remainder.substr( 1 ); + } + else { + spliceLine( indent, remainder, width-1 ); + lines.back() += "-"; + } + if( lines.size() == 1 ) + indent = _attr.indent; + if( tabPos != std::string::npos ) + indent += tabPos; + } + } + } + + void spliceLine( std::size_t _indent, std::string& _remainder, std::size_t _pos ) { + lines.push_back( std::string( _indent, ' ' ) + _remainder.substr( 0, _pos ) ); + _remainder = _remainder.substr( _pos ); + } + + typedef std::vector<std::string>::const_iterator const_iterator; + + const_iterator begin() const { return lines.begin(); } + const_iterator end() const { return lines.end(); } + std::string const& last() const { return lines.back(); } + std::size_t size() const { return lines.size(); } + std::string const& operator[]( std::size_t _index ) const { return lines[_index]; } + std::string toString() const { + std::ostringstream oss; + oss << *this; + return oss.str(); + } + + inline friend std::ostream& operator << ( std::ostream& _stream, Text const& _text ) { + for( Text::const_iterator it = _text.begin(), itEnd = _text.end(); + it != itEnd; ++it ) { + if( it != _text.begin() ) + _stream << "\n"; + _stream << *it; + } + return _stream; + } + + private: + std::string str; + TextAttributes attr; + std::vector<std::string> lines; + }; + +} // end namespace Tbc + +#ifdef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE +} // end outer namespace +#endif + +#endif // TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED +#undef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE + +namespace Catch { + using Tbc::Text; + using Tbc::TextAttributes; +} + +// #included from: catch_console_colour.hpp +#define TWOBLUECUBES_CATCH_CONSOLE_COLOUR_HPP_INCLUDED + +namespace Catch { + + struct Colour { + enum Code { + None = 0, + + White, + Red, + Green, + Blue, + Cyan, + Yellow, + Grey, + + Bright = 0x10, + + BrightRed = Bright | Red, + BrightGreen = Bright | Green, + LightGrey = Bright | Grey, + BrightWhite = Bright | White, + + // By intention + FileName = LightGrey, + Warning = Yellow, + ResultError = BrightRed, + ResultSuccess = BrightGreen, + ResultExpectedFailure = Warning, + + Error = BrightRed, + Success = Green, + + OriginalExpression = Cyan, + ReconstructedExpression = Yellow, + + SecondaryText = LightGrey, + Headers = White + }; + + // Use constructed object for RAII guard + Colour( Code _colourCode ); + Colour( Colour const& other ); + ~Colour(); + + // Use static method for one-shot changes + static void use( Code _colourCode ); + + private: + bool m_moved; + }; + + inline std::ostream& operator << ( std::ostream& os, Colour const& ) { return os; } + +} // end namespace Catch + +// #included from: catch_interfaces_reporter.h +#define TWOBLUECUBES_CATCH_INTERFACES_REPORTER_H_INCLUDED + +#include <string> +#include <ostream> +#include <map> +#include <assert.h> + +namespace Catch +{ + struct ReporterConfig { + explicit ReporterConfig( Ptr<IConfig const> const& _fullConfig ) + : m_stream( &_fullConfig->stream() ), m_fullConfig( _fullConfig ) {} + + ReporterConfig( Ptr<IConfig const> const& _fullConfig, std::ostream& _stream ) + : m_stream( &_stream ), m_fullConfig( _fullConfig ) {} + + std::ostream& stream() const { return *m_stream; } + Ptr<IConfig const> fullConfig() const { return m_fullConfig; } + + private: + std::ostream* m_stream; + Ptr<IConfig const> m_fullConfig; + }; + + struct ReporterPreferences { + ReporterPreferences() + : shouldRedirectStdOut( false ) + {} + + bool shouldRedirectStdOut; + }; + + template<typename T> + struct LazyStat : Option<T> { + LazyStat() : used( false ) {} + LazyStat& operator=( T const& _value ) { + Option<T>::operator=( _value ); + used = false; + return *this; + } + void reset() { + Option<T>::reset(); + used = false; + } + bool used; + }; + + struct TestRunInfo { + TestRunInfo( std::string const& _name ) : name( _name ) {} + std::string name; + }; + struct GroupInfo { + GroupInfo( std::string const& _name, + std::size_t _groupIndex, + std::size_t _groupsCount ) + : name( _name ), + groupIndex( _groupIndex ), + groupsCounts( _groupsCount ) + {} + + std::string name; + std::size_t groupIndex; + std::size_t groupsCounts; + }; + + struct AssertionStats { + AssertionStats( AssertionResult const& _assertionResult, + std::vector<MessageInfo> const& _infoMessages, + Totals const& _totals ) + : assertionResult( _assertionResult ), + infoMessages( _infoMessages ), + totals( _totals ) + { + if( assertionResult.hasMessage() ) { + // Copy message into messages list. + // !TBD This should have been done earlier, somewhere + MessageBuilder builder( assertionResult.getTestMacroName(), assertionResult.getSourceInfo(), assertionResult.getResultType() ); + builder << assertionResult.getMessage(); + builder.m_info.message = builder.m_stream.str(); + + infoMessages.push_back( builder.m_info ); + } + } + virtual ~AssertionStats(); + +# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS + AssertionStats( AssertionStats const& ) = default; + AssertionStats( AssertionStats && ) = default; + AssertionStats& operator = ( AssertionStats const& ) = default; + AssertionStats& operator = ( AssertionStats && ) = default; +# endif + + AssertionResult assertionResult; + std::vector<MessageInfo> infoMessages; + Totals totals; + }; + + struct SectionStats { + SectionStats( SectionInfo const& _sectionInfo, + Counts const& _assertions, + double _durationInSeconds, + bool _missingAssertions ) + : sectionInfo( _sectionInfo ), + assertions( _assertions ), + durationInSeconds( _durationInSeconds ), + missingAssertions( _missingAssertions ) + {} + virtual ~SectionStats(); +# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS + SectionStats( SectionStats const& ) = default; + SectionStats( SectionStats && ) = default; + SectionStats& operator = ( SectionStats const& ) = default; + SectionStats& operator = ( SectionStats && ) = default; +# endif + + SectionInfo sectionInfo; + Counts assertions; + double durationInSeconds; + bool missingAssertions; + }; + + struct TestCaseStats { + TestCaseStats( TestCaseInfo const& _testInfo, + Totals const& _totals, + std::string const& _stdOut, + std::string const& _stdErr, + bool _aborting ) + : testInfo( _testInfo ), + totals( _totals ), + stdOut( _stdOut ), + stdErr( _stdErr ), + aborting( _aborting ) + {} + virtual ~TestCaseStats(); + +# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS + TestCaseStats( TestCaseStats const& ) = default; + TestCaseStats( TestCaseStats && ) = default; + TestCaseStats& operator = ( TestCaseStats const& ) = default; + TestCaseStats& operator = ( TestCaseStats && ) = default; +# endif + + TestCaseInfo testInfo; + Totals totals; + std::string stdOut; + std::string stdErr; + bool aborting; + }; + + struct TestGroupStats { + TestGroupStats( GroupInfo const& _groupInfo, + Totals const& _totals, + bool _aborting ) + : groupInfo( _groupInfo ), + totals( _totals ), + aborting( _aborting ) + {} + TestGroupStats( GroupInfo const& _groupInfo ) + : groupInfo( _groupInfo ), + aborting( false ) + {} + virtual ~TestGroupStats(); + +# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS + TestGroupStats( TestGroupStats const& ) = default; + TestGroupStats( TestGroupStats && ) = default; + TestGroupStats& operator = ( TestGroupStats const& ) = default; + TestGroupStats& operator = ( TestGroupStats && ) = default; +# endif + + GroupInfo groupInfo; + Totals totals; + bool aborting; + }; + + struct TestRunStats { + TestRunStats( TestRunInfo const& _runInfo, + Totals const& _totals, + bool _aborting ) + : runInfo( _runInfo ), + totals( _totals ), + aborting( _aborting ) + {} + virtual ~TestRunStats(); + +# ifndef CATCH_CONFIG_CPP11_GENERATED_METHODS + TestRunStats( TestRunStats const& _other ) + : runInfo( _other.runInfo ), + totals( _other.totals ), + aborting( _other.aborting ) + {} +# else + TestRunStats( TestRunStats const& ) = default; + TestRunStats( TestRunStats && ) = default; + TestRunStats& operator = ( TestRunStats const& ) = default; + TestRunStats& operator = ( TestRunStats && ) = default; +# endif + + TestRunInfo runInfo; + Totals totals; + bool aborting; + }; + + struct IStreamingReporter : IShared { + virtual ~IStreamingReporter(); + + // Implementing class must also provide the following static method: + // static std::string getDescription(); + + virtual ReporterPreferences getPreferences() const = 0; + + virtual void noMatchingTestCases( std::string const& spec ) = 0; + + virtual void testRunStarting( TestRunInfo const& testRunInfo ) = 0; + virtual void testGroupStarting( GroupInfo const& groupInfo ) = 0; + + virtual void testCaseStarting( TestCaseInfo const& testInfo ) = 0; + virtual void sectionStarting( SectionInfo const& sectionInfo ) = 0; + + virtual void assertionStarting( AssertionInfo const& assertionInfo ) = 0; + + // The return value indicates if the messages buffer should be cleared: + virtual bool assertionEnded( AssertionStats const& assertionStats ) = 0; + + virtual void sectionEnded( SectionStats const& sectionStats ) = 0; + virtual void testCaseEnded( TestCaseStats const& testCaseStats ) = 0; + virtual void testGroupEnded( TestGroupStats const& testGroupStats ) = 0; + virtual void testRunEnded( TestRunStats const& testRunStats ) = 0; + + virtual void skipTest( TestCaseInfo const& testInfo ) = 0; + }; + + struct IReporterFactory : IShared { + virtual ~IReporterFactory(); + virtual IStreamingReporter* create( ReporterConfig const& config ) const = 0; + virtual std::string getDescription() const = 0; + }; + + struct IReporterRegistry { + typedef std::map<std::string, Ptr<IReporterFactory> > FactoryMap; + typedef std::vector<Ptr<IReporterFactory> > Listeners; + + virtual ~IReporterRegistry(); + virtual IStreamingReporter* create( std::string const& name, Ptr<IConfig const> const& config ) const = 0; + virtual FactoryMap const& getFactories() const = 0; + virtual Listeners const& getListeners() const = 0; + }; + + Ptr<IStreamingReporter> addReporter( Ptr<IStreamingReporter> const& existingReporter, Ptr<IStreamingReporter> const& additionalReporter ); + +} + +#include <limits> +#include <algorithm> + +namespace Catch { + + inline std::size_t listTests( Config const& config ) { + + TestSpec testSpec = config.testSpec(); + if( config.testSpec().hasFilters() ) + Catch::cout() << "Matching test cases:\n"; + else { + Catch::cout() << "All available test cases:\n"; + testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "*" ).testSpec(); + } + + std::size_t matchedTests = 0; + TextAttributes nameAttr, tagsAttr; + nameAttr.setInitialIndent( 2 ).setIndent( 4 ); + tagsAttr.setIndent( 6 ); + + std::vector<TestCase> matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config ); + for( std::vector<TestCase>::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end(); + it != itEnd; + ++it ) { + matchedTests++; + TestCaseInfo const& testCaseInfo = it->getTestCaseInfo(); + Colour::Code colour = testCaseInfo.isHidden() + ? Colour::SecondaryText + : Colour::None; + Colour colourGuard( colour ); + + Catch::cout() << Text( testCaseInfo.name, nameAttr ) << std::endl; + if( !testCaseInfo.tags.empty() ) + Catch::cout() << Text( testCaseInfo.tagsAsString, tagsAttr ) << std::endl; + } + + if( !config.testSpec().hasFilters() ) + Catch::cout() << pluralise( matchedTests, "test case" ) << "\n" << std::endl; + else + Catch::cout() << pluralise( matchedTests, "matching test case" ) << "\n" << std::endl; + return matchedTests; + } + + inline std::size_t listTestsNamesOnly( Config const& config ) { + TestSpec testSpec = config.testSpec(); + if( !config.testSpec().hasFilters() ) + testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "*" ).testSpec(); + std::size_t matchedTests = 0; + std::vector<TestCase> matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config ); + for( std::vector<TestCase>::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end(); + it != itEnd; + ++it ) { + matchedTests++; + TestCaseInfo const& testCaseInfo = it->getTestCaseInfo(); + Catch::cout() << testCaseInfo.name << std::endl; + } + return matchedTests; + } + + struct TagInfo { + TagInfo() : count ( 0 ) {} + void add( std::string const& spelling ) { + ++count; + spellings.insert( spelling ); + } + std::string all() const { + std::string out; + for( std::set<std::string>::const_iterator it = spellings.begin(), itEnd = spellings.end(); + it != itEnd; + ++it ) + out += "[" + *it + "]"; + return out; + } + std::set<std::string> spellings; + std::size_t count; + }; + + inline std::size_t listTags( Config const& config ) { + TestSpec testSpec = config.testSpec(); + if( config.testSpec().hasFilters() ) + Catch::cout() << "Tags for matching test cases:\n"; + else { + Catch::cout() << "All available tags:\n"; + testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "*" ).testSpec(); + } + + std::map<std::string, TagInfo> tagCounts; + + std::vector<TestCase> matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config ); + for( std::vector<TestCase>::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end(); + it != itEnd; + ++it ) { + for( std::set<std::string>::const_iterator tagIt = it->getTestCaseInfo().tags.begin(), + tagItEnd = it->getTestCaseInfo().tags.end(); + tagIt != tagItEnd; + ++tagIt ) { + std::string tagName = *tagIt; + std::string lcaseTagName = toLower( tagName ); + std::map<std::string, TagInfo>::iterator countIt = tagCounts.find( lcaseTagName ); + if( countIt == tagCounts.end() ) + countIt = tagCounts.insert( std::make_pair( lcaseTagName, TagInfo() ) ).first; + countIt->second.add( tagName ); + } + } + + for( std::map<std::string, TagInfo>::const_iterator countIt = tagCounts.begin(), + countItEnd = tagCounts.end(); + countIt != countItEnd; + ++countIt ) { + std::ostringstream oss; + oss << " " << std::setw(2) << countIt->second.count << " "; + Text wrapper( countIt->second.all(), TextAttributes() + .setInitialIndent( 0 ) + .setIndent( oss.str().size() ) + .setWidth( CATCH_CONFIG_CONSOLE_WIDTH-10 ) ); + Catch::cout() << oss.str() << wrapper << "\n"; + } + Catch::cout() << pluralise( tagCounts.size(), "tag" ) << "\n" << std::endl; + return tagCounts.size(); + } + + inline std::size_t listReporters( Config const& /*config*/ ) { + Catch::cout() << "Available reporters:\n"; + IReporterRegistry::FactoryMap const& factories = getRegistryHub().getReporterRegistry().getFactories(); + IReporterRegistry::FactoryMap::const_iterator itBegin = factories.begin(), itEnd = factories.end(), it; + std::size_t maxNameLen = 0; + for(it = itBegin; it != itEnd; ++it ) + maxNameLen = (std::max)( maxNameLen, it->first.size() ); + + for(it = itBegin; it != itEnd; ++it ) { + Text wrapper( it->second->getDescription(), TextAttributes() + .setInitialIndent( 0 ) + .setIndent( 7+maxNameLen ) + .setWidth( CATCH_CONFIG_CONSOLE_WIDTH - maxNameLen-8 ) ); + Catch::cout() << " " + << it->first + << ":" + << std::string( maxNameLen - it->first.size() + 2, ' ' ) + << wrapper << "\n"; + } + Catch::cout() << std::endl; + return factories.size(); + } + + inline Option<std::size_t> list( Config const& config ) { + Option<std::size_t> listedCount; + if( config.listTests() ) + listedCount = listedCount.valueOr(0) + listTests( config ); + if( config.listTestNamesOnly() ) + listedCount = listedCount.valueOr(0) + listTestsNamesOnly( config ); + if( config.listTags() ) + listedCount = listedCount.valueOr(0) + listTags( config ); + if( config.listReporters() ) + listedCount = listedCount.valueOr(0) + listReporters( config ); + return listedCount; + } + +} // end namespace Catch + +// #included from: internal/catch_run_context.hpp +#define TWOBLUECUBES_CATCH_RUNNER_IMPL_HPP_INCLUDED + +// #included from: catch_test_case_tracker.hpp +#define TWOBLUECUBES_CATCH_TEST_CASE_TRACKER_HPP_INCLUDED + +#include <map> +#include <string> +#include <assert.h> +#include <vector> + +namespace Catch { +namespace TestCaseTracking { + + struct ITracker : SharedImpl<> { + virtual ~ITracker(); + + // static queries + virtual std::string name() const = 0; + + // dynamic queries + virtual bool isComplete() const = 0; // Successfully completed or failed + virtual bool isSuccessfullyCompleted() const = 0; + virtual bool isOpen() const = 0; // Started but not complete + virtual bool hasChildren() const = 0; + + virtual ITracker& parent() = 0; + + // actions + virtual void close() = 0; // Successfully complete + virtual void fail() = 0; + virtual void markAsNeedingAnotherRun() = 0; + + virtual void addChild( Ptr<ITracker> const& child ) = 0; + virtual ITracker* findChild( std::string const& name ) = 0; + virtual void openChild() = 0; + }; + + class TrackerContext { + + enum RunState { + NotStarted, + Executing, + CompletedCycle + }; + + Ptr<ITracker> m_rootTracker; + ITracker* m_currentTracker; + RunState m_runState; + + public: + + static TrackerContext& instance() { + static TrackerContext s_instance; + return s_instance; + } + + TrackerContext() + : m_currentTracker( CATCH_NULL ), + m_runState( NotStarted ) + {} + + ITracker& startRun(); + + void endRun() { + m_rootTracker.reset(); + m_currentTracker = CATCH_NULL; + m_runState = NotStarted; + } + + void startCycle() { + m_currentTracker = m_rootTracker.get(); + m_runState = Executing; + } + void completeCycle() { + m_runState = CompletedCycle; + } + + bool completedCycle() const { + return m_runState == CompletedCycle; + } + ITracker& currentTracker() { + return *m_currentTracker; + } + void setCurrentTracker( ITracker* tracker ) { + m_currentTracker = tracker; + } + }; + + class TrackerBase : public ITracker { + protected: + enum CycleState { + NotStarted, + Executing, + ExecutingChildren, + NeedsAnotherRun, + CompletedSuccessfully, + Failed + }; + class TrackerHasName { + std::string m_name; + public: + TrackerHasName( std::string const& name ) : m_name( name ) {} + bool operator ()( Ptr<ITracker> const& tracker ) { + return tracker->name() == m_name; + } + }; + typedef std::vector<Ptr<ITracker> > Children; + std::string m_name; + TrackerContext& m_ctx; + ITracker* m_parent; + Children m_children; + CycleState m_runState; + public: + TrackerBase( std::string const& name, TrackerContext& ctx, ITracker* parent ) + : m_name( name ), + m_ctx( ctx ), + m_parent( parent ), + m_runState( NotStarted ) + {} + virtual ~TrackerBase(); + + virtual std::string name() const CATCH_OVERRIDE { + return m_name; + } + virtual bool isComplete() const CATCH_OVERRIDE { + return m_runState == CompletedSuccessfully || m_runState == Failed; + } + virtual bool isSuccessfullyCompleted() const CATCH_OVERRIDE { + return m_runState == CompletedSuccessfully; + } + virtual bool isOpen() const CATCH_OVERRIDE { + return m_runState != NotStarted && !isComplete(); + } + virtual bool hasChildren() const CATCH_OVERRIDE { + return !m_children.empty(); + } + + virtual void addChild( Ptr<ITracker> const& child ) CATCH_OVERRIDE { + m_children.push_back( child ); + } + + virtual ITracker* findChild( std::string const& name ) CATCH_OVERRIDE { + Children::const_iterator it = std::find_if( m_children.begin(), m_children.end(), TrackerHasName( name ) ); + return( it != m_children.end() ) + ? it->get() + : CATCH_NULL; + } + virtual ITracker& parent() CATCH_OVERRIDE { + assert( m_parent ); // Should always be non-null except for root + return *m_parent; + } + + virtual void openChild() CATCH_OVERRIDE { + if( m_runState != ExecutingChildren ) { + m_runState = ExecutingChildren; + if( m_parent ) + m_parent->openChild(); + } + } + void open() { + m_runState = Executing; + moveToThis(); + if( m_parent ) + m_parent->openChild(); + } + + virtual void close() CATCH_OVERRIDE { + + // Close any still open children (e.g. generators) + while( &m_ctx.currentTracker() != this ) + m_ctx.currentTracker().close(); + + switch( m_runState ) { + case NotStarted: + case CompletedSuccessfully: + case Failed: + throw std::logic_error( "Illogical state" ); + + case NeedsAnotherRun: + break;; + + case Executing: + m_runState = CompletedSuccessfully; + break; + case ExecutingChildren: + if( m_children.empty() || m_children.back()->isComplete() ) + m_runState = CompletedSuccessfully; + break; + + default: + throw std::logic_error( "Unexpected state" ); + } + moveToParent(); + m_ctx.completeCycle(); + } + virtual void fail() CATCH_OVERRIDE { + m_runState = Failed; + if( m_parent ) + m_parent->markAsNeedingAnotherRun(); + moveToParent(); + m_ctx.completeCycle(); + } + virtual void markAsNeedingAnotherRun() CATCH_OVERRIDE { + m_runState = NeedsAnotherRun; + } + private: + void moveToParent() { + assert( m_parent ); + m_ctx.setCurrentTracker( m_parent ); + } + void moveToThis() { + m_ctx.setCurrentTracker( this ); + } + }; + + class SectionTracker : public TrackerBase { + public: + SectionTracker( std::string const& name, TrackerContext& ctx, ITracker* parent ) + : TrackerBase( name, ctx, parent ) + {} + virtual ~SectionTracker(); + + static SectionTracker& acquire( TrackerContext& ctx, std::string const& name ) { + SectionTracker* section = CATCH_NULL; + + ITracker& currentTracker = ctx.currentTracker(); + if( ITracker* childTracker = currentTracker.findChild( name ) ) { + section = dynamic_cast<SectionTracker*>( childTracker ); + assert( section ); + } + else { + section = new SectionTracker( name, ctx, ¤tTracker ); + currentTracker.addChild( section ); + } + if( !ctx.completedCycle() && !section->isComplete() ) { + + section->open(); + } + return *section; + } + }; + + class IndexTracker : public TrackerBase { + int m_size; + int m_index; + public: + IndexTracker( std::string const& name, TrackerContext& ctx, ITracker* parent, int size ) + : TrackerBase( name, ctx, parent ), + m_size( size ), + m_index( -1 ) + {} + virtual ~IndexTracker(); + + static IndexTracker& acquire( TrackerContext& ctx, std::string const& name, int size ) { + IndexTracker* tracker = CATCH_NULL; + + ITracker& currentTracker = ctx.currentTracker(); + if( ITracker* childTracker = currentTracker.findChild( name ) ) { + tracker = dynamic_cast<IndexTracker*>( childTracker ); + assert( tracker ); + } + else { + tracker = new IndexTracker( name, ctx, ¤tTracker, size ); + currentTracker.addChild( tracker ); + } + + if( !ctx.completedCycle() && !tracker->isComplete() ) { + if( tracker->m_runState != ExecutingChildren && tracker->m_runState != NeedsAnotherRun ) + tracker->moveNext(); + tracker->open(); + } + + return *tracker; + } + + int index() const { return m_index; } + + void moveNext() { + m_index++; + m_children.clear(); + } + + virtual void close() CATCH_OVERRIDE { + TrackerBase::close(); + if( m_runState == CompletedSuccessfully && m_index < m_size-1 ) + m_runState = Executing; + } + }; + + inline ITracker& TrackerContext::startRun() { + m_rootTracker = new SectionTracker( "{root}", *this, CATCH_NULL ); + m_currentTracker = CATCH_NULL; + m_runState = Executing; + return *m_rootTracker; + } + +} // namespace TestCaseTracking + +using TestCaseTracking::ITracker; +using TestCaseTracking::TrackerContext; +using TestCaseTracking::SectionTracker; +using TestCaseTracking::IndexTracker; + +} // namespace Catch + +// #included from: catch_fatal_condition.hpp +#define TWOBLUECUBES_CATCH_FATAL_CONDITION_H_INCLUDED + +namespace Catch { + + // Report the error condition then exit the process + inline void fatal( std::string const& message, int exitCode ) { + IContext& context = Catch::getCurrentContext(); + IResultCapture* resultCapture = context.getResultCapture(); + resultCapture->handleFatalErrorCondition( message ); + + if( Catch::alwaysTrue() ) // avoids "no return" warnings + exit( exitCode ); + } + +} // namespace Catch + +#if defined ( CATCH_PLATFORM_WINDOWS ) ///////////////////////////////////////// + +namespace Catch { + + struct FatalConditionHandler { + void reset() {} + }; + +} // namespace Catch + +#else // Not Windows - assumed to be POSIX compatible ////////////////////////// + +#include <signal.h> + +namespace Catch { + + struct SignalDefs { int id; const char* name; }; + extern SignalDefs signalDefs[]; + SignalDefs signalDefs[] = { + { SIGINT, "SIGINT - Terminal interrupt signal" }, + { SIGILL, "SIGILL - Illegal instruction signal" }, + { SIGFPE, "SIGFPE - Floating point error signal" }, + { SIGSEGV, "SIGSEGV - Segmentation violation signal" }, + { SIGTERM, "SIGTERM - Termination request signal" }, + { SIGABRT, "SIGABRT - Abort (abnormal termination) signal" } + }; + + struct FatalConditionHandler { + + static void handleSignal( int sig ) { + for( std::size_t i = 0; i < sizeof(signalDefs)/sizeof(SignalDefs); ++i ) + if( sig == signalDefs[i].id ) + fatal( signalDefs[i].name, -sig ); + fatal( "<unknown signal>", -sig ); + } + + FatalConditionHandler() : m_isSet( true ) { + for( std::size_t i = 0; i < sizeof(signalDefs)/sizeof(SignalDefs); ++i ) + signal( signalDefs[i].id, handleSignal ); + } + ~FatalConditionHandler() { + reset(); + } + void reset() { + if( m_isSet ) { + for( std::size_t i = 0; i < sizeof(signalDefs)/sizeof(SignalDefs); ++i ) + signal( signalDefs[i].id, SIG_DFL ); + m_isSet = false; + } + } + + bool m_isSet; + }; + +} // namespace Catch + +#endif // not Windows + +#include <set> +#include <string> + +namespace Catch { + + class StreamRedirect { + + public: + StreamRedirect( std::ostream& stream, std::string& targetString ) + : m_stream( stream ), + m_prevBuf( stream.rdbuf() ), + m_targetString( targetString ) + { + stream.rdbuf( m_oss.rdbuf() ); + } + + ~StreamRedirect() { + m_targetString += m_oss.str(); + m_stream.rdbuf( m_prevBuf ); + } + + private: + std::ostream& m_stream; + std::streambuf* m_prevBuf; + std::ostringstream m_oss; + std::string& m_targetString; + }; + + /////////////////////////////////////////////////////////////////////////// + + class RunContext : public IResultCapture, public IRunner { + + RunContext( RunContext const& ); + void operator =( RunContext const& ); + + public: + + explicit RunContext( Ptr<IConfig const> const& _config, Ptr<IStreamingReporter> const& reporter ) + : m_runInfo( _config->name() ), + m_context( getCurrentMutableContext() ), + m_activeTestCase( CATCH_NULL ), + m_config( _config ), + m_reporter( reporter ) + { + m_context.setRunner( this ); + m_context.setConfig( m_config ); + m_context.setResultCapture( this ); + m_reporter->testRunStarting( m_runInfo ); + } + + virtual ~RunContext() { + m_reporter->testRunEnded( TestRunStats( m_runInfo, m_totals, aborting() ) ); + } + + void testGroupStarting( std::string const& testSpec, std::size_t groupIndex, std::size_t groupsCount ) { + m_reporter->testGroupStarting( GroupInfo( testSpec, groupIndex, groupsCount ) ); + } + void testGroupEnded( std::string const& testSpec, Totals const& totals, std::size_t groupIndex, std::size_t groupsCount ) { + m_reporter->testGroupEnded( TestGroupStats( GroupInfo( testSpec, groupIndex, groupsCount ), totals, aborting() ) ); + } + + Totals runTest( TestCase const& testCase ) { + Totals prevTotals = m_totals; + + std::string redirectedCout; + std::string redirectedCerr; + + TestCaseInfo testInfo = testCase.getTestCaseInfo(); + + m_reporter->testCaseStarting( testInfo ); + + m_activeTestCase = &testCase; + + do { + m_trackerContext.startRun(); + do { + m_trackerContext.startCycle(); + m_testCaseTracker = &SectionTracker::acquire( m_trackerContext, testInfo.name ); + runCurrentTest( redirectedCout, redirectedCerr ); + } + while( !m_testCaseTracker->isSuccessfullyCompleted() && !aborting() ); + } + // !TBD: deprecated - this will be replaced by indexed trackers + while( getCurrentContext().advanceGeneratorsForCurrentTest() && !aborting() ); + + Totals deltaTotals = m_totals.delta( prevTotals ); + m_totals.testCases += deltaTotals.testCases; + m_reporter->testCaseEnded( TestCaseStats( testInfo, + deltaTotals, + redirectedCout, + redirectedCerr, + aborting() ) ); + + m_activeTestCase = CATCH_NULL; + m_testCaseTracker = CATCH_NULL; + + return deltaTotals; + } + + Ptr<IConfig const> config() const { + return m_config; + } + + private: // IResultCapture + + virtual void assertionEnded( AssertionResult const& result ) { + if( result.getResultType() == ResultWas::Ok ) { + m_totals.assertions.passed++; + } + else if( !result.isOk() ) { + m_totals.assertions.failed++; + } + + if( m_reporter->assertionEnded( AssertionStats( result, m_messages, m_totals ) ) ) + m_messages.clear(); + + // Reset working state + m_lastAssertionInfo = AssertionInfo( "", m_lastAssertionInfo.lineInfo, "{Unknown expression after the reported line}" , m_lastAssertionInfo.resultDisposition ); + m_lastResult = result; + } + + virtual bool sectionStarted ( + SectionInfo const& sectionInfo, + Counts& assertions + ) + { + std::ostringstream oss; + oss << sectionInfo.name << "@" << sectionInfo.lineInfo; + + ITracker& sectionTracker = SectionTracker::acquire( m_trackerContext, oss.str() ); + if( !sectionTracker.isOpen() ) + return false; + m_activeSections.push_back( §ionTracker ); + + m_lastAssertionInfo.lineInfo = sectionInfo.lineInfo; + + m_reporter->sectionStarting( sectionInfo ); + + assertions = m_totals.assertions; + + return true; + } + bool testForMissingAssertions( Counts& assertions ) { + if( assertions.total() != 0 ) + return false; + if( !m_config->warnAboutMissingAssertions() ) + return false; + if( m_trackerContext.currentTracker().hasChildren() ) + return false; + m_totals.assertions.failed++; + assertions.failed++; + return true; + } + + virtual void sectionEnded( SectionEndInfo const& endInfo ) { + Counts assertions = m_totals.assertions - endInfo.prevAssertions; + bool missingAssertions = testForMissingAssertions( assertions ); + + if( !m_activeSections.empty() ) { + m_activeSections.back()->close(); + m_activeSections.pop_back(); + } + + m_reporter->sectionEnded( SectionStats( endInfo.sectionInfo, assertions, endInfo.durationInSeconds, missingAssertions ) ); + m_messages.clear(); + } + + virtual void sectionEndedEarly( SectionEndInfo const& endInfo ) { + if( m_unfinishedSections.empty() ) + m_activeSections.back()->fail(); + else + m_activeSections.back()->close(); + m_activeSections.pop_back(); + + m_unfinishedSections.push_back( endInfo ); + } + + virtual void pushScopedMessage( MessageInfo const& message ) { + m_messages.push_back( message ); + } + + virtual void popScopedMessage( MessageInfo const& message ) { + m_messages.erase( std::remove( m_messages.begin(), m_messages.end(), message ), m_messages.end() ); + } + + virtual std::string getCurrentTestName() const { + return m_activeTestCase + ? m_activeTestCase->getTestCaseInfo().name + : ""; + } + + virtual const AssertionResult* getLastResult() const { + return &m_lastResult; + } + + virtual void handleFatalErrorCondition( std::string const& message ) { + ResultBuilder resultBuilder = makeUnexpectedResultBuilder(); + resultBuilder.setResultType( ResultWas::FatalErrorCondition ); + resultBuilder << message; + resultBuilder.captureExpression(); + + handleUnfinishedSections(); + + // Recreate section for test case (as we will lose the one that was in scope) + TestCaseInfo const& testCaseInfo = m_activeTestCase->getTestCaseInfo(); + SectionInfo testCaseSection( testCaseInfo.lineInfo, testCaseInfo.name, testCaseInfo.description ); + + Counts assertions; + assertions.failed = 1; + SectionStats testCaseSectionStats( testCaseSection, assertions, 0, false ); + m_reporter->sectionEnded( testCaseSectionStats ); + + TestCaseInfo testInfo = m_activeTestCase->getTestCaseInfo(); + + Totals deltaTotals; + deltaTotals.testCases.failed = 1; + m_reporter->testCaseEnded( TestCaseStats( testInfo, + deltaTotals, + "", + "", + false ) ); + m_totals.testCases.failed++; + testGroupEnded( "", m_totals, 1, 1 ); + m_reporter->testRunEnded( TestRunStats( m_runInfo, m_totals, false ) ); + } + + public: + // !TBD We need to do this another way! + bool aborting() const { + return m_totals.assertions.failed == static_cast<std::size_t>( m_config->abortAfter() ); + } + + private: + + void runCurrentTest( std::string& redirectedCout, std::string& redirectedCerr ) { + TestCaseInfo const& testCaseInfo = m_activeTestCase->getTestCaseInfo(); + SectionInfo testCaseSection( testCaseInfo.lineInfo, testCaseInfo.name, testCaseInfo.description ); + m_reporter->sectionStarting( testCaseSection ); + Counts prevAssertions = m_totals.assertions; + double duration = 0; + try { + m_lastAssertionInfo = AssertionInfo( "TEST_CASE", testCaseInfo.lineInfo, "", ResultDisposition::Normal ); + + seedRng( *m_config ); + + Timer timer; + timer.start(); + if( m_reporter->getPreferences().shouldRedirectStdOut ) { + StreamRedirect coutRedir( Catch::cout(), redirectedCout ); + StreamRedirect cerrRedir( Catch::cerr(), redirectedCerr ); + invokeActiveTestCase(); + } + else { + invokeActiveTestCase(); + } + duration = timer.getElapsedSeconds(); + } + catch( TestFailureException& ) { + // This just means the test was aborted due to failure + } + catch(...) { + makeUnexpectedResultBuilder().useActiveException(); + } + m_testCaseTracker->close(); + handleUnfinishedSections(); + m_messages.clear(); + + Counts assertions = m_totals.assertions - prevAssertions; + bool missingAssertions = testForMissingAssertions( assertions ); + + if( testCaseInfo.okToFail() ) { + std::swap( assertions.failedButOk, assertions.failed ); + m_totals.assertions.failed -= assertions.failedButOk; + m_totals.assertions.failedButOk += assertions.failedButOk; + } + + SectionStats testCaseSectionStats( testCaseSection, assertions, duration, missingAssertions ); + m_reporter->sectionEnded( testCaseSectionStats ); + } + + void invokeActiveTestCase() { + FatalConditionHandler fatalConditionHandler; // Handle signals + m_activeTestCase->invoke(); + fatalConditionHandler.reset(); + } + + private: + + ResultBuilder makeUnexpectedResultBuilder() const { + return ResultBuilder( m_lastAssertionInfo.macroName.c_str(), + m_lastAssertionInfo.lineInfo, + m_lastAssertionInfo.capturedExpression.c_str(), + m_lastAssertionInfo.resultDisposition ); + } + + void handleUnfinishedSections() { + // If sections ended prematurely due to an exception we stored their + // infos here so we can tear them down outside the unwind process. + for( std::vector<SectionEndInfo>::const_reverse_iterator it = m_unfinishedSections.rbegin(), + itEnd = m_unfinishedSections.rend(); + it != itEnd; + ++it ) + sectionEnded( *it ); + m_unfinishedSections.clear(); + } + + TestRunInfo m_runInfo; + IMutableContext& m_context; + TestCase const* m_activeTestCase; + ITracker* m_testCaseTracker; + ITracker* m_currentSectionTracker; + AssertionResult m_lastResult; + + Ptr<IConfig const> m_config; + Totals m_totals; + Ptr<IStreamingReporter> m_reporter; + std::vector<MessageInfo> m_messages; + AssertionInfo m_lastAssertionInfo; + std::vector<SectionEndInfo> m_unfinishedSections; + std::vector<ITracker*> m_activeSections; + TrackerContext m_trackerContext; + }; + + IResultCapture& getResultCapture() { + if( IResultCapture* capture = getCurrentContext().getResultCapture() ) + return *capture; + else + throw std::logic_error( "No result capture instance" ); + } + +} // end namespace Catch + +// #included from: internal/catch_version.h +#define TWOBLUECUBES_CATCH_VERSION_H_INCLUDED + +namespace Catch { + + // Versioning information + struct Version { + Version( unsigned int _majorVersion, + unsigned int _minorVersion, + unsigned int _patchNumber, + std::string const& _branchName, + unsigned int _buildNumber ); + + unsigned int const majorVersion; + unsigned int const minorVersion; + unsigned int const patchNumber; + + // buildNumber is only used if branchName is not null + std::string const branchName; + unsigned int const buildNumber; + + friend std::ostream& operator << ( std::ostream& os, Version const& version ); + + private: + void operator=( Version const& ); + }; + + extern Version libraryVersion; +} + +#include <fstream> +#include <stdlib.h> +#include <limits> + +namespace Catch { + + Ptr<IStreamingReporter> createReporter( std::string const& reporterName, Ptr<Config> const& config ) { + Ptr<IStreamingReporter> reporter = getRegistryHub().getReporterRegistry().create( reporterName, config.get() ); + if( !reporter ) { + std::ostringstream oss; + oss << "No reporter registered with name: '" << reporterName << "'"; + throw std::domain_error( oss.str() ); + } + return reporter; + } + + Ptr<IStreamingReporter> makeReporter( Ptr<Config> const& config ) { + std::vector<std::string> reporters = config->getReporterNames(); + if( reporters.empty() ) + reporters.push_back( "console" ); + + Ptr<IStreamingReporter> reporter; + for( std::vector<std::string>::const_iterator it = reporters.begin(), itEnd = reporters.end(); + it != itEnd; + ++it ) + reporter = addReporter( reporter, createReporter( *it, config ) ); + return reporter; + } + Ptr<IStreamingReporter> addListeners( Ptr<IConfig const> const& config, Ptr<IStreamingReporter> reporters ) { + IReporterRegistry::Listeners listeners = getRegistryHub().getReporterRegistry().getListeners(); + for( IReporterRegistry::Listeners::const_iterator it = listeners.begin(), itEnd = listeners.end(); + it != itEnd; + ++it ) + reporters = addReporter(reporters, (*it)->create( ReporterConfig( config ) ) ); + return reporters; + } + + Totals runTests( Ptr<Config> const& config ) { + + Ptr<IConfig const> iconfig = config.get(); + + Ptr<IStreamingReporter> reporter = makeReporter( config ); + reporter = addListeners( iconfig, reporter ); + + RunContext context( iconfig, reporter ); + + Totals totals; + + context.testGroupStarting( config->name(), 1, 1 ); + + TestSpec testSpec = config->testSpec(); + if( !testSpec.hasFilters() ) + testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "~[.]" ).testSpec(); // All not hidden tests + + std::vector<TestCase> const& allTestCases = getAllTestCasesSorted( *iconfig ); + for( std::vector<TestCase>::const_iterator it = allTestCases.begin(), itEnd = allTestCases.end(); + it != itEnd; + ++it ) { + if( !context.aborting() && matchTest( *it, testSpec, *iconfig ) ) + totals += context.runTest( *it ); + else + reporter->skipTest( *it ); + } + + context.testGroupEnded( iconfig->name(), totals, 1, 1 ); + return totals; + } + + void applyFilenamesAsTags( IConfig const& config ) { + std::vector<TestCase> const& tests = getAllTestCasesSorted( config ); + for(std::size_t i = 0; i < tests.size(); ++i ) { + TestCase& test = const_cast<TestCase&>( tests[i] ); + std::set<std::string> tags = test.tags; + + std::string filename = test.lineInfo.file; + std::string::size_type lastSlash = filename.find_last_of( "\\/" ); + if( lastSlash != std::string::npos ) + filename = filename.substr( lastSlash+1 ); + + std::string::size_type lastDot = filename.find_last_of( "." ); + if( lastDot != std::string::npos ) + filename = filename.substr( 0, lastDot ); + + tags.insert( "#" + filename ); + setTags( test, tags ); + } + } + + class Session : NonCopyable { + static bool alreadyInstantiated; + + public: + + struct OnUnusedOptions { enum DoWhat { Ignore, Fail }; }; + + Session() + : m_cli( makeCommandLineParser() ) { + if( alreadyInstantiated ) { + std::string msg = "Only one instance of Catch::Session can ever be used"; + Catch::cerr() << msg << std::endl; + throw std::logic_error( msg ); + } + alreadyInstantiated = true; + } + ~Session() { + Catch::cleanUp(); + } + + void showHelp( std::string const& processName ) { + Catch::cout() << "\nCatch v" << libraryVersion << "\n"; + + m_cli.usage( Catch::cout(), processName ); + Catch::cout() << "For more detail usage please see the project docs\n" << std::endl; + } + + int applyCommandLine( int argc, char const* argv[], OnUnusedOptions::DoWhat unusedOptionBehaviour = OnUnusedOptions::Fail ) { + try { + m_cli.setThrowOnUnrecognisedTokens( unusedOptionBehaviour == OnUnusedOptions::Fail ); + m_unusedTokens = m_cli.parseInto( argc, argv, m_configData ); + if( m_configData.showHelp ) + showHelp( m_configData.processName ); + m_config.reset(); + } + catch( std::exception& ex ) { + { + Colour colourGuard( Colour::Red ); + Catch::cerr() + << "\nError(s) in input:\n" + << Text( ex.what(), TextAttributes().setIndent(2) ) + << "\n\n"; + } + m_cli.usage( Catch::cout(), m_configData.processName ); + return (std::numeric_limits<int>::max)(); + } + return 0; + } + + void useConfigData( ConfigData const& _configData ) { + m_configData = _configData; + m_config.reset(); + } + + int run( int argc, char const* argv[] ) { + + int returnCode = applyCommandLine( argc, argv ); + if( returnCode == 0 ) + returnCode = run(); + return returnCode; + } + int run( int argc, char* argv[] ) { + return run( argc, const_cast<char const**>( argv ) ); + } + + int run() { + if( m_configData.showHelp ) + return 0; + + try + { + config(); // Force config to be constructed + + seedRng( *m_config ); + + if( m_configData.filenamesAsTags ) + applyFilenamesAsTags( *m_config ); + + // Handle list request + if( Option<std::size_t> listed = list( config() ) ) + return static_cast<int>( *listed ); + + return static_cast<int>( runTests( m_config ).assertions.failed ); + } + catch( std::exception& ex ) { + Catch::cerr() << ex.what() << std::endl; + return (std::numeric_limits<int>::max)(); + } + } + + Clara::CommandLine<ConfigData> const& cli() const { + return m_cli; + } + std::vector<Clara::Parser::Token> const& unusedTokens() const { + return m_unusedTokens; + } + ConfigData& configData() { + return m_configData; + } + Config& config() { + if( !m_config ) + m_config = new Config( m_configData ); + return *m_config; + } + private: + Clara::CommandLine<ConfigData> m_cli; + std::vector<Clara::Parser::Token> m_unusedTokens; + ConfigData m_configData; + Ptr<Config> m_config; + }; + + bool Session::alreadyInstantiated = false; + +} // end namespace Catch + +// #included from: catch_registry_hub.hpp +#define TWOBLUECUBES_CATCH_REGISTRY_HUB_HPP_INCLUDED + +// #included from: catch_test_case_registry_impl.hpp +#define TWOBLUECUBES_CATCH_TEST_CASE_REGISTRY_IMPL_HPP_INCLUDED + +#include <vector> +#include <set> +#include <sstream> +#include <iostream> +#include <algorithm> + +namespace Catch { + + struct LexSort { + bool operator() (TestCase i,TestCase j) const { return (i<j);} + }; + struct RandomNumberGenerator { + int operator()( int n ) const { return std::rand() % n; } + }; + + inline std::vector<TestCase> sortTests( IConfig const& config, std::vector<TestCase> const& unsortedTestCases ) { + + std::vector<TestCase> sorted = unsortedTestCases; + + switch( config.runOrder() ) { + case RunTests::InLexicographicalOrder: + std::sort( sorted.begin(), sorted.end(), LexSort() ); + break; + case RunTests::InRandomOrder: + { + seedRng( config ); + + RandomNumberGenerator rng; + std::random_shuffle( sorted.begin(), sorted.end(), rng ); + } + break; + case RunTests::InDeclarationOrder: + // already in declaration order + break; + } + return sorted; + } + bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config ) { + return testSpec.matches( testCase ) && ( config.allowThrows() || !testCase.throws() ); + } + + void enforceNoDuplicateTestCases( std::vector<TestCase> const& functions ) { + std::set<TestCase> seenFunctions; + for( std::vector<TestCase>::const_iterator it = functions.begin(), itEnd = functions.end(); + it != itEnd; + ++it ) { + std::pair<std::set<TestCase>::const_iterator, bool> prev = seenFunctions.insert( *it ); + if( !prev.second ){ + Catch::cerr() + << Colour( Colour::Red ) + << "error: TEST_CASE( \"" << it->name << "\" ) already defined.\n" + << "\tFirst seen at " << prev.first->getTestCaseInfo().lineInfo << "\n" + << "\tRedefined at " << it->getTestCaseInfo().lineInfo << std::endl; + exit(1); + } + } + } + + std::vector<TestCase> filterTests( std::vector<TestCase> const& testCases, TestSpec const& testSpec, IConfig const& config ) { + std::vector<TestCase> filtered; + filtered.reserve( testCases.size() ); + for( std::vector<TestCase>::const_iterator it = testCases.begin(), itEnd = testCases.end(); + it != itEnd; + ++it ) + if( matchTest( *it, testSpec, config ) ) + filtered.push_back( *it ); + return filtered; + } + std::vector<TestCase> const& getAllTestCasesSorted( IConfig const& config ) { + return getRegistryHub().getTestCaseRegistry().getAllTestsSorted( config ); + } + + class TestRegistry : public ITestCaseRegistry { + public: + TestRegistry() + : m_currentSortOrder( RunTests::InDeclarationOrder ), + m_unnamedCount( 0 ) + {} + virtual ~TestRegistry(); + + virtual void registerTest( TestCase const& testCase ) { + std::string name = testCase.getTestCaseInfo().name; + if( name == "" ) { + std::ostringstream oss; + oss << "Anonymous test case " << ++m_unnamedCount; + return registerTest( testCase.withName( oss.str() ) ); + } + m_functions.push_back( testCase ); + } + + virtual std::vector<TestCase> const& getAllTests() const { + return m_functions; + } + virtual std::vector<TestCase> const& getAllTestsSorted( IConfig const& config ) const { + if( m_sortedFunctions.empty() ) + enforceNoDuplicateTestCases( m_functions ); + + if( m_currentSortOrder != config.runOrder() || m_sortedFunctions.empty() ) { + m_sortedFunctions = sortTests( config, m_functions ); + m_currentSortOrder = config.runOrder(); + } + return m_sortedFunctions; + } + + private: + std::vector<TestCase> m_functions; + mutable RunTests::InWhatOrder m_currentSortOrder; + mutable std::vector<TestCase> m_sortedFunctions; + size_t m_unnamedCount; + std::ios_base::Init m_ostreamInit; // Forces cout/ cerr to be initialised + }; + + /////////////////////////////////////////////////////////////////////////// + + class FreeFunctionTestCase : public SharedImpl<ITestCase> { + public: + + FreeFunctionTestCase( TestFunction fun ) : m_fun( fun ) {} + + virtual void invoke() const { + m_fun(); + } + + private: + virtual ~FreeFunctionTestCase(); + + TestFunction m_fun; + }; + + inline std::string extractClassName( std::string const& classOrQualifiedMethodName ) { + std::string className = classOrQualifiedMethodName; + if( startsWith( className, "&" ) ) + { + std::size_t lastColons = className.rfind( "::" ); + std::size_t penultimateColons = className.rfind( "::", lastColons-1 ); + if( penultimateColons == std::string::npos ) + penultimateColons = 1; + className = className.substr( penultimateColons, lastColons-penultimateColons ); + } + return className; + } + + void registerTestCase + ( ITestCase* testCase, + char const* classOrQualifiedMethodName, + NameAndDesc const& nameAndDesc, + SourceLineInfo const& lineInfo ) { + + getMutableRegistryHub().registerTest + ( makeTestCase + ( testCase, + extractClassName( classOrQualifiedMethodName ), + nameAndDesc.name, + nameAndDesc.description, + lineInfo ) ); + } + void registerTestCaseFunction + ( TestFunction function, + SourceLineInfo const& lineInfo, + NameAndDesc const& nameAndDesc ) { + registerTestCase( new FreeFunctionTestCase( function ), "", nameAndDesc, lineInfo ); + } + + /////////////////////////////////////////////////////////////////////////// + + AutoReg::AutoReg + ( TestFunction function, + SourceLineInfo const& lineInfo, + NameAndDesc const& nameAndDesc ) { + registerTestCaseFunction( function, lineInfo, nameAndDesc ); + } + + AutoReg::~AutoReg() {} + +} // end namespace Catch + +// #included from: catch_reporter_registry.hpp +#define TWOBLUECUBES_CATCH_REPORTER_REGISTRY_HPP_INCLUDED + +#include <map> + +namespace Catch { + + class ReporterRegistry : public IReporterRegistry { + + public: + + virtual ~ReporterRegistry() CATCH_OVERRIDE {} + + virtual IStreamingReporter* create( std::string const& name, Ptr<IConfig const> const& config ) const CATCH_OVERRIDE { + FactoryMap::const_iterator it = m_factories.find( name ); + if( it == m_factories.end() ) + return CATCH_NULL; + return it->second->create( ReporterConfig( config ) ); + } + + void registerReporter( std::string const& name, Ptr<IReporterFactory> const& factory ) { + m_factories.insert( std::make_pair( name, factory ) ); + } + void registerListener( Ptr<IReporterFactory> const& factory ) { + m_listeners.push_back( factory ); + } + + virtual FactoryMap const& getFactories() const CATCH_OVERRIDE { + return m_factories; + } + virtual Listeners const& getListeners() const CATCH_OVERRIDE { + return m_listeners; + } + + private: + FactoryMap m_factories; + Listeners m_listeners; + }; +} + +// #included from: catch_exception_translator_registry.hpp +#define TWOBLUECUBES_CATCH_EXCEPTION_TRANSLATOR_REGISTRY_HPP_INCLUDED + +#ifdef __OBJC__ +#import "Foundation/Foundation.h" +#endif + +namespace Catch { + + class ExceptionTranslatorRegistry : public IExceptionTranslatorRegistry { + public: + ~ExceptionTranslatorRegistry() { + deleteAll( m_translators ); + } + + virtual void registerTranslator( const IExceptionTranslator* translator ) { + m_translators.push_back( translator ); + } + + virtual std::string translateActiveException() const { + try { +#ifdef __OBJC__ + // In Objective-C try objective-c exceptions first + @try { + return tryTranslators(); + } + @catch (NSException *exception) { + return Catch::toString( [exception description] ); + } +#else + return tryTranslators(); +#endif + } + catch( TestFailureException& ) { + throw; + } + catch( std::exception& ex ) { + return ex.what(); + } + catch( std::string& msg ) { + return msg; + } + catch( const char* msg ) { + return msg; + } + catch(...) { + return "Unknown exception"; + } + } + + std::string tryTranslators() const { + if( m_translators.empty() ) + throw; + else + return m_translators[0]->translate( m_translators.begin()+1, m_translators.end() ); + } + + private: + std::vector<const IExceptionTranslator*> m_translators; + }; +} + +namespace Catch { + + namespace { + + class RegistryHub : public IRegistryHub, public IMutableRegistryHub { + + RegistryHub( RegistryHub const& ); + void operator=( RegistryHub const& ); + + public: // IRegistryHub + RegistryHub() { + } + virtual IReporterRegistry const& getReporterRegistry() const CATCH_OVERRIDE { + return m_reporterRegistry; + } + virtual ITestCaseRegistry const& getTestCaseRegistry() const CATCH_OVERRIDE { + return m_testCaseRegistry; + } + virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() CATCH_OVERRIDE { + return m_exceptionTranslatorRegistry; + } + + public: // IMutableRegistryHub + virtual void registerReporter( std::string const& name, Ptr<IReporterFactory> const& factory ) CATCH_OVERRIDE { + m_reporterRegistry.registerReporter( name, factory ); + } + virtual void registerListener( Ptr<IReporterFactory> const& factory ) CATCH_OVERRIDE { + m_reporterRegistry.registerListener( factory ); + } + virtual void registerTest( TestCase const& testInfo ) CATCH_OVERRIDE { + m_testCaseRegistry.registerTest( testInfo ); + } + virtual void registerTranslator( const IExceptionTranslator* translator ) CATCH_OVERRIDE { + m_exceptionTranslatorRegistry.registerTranslator( translator ); + } + + private: + TestRegistry m_testCaseRegistry; + ReporterRegistry m_reporterRegistry; + ExceptionTranslatorRegistry m_exceptionTranslatorRegistry; + }; + + // Single, global, instance + inline RegistryHub*& getTheRegistryHub() { + static RegistryHub* theRegistryHub = CATCH_NULL; + if( !theRegistryHub ) + theRegistryHub = new RegistryHub(); + return theRegistryHub; + } + } + + IRegistryHub& getRegistryHub() { + return *getTheRegistryHub(); + } + IMutableRegistryHub& getMutableRegistryHub() { + return *getTheRegistryHub(); + } + void cleanUp() { + delete getTheRegistryHub(); + getTheRegistryHub() = CATCH_NULL; + cleanUpContext(); + } + std::string translateActiveException() { + return getRegistryHub().getExceptionTranslatorRegistry().translateActiveException(); + } + +} // end namespace Catch + +// #included from: catch_notimplemented_exception.hpp +#define TWOBLUECUBES_CATCH_NOTIMPLEMENTED_EXCEPTION_HPP_INCLUDED + +#include <ostream> + +namespace Catch { + + NotImplementedException::NotImplementedException( SourceLineInfo const& lineInfo ) + : m_lineInfo( lineInfo ) { + std::ostringstream oss; + oss << lineInfo << ": function "; + oss << "not implemented"; + m_what = oss.str(); + } + + const char* NotImplementedException::what() const CATCH_NOEXCEPT { + return m_what.c_str(); + } + +} // end namespace Catch + +// #included from: catch_context_impl.hpp +#define TWOBLUECUBES_CATCH_CONTEXT_IMPL_HPP_INCLUDED + +// #included from: catch_stream.hpp +#define TWOBLUECUBES_CATCH_STREAM_HPP_INCLUDED + +#include <stdexcept> +#include <cstdio> +#include <iostream> + +namespace Catch { + + template<typename WriterF, size_t bufferSize=256> + class StreamBufImpl : public StreamBufBase { + char data[bufferSize]; + WriterF m_writer; + + public: + StreamBufImpl() { + setp( data, data + sizeof(data) ); + } + + ~StreamBufImpl() CATCH_NOEXCEPT { + sync(); + } + + private: + int overflow( int c ) { + sync(); + + if( c != EOF ) { + if( pbase() == epptr() ) + m_writer( std::string( 1, static_cast<char>( c ) ) ); + else + sputc( static_cast<char>( c ) ); + } + return 0; + } + + int sync() { + if( pbase() != pptr() ) { + m_writer( std::string( pbase(), static_cast<std::string::size_type>( pptr() - pbase() ) ) ); + setp( pbase(), epptr() ); + } + return 0; + } + }; + + /////////////////////////////////////////////////////////////////////////// + + FileStream::FileStream( std::string const& filename ) { + m_ofs.open( filename.c_str() ); + if( m_ofs.fail() ) { + std::ostringstream oss; + oss << "Unable to open file: '" << filename << "'"; + throw std::domain_error( oss.str() ); + } + } + + std::ostream& FileStream::stream() const { + return m_ofs; + } + + struct OutputDebugWriter { + + void operator()( std::string const&str ) { + writeToDebugConsole( str ); + } + }; + + DebugOutStream::DebugOutStream() + : m_streamBuf( new StreamBufImpl<OutputDebugWriter>() ), + m_os( m_streamBuf.get() ) + {} + + std::ostream& DebugOutStream::stream() const { + return m_os; + } + + // Store the streambuf from cout up-front because + // cout may get redirected when running tests + CoutStream::CoutStream() + : m_os( Catch::cout().rdbuf() ) + {} + + std::ostream& CoutStream::stream() const { + return m_os; + } + +#ifndef CATCH_CONFIG_NOSTDOUT // If you #define this you must implement these functions + std::ostream& cout() { + return std::cout; + } + std::ostream& cerr() { + return std::cerr; + } +#endif +} + +namespace Catch { + + class Context : public IMutableContext { + + Context() : m_config( CATCH_NULL ), m_runner( CATCH_NULL ), m_resultCapture( CATCH_NULL ) {} + Context( Context const& ); + void operator=( Context const& ); + + public: // IContext + virtual IResultCapture* getResultCapture() { + return m_resultCapture; + } + virtual IRunner* getRunner() { + return m_runner; + } + virtual size_t getGeneratorIndex( std::string const& fileInfo, size_t totalSize ) { + return getGeneratorsForCurrentTest() + .getGeneratorInfo( fileInfo, totalSize ) + .getCurrentIndex(); + } + virtual bool advanceGeneratorsForCurrentTest() { + IGeneratorsForTest* generators = findGeneratorsForCurrentTest(); + return generators && generators->moveNext(); + } + + virtual Ptr<IConfig const> getConfig() const { + return m_config; + } + + public: // IMutableContext + virtual void setResultCapture( IResultCapture* resultCapture ) { + m_resultCapture = resultCapture; + } + virtual void setRunner( IRunner* runner ) { + m_runner = runner; + } + virtual void setConfig( Ptr<IConfig const> const& config ) { + m_config = config; + } + + friend IMutableContext& getCurrentMutableContext(); + + private: + IGeneratorsForTest* findGeneratorsForCurrentTest() { + std::string testName = getResultCapture()->getCurrentTestName(); + + std::map<std::string, IGeneratorsForTest*>::const_iterator it = + m_generatorsByTestName.find( testName ); + return it != m_generatorsByTestName.end() + ? it->second + : CATCH_NULL; + } + + IGeneratorsForTest& getGeneratorsForCurrentTest() { + IGeneratorsForTest* generators = findGeneratorsForCurrentTest(); + if( !generators ) { + std::string testName = getResultCapture()->getCurrentTestName(); + generators = createGeneratorsForTest(); + m_generatorsByTestName.insert( std::make_pair( testName, generators ) ); + } + return *generators; + } + + private: + Ptr<IConfig const> m_config; + IRunner* m_runner; + IResultCapture* m_resultCapture; + std::map<std::string, IGeneratorsForTest*> m_generatorsByTestName; + }; + + namespace { + Context* currentContext = CATCH_NULL; + } + IMutableContext& getCurrentMutableContext() { + if( !currentContext ) + currentContext = new Context(); + return *currentContext; + } + IContext& getCurrentContext() { + return getCurrentMutableContext(); + } + + void cleanUpContext() { + delete currentContext; + currentContext = CATCH_NULL; + } +} + +// #included from: catch_console_colour_impl.hpp +#define TWOBLUECUBES_CATCH_CONSOLE_COLOUR_IMPL_HPP_INCLUDED + +namespace Catch { + namespace { + + struct IColourImpl { + virtual ~IColourImpl() {} + virtual void use( Colour::Code _colourCode ) = 0; + }; + + struct NoColourImpl : IColourImpl { + void use( Colour::Code ) {} + + static IColourImpl* instance() { + static NoColourImpl s_instance; + return &s_instance; + } + }; + + } // anon namespace +} // namespace Catch + +#if !defined( CATCH_CONFIG_COLOUR_NONE ) && !defined( CATCH_CONFIG_COLOUR_WINDOWS ) && !defined( CATCH_CONFIG_COLOUR_ANSI ) +# ifdef CATCH_PLATFORM_WINDOWS +# define CATCH_CONFIG_COLOUR_WINDOWS +# else +# define CATCH_CONFIG_COLOUR_ANSI +# endif +#endif + +#if defined ( CATCH_CONFIG_COLOUR_WINDOWS ) ///////////////////////////////////////// + +#ifndef NOMINMAX +#define NOMINMAX +#endif + +#ifdef __AFXDLL +#include <AfxWin.h> +#else +#include <windows.h> +#endif + +namespace Catch { +namespace { + + class Win32ColourImpl : public IColourImpl { + public: + Win32ColourImpl() : stdoutHandle( GetStdHandle(STD_OUTPUT_HANDLE) ) + { + CONSOLE_SCREEN_BUFFER_INFO csbiInfo; + GetConsoleScreenBufferInfo( stdoutHandle, &csbiInfo ); + originalForegroundAttributes = csbiInfo.wAttributes & ~( BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_BLUE | BACKGROUND_INTENSITY ); + originalBackgroundAttributes = csbiInfo.wAttributes & ~( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY ); + } + + virtual void use( Colour::Code _colourCode ) { + switch( _colourCode ) { + case Colour::None: return setTextAttribute( originalForegroundAttributes ); + case Colour::White: return setTextAttribute( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE ); + case Colour::Red: return setTextAttribute( FOREGROUND_RED ); + case Colour::Green: return setTextAttribute( FOREGROUND_GREEN ); + case Colour::Blue: return setTextAttribute( FOREGROUND_BLUE ); + case Colour::Cyan: return setTextAttribute( FOREGROUND_BLUE | FOREGROUND_GREEN ); + case Colour::Yellow: return setTextAttribute( FOREGROUND_RED | FOREGROUND_GREEN ); + case Colour::Grey: return setTextAttribute( 0 ); + + case Colour::LightGrey: return setTextAttribute( FOREGROUND_INTENSITY ); + case Colour::BrightRed: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_RED ); + case Colour::BrightGreen: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN ); + case Colour::BrightWhite: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE ); + + case Colour::Bright: throw std::logic_error( "not a colour" ); + } + } + + private: + void setTextAttribute( WORD _textAttribute ) { + SetConsoleTextAttribute( stdoutHandle, _textAttribute | originalBackgroundAttributes ); + } + HANDLE stdoutHandle; + WORD originalForegroundAttributes; + WORD originalBackgroundAttributes; + }; + + IColourImpl* platformColourInstance() { + static Win32ColourImpl s_instance; + + Ptr<IConfig const> config = getCurrentContext().getConfig(); + UseColour::YesOrNo colourMode = config + ? config->useColour() + : UseColour::Auto; + if( colourMode == UseColour::Auto ) + colourMode = !isDebuggerActive() + ? UseColour::Yes + : UseColour::No; + return colourMode == UseColour::Yes + ? &s_instance + : NoColourImpl::instance(); + } + +} // end anon namespace +} // end namespace Catch + +#elif defined( CATCH_CONFIG_COLOUR_ANSI ) ////////////////////////////////////// + +#include <unistd.h> + +namespace Catch { +namespace { + + // use POSIX/ ANSI console terminal codes + // Thanks to Adam Strzelecki for original contribution + // (http://github.com/nanoant) + // https://github.com/philsquared/Catch/pull/131 + class PosixColourImpl : public IColourImpl { + public: + virtual void use( Colour::Code _colourCode ) { + switch( _colourCode ) { + case Colour::None: + case Colour::White: return setColour( "[0m" ); + case Colour::Red: return setColour( "[0;31m" ); + case Colour::Green: return setColour( "[0;32m" ); + case Colour::Blue: return setColour( "[0:34m" ); + case Colour::Cyan: return setColour( "[0;36m" ); + case Colour::Yellow: return setColour( "[0;33m" ); + case Colour::Grey: return setColour( "[1;30m" ); + + case Colour::LightGrey: return setColour( "[0;37m" ); + case Colour::BrightRed: return setColour( "[1;31m" ); + case Colour::BrightGreen: return setColour( "[1;32m" ); + case Colour::BrightWhite: return setColour( "[1;37m" ); + + case Colour::Bright: throw std::logic_error( "not a colour" ); + } + } + static IColourImpl* instance() { + static PosixColourImpl s_instance; + return &s_instance; + } + + private: + void setColour( const char* _escapeCode ) { + Catch::cout() << '\033' << _escapeCode; + } + }; + + IColourImpl* platformColourInstance() { + Ptr<IConfig const> config = getCurrentContext().getConfig(); + UseColour::YesOrNo colourMode = config + ? config->useColour() + : UseColour::Auto; + if( colourMode == UseColour::Auto ) + colourMode = (!isDebuggerActive() && isatty(STDOUT_FILENO) ) + ? UseColour::Yes + : UseColour::No; + return colourMode == UseColour::Yes + ? PosixColourImpl::instance() + : NoColourImpl::instance(); + } + +} // end anon namespace +} // end namespace Catch + +#else // not Windows or ANSI /////////////////////////////////////////////// + +namespace Catch { + + static IColourImpl* platformColourInstance() { return NoColourImpl::instance(); } + +} // end namespace Catch + +#endif // Windows/ ANSI/ None + +namespace Catch { + + Colour::Colour( Code _colourCode ) : m_moved( false ) { use( _colourCode ); } + Colour::Colour( Colour const& _other ) : m_moved( false ) { const_cast<Colour&>( _other ).m_moved = true; } + Colour::~Colour(){ if( !m_moved ) use( None ); } + + void Colour::use( Code _colourCode ) { + static IColourImpl* impl = platformColourInstance(); + impl->use( _colourCode ); + } + +} // end namespace Catch + +// #included from: catch_generators_impl.hpp +#define TWOBLUECUBES_CATCH_GENERATORS_IMPL_HPP_INCLUDED + +#include <vector> +#include <string> +#include <map> + +namespace Catch { + + struct GeneratorInfo : IGeneratorInfo { + + GeneratorInfo( std::size_t size ) + : m_size( size ), + m_currentIndex( 0 ) + {} + + bool moveNext() { + if( ++m_currentIndex == m_size ) { + m_currentIndex = 0; + return false; + } + return true; + } + + std::size_t getCurrentIndex() const { + return m_currentIndex; + } + + std::size_t m_size; + std::size_t m_currentIndex; + }; + + /////////////////////////////////////////////////////////////////////////// + + class GeneratorsForTest : public IGeneratorsForTest { + + public: + ~GeneratorsForTest() { + deleteAll( m_generatorsInOrder ); + } + + IGeneratorInfo& getGeneratorInfo( std::string const& fileInfo, std::size_t size ) { + std::map<std::string, IGeneratorInfo*>::const_iterator it = m_generatorsByName.find( fileInfo ); + if( it == m_generatorsByName.end() ) { + IGeneratorInfo* info = new GeneratorInfo( size ); + m_generatorsByName.insert( std::make_pair( fileInfo, info ) ); + m_generatorsInOrder.push_back( info ); + return *info; + } + return *it->second; + } + + bool moveNext() { + std::vector<IGeneratorInfo*>::const_iterator it = m_generatorsInOrder.begin(); + std::vector<IGeneratorInfo*>::const_iterator itEnd = m_generatorsInOrder.end(); + for(; it != itEnd; ++it ) { + if( (*it)->moveNext() ) + return true; + } + return false; + } + + private: + std::map<std::string, IGeneratorInfo*> m_generatorsByName; + std::vector<IGeneratorInfo*> m_generatorsInOrder; + }; + + IGeneratorsForTest* createGeneratorsForTest() + { + return new GeneratorsForTest(); + } + +} // end namespace Catch + +// #included from: catch_assertionresult.hpp +#define TWOBLUECUBES_CATCH_ASSERTIONRESULT_HPP_INCLUDED + +namespace Catch { + + AssertionInfo::AssertionInfo( std::string const& _macroName, + SourceLineInfo const& _lineInfo, + std::string const& _capturedExpression, + ResultDisposition::Flags _resultDisposition ) + : macroName( _macroName ), + lineInfo( _lineInfo ), + capturedExpression( _capturedExpression ), + resultDisposition( _resultDisposition ) + {} + + AssertionResult::AssertionResult() {} + + AssertionResult::AssertionResult( AssertionInfo const& info, AssertionResultData const& data ) + : m_info( info ), + m_resultData( data ) + {} + + AssertionResult::~AssertionResult() {} + + // Result was a success + bool AssertionResult::succeeded() const { + return Catch::isOk( m_resultData.resultType ); + } + + // Result was a success, or failure is suppressed + bool AssertionResult::isOk() const { + return Catch::isOk( m_resultData.resultType ) || shouldSuppressFailure( m_info.resultDisposition ); + } + + ResultWas::OfType AssertionResult::getResultType() const { + return m_resultData.resultType; + } + + bool AssertionResult::hasExpression() const { + return !m_info.capturedExpression.empty(); + } + + bool AssertionResult::hasMessage() const { + return !m_resultData.message.empty(); + } + + std::string AssertionResult::getExpression() const { + if( isFalseTest( m_info.resultDisposition ) ) + return "!" + m_info.capturedExpression; + else + return m_info.capturedExpression; + } + std::string AssertionResult::getExpressionInMacro() const { + if( m_info.macroName.empty() ) + return m_info.capturedExpression; + else + return m_info.macroName + "( " + m_info.capturedExpression + " )"; + } + + bool AssertionResult::hasExpandedExpression() const { + return hasExpression() && getExpandedExpression() != getExpression(); + } + + std::string AssertionResult::getExpandedExpression() const { + return m_resultData.reconstructedExpression; + } + + std::string AssertionResult::getMessage() const { + return m_resultData.message; + } + SourceLineInfo AssertionResult::getSourceInfo() const { + return m_info.lineInfo; + } + + std::string AssertionResult::getTestMacroName() const { + return m_info.macroName; + } + +} // end namespace Catch + +// #included from: catch_test_case_info.hpp +#define TWOBLUECUBES_CATCH_TEST_CASE_INFO_HPP_INCLUDED + +namespace Catch { + + inline TestCaseInfo::SpecialProperties parseSpecialTag( std::string const& tag ) { + if( startsWith( tag, "." ) || + tag == "hide" || + tag == "!hide" ) + return TestCaseInfo::IsHidden; + else if( tag == "!throws" ) + return TestCaseInfo::Throws; + else if( tag == "!shouldfail" ) + return TestCaseInfo::ShouldFail; + else if( tag == "!mayfail" ) + return TestCaseInfo::MayFail; + else + return TestCaseInfo::None; + } + inline bool isReservedTag( std::string const& tag ) { + return parseSpecialTag( tag ) == TestCaseInfo::None && tag.size() > 0 && !isalnum( tag[0] ); + } + inline void enforceNotReservedTag( std::string const& tag, SourceLineInfo const& _lineInfo ) { + if( isReservedTag( tag ) ) { + { + Colour colourGuard( Colour::Red ); + Catch::cerr() + << "Tag name [" << tag << "] not allowed.\n" + << "Tag names starting with non alpha-numeric characters are reserved\n"; + } + { + Colour colourGuard( Colour::FileName ); + Catch::cerr() << _lineInfo << std::endl; + } + exit(1); + } + } + + TestCase makeTestCase( ITestCase* _testCase, + std::string const& _className, + std::string const& _name, + std::string const& _descOrTags, + SourceLineInfo const& _lineInfo ) + { + bool isHidden( startsWith( _name, "./" ) ); // Legacy support + + // Parse out tags + std::set<std::string> tags; + std::string desc, tag; + bool inTag = false; + for( std::size_t i = 0; i < _descOrTags.size(); ++i ) { + char c = _descOrTags[i]; + if( !inTag ) { + if( c == '[' ) + inTag = true; + else + desc += c; + } + else { + if( c == ']' ) { + TestCaseInfo::SpecialProperties prop = parseSpecialTag( tag ); + if( prop == TestCaseInfo::IsHidden ) + isHidden = true; + else if( prop == TestCaseInfo::None ) + enforceNotReservedTag( tag, _lineInfo ); + + tags.insert( tag ); + tag.clear(); + inTag = false; + } + else + tag += c; + } + } + if( isHidden ) { + tags.insert( "hide" ); + tags.insert( "." ); + } + + TestCaseInfo info( _name, _className, desc, tags, _lineInfo ); + return TestCase( _testCase, info ); + } + + void setTags( TestCaseInfo& testCaseInfo, std::set<std::string> const& tags ) + { + testCaseInfo.tags = tags; + testCaseInfo.lcaseTags.clear(); + + std::ostringstream oss; + for( std::set<std::string>::const_iterator it = tags.begin(), itEnd = tags.end(); it != itEnd; ++it ) { + oss << "[" << *it << "]"; + std::string lcaseTag = toLower( *it ); + testCaseInfo.properties = static_cast<TestCaseInfo::SpecialProperties>( testCaseInfo.properties | parseSpecialTag( lcaseTag ) ); + testCaseInfo.lcaseTags.insert( lcaseTag ); + } + testCaseInfo.tagsAsString = oss.str(); + } + + TestCaseInfo::TestCaseInfo( std::string const& _name, + std::string const& _className, + std::string const& _description, + std::set<std::string> const& _tags, + SourceLineInfo const& _lineInfo ) + : name( _name ), + className( _className ), + description( _description ), + lineInfo( _lineInfo ), + properties( None ) + { + setTags( *this, _tags ); + } + + TestCaseInfo::TestCaseInfo( TestCaseInfo const& other ) + : name( other.name ), + className( other.className ), + description( other.description ), + tags( other.tags ), + lcaseTags( other.lcaseTags ), + tagsAsString( other.tagsAsString ), + lineInfo( other.lineInfo ), + properties( other.properties ) + {} + + bool TestCaseInfo::isHidden() const { + return ( properties & IsHidden ) != 0; + } + bool TestCaseInfo::throws() const { + return ( properties & Throws ) != 0; + } + bool TestCaseInfo::okToFail() const { + return ( properties & (ShouldFail | MayFail ) ) != 0; + } + bool TestCaseInfo::expectedToFail() const { + return ( properties & (ShouldFail ) ) != 0; + } + + TestCase::TestCase( ITestCase* testCase, TestCaseInfo const& info ) : TestCaseInfo( info ), test( testCase ) {} + + TestCase::TestCase( TestCase const& other ) + : TestCaseInfo( other ), + test( other.test ) + {} + + TestCase TestCase::withName( std::string const& _newName ) const { + TestCase other( *this ); + other.name = _newName; + return other; + } + + void TestCase::swap( TestCase& other ) { + test.swap( other.test ); + name.swap( other.name ); + className.swap( other.className ); + description.swap( other.description ); + tags.swap( other.tags ); + lcaseTags.swap( other.lcaseTags ); + tagsAsString.swap( other.tagsAsString ); + std::swap( TestCaseInfo::properties, static_cast<TestCaseInfo&>( other ).properties ); + std::swap( lineInfo, other.lineInfo ); + } + + void TestCase::invoke() const { + test->invoke(); + } + + bool TestCase::operator == ( TestCase const& other ) const { + return test.get() == other.test.get() && + name == other.name && + className == other.className; + } + + bool TestCase::operator < ( TestCase const& other ) const { + return name < other.name; + } + TestCase& TestCase::operator = ( TestCase const& other ) { + TestCase temp( other ); + swap( temp ); + return *this; + } + + TestCaseInfo const& TestCase::getTestCaseInfo() const + { + return *this; + } + +} // end namespace Catch + +// #included from: catch_version.hpp +#define TWOBLUECUBES_CATCH_VERSION_HPP_INCLUDED + +namespace Catch { + + Version::Version + ( unsigned int _majorVersion, + unsigned int _minorVersion, + unsigned int _patchNumber, + std::string const& _branchName, + unsigned int _buildNumber ) + : majorVersion( _majorVersion ), + minorVersion( _minorVersion ), + patchNumber( _patchNumber ), + branchName( _branchName ), + buildNumber( _buildNumber ) + {} + + std::ostream& operator << ( std::ostream& os, Version const& version ) { + os << version.majorVersion << "." + << version.minorVersion << "." + << version.patchNumber; + + if( !version.branchName.empty() ) { + os << "-" << version.branchName + << "." << version.buildNumber; + } + return os; + } + + Version libraryVersion( 1, 3, 5, "", 0 ); + +} + +// #included from: catch_message.hpp +#define TWOBLUECUBES_CATCH_MESSAGE_HPP_INCLUDED + +namespace Catch { + + MessageInfo::MessageInfo( std::string const& _macroName, + SourceLineInfo const& _lineInfo, + ResultWas::OfType _type ) + : macroName( _macroName ), + lineInfo( _lineInfo ), + type( _type ), + sequence( ++globalCount ) + {} + + // This may need protecting if threading support is added + unsigned int MessageInfo::globalCount = 0; + + //////////////////////////////////////////////////////////////////////////// + + ScopedMessage::ScopedMessage( MessageBuilder const& builder ) + : m_info( builder.m_info ) + { + m_info.message = builder.m_stream.str(); + getResultCapture().pushScopedMessage( m_info ); + } + ScopedMessage::ScopedMessage( ScopedMessage const& other ) + : m_info( other.m_info ) + {} + + ScopedMessage::~ScopedMessage() { + getResultCapture().popScopedMessage( m_info ); + } + +} // end namespace Catch + +// #included from: catch_legacy_reporter_adapter.hpp +#define TWOBLUECUBES_CATCH_LEGACY_REPORTER_ADAPTER_HPP_INCLUDED + +// #included from: catch_legacy_reporter_adapter.h +#define TWOBLUECUBES_CATCH_LEGACY_REPORTER_ADAPTER_H_INCLUDED + +namespace Catch +{ + // Deprecated + struct IReporter : IShared { + virtual ~IReporter(); + + virtual bool shouldRedirectStdout() const = 0; + + virtual void StartTesting() = 0; + virtual void EndTesting( Totals const& totals ) = 0; + virtual void StartGroup( std::string const& groupName ) = 0; + virtual void EndGroup( std::string const& groupName, Totals const& totals ) = 0; + virtual void StartTestCase( TestCaseInfo const& testInfo ) = 0; + virtual void EndTestCase( TestCaseInfo const& testInfo, Totals const& totals, std::string const& stdOut, std::string const& stdErr ) = 0; + virtual void StartSection( std::string const& sectionName, std::string const& description ) = 0; + virtual void EndSection( std::string const& sectionName, Counts const& assertions ) = 0; + virtual void NoAssertionsInSection( std::string const& sectionName ) = 0; + virtual void NoAssertionsInTestCase( std::string const& testName ) = 0; + virtual void Aborted() = 0; + virtual void Result( AssertionResult const& result ) = 0; + }; + + class LegacyReporterAdapter : public SharedImpl<IStreamingReporter> + { + public: + LegacyReporterAdapter( Ptr<IReporter> const& legacyReporter ); + virtual ~LegacyReporterAdapter(); + + virtual ReporterPreferences getPreferences() const; + virtual void noMatchingTestCases( std::string const& ); + virtual void testRunStarting( TestRunInfo const& ); + virtual void testGroupStarting( GroupInfo const& groupInfo ); + virtual void testCaseStarting( TestCaseInfo const& testInfo ); + virtual void sectionStarting( SectionInfo const& sectionInfo ); + virtual void assertionStarting( AssertionInfo const& ); + virtual bool assertionEnded( AssertionStats const& assertionStats ); + virtual void sectionEnded( SectionStats const& sectionStats ); + virtual void testCaseEnded( TestCaseStats const& testCaseStats ); + virtual void testGroupEnded( TestGroupStats const& testGroupStats ); + virtual void testRunEnded( TestRunStats const& testRunStats ); + virtual void skipTest( TestCaseInfo const& ); + + private: + Ptr<IReporter> m_legacyReporter; + }; +} + +namespace Catch +{ + LegacyReporterAdapter::LegacyReporterAdapter( Ptr<IReporter> const& legacyReporter ) + : m_legacyReporter( legacyReporter ) + {} + LegacyReporterAdapter::~LegacyReporterAdapter() {} + + ReporterPreferences LegacyReporterAdapter::getPreferences() const { + ReporterPreferences prefs; + prefs.shouldRedirectStdOut = m_legacyReporter->shouldRedirectStdout(); + return prefs; + } + + void LegacyReporterAdapter::noMatchingTestCases( std::string const& ) {} + void LegacyReporterAdapter::testRunStarting( TestRunInfo const& ) { + m_legacyReporter->StartTesting(); + } + void LegacyReporterAdapter::testGroupStarting( GroupInfo const& groupInfo ) { + m_legacyReporter->StartGroup( groupInfo.name ); + } + void LegacyReporterAdapter::testCaseStarting( TestCaseInfo const& testInfo ) { + m_legacyReporter->StartTestCase( testInfo ); + } + void LegacyReporterAdapter::sectionStarting( SectionInfo const& sectionInfo ) { + m_legacyReporter->StartSection( sectionInfo.name, sectionInfo.description ); + } + void LegacyReporterAdapter::assertionStarting( AssertionInfo const& ) { + // Not on legacy interface + } + + bool LegacyReporterAdapter::assertionEnded( AssertionStats const& assertionStats ) { + if( assertionStats.assertionResult.getResultType() != ResultWas::Ok ) { + for( std::vector<MessageInfo>::const_iterator it = assertionStats.infoMessages.begin(), itEnd = assertionStats.infoMessages.end(); + it != itEnd; + ++it ) { + if( it->type == ResultWas::Info ) { + ResultBuilder rb( it->macroName.c_str(), it->lineInfo, "", ResultDisposition::Normal ); + rb << it->message; + rb.setResultType( ResultWas::Info ); + AssertionResult result = rb.build(); + m_legacyReporter->Result( result ); + } + } + } + m_legacyReporter->Result( assertionStats.assertionResult ); + return true; + } + void LegacyReporterAdapter::sectionEnded( SectionStats const& sectionStats ) { + if( sectionStats.missingAssertions ) + m_legacyReporter->NoAssertionsInSection( sectionStats.sectionInfo.name ); + m_legacyReporter->EndSection( sectionStats.sectionInfo.name, sectionStats.assertions ); + } + void LegacyReporterAdapter::testCaseEnded( TestCaseStats const& testCaseStats ) { + m_legacyReporter->EndTestCase + ( testCaseStats.testInfo, + testCaseStats.totals, + testCaseStats.stdOut, + testCaseStats.stdErr ); + } + void LegacyReporterAdapter::testGroupEnded( TestGroupStats const& testGroupStats ) { + if( testGroupStats.aborting ) + m_legacyReporter->Aborted(); + m_legacyReporter->EndGroup( testGroupStats.groupInfo.name, testGroupStats.totals ); + } + void LegacyReporterAdapter::testRunEnded( TestRunStats const& testRunStats ) { + m_legacyReporter->EndTesting( testRunStats.totals ); + } + void LegacyReporterAdapter::skipTest( TestCaseInfo const& ) { + } +} + +// #included from: catch_timer.hpp + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wc++11-long-long" +#endif + +#ifdef CATCH_PLATFORM_WINDOWS +#include <windows.h> +#else +#include <sys/time.h> +#endif + +namespace Catch { + + namespace { +#ifdef CATCH_PLATFORM_WINDOWS + uint64_t getCurrentTicks() { + static uint64_t hz=0, hzo=0; + if (!hz) { + QueryPerformanceFrequency( reinterpret_cast<LARGE_INTEGER*>( &hz ) ); + QueryPerformanceCounter( reinterpret_cast<LARGE_INTEGER*>( &hzo ) ); + } + uint64_t t; + QueryPerformanceCounter( reinterpret_cast<LARGE_INTEGER*>( &t ) ); + return ((t-hzo)*1000000)/hz; + } +#else + uint64_t getCurrentTicks() { + timeval t; + gettimeofday(&t,CATCH_NULL); + return static_cast<uint64_t>( t.tv_sec ) * 1000000ull + static_cast<uint64_t>( t.tv_usec ); + } +#endif + } + + void Timer::start() { + m_ticks = getCurrentTicks(); + } + unsigned int Timer::getElapsedMicroseconds() const { + return static_cast<unsigned int>(getCurrentTicks() - m_ticks); + } + unsigned int Timer::getElapsedMilliseconds() const { + return static_cast<unsigned int>(getElapsedMicroseconds()/1000); + } + double Timer::getElapsedSeconds() const { + return getElapsedMicroseconds()/1000000.0; + } + +} // namespace Catch + +#ifdef __clang__ +#pragma clang diagnostic pop +#endif +// #included from: catch_common.hpp +#define TWOBLUECUBES_CATCH_COMMON_HPP_INCLUDED + +namespace Catch { + + bool startsWith( std::string const& s, std::string const& prefix ) { + return s.size() >= prefix.size() && s.substr( 0, prefix.size() ) == prefix; + } + bool endsWith( std::string const& s, std::string const& suffix ) { + return s.size() >= suffix.size() && s.substr( s.size()-suffix.size(), suffix.size() ) == suffix; + } + bool contains( std::string const& s, std::string const& infix ) { + return s.find( infix ) != std::string::npos; + } + void toLowerInPlace( std::string& s ) { + std::transform( s.begin(), s.end(), s.begin(), ::tolower ); + } + std::string toLower( std::string const& s ) { + std::string lc = s; + toLowerInPlace( lc ); + return lc; + } + std::string trim( std::string const& str ) { + static char const* whitespaceChars = "\n\r\t "; + std::string::size_type start = str.find_first_not_of( whitespaceChars ); + std::string::size_type end = str.find_last_not_of( whitespaceChars ); + + return start != std::string::npos ? str.substr( start, 1+end-start ) : ""; + } + + bool replaceInPlace( std::string& str, std::string const& replaceThis, std::string const& withThis ) { + bool replaced = false; + std::size_t i = str.find( replaceThis ); + while( i != std::string::npos ) { + replaced = true; + str = str.substr( 0, i ) + withThis + str.substr( i+replaceThis.size() ); + if( i < str.size()-withThis.size() ) + i = str.find( replaceThis, i+withThis.size() ); + else + i = std::string::npos; + } + return replaced; + } + + pluralise::pluralise( std::size_t count, std::string const& label ) + : m_count( count ), + m_label( label ) + {} + + std::ostream& operator << ( std::ostream& os, pluralise const& pluraliser ) { + os << pluraliser.m_count << " " << pluraliser.m_label; + if( pluraliser.m_count != 1 ) + os << "s"; + return os; + } + + SourceLineInfo::SourceLineInfo() : line( 0 ){} + SourceLineInfo::SourceLineInfo( char const* _file, std::size_t _line ) + : file( _file ), + line( _line ) + {} + SourceLineInfo::SourceLineInfo( SourceLineInfo const& other ) + : file( other.file ), + line( other.line ) + {} + bool SourceLineInfo::empty() const { + return file.empty(); + } + bool SourceLineInfo::operator == ( SourceLineInfo const& other ) const { + return line == other.line && file == other.file; + } + bool SourceLineInfo::operator < ( SourceLineInfo const& other ) const { + return line < other.line || ( line == other.line && file < other.file ); + } + + void seedRng( IConfig const& config ) { + if( config.rngSeed() != 0 ) + std::srand( config.rngSeed() ); + } + unsigned int rngSeed() { + return getCurrentContext().getConfig()->rngSeed(); + } + + std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info ) { +#ifndef __GNUG__ + os << info.file << "(" << info.line << ")"; +#else + os << info.file << ":" << info.line; +#endif + return os; + } + + void throwLogicError( std::string const& message, SourceLineInfo const& locationInfo ) { + std::ostringstream oss; + oss << locationInfo << ": Internal Catch error: '" << message << "'"; + if( alwaysTrue() ) + throw std::logic_error( oss.str() ); + } +} + +// #included from: catch_section.hpp +#define TWOBLUECUBES_CATCH_SECTION_HPP_INCLUDED + +namespace Catch { + + SectionInfo::SectionInfo + ( SourceLineInfo const& _lineInfo, + std::string const& _name, + std::string const& _description ) + : name( _name ), + description( _description ), + lineInfo( _lineInfo ) + {} + + Section::Section( SectionInfo const& info ) + : m_info( info ), + m_sectionIncluded( getResultCapture().sectionStarted( m_info, m_assertions ) ) + { + m_timer.start(); + } + + Section::~Section() { + if( m_sectionIncluded ) { + SectionEndInfo endInfo( m_info, m_assertions, m_timer.getElapsedSeconds() ); + if( std::uncaught_exception() ) + getResultCapture().sectionEndedEarly( endInfo ); + else + getResultCapture().sectionEnded( endInfo ); + } + } + + // This indicates whether the section should be executed or not + Section::operator bool() const { + return m_sectionIncluded; + } + +} // end namespace Catch + +// #included from: catch_debugger.hpp +#define TWOBLUECUBES_CATCH_DEBUGGER_HPP_INCLUDED + +#include <iostream> + +#ifdef CATCH_PLATFORM_MAC + + #include <assert.h> + #include <stdbool.h> + #include <sys/types.h> + #include <unistd.h> + #include <sys/sysctl.h> + + namespace Catch{ + + // The following function is taken directly from the following technical note: + // http://developer.apple.com/library/mac/#qa/qa2004/qa1361.html + + // Returns true if the current process is being debugged (either + // running under the debugger or has a debugger attached post facto). + bool isDebuggerActive(){ + + int mib[4]; + struct kinfo_proc info; + size_t size; + + // Initialize the flags so that, if sysctl fails for some bizarre + // reason, we get a predictable result. + + info.kp_proc.p_flag = 0; + + // Initialize mib, which tells sysctl the info we want, in this case + // we're looking for information about a specific process ID. + + mib[0] = CTL_KERN; + mib[1] = KERN_PROC; + mib[2] = KERN_PROC_PID; + mib[3] = getpid(); + + // Call sysctl. + + size = sizeof(info); + if( sysctl(mib, sizeof(mib) / sizeof(*mib), &info, &size, CATCH_NULL, 0) != 0 ) { + Catch::cerr() << "\n** Call to sysctl failed - unable to determine if debugger is active **\n" << std::endl; + return false; + } + + // We're being debugged if the P_TRACED flag is set. + + return ( (info.kp_proc.p_flag & P_TRACED) != 0 ); + } + } // namespace Catch + +#elif defined(_MSC_VER) + extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent(); + namespace Catch { + bool isDebuggerActive() { + return IsDebuggerPresent() != 0; + } + } +#elif defined(__MINGW32__) + extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent(); + namespace Catch { + bool isDebuggerActive() { + return IsDebuggerPresent() != 0; + } + } +#else + namespace Catch { + inline bool isDebuggerActive() { return false; } + } +#endif // Platform + +#ifdef CATCH_PLATFORM_WINDOWS + extern "C" __declspec(dllimport) void __stdcall OutputDebugStringA( const char* ); + namespace Catch { + void writeToDebugConsole( std::string const& text ) { + ::OutputDebugStringA( text.c_str() ); + } + } +#else + namespace Catch { + void writeToDebugConsole( std::string const& text ) { + // !TBD: Need a version for Mac/ XCode and other IDEs + Catch::cout() << text; + } + } +#endif // Platform + +// #included from: catch_tostring.hpp +#define TWOBLUECUBES_CATCH_TOSTRING_HPP_INCLUDED + +namespace Catch { + +namespace Detail { + + const std::string unprintableString = "{?}"; + + namespace { + const int hexThreshold = 255; + + struct Endianness { + enum Arch { Big, Little }; + + static Arch which() { + union _{ + int asInt; + char asChar[sizeof (int)]; + } u; + + u.asInt = 1; + return ( u.asChar[sizeof(int)-1] == 1 ) ? Big : Little; + } + }; + } + + std::string rawMemoryToString( const void *object, std::size_t size ) + { + // Reverse order for little endian architectures + int i = 0, end = static_cast<int>( size ), inc = 1; + if( Endianness::which() == Endianness::Little ) { + i = end-1; + end = inc = -1; + } + + unsigned char const *bytes = static_cast<unsigned char const *>(object); + std::ostringstream os; + os << "0x" << std::setfill('0') << std::hex; + for( ; i != end; i += inc ) + os << std::setw(2) << static_cast<unsigned>(bytes[i]); + return os.str(); + } +} + +std::string toString( std::string const& value ) { + std::string s = value; + if( getCurrentContext().getConfig()->showInvisibles() ) { + for(size_t i = 0; i < s.size(); ++i ) { + std::string subs; + switch( s[i] ) { + case '\n': subs = "\\n"; break; + case '\t': subs = "\\t"; break; + default: break; + } + if( !subs.empty() ) { + s = s.substr( 0, i ) + subs + s.substr( i+1 ); + ++i; + } + } + } + return "\"" + s + "\""; +} +std::string toString( std::wstring const& value ) { + + std::string s; + s.reserve( value.size() ); + for(size_t i = 0; i < value.size(); ++i ) + s += value[i] <= 0xff ? static_cast<char>( value[i] ) : '?'; + return Catch::toString( s ); +} + +std::string toString( const char* const value ) { + return value ? Catch::toString( std::string( value ) ) : std::string( "{null string}" ); +} + +std::string toString( char* const value ) { + return Catch::toString( static_cast<const char*>( value ) ); +} + +std::string toString( const wchar_t* const value ) +{ + return value ? Catch::toString( std::wstring(value) ) : std::string( "{null string}" ); +} + +std::string toString( wchar_t* const value ) +{ + return Catch::toString( static_cast<const wchar_t*>( value ) ); +} + +std::string toString( int value ) { + std::ostringstream oss; + oss << value; + if( value > Detail::hexThreshold ) + oss << " (0x" << std::hex << value << ")"; + return oss.str(); +} + +std::string toString( unsigned long value ) { + std::ostringstream oss; + oss << value; + if( value > Detail::hexThreshold ) + oss << " (0x" << std::hex << value << ")"; + return oss.str(); +} + +std::string toString( unsigned int value ) { + return Catch::toString( static_cast<unsigned long>( value ) ); +} + +template<typename T> +std::string fpToString( T value, int precision ) { + std::ostringstream oss; + oss << std::setprecision( precision ) + << std::fixed + << value; + std::string d = oss.str(); + std::size_t i = d.find_last_not_of( '0' ); + if( i != std::string::npos && i != d.size()-1 ) { + if( d[i] == '.' ) + i++; + d = d.substr( 0, i+1 ); + } + return d; +} + +std::string toString( const double value ) { + return fpToString( value, 10 ); +} +std::string toString( const float value ) { + return fpToString( value, 5 ) + "f"; +} + +std::string toString( bool value ) { + return value ? "true" : "false"; +} + +std::string toString( char value ) { + return value < ' ' + ? toString( static_cast<unsigned int>( value ) ) + : Detail::makeString( value ); +} + +std::string toString( signed char value ) { + return toString( static_cast<char>( value ) ); +} + +std::string toString( unsigned char value ) { + return toString( static_cast<char>( value ) ); +} + +#ifdef CATCH_CONFIG_CPP11_LONG_LONG +std::string toString( long long value ) { + std::ostringstream oss; + oss << value; + if( value > Detail::hexThreshold ) + oss << " (0x" << std::hex << value << ")"; + return oss.str(); +} +std::string toString( unsigned long long value ) { + std::ostringstream oss; + oss << value; + if( value > Detail::hexThreshold ) + oss << " (0x" << std::hex << value << ")"; + return oss.str(); +} +#endif + +#ifdef CATCH_CONFIG_CPP11_NULLPTR +std::string toString( std::nullptr_t ) { + return "nullptr"; +} +#endif + +#ifdef __OBJC__ + std::string toString( NSString const * const& nsstring ) { + if( !nsstring ) + return "nil"; + return "@" + toString([nsstring UTF8String]); + } + std::string toString( NSString * CATCH_ARC_STRONG const& nsstring ) { + if( !nsstring ) + return "nil"; + return "@" + toString([nsstring UTF8String]); + } + std::string toString( NSObject* const& nsObject ) { + return toString( [nsObject description] ); + } +#endif + +} // end namespace Catch + +// #included from: catch_result_builder.hpp +#define TWOBLUECUBES_CATCH_RESULT_BUILDER_HPP_INCLUDED + +namespace Catch { + + std::string capturedExpressionWithSecondArgument( std::string const& capturedExpression, std::string const& secondArg ) { + return secondArg.empty() || secondArg == "\"\"" + ? capturedExpression + : capturedExpression + ", " + secondArg; + } + ResultBuilder::ResultBuilder( char const* macroName, + SourceLineInfo const& lineInfo, + char const* capturedExpression, + ResultDisposition::Flags resultDisposition, + char const* secondArg ) + : m_assertionInfo( macroName, lineInfo, capturedExpressionWithSecondArgument( capturedExpression, secondArg ), resultDisposition ), + m_shouldDebugBreak( false ), + m_shouldThrow( false ) + {} + + ResultBuilder& ResultBuilder::setResultType( ResultWas::OfType result ) { + m_data.resultType = result; + return *this; + } + ResultBuilder& ResultBuilder::setResultType( bool result ) { + m_data.resultType = result ? ResultWas::Ok : ResultWas::ExpressionFailed; + return *this; + } + ResultBuilder& ResultBuilder::setLhs( std::string const& lhs ) { + m_exprComponents.lhs = lhs; + return *this; + } + ResultBuilder& ResultBuilder::setRhs( std::string const& rhs ) { + m_exprComponents.rhs = rhs; + return *this; + } + ResultBuilder& ResultBuilder::setOp( std::string const& op ) { + m_exprComponents.op = op; + return *this; + } + + void ResultBuilder::endExpression() { + m_exprComponents.testFalse = isFalseTest( m_assertionInfo.resultDisposition ); + captureExpression(); + } + + void ResultBuilder::useActiveException( ResultDisposition::Flags resultDisposition ) { + m_assertionInfo.resultDisposition = resultDisposition; + m_stream.oss << Catch::translateActiveException(); + captureResult( ResultWas::ThrewException ); + } + + void ResultBuilder::captureResult( ResultWas::OfType resultType ) { + setResultType( resultType ); + captureExpression(); + } + void ResultBuilder::captureExpectedException( std::string const& expectedMessage ) { + if( expectedMessage.empty() ) + captureExpectedException( Matchers::Impl::Generic::AllOf<std::string>() ); + else + captureExpectedException( Matchers::Equals( expectedMessage ) ); + } + + void ResultBuilder::captureExpectedException( Matchers::Impl::Matcher<std::string> const& matcher ) { + + assert( m_exprComponents.testFalse == false ); + AssertionResultData data = m_data; + data.resultType = ResultWas::Ok; + data.reconstructedExpression = m_assertionInfo.capturedExpression; + + std::string actualMessage = Catch::translateActiveException(); + if( !matcher.match( actualMessage ) ) { + data.resultType = ResultWas::ExpressionFailed; + data.reconstructedExpression = actualMessage; + } + AssertionResult result( m_assertionInfo, data ); + handleResult( result ); + } + + void ResultBuilder::captureExpression() { + AssertionResult result = build(); + handleResult( result ); + } + void ResultBuilder::handleResult( AssertionResult const& result ) + { + getResultCapture().assertionEnded( result ); + + if( !result.isOk() ) { + if( getCurrentContext().getConfig()->shouldDebugBreak() ) + m_shouldDebugBreak = true; + if( getCurrentContext().getRunner()->aborting() || (m_assertionInfo.resultDisposition & ResultDisposition::Normal) ) + m_shouldThrow = true; + } + } + void ResultBuilder::react() { + if( m_shouldThrow ) + throw Catch::TestFailureException(); + } + + bool ResultBuilder::shouldDebugBreak() const { return m_shouldDebugBreak; } + bool ResultBuilder::allowThrows() const { return getCurrentContext().getConfig()->allowThrows(); } + + AssertionResult ResultBuilder::build() const + { + assert( m_data.resultType != ResultWas::Unknown ); + + AssertionResultData data = m_data; + + // Flip bool results if testFalse is set + if( m_exprComponents.testFalse ) { + if( data.resultType == ResultWas::Ok ) + data.resultType = ResultWas::ExpressionFailed; + else if( data.resultType == ResultWas::ExpressionFailed ) + data.resultType = ResultWas::Ok; + } + + data.message = m_stream.oss.str(); + data.reconstructedExpression = reconstructExpression(); + if( m_exprComponents.testFalse ) { + if( m_exprComponents.op == "" ) + data.reconstructedExpression = "!" + data.reconstructedExpression; + else + data.reconstructedExpression = "!(" + data.reconstructedExpression + ")"; + } + return AssertionResult( m_assertionInfo, data ); + } + std::string ResultBuilder::reconstructExpression() const { + if( m_exprComponents.op == "" ) + return m_exprComponents.lhs.empty() ? m_assertionInfo.capturedExpression : m_exprComponents.op + m_exprComponents.lhs; + else if( m_exprComponents.op == "matches" ) + return m_exprComponents.lhs + " " + m_exprComponents.rhs; + else if( m_exprComponents.op != "!" ) { + if( m_exprComponents.lhs.size() + m_exprComponents.rhs.size() < 40 && + m_exprComponents.lhs.find("\n") == std::string::npos && + m_exprComponents.rhs.find("\n") == std::string::npos ) + return m_exprComponents.lhs + " " + m_exprComponents.op + " " + m_exprComponents.rhs; + else + return m_exprComponents.lhs + "\n" + m_exprComponents.op + "\n" + m_exprComponents.rhs; + } + else + return "{can't expand - use " + m_assertionInfo.macroName + "_FALSE( " + m_assertionInfo.capturedExpression.substr(1) + " ) instead of " + m_assertionInfo.macroName + "( " + m_assertionInfo.capturedExpression + " ) for better diagnostics}"; + } + +} // end namespace Catch + +// #included from: catch_tag_alias_registry.hpp +#define TWOBLUECUBES_CATCH_TAG_ALIAS_REGISTRY_HPP_INCLUDED + +// #included from: catch_tag_alias_registry.h +#define TWOBLUECUBES_CATCH_TAG_ALIAS_REGISTRY_H_INCLUDED + +#include <map> + +namespace Catch { + + class TagAliasRegistry : public ITagAliasRegistry { + public: + virtual ~TagAliasRegistry(); + virtual Option<TagAlias> find( std::string const& alias ) const; + virtual std::string expandAliases( std::string const& unexpandedTestSpec ) const; + void add( char const* alias, char const* tag, SourceLineInfo const& lineInfo ); + static TagAliasRegistry& get(); + + private: + std::map<std::string, TagAlias> m_registry; + }; + +} // end namespace Catch + +#include <map> +#include <iostream> + +namespace Catch { + + TagAliasRegistry::~TagAliasRegistry() {} + + Option<TagAlias> TagAliasRegistry::find( std::string const& alias ) const { + std::map<std::string, TagAlias>::const_iterator it = m_registry.find( alias ); + if( it != m_registry.end() ) + return it->second; + else + return Option<TagAlias>(); + } + + std::string TagAliasRegistry::expandAliases( std::string const& unexpandedTestSpec ) const { + std::string expandedTestSpec = unexpandedTestSpec; + for( std::map<std::string, TagAlias>::const_iterator it = m_registry.begin(), itEnd = m_registry.end(); + it != itEnd; + ++it ) { + std::size_t pos = expandedTestSpec.find( it->first ); + if( pos != std::string::npos ) { + expandedTestSpec = expandedTestSpec.substr( 0, pos ) + + it->second.tag + + expandedTestSpec.substr( pos + it->first.size() ); + } + } + return expandedTestSpec; + } + + void TagAliasRegistry::add( char const* alias, char const* tag, SourceLineInfo const& lineInfo ) { + + if( !startsWith( alias, "[@" ) || !endsWith( alias, "]" ) ) { + std::ostringstream oss; + oss << "error: tag alias, \"" << alias << "\" is not of the form [@alias name].\n" << lineInfo; + throw std::domain_error( oss.str().c_str() ); + } + if( !m_registry.insert( std::make_pair( alias, TagAlias( tag, lineInfo ) ) ).second ) { + std::ostringstream oss; + oss << "error: tag alias, \"" << alias << "\" already registered.\n" + << "\tFirst seen at " << find(alias)->lineInfo << "\n" + << "\tRedefined at " << lineInfo; + throw std::domain_error( oss.str().c_str() ); + } + } + + TagAliasRegistry& TagAliasRegistry::get() { + static TagAliasRegistry instance; + return instance; + + } + + ITagAliasRegistry::~ITagAliasRegistry() {} + ITagAliasRegistry const& ITagAliasRegistry::get() { return TagAliasRegistry::get(); } + + RegistrarForTagAliases::RegistrarForTagAliases( char const* alias, char const* tag, SourceLineInfo const& lineInfo ) { + try { + TagAliasRegistry::get().add( alias, tag, lineInfo ); + } + catch( std::exception& ex ) { + Colour colourGuard( Colour::Red ); + Catch::cerr() << ex.what() << std::endl; + exit(1); + } + } + +} // end namespace Catch + +// #included from: ../reporters/catch_reporter_multi.hpp +#define TWOBLUECUBES_CATCH_REPORTER_MULTI_HPP_INCLUDED + +namespace Catch { + +class MultipleReporters : public SharedImpl<IStreamingReporter> { + typedef std::vector<Ptr<IStreamingReporter> > Reporters; + Reporters m_reporters; + +public: + void add( Ptr<IStreamingReporter> const& reporter ) { + m_reporters.push_back( reporter ); + } + +public: // IStreamingReporter + + virtual ReporterPreferences getPreferences() const CATCH_OVERRIDE { + return m_reporters[0]->getPreferences(); + } + + virtual void noMatchingTestCases( std::string const& spec ) CATCH_OVERRIDE { + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + (*it)->noMatchingTestCases( spec ); + } + + virtual void testRunStarting( TestRunInfo const& testRunInfo ) CATCH_OVERRIDE { + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + (*it)->testRunStarting( testRunInfo ); + } + + virtual void testGroupStarting( GroupInfo const& groupInfo ) CATCH_OVERRIDE { + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + (*it)->testGroupStarting( groupInfo ); + } + + virtual void testCaseStarting( TestCaseInfo const& testInfo ) CATCH_OVERRIDE { + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + (*it)->testCaseStarting( testInfo ); + } + + virtual void sectionStarting( SectionInfo const& sectionInfo ) CATCH_OVERRIDE { + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + (*it)->sectionStarting( sectionInfo ); + } + + virtual void assertionStarting( AssertionInfo const& assertionInfo ) CATCH_OVERRIDE { + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + (*it)->assertionStarting( assertionInfo ); + } + + // The return value indicates if the messages buffer should be cleared: + virtual bool assertionEnded( AssertionStats const& assertionStats ) CATCH_OVERRIDE { + bool clearBuffer = false; + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + clearBuffer |= (*it)->assertionEnded( assertionStats ); + return clearBuffer; + } + + virtual void sectionEnded( SectionStats const& sectionStats ) CATCH_OVERRIDE { + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + (*it)->sectionEnded( sectionStats ); + } + + virtual void testCaseEnded( TestCaseStats const& testCaseStats ) CATCH_OVERRIDE { + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + (*it)->testCaseEnded( testCaseStats ); + } + + virtual void testGroupEnded( TestGroupStats const& testGroupStats ) CATCH_OVERRIDE { + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + (*it)->testGroupEnded( testGroupStats ); + } + + virtual void testRunEnded( TestRunStats const& testRunStats ) CATCH_OVERRIDE { + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + (*it)->testRunEnded( testRunStats ); + } + + virtual void skipTest( TestCaseInfo const& testInfo ) CATCH_OVERRIDE { + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + (*it)->skipTest( testInfo ); + } +}; + +Ptr<IStreamingReporter> addReporter( Ptr<IStreamingReporter> const& existingReporter, Ptr<IStreamingReporter> const& additionalReporter ) { + Ptr<IStreamingReporter> resultingReporter; + + if( existingReporter ) { + MultipleReporters* multi = dynamic_cast<MultipleReporters*>( existingReporter.get() ); + if( !multi ) { + multi = new MultipleReporters; + resultingReporter = Ptr<IStreamingReporter>( multi ); + if( existingReporter ) + multi->add( existingReporter ); + } + else + resultingReporter = existingReporter; + multi->add( additionalReporter ); + } + else + resultingReporter = additionalReporter; + + return resultingReporter; +} + +} // end namespace Catch + +// #included from: ../reporters/catch_reporter_xml.hpp +#define TWOBLUECUBES_CATCH_REPORTER_XML_HPP_INCLUDED + +// #included from: catch_reporter_bases.hpp +#define TWOBLUECUBES_CATCH_REPORTER_BASES_HPP_INCLUDED + +#include <cstring> + +namespace Catch { + + struct StreamingReporterBase : SharedImpl<IStreamingReporter> { + + StreamingReporterBase( ReporterConfig const& _config ) + : m_config( _config.fullConfig() ), + stream( _config.stream() ) + { + m_reporterPrefs.shouldRedirectStdOut = false; + } + + virtual ReporterPreferences getPreferences() const CATCH_OVERRIDE { + return m_reporterPrefs; + } + + virtual ~StreamingReporterBase() CATCH_OVERRIDE; + + virtual void noMatchingTestCases( std::string const& ) CATCH_OVERRIDE {} + + virtual void testRunStarting( TestRunInfo const& _testRunInfo ) CATCH_OVERRIDE { + currentTestRunInfo = _testRunInfo; + } + virtual void testGroupStarting( GroupInfo const& _groupInfo ) CATCH_OVERRIDE { + currentGroupInfo = _groupInfo; + } + + virtual void testCaseStarting( TestCaseInfo const& _testInfo ) CATCH_OVERRIDE { + currentTestCaseInfo = _testInfo; + } + virtual void sectionStarting( SectionInfo const& _sectionInfo ) CATCH_OVERRIDE { + m_sectionStack.push_back( _sectionInfo ); + } + + virtual void sectionEnded( SectionStats const& /* _sectionStats */ ) CATCH_OVERRIDE { + m_sectionStack.pop_back(); + } + virtual void testCaseEnded( TestCaseStats const& /* _testCaseStats */ ) CATCH_OVERRIDE { + currentTestCaseInfo.reset(); + } + virtual void testGroupEnded( TestGroupStats const& /* _testGroupStats */ ) CATCH_OVERRIDE { + currentGroupInfo.reset(); + } + virtual void testRunEnded( TestRunStats const& /* _testRunStats */ ) CATCH_OVERRIDE { + currentTestCaseInfo.reset(); + currentGroupInfo.reset(); + currentTestRunInfo.reset(); + } + + virtual void skipTest( TestCaseInfo const& ) CATCH_OVERRIDE { + // Don't do anything with this by default. + // It can optionally be overridden in the derived class. + } + + Ptr<IConfig const> m_config; + std::ostream& stream; + + LazyStat<TestRunInfo> currentTestRunInfo; + LazyStat<GroupInfo> currentGroupInfo; + LazyStat<TestCaseInfo> currentTestCaseInfo; + + std::vector<SectionInfo> m_sectionStack; + ReporterPreferences m_reporterPrefs; + }; + + struct CumulativeReporterBase : SharedImpl<IStreamingReporter> { + template<typename T, typename ChildNodeT> + struct Node : SharedImpl<> { + explicit Node( T const& _value ) : value( _value ) {} + virtual ~Node() {} + + typedef std::vector<Ptr<ChildNodeT> > ChildNodes; + T value; + ChildNodes children; + }; + struct SectionNode : SharedImpl<> { + explicit SectionNode( SectionStats const& _stats ) : stats( _stats ) {} + virtual ~SectionNode(); + + bool operator == ( SectionNode const& other ) const { + return stats.sectionInfo.lineInfo == other.stats.sectionInfo.lineInfo; + } + bool operator == ( Ptr<SectionNode> const& other ) const { + return operator==( *other ); + } + + SectionStats stats; + typedef std::vector<Ptr<SectionNode> > ChildSections; + typedef std::vector<AssertionStats> Assertions; + ChildSections childSections; + Assertions assertions; + std::string stdOut; + std::string stdErr; + }; + + struct BySectionInfo { + BySectionInfo( SectionInfo const& other ) : m_other( other ) {} + BySectionInfo( BySectionInfo const& other ) : m_other( other.m_other ) {} + bool operator() ( Ptr<SectionNode> const& node ) const { + return node->stats.sectionInfo.lineInfo == m_other.lineInfo; + } + private: + void operator=( BySectionInfo const& ); + SectionInfo const& m_other; + }; + + typedef Node<TestCaseStats, SectionNode> TestCaseNode; + typedef Node<TestGroupStats, TestCaseNode> TestGroupNode; + typedef Node<TestRunStats, TestGroupNode> TestRunNode; + + CumulativeReporterBase( ReporterConfig const& _config ) + : m_config( _config.fullConfig() ), + stream( _config.stream() ) + { + m_reporterPrefs.shouldRedirectStdOut = false; + } + ~CumulativeReporterBase(); + + virtual ReporterPreferences getPreferences() const CATCH_OVERRIDE { + return m_reporterPrefs; + } + + virtual void testRunStarting( TestRunInfo const& ) CATCH_OVERRIDE {} + virtual void testGroupStarting( GroupInfo const& ) CATCH_OVERRIDE {} + + virtual void testCaseStarting( TestCaseInfo const& ) CATCH_OVERRIDE {} + + virtual void sectionStarting( SectionInfo const& sectionInfo ) CATCH_OVERRIDE { + SectionStats incompleteStats( sectionInfo, Counts(), 0, false ); + Ptr<SectionNode> node; + if( m_sectionStack.empty() ) { + if( !m_rootSection ) + m_rootSection = new SectionNode( incompleteStats ); + node = m_rootSection; + } + else { + SectionNode& parentNode = *m_sectionStack.back(); + SectionNode::ChildSections::const_iterator it = + std::find_if( parentNode.childSections.begin(), + parentNode.childSections.end(), + BySectionInfo( sectionInfo ) ); + if( it == parentNode.childSections.end() ) { + node = new SectionNode( incompleteStats ); + parentNode.childSections.push_back( node ); + } + else + node = *it; + } + m_sectionStack.push_back( node ); + m_deepestSection = node; + } + + virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE {} + + virtual bool assertionEnded( AssertionStats const& assertionStats ) { + assert( !m_sectionStack.empty() ); + SectionNode& sectionNode = *m_sectionStack.back(); + sectionNode.assertions.push_back( assertionStats ); + return true; + } + virtual void sectionEnded( SectionStats const& sectionStats ) CATCH_OVERRIDE { + assert( !m_sectionStack.empty() ); + SectionNode& node = *m_sectionStack.back(); + node.stats = sectionStats; + m_sectionStack.pop_back(); + } + virtual void testCaseEnded( TestCaseStats const& testCaseStats ) CATCH_OVERRIDE { + Ptr<TestCaseNode> node = new TestCaseNode( testCaseStats ); + assert( m_sectionStack.size() == 0 ); + node->children.push_back( m_rootSection ); + m_testCases.push_back( node ); + m_rootSection.reset(); + + assert( m_deepestSection ); + m_deepestSection->stdOut = testCaseStats.stdOut; + m_deepestSection->stdErr = testCaseStats.stdErr; + } + virtual void testGroupEnded( TestGroupStats const& testGroupStats ) CATCH_OVERRIDE { + Ptr<TestGroupNode> node = new TestGroupNode( testGroupStats ); + node->children.swap( m_testCases ); + m_testGroups.push_back( node ); + } + virtual void testRunEnded( TestRunStats const& testRunStats ) CATCH_OVERRIDE { + Ptr<TestRunNode> node = new TestRunNode( testRunStats ); + node->children.swap( m_testGroups ); + m_testRuns.push_back( node ); + testRunEndedCumulative(); + } + virtual void testRunEndedCumulative() = 0; + + virtual void skipTest( TestCaseInfo const& ) CATCH_OVERRIDE {} + + Ptr<IConfig const> m_config; + std::ostream& stream; + std::vector<AssertionStats> m_assertions; + std::vector<std::vector<Ptr<SectionNode> > > m_sections; + std::vector<Ptr<TestCaseNode> > m_testCases; + std::vector<Ptr<TestGroupNode> > m_testGroups; + + std::vector<Ptr<TestRunNode> > m_testRuns; + + Ptr<SectionNode> m_rootSection; + Ptr<SectionNode> m_deepestSection; + std::vector<Ptr<SectionNode> > m_sectionStack; + ReporterPreferences m_reporterPrefs; + + }; + + template<char C> + char const* getLineOfChars() { + static char line[CATCH_CONFIG_CONSOLE_WIDTH] = {0}; + if( !*line ) { + memset( line, C, CATCH_CONFIG_CONSOLE_WIDTH-1 ); + line[CATCH_CONFIG_CONSOLE_WIDTH-1] = 0; + } + return line; + } + + struct TestEventListenerBase : StreamingReporterBase { + TestEventListenerBase( ReporterConfig const& _config ) + : StreamingReporterBase( _config ) + {} + + virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE {} + virtual bool assertionEnded( AssertionStats const& ) CATCH_OVERRIDE { + return false; + } + }; + +} // end namespace Catch + +// #included from: ../internal/catch_reporter_registrars.hpp +#define TWOBLUECUBES_CATCH_REPORTER_REGISTRARS_HPP_INCLUDED + +namespace Catch { + + template<typename T> + class LegacyReporterRegistrar { + + class ReporterFactory : public IReporterFactory { + virtual IStreamingReporter* create( ReporterConfig const& config ) const { + return new LegacyReporterAdapter( new T( config ) ); + } + + virtual std::string getDescription() const { + return T::getDescription(); + } + }; + + public: + + LegacyReporterRegistrar( std::string const& name ) { + getMutableRegistryHub().registerReporter( name, new ReporterFactory() ); + } + }; + + template<typename T> + class ReporterRegistrar { + + class ReporterFactory : public SharedImpl<IReporterFactory> { + + // *** Please Note ***: + // - If you end up here looking at a compiler error because it's trying to register + // your custom reporter class be aware that the native reporter interface has changed + // to IStreamingReporter. The "legacy" interface, IReporter, is still supported via + // an adapter. Just use REGISTER_LEGACY_REPORTER to take advantage of the adapter. + // However please consider updating to the new interface as the old one is now + // deprecated and will probably be removed quite soon! + // Please contact me via github if you have any questions at all about this. + // In fact, ideally, please contact me anyway to let me know you've hit this - as I have + // no idea who is actually using custom reporters at all (possibly no-one!). + // The new interface is designed to minimise exposure to interface changes in the future. + virtual IStreamingReporter* create( ReporterConfig const& config ) const { + return new T( config ); + } + + virtual std::string getDescription() const { + return T::getDescription(); + } + }; + + public: + + ReporterRegistrar( std::string const& name ) { + getMutableRegistryHub().registerReporter( name, new ReporterFactory() ); + } + }; + + template<typename T> + class ListenerRegistrar { + + class ListenerFactory : public SharedImpl<IReporterFactory> { + + virtual IStreamingReporter* create( ReporterConfig const& config ) const { + return new T( config ); + } + virtual std::string getDescription() const { + return ""; + } + }; + + public: + + ListenerRegistrar() { + getMutableRegistryHub().registerListener( new ListenerFactory() ); + } + }; +} + +#define INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) \ + namespace{ Catch::LegacyReporterRegistrar<reporterType> catch_internal_RegistrarFor##reporterType( name ); } + +#define INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType ) \ + namespace{ Catch::ReporterRegistrar<reporterType> catch_internal_RegistrarFor##reporterType( name ); } + +#define INTERNAL_CATCH_REGISTER_LISTENER( listenerType ) \ + namespace{ Catch::ListenerRegistrar<listenerType> catch_internal_RegistrarFor##listenerType; } + +// #included from: ../internal/catch_xmlwriter.hpp +#define TWOBLUECUBES_CATCH_XMLWRITER_HPP_INCLUDED + +#include <sstream> +#include <string> +#include <vector> +#include <iomanip> + +namespace Catch { + + class XmlEncode { + public: + enum ForWhat { ForTextNodes, ForAttributes }; + + XmlEncode( std::string const& str, ForWhat forWhat = ForTextNodes ) + : m_str( str ), + m_forWhat( forWhat ) + {} + + void encodeTo( std::ostream& os ) const { + + // Apostrophe escaping not necessary if we always use " to write attributes + // (see: http://www.w3.org/TR/xml/#syntax) + + for( std::size_t i = 0; i < m_str.size(); ++ i ) { + char c = m_str[i]; + switch( c ) { + case '<': os << "<"; break; + case '&': os << "&"; break; + + case '>': + // See: http://www.w3.org/TR/xml/#syntax + if( i > 2 && m_str[i-1] == ']' && m_str[i-2] == ']' ) + os << ">"; + else + os << c; + break; + + case '\"': + if( m_forWhat == ForAttributes ) + os << """; + else + os << c; + break; + + default: + // Escape control chars - based on contribution by @espenalb in PR #465 + if ( ( c < '\x09' ) || ( c > '\x0D' && c < '\x20') || c=='\x7F' ) + os << "&#x" << std::uppercase << std::hex << static_cast<int>( c ); + else + os << c; + } + } + } + + friend std::ostream& operator << ( std::ostream& os, XmlEncode const& xmlEncode ) { + xmlEncode.encodeTo( os ); + return os; + } + + private: + std::string m_str; + ForWhat m_forWhat; + }; + + class XmlWriter { + public: + + class ScopedElement { + public: + ScopedElement( XmlWriter* writer ) + : m_writer( writer ) + {} + + ScopedElement( ScopedElement const& other ) + : m_writer( other.m_writer ){ + other.m_writer = CATCH_NULL; + } + + ~ScopedElement() { + if( m_writer ) + m_writer->endElement(); + } + + ScopedElement& writeText( std::string const& text, bool indent = true ) { + m_writer->writeText( text, indent ); + return *this; + } + + template<typename T> + ScopedElement& writeAttribute( std::string const& name, T const& attribute ) { + m_writer->writeAttribute( name, attribute ); + return *this; + } + + private: + mutable XmlWriter* m_writer; + }; + + XmlWriter() + : m_tagIsOpen( false ), + m_needsNewline( false ), + m_os( &Catch::cout() ) + {} + + XmlWriter( std::ostream& os ) + : m_tagIsOpen( false ), + m_needsNewline( false ), + m_os( &os ) + {} + + ~XmlWriter() { + while( !m_tags.empty() ) + endElement(); + } + + XmlWriter& startElement( std::string const& name ) { + ensureTagClosed(); + newlineIfNecessary(); + stream() << m_indent << "<" << name; + m_tags.push_back( name ); + m_indent += " "; + m_tagIsOpen = true; + return *this; + } + + ScopedElement scopedElement( std::string const& name ) { + ScopedElement scoped( this ); + startElement( name ); + return scoped; + } + + XmlWriter& endElement() { + newlineIfNecessary(); + m_indent = m_indent.substr( 0, m_indent.size()-2 ); + if( m_tagIsOpen ) { + stream() << "/>\n"; + m_tagIsOpen = false; + } + else { + stream() << m_indent << "</" << m_tags.back() << ">\n"; + } + m_tags.pop_back(); + return *this; + } + + XmlWriter& writeAttribute( std::string const& name, std::string const& attribute ) { + if( !name.empty() && !attribute.empty() ) + stream() << " " << name << "=\"" << XmlEncode( attribute, XmlEncode::ForAttributes ) << "\""; + return *this; + } + + XmlWriter& writeAttribute( std::string const& name, bool attribute ) { + stream() << " " << name << "=\"" << ( attribute ? "true" : "false" ) << "\""; + return *this; + } + + template<typename T> + XmlWriter& writeAttribute( std::string const& name, T const& attribute ) { + std::ostringstream oss; + oss << attribute; + return writeAttribute( name, oss.str() ); + } + + XmlWriter& writeText( std::string const& text, bool indent = true ) { + if( !text.empty() ){ + bool tagWasOpen = m_tagIsOpen; + ensureTagClosed(); + if( tagWasOpen && indent ) + stream() << m_indent; + stream() << XmlEncode( text ); + m_needsNewline = true; + } + return *this; + } + + XmlWriter& writeComment( std::string const& text ) { + ensureTagClosed(); + stream() << m_indent << "<!--" << text << "-->"; + m_needsNewline = true; + return *this; + } + + XmlWriter& writeBlankLine() { + ensureTagClosed(); + stream() << "\n"; + return *this; + } + + void setStream( std::ostream& os ) { + m_os = &os; + } + + private: + XmlWriter( XmlWriter const& ); + void operator=( XmlWriter const& ); + + std::ostream& stream() { + return *m_os; + } + + void ensureTagClosed() { + if( m_tagIsOpen ) { + stream() << ">\n"; + m_tagIsOpen = false; + } + } + + void newlineIfNecessary() { + if( m_needsNewline ) { + stream() << "\n"; + m_needsNewline = false; + } + } + + bool m_tagIsOpen; + bool m_needsNewline; + std::vector<std::string> m_tags; + std::string m_indent; + std::ostream* m_os; + }; + +} +// #included from: catch_reenable_warnings.h + +#define TWOBLUECUBES_CATCH_REENABLE_WARNINGS_H_INCLUDED + +#ifdef __clang__ +# ifdef __ICC // icpc defines the __clang__ macro +# pragma warning(pop) +# else +# pragma clang diagnostic pop +# endif +#elif defined __GNUC__ +# pragma GCC diagnostic pop +#endif + + +namespace Catch { + class XmlReporter : public StreamingReporterBase { + public: + XmlReporter( ReporterConfig const& _config ) + : StreamingReporterBase( _config ), + m_sectionDepth( 0 ) + { + m_reporterPrefs.shouldRedirectStdOut = true; + } + + virtual ~XmlReporter() CATCH_OVERRIDE; + + static std::string getDescription() { + return "Reports test results as an XML document"; + } + + public: // StreamingReporterBase + + virtual void noMatchingTestCases( std::string const& s ) CATCH_OVERRIDE { + StreamingReporterBase::noMatchingTestCases( s ); + } + + virtual void testRunStarting( TestRunInfo const& testInfo ) CATCH_OVERRIDE { + StreamingReporterBase::testRunStarting( testInfo ); + m_xml.setStream( stream ); + m_xml.startElement( "Catch" ); + if( !m_config->name().empty() ) + m_xml.writeAttribute( "name", m_config->name() ); + } + + virtual void testGroupStarting( GroupInfo const& groupInfo ) CATCH_OVERRIDE { + StreamingReporterBase::testGroupStarting( groupInfo ); + m_xml.startElement( "Group" ) + .writeAttribute( "name", groupInfo.name ); + } + + virtual void testCaseStarting( TestCaseInfo const& testInfo ) CATCH_OVERRIDE { + StreamingReporterBase::testCaseStarting(testInfo); + m_xml.startElement( "TestCase" ).writeAttribute( "name", trim( testInfo.name ) ); + + if ( m_config->showDurations() == ShowDurations::Always ) + m_testCaseTimer.start(); + } + + virtual void sectionStarting( SectionInfo const& sectionInfo ) CATCH_OVERRIDE { + StreamingReporterBase::sectionStarting( sectionInfo ); + if( m_sectionDepth++ > 0 ) { + m_xml.startElement( "Section" ) + .writeAttribute( "name", trim( sectionInfo.name ) ) + .writeAttribute( "description", sectionInfo.description ); + } + } + + virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE { } + + virtual bool assertionEnded( AssertionStats const& assertionStats ) CATCH_OVERRIDE { + const AssertionResult& assertionResult = assertionStats.assertionResult; + + // Print any info messages in <Info> tags. + if( assertionStats.assertionResult.getResultType() != ResultWas::Ok ) { + for( std::vector<MessageInfo>::const_iterator it = assertionStats.infoMessages.begin(), itEnd = assertionStats.infoMessages.end(); + it != itEnd; + ++it ) { + if( it->type == ResultWas::Info ) { + m_xml.scopedElement( "Info" ) + .writeText( it->message ); + } else if ( it->type == ResultWas::Warning ) { + m_xml.scopedElement( "Warning" ) + .writeText( it->message ); + } + } + } + + // Drop out if result was successful but we're not printing them. + if( !m_config->includeSuccessfulResults() && isOk(assertionResult.getResultType()) ) + return true; + + // Print the expression if there is one. + if( assertionResult.hasExpression() ) { + m_xml.startElement( "Expression" ) + .writeAttribute( "success", assertionResult.succeeded() ) + .writeAttribute( "type", assertionResult.getTestMacroName() ) + .writeAttribute( "filename", assertionResult.getSourceInfo().file ) + .writeAttribute( "line", assertionResult.getSourceInfo().line ); + + m_xml.scopedElement( "Original" ) + .writeText( assertionResult.getExpression() ); + m_xml.scopedElement( "Expanded" ) + .writeText( assertionResult.getExpandedExpression() ); + } + + // And... Print a result applicable to each result type. + switch( assertionResult.getResultType() ) { + case ResultWas::ThrewException: + m_xml.scopedElement( "Exception" ) + .writeAttribute( "filename", assertionResult.getSourceInfo().file ) + .writeAttribute( "line", assertionResult.getSourceInfo().line ) + .writeText( assertionResult.getMessage() ); + break; + case ResultWas::FatalErrorCondition: + m_xml.scopedElement( "Fatal Error Condition" ) + .writeAttribute( "filename", assertionResult.getSourceInfo().file ) + .writeAttribute( "line", assertionResult.getSourceInfo().line ) + .writeText( assertionResult.getMessage() ); + break; + case ResultWas::Info: + m_xml.scopedElement( "Info" ) + .writeText( assertionResult.getMessage() ); + break; + case ResultWas::Warning: + // Warning will already have been written + break; + case ResultWas::ExplicitFailure: + m_xml.scopedElement( "Failure" ) + .writeText( assertionResult.getMessage() ); + break; + default: + break; + } + + if( assertionResult.hasExpression() ) + m_xml.endElement(); + + return true; + } + + virtual void sectionEnded( SectionStats const& sectionStats ) CATCH_OVERRIDE { + StreamingReporterBase::sectionEnded( sectionStats ); + if( --m_sectionDepth > 0 ) { + XmlWriter::ScopedElement e = m_xml.scopedElement( "OverallResults" ); + e.writeAttribute( "successes", sectionStats.assertions.passed ); + e.writeAttribute( "failures", sectionStats.assertions.failed ); + e.writeAttribute( "expectedFailures", sectionStats.assertions.failedButOk ); + + if ( m_config->showDurations() == ShowDurations::Always ) + e.writeAttribute( "durationInSeconds", sectionStats.durationInSeconds ); + + m_xml.endElement(); + } + } + + virtual void testCaseEnded( TestCaseStats const& testCaseStats ) CATCH_OVERRIDE { + StreamingReporterBase::testCaseEnded( testCaseStats ); + XmlWriter::ScopedElement e = m_xml.scopedElement( "OverallResult" ); + e.writeAttribute( "success", testCaseStats.totals.assertions.allOk() ); + + if ( m_config->showDurations() == ShowDurations::Always ) + e.writeAttribute( "durationInSeconds", m_testCaseTimer.getElapsedSeconds() ); + + m_xml.endElement(); + } + + virtual void testGroupEnded( TestGroupStats const& testGroupStats ) CATCH_OVERRIDE { + StreamingReporterBase::testGroupEnded( testGroupStats ); + // TODO: Check testGroupStats.aborting and act accordingly. + m_xml.scopedElement( "OverallResults" ) + .writeAttribute( "successes", testGroupStats.totals.assertions.passed ) + .writeAttribute( "failures", testGroupStats.totals.assertions.failed ) + .writeAttribute( "expectedFailures", testGroupStats.totals.assertions.failedButOk ); + m_xml.endElement(); + } + + virtual void testRunEnded( TestRunStats const& testRunStats ) CATCH_OVERRIDE { + StreamingReporterBase::testRunEnded( testRunStats ); + m_xml.scopedElement( "OverallResults" ) + .writeAttribute( "successes", testRunStats.totals.assertions.passed ) + .writeAttribute( "failures", testRunStats.totals.assertions.failed ) + .writeAttribute( "expectedFailures", testRunStats.totals.assertions.failedButOk ); + m_xml.endElement(); + } + + private: + Timer m_testCaseTimer; + XmlWriter m_xml; + int m_sectionDepth; + }; + + INTERNAL_CATCH_REGISTER_REPORTER( "xml", XmlReporter ) + +} // end namespace Catch + +// #included from: ../reporters/catch_reporter_junit.hpp +#define TWOBLUECUBES_CATCH_REPORTER_JUNIT_HPP_INCLUDED + +#include <assert.h> + +namespace Catch { + + class JunitReporter : public CumulativeReporterBase { + public: + JunitReporter( ReporterConfig const& _config ) + : CumulativeReporterBase( _config ), + xml( _config.stream() ) + { + m_reporterPrefs.shouldRedirectStdOut = true; + } + + virtual ~JunitReporter() CATCH_OVERRIDE; + + static std::string getDescription() { + return "Reports test results in an XML format that looks like Ant's junitreport target"; + } + + virtual void noMatchingTestCases( std::string const& /*spec*/ ) CATCH_OVERRIDE {} + + virtual void testRunStarting( TestRunInfo const& runInfo ) CATCH_OVERRIDE { + CumulativeReporterBase::testRunStarting( runInfo ); + xml.startElement( "testsuites" ); + } + + virtual void testGroupStarting( GroupInfo const& groupInfo ) CATCH_OVERRIDE { + suiteTimer.start(); + stdOutForSuite.str(""); + stdErrForSuite.str(""); + unexpectedExceptions = 0; + CumulativeReporterBase::testGroupStarting( groupInfo ); + } + + virtual bool assertionEnded( AssertionStats const& assertionStats ) CATCH_OVERRIDE { + if( assertionStats.assertionResult.getResultType() == ResultWas::ThrewException ) + unexpectedExceptions++; + return CumulativeReporterBase::assertionEnded( assertionStats ); + } + + virtual void testCaseEnded( TestCaseStats const& testCaseStats ) CATCH_OVERRIDE { + stdOutForSuite << testCaseStats.stdOut; + stdErrForSuite << testCaseStats.stdErr; + CumulativeReporterBase::testCaseEnded( testCaseStats ); + } + + virtual void testGroupEnded( TestGroupStats const& testGroupStats ) CATCH_OVERRIDE { + double suiteTime = suiteTimer.getElapsedSeconds(); + CumulativeReporterBase::testGroupEnded( testGroupStats ); + writeGroup( *m_testGroups.back(), suiteTime ); + } + + virtual void testRunEndedCumulative() CATCH_OVERRIDE { + xml.endElement(); + } + + void writeGroup( TestGroupNode const& groupNode, double suiteTime ) { + XmlWriter::ScopedElement e = xml.scopedElement( "testsuite" ); + TestGroupStats const& stats = groupNode.value; + xml.writeAttribute( "name", stats.groupInfo.name ); + xml.writeAttribute( "errors", unexpectedExceptions ); + xml.writeAttribute( "failures", stats.totals.assertions.failed-unexpectedExceptions ); + xml.writeAttribute( "tests", stats.totals.assertions.total() ); + xml.writeAttribute( "hostname", "tbd" ); // !TBD + if( m_config->showDurations() == ShowDurations::Never ) + xml.writeAttribute( "time", "" ); + else + xml.writeAttribute( "time", suiteTime ); + xml.writeAttribute( "timestamp", "tbd" ); // !TBD + + // Write test cases + for( TestGroupNode::ChildNodes::const_iterator + it = groupNode.children.begin(), itEnd = groupNode.children.end(); + it != itEnd; + ++it ) + writeTestCase( **it ); + + xml.scopedElement( "system-out" ).writeText( trim( stdOutForSuite.str() ), false ); + xml.scopedElement( "system-err" ).writeText( trim( stdErrForSuite.str() ), false ); + } + + void writeTestCase( TestCaseNode const& testCaseNode ) { + TestCaseStats const& stats = testCaseNode.value; + + // All test cases have exactly one section - which represents the + // test case itself. That section may have 0-n nested sections + assert( testCaseNode.children.size() == 1 ); + SectionNode const& rootSection = *testCaseNode.children.front(); + + std::string className = stats.testInfo.className; + + if( className.empty() ) { + if( rootSection.childSections.empty() ) + className = "global"; + } + writeSection( className, "", rootSection ); + } + + void writeSection( std::string const& className, + std::string const& rootName, + SectionNode const& sectionNode ) { + std::string name = trim( sectionNode.stats.sectionInfo.name ); + if( !rootName.empty() ) + name = rootName + "/" + name; + + if( !sectionNode.assertions.empty() || + !sectionNode.stdOut.empty() || + !sectionNode.stdErr.empty() ) { + XmlWriter::ScopedElement e = xml.scopedElement( "testcase" ); + if( className.empty() ) { + xml.writeAttribute( "classname", name ); + xml.writeAttribute( "name", "root" ); + } + else { + xml.writeAttribute( "classname", className ); + xml.writeAttribute( "name", name ); + } + xml.writeAttribute( "time", Catch::toString( sectionNode.stats.durationInSeconds ) ); + + writeAssertions( sectionNode ); + + if( !sectionNode.stdOut.empty() ) + xml.scopedElement( "system-out" ).writeText( trim( sectionNode.stdOut ), false ); + if( !sectionNode.stdErr.empty() ) + xml.scopedElement( "system-err" ).writeText( trim( sectionNode.stdErr ), false ); + } + for( SectionNode::ChildSections::const_iterator + it = sectionNode.childSections.begin(), + itEnd = sectionNode.childSections.end(); + it != itEnd; + ++it ) + if( className.empty() ) + writeSection( name, "", **it ); + else + writeSection( className, name, **it ); + } + + void writeAssertions( SectionNode const& sectionNode ) { + for( SectionNode::Assertions::const_iterator + it = sectionNode.assertions.begin(), itEnd = sectionNode.assertions.end(); + it != itEnd; + ++it ) + writeAssertion( *it ); + } + void writeAssertion( AssertionStats const& stats ) { + AssertionResult const& result = stats.assertionResult; + if( !result.isOk() ) { + std::string elementName; + switch( result.getResultType() ) { + case ResultWas::ThrewException: + case ResultWas::FatalErrorCondition: + elementName = "error"; + break; + case ResultWas::ExplicitFailure: + elementName = "failure"; + break; + case ResultWas::ExpressionFailed: + elementName = "failure"; + break; + case ResultWas::DidntThrowException: + elementName = "failure"; + break; + + // We should never see these here: + case ResultWas::Info: + case ResultWas::Warning: + case ResultWas::Ok: + case ResultWas::Unknown: + case ResultWas::FailureBit: + case ResultWas::Exception: + elementName = "internalError"; + break; + } + + XmlWriter::ScopedElement e = xml.scopedElement( elementName ); + + xml.writeAttribute( "message", result.getExpandedExpression() ); + xml.writeAttribute( "type", result.getTestMacroName() ); + + std::ostringstream oss; + if( !result.getMessage().empty() ) + oss << result.getMessage() << "\n"; + for( std::vector<MessageInfo>::const_iterator + it = stats.infoMessages.begin(), + itEnd = stats.infoMessages.end(); + it != itEnd; + ++it ) + if( it->type == ResultWas::Info ) + oss << it->message << "\n"; + + oss << "at " << result.getSourceInfo(); + xml.writeText( oss.str(), false ); + } + } + + XmlWriter xml; + Timer suiteTimer; + std::ostringstream stdOutForSuite; + std::ostringstream stdErrForSuite; + unsigned int unexpectedExceptions; + }; + + INTERNAL_CATCH_REGISTER_REPORTER( "junit", JunitReporter ) + +} // end namespace Catch + +// #included from: ../reporters/catch_reporter_console.hpp +#define TWOBLUECUBES_CATCH_REPORTER_CONSOLE_HPP_INCLUDED + +namespace Catch { + + struct ConsoleReporter : StreamingReporterBase { + ConsoleReporter( ReporterConfig const& _config ) + : StreamingReporterBase( _config ), + m_headerPrinted( false ) + {} + + virtual ~ConsoleReporter() CATCH_OVERRIDE; + static std::string getDescription() { + return "Reports test results as plain lines of text"; + } + + virtual void noMatchingTestCases( std::string const& spec ) CATCH_OVERRIDE { + stream << "No test cases matched '" << spec << "'" << std::endl; + } + + virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE { + } + + virtual bool assertionEnded( AssertionStats const& _assertionStats ) CATCH_OVERRIDE { + AssertionResult const& result = _assertionStats.assertionResult; + + bool printInfoMessages = true; + + // Drop out if result was successful and we're not printing those + if( !m_config->includeSuccessfulResults() && result.isOk() ) { + if( result.getResultType() != ResultWas::Warning ) + return false; + printInfoMessages = false; + } + + lazyPrint(); + + AssertionPrinter printer( stream, _assertionStats, printInfoMessages ); + printer.print(); + stream << std::endl; + return true; + } + + virtual void sectionStarting( SectionInfo const& _sectionInfo ) CATCH_OVERRIDE { + m_headerPrinted = false; + StreamingReporterBase::sectionStarting( _sectionInfo ); + } + virtual void sectionEnded( SectionStats const& _sectionStats ) CATCH_OVERRIDE { + if( _sectionStats.missingAssertions ) { + lazyPrint(); + Colour colour( Colour::ResultError ); + if( m_sectionStack.size() > 1 ) + stream << "\nNo assertions in section"; + else + stream << "\nNo assertions in test case"; + stream << " '" << _sectionStats.sectionInfo.name << "'\n" << std::endl; + } + if( m_headerPrinted ) { + if( m_config->showDurations() == ShowDurations::Always ) + stream << "Completed in " << _sectionStats.durationInSeconds << "s" << std::endl; + m_headerPrinted = false; + } + else { + if( m_config->showDurations() == ShowDurations::Always ) + stream << _sectionStats.sectionInfo.name << " completed in " << _sectionStats.durationInSeconds << "s" << std::endl; + } + StreamingReporterBase::sectionEnded( _sectionStats ); + } + + virtual void testCaseEnded( TestCaseStats const& _testCaseStats ) CATCH_OVERRIDE { + StreamingReporterBase::testCaseEnded( _testCaseStats ); + m_headerPrinted = false; + } + virtual void testGroupEnded( TestGroupStats const& _testGroupStats ) CATCH_OVERRIDE { + if( currentGroupInfo.used ) { + printSummaryDivider(); + stream << "Summary for group '" << _testGroupStats.groupInfo.name << "':\n"; + printTotals( _testGroupStats.totals ); + stream << "\n" << std::endl; + } + StreamingReporterBase::testGroupEnded( _testGroupStats ); + } + virtual void testRunEnded( TestRunStats const& _testRunStats ) CATCH_OVERRIDE { + printTotalsDivider( _testRunStats.totals ); + printTotals( _testRunStats.totals ); + stream << std::endl; + StreamingReporterBase::testRunEnded( _testRunStats ); + } + + private: + + class AssertionPrinter { + void operator= ( AssertionPrinter const& ); + public: + AssertionPrinter( std::ostream& _stream, AssertionStats const& _stats, bool _printInfoMessages ) + : stream( _stream ), + stats( _stats ), + result( _stats.assertionResult ), + colour( Colour::None ), + message( result.getMessage() ), + messages( _stats.infoMessages ), + printInfoMessages( _printInfoMessages ) + { + switch( result.getResultType() ) { + case ResultWas::Ok: + colour = Colour::Success; + passOrFail = "PASSED"; + //if( result.hasMessage() ) + if( _stats.infoMessages.size() == 1 ) + messageLabel = "with message"; + if( _stats.infoMessages.size() > 1 ) + messageLabel = "with messages"; + break; + case ResultWas::ExpressionFailed: + if( result.isOk() ) { + colour = Colour::Success; + passOrFail = "FAILED - but was ok"; + } + else { + colour = Colour::Error; + passOrFail = "FAILED"; + } + if( _stats.infoMessages.size() == 1 ) + messageLabel = "with message"; + if( _stats.infoMessages.size() > 1 ) + messageLabel = "with messages"; + break; + case ResultWas::ThrewException: + colour = Colour::Error; + passOrFail = "FAILED"; + messageLabel = "due to unexpected exception with message"; + break; + case ResultWas::FatalErrorCondition: + colour = Colour::Error; + passOrFail = "FAILED"; + messageLabel = "due to a fatal error condition"; + break; + case ResultWas::DidntThrowException: + colour = Colour::Error; + passOrFail = "FAILED"; + messageLabel = "because no exception was thrown where one was expected"; + break; + case ResultWas::Info: + messageLabel = "info"; + break; + case ResultWas::Warning: + messageLabel = "warning"; + break; + case ResultWas::ExplicitFailure: + passOrFail = "FAILED"; + colour = Colour::Error; + if( _stats.infoMessages.size() == 1 ) + messageLabel = "explicitly with message"; + if( _stats.infoMessages.size() > 1 ) + messageLabel = "explicitly with messages"; + break; + // These cases are here to prevent compiler warnings + case ResultWas::Unknown: + case ResultWas::FailureBit: + case ResultWas::Exception: + passOrFail = "** internal error **"; + colour = Colour::Error; + break; + } + } + + void print() const { + printSourceInfo(); + if( stats.totals.assertions.total() > 0 ) { + if( result.isOk() ) + stream << "\n"; + printResultType(); + printOriginalExpression(); + printReconstructedExpression(); + } + else { + stream << "\n"; + } + printMessage(); + } + + private: + void printResultType() const { + if( !passOrFail.empty() ) { + Colour colourGuard( colour ); + stream << passOrFail << ":\n"; + } + } + void printOriginalExpression() const { + if( result.hasExpression() ) { + Colour colourGuard( Colour::OriginalExpression ); + stream << " "; + stream << result.getExpressionInMacro(); + stream << "\n"; + } + } + void printReconstructedExpression() const { + if( result.hasExpandedExpression() ) { + stream << "with expansion:\n"; + Colour colourGuard( Colour::ReconstructedExpression ); + stream << Text( result.getExpandedExpression(), TextAttributes().setIndent(2) ) << "\n"; + } + } + void printMessage() const { + if( !messageLabel.empty() ) + stream << messageLabel << ":" << "\n"; + for( std::vector<MessageInfo>::const_iterator it = messages.begin(), itEnd = messages.end(); + it != itEnd; + ++it ) { + // If this assertion is a warning ignore any INFO messages + if( printInfoMessages || it->type != ResultWas::Info ) + stream << Text( it->message, TextAttributes().setIndent(2) ) << "\n"; + } + } + void printSourceInfo() const { + Colour colourGuard( Colour::FileName ); + stream << result.getSourceInfo() << ": "; + } + + std::ostream& stream; + AssertionStats const& stats; + AssertionResult const& result; + Colour::Code colour; + std::string passOrFail; + std::string messageLabel; + std::string message; + std::vector<MessageInfo> messages; + bool printInfoMessages; + }; + + void lazyPrint() { + + if( !currentTestRunInfo.used ) + lazyPrintRunInfo(); + if( !currentGroupInfo.used ) + lazyPrintGroupInfo(); + + if( !m_headerPrinted ) { + printTestCaseAndSectionHeader(); + m_headerPrinted = true; + } + } + void lazyPrintRunInfo() { + stream << "\n" << getLineOfChars<'~'>() << "\n"; + Colour colour( Colour::SecondaryText ); + stream << currentTestRunInfo->name + << " is a Catch v" << libraryVersion << " host application.\n" + << "Run with -? for options\n\n"; + + if( m_config->rngSeed() != 0 ) + stream << "Randomness seeded to: " << m_config->rngSeed() << "\n\n"; + + currentTestRunInfo.used = true; + } + void lazyPrintGroupInfo() { + if( !currentGroupInfo->name.empty() && currentGroupInfo->groupsCounts > 1 ) { + printClosedHeader( "Group: " + currentGroupInfo->name ); + currentGroupInfo.used = true; + } + } + void printTestCaseAndSectionHeader() { + assert( !m_sectionStack.empty() ); + printOpenHeader( currentTestCaseInfo->name ); + + if( m_sectionStack.size() > 1 ) { + Colour colourGuard( Colour::Headers ); + + std::vector<SectionInfo>::const_iterator + it = m_sectionStack.begin()+1, // Skip first section (test case) + itEnd = m_sectionStack.end(); + for( ; it != itEnd; ++it ) + printHeaderString( it->name, 2 ); + } + + SourceLineInfo lineInfo = m_sectionStack.front().lineInfo; + + if( !lineInfo.empty() ){ + stream << getLineOfChars<'-'>() << "\n"; + Colour colourGuard( Colour::FileName ); + stream << lineInfo << "\n"; + } + stream << getLineOfChars<'.'>() << "\n" << std::endl; + } + + void printClosedHeader( std::string const& _name ) { + printOpenHeader( _name ); + stream << getLineOfChars<'.'>() << "\n"; + } + void printOpenHeader( std::string const& _name ) { + stream << getLineOfChars<'-'>() << "\n"; + { + Colour colourGuard( Colour::Headers ); + printHeaderString( _name ); + } + } + + // if string has a : in first line will set indent to follow it on + // subsequent lines + void printHeaderString( std::string const& _string, std::size_t indent = 0 ) { + std::size_t i = _string.find( ": " ); + if( i != std::string::npos ) + i+=2; + else + i = 0; + stream << Text( _string, TextAttributes() + .setIndent( indent+i) + .setInitialIndent( indent ) ) << "\n"; + } + + struct SummaryColumn { + + SummaryColumn( std::string const& _label, Colour::Code _colour ) + : label( _label ), + colour( _colour ) + {} + SummaryColumn addRow( std::size_t count ) { + std::ostringstream oss; + oss << count; + std::string row = oss.str(); + for( std::vector<std::string>::iterator it = rows.begin(); it != rows.end(); ++it ) { + while( it->size() < row.size() ) + *it = " " + *it; + while( it->size() > row.size() ) + row = " " + row; + } + rows.push_back( row ); + return *this; + } + + std::string label; + Colour::Code colour; + std::vector<std::string> rows; + + }; + + void printTotals( Totals const& totals ) { + if( totals.testCases.total() == 0 ) { + stream << Colour( Colour::Warning ) << "No tests ran\n"; + } + else if( totals.assertions.total() > 0 && totals.assertions.allPassed() ) { + stream << Colour( Colour::ResultSuccess ) << "All tests passed"; + stream << " (" + << pluralise( totals.assertions.passed, "assertion" ) << " in " + << pluralise( totals.testCases.passed, "test case" ) << ")" + << "\n"; + } + else { + + std::vector<SummaryColumn> columns; + columns.push_back( SummaryColumn( "", Colour::None ) + .addRow( totals.testCases.total() ) + .addRow( totals.assertions.total() ) ); + columns.push_back( SummaryColumn( "passed", Colour::Success ) + .addRow( totals.testCases.passed ) + .addRow( totals.assertions.passed ) ); + columns.push_back( SummaryColumn( "failed", Colour::ResultError ) + .addRow( totals.testCases.failed ) + .addRow( totals.assertions.failed ) ); + columns.push_back( SummaryColumn( "failed as expected", Colour::ResultExpectedFailure ) + .addRow( totals.testCases.failedButOk ) + .addRow( totals.assertions.failedButOk ) ); + + printSummaryRow( "test cases", columns, 0 ); + printSummaryRow( "assertions", columns, 1 ); + } + } + void printSummaryRow( std::string const& label, std::vector<SummaryColumn> const& cols, std::size_t row ) { + for( std::vector<SummaryColumn>::const_iterator it = cols.begin(); it != cols.end(); ++it ) { + std::string value = it->rows[row]; + if( it->label.empty() ) { + stream << label << ": "; + if( value != "0" ) + stream << value; + else + stream << Colour( Colour::Warning ) << "- none -"; + } + else if( value != "0" ) { + stream << Colour( Colour::LightGrey ) << " | "; + stream << Colour( it->colour ) + << value << " " << it->label; + } + } + stream << "\n"; + } + + static std::size_t makeRatio( std::size_t number, std::size_t total ) { + std::size_t ratio = total > 0 ? CATCH_CONFIG_CONSOLE_WIDTH * number/ total : 0; + return ( ratio == 0 && number > 0 ) ? 1 : ratio; + } + static std::size_t& findMax( std::size_t& i, std::size_t& j, std::size_t& k ) { + if( i > j && i > k ) + return i; + else if( j > k ) + return j; + else + return k; + } + + void printTotalsDivider( Totals const& totals ) { + if( totals.testCases.total() > 0 ) { + std::size_t failedRatio = makeRatio( totals.testCases.failed, totals.testCases.total() ); + std::size_t failedButOkRatio = makeRatio( totals.testCases.failedButOk, totals.testCases.total() ); + std::size_t passedRatio = makeRatio( totals.testCases.passed, totals.testCases.total() ); + while( failedRatio + failedButOkRatio + passedRatio < CATCH_CONFIG_CONSOLE_WIDTH-1 ) + findMax( failedRatio, failedButOkRatio, passedRatio )++; + while( failedRatio + failedButOkRatio + passedRatio > CATCH_CONFIG_CONSOLE_WIDTH-1 ) + findMax( failedRatio, failedButOkRatio, passedRatio )--; + + stream << Colour( Colour::Error ) << std::string( failedRatio, '=' ); + stream << Colour( Colour::ResultExpectedFailure ) << std::string( failedButOkRatio, '=' ); + if( totals.testCases.allPassed() ) + stream << Colour( Colour::ResultSuccess ) << std::string( passedRatio, '=' ); + else + stream << Colour( Colour::Success ) << std::string( passedRatio, '=' ); + } + else { + stream << Colour( Colour::Warning ) << std::string( CATCH_CONFIG_CONSOLE_WIDTH-1, '=' ); + } + stream << "\n"; + } + void printSummaryDivider() { + stream << getLineOfChars<'-'>() << "\n"; + } + + private: + bool m_headerPrinted; + }; + + INTERNAL_CATCH_REGISTER_REPORTER( "console", ConsoleReporter ) + +} // end namespace Catch + +// #included from: ../reporters/catch_reporter_compact.hpp +#define TWOBLUECUBES_CATCH_REPORTER_COMPACT_HPP_INCLUDED + +namespace Catch { + + struct CompactReporter : StreamingReporterBase { + + CompactReporter( ReporterConfig const& _config ) + : StreamingReporterBase( _config ) + {} + + virtual ~CompactReporter(); + + static std::string getDescription() { + return "Reports test results on a single line, suitable for IDEs"; + } + + virtual ReporterPreferences getPreferences() const { + ReporterPreferences prefs; + prefs.shouldRedirectStdOut = false; + return prefs; + } + + virtual void noMatchingTestCases( std::string const& spec ) { + stream << "No test cases matched '" << spec << "'" << std::endl; + } + + virtual void assertionStarting( AssertionInfo const& ) { + } + + virtual bool assertionEnded( AssertionStats const& _assertionStats ) { + AssertionResult const& result = _assertionStats.assertionResult; + + bool printInfoMessages = true; + + // Drop out if result was successful and we're not printing those + if( !m_config->includeSuccessfulResults() && result.isOk() ) { + if( result.getResultType() != ResultWas::Warning ) + return false; + printInfoMessages = false; + } + + AssertionPrinter printer( stream, _assertionStats, printInfoMessages ); + printer.print(); + + stream << std::endl; + return true; + } + + virtual void testRunEnded( TestRunStats const& _testRunStats ) { + printTotals( _testRunStats.totals ); + stream << "\n" << std::endl; + StreamingReporterBase::testRunEnded( _testRunStats ); + } + + private: + class AssertionPrinter { + void operator= ( AssertionPrinter const& ); + public: + AssertionPrinter( std::ostream& _stream, AssertionStats const& _stats, bool _printInfoMessages ) + : stream( _stream ) + , stats( _stats ) + , result( _stats.assertionResult ) + , messages( _stats.infoMessages ) + , itMessage( _stats.infoMessages.begin() ) + , printInfoMessages( _printInfoMessages ) + {} + + void print() { + printSourceInfo(); + + itMessage = messages.begin(); + + switch( result.getResultType() ) { + case ResultWas::Ok: + printResultType( Colour::ResultSuccess, passedString() ); + printOriginalExpression(); + printReconstructedExpression(); + if ( ! result.hasExpression() ) + printRemainingMessages( Colour::None ); + else + printRemainingMessages(); + break; + case ResultWas::ExpressionFailed: + if( result.isOk() ) + printResultType( Colour::ResultSuccess, failedString() + std::string( " - but was ok" ) ); + else + printResultType( Colour::Error, failedString() ); + printOriginalExpression(); + printReconstructedExpression(); + printRemainingMessages(); + break; + case ResultWas::ThrewException: + printResultType( Colour::Error, failedString() ); + printIssue( "unexpected exception with message:" ); + printMessage(); + printExpressionWas(); + printRemainingMessages(); + break; + case ResultWas::FatalErrorCondition: + printResultType( Colour::Error, failedString() ); + printIssue( "fatal error condition with message:" ); + printMessage(); + printExpressionWas(); + printRemainingMessages(); + break; + case ResultWas::DidntThrowException: + printResultType( Colour::Error, failedString() ); + printIssue( "expected exception, got none" ); + printExpressionWas(); + printRemainingMessages(); + break; + case ResultWas::Info: + printResultType( Colour::None, "info" ); + printMessage(); + printRemainingMessages(); + break; + case ResultWas::Warning: + printResultType( Colour::None, "warning" ); + printMessage(); + printRemainingMessages(); + break; + case ResultWas::ExplicitFailure: + printResultType( Colour::Error, failedString() ); + printIssue( "explicitly" ); + printRemainingMessages( Colour::None ); + break; + // These cases are here to prevent compiler warnings + case ResultWas::Unknown: + case ResultWas::FailureBit: + case ResultWas::Exception: + printResultType( Colour::Error, "** internal error **" ); + break; + } + } + + private: + // Colour::LightGrey + + static Colour::Code dimColour() { return Colour::FileName; } + +#ifdef CATCH_PLATFORM_MAC + static const char* failedString() { return "FAILED"; } + static const char* passedString() { return "PASSED"; } +#else + static const char* failedString() { return "failed"; } + static const char* passedString() { return "passed"; } +#endif + + void printSourceInfo() const { + Colour colourGuard( Colour::FileName ); + stream << result.getSourceInfo() << ":"; + } + + void printResultType( Colour::Code colour, std::string passOrFail ) const { + if( !passOrFail.empty() ) { + { + Colour colourGuard( colour ); + stream << " " << passOrFail; + } + stream << ":"; + } + } + + void printIssue( std::string issue ) const { + stream << " " << issue; + } + + void printExpressionWas() { + if( result.hasExpression() ) { + stream << ";"; + { + Colour colour( dimColour() ); + stream << " expression was:"; + } + printOriginalExpression(); + } + } + + void printOriginalExpression() const { + if( result.hasExpression() ) { + stream << " " << result.getExpression(); + } + } + + void printReconstructedExpression() const { + if( result.hasExpandedExpression() ) { + { + Colour colour( dimColour() ); + stream << " for: "; + } + stream << result.getExpandedExpression(); + } + } + + void printMessage() { + if ( itMessage != messages.end() ) { + stream << " '" << itMessage->message << "'"; + ++itMessage; + } + } + + void printRemainingMessages( Colour::Code colour = dimColour() ) { + if ( itMessage == messages.end() ) + return; + + // using messages.end() directly yields compilation error: + std::vector<MessageInfo>::const_iterator itEnd = messages.end(); + const std::size_t N = static_cast<std::size_t>( std::distance( itMessage, itEnd ) ); + + { + Colour colourGuard( colour ); + stream << " with " << pluralise( N, "message" ) << ":"; + } + + for(; itMessage != itEnd; ) { + // If this assertion is a warning ignore any INFO messages + if( printInfoMessages || itMessage->type != ResultWas::Info ) { + stream << " '" << itMessage->message << "'"; + if ( ++itMessage != itEnd ) { + Colour colourGuard( dimColour() ); + stream << " and"; + } + } + } + } + + private: + std::ostream& stream; + AssertionStats const& stats; + AssertionResult const& result; + std::vector<MessageInfo> messages; + std::vector<MessageInfo>::const_iterator itMessage; + bool printInfoMessages; + }; + + // Colour, message variants: + // - white: No tests ran. + // - red: Failed [both/all] N test cases, failed [both/all] M assertions. + // - white: Passed [both/all] N test cases (no assertions). + // - red: Failed N tests cases, failed M assertions. + // - green: Passed [both/all] N tests cases with M assertions. + + std::string bothOrAll( std::size_t count ) const { + return count == 1 ? "" : count == 2 ? "both " : "all " ; + } + + void printTotals( const Totals& totals ) const { + if( totals.testCases.total() == 0 ) { + stream << "No tests ran."; + } + else if( totals.testCases.failed == totals.testCases.total() ) { + Colour colour( Colour::ResultError ); + const std::string qualify_assertions_failed = + totals.assertions.failed == totals.assertions.total() ? + bothOrAll( totals.assertions.failed ) : ""; + stream << + "Failed " << bothOrAll( totals.testCases.failed ) + << pluralise( totals.testCases.failed, "test case" ) << ", " + "failed " << qualify_assertions_failed << + pluralise( totals.assertions.failed, "assertion" ) << "."; + } + else if( totals.assertions.total() == 0 ) { + stream << + "Passed " << bothOrAll( totals.testCases.total() ) + << pluralise( totals.testCases.total(), "test case" ) + << " (no assertions)."; + } + else if( totals.assertions.failed ) { + Colour colour( Colour::ResultError ); + stream << + "Failed " << pluralise( totals.testCases.failed, "test case" ) << ", " + "failed " << pluralise( totals.assertions.failed, "assertion" ) << "."; + } + else { + Colour colour( Colour::ResultSuccess ); + stream << + "Passed " << bothOrAll( totals.testCases.passed ) + << pluralise( totals.testCases.passed, "test case" ) << + " with " << pluralise( totals.assertions.passed, "assertion" ) << "."; + } + } + }; + + INTERNAL_CATCH_REGISTER_REPORTER( "compact", CompactReporter ) + +} // end namespace Catch + +namespace Catch { + // These are all here to avoid warnings about not having any out of line + // virtual methods + NonCopyable::~NonCopyable() {} + IShared::~IShared() {} + IStream::~IStream() CATCH_NOEXCEPT {} + FileStream::~FileStream() CATCH_NOEXCEPT {} + CoutStream::~CoutStream() CATCH_NOEXCEPT {} + DebugOutStream::~DebugOutStream() CATCH_NOEXCEPT {} + StreamBufBase::~StreamBufBase() CATCH_NOEXCEPT {} + IContext::~IContext() {} + IResultCapture::~IResultCapture() {} + ITestCase::~ITestCase() {} + ITestCaseRegistry::~ITestCaseRegistry() {} + IRegistryHub::~IRegistryHub() {} + IMutableRegistryHub::~IMutableRegistryHub() {} + IExceptionTranslator::~IExceptionTranslator() {} + IExceptionTranslatorRegistry::~IExceptionTranslatorRegistry() {} + IReporter::~IReporter() {} + IReporterFactory::~IReporterFactory() {} + IReporterRegistry::~IReporterRegistry() {} + IStreamingReporter::~IStreamingReporter() {} + AssertionStats::~AssertionStats() {} + SectionStats::~SectionStats() {} + TestCaseStats::~TestCaseStats() {} + TestGroupStats::~TestGroupStats() {} + TestRunStats::~TestRunStats() {} + CumulativeReporterBase::SectionNode::~SectionNode() {} + CumulativeReporterBase::~CumulativeReporterBase() {} + + StreamingReporterBase::~StreamingReporterBase() {} + ConsoleReporter::~ConsoleReporter() {} + CompactReporter::~CompactReporter() {} + IRunner::~IRunner() {} + IMutableContext::~IMutableContext() {} + IConfig::~IConfig() {} + XmlReporter::~XmlReporter() {} + JunitReporter::~JunitReporter() {} + TestRegistry::~TestRegistry() {} + FreeFunctionTestCase::~FreeFunctionTestCase() {} + IGeneratorInfo::~IGeneratorInfo() {} + IGeneratorsForTest::~IGeneratorsForTest() {} + WildcardPattern::~WildcardPattern() {} + TestSpec::Pattern::~Pattern() {} + TestSpec::NamePattern::~NamePattern() {} + TestSpec::TagPattern::~TagPattern() {} + TestSpec::ExcludedPattern::~ExcludedPattern() {} + + Matchers::Impl::StdString::Equals::~Equals() {} + Matchers::Impl::StdString::Contains::~Contains() {} + Matchers::Impl::StdString::StartsWith::~StartsWith() {} + Matchers::Impl::StdString::EndsWith::~EndsWith() {} + + void Config::dummy() {} + + namespace TestCaseTracking { + ITracker::~ITracker() {} + TrackerBase::~TrackerBase() {} + SectionTracker::~SectionTracker() {} + IndexTracker::~IndexTracker() {} + } +} + +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + +#endif + +#ifdef CATCH_CONFIG_MAIN +// #included from: internal/catch_default_main.hpp +#define TWOBLUECUBES_CATCH_DEFAULT_MAIN_HPP_INCLUDED + +#ifndef __OBJC__ + +// Standard C/C++ main entry point +int main (int argc, char * argv[]) { + return Catch::Session().run( argc, argv ); +} + +#else // __OBJC__ + +// Objective-C entry point +int main (int argc, char * const argv[]) { +#if !CATCH_ARC_ENABLED + NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; +#endif + + Catch::registerTestMethods(); + int result = Catch::Session().run( argc, (char* const*)argv ); + +#if !CATCH_ARC_ENABLED + [pool drain]; +#endif + + return result; +} + +#endif // __OBJC__ + +#endif + +#ifdef CLARA_CONFIG_MAIN_NOT_DEFINED +# undef CLARA_CONFIG_MAIN +#endif + +////// + +// If this config identifier is defined then all CATCH macros are prefixed with CATCH_ +#ifdef CATCH_CONFIG_PREFIX_ALL + +#define CATCH_REQUIRE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal, "CATCH_REQUIRE" ) +#define CATCH_REQUIRE_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, "CATCH_REQUIRE_FALSE" ) + +#define CATCH_REQUIRE_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::Normal, "", "CATCH_REQUIRE_THROWS" ) +#define CATCH_REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_THROWS_AS" ) +#define CATCH_REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::Normal, matcher, "CATCH_REQUIRE_THROWS_WITH" ) +#define CATCH_REQUIRE_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_NOTHROW" ) + +#define CATCH_CHECK( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK" ) +#define CATCH_CHECK_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::FalseTest, "CATCH_CHECK_FALSE" ) +#define CATCH_CHECKED_IF( expr ) INTERNAL_CATCH_IF( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECKED_IF" ) +#define CATCH_CHECKED_ELSE( expr ) INTERNAL_CATCH_ELSE( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECKED_ELSE" ) +#define CATCH_CHECK_NOFAIL( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, "CATCH_CHECK_NOFAIL" ) + +#define CATCH_CHECK_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_THROWS" ) +#define CATCH_CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_THROWS_AS" ) +#define CATCH_CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::ContinueOnFailure, matcher, "CATCH_CHECK_THROWS_WITH" ) +#define CATCH_CHECK_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_NOTHROW" ) + +#define CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_THAT" ) +#define CATCH_REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_THAT" ) + +#define CATCH_INFO( msg ) INTERNAL_CATCH_INFO( msg, "CATCH_INFO" ) +#define CATCH_WARN( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, "CATCH_WARN", msg ) +#define CATCH_SCOPED_INFO( msg ) INTERNAL_CATCH_INFO( msg, "CATCH_INFO" ) +#define CATCH_CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CATCH_CAPTURE" ) +#define CATCH_SCOPED_CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CATCH_CAPTURE" ) + +#ifdef CATCH_CONFIG_VARIADIC_MACROS + #define CATCH_TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ ) + #define CATCH_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ ) + #define CATCH_METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ ) + #define CATCH_REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ ) + #define CATCH_SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ ) + #define CATCH_FAIL( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "CATCH_FAIL", __VA_ARGS__ ) + #define CATCH_SUCCEED( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "CATCH_SUCCEED", __VA_ARGS__ ) +#else + #define CATCH_TEST_CASE( name, description ) INTERNAL_CATCH_TESTCASE( name, description ) + #define CATCH_TEST_CASE_METHOD( className, name, description ) INTERNAL_CATCH_TEST_CASE_METHOD( className, name, description ) + #define CATCH_METHOD_AS_TEST_CASE( method, name, description ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, name, description ) + #define CATCH_REGISTER_TEST_CASE( function, name, description ) INTERNAL_CATCH_REGISTER_TESTCASE( function, name, description ) + #define CATCH_SECTION( name, description ) INTERNAL_CATCH_SECTION( name, description ) + #define CATCH_FAIL( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "CATCH_FAIL", msg ) + #define CATCH_SUCCEED( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "CATCH_SUCCEED", msg ) +#endif +#define CATCH_ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE( "", "" ) + +#define CATCH_REGISTER_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType ) +#define CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) + +#define CATCH_GENERATE( expr) INTERNAL_CATCH_GENERATE( expr ) + +// "BDD-style" convenience wrappers +#ifdef CATCH_CONFIG_VARIADIC_MACROS +#define CATCH_SCENARIO( ... ) CATCH_TEST_CASE( "Scenario: " __VA_ARGS__ ) +#define CATCH_SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ ) +#else +#define CATCH_SCENARIO( name, tags ) CATCH_TEST_CASE( "Scenario: " name, tags ) +#define CATCH_SCENARIO_METHOD( className, name, tags ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " name, tags ) +#endif +#define CATCH_GIVEN( desc ) CATCH_SECTION( std::string( "Given: ") + desc, "" ) +#define CATCH_WHEN( desc ) CATCH_SECTION( std::string( " When: ") + desc, "" ) +#define CATCH_AND_WHEN( desc ) CATCH_SECTION( std::string( " And: ") + desc, "" ) +#define CATCH_THEN( desc ) CATCH_SECTION( std::string( " Then: ") + desc, "" ) +#define CATCH_AND_THEN( desc ) CATCH_SECTION( std::string( " And: ") + desc, "" ) + +// If CATCH_CONFIG_PREFIX_ALL is not defined then the CATCH_ prefix is not required +#else + +#define REQUIRE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal, "REQUIRE" ) +#define REQUIRE_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, "REQUIRE_FALSE" ) + +#define REQUIRE_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::Normal, "", "REQUIRE_THROWS" ) +#define REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::Normal, "REQUIRE_THROWS_AS" ) +#define REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::Normal, matcher, "REQUIRE_THROWS_WITH" ) +#define REQUIRE_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::Normal, "REQUIRE_NOTHROW" ) + +#define CHECK( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECK" ) +#define CHECK_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::FalseTest, "CHECK_FALSE" ) +#define CHECKED_IF( expr ) INTERNAL_CATCH_IF( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECKED_IF" ) +#define CHECKED_ELSE( expr ) INTERNAL_CATCH_ELSE( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECKED_ELSE" ) +#define CHECK_NOFAIL( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, "CHECK_NOFAIL" ) + +#define CHECK_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::ContinueOnFailure, "", "CHECK_THROWS" ) +#define CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::ContinueOnFailure, "CHECK_THROWS_AS" ) +#define CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::ContinueOnFailure, matcher, "CHECK_THROWS_WITH" ) +#define CHECK_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECK_NOTHROW" ) + +#define CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::ContinueOnFailure, "CHECK_THAT" ) +#define REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::Normal, "REQUIRE_THAT" ) + +#define INFO( msg ) INTERNAL_CATCH_INFO( msg, "INFO" ) +#define WARN( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, "WARN", msg ) +#define SCOPED_INFO( msg ) INTERNAL_CATCH_INFO( msg, "INFO" ) +#define CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CAPTURE" ) +#define SCOPED_CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CAPTURE" ) + +#ifdef CATCH_CONFIG_VARIADIC_MACROS + #define TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ ) + #define TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ ) + #define METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ ) + #define REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ ) + #define SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ ) + #define FAIL( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "FAIL", __VA_ARGS__ ) + #define SUCCEED( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "SUCCEED", __VA_ARGS__ ) +#else + #define TEST_CASE( name, description ) INTERNAL_CATCH_TESTCASE( name, description ) + #define TEST_CASE_METHOD( className, name, description ) INTERNAL_CATCH_TEST_CASE_METHOD( className, name, description ) + #define METHOD_AS_TEST_CASE( method, name, description ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, name, description ) + #define REGISTER_TEST_CASE( method, name, description ) INTERNAL_CATCH_REGISTER_TESTCASE( method, name, description ) + #define SECTION( name, description ) INTERNAL_CATCH_SECTION( name, description ) + #define FAIL( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "FAIL", msg ) + #define SUCCEED( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "SUCCEED", msg ) +#endif +#define ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE( "", "" ) + +#define REGISTER_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType ) +#define REGISTER_LEGACY_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) + +#define GENERATE( expr) INTERNAL_CATCH_GENERATE( expr ) + +#endif + +#define CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) + +// "BDD-style" convenience wrappers +#ifdef CATCH_CONFIG_VARIADIC_MACROS +#define SCENARIO( ... ) TEST_CASE( "Scenario: " __VA_ARGS__ ) +#define SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ ) +#else +#define SCENARIO( name, tags ) TEST_CASE( "Scenario: " name, tags ) +#define SCENARIO_METHOD( className, name, tags ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " name, tags ) +#endif +#define GIVEN( desc ) SECTION( std::string(" Given: ") + desc, "" ) +#define WHEN( desc ) SECTION( std::string(" When: ") + desc, "" ) +#define AND_WHEN( desc ) SECTION( std::string("And when: ") + desc, "" ) +#define THEN( desc ) SECTION( std::string(" Then: ") + desc, "" ) +#define AND_THEN( desc ) SECTION( std::string(" And: ") + desc, "" ) + +using Catch::Detail::Approx; + +#endif // TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED + diff --git a/unittest/build/libnitrokey.so b/unittest/build/libnitrokey.so new file mode 120000 index 0000000..69a5e22 --- /dev/null +++ b/unittest/build/libnitrokey.so @@ -0,0 +1 @@ +../../build/libnitrokey.so
\ No newline at end of file diff --git a/unittest/build/run.sh b/unittest/build/run.sh new file mode 100755 index 0000000..2bcc580 --- /dev/null +++ b/unittest/build/run.sh @@ -0,0 +1 @@ +LD_LIBRARY_PATH=. ./test_HOTP diff --git a/unittest/catch_main.cpp b/unittest/catch_main.cpp new file mode 100644 index 0000000..c8270db --- /dev/null +++ b/unittest/catch_main.cpp @@ -0,0 +1,2 @@ +#define CATCH_CONFIG_MAIN // This tells Catch to provide a main() +#include "catch.hpp"
\ No newline at end of file diff --git a/unittest/conftest.py b/unittest/conftest.py new file mode 100644 index 0000000..a53b005 --- /dev/null +++ b/unittest/conftest.py @@ -0,0 +1,83 @@ +import pytest + +from misc import ffi + +device_type = None + +def skip_if_device_version_lower_than(allowed_devices): + global device_type + model, version = device_type + infinite_version_number = 999 + if allowed_devices.get(model, infinite_version_number) > version: + pytest.skip('This device model is not applicable to run this test') + + +@pytest.fixture(scope="module") +def C(request): + fp = '../NK_C_API.h' + + declarations = [] + with open(fp, 'r') as f: + declarations = f.readlines() + + cnt = 0 + a = iter(declarations) + for declaration in a: + if declaration.strip().startswith('NK_C_API'): + declaration = declaration.replace('NK_C_API', '').strip() + while ';' not in declaration: + declaration += (next(a)).strip() + # print(declaration) + ffi.cdef(declaration, override=True) + cnt +=1 + print('Imported {} declarations'.format(cnt)) + + C = None + import os, sys + path_build = os.path.join("..", "build") + paths = [ + os.environ.get('LIBNK_PATH', None), + os.path.join(path_build,"libnitrokey.so"), + os.path.join(path_build,"libnitrokey.dylib"), + os.path.join(path_build,"libnitrokey.dll"), + os.path.join(path_build,"nitrokey.dll"), + ] + for p in paths: + if not p: continue + print("Trying " +p) + p = os.path.abspath(p) + if os.path.exists(p): + print("Found: "+p) + C = ffi.dlopen(p) + break + else: + print("File does not exist: " + p) + if not C: + print("No library file found") + sys.exit(1) + + C.NK_set_debug(False) + nk_login = C.NK_login_auto() + if nk_login != 1: + print('No devices detected!') + assert nk_login != 0 # returns 0 if not connected or wrong model or 1 when connected + global device_type + firmware_version = C.NK_get_major_firmware_version() + model = 'P' if firmware_version in [7,8] else 'S' + device_type = (model, firmware_version) + + # assert C.NK_first_authenticate(DefaultPasswords.ADMIN, DefaultPasswords.ADMIN_TEMP) == DeviceErrorCode.STATUS_OK + # assert C.NK_user_authenticate(DefaultPasswords.USER, DefaultPasswords.USER_TEMP) == DeviceErrorCode.STATUS_OK + + # C.NK_status() + + def fin(): + print('\nFinishing connection to device') + C.NK_logout() + print('Finished') + + request.addfinalizer(fin) + # C.NK_set_debug(True) + C.NK_set_debug_level(3) + + return C diff --git a/unittest/constants.py b/unittest/constants.py new file mode 100644 index 0000000..f3e876a --- /dev/null +++ b/unittest/constants.py @@ -0,0 +1,37 @@ +from misc import to_hex + +def bb(x): + return bytes(x, encoding='ascii') + + +RFC_SECRET_HR = '12345678901234567890' +RFC_SECRET = to_hex(RFC_SECRET_HR) # '31323334353637383930...' +bbRFC_SECRET = bb(RFC_SECRET) + + +# print( repr((RFC_SECRET, RFC_SECRET_, len(RFC_SECRET))) ) + +class DefaultPasswords: + ADMIN = b'12345678' + USER = b'123456' + ADMIN_TEMP = b'123123123' + USER_TEMP = b'234234234' + UPDATE = b'12345678' + UPDATE_TEMP = b'123update123' + + +class DeviceErrorCode: + STATUS_OK = 0 + BUSY = 1 # busy or busy progressbar in place of wrong_CRC status + NOT_PROGRAMMED = 3 + WRONG_PASSWORD = 4 + STATUS_NOT_AUTHORIZED = 5 + STATUS_AES_DEC_FAILED = 0xa + + +class LibraryErrors: + TOO_LONG_STRING = 200 + INVALID_SLOT = 201 + INVALID_HEX_STRING = 202 + TARGET_BUFFER_SIZE_SMALLER_THAN_SOURCE = 203 + diff --git a/unittest/misc.py b/unittest/misc.py new file mode 100644 index 0000000..f4d7731 --- /dev/null +++ b/unittest/misc.py @@ -0,0 +1,48 @@ +import cffi + +ffi = cffi.FFI() +gs = ffi.string + + +def to_hex(s): + return "".join("{:02x}".format(ord(c)) for c in s) + + +def wait(t): + import time + msg = 'Waiting for %d seconds' % t + print(msg.center(40, '=')) + time.sleep(t) + + +def cast_pointer_to_tuple(obj, typen, len): + # usage: + # config = cast_pointer_to_tuple(config_raw_data, 'uint8_t', 5) + return tuple(ffi.cast("%s [%d]" % (typen, len), obj)[0:len]) + + +def get_devices_firmware_version(C): + firmware = C.NK_get_major_firmware_version() + return firmware + + +def is_pro_rtm_07(C): + firmware = get_devices_firmware_version(C) + return firmware == 7 + + +def is_pro_rtm_08(C): + firmware = get_devices_firmware_version(C) + return firmware == 8 + + +def is_storage(C): + """ + exact firmware storage is sent by other function + """ + # TODO identify connected device directly + return not is_pro_rtm_08(C) and not is_pro_rtm_07(C) + + +def is_long_OTP_secret_handled(C): + return is_pro_rtm_08(C) or is_storage(C) and get_devices_firmware_version(C) > 43 diff --git a/unittest/requirements.txt b/unittest/requirements.txt new file mode 100644 index 0000000..5c0110b --- /dev/null +++ b/unittest/requirements.txt @@ -0,0 +1,4 @@ +cffi +pytest-repeat +pytest-randomly +oath
\ No newline at end of file diff --git a/unittest/setup_python_dependencies.sh b/unittest/setup_python_dependencies.sh new file mode 100644 index 0000000..0f1a0f7 --- /dev/null +++ b/unittest/setup_python_dependencies.sh @@ -0,0 +1,3 @@ +#!/bin/bash + +pip install -r requirements.txt --user diff --git a/unittest/test.cc b/unittest/test.cc new file mode 100644 index 0000000..15235bd --- /dev/null +++ b/unittest/test.cc @@ -0,0 +1,83 @@ +#include "catch.hpp" + +#include <iostream> +#include <string.h> +#include "device_proto.h" +#include "log.h" +#include "stick10_commands.h" + +using namespace std; +using namespace nitrokey::device; +using namespace nitrokey::proto::stick10; +using namespace nitrokey::log; +using namespace nitrokey::misc; + +using Dev10 = std::shared_ptr<Stick10>; + +std::string getSlotName(Dev10 stick, int slotNo) { + auto slot_req = get_payload<ReadSlot>(); + slot_req.slot_number = slotNo; + auto slot = ReadSlot::CommandTransaction::run(stick, slot_req); + std::string sName(reinterpret_cast<char *>(slot.data().slot_name)); + return sName; +} + +TEST_CASE("Slot names are correct", "[slotNames]") { + auto stick = make_shared<Stick10>(); + bool connected = stick->connect(); + REQUIRE(connected == true); + + Log::instance().set_loglevel(Loglevel::DEBUG); + + auto resp = GetStatus::CommandTransaction::run(stick); + + auto authreq = get_payload<FirstAuthenticate>(); + strcpy((char *)(authreq.card_password), "12345678"); + FirstAuthenticate::CommandTransaction::run(stick, authreq); + + { + auto authreq = get_payload<EnablePasswordSafe>(); + strcpy((char *)(authreq.user_password), "123456"); + EnablePasswordSafe::CommandTransaction::run(stick, authreq); + } + + //assuming these values were set earlier, thus failing on normal use + REQUIRE(getSlotName(stick, 0x20) == std::string("1")); + REQUIRE(getSlotName(stick, 0x21) == std::string("slot2")); + + { + auto resp = GetPasswordRetryCount::CommandTransaction::run(stick); + REQUIRE(resp.data().password_retry_count == 3); + } + { + auto resp = GetUserPasswordRetryCount::CommandTransaction::run(stick); + REQUIRE(resp.data().password_retry_count == 3); + } + + { + auto slot = get_payload<GetPasswordSafeSlotName>(); + slot.slot_number = 0; + auto resp2 = GetPasswordSafeSlotName::CommandTransaction::run(stick, slot); + std::string sName(reinterpret_cast<char *>(resp2.data().slot_name)); + REQUIRE(sName == std::string("web1")); + } + + { + auto slot = get_payload<GetPasswordSafeSlotPassword>(); + slot.slot_number = 0; + auto resp2 = + GetPasswordSafeSlotPassword::CommandTransaction::run(stick, slot); + std::string sName(reinterpret_cast<char *>(resp2.data().slot_password)); + REQUIRE(sName == std::string("pass1")); + } + + { + auto slot = get_payload<GetPasswordSafeSlotLogin>(); + slot.slot_number = 0; + auto resp2 = GetPasswordSafeSlotLogin::CommandTransaction::run(stick, slot); + std::string sName(reinterpret_cast<char *>(resp2.data().slot_login)); + REQUIRE(sName == std::string("login1")); + } + + stick->disconnect(); +} diff --git a/unittest/test2.cc b/unittest/test2.cc new file mode 100644 index 0000000..bbe5b07 --- /dev/null +++ b/unittest/test2.cc @@ -0,0 +1,212 @@ + +static const char *const default_admin_pin = "12345678"; +static const char *const default_user_pin = "123456"; + +#include "catch.hpp" + +#include <iostream> +#include <string.h> +#include <NitrokeyManager.h> +#include "device_proto.h" +#include "log.h" +//#include "stick10_commands.h" +#include "stick20_commands.h" + +using namespace std; +using namespace nitrokey::device; +using namespace nitrokey::proto; +using namespace nitrokey::proto::stick20; +using namespace nitrokey::log; +using namespace nitrokey::misc; + +#include <memory> + +template<typename CMDTYPE> +void execute_password_command(std::shared_ptr<Device> stick, const char *password, const char kind = 'P') { + auto p = get_payload<CMDTYPE>(); + if (kind == 'P'){ + p.set_kind_user(); + } else { + p.set_kind_admin(); + } + strcpyT(p.password, password); + CMDTYPE::CommandTransaction::run(stick, p); + this_thread::sleep_for(1000ms); +} + +/** + * fail on purpose (will result in failed test) + * disable from running unwillingly + */ +void SKIP_TEST() { + CAPTURE("Failing current test to SKIP it"); + REQUIRE(false); +} + + +TEST_CASE("long operation test", "[test_long]") { + SKIP_TEST(); + + auto stick = make_shared<Stick20>(); + bool connected = stick->connect(); + REQUIRE(connected == true); + Log::instance().set_loglevel(Loglevel::DEBUG); + try{ + auto p = get_payload<FillSDCardWithRandomChars>(); + p.set_defaults(); + strcpyT(p.admin_pin, default_admin_pin); + FillSDCardWithRandomChars::CommandTransaction::run(stick, p); + this_thread::sleep_for(1000ms); + + CHECK(false); + } + catch (LongOperationInProgressException &progressException){ + CHECK(true); + } + + + for (int i = 0; i < 30; ++i) { + try { + stick10::GetStatus::CommandTransaction::run(stick); + } + catch (LongOperationInProgressException &progressException){ + CHECK((int)progressException.progress_bar_value>=0); + CAPTURE((int)progressException.progress_bar_value); + this_thread::sleep_for(2000ms); + } + + } + +} + + +TEST_CASE("test device internal status with various commands", "[fast]") { + auto stick = make_shared<Stick20>(); + bool connected = stick->connect(); + REQUIRE(connected == true); + + Log::instance().set_loglevel(Loglevel::DEBUG); + auto p = get_payload<stick20::SendStartup>(); + p.set_defaults(); + auto device_status = stick20::SendStartup::CommandTransaction::run(stick, p); + REQUIRE(device_status.data().AdminPwRetryCount == 3); + REQUIRE(device_status.data().UserPwRetryCount == 3); + REQUIRE(device_status.data().ActiveSmartCardID_u32 != 0); + + auto production_status = stick20::ProductionTest::CommandTransaction::run(stick); + REQUIRE(production_status.data().SD_Card_Size_u8 == 8); + REQUIRE(production_status.data().SD_CardID_u32 != 0); + + auto sdcard_occupancy = stick20::GetSDCardOccupancy::CommandTransaction::run(stick); + REQUIRE((int) sdcard_occupancy.data().ReadLevelMin >= 0); + REQUIRE((int) sdcard_occupancy.data().ReadLevelMax <= 100); + REQUIRE((int) sdcard_occupancy.data().WriteLevelMin >= 0); + REQUIRE((int) sdcard_occupancy.data().WriteLevelMax <= 100); +} + +TEST_CASE("setup hidden volume test", "[hidden]") { + auto stick = make_shared<Stick20>(); + bool connected = stick->connect(); + REQUIRE(connected == true); + Log::instance().set_loglevel(Loglevel::DEBUG); + stick10::LockDevice::CommandTransaction::run(stick); + this_thread::sleep_for(2000ms); + + auto user_pin = default_user_pin; + execute_password_command<EnableEncryptedPartition>(stick, user_pin); + + auto p = get_payload<stick20::SetupHiddenVolume>(); + p.SlotNr_u8 = 0; + p.StartBlockPercent_u8 = 70; + p.EndBlockPercent_u8 = 90; + auto hidden_volume_password = "123123123"; + strcpyT(p.HiddenVolumePassword_au8, hidden_volume_password); + stick20::SetupHiddenVolume::CommandTransaction::run(stick, p); + this_thread::sleep_for(2000ms); + + execute_password_command<EnableHiddenEncryptedPartition>(stick, hidden_volume_password); +} + +TEST_CASE("setup multiple hidden volumes", "[hidden]") { + auto stick = make_shared<Stick20>(); + bool connected = stick->connect(); + REQUIRE(connected == true); + Log::instance().set_loglevel(Loglevel::DEBUG); + + auto user_pin = default_user_pin; + stick10::LockDevice::CommandTransaction::run(stick); + this_thread::sleep_for(2000ms); + execute_password_command<EnableEncryptedPartition>(stick, user_pin); + + constexpr int volume_count = 4; + for (int i = 0; i < volume_count; ++i) { + auto p = get_payload<stick20::SetupHiddenVolume>(); + p.SlotNr_u8 = i; + p.StartBlockPercent_u8 = 20 + 10*i; + p.EndBlockPercent_u8 = p.StartBlockPercent_u8+i+1; + auto hidden_volume_password = std::string("123123123")+std::to_string(i); + strcpyT(p.HiddenVolumePassword_au8, hidden_volume_password.c_str()); + stick20::SetupHiddenVolume::CommandTransaction::run(stick, p); + this_thread::sleep_for(2000ms); + } + + + for (int i = 0; i < volume_count; ++i) { + execute_password_command<EnableEncryptedPartition>(stick, user_pin); + auto hidden_volume_password = std::string("123123123")+std::to_string(i); + execute_password_command<EnableHiddenEncryptedPartition>(stick, hidden_volume_password.c_str()); + this_thread::sleep_for(2000ms); + } +} + + +//in case of a bug this could change update PIN to some unexpected value +// - please save log with packet dump if this test will not pass +TEST_CASE("update password change", "[dangerous]") { + SKIP_TEST(); + + auto stick = make_shared<Stick20>(); + bool connected = stick->connect(); + REQUIRE(connected == true); + Log::instance().set_loglevel(Loglevel::DEBUG); + + auto pass1 = default_admin_pin; + auto pass2 = "12345678901234567890"; + + auto data = { + make_pair(pass1, pass2), + make_pair(pass2, pass1), + }; + for (auto && password: data) { + auto p = get_payload<stick20::ChangeUpdatePassword>(); + strcpyT(p.current_update_password, password.first); + strcpyT(p.new_update_password, password.second); + stick20::ChangeUpdatePassword::CommandTransaction::run(stick, p); + } +} + +TEST_CASE("general test", "[test]") { + auto stick = make_shared<Stick20>(); + bool connected = stick->connect(); + REQUIRE(connected == true); + + Log::instance().set_loglevel(Loglevel::DEBUG); + + stick10::LockDevice::CommandTransaction::run(stick); +// execute_password_command<EnableEncryptedPartition>(stick, "123456"); +// execute_password_command<DisableEncryptedPartition>(stick, "123456"); +// execute_password_command<DisableHiddenEncryptedPartition>(stick, "123123123"); + + execute_password_command<SendSetReadonlyToUncryptedVolume>(stick, default_user_pin); + execute_password_command<SendSetReadwriteToUncryptedVolume>(stick, default_user_pin); + execute_password_command<SendClearNewSdCardFound>(stick, default_admin_pin, 'A'); + stick20::GetDeviceStatus::CommandTransaction::run(stick); + this_thread::sleep_for(1000ms); +// execute_password_command<LockFirmware>(stick, "123123123"); //CAUTION +// execute_password_command<EnableFirmwareUpdate>(stick, "123123123"); //CAUTION FIRMWARE PIN + + execute_password_command<ExportFirmware>(stick, "12345678", 'A'); +// execute_password_command<FillSDCardWithRandomChars>(stick, "12345678", 'A'); + + stick10::LockDevice::CommandTransaction::run(stick); +} diff --git a/unittest/test3.cc b/unittest/test3.cc new file mode 100644 index 0000000..b5289f7 --- /dev/null +++ b/unittest/test3.cc @@ -0,0 +1,219 @@ + +static const char *const default_admin_pin = "12345678"; +static const char *const default_user_pin = "123456"; +const char * temporary_password = "123456789012345678901234"; +const char * RFC_SECRET = "12345678901234567890"; + +#include "catch.hpp" + +#include <iostream> +#include <string.h> +#include <NitrokeyManager.h> +#include "device_proto.h" +#include "log.h" +#include "stick10_commands_0.8.h" +//#include "stick20_commands.h" + +using namespace std; +using namespace nitrokey::device; +using namespace nitrokey::proto; +using namespace nitrokey::proto::stick10_08; +using namespace nitrokey::log; +using namespace nitrokey::misc; + +using Dev = Stick10; +using Dev10 = std::shared_ptr<Dev>; + +void connect_and_setup(Dev10 stick) { + bool connected = stick->connect(); + REQUIRE(connected == true); + Log::instance().set_loglevel(Loglevel::DEBUG); +} + +void authorize(Dev10 stick) { + auto authreq = get_payload<FirstAuthenticate>(); + strcpy((char *) (authreq.card_password), default_admin_pin); + strcpy((char *) (authreq.temporary_password), temporary_password); + FirstAuthenticate::CommandTransaction::run(stick, authreq); + + auto user_auth = get_payload<UserAuthenticate>(); + strcpyT(user_auth.temporary_password, temporary_password); + strcpyT(user_auth.card_password, default_user_pin); + UserAuthenticate::CommandTransaction::run(stick, user_auth); +} + +TEST_CASE("write slot", "[pronew]"){ + auto stick = make_shared<Dev>(); + + connect_and_setup(stick); + authorize(stick); + + auto p2 = get_payload<SendOTPData>(); + strcpyT(p2.temporary_admin_password, temporary_password); + p2.setTypeName(); + strcpyT(p2.data, "test name aaa"); + stick10_08::SendOTPData::CommandTransaction::run(stick, p2); + + p2 = get_payload<SendOTPData>(); + strcpyT(p2.temporary_admin_password, temporary_password); + strcpyT(p2.data, RFC_SECRET); + p2.setTypeSecret(); + stick10_08::SendOTPData::CommandTransaction::run(stick, p2); + + auto p = get_payload<WriteToOTPSlot>(); + strcpyT(p.temporary_admin_password, temporary_password); + p.use_8_digits = true; + p.slot_number = 0 + 0x10; + p.slot_counter_or_interval = 0; + stick10_08::WriteToOTPSlot::CommandTransaction::run(stick, p); + + auto pc = get_payload<WriteGeneralConfig>(); + pc.enable_user_password = 0; + strcpyT(pc.temporary_admin_password, temporary_password); + WriteGeneralConfig::CommandTransaction::run(stick, pc); + + auto p3 = get_payload<GetHOTP>(); + p3.slot_number = 0 + 0x10; + GetHOTP::CommandTransaction::run(stick, p3); + +} + + +TEST_CASE("erase slot", "[pronew]"){ + auto stick = make_shared<Dev>(); + connect_and_setup(stick); + authorize(stick); + + auto p = get_payload<WriteGeneralConfig>(); + p.enable_user_password = 0; + strcpyT(p.temporary_admin_password, temporary_password); + WriteGeneralConfig::CommandTransaction::run(stick, p); + + auto p3 = get_payload<GetHOTP>(); + p3.slot_number = 0 + 0x10; + GetHOTP::CommandTransaction::run(stick, p3); + + auto erase_payload = get_payload<EraseSlot>(); + erase_payload.slot_number = 0 + 0x10; + strcpyT(erase_payload.temporary_admin_password, temporary_password); + EraseSlot::CommandTransaction::run(stick, erase_payload); + + auto p4 = get_payload<GetHOTP>(); + p4.slot_number = 0 + 0x10; + REQUIRE_THROWS( + GetHOTP::CommandTransaction::run(stick, p4) + ); +} + +TEST_CASE("write general config", "[pronew]") { + auto stick = make_shared<Dev>(); + connect_and_setup(stick); + authorize(stick); + + auto p = get_payload<WriteGeneralConfig>(); + p.enable_user_password = 1; + REQUIRE_THROWS( + WriteGeneralConfig::CommandTransaction::run(stick, p) + ); + strcpyT(p.temporary_admin_password, temporary_password); + WriteGeneralConfig::CommandTransaction::run(stick, p); +} + +TEST_CASE("authorize user HOTP", "[pronew]") { + auto stick = make_shared<Dev>(); + connect_and_setup(stick); + authorize(stick); + + { + auto p = get_payload<WriteGeneralConfig>(); + p.enable_user_password = 1; + strcpyT(p.temporary_admin_password, temporary_password); + WriteGeneralConfig::CommandTransaction::run(stick, p); + } + + auto p2 = get_payload<SendOTPData>(); + strcpyT(p2.temporary_admin_password, temporary_password); + p2.setTypeName(); + strcpyT(p2.data, "test name aaa"); + stick10_08::SendOTPData::CommandTransaction::run(stick, p2); + + p2 = get_payload<SendOTPData>(); + strcpyT(p2.temporary_admin_password, temporary_password); + strcpyT(p2.data, RFC_SECRET); + p2.setTypeSecret(); + stick10_08::SendOTPData::CommandTransaction::run(stick, p2); + + auto p = get_payload<WriteToOTPSlot>(); + strcpyT(p.temporary_admin_password, temporary_password); + p.use_8_digits = true; + p.slot_number = 0 + 0x10; + p.slot_counter_or_interval = 0; + stick10_08::WriteToOTPSlot::CommandTransaction::run(stick, p); + + + auto p3 = get_payload<GetHOTP>(); + p3.slot_number = 0 + 0x10; + REQUIRE_THROWS( + GetHOTP::CommandTransaction::run(stick, p3) + ); + strcpyT(p3.temporary_user_password, temporary_password); + auto code_response = GetHOTP::CommandTransaction::run(stick, p3); + REQUIRE(code_response.data().code == 84755224); + +} + +TEST_CASE("check firmware version", "[pronew]") { + auto stick = make_shared<Dev>(); + connect_and_setup(stick); + + auto p = GetStatus::CommandTransaction::run(stick); + REQUIRE(p.data().firmware_version == 8); +} + +TEST_CASE("authorize user TOTP", "[pronew]") { + auto stick = make_shared<Dev>(); + connect_and_setup(stick); + authorize(stick); + + { + auto p = get_payload<WriteGeneralConfig>(); + p.enable_user_password = 1; + strcpyT(p.temporary_admin_password, temporary_password); + WriteGeneralConfig::CommandTransaction::run(stick, p); + } + + auto p2 = get_payload<SendOTPData>(); + strcpyT(p2.temporary_admin_password, temporary_password); + p2.setTypeName(); + strcpyT(p2.data, "test name TOTP"); + stick10_08::SendOTPData::CommandTransaction::run(stick, p2); + + p2 = get_payload<SendOTPData>(); + strcpyT(p2.temporary_admin_password, temporary_password); + strcpyT(p2.data, RFC_SECRET); + p2.setTypeSecret(); + stick10_08::SendOTPData::CommandTransaction::run(stick, p2); + + auto p = get_payload<WriteToOTPSlot>(); + strcpyT(p.temporary_admin_password, temporary_password); + p.use_8_digits = true; + p.slot_number = 0 + 0x20; + p.slot_counter_or_interval = 30; + stick10_08::WriteToOTPSlot::CommandTransaction::run(stick, p); + + auto p_get_totp = get_payload<GetTOTP>(); + p_get_totp.slot_number = 0 + 0x20; + + REQUIRE_THROWS( + GetTOTP::CommandTransaction::run(stick, p_get_totp) + ); + strcpyT(p_get_totp.temporary_user_password, temporary_password); + + auto p_set_time = get_payload<SetTime>(); + p_set_time.reset = 1; + p_set_time.time = 59; + SetTime::CommandTransaction::run(stick, p_set_time); + auto code = GetTOTP::CommandTransaction::run(stick, p_get_totp); + REQUIRE(code.data().code == 94287082); + +} diff --git a/unittest/test_C_API.cpp b/unittest/test_C_API.cpp new file mode 100644 index 0000000..160145b --- /dev/null +++ b/unittest/test_C_API.cpp @@ -0,0 +1,34 @@ +static const int TOO_LONG_STRING = 200; + +#include "catch.hpp" + +#include <iostream> +#include <string> +#include "log.h" +#include "../NK_C_API.h" + +TEST_CASE("C API connect", "[BASIC]") { + auto login = NK_login_auto(); + REQUIRE(login != 0); + NK_logout(); + login = NK_login_auto(); + REQUIRE(login != 0); + NK_logout(); + login = NK_login_auto(); + REQUIRE(login != 0); +} + +TEST_CASE("Check retry count", "[BASIC]") { + REQUIRE(NK_get_admin_retry_count() == 3); + REQUIRE(NK_get_user_retry_count() == 3); +} + +TEST_CASE("Check long strings", "[STANDARD]") { + const char* longPin = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; + const char* pin = "123123123"; + auto result = NK_change_user_PIN(longPin, pin); + REQUIRE(result == TOO_LONG_STRING); + result = NK_change_user_PIN(pin, longPin); + REQUIRE(result == TOO_LONG_STRING); + CAPTURE(result); +}
\ No newline at end of file diff --git a/unittest/test_HOTP.cc b/unittest/test_HOTP.cc new file mode 100644 index 0000000..e6f7d7c --- /dev/null +++ b/unittest/test_HOTP.cc @@ -0,0 +1,101 @@ +#include "catch.hpp" +#include <iostream> +#include "device_proto.h" +#include "log.h" +#include "stick10_commands.h" +#include <cstdlib> +#include "misc.h" + +using namespace std; +using namespace nitrokey::device; +using namespace nitrokey::proto::stick10; +using namespace nitrokey::log; +using namespace nitrokey::misc; + +void hexStringToByte(uint8_t data[], const char* hexString){ + REQUIRE(strlen(hexString)%2==0); + char buf[2]; + for(int i=0; i<strlen(hexString); i++){ + buf[i%2] = hexString[i]; + if (i%2==1){ + data[i/2] = strtoul(buf, NULL, 16) & 0xFF; + } + } +}; + +TEST_CASE("test secret", "[functions]") { + uint8_t slot_secret[21]; + slot_secret[20] = 0; + const char* secretHex = "3132333435363738393031323334353637383930"; + hexStringToByte(slot_secret, secretHex); + CAPTURE(slot_secret); + REQUIRE(strcmp("12345678901234567890",reinterpret_cast<char *>(slot_secret) ) == 0 ); +} + +TEST_CASE("Test HOTP codes according to RFC", "[HOTP]") { + std::shared_ptr<Stick10> stick = make_shared<Stick10>(); + bool connected = stick->connect(); + + REQUIRE(connected == true); + + Log::instance().set_loglevel(Loglevel::DEBUG); + + auto resp = GetStatus::CommandTransaction::run(stick); + + const char * temporary_password = "123456789012345678901234"; + { + auto authreq = get_payload<FirstAuthenticate>(); + strcpy((char *)(authreq.card_password), "12345678"); + strcpy((char *)(authreq.temporary_password), temporary_password); + FirstAuthenticate::CommandTransaction::run(stick, authreq); + } + + //test according to https://tools.ietf.org/html/rfc4226#page-32 + { + auto hwrite = get_payload<WriteToHOTPSlot>(); + hwrite.slot_number = 0x10; + strcpy(reinterpret_cast<char *>(hwrite.slot_name), "rfc4226_lib"); + //strcpy(reinterpret_cast<char *>(hwrite.slot_secret), ""); + const char* secretHex = "3132333435363738393031323334353637383930"; + hexStringToByte(hwrite.slot_secret, secretHex); + + //hwrite.slot_config; //TODO check various configs in separate test cases + //strcpy(reinterpret_cast<char *>(hwrite.slot_token_id), ""); + //strcpy(reinterpret_cast<char *>(hwrite.slot_counter), ""); + + //authorize writehotp first + { + auto auth = get_payload<Authorize>(); + strcpy((char *)(auth.temporary_password), temporary_password); + auth.crc_to_authorize = WriteToHOTPSlot::CommandTransaction::getCRC(hwrite); + Authorize::CommandTransaction::run(stick, auth); + } + + //run hotp command + WriteToHOTPSlot::CommandTransaction::run(stick, hwrite); + + uint32_t codes[] = { + 755224, 287082, 359152, 969429, 338314, + 254676, 287922, 162583, 399871, 520489 + }; + + for( auto code: codes){ + auto gh = get_payload<GetHOTP>(); + gh.slot_number = 0x10; + auto resp = GetHOTP::CommandTransaction::run(stick, gh); + REQUIRE( resp.data().code == code); + } + //checking slot programmed before with nitro-app + /* + for( auto code: codes){ + GetHOTP::CommandTransaction::CommandPayload gh; + gh.slot_number = 0x12; + auto resp = GetHOTP::CommandTransaction::run(stick, gh); + REQUIRE( resp.code == code); + } + */ + } + + + stick->disconnect(); +} diff --git a/unittest/test_command_ids_header.h b/unittest/test_command_ids_header.h new file mode 100644 index 0000000..cd55c8a --- /dev/null +++ b/unittest/test_command_ids_header.h @@ -0,0 +1,41 @@ +#ifndef LIBNITROKEY_TEST_COMMAND_IDS_HEADER_H_H +#define LIBNITROKEY_TEST_COMMAND_IDS_HEADER_H_H + +#define STICK20_CMD_START_VALUE 0x20 +#define STICK20_CMD_ENABLE_CRYPTED_PARI (STICK20_CMD_START_VALUE + 0) +#define STICK20_CMD_DISABLE_CRYPTED_PARI (STICK20_CMD_START_VALUE + 1) +#define STICK20_CMD_ENABLE_HIDDEN_CRYPTED_PARI (STICK20_CMD_START_VALUE + 2) +#define STICK20_CMD_DISABLE_HIDDEN_CRYPTED_PARI (STICK20_CMD_START_VALUE + 3) +#define STICK20_CMD_ENABLE_FIRMWARE_UPDATE (STICK20_CMD_START_VALUE + 4) +#define STICK20_CMD_EXPORT_FIRMWARE_TO_FILE (STICK20_CMD_START_VALUE + 5) +#define STICK20_CMD_GENERATE_NEW_KEYS (STICK20_CMD_START_VALUE + 6) +#define STICK20_CMD_FILL_SD_CARD_WITH_RANDOM_CHARS (STICK20_CMD_START_VALUE + 7) + +#define STICK20_CMD_WRITE_STATUS_DATA (STICK20_CMD_START_VALUE + 8) +#define STICK20_CMD_ENABLE_READONLY_UNCRYPTED_LUN (STICK20_CMD_START_VALUE + 9) +#define STICK20_CMD_ENABLE_READWRITE_UNCRYPTED_LUN (STICK20_CMD_START_VALUE + 10) + +#define STICK20_CMD_SEND_PASSWORD_MATRIX (STICK20_CMD_START_VALUE + 11) +#define STICK20_CMD_SEND_PASSWORD_MATRIX_PINDATA (STICK20_CMD_START_VALUE + 12) +#define STICK20_CMD_SEND_PASSWORD_MATRIX_SETUP (STICK20_CMD_START_VALUE + 13) + +#define STICK20_CMD_GET_DEVICE_STATUS (STICK20_CMD_START_VALUE + 14) +#define STICK20_CMD_SEND_DEVICE_STATUS (STICK20_CMD_START_VALUE + 15) + +#define STICK20_CMD_SEND_HIDDEN_VOLUME_PASSWORD (STICK20_CMD_START_VALUE + 16) +#define STICK20_CMD_SEND_HIDDEN_VOLUME_SETUP (STICK20_CMD_START_VALUE + 17) +#define STICK20_CMD_SEND_PASSWORD (STICK20_CMD_START_VALUE + 18) +#define STICK20_CMD_SEND_NEW_PASSWORD (STICK20_CMD_START_VALUE + 19) +#define STICK20_CMD_CLEAR_NEW_SD_CARD_FOUND (STICK20_CMD_START_VALUE + 20) + +#define STICK20_CMD_SEND_STARTUP (STICK20_CMD_START_VALUE + 21) +#define STICK20_CMD_SEND_CLEAR_STICK_KEYS_NOT_INITIATED (STICK20_CMD_START_VALUE + 22) +#define STICK20_CMD_SEND_LOCK_STICK_HARDWARE (STICK20_CMD_START_VALUE + 23) + +#define STICK20_CMD_PRODUCTION_TEST (STICK20_CMD_START_VALUE + 24) +#define STICK20_CMD_SEND_DEBUG_DATA (STICK20_CMD_START_VALUE + 25) + +#define STICK20_CMD_CHANGE_UPDATE_PIN (STICK20_CMD_START_VALUE + 26) + + +#endif //LIBNITROKEY_TEST_COMMAND_IDS_HEADER_H_H diff --git a/unittest/test_issues.cc b/unittest/test_issues.cc new file mode 100644 index 0000000..63ce678 --- /dev/null +++ b/unittest/test_issues.cc @@ -0,0 +1,78 @@ + +const char * const default_admin_pin = "12345678"; +const char * const default_user_pin = "123456"; +const char * const temporary_password = "123456789012345678901234"; +const char * const RFC_SECRET = "12345678901234567890"; +const char * const hidden_volume_pass = "123456789012345"; + +#include "catch.hpp" + +#include <NitrokeyManager.h> + +using namespace std; +using namespace nitrokey; + + +bool test_36(){ + auto i = NitrokeyManager::instance(); + i->set_loglevel(3); + REQUIRE(i->connect()); + + for (int j = 0; j < 200; ++j) { + i->get_status(); + i->get_status_storage_as_string(); + INFO( "Iteration: " << j); + } + return true; +} + +bool test_31(){ + auto i = NitrokeyManager::instance(); + i->set_loglevel(3); + REQUIRE(i->connect()); + +// i->unlock_encrypted_volume(default_user_pin); +// i->create_hidden_volume(0, 70, 80, hidden_volume_pass); +// i->lock_device(); + + try{ + i->get_password_safe_slot_status(); + } + catch (...){ + //pass + } + + i->get_status_storage(); + i->get_admin_retry_count(); + i->get_status_storage(); + i->get_user_retry_count(); + i->unlock_encrypted_volume(default_user_pin); + i->get_status_storage(); + i->get_password_safe_slot_status(); + i->get_status_storage(); + i->get_user_retry_count(); + i->get_password_safe_slot_status(); + i->get_status(); + i->get_status_storage(); + i->get_admin_retry_count(); + i->get_status(); + i->get_user_retry_count(); + i->unlock_hidden_volume(hidden_volume_pass); + i->get_status_storage(); + i->get_password_safe_slot_status(); + + + return true; +} + +TEST_CASE("issue 31", "[issue]"){ + for(int i=0; i<20; i++){ + REQUIRE(test_31()); + } +} + + + +TEST_CASE("issue 36", "[issue]"){ + REQUIRE(test_36()); +} diff --git a/unittest/test_library.py b/unittest/test_library.py new file mode 100644 index 0000000..7012619 --- /dev/null +++ b/unittest/test_library.py @@ -0,0 +1,68 @@ +import pytest + +from misc import ffi, gs, to_hex, is_pro_rtm_07, is_long_OTP_secret_handled +from constants import DefaultPasswords, DeviceErrorCode, RFC_SECRET, LibraryErrors, bbRFC_SECRET + + +def test_too_long_strings(C): + new_password = b'123123123' + long_string = b'a' * 100 + assert C.NK_change_user_PIN(long_string, new_password) == LibraryErrors.TOO_LONG_STRING + assert C.NK_change_user_PIN(new_password, long_string) == LibraryErrors.TOO_LONG_STRING + assert C.NK_change_admin_PIN(long_string, new_password) == LibraryErrors.TOO_LONG_STRING + assert C.NK_change_admin_PIN(new_password, long_string) == LibraryErrors.TOO_LONG_STRING + assert C.NK_first_authenticate(long_string, DefaultPasswords.ADMIN_TEMP) == LibraryErrors.TOO_LONG_STRING + assert C.NK_erase_totp_slot(0, long_string) == LibraryErrors.TOO_LONG_STRING + digits = False + assert C.NK_write_hotp_slot(1, long_string, bbRFC_SECRET, 0, digits, False, False, b"", + DefaultPasswords.ADMIN_TEMP) == LibraryErrors.TOO_LONG_STRING + assert C.NK_write_hotp_slot(1, b'long_test', bbRFC_SECRET, 0, digits, False, False, b"", + long_string) == LibraryErrors.TOO_LONG_STRING + assert gs(C.NK_get_hotp_code_PIN(0, long_string)) == b"" + assert C.NK_get_last_command_status() == LibraryErrors.TOO_LONG_STRING + + +def test_invalid_slot(C): + invalid_slot = 255 + assert C.NK_erase_totp_slot(invalid_slot, b'some password') == LibraryErrors.INVALID_SLOT + assert C.NK_write_hotp_slot(invalid_slot, b'long_test', bbRFC_SECRET, 0, False, False, False, b"", + b'aaa') == LibraryErrors.INVALID_SLOT + assert gs(C.NK_get_hotp_code_PIN(invalid_slot, b'some password')) == b"" + assert C.NK_get_last_command_status() == LibraryErrors.INVALID_SLOT + assert C.NK_erase_password_safe_slot(invalid_slot) == LibraryErrors.INVALID_SLOT + assert C.NK_enable_password_safe(DefaultPasswords.USER) == DeviceErrorCode.STATUS_OK + assert gs(C.NK_get_password_safe_slot_name(invalid_slot)) == b'' + assert C.NK_get_last_command_status() == LibraryErrors.INVALID_SLOT + assert gs(C.NK_get_password_safe_slot_login(invalid_slot)) == b'' + assert C.NK_get_last_command_status() == LibraryErrors.INVALID_SLOT + + +@pytest.mark.parametrize("invalid_hex_string", + ['text', '00 ', '0xff', 'zzzzzzzzzzzz', 'fff', 'f' * 257, 'f' * 258]) +def test_invalid_secret_hex_string_for_OTP_write(C, invalid_hex_string): + """ + Tests for invalid secret hex string during writing to OTP slot. Invalid strings are not hexadecimal number, + empty or longer than 255 characters. + """ + invalid_hex_string = invalid_hex_string.encode('ascii') + assert C.NK_first_authenticate(DefaultPasswords.ADMIN, DefaultPasswords.ADMIN_TEMP) == DeviceErrorCode.STATUS_OK + assert C.NK_write_hotp_slot(1, b'slot_name', invalid_hex_string, 0, True, False, False, b'', + DefaultPasswords.ADMIN_TEMP) == LibraryErrors.INVALID_HEX_STRING + assert C.NK_write_totp_slot(1, b'python_test', invalid_hex_string, 30, True, False, False, b"", + DefaultPasswords.ADMIN_TEMP) == LibraryErrors.INVALID_HEX_STRING + +def test_warning_binary_bigger_than_secret_buffer(C): + invalid_hex_string = to_hex('1234567890') * 3 + invalid_hex_string = invalid_hex_string.encode('ascii') + if is_long_OTP_secret_handled(C): + invalid_hex_string *= 2 + assert C.NK_write_hotp_slot(1, b'slot_name', invalid_hex_string, 0, True, False, False, b'', + DefaultPasswords.ADMIN_TEMP) == LibraryErrors.TARGET_BUFFER_SIZE_SMALLER_THAN_SOURCE + + +@pytest.mark.skip(reason='Experimental') +def test_clear(C): + d = 'asdasdasd' + print(d) + C.clear_password(d) + print(d)
\ No newline at end of file diff --git a/unittest/test_offline.cc b/unittest/test_offline.cc new file mode 100644 index 0000000..58c7555 --- /dev/null +++ b/unittest/test_offline.cc @@ -0,0 +1,141 @@ +#include "catch.hpp" +#include <NitrokeyManager.h> +#include <memory> +#include "../NK_C_API.h" + +using namespace nitrokey::proto; +using namespace nitrokey::device; + +using namespace std; +using namespace nitrokey; + +//This test suite assumes no Pro or Storage devices are connected + +TEST_CASE("Return false on no device connected", "[fast]") { + INFO("This test case assumes no Pro or Storage devices are connected"); + auto stick = make_shared<Stick20>(); + bool connected = true; + REQUIRE_NOTHROW(connected = stick->connect()); + REQUIRE_FALSE(connected); + + auto stick_pro = make_shared<Stick10>(); + REQUIRE_NOTHROW(connected = stick_pro->connect()); + REQUIRE_FALSE(connected); + + + auto i = NitrokeyManager::instance(); + REQUIRE_NOTHROW(connected = i->connect()); + REQUIRE_FALSE(connected); + REQUIRE_FALSE(i->is_connected()); + REQUIRE_FALSE(i->disconnect()); + REQUIRE_FALSE(i->could_current_device_be_enumerated()); + + + int C_connected = 1; + REQUIRE_NOTHROW(C_connected = NK_login_auto()); + REQUIRE(0 == C_connected); +} + +TEST_CASE("Test C++ side behaviour in offline", "[fast]") { + auto i = NitrokeyManager::instance(); + + string serial_number; + REQUIRE_NOTHROW (serial_number = i->get_serial_number()); + REQUIRE(serial_number.empty()); + + REQUIRE_THROWS_AS( + i->get_status(), DeviceNotConnected + ); + + REQUIRE_THROWS_AS( + i->get_HOTP_code(0xFF, ""), InvalidSlotException + ); + + REQUIRE_THROWS_AS( + i->get_TOTP_code(0xFF, ""), InvalidSlotException + ); + + REQUIRE_THROWS_AS( + i->erase_hotp_slot(0xFF, ""), InvalidSlotException + ); + + REQUIRE_THROWS_AS( + i->erase_totp_slot(0xFF, ""), InvalidSlotException + ); + + REQUIRE_THROWS_AS( + i->get_totp_slot_name(0xFF), InvalidSlotException + ); + + REQUIRE_THROWS_AS( + i->get_hotp_slot_name(0xFF), InvalidSlotException + ); + + REQUIRE_THROWS_AS( + i->first_authenticate("123123", "123123"), DeviceNotConnected + ); + + REQUIRE_THROWS_AS( + i->get_connected_device_model(), DeviceNotConnected + ); + + REQUIRE_THROWS_AS( + i->clear_new_sd_card_warning("123123"), DeviceNotConnected + ); + +} + + +TEST_CASE("Test helper function - hex_string_to_byte", "[fast]") { + using namespace nitrokey::misc; + std::vector<uint8_t> v; + REQUIRE_NOTHROW(v = hex_string_to_byte("00112233445566")); + const uint8_t test_data[] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66}; + REQUIRE(v.size() == sizeof(test_data)); + for (int i = 0; i < v.size(); ++i) { + INFO("Position i: " << i); + REQUIRE(v.data()[i] == test_data[i]); + } +} + +#include "test_command_ids_header.h" +TEST_CASE("Test device commands ids", "[fast]") { +// Make sure CommandID values are in sync with firmware's header + +// REQUIRE(STICK20_CMD_START_VALUE == static_cast<uint8_t>(CommandID::START_VALUE)); + REQUIRE(STICK20_CMD_ENABLE_CRYPTED_PARI == static_cast<uint8_t>(CommandID::ENABLE_CRYPTED_PARI)); + REQUIRE(STICK20_CMD_DISABLE_CRYPTED_PARI == static_cast<uint8_t>(CommandID::DISABLE_CRYPTED_PARI)); + REQUIRE(STICK20_CMD_ENABLE_HIDDEN_CRYPTED_PARI == static_cast<uint8_t>(CommandID::ENABLE_HIDDEN_CRYPTED_PARI)); + REQUIRE(STICK20_CMD_DISABLE_HIDDEN_CRYPTED_PARI == static_cast<uint8_t>(CommandID::DISABLE_HIDDEN_CRYPTED_PARI)); + REQUIRE(STICK20_CMD_ENABLE_FIRMWARE_UPDATE == static_cast<uint8_t>(CommandID::ENABLE_FIRMWARE_UPDATE)); + REQUIRE(STICK20_CMD_EXPORT_FIRMWARE_TO_FILE == static_cast<uint8_t>(CommandID::EXPORT_FIRMWARE_TO_FILE)); + REQUIRE(STICK20_CMD_GENERATE_NEW_KEYS == static_cast<uint8_t>(CommandID::GENERATE_NEW_KEYS)); + REQUIRE(STICK20_CMD_FILL_SD_CARD_WITH_RANDOM_CHARS == static_cast<uint8_t>(CommandID::FILL_SD_CARD_WITH_RANDOM_CHARS)); + + REQUIRE(STICK20_CMD_WRITE_STATUS_DATA == static_cast<uint8_t>(CommandID::WRITE_STATUS_DATA)); + REQUIRE(STICK20_CMD_ENABLE_READONLY_UNCRYPTED_LUN == static_cast<uint8_t>(CommandID::ENABLE_READONLY_UNCRYPTED_LUN)); + REQUIRE(STICK20_CMD_ENABLE_READWRITE_UNCRYPTED_LUN == static_cast<uint8_t>(CommandID::ENABLE_READWRITE_UNCRYPTED_LUN)); + + REQUIRE(STICK20_CMD_SEND_PASSWORD_MATRIX == static_cast<uint8_t>(CommandID::SEND_PASSWORD_MATRIX)); + REQUIRE(STICK20_CMD_SEND_PASSWORD_MATRIX_PINDATA == static_cast<uint8_t>(CommandID::SEND_PASSWORD_MATRIX_PINDATA)); + REQUIRE(STICK20_CMD_SEND_PASSWORD_MATRIX_SETUP == static_cast<uint8_t>(CommandID::SEND_PASSWORD_MATRIX_SETUP)); + + REQUIRE(STICK20_CMD_GET_DEVICE_STATUS == static_cast<uint8_t>(CommandID::GET_DEVICE_STATUS)); + REQUIRE(STICK20_CMD_SEND_DEVICE_STATUS == static_cast<uint8_t>(CommandID::SEND_DEVICE_STATUS)); + + REQUIRE(STICK20_CMD_SEND_HIDDEN_VOLUME_PASSWORD == static_cast<uint8_t>(CommandID::SEND_HIDDEN_VOLUME_PASSWORD)); + REQUIRE(STICK20_CMD_SEND_HIDDEN_VOLUME_SETUP == static_cast<uint8_t>(CommandID::SEND_HIDDEN_VOLUME_SETUP)); + REQUIRE(STICK20_CMD_SEND_PASSWORD == static_cast<uint8_t>(CommandID::SEND_PASSWORD)); + REQUIRE(STICK20_CMD_SEND_NEW_PASSWORD == static_cast<uint8_t>(CommandID::SEND_NEW_PASSWORD)); + REQUIRE(STICK20_CMD_CLEAR_NEW_SD_CARD_FOUND == static_cast<uint8_t>(CommandID::CLEAR_NEW_SD_CARD_FOUND)); + + REQUIRE(STICK20_CMD_SEND_STARTUP == static_cast<uint8_t>(CommandID::SEND_STARTUP)); + REQUIRE(STICK20_CMD_SEND_CLEAR_STICK_KEYS_NOT_INITIATED == static_cast<uint8_t>(CommandID::SEND_CLEAR_STICK_KEYS_NOT_INITIATED)); + REQUIRE(STICK20_CMD_SEND_LOCK_STICK_HARDWARE == static_cast<uint8_t>(CommandID::SEND_LOCK_STICK_HARDWARE)); + + REQUIRE(STICK20_CMD_PRODUCTION_TEST == static_cast<uint8_t>(CommandID::PRODUCTION_TEST)); + REQUIRE(STICK20_CMD_SEND_DEBUG_DATA == static_cast<uint8_t>(CommandID::SEND_DEBUG_DATA)); + + REQUIRE(STICK20_CMD_CHANGE_UPDATE_PIN == static_cast<uint8_t>(CommandID::CHANGE_UPDATE_PIN)); + +} diff --git a/unittest/test_pro.py b/unittest/test_pro.py new file mode 100644 index 0000000..830946d --- /dev/null +++ b/unittest/test_pro.py @@ -0,0 +1,853 @@ +import pytest + +from conftest import skip_if_device_version_lower_than +from constants import DefaultPasswords, DeviceErrorCode, RFC_SECRET, bb, bbRFC_SECRET +from misc import ffi, gs, wait, cast_pointer_to_tuple +from misc import is_pro_rtm_07, is_pro_rtm_08, is_storage + +@pytest.mark.lock_device +@pytest.mark.PWS +def test_enable_password_safe(C): + """ + All Password Safe tests depend on AES keys being initialized. They will fail otherwise. + """ + assert C.NK_lock_device() == DeviceErrorCode.STATUS_OK + assert C.NK_enable_password_safe(b'wrong_password') == DeviceErrorCode.WRONG_PASSWORD + assert C.NK_enable_password_safe(DefaultPasswords.USER) == DeviceErrorCode.STATUS_OK + +@pytest.mark.lock_device +@pytest.mark.PWS +def test_write_password_safe_slot(C): + assert C.NK_lock_device() == DeviceErrorCode.STATUS_OK + assert C.NK_write_password_safe_slot(0, b'slotname1', b'login1', b'pass1') == DeviceErrorCode.STATUS_NOT_AUTHORIZED + assert C.NK_enable_password_safe(DefaultPasswords.USER) == DeviceErrorCode.STATUS_OK + assert C.NK_write_password_safe_slot(0, b'slotname1', b'login1', b'pass1') == DeviceErrorCode.STATUS_OK + + +@pytest.mark.lock_device +@pytest.mark.PWS +@pytest.mark.slowtest +def test_write_all_password_safe_slots_and_read_10_times(C): + def fill(s, wid): + assert wid >= len(s) + numbers = '1234567890'*4 + s += numbers[:wid-len(s)] + assert len(s) == wid + return bb(s) + + def get_pass(suffix): + return fill('pass' + suffix, 20) + + def get_loginname(suffix): + return fill('login' + suffix, 32) + + def get_slotname(suffix): + return fill('slotname' + suffix, 11) + + assert C.NK_lock_device() == DeviceErrorCode.STATUS_OK + assert C.NK_enable_password_safe(DefaultPasswords.USER) == DeviceErrorCode.STATUS_OK + PWS_slot_count = 16 + for i in range(0, PWS_slot_count): + iss = str(i) + assert C.NK_write_password_safe_slot(i, + get_slotname(iss), get_loginname(iss), + get_pass(iss)) == DeviceErrorCode.STATUS_OK + + for j in range(0, 10): + for i in range(0, PWS_slot_count): + iss = str(i) + assert gs(C.NK_get_password_safe_slot_name(i)) == get_slotname(iss) + assert gs(C.NK_get_password_safe_slot_login(i)) == get_loginname(iss) + assert gs(C.NK_get_password_safe_slot_password(i)) == get_pass(iss) + + +@pytest.mark.lock_device +@pytest.mark.PWS +@pytest.mark.slowtest +@pytest.mark.xfail(reason="This test should be run directly after test_write_all_password_safe_slots_and_read_10_times") +def test_read_all_password_safe_slots_10_times(C): + def fill(s, wid): + assert wid >= len(s) + numbers = '1234567890'*4 + s += numbers[:wid-len(s)] + assert len(s) == wid + return bb(s) + + def get_pass(suffix): + return fill('pass' + suffix, 20) + + def get_loginname(suffix): + return fill('login' + suffix, 32) + + def get_slotname(suffix): + return fill('slotname' + suffix, 11) + + assert C.NK_lock_device() == DeviceErrorCode.STATUS_OK + assert C.NK_enable_password_safe(DefaultPasswords.USER) == DeviceErrorCode.STATUS_OK + PWS_slot_count = 16 + + for j in range(0, 10): + for i in range(0, PWS_slot_count): + iss = str(i) + assert gs(C.NK_get_password_safe_slot_name(i)) == get_slotname(iss) + assert gs(C.NK_get_password_safe_slot_login(i)) == get_loginname(iss) + assert gs(C.NK_get_password_safe_slot_password(i)) == get_pass(iss) + + +@pytest.mark.lock_device +@pytest.mark.PWS +def test_get_password_safe_slot_name(C): + assert C.NK_enable_password_safe(DefaultPasswords.USER) == DeviceErrorCode.STATUS_OK + assert C.NK_write_password_safe_slot(0, b'slotname1', b'login1', b'pass1') == DeviceErrorCode.STATUS_OK + assert C.NK_lock_device() == DeviceErrorCode.STATUS_OK + assert gs(C.NK_get_password_safe_slot_name(0)) == b'' + assert C.NK_get_last_command_status() == DeviceErrorCode.STATUS_NOT_AUTHORIZED + + assert C.NK_enable_password_safe(DefaultPasswords.USER) == DeviceErrorCode.STATUS_OK + assert gs(C.NK_get_password_safe_slot_name(0)) == b'slotname1' + assert C.NK_get_last_command_status() == DeviceErrorCode.STATUS_OK + + +@pytest.mark.PWS +def test_get_password_safe_slot_login_password(C): + assert C.NK_enable_password_safe(DefaultPasswords.USER) == DeviceErrorCode.STATUS_OK + assert C.NK_write_password_safe_slot(0, b'slotname1', b'login1', b'pass1') == DeviceErrorCode.STATUS_OK + slot_login = C.NK_get_password_safe_slot_login(0) + assert C.NK_get_last_command_status() == DeviceErrorCode.STATUS_OK + assert gs(slot_login) == b'login1' + slot_password = gs(C.NK_get_password_safe_slot_password(0)) + assert C.NK_get_last_command_status() == DeviceErrorCode.STATUS_OK + assert slot_password == b'pass1' + + +@pytest.mark.PWS +def test_erase_password_safe_slot(C): + assert C.NK_enable_password_safe(DefaultPasswords.USER) == DeviceErrorCode.STATUS_OK + assert C.NK_erase_password_safe_slot(0) == DeviceErrorCode.STATUS_OK + assert gs(C.NK_get_password_safe_slot_name(0)) == b'' + assert C.NK_get_last_command_status() == DeviceErrorCode.STATUS_OK # TODO CHECK shouldn't this be DeviceErrorCode.NOT_PROGRAMMED ? + + +@pytest.mark.PWS +def test_password_safe_slot_status(C): + assert C.NK_enable_password_safe(DefaultPasswords.USER) == DeviceErrorCode.STATUS_OK + assert C.NK_erase_password_safe_slot(0) == DeviceErrorCode.STATUS_OK + assert C.NK_write_password_safe_slot(1, b'slotname2', b'login2', b'pass2') == DeviceErrorCode.STATUS_OK + safe_slot_status = C.NK_get_password_safe_slot_status() + assert C.NK_get_last_command_status() == DeviceErrorCode.STATUS_OK + is_slot_programmed = list(ffi.cast("uint8_t [16]", safe_slot_status)[0:16]) + print((is_slot_programmed, len(is_slot_programmed))) + assert is_slot_programmed[0] == 0 + assert is_slot_programmed[1] == 1 + + +@pytest.mark.aes +def test_issue_device_locks_on_second_key_generation_in_sequence(C): + if is_pro_rtm_07(C) or is_pro_rtm_08(C): + pytest.skip("issue to register: device locks up " + "after below commands sequence (reinsertion fixes), skipping for now") + assert C.NK_build_aes_key(DefaultPasswords.ADMIN) == DeviceErrorCode.STATUS_OK + assert C.NK_build_aes_key(DefaultPasswords.ADMIN) == DeviceErrorCode.STATUS_OK + + +@pytest.mark.aes +def test_regenerate_aes_key(C): + assert C.NK_first_authenticate(DefaultPasswords.ADMIN, DefaultPasswords.ADMIN_TEMP) == DeviceErrorCode.STATUS_OK + assert C.NK_build_aes_key(DefaultPasswords.ADMIN) == DeviceErrorCode.STATUS_OK + assert C.NK_enable_password_safe(DefaultPasswords.USER) == DeviceErrorCode.STATUS_OK + + +@pytest.mark.lock_device +@pytest.mark.aes +@pytest.mark.factory_reset +def test_enable_password_safe_after_factory_reset(C): + assert C.NK_lock_device() == DeviceErrorCode.STATUS_OK + if is_storage(C): + # for some reason storage likes to be authenticated before reset (to investigate) + assert C.NK_first_authenticate(DefaultPasswords.ADMIN, DefaultPasswords.ADMIN_TEMP) == DeviceErrorCode.STATUS_OK + assert C.NK_factory_reset(DefaultPasswords.ADMIN) == DeviceErrorCode.STATUS_OK + wait(10) + if is_storage(C): + assert C.NK_clear_new_sd_card_warning(DefaultPasswords.ADMIN) == DeviceErrorCode.STATUS_OK + enable_password_safe_result = C.NK_enable_password_safe(DefaultPasswords.USER) + assert enable_password_safe_result == DeviceErrorCode.STATUS_AES_DEC_FAILED \ + or is_storage(C) and enable_password_safe_result == DeviceErrorCode.WRONG_PASSWORD + assert C.NK_build_aes_key(DefaultPasswords.ADMIN) == DeviceErrorCode.STATUS_OK + assert C.NK_enable_password_safe(DefaultPasswords.USER) == DeviceErrorCode.STATUS_OK + +@pytest.mark.lock_device +@pytest.mark.aes +@pytest.mark.xfail(reason="NK Pro firmware bug: regenerating AES key command not always results in cleared slot data") +def test_destroy_password_safe(C): + """ + Sometimes fails on NK Pro - slot name is not cleared ergo key generation has not succeed despite the success result + returned from the device + """ + assert C.NK_enable_password_safe(DefaultPasswords.USER) == DeviceErrorCode.STATUS_OK + # write password safe slot + assert C.NK_write_password_safe_slot(0, b'slotname1', b'login1', b'pass1') == DeviceErrorCode.STATUS_OK + # read slot + assert gs(C.NK_get_password_safe_slot_name(0)) == b'slotname1' + assert C.NK_get_last_command_status() == DeviceErrorCode.STATUS_OK + slot_login = C.NK_get_password_safe_slot_login(0) + assert C.NK_get_last_command_status() == DeviceErrorCode.STATUS_OK + assert gs(slot_login) == b'login1' + # destroy password safe by regenerating aes key + assert C.NK_lock_device() == DeviceErrorCode.STATUS_OK + + assert C.NK_first_authenticate(DefaultPasswords.ADMIN, DefaultPasswords.ADMIN_TEMP) == DeviceErrorCode.STATUS_OK + assert C.NK_build_aes_key(DefaultPasswords.ADMIN) == DeviceErrorCode.STATUS_OK + assert C.NK_lock_device() == DeviceErrorCode.STATUS_OK + assert C.NK_enable_password_safe(DefaultPasswords.USER) == DeviceErrorCode.STATUS_OK + + assert gs(C.NK_get_password_safe_slot_name(0)) != b'slotname1' + assert C.NK_get_last_command_status() == DeviceErrorCode.STATUS_OK + + # check was slot status cleared + safe_slot_status = C.NK_get_password_safe_slot_status() + assert C.NK_get_last_command_status() == DeviceErrorCode.STATUS_OK + is_slot_programmed = list(ffi.cast("uint8_t [16]", safe_slot_status)[0:16]) + assert is_slot_programmed[0] == 0 + + +@pytest.mark.aes +def test_is_AES_supported(C): + if is_storage(C): + pytest.skip("Storage does not implement this command") + assert C.NK_is_AES_supported(b'wrong password') != 1 + assert C.NK_get_last_command_status() == DeviceErrorCode.WRONG_PASSWORD + assert C.NK_is_AES_supported(DefaultPasswords.USER) == 1 + assert C.NK_get_last_command_status() == DeviceErrorCode.STATUS_OK + + +@pytest.mark.pin +def test_admin_PIN_change(C): + new_password = b'123123123' + assert C.NK_change_admin_PIN(b'wrong_password', new_password) == DeviceErrorCode.WRONG_PASSWORD + assert C.NK_change_admin_PIN(DefaultPasswords.ADMIN, new_password) == DeviceErrorCode.STATUS_OK + assert C.NK_change_admin_PIN(new_password, DefaultPasswords.ADMIN) == DeviceErrorCode.STATUS_OK + + +@pytest.mark.pin +def test_user_PIN_change(C): + new_password = b'123123123' + assert C.NK_change_user_PIN(b'wrong_password', new_password) == DeviceErrorCode.WRONG_PASSWORD + assert C.NK_change_user_PIN(DefaultPasswords.USER, new_password) == DeviceErrorCode.STATUS_OK + assert C.NK_change_user_PIN(new_password, DefaultPasswords.USER) == DeviceErrorCode.STATUS_OK + + +@pytest.mark.lock_device +@pytest.mark.pin +def test_admin_retry_counts(C): + default_admin_retry_count = 3 + assert C.NK_lock_device() == DeviceErrorCode.STATUS_OK + assert C.NK_get_admin_retry_count() == default_admin_retry_count + assert C.NK_change_admin_PIN(b'wrong_password', DefaultPasswords.ADMIN_TEMP) == DeviceErrorCode.WRONG_PASSWORD + assert C.NK_get_admin_retry_count() == default_admin_retry_count - 1 + assert C.NK_change_admin_PIN(DefaultPasswords.ADMIN, DefaultPasswords.ADMIN) == DeviceErrorCode.STATUS_OK + assert C.NK_get_admin_retry_count() == default_admin_retry_count + + +@pytest.mark.lock_device +@pytest.mark.pin +def test_user_retry_counts_change_PIN(C): + assert C.NK_change_user_PIN(DefaultPasswords.USER, DefaultPasswords.USER) == DeviceErrorCode.STATUS_OK + wrong_password = b'wrong_password' + default_user_retry_count = 3 + assert C.NK_lock_device() == DeviceErrorCode.STATUS_OK + assert C.NK_get_user_retry_count() == default_user_retry_count + assert C.NK_change_user_PIN(wrong_password, wrong_password) == DeviceErrorCode.WRONG_PASSWORD + assert C.NK_get_user_retry_count() == default_user_retry_count - 1 + assert C.NK_change_user_PIN(DefaultPasswords.USER, DefaultPasswords.USER) == DeviceErrorCode.STATUS_OK + assert C.NK_get_user_retry_count() == default_user_retry_count + + +@pytest.mark.lock_device +@pytest.mark.pin +def test_user_retry_counts_PWSafe(C): + default_user_retry_count = 3 + assert C.NK_lock_device() == DeviceErrorCode.STATUS_OK + assert C.NK_get_user_retry_count() == default_user_retry_count + assert C.NK_enable_password_safe(b'wrong_password') == DeviceErrorCode.WRONG_PASSWORD + assert C.NK_get_user_retry_count() == default_user_retry_count - 1 + assert C.NK_enable_password_safe(DefaultPasswords.USER) == DeviceErrorCode.STATUS_OK + assert C.NK_get_user_retry_count() == default_user_retry_count + + +@pytest.mark.pin +def test_unlock_user_password(C): + default_user_retry_count = 3 + default_admin_retry_count = 3 + new_password = b'123123123' + assert C.NK_get_user_retry_count() == default_user_retry_count + assert C.NK_change_user_PIN(b'wrong_password', new_password) == DeviceErrorCode.WRONG_PASSWORD + assert C.NK_change_user_PIN(b'wrong_password', new_password) == DeviceErrorCode.WRONG_PASSWORD + assert C.NK_change_user_PIN(b'wrong_password', new_password) == DeviceErrorCode.WRONG_PASSWORD + assert C.NK_get_user_retry_count() == default_user_retry_count - 3 + assert C.NK_get_admin_retry_count() == default_admin_retry_count + + assert C.NK_unlock_user_password(b'wrong password', DefaultPasswords.USER) == DeviceErrorCode.WRONG_PASSWORD + assert C.NK_get_admin_retry_count() == default_admin_retry_count - 1 + assert C.NK_unlock_user_password(DefaultPasswords.ADMIN, DefaultPasswords.USER) == DeviceErrorCode.STATUS_OK + assert C.NK_get_user_retry_count() == default_user_retry_count + assert C.NK_get_admin_retry_count() == default_admin_retry_count + + +@pytest.mark.pin +def test_admin_auth(C): + assert C.NK_first_authenticate(b'wrong_password', DefaultPasswords.ADMIN_TEMP) == DeviceErrorCode.WRONG_PASSWORD + assert C.NK_first_authenticate(DefaultPasswords.ADMIN, DefaultPasswords.ADMIN_TEMP) == DeviceErrorCode.STATUS_OK + + +@pytest.mark.pin +def test_user_auth(C): + assert C.NK_user_authenticate(b'wrong_password', DefaultPasswords.USER_TEMP) == DeviceErrorCode.WRONG_PASSWORD + assert C.NK_user_authenticate(DefaultPasswords.USER, DefaultPasswords.USER_TEMP) == DeviceErrorCode.STATUS_OK + + +@pytest.mark.otp +def check_HOTP_RFC_codes(C, func, prep=None, use_8_digits=False): + """ + # https://tools.ietf.org/html/rfc4226#page-32 + """ + assert C.NK_first_authenticate(DefaultPasswords.ADMIN, DefaultPasswords.ADMIN_TEMP) == DeviceErrorCode.STATUS_OK + assert C.NK_write_hotp_slot(1, b'python_test', bbRFC_SECRET, 0, use_8_digits, False, False, b'', + DefaultPasswords.ADMIN_TEMP) == DeviceErrorCode.STATUS_OK + test_data = [ + 1284755224, 1094287082, 137359152, 1726969429, 1640338314, 868254676, 1918287922, 82162583, 673399871, + 645520489, + ] + for code in test_data: + if prep: + prep() + r = func(1) + code = str(code)[-8:] if use_8_digits else str(code)[-6:] + assert bb(code) == r + + +@pytest.mark.otp +@pytest.mark.parametrize("use_8_digits", [False, True, ]) +@pytest.mark.parametrize("use_pin_protection", [False, True, ]) +def test_HOTP_RFC_use8digits_usepin(C, use_8_digits, use_pin_protection): + assert C.NK_first_authenticate(DefaultPasswords.ADMIN, DefaultPasswords.ADMIN_TEMP) == DeviceErrorCode.STATUS_OK + assert C.NK_write_config(255, 255, 255, use_pin_protection, not use_pin_protection, + DefaultPasswords.ADMIN_TEMP) == DeviceErrorCode.STATUS_OK + if use_pin_protection: + check_HOTP_RFC_codes(C, + lambda x: gs(C.NK_get_hotp_code_PIN(x, DefaultPasswords.USER_TEMP)), + lambda: C.NK_user_authenticate(DefaultPasswords.USER, DefaultPasswords.USER_TEMP), + use_8_digits=use_8_digits) + else: + check_HOTP_RFC_codes(C, lambda x: gs(C.NK_get_hotp_code(x)), use_8_digits=use_8_digits) + + +@pytest.mark.otp +def test_HOTP_token(C): + """ + Check HOTP routine with written token ID to slot. + """ + use_pin_protection = False + assert C.NK_first_authenticate(DefaultPasswords.ADMIN, DefaultPasswords.ADMIN_TEMP) == DeviceErrorCode.STATUS_OK + assert C.NK_write_config(255, 255, 255, use_pin_protection, not use_pin_protection, + DefaultPasswords.ADMIN_TEMP) == DeviceErrorCode.STATUS_OK + assert C.NK_first_authenticate(DefaultPasswords.ADMIN, DefaultPasswords.ADMIN_TEMP) == DeviceErrorCode.STATUS_OK + token_ID = b"AAV100000022" + assert C.NK_write_hotp_slot(1, b'python_test', bbRFC_SECRET, 0, False, False, True, token_ID, + DefaultPasswords.ADMIN_TEMP) == DeviceErrorCode.STATUS_OK + for i in range(5): + hotp_code = gs(C.NK_get_hotp_code(1)) + assert hotp_code != b'' + assert C.NK_get_last_command_status() == DeviceErrorCode.STATUS_OK + + +@pytest.mark.otp +def test_HOTP_counters(C): + """ + # https://tools.ietf.org/html/rfc4226#page-32 + """ + use_pin_protection = False + assert C.NK_first_authenticate(DefaultPasswords.ADMIN, DefaultPasswords.ADMIN_TEMP) == DeviceErrorCode.STATUS_OK + assert C.NK_write_config(255, 255, 255, use_pin_protection, not use_pin_protection, + DefaultPasswords.ADMIN_TEMP) == DeviceErrorCode.STATUS_OK + use_8_digits = True + HOTP_test_data = [ + 1284755224, 1094287082, 137359152, 1726969429, 1640338314, + 868254676, 1918287922, 82162583, 673399871, 645520489, + ] + slot_number = 1 + for counter, code in enumerate(HOTP_test_data): + assert C.NK_first_authenticate(DefaultPasswords.ADMIN, DefaultPasswords.ADMIN_TEMP) == DeviceErrorCode.STATUS_OK + assert C.NK_write_hotp_slot(slot_number, b'python_test', bbRFC_SECRET, counter, use_8_digits, False, False, b'', + DefaultPasswords.ADMIN_TEMP) == DeviceErrorCode.STATUS_OK + r = gs(C.NK_get_hotp_code(slot_number)) + code = str(code)[-8:] if use_8_digits else str(code)[-6:] + assert bb(code) == r + + +INT32_MAX = 2 ** 31 - 1 +@pytest.mark.otp +def test_HOTP_64bit_counter(C): + if is_storage(C): + pytest.xfail('bug in NK Storage HOTP firmware - counter is set with a 8 digits string, ' + 'however int32max takes 10 digits to be written') + oath = pytest.importorskip("oath") + lib_at = lambda t: bb(oath.hotp(RFC_SECRET, t, format='dec6')) + PIN_protection = False + use_8_digits = False + slot_number = 1 + assert C.NK_first_authenticate(DefaultPasswords.ADMIN, DefaultPasswords.ADMIN_TEMP) == DeviceErrorCode.STATUS_OK + assert C.NK_write_config(255, 255, 255, PIN_protection, not PIN_protection, + DefaultPasswords.ADMIN_TEMP) == DeviceErrorCode.STATUS_OK + dev_res = [] + lib_res = [] + for t in range(INT32_MAX - 5, INT32_MAX + 5, 1): + assert C.NK_first_authenticate(DefaultPasswords.ADMIN, DefaultPasswords.ADMIN_TEMP) == DeviceErrorCode.STATUS_OK + assert C.NK_write_hotp_slot(slot_number, b'python_test', bbRFC_SECRET, t, use_8_digits, False, False, b'', + DefaultPasswords.ADMIN_TEMP) == DeviceErrorCode.STATUS_OK + code_device = gs(C.NK_get_hotp_code(slot_number)) + dev_res += (t, code_device) + lib_res += (t, lib_at(t)) + assert dev_res == lib_res + + +@pytest.mark.otp +def test_TOTP_64bit_time(C): + if is_storage(C): + pytest.xfail('bug in NK Storage TOTP firmware') + oath = pytest.importorskip("oath") + T = 1 + lib_at = lambda t: bb(oath.totp(RFC_SECRET, t=t)) + PIN_protection = False + slot_number = 1 + assert C.NK_first_authenticate(DefaultPasswords.ADMIN, DefaultPasswords.ADMIN_TEMP) == DeviceErrorCode.STATUS_OK + assert C.NK_write_config(255, 255, 255, PIN_protection, not PIN_protection, + DefaultPasswords.ADMIN_TEMP) == DeviceErrorCode.STATUS_OK + assert C.NK_first_authenticate(DefaultPasswords.ADMIN, DefaultPasswords.ADMIN_TEMP) == DeviceErrorCode.STATUS_OK + assert C.NK_write_totp_slot(slot_number, b'python_test', bbRFC_SECRET, 30, False, False, False, b'', + DefaultPasswords.ADMIN_TEMP) == DeviceErrorCode.STATUS_OK + dev_res = [] + lib_res = [] + for t in range(INT32_MAX - 5, INT32_MAX + 5, 1): + assert C.NK_first_authenticate(DefaultPasswords.ADMIN, DefaultPasswords.ADMIN_TEMP) == DeviceErrorCode.STATUS_OK + assert C.NK_totp_set_time(t) == DeviceErrorCode.STATUS_OK + code_device = gs((C.NK_get_totp_code(slot_number, T, 0, 30))) + dev_res += (t, code_device) + lib_res += (t, lib_at(t)) + assert dev_res == lib_res + + +@pytest.mark.otp +@pytest.mark.xfail(reason="NK Pro: Test fails in 50% of cases due to test vectors set 1 second before interval count change" + "Here time is changed on seconds side only and miliseconds part is not being reset apparently" + "This results in available time to test of half a second on average, thus 50% failed cases" + "With disabled two first test vectors test passess 10/10 times" + "Fail may also occurs on NK Storage with lower occurrency since it needs less time to execute " + "commands") +@pytest.mark.parametrize("PIN_protection", [False, True, ]) +def test_TOTP_RFC_usepin(C, PIN_protection): + slot_number = 1 + assert C.NK_first_authenticate(DefaultPasswords.ADMIN, DefaultPasswords.ADMIN_TEMP) == DeviceErrorCode.STATUS_OK + assert C.NK_write_config(255, 255, 255, PIN_protection, not PIN_protection, + DefaultPasswords.ADMIN_TEMP) == DeviceErrorCode.STATUS_OK + # test according to https://tools.ietf.org/html/rfc6238#appendix-B + assert C.NK_first_authenticate(DefaultPasswords.ADMIN, DefaultPasswords.ADMIN_TEMP) == DeviceErrorCode.STATUS_OK + assert C.NK_write_totp_slot(slot_number, b'python_test', bbRFC_SECRET, 30, True, False, False, b'', + DefaultPasswords.ADMIN_TEMP) == DeviceErrorCode.STATUS_OK + + get_func = None + if PIN_protection: + get_func = lambda x, y, z, r: gs(C.NK_get_totp_code_PIN(x, y, z, r, DefaultPasswords.USER_TEMP)) + else: + get_func = lambda x, y, z, r: gs(C.NK_get_totp_code(x, y, z, r)) + + # Mode: Sha1, time step X=30 + test_data = [ + #Time T (hex) TOTP + (59, 0x1, 94287082), # Warning - test vector time 1 second before interval count changes + (1111111109, 0x00000000023523EC, 7081804), # Warning - test vector time 1 second before interval count changes + (1111111111, 0x00000000023523ED, 14050471), + (1234567890, 0x000000000273EF07, 89005924), + (2000000000, 0x0000000003F940AA, 69279037), + # (20000000000, 0x0000000027BC86AA, 65353130), # 64bit is also checked in other test + ] + responses = [] + data = [] + correct = 0 + for t, T, expected_code in test_data: + if PIN_protection: + C.NK_user_authenticate(DefaultPasswords.USER, DefaultPasswords.USER_TEMP) + assert C.NK_first_authenticate(DefaultPasswords.ADMIN, DefaultPasswords.ADMIN_TEMP) == DeviceErrorCode.STATUS_OK + assert C.NK_totp_set_time(t) == DeviceErrorCode.STATUS_OK + code_from_device = get_func(slot_number, T, 0, 30) # FIXME T is not changing the outcome + data += [ (t, bb(str(expected_code).zfill(8))) ] + responses += [ (t, code_from_device) ] + correct += expected_code == code_from_device + assert data == responses or correct == len(test_data) + + +@pytest.mark.otp +def test_get_slot_names(C): + assert C.NK_first_authenticate(DefaultPasswords.ADMIN, DefaultPasswords.ADMIN_TEMP) == DeviceErrorCode.STATUS_OK + assert C.NK_erase_totp_slot(0, DefaultPasswords.ADMIN_TEMP) == DeviceErrorCode.STATUS_OK + # erasing slot invalidates temporary password, so requesting authentication + assert C.NK_first_authenticate(DefaultPasswords.ADMIN, DefaultPasswords.ADMIN_TEMP) == DeviceErrorCode.STATUS_OK + assert C.NK_erase_hotp_slot(0, DefaultPasswords.ADMIN_TEMP) == DeviceErrorCode.STATUS_OK + + for i in range(15): + name = ffi.string(C.NK_get_totp_slot_name(i)) + if name == '': + assert C.NK_get_last_command_status() == DeviceErrorCode.NOT_PROGRAMMED + for i in range(3): + name = ffi.string(C.NK_get_hotp_slot_name(i)) + if name == '': + assert C.NK_get_last_command_status() == DeviceErrorCode.NOT_PROGRAMMED + + +@pytest.mark.otp +def test_get_OTP_codes(C): + assert C.NK_first_authenticate(DefaultPasswords.ADMIN, DefaultPasswords.ADMIN_TEMP) == DeviceErrorCode.STATUS_OK + assert C.NK_write_config(255, 255, 255, False, True, DefaultPasswords.ADMIN_TEMP) == DeviceErrorCode.STATUS_OK + for i in range(15): + code = gs(C.NK_get_totp_code(i, 0, 0, 0)) + if code == b'': + assert C.NK_get_last_command_status() == DeviceErrorCode.NOT_PROGRAMMED + + for i in range(3): + code = gs(C.NK_get_hotp_code(i)) + if code == b'': + assert C.NK_get_last_command_status() == DeviceErrorCode.NOT_PROGRAMMED + + +@pytest.mark.otp +def test_get_OTP_code_from_not_programmed_slot(C): + assert C.NK_first_authenticate(DefaultPasswords.ADMIN, DefaultPasswords.ADMIN_TEMP) == DeviceErrorCode.STATUS_OK + assert C.NK_write_config(255, 255, 255, False, True, DefaultPasswords.ADMIN_TEMP) == DeviceErrorCode.STATUS_OK + assert C.NK_first_authenticate(DefaultPasswords.ADMIN, DefaultPasswords.ADMIN_TEMP) == DeviceErrorCode.STATUS_OK + assert C.NK_erase_hotp_slot(0, DefaultPasswords.ADMIN_TEMP) == DeviceErrorCode.STATUS_OK + assert C.NK_first_authenticate(DefaultPasswords.ADMIN, DefaultPasswords.ADMIN_TEMP) == DeviceErrorCode.STATUS_OK + assert C.NK_erase_totp_slot(0, DefaultPasswords.ADMIN_TEMP) == DeviceErrorCode.STATUS_OK + + code = gs(C.NK_get_hotp_code(0)) + assert code == b'' + assert C.NK_get_last_command_status() == DeviceErrorCode.NOT_PROGRAMMED + + code = gs(C.NK_get_totp_code(0, 0, 0, 0)) + assert code == b'' + assert C.NK_get_last_command_status() == DeviceErrorCode.NOT_PROGRAMMED + + +@pytest.mark.otp +def test_get_code_user_authorize(C): + assert C.NK_first_authenticate(DefaultPasswords.ADMIN, DefaultPasswords.ADMIN_TEMP) == DeviceErrorCode.STATUS_OK + assert C.NK_write_totp_slot(0, b'python_otp_auth', bbRFC_SECRET, 30, True, False, False, b'', + DefaultPasswords.ADMIN_TEMP) == DeviceErrorCode.STATUS_OK + # enable PIN protection of OTP codes with write_config + # TODO create convinience function on C API side to enable/disable OTP USER_PIN protection + assert C.NK_first_authenticate(DefaultPasswords.ADMIN, DefaultPasswords.ADMIN_TEMP) == DeviceErrorCode.STATUS_OK + assert C.NK_write_config(255, 255, 255, True, False, DefaultPasswords.ADMIN_TEMP) == DeviceErrorCode.STATUS_OK + code = gs(C.NK_get_totp_code(0, 0, 0, 0)) + assert code == b'' + assert C.NK_get_last_command_status() == DeviceErrorCode.STATUS_NOT_AUTHORIZED + # disable PIN protection with write_config + assert C.NK_first_authenticate(DefaultPasswords.ADMIN, DefaultPasswords.ADMIN_TEMP) == DeviceErrorCode.STATUS_OK + assert C.NK_write_config(255, 255, 255, False, True, DefaultPasswords.ADMIN_TEMP) == DeviceErrorCode.STATUS_OK + code = gs(C.NK_get_totp_code(0, 0, 0, 0)) + assert code != b'' + assert C.NK_get_last_command_status() == DeviceErrorCode.STATUS_OK + + +def cast_pointer_to_tuple(obj, typen, len): + # usage: + # config = cast_pointer_to_tuple(config_raw_data, 'uint8_t', 5) + return tuple(ffi.cast("%s [%d]" % (typen, len), obj)[0:len]) + + +def test_read_write_config(C): + # let's set sample config with pin protection and disabled scrolllock + assert C.NK_first_authenticate(DefaultPasswords.ADMIN, DefaultPasswords.ADMIN_TEMP) == DeviceErrorCode.STATUS_OK + assert C.NK_write_config(0, 1, 2, True, False, DefaultPasswords.ADMIN_TEMP) == DeviceErrorCode.STATUS_OK + config_raw_data = C.NK_read_config() + assert C.NK_get_last_command_status() == DeviceErrorCode.STATUS_OK + config = cast_pointer_to_tuple(config_raw_data, 'uint8_t', 5) + assert config == (0, 1, 2, True, False) + + # restore defaults and check + assert C.NK_first_authenticate(DefaultPasswords.ADMIN, DefaultPasswords.ADMIN_TEMP) == DeviceErrorCode.STATUS_OK + assert C.NK_write_config(255, 255, 255, False, True, DefaultPasswords.ADMIN_TEMP) == DeviceErrorCode.STATUS_OK + config_raw_data = C.NK_read_config() + assert C.NK_get_last_command_status() == DeviceErrorCode.STATUS_OK + config = cast_pointer_to_tuple(config_raw_data, 'uint8_t', 5) + assert config == (255, 255, 255, False, True) + + +@pytest.mark.lock_device +@pytest.mark.factory_reset +def test_factory_reset(C): + assert C.NK_first_authenticate(DefaultPasswords.ADMIN, DefaultPasswords.ADMIN_TEMP) == DeviceErrorCode.STATUS_OK + assert C.NK_write_config(255, 255, 255, False, True, DefaultPasswords.ADMIN_TEMP) == DeviceErrorCode.STATUS_OK + assert C.NK_first_authenticate(DefaultPasswords.ADMIN, DefaultPasswords.ADMIN_TEMP) == DeviceErrorCode.STATUS_OK + assert C.NK_write_hotp_slot(1, b'python_test', bbRFC_SECRET, 0, False, False, False, b"", + DefaultPasswords.ADMIN_TEMP) == DeviceErrorCode.STATUS_OK + assert gs(C.NK_get_hotp_code(1)) == b"755224" + assert C.NK_factory_reset(DefaultPasswords.ADMIN) == DeviceErrorCode.STATUS_OK + wait(10) + assert gs(C.NK_get_hotp_code(1)) != b"287082" + assert C.NK_get_last_command_status() == DeviceErrorCode.NOT_PROGRAMMED + # restore AES key + assert C.NK_first_authenticate(DefaultPasswords.ADMIN, DefaultPasswords.ADMIN_TEMP) == DeviceErrorCode.STATUS_OK + assert C.NK_build_aes_key(DefaultPasswords.ADMIN) == DeviceErrorCode.STATUS_OK + assert C.NK_enable_password_safe(DefaultPasswords.USER) == DeviceErrorCode.STATUS_OK + assert C.NK_lock_device() == DeviceErrorCode.STATUS_OK + if is_storage(C): + assert C.NK_clear_new_sd_card_warning(DefaultPasswords.ADMIN) == DeviceErrorCode.STATUS_OK + + +@pytest.mark.status +def test_get_status(C): + status = C.NK_status() + s = gs(status) + assert len(s) > 0 + +@pytest.mark.status +def test_get_serial_number(C): + sn = C.NK_device_serial_number() + sn = gs(sn) + assert len(sn) > 0 + print(('Serial number of the device: ', sn)) + + +@pytest.mark.otp +@pytest.mark.parametrize("secret", ['000001', '00'*10+'ff', '00'*19+'ff', '000102', + '00'*29+'ff', '00'*39+'ff', '002EF43F51AFA97BA2B46418768123C9E1809A5B' ]) +def test_OTP_secret_started_from_null(C, secret): + """ + NK Pro 0.8+, NK Storage 0.43+ + """ + skip_if_device_version_lower_than({'S': 43, 'P': 8}) + if len(secret) > 40: + # feature: 320 bit long secret handling + skip_if_device_version_lower_than({'P': 8}) + + oath = pytest.importorskip("oath") + lib_at = lambda t: bb(oath.hotp(secret, t, format='dec6')) + PIN_protection = False + use_8_digits = False + slot_number = 1 + assert C.NK_first_authenticate(DefaultPasswords.ADMIN, DefaultPasswords.ADMIN_TEMP) == DeviceErrorCode.STATUS_OK + assert C.NK_write_config(255, 255, 255, PIN_protection, not PIN_protection, + DefaultPasswords.ADMIN_TEMP) == DeviceErrorCode.STATUS_OK + dev_res = [] + lib_res = [] + for t in range(1,5): + assert C.NK_first_authenticate(DefaultPasswords.ADMIN, DefaultPasswords.ADMIN_TEMP) == DeviceErrorCode.STATUS_OK + assert C.NK_write_hotp_slot(slot_number, b'null_secret', bb(secret), t, use_8_digits, False, False, b'', + DefaultPasswords.ADMIN_TEMP) == DeviceErrorCode.STATUS_OK + code_device = gs(C.NK_get_hotp_code(slot_number)) + dev_res += (t, code_device) + lib_res += (t, lib_at(t)) + assert dev_res == lib_res + + +@pytest.mark.otp +@pytest.mark.parametrize("counter", [0, 3, 7, 0xffff, + 0xffffffff, + 0xffffffffffffffff] ) +def test_HOTP_slots_read_write_counter(C, counter): + """ + Write different counters to all HOTP slots, read code and compare with 3rd party + :param counter: + """ + if counter >= 1e7: + # Storage does not handle counters longer than 7 digits + skip_if_device_version_lower_than({'P': 7}) + + secret = RFC_SECRET + oath = pytest.importorskip("oath") + lib_at = lambda t: bb(oath.hotp(secret, t, format='dec6')) + PIN_protection = False + use_8_digits = False + assert C.NK_first_authenticate(DefaultPasswords.ADMIN, DefaultPasswords.ADMIN_TEMP) == DeviceErrorCode.STATUS_OK + assert C.NK_write_config(255, 255, 255, PIN_protection, not PIN_protection, + DefaultPasswords.ADMIN_TEMP) == DeviceErrorCode.STATUS_OK + dev_res = [] + lib_res = [] + for slot_number in range(3): + assert C.NK_first_authenticate(DefaultPasswords.ADMIN, DefaultPasswords.ADMIN_TEMP) == DeviceErrorCode.STATUS_OK + assert C.NK_write_hotp_slot(slot_number, b'HOTP rw' + bytes(slot_number), bb(secret), counter, use_8_digits, False, False, b"", + DefaultPasswords.ADMIN_TEMP) == DeviceErrorCode.STATUS_OK + code_device = gs(C.NK_get_hotp_code(slot_number)) + dev_res += (counter, code_device) + lib_res += (counter, lib_at(counter)) + assert dev_res == lib_res + + +@pytest.mark.otp +@pytest.mark.parametrize("period", [30,60] ) +@pytest.mark.parametrize("time", range(21,70,20) ) +def test_TOTP_slots_read_write_at_time_period(C, time, period): + """ + Write to all TOTP slots with specified period, read code at specified time + and compare with 3rd party + """ + secret = RFC_SECRET + oath = pytest.importorskip("oath") + lib_at = lambda t: bb(oath.totp(RFC_SECRET, t=t, period=period)) + PIN_protection = False + use_8_digits = False + T = 0 + assert C.NK_first_authenticate(DefaultPasswords.ADMIN, DefaultPasswords.ADMIN_TEMP) == DeviceErrorCode.STATUS_OK + assert C.NK_write_config(255, 255, 255, PIN_protection, not PIN_protection, + DefaultPasswords.ADMIN_TEMP) == DeviceErrorCode.STATUS_OK + dev_res = [] + lib_res = [] + for slot_number in range(15): + assert C.NK_first_authenticate(DefaultPasswords.ADMIN, DefaultPasswords.ADMIN_TEMP) == DeviceErrorCode.STATUS_OK + assert C.NK_write_totp_slot(slot_number, b'TOTP rw' + bytes(slot_number), bb(secret), period, use_8_digits, False, False, b"", + DefaultPasswords.ADMIN_TEMP) == DeviceErrorCode.STATUS_OK + assert C.NK_first_authenticate(DefaultPasswords.ADMIN, DefaultPasswords.ADMIN_TEMP) == DeviceErrorCode.STATUS_OK + assert C.NK_totp_set_time(time) == DeviceErrorCode.STATUS_OK + code_device = gs(C.NK_get_totp_code(slot_number, T, 0, period)) + dev_res += (time, code_device) + lib_res += (time, lib_at(time)) + assert dev_res == lib_res + + +@pytest.mark.otp +@pytest.mark.parametrize("secret", [RFC_SECRET, 2*RFC_SECRET, '12'*10, '12'*30] ) +def test_TOTP_secrets(C, secret): + ''' + NK Pro 0.8+, NK Storage 0.44+ + ''' + skip_if_device_version_lower_than({'S': 44, 'P': 8}) + + if len(secret)>20*2: #*2 since secret is in hex + # pytest.skip("Secret lengths over 20 bytes are not supported by NK Pro 0.7 and NK Storage") + skip_if_device_version_lower_than({'P': 8}) + slot_number = 0 + time = 0 + period = 30 + oath = pytest.importorskip("oath") + lib_at = lambda t: bb(oath.totp(secret, t=t, period=period)) + PIN_protection = False + use_8_digits = False + T = 0 + assert C.NK_first_authenticate(DefaultPasswords.ADMIN, DefaultPasswords.ADMIN_TEMP) == DeviceErrorCode.STATUS_OK + assert C.NK_write_config(255, 255, 255, PIN_protection, not PIN_protection, + DefaultPasswords.ADMIN_TEMP) == DeviceErrorCode.STATUS_OK + dev_res = [] + lib_res = [] + assert C.NK_write_totp_slot(slot_number, b'secret' + bytes(len(secret)), bb(secret), period, use_8_digits, False, False, b"", + DefaultPasswords.ADMIN_TEMP) == DeviceErrorCode.STATUS_OK + assert C.NK_totp_set_time(time) == DeviceErrorCode.STATUS_OK + code_device = gs(C.NK_get_totp_code(slot_number, T, 0, period)) + dev_res += (time, code_device) + lib_res += (time, lib_at(time)) + assert dev_res == lib_res + + +@pytest.mark.otp +@pytest.mark.parametrize("secret", [RFC_SECRET, 2*RFC_SECRET, '12'*10, '12'*30] ) +def test_HOTP_secrets(C, secret): + """ + NK Pro 0.8+ + feature needed: support for 320bit secrets + """ + if len(secret)>40: + skip_if_device_version_lower_than({'P': 8}) + + slot_number = 0 + counter = 0 + oath = pytest.importorskip("oath") + lib_at = lambda t: bb(oath.hotp(secret, counter=t)) + PIN_protection = False + use_8_digits = False + T = 0 + assert C.NK_first_authenticate(DefaultPasswords.ADMIN, DefaultPasswords.ADMIN_TEMP) == DeviceErrorCode.STATUS_OK + assert C.NK_write_config(255, 255, 255, PIN_protection, not PIN_protection, + DefaultPasswords.ADMIN_TEMP) == DeviceErrorCode.STATUS_OK + dev_res = [] + lib_res = [] + # repeat authentication for Pro 0.7 + assert C.NK_first_authenticate(DefaultPasswords.ADMIN, DefaultPasswords.ADMIN_TEMP) == DeviceErrorCode.STATUS_OK + assert C.NK_write_hotp_slot(slot_number, b'secret' + bytes(len(secret)), bb(secret), counter, use_8_digits, False, False, b"", + DefaultPasswords.ADMIN_TEMP) == DeviceErrorCode.STATUS_OK + code_device = gs(C.NK_get_hotp_code(slot_number)) + dev_res += (counter, code_device) + lib_res += (counter, lib_at(counter)) + assert dev_res == lib_res + + +def test_special_double_press(C): + """ + requires manual check after function run + double press each of num-, scroll-, caps-lock and check inserted OTP codes (each 1st should be 755224) + on nkpro 0.7 scrolllock should do nothing, on nkpro 0.8+ should return OTP code + """ + secret = RFC_SECRET + counter = 0 + PIN_protection = False + use_8_digits = False + assert C.NK_first_authenticate(DefaultPasswords.ADMIN, DefaultPasswords.ADMIN_TEMP) == DeviceErrorCode.STATUS_OK + assert C.NK_write_config(0, 1, 2, PIN_protection, not PIN_protection, + DefaultPasswords.ADMIN_TEMP) == DeviceErrorCode.STATUS_OK + for slot_number in range(3): + assert C.NK_first_authenticate(DefaultPasswords.ADMIN, DefaultPasswords.ADMIN_TEMP) == DeviceErrorCode.STATUS_OK + assert C.NK_write_hotp_slot(slot_number, b'double' + bytes(slot_number), bb(secret), counter, use_8_digits, False, False, b"", + DefaultPasswords.ADMIN_TEMP) == DeviceErrorCode.STATUS_OK + # requires manual check + + +@pytest.mark.otp +def test_edit_OTP_slot(C): + """ + should change slots counter and name without changing its secret (using null secret for second update) + """ + # counter is not getting updated under Storage v0.43 - #TOREPORT + skip_if_device_version_lower_than({'S': 44, 'P': 7}) + + secret = RFC_SECRET + counter = 0 + PIN_protection = False + use_8_digits = False + assert C.NK_first_authenticate(DefaultPasswords.ADMIN, DefaultPasswords.ADMIN_TEMP) == DeviceErrorCode.STATUS_OK + assert C.NK_write_config(255, 255, 255, PIN_protection, not PIN_protection, + DefaultPasswords.ADMIN_TEMP) == DeviceErrorCode.STATUS_OK + slot_number = 0 + assert C.NK_first_authenticate(DefaultPasswords.ADMIN, DefaultPasswords.ADMIN_TEMP) == DeviceErrorCode.STATUS_OK + first_name = b'edit slot' + assert C.NK_write_hotp_slot(slot_number, first_name, bb(secret), counter, use_8_digits, False, False, b"", + DefaultPasswords.ADMIN_TEMP) == DeviceErrorCode.STATUS_OK + assert gs(C.NK_get_hotp_slot_name(slot_number)) == first_name + + + first_code = gs(C.NK_get_hotp_code(slot_number)) + changed_name = b'changedname' + empty_secret = b'' + assert C.NK_first_authenticate(DefaultPasswords.ADMIN, DefaultPasswords.ADMIN_TEMP) == DeviceErrorCode.STATUS_OK + assert C.NK_write_hotp_slot(slot_number, changed_name, empty_secret, counter, use_8_digits, False, False, b"", + DefaultPasswords.ADMIN_TEMP) == DeviceErrorCode.STATUS_OK + second_code = gs(C.NK_get_hotp_code(slot_number)) + assert first_code == second_code + assert gs(C.NK_get_hotp_slot_name(slot_number)) == changed_name + + +@pytest.mark.otp +@pytest.mark.skip +@pytest.mark.parametrize("secret", ['31323334353637383930'*2,'31323334353637383930'*4] ) +def test_TOTP_codes_from_nitrokeyapp(secret, C): + """ + Helper test for manual TOTP check of written secret by Nitrokey App + Destined to run by hand + """ + slot_number = 0 + PIN_protection = False + period = 30 + assert C.NK_first_authenticate(DefaultPasswords.ADMIN, DefaultPasswords.ADMIN_TEMP) == DeviceErrorCode.STATUS_OK + assert C.NK_write_config(255, 255, 255, PIN_protection, not PIN_protection, + DefaultPasswords.ADMIN_TEMP) == DeviceErrorCode.STATUS_OK + code_device = gs(C.NK_get_totp_code(slot_number, 0, 0, period)) + + oath = pytest.importorskip("oath") + lib_at = lambda : bb(oath.totp(secret, period=period)) + print (lib_at()) + assert lib_at() == code_device diff --git a/unittest/test_storage.py b/unittest/test_storage.py new file mode 100644 index 0000000..2466779 --- /dev/null +++ b/unittest/test_storage.py @@ -0,0 +1,304 @@ +import pprint +import pytest + +from conftest import skip_if_device_version_lower_than +from constants import DefaultPasswords, DeviceErrorCode, bb +from misc import gs, wait +pprint = pprint.PrettyPrinter(indent=4).pprint + + +def get_dict_from_dissect(status): + x = [] + for s in status.split('\n'): + try: + if not ':' in s: continue + ss = s.replace('\t', '').replace(' (int) ', '').split(':') + if not len(ss) == 2: continue + x.append(ss) + except: + pass + d = {k.strip(): v.strip() for k, v in x} + return d + + +@pytest.mark.other +@pytest.mark.info +def test_get_status_storage(C): + skip_if_device_version_lower_than({'S': 43}) + status_pointer = C.NK_get_status_storage_as_string() + assert C.NK_get_last_command_status() == DeviceErrorCode.STATUS_OK + status_string = gs(status_pointer) + assert len(status_string) > 0 + status_dict = get_dict_from_dissect(status_string.decode('ascii')) + default_admin_password_retry_count = 3 + assert int(status_dict['AdminPwRetryCount']) == default_admin_password_retry_count + + +@pytest.mark.other +@pytest.mark.info +def test_sd_card_usage(C): + skip_if_device_version_lower_than({'S': 43}) + data_pointer = C.NK_get_SD_usage_data_as_string() + assert C.NK_get_last_command_status() == DeviceErrorCode.STATUS_OK + data_string = gs(data_pointer) + assert len(data_string) > 0 + data_dict = get_dict_from_dissect(data_string.decode("ascii")) + assert int(data_dict['WriteLevelMax']) <= 100 + + +@pytest.mark.encrypted +def test_encrypted_volume_unlock(C): + skip_if_device_version_lower_than({'S': 43}) + assert C.NK_lock_device() == DeviceErrorCode.STATUS_OK + assert C.NK_unlock_encrypted_volume(DefaultPasswords.USER) == DeviceErrorCode.STATUS_OK + + +@pytest.mark.hidden +def test_encrypted_volume_unlock_hidden(C): + skip_if_device_version_lower_than({'S': 43}) + hidden_volume_password = b'hiddenpassword' + assert C.NK_lock_device() == DeviceErrorCode.STATUS_OK + assert C.NK_unlock_encrypted_volume(DefaultPasswords.USER) == DeviceErrorCode.STATUS_OK + assert C.NK_create_hidden_volume(0, 20, 21, hidden_volume_password) == DeviceErrorCode.STATUS_OK + assert C.NK_unlock_hidden_volume(hidden_volume_password) == DeviceErrorCode.STATUS_OK + + +@pytest.mark.hidden +def test_encrypted_volume_setup_multiple_hidden_lock(C): + import random + skip_if_device_version_lower_than({'S': 45}) #hangs device on lower version + hidden_volume_password = b'hiddenpassword' + bb(str(random.randint(0,100))) + p = lambda i: hidden_volume_password + bb(str(i)) + assert C.NK_lock_device() == DeviceErrorCode.STATUS_OK + assert C.NK_unlock_encrypted_volume(DefaultPasswords.USER) == DeviceErrorCode.STATUS_OK + for i in range(4): + assert C.NK_create_hidden_volume(i, 20+i*10, 20+i*10+i+1, p(i) ) == DeviceErrorCode.STATUS_OK + for i in range(4): + assert C.NK_lock_device() == DeviceErrorCode.STATUS_OK + assert C.NK_unlock_encrypted_volume(DefaultPasswords.USER) == DeviceErrorCode.STATUS_OK + assert C.NK_unlock_hidden_volume(p(i)) == DeviceErrorCode.STATUS_OK + + +@pytest.mark.hidden +@pytest.mark.parametrize("volumes_to_setup", range(1, 5)) +def test_encrypted_volume_setup_multiple_hidden_no_lock_device_volumes(C, volumes_to_setup): + skip_if_device_version_lower_than({'S': 43}) + hidden_volume_password = b'hiddenpassword' + p = lambda i: hidden_volume_password + bb(str(i)) + assert C.NK_lock_device() == DeviceErrorCode.STATUS_OK + assert C.NK_unlock_encrypted_volume(DefaultPasswords.USER) == DeviceErrorCode.STATUS_OK + for i in range(volumes_to_setup): + assert C.NK_create_hidden_volume(i, 20+i*10, 20+i*10+i+1, p(i)) == DeviceErrorCode.STATUS_OK + + assert C.NK_lock_encrypted_volume() == DeviceErrorCode.STATUS_OK + assert C.NK_unlock_encrypted_volume(DefaultPasswords.USER) == DeviceErrorCode.STATUS_OK + + for i in range(volumes_to_setup): + assert C.NK_unlock_hidden_volume(p(i)) == DeviceErrorCode.STATUS_OK + # TODO mount and test for files + assert C.NK_lock_hidden_volume() == DeviceErrorCode.STATUS_OK + + +@pytest.mark.hidden +@pytest.mark.parametrize("volumes_to_setup", range(1, 5)) +def test_encrypted_volume_setup_multiple_hidden_no_lock_device_volumes_unlock_at_once(C, volumes_to_setup): + skip_if_device_version_lower_than({'S': 43}) + hidden_volume_password = b'hiddenpassword' + p = lambda i: hidden_volume_password + bb(str(i)) + assert C.NK_lock_device() == DeviceErrorCode.STATUS_OK + assert C.NK_unlock_encrypted_volume(DefaultPasswords.USER) == DeviceErrorCode.STATUS_OK + for i in range(volumes_to_setup): + assert C.NK_create_hidden_volume(i, 20+i*10, 20+i*10+i+1, p(i)) == DeviceErrorCode.STATUS_OK + assert C.NK_unlock_hidden_volume(p(i)) == DeviceErrorCode.STATUS_OK + assert C.NK_lock_hidden_volume() == DeviceErrorCode.STATUS_OK + + assert C.NK_lock_encrypted_volume() == DeviceErrorCode.STATUS_OK + assert C.NK_unlock_encrypted_volume(DefaultPasswords.USER) == DeviceErrorCode.STATUS_OK + + for i in range(volumes_to_setup): + assert C.NK_unlock_hidden_volume(p(i)) == DeviceErrorCode.STATUS_OK + # TODO mount and test for files + assert C.NK_lock_hidden_volume() == DeviceErrorCode.STATUS_OK + + +@pytest.mark.hidden +@pytest.mark.parametrize("use_slot", range(4)) +def test_encrypted_volume_setup_one_hidden_no_lock_device_slot(C, use_slot): + skip_if_device_version_lower_than({'S': 43}) + hidden_volume_password = b'hiddenpassword' + p = lambda i: hidden_volume_password + bb(str(i)) + assert C.NK_lock_device() == DeviceErrorCode.STATUS_OK + assert C.NK_unlock_encrypted_volume(DefaultPasswords.USER) == DeviceErrorCode.STATUS_OK + i = use_slot + assert C.NK_create_hidden_volume(i, 20+i*10, 20+i*10+i+1, p(i)) == DeviceErrorCode.STATUS_OK + assert C.NK_unlock_hidden_volume(p(i)) == DeviceErrorCode.STATUS_OK + assert C.NK_lock_hidden_volume() == DeviceErrorCode.STATUS_OK + + assert C.NK_lock_encrypted_volume() == DeviceErrorCode.STATUS_OK + assert C.NK_unlock_encrypted_volume(DefaultPasswords.USER) == DeviceErrorCode.STATUS_OK + + for j in range(3): + assert C.NK_unlock_hidden_volume(p(i)) == DeviceErrorCode.STATUS_OK + # TODO mount and test for files + assert C.NK_lock_hidden_volume() == DeviceErrorCode.STATUS_OK + + +@pytest.mark.hidden +@pytest.mark.PWS +def test_password_safe_slot_name_corruption(C): + skip_if_device_version_lower_than({'S': 43}) + volumes_to_setup = 4 + # connected with encrypted volumes, possible also with hidden + def fill(s, wid): + assert wid >= len(s) + numbers = '1234567890' * 4 + s += numbers[:wid - len(s)] + assert len(s) == wid + return bb(s) + + def get_pass(suffix): + return fill('pass' + suffix, 20) + + def get_loginname(suffix): + return fill('login' + suffix, 32) + + def get_slotname(suffix): + return fill('slotname' + suffix, 11) + + assert C.NK_lock_device() == DeviceErrorCode.STATUS_OK + assert C.NK_enable_password_safe(DefaultPasswords.USER) == DeviceErrorCode.STATUS_OK + PWS_slot_count = 16 + for i in range(0, PWS_slot_count): + iss = str(i) + assert C.NK_write_password_safe_slot(i, + get_slotname(iss), get_loginname(iss), + get_pass(iss)) == DeviceErrorCode.STATUS_OK + + def check_PWS_correctness(C): + for i in range(0, PWS_slot_count): + iss = str(i) + assert gs(C.NK_get_password_safe_slot_name(i)) == get_slotname(iss) + assert gs(C.NK_get_password_safe_slot_login(i)) == get_loginname(iss) + assert gs(C.NK_get_password_safe_slot_password(i)) == get_pass(iss) + + hidden_volume_password = b'hiddenpassword' + p = lambda i: hidden_volume_password + bb(str(i)) + def check_volumes_correctness(C): + for i in range(volumes_to_setup): + assert C.NK_unlock_hidden_volume(p(i)) == DeviceErrorCode.STATUS_OK + # TODO mount and test for files + assert C.NK_lock_hidden_volume() == DeviceErrorCode.STATUS_OK + + check_PWS_correctness(C) + + assert C.NK_lock_device() == DeviceErrorCode.STATUS_OK + assert C.NK_unlock_encrypted_volume(DefaultPasswords.USER) == DeviceErrorCode.STATUS_OK + for i in range(volumes_to_setup): + assert C.NK_create_hidden_volume(i, 20+i*10, 20+i*10+i+1, p(i)) == DeviceErrorCode.STATUS_OK + assert C.NK_unlock_hidden_volume(p(i)) == DeviceErrorCode.STATUS_OK + assert C.NK_lock_hidden_volume() == DeviceErrorCode.STATUS_OK + + assert C.NK_lock_encrypted_volume() == DeviceErrorCode.STATUS_OK + assert C.NK_unlock_encrypted_volume(DefaultPasswords.USER) == DeviceErrorCode.STATUS_OK + + check_volumes_correctness(C) + check_PWS_correctness(C) + check_volumes_correctness(C) + check_PWS_correctness(C) + + assert C.NK_lock_device() == DeviceErrorCode.STATUS_OK + assert C.NK_unlock_encrypted_volume(DefaultPasswords.USER) == DeviceErrorCode.STATUS_OK + check_volumes_correctness(C) + check_PWS_correctness(C) + assert C.NK_lock_device() == DeviceErrorCode.STATUS_OK + assert C.NK_unlock_encrypted_volume(DefaultPasswords.USER) == DeviceErrorCode.STATUS_OK + check_volumes_correctness(C) + check_PWS_correctness(C) + + +@pytest.mark.hidden +def test_hidden_volume_corruption(C): + # bug: this should return error without unlocking encrypted volume each hidden volume lock, but it does not + skip_if_device_version_lower_than({'S': 43}) + hidden_volume_password = b'hiddenpassword' + p = lambda i: hidden_volume_password + bb(str(i)) + volumes_to_setup = 4 + for i in range(volumes_to_setup): + assert C.NK_create_hidden_volume(i, 20 + i * 10, 20 + i * 10 + i + 1, p(i)) == DeviceErrorCode.STATUS_OK + assert C.NK_unlock_hidden_volume(p(i)) == DeviceErrorCode.STATUS_OK + assert C.NK_lock_hidden_volume() == DeviceErrorCode.STATUS_OK + + assert C.NK_lock_encrypted_volume() == DeviceErrorCode.STATUS_OK + + assert C.NK_unlock_encrypted_volume(DefaultPasswords.USER) == DeviceErrorCode.STATUS_OK + for i in range(volumes_to_setup): + assert C.NK_unlock_encrypted_volume(DefaultPasswords.USER) == DeviceErrorCode.STATUS_OK + assert C.NK_unlock_hidden_volume(p(i)) == DeviceErrorCode.STATUS_OK + wait(2) + assert C.NK_lock_hidden_volume() == DeviceErrorCode.STATUS_OK + + +@pytest.mark.unencrypted +def test_unencrypted_volume_set_read_only(C): + skip_if_device_version_lower_than({'S': 43}) + assert C.NK_lock_device() == DeviceErrorCode.STATUS_OK + assert C.NK_set_unencrypted_read_only(DefaultPasswords.USER) == DeviceErrorCode.STATUS_OK + + +@pytest.mark.unencrypted +def test_unencrypted_volume_set_read_write(C): + skip_if_device_version_lower_than({'S': 43}) + assert C.NK_lock_device() == DeviceErrorCode.STATUS_OK + assert C.NK_set_unencrypted_read_write(DefaultPasswords.USER) == DeviceErrorCode.STATUS_OK + + +@pytest.mark.other +def test_export_firmware(C): + skip_if_device_version_lower_than({'S': 43}) + assert C.NK_export_firmware(DefaultPasswords.ADMIN) == DeviceErrorCode.STATUS_OK + + +@pytest.mark.other +def test_clear_new_sd_card_notification(C): + skip_if_device_version_lower_than({'S': 43}) + assert C.NK_clear_new_sd_card_warning(DefaultPasswords.ADMIN) == DeviceErrorCode.STATUS_OK + + +@pytest.mark.encrypted +@pytest.mark.slowtest +@pytest.mark.skip(reason='long test (about 1h)') +def test_fill_SD_card(C): + skip_if_device_version_lower_than({'S': 43}) + status = C.NK_fill_SD_card_with_random_data(DefaultPasswords.ADMIN) + assert status == DeviceErrorCode.STATUS_OK or status == DeviceErrorCode.BUSY + while 1: + value = C.NK_get_progress_bar_value() + if value == -1: break + assert 0 <= value <= 100 + assert C.NK_get_last_command_status() == DeviceErrorCode.STATUS_OK + wait(5) + + +@pytest.mark.other +@pytest.mark.info +def test_get_busy_progress_on_idle(C): + skip_if_device_version_lower_than({'S': 43}) + value = C.NK_get_progress_bar_value() + assert value == -1 + assert C.NK_get_last_command_status() == DeviceErrorCode.STATUS_OK + + +@pytest.mark.update +def test_change_update_password(C): + skip_if_device_version_lower_than({'S': 43}) + wrong_password = b'aaaaaaaaaaa' + assert C.NK_change_update_password(wrong_password, DefaultPasswords.UPDATE_TEMP) == DeviceErrorCode.WRONG_PASSWORD + assert C.NK_change_update_password(DefaultPasswords.UPDATE, DefaultPasswords.UPDATE_TEMP) == DeviceErrorCode.STATUS_OK + assert C.NK_change_update_password(DefaultPasswords.UPDATE_TEMP, DefaultPasswords.UPDATE) == DeviceErrorCode.STATUS_OK + + +@pytest.mark.other +def test_send_startup(C): + skip_if_device_version_lower_than({'S': 43}) + time_seconds_from_epoch = 0 # FIXME set proper date + assert C.NK_send_startup(time_seconds_from_epoch) == DeviceErrorCode.STATUS_OK |