diff --git a/.gitignore b/.gitignore index 432d6ac3..ea92772c 100644 --- a/.gitignore +++ b/.gitignore @@ -47,4 +47,5 @@ libjson.a Testing -.idea \ No newline at end of file +.idea +utf8_test diff --git a/LICENSE.MIT b/LICENSE.MIT index 64be5cf0..18332db3 100644 --- a/LICENSE.MIT +++ b/LICENSE.MIT @@ -1,7 +1,7 @@ The library is licensed under the MIT License : -Copyright (c) 2013-2014 Niels Lohmann +Copyright (c) 2013-2015 Niels Lohmann Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in diff --git a/Makefile.am b/Makefile.am index d079b5b8..f2976975 100644 --- a/Makefile.am +++ b/Makefile.am @@ -4,12 +4,20 @@ noinst_PROGRAMS = json_unit FLAGS = -Wall -Wextra -pedantic -Weffc++ -Wcast-align -Wcast-qual -Wctor-dtor-privacy -Wdisabled-optimization -Wformat=2 -Winit-self -Wmissing-declarations -Wmissing-include-dirs -Wold-style-cast -Woverloaded-virtual -Wredundant-decls -Wshadow -Wsign-conversion -Wsign-promo -Wstrict-overflow=5 -Wswitch -Wundef -Wno-unused -Wnon-virtual-dtor -Wreorder -json_unit_SOURCES = $(CORE_SOURCES) test/catch.hpp test/unit.cpp src/json.hpp +json_unit_SOURCES = src/json.hpp test/catch.hpp test/unit.cpp json_unit_CXXFLAGS = $(FLAGS) -std=c++11 json_unit_CPPFLAGS = -I$(top_srcdir)/src -I$(top_srcdir)/test -Dprivate=public +# parameters: +# -b use bit vectors +# -s nested ifs +# -i do not create #line information +# --no-generation-date suppress generation date output +src/json.hpp: src/json.hpp.re2c + $(AM_V_GEN)$(RE2C) -b -s -i --no-generation-date $< | $(SED) '1d' > $@ + cppcheck: - cppcheck --enable=all --inconclusive --std=c++11 src/json.* + cppcheck --enable=all --inconclusive --std=c++11 src/json.hpp svn-clean: maintainer-clean rm -fr configure INSTALL aclocal.m4 build-aux depcomp install-sh missing test-driver @@ -21,4 +29,4 @@ pretty: --indent-col1-comments --pad-oper --pad-header --align-pointer=type \ --align-reference=type --add-brackets --convert-tabs --close-templates \ --lineend=linux --preserve-date --suffix=none \ - $(SOURCES) + src/json.hpp src/json.hpp.re2c test/unit.cpp diff --git a/configure.ac b/configure.ac index 255281f3..05a88bb8 100644 --- a/configure.ac +++ b/configure.ac @@ -1,10 +1,14 @@ AC_INIT([JSON], [3.0], [mail@nlohmann.me]) -AC_CONFIG_SRCDIR([src/json.hpp]) +AC_CONFIG_SRCDIR([src/json.hpp.re2c]) AM_INIT_AUTOMAKE([foreign subdir-objects]) AM_SILENT_RULES([yes]) AC_PROG_CXX +AC_PROG_SED +AC_PATH_PROG(RE2C, [re2c]) +AM_MISSING_PROG(CPPCHECK, [cppcheck]) +AM_MISSING_PROG(ASTYLE, [astyle]) AC_CONFIG_FILES(Makefile) AC_OUTPUT diff --git a/src/json.hpp b/src/json.hpp.re2c similarity index 79% rename from src/json.hpp rename to src/json.hpp.re2c index 1e61d5e4..07cce7c7 100644 --- a/src/json.hpp +++ b/src/json.hpp.re2c @@ -1283,6 +1283,31 @@ class basic_json } + ///////////////////// + // deserialization // + ///////////////////// + + /// deserialize from string + static basic_json parse(const std::string& s) + { + return parser(s).parse(); + } + + /// deserialize from stream + friend std::istream& operator>>(std::istream& i, basic_json& j) + { + j = parser(i).parse(); + return i; + } + + /// deserialize from stream + friend std::istream& operator<<(basic_json& j, std::istream& i) + { + j = parser(i).parse(); + return i; + } + + private: /////////////////////////// // convenience functions // @@ -1322,64 +1347,85 @@ class basic_json } /*! - Escape a string by replacing special characters by a sequence of an - escape character (backslash) and another character. + @brief escape a string + + Escape a string by replacing certain special characters by a sequence of an + escape character (backslash) and another character and other control + characters by a sequence of "\u" followed by a four-digit hex + representation. + + @param s the string to escape + @return escaped string */ - static string_t escape_string(const string_t& s) + static string_t escape_string(const string_t& s) noexcept { // create a result string of at least the size than s string_t result; result.reserve(s.size()); - for (auto c : s) + for (const auto c : s) { switch (c) { - // quotation mark + // quotation mark (0x22) case '"': { - result.append("\\\"", 2); + result += "\\\""; break; } - // reverse solidus + // reverse solidus (0x5c) case '\\': { - result.append("\\\\", 2); + result += "\\\\"; break; } - // backspace + // backspace (0x08) case '\b': { - result.append("\\b", 2); + result += "\\b"; break; } - // formfeed + // formfeed (0x0c) case '\f': { - result.append("\\f", 2); + result += "\\f"; break; } - // newline + // newline (0x0a) case '\n': { - result.append("\\n", 2); + result += "\\n"; break; } - // carriage return + // carriage return (0x0d) case '\r': { - result.append("\\r", 2); + result += "\\r"; break; } - // horizontal tab + // horizontal tab (0x09) case '\t': { - result.append("\\t", 2); + result += "\\t"; break; } + default: { - result.append(1, c); + if (c <= 0x1f) + { + // control characters (everything between 0x00 and 0x1f) + // -> create four-digit hex representation + std::stringstream ss; + ss << "\\u" << std::hex << std::setw(4) << std::setfill('0') << int(c); + result += ss.str(); + } + else + { + // all other characters are added as-is + result.append(1, c); + } + break; } } } @@ -1387,8 +1433,17 @@ class basic_json return result; } + /*! - Internal implementation of the serialization function. + @brief internal implementation of the serialization function + + This function is called by the public member function dump and organizes + the serializaion internally. The indentation level is propagated as + additional parameter. In case of arrays and objects, the function is called + recursively. Note that + + - strings and object keys are escaped using escape_string() + - numbers are converted to a string before output using std::to_string() @param prettyPrint whether the output shall be pretty-printed @param indentStep the indent level @@ -1426,13 +1481,13 @@ class basic_json result += "\n"; } - for (typename object_t::const_iterator i = m_value.object->begin(); i != m_value.object->end(); ++i) + for (auto i = m_value.object->cbegin(); i != m_value.object->cend(); ++i) { - if (i != m_value.object->begin()) + if (i != m_value.object->cbegin()) { result += prettyPrint ? ",\n" : ","; } - result += indent() + "\"" + i->first + "\":" + (prettyPrint ? " " : "") + result += indent() + "\"" + escape_string(i->first) + "\":" + (prettyPrint ? " " : "") + i->second.dump(prettyPrint, indentStep, currentIndent); } @@ -1462,9 +1517,9 @@ class basic_json result += "\n"; } - for (typename array_t::const_iterator i = m_value.array->begin(); i != m_value.array->end(); ++i) + for (auto i = m_value.array->cbegin(); i != m_value.array->cend(); ++i) { - if (i != m_value.array->begin()) + if (i != m_value.array->cbegin()) { result += prettyPrint ? ",\n" : ","; } @@ -2221,6 +2276,365 @@ class basic_json /// the actual iterator of the associated instance internal_const_iterator m_it; }; + + private: + //////////// + // parser // + //////////// + + class parser + { + private: + /// token types for the parser + enum class token_type + { + uninitialized, + literal_true, + literal_false, + literal_null, + value_string, + value_number, + begin_array, + begin_object, + end_array, + end_object, + name_separator, + value_separator, + parse_error + }; + + /// the type of a lexer character + using lexer_char_t = unsigned char; + + public: + /// constructor for strings + inline parser(const std::string& s) : buffer(s) + { + // set buffer for RE2C + buffer_re2c = reinterpret_cast(buffer.c_str()); + // set a pointer past the end of the buffer + buffer_re2c_limit = buffer_re2c + buffer.size(); + // read first token + get_token(); + } + + /// a parser reading from an input stream + inline parser(std::istream& _is) + { + while (_is) + { + std::string input_line; + std::getline(_is, input_line); + buffer += input_line; + } + + // set buffer for RE2C + buffer_re2c = reinterpret_cast(buffer.c_str()); + // set a pointer past the end of the buffer + buffer_re2c_limit = buffer_re2c + buffer.size(); + // read first token + get_token(); + } + + inline basic_json parse() + { + switch (last_token) + { + case (token_type::begin_object): + { + // explicitly set result to object to cope with {} + basic_json result(value_t::object); + + // read next token + get_token(); + + // closing } -> we are done + if (last_token == token_type::end_object) + { + return result; + } + + // otherwise: parse key-value pairs + do + { + // store key + expect_new(token_type::value_string); + const auto key = get_string(); + + // parse separator (:) + get_token(); + expect_new(token_type::name_separator); + + // parse value + get_token(); + result[key] = parse(); + + // read next character + get_token(); + } + while (last_token == token_type::value_separator + and get_token() == last_token); + + // closing } + expect_new(token_type::end_object); + + return result; + } + + case (token_type::begin_array): + { + // explicitly set result to object to cope with [] + basic_json result(value_t::array); + + // read next token + get_token(); + + // closing ] -> we are done + if (last_token == token_type::end_array) + { + return result; + } + + // otherwise: parse values + do + { + // parse value + result.push_back(parse()); + + // read next character + get_token(); + } + while (last_token == token_type::value_separator + and get_token() == last_token); + + // closing ] + expect_new(token_type::end_array); + + return result; + } + + case (token_type::literal_null): + { + return basic_json(nullptr); + } + + case (token_type::value_string): + { + return basic_json(get_string()); + } + + case (token_type::literal_true): + { + return basic_json(true); + } + + case (token_type::literal_false): + { + return basic_json(false); + } + + case (token_type::value_number): + { + // The pointer current_re2c points to the beginning of the parsed + // number. We pass this pointer to std::strtod which sets endptr + // to the first character past the converted number. If this pointer + // is not the same as buffer_re2c, then either more or less + // characters have been used during the comparison. This can happen + // for inputs like "01" which will be treated like number 0 followed + // by number 1. + + // conversion + char* endptr; + const auto float_val = std::strtod(reinterpret_cast(current_re2c), &endptr); + + // check if strtod read beyond the end of the lexem + if (reinterpret_cast(endptr) != buffer_re2c) + { + throw std::invalid_argument(std::string("parse error - ") + + reinterpret_cast(current_re2c) + " is not a number"); + } + + // check if conversion loses precision + const auto int_val = static_cast(float_val); + if (float_val == int_val) + { + // we basic_json not lose precision -> return int + return basic_json(int_val); + } + else + { + // we would lose precision -> returnfloat + return basic_json(float_val); + } + } + + default: + { + std::string error_msg = "parse error - unexpected \'"; + error_msg += static_cast(current_re2c[0]); + error_msg += "\' ("; + error_msg += token_type_name(last_token) + ")"; + throw std::invalid_argument(error_msg); + } + } + } + + private: + /*! + This function implements a scanner for JSON. It is specified using + regular expressions that try to follow RFC 7159 and ECMA-404 as close + as possible. These regular expressions are then translated into a + deterministic finite automaton (DFA) by the tool RE2C. As a result, the + translated code for this function consists of a large block of code + with goto jumps. + + @return the class of the next token read from the buffer + + @todo Unicode support needs to be checked. + */ + inline token_type get_token() + { + // needed by RE2C + const lexer_char_t* marker; + + // set up RE2C + /*!re2c + re2c:labelprefix = "json_parser_"; + re2c:yyfill:enable = 0; + re2c:define:YYCURSOR = buffer_re2c; + re2c:define:YYCTYPE = lexer_char_t; + re2c:define:YYMARKER = marker; + re2c:indent:string = " "; + re2c:define:YYLIMIT = buffer_re2c_limit; + */ + + for (;;) + { + // set current to the begin of the buffer + current_re2c = buffer_re2c; + + /*!re2c + // whitespace + ws = [ \t\n\r]*; + ws { continue; } + + // structural characters + "[" { return last_token = token_type::begin_array; } + "]" { return last_token = token_type::end_array; } + "{" { return last_token = token_type::begin_object; } + "}" { return last_token = token_type::end_object; } + "," { return last_token = token_type::value_separator; } + ":" { return last_token = token_type::name_separator; } + + // literal names + "null" { return last_token = token_type::literal_null; } + "true" { return last_token = token_type::literal_true; } + "false" { return last_token = token_type::literal_false; } + + // number + decimal_point = [.]; + digit = [0-9]; + digit_1_9 = [1-9]; + e = [eE]; + minus = [-]; + plus = [+]; + zero = [0]; + exp = e (minus|plus)? digit+; + frac = decimal_point digit+; + int = (zero|digit_1_9 digit*); + number = minus? int frac? exp?; + number { return last_token = token_type::value_number; } + + // string + quotation_mark = [\"]; + escape = [\\]; + unescaped = [^\"\\]; + escaped = escape ([\"\\/bfnrt] | [u][0-9a-fA-F]{4}); + char = unescaped | escaped; + string = quotation_mark char* quotation_mark; + string { return last_token = token_type::value_string; } + + // anything else is an error + * { return last_token = token_type::parse_error; } + */ + } + } + + inline std::string token_type_name(token_type t) + { + switch (t) + { + case (token_type::uninitialized): + return ""; + case (token_type::literal_true): + return "true literal"; + case (token_type::literal_false): + return "false literal"; + case (token_type::literal_null): + return "null literal"; + case (token_type::value_string): + return "string literal"; + case (token_type::value_number): + return "number literal"; + case (token_type::begin_array): + return "["; + case (token_type::begin_object): + return "{"; + case (token_type::end_array): + return "]"; + case (token_type::end_object): + return "}"; + case (token_type::name_separator): + return ":"; + case (token_type::value_separator): + return ","; + case (token_type::parse_error): + return ""; + } + } + + inline void expect_new(token_type t) + { + if (t != last_token) + { + std::string error_msg = "parse error - unexpected \'"; + error_msg += static_cast(current_re2c[0]); + error_msg += "\' (" + token_type_name(last_token); + error_msg += "); expected " + token_type_name(t); + throw std::invalid_argument(error_msg); + } + } + + /*! + The pointer current_re2c points to the opening quote of the string, and + buffer_re2c past the closing quote of the string. We create a std::string from + the character after the opening quotes (current_re2c+1) until the character + before the closing quotes (hence subtracting 2 characters from the pointer + difference of the two pointers). + + @return string value of current token without opening and closing quotes + + @todo Take care of Unicode. + */ + std::string get_string() const + { + return std::string( + reinterpret_cast(current_re2c + 1), + static_cast(buffer_re2c - current_re2c - 2) + ); + } + + /// the buffer + std::string buffer; + /// a pointer to the next character to read from the buffer + const lexer_char_t* buffer_re2c = nullptr; + /// a pointer past the last character of the buffer + const lexer_char_t* buffer_re2c_limit = nullptr; + /// a pointer to the beginning of the current token + const lexer_char_t* current_re2c = nullptr; + /// the type of the last read token + token_type last_token = token_type::uninitialized; + }; }; @@ -2264,4 +2678,17 @@ struct hash }; } +/*! +This operator implements a user-defined string literal for JSON objects. It can +be used by adding \p "_json" to a string literal and returns a JSON object if +no parse error occurred. + +@param s a string representation of a JSON object +@return a JSON object +*/ +nlohmann::json operator "" _json(const char* s, std::size_t) +{ + return nlohmann::json::parse(s); +} + #endif diff --git a/test/catch.hpp b/test/catch.hpp index 185c142b..6b8dfb5e 100644 --- a/test/catch.hpp +++ b/test/catch.hpp @@ -18,30 +18,30 @@ #define TWOBLUECUBES_CATCH_SUPPRESS_WARNINGS_H_INCLUDED #ifdef __clang__ - #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 "-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" #elif defined __GNUC__ - #pragma GCC diagnostic ignored "-Wvariadic-macros" - #pragma GCC diagnostic ignored "-Wunused-variable" - #pragma GCC diagnostic push - #pragma GCC diagnostic ignored "-Wpadded" +#pragma GCC diagnostic ignored "-Wvariadic-macros" +#pragma GCC diagnostic ignored "-Wunused-variable" +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wpadded" #endif #ifdef CATCH_CONFIG_MAIN - #define CATCH_CONFIG_RUNNER +# define CATCH_CONFIG_RUNNER #endif #ifdef CATCH_CONFIG_RUNNER - #ifndef CLARA_CONFIG_MAIN - #define CLARA_CONFIG_MAIN_NOT_DEFINED - #define CLARA_CONFIG_MAIN - #endif +# ifndef CLARA_CONFIG_MAIN +# define CLARA_CONFIG_MAIN_NOT_DEFINED +# define CLARA_CONFIG_MAIN +# endif #endif // #included from: internal/catch_notimplemented_exception.h @@ -68,13 +68,13 @@ #ifdef __clang__ - #if __has_feature(cxx_nullptr) - #define CATCH_CONFIG_CPP11_NULLPTR - #endif +# if __has_feature(cxx_nullptr) +# define CATCH_CONFIG_CPP11_NULLPTR +# endif - #if __has_feature(cxx_noexcept) - #define CATCH_CONFIG_CPP11_NOEXCEPT - #endif +# if __has_feature(cxx_noexcept) +# define CATCH_CONFIG_CPP11_NOEXCEPT +# endif #endif // __clang__ @@ -82,9 +82,9 @@ // Borland #ifdef __BORLANDC__ - #if (__BORLANDC__ > 0x582 ) - //#define CATCH_CONFIG_SFINAE // Not confirmed - #endif +#if (__BORLANDC__ > 0x582 ) +//#define CATCH_CONFIG_SFINAE // Not confirmed +#endif #endif // __BORLANDC__ @@ -92,9 +92,9 @@ // EDG #ifdef __EDG_VERSION__ - #if (__EDG_VERSION__ > 238 ) - //#define CATCH_CONFIG_SFINAE // Not confirmed - #endif +#if (__EDG_VERSION__ > 238 ) +//#define CATCH_CONFIG_SFINAE // Not confirmed +#endif #endif // __EDG_VERSION__ @@ -102,9 +102,9 @@ // Digital Mars #ifdef __DMC__ - #if (__DMC__ > 0x840 ) - //#define CATCH_CONFIG_SFINAE // Not confirmed - #endif +#if (__DMC__ > 0x840 ) +//#define CATCH_CONFIG_SFINAE // Not confirmed +#endif #endif // __DMC__ @@ -112,22 +112,22 @@ // GCC #ifdef __GNUC__ - #if __GNUC__ < 3 +#if __GNUC__ < 3 - #if (__GNUC_MINOR__ >= 96 ) - //#define CATCH_CONFIG_SFINAE - #endif +#if (__GNUC_MINOR__ >= 96 ) +//#define CATCH_CONFIG_SFINAE +#endif - #elif __GNUC__ >= 3 +#elif __GNUC__ >= 3 - // #define CATCH_CONFIG_SFINAE // Taking this out completely for now +// #define CATCH_CONFIG_SFINAE // Taking this out completely for now - #endif // __GNUC__ < 3 +#endif // __GNUC__ < 3 - #if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6 && defined(__GXX_EXPERIMENTAL_CXX0X__) ) +#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6 && defined(__GXX_EXPERIMENTAL_CXX0X__) ) - #define CATCH_CONFIG_CPP11_NULLPTR - #endif +#define CATCH_CONFIG_CPP11_NULLPTR +#endif #endif // __GNUC__ @@ -135,9 +135,9 @@ // Visual C++ #ifdef _MSC_VER - #if (_MSC_VER >= 1310 ) // (VC++ 7.0+) - //#define CATCH_CONFIG_SFINAE // Not confirmed - #endif +#if (_MSC_VER >= 1310 ) // (VC++ 7.0+) +//#define CATCH_CONFIG_SFINAE // Not confirmed +#endif #endif // _MSC_VER @@ -147,9 +147,9 @@ ( defined __GNUC__ && __GNUC__ >= 3 ) || \ ( !defined __cplusplus && __STDC_VERSION__ >= 199901L || __cplusplus >= 201103L ) - #ifndef CATCH_CONFIG_NO_VARIADIC_MACROS - #define CATCH_CONFIG_VARIADIC_MACROS - #endif +#ifndef CATCH_CONFIG_NO_VARIADIC_MACROS +#define CATCH_CONFIG_VARIADIC_MACROS +#endif #endif @@ -158,136 +158,112 @@ // detect language version: #if (__cplusplus == 201103L) - #define CATCH_CPP11 - #define CATCH_CPP11_OR_GREATER +# define CATCH_CPP11 +# define CATCH_CPP11_OR_GREATER #elif (__cplusplus >= 201103L) - #define CATCH_CPP11_OR_GREATER +# define CATCH_CPP11_OR_GREATER #endif // noexcept support: #if defined(CATCH_CONFIG_CPP11_NOEXCEPT) && !defined(CATCH_NOEXCEPT) - #define CATCH_NOEXCEPT noexcept - #define CATCH_NOEXCEPT_IS(x) noexcept(x) +# define CATCH_NOEXCEPT noexcept +# define CATCH_NOEXCEPT_IS(x) noexcept(x) #else - #define CATCH_NOEXCEPT throw() - #define CATCH_NOEXCEPT_IS(x) +# define CATCH_NOEXCEPT throw() +# define CATCH_NOEXCEPT_IS(x) #endif -namespace Catch -{ +namespace Catch { -class NonCopyable -{ - NonCopyable( NonCopyable const&); - void operator = ( NonCopyable const&); - protected: - NonCopyable() {} - virtual ~NonCopyable(); -}; + class NonCopyable { + NonCopyable( NonCopyable const& ); + void operator = ( NonCopyable const& ); + protected: + NonCopyable() {} + virtual ~NonCopyable(); + }; -class SafeBool -{ - public: - typedef void (SafeBool::*type)() const; + class SafeBool { + public: + typedef void (SafeBool::*type)() const; - static type makeSafe( bool value ) - { - return value ? &SafeBool::trueValue : 0; + static type makeSafe( bool value ) { + return value ? &SafeBool::trueValue : 0; + } + private: + void trueValue() const {} + }; + + template + 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; } - private: - void trueValue() const {} -}; - -template -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 + 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; } -} -template -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 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 ); -struct pluralise -{ - pluralise( std::size_t count, std::string const& label ); + struct pluralise { + pluralise( std::size_t count, std::string const& label ); - friend std::ostream& operator << ( std::ostream& os, pluralise const& pluraliser ); + friend std::ostream& operator << ( std::ostream& os, pluralise const& pluraliser ); - std::size_t m_count; - std::string m_label; -}; + std::size_t m_count; + std::string m_label; + }; -struct SourceLineInfo -{ + struct SourceLineInfo { - SourceLineInfo(); - SourceLineInfo( char const* _file, std::size_t _line ); - SourceLineInfo( SourceLineInfo const& other ); + SourceLineInfo(); + SourceLineInfo( char const* _file, std::size_t _line ); + SourceLineInfo( SourceLineInfo const& other ); # ifdef CATCH_CPP11_OR_GREATER - SourceLineInfo( SourceLineInfo&&) = default; - SourceLineInfo& operator = ( SourceLineInfo const&) = default; - SourceLineInfo& operator = ( SourceLineInfo&&) = default; + SourceLineInfo( SourceLineInfo && ) = default; + SourceLineInfo& operator = ( SourceLineInfo const& ) = default; + SourceLineInfo& operator = ( SourceLineInfo && ) = default; # endif - bool empty() const; - bool operator == ( SourceLineInfo const& other ) const; + bool empty() const; + bool operator == ( SourceLineInfo const& other ) const; - std::string file; - std::size_t line; -}; + std::string file; + std::size_t line; + }; -std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info ); + 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; -} + // 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 throwLogicError( std::string const& message, SourceLineInfo const& locationInfo ); -// Use this in variadic streaming macros to allow -// >> +StreamEndStop -// as well as -// >> stuff +StreamEndStop -struct StreamEndStop -{ - std::string operator+() - { - return std::string(); + // Use this in variadic streaming macros to allow + // >> +StreamEndStop + // as well as + // >> stuff +StreamEndStop + struct StreamEndStop { + std::string operator+() { + return std::string(); + } + }; + template + T const& operator + ( T const& value, StreamEndStop ) { + return value; } -}; -template -T const& operator + ( T const& value, StreamEndStop ) -{ - return value; -} } #define CATCH_INTERNAL_LINEINFO ::Catch::SourceLineInfo( __FILE__, static_cast( __LINE__ ) ) @@ -295,23 +271,22 @@ T const& operator + ( T const& value, StreamEndStop ) #include -namespace Catch -{ +namespace Catch { -class NotImplementedException : public std::exception -{ - public: - NotImplementedException( SourceLineInfo const& lineInfo ); - NotImplementedException( NotImplementedException const&) {} + class NotImplementedException : public std::exception + { + public: + NotImplementedException( SourceLineInfo const& lineInfo ); + NotImplementedException( NotImplementedException const& ) {} - virtual ~NotImplementedException() CATCH_NOEXCEPT {} + virtual ~NotImplementedException() CATCH_NOEXCEPT {} - virtual const char* what() const CATCH_NOEXCEPT; + virtual const char* what() const CATCH_NOEXCEPT; - private: - std::string m_what; - SourceLineInfo m_lineInfo; -}; + private: + std::string m_what; + SourceLineInfo m_lineInfo; + }; } // end namespace Catch @@ -326,25 +301,22 @@ class NotImplementedException : public std::exception #include -namespace Catch -{ +namespace Catch { -struct IGeneratorInfo -{ - virtual ~IGeneratorInfo(); - virtual bool moveNext() = 0; - virtual std::size_t getCurrentIndex() const = 0; -}; + struct IGeneratorInfo { + virtual ~IGeneratorInfo(); + virtual bool moveNext() = 0; + virtual std::size_t getCurrentIndex() const = 0; + }; -struct IGeneratorsForTest -{ - virtual ~IGeneratorsForTest(); + struct IGeneratorsForTest { + virtual ~IGeneratorsForTest(); - virtual IGeneratorInfo& getGeneratorInfo( std::string const& fileInfo, std::size_t size ) = 0; - virtual bool moveNext() = 0; -}; + virtual IGeneratorInfo& getGeneratorInfo( std::string const& fileInfo, std::size_t size ) = 0; + virtual bool moveNext() = 0; + }; -IGeneratorsForTest* createGeneratorsForTest(); + IGeneratorsForTest* createGeneratorsForTest(); } // end namespace Catch @@ -352,166 +324,122 @@ IGeneratorsForTest* createGeneratorsForTest(); #define TWOBLUECUBES_CATCH_PTR_HPP_INCLUDED #ifdef __clang__ - #pragma clang diagnostic push - #pragma clang diagnostic ignored "-Wpadded" +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wpadded" #endif -namespace Catch -{ +namespace Catch { -// An intrusive reference counting smart pointer. -// T must implement addRef() and release() methods -// typically implementing the IShared interface -template -class Ptr -{ - public: - Ptr() : m_p( NULL ) {} - Ptr( T* p ) : m_p( p ) - { - if ( m_p ) - { - m_p->addRef(); + // An intrusive reference counting smart pointer. + // T must implement addRef() and release() methods + // typically implementing the IShared interface + template + class Ptr { + public: + Ptr() : m_p( 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( Ptr const& other ) : m_p( other.m_p ){ + if( m_p ) + m_p->addRef(); } - } - ~Ptr() - { - if ( m_p ) - { - m_p->release(); + ~Ptr(){ + if( m_p ) + m_p->release(); } - } - void reset() - { - if ( m_p ) - { - m_p->release(); + void reset() { + if( m_p ) + m_p->release(); + m_p = NULL; } - m_p = 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() - { - return m_p; - } - const T* get() const - { - return m_p; - } - T& operator*() const - { - return *m_p; - } - T* operator->() const - { - return m_p; - } - bool operator !() const - { - return m_p == NULL; - } - operator SafeBool::type() const - { - return SafeBool::makeSafe( m_p != NULL ); - } - - private: - T* m_p; -}; - -struct IShared : NonCopyable -{ - virtual ~IShared(); - virtual void addRef() const = 0; - virtual void release() const = 0; -}; - -template -struct SharedImpl : T -{ - - SharedImpl() : m_rc( 0 ) {} - - virtual void addRef() const - { - ++m_rc; - } - virtual void release() const - { - if ( --m_rc == 0 ) - { - delete this; + 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() { return m_p; } + const T* get() const{ return m_p; } + T& operator*() const { return *m_p; } + T* operator->() const { return m_p; } + bool operator !() const { return m_p == NULL; } + operator SafeBool::type() const { return SafeBool::makeSafe( m_p != NULL ); } - mutable unsigned int m_rc; -}; + private: + T* m_p; + }; + + struct IShared : NonCopyable { + virtual ~IShared(); + virtual void addRef() const = 0; + virtual void release() const = 0; + }; + + template + 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 +#pragma clang diagnostic pop #endif #include #include #include -namespace Catch -{ +namespace Catch { -class TestCase; -class Stream; -struct IResultCapture; -struct IRunner; -struct IGeneratorsForTest; -struct IConfig; + class TestCase; + class Stream; + struct IResultCapture; + struct IRunner; + struct IGeneratorsForTest; + struct IConfig; -struct IContext -{ - virtual ~IContext(); + 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 getConfig() const = 0; -}; + 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 getConfig() const = 0; + }; -struct IMutableContext : IContext -{ - virtual ~IMutableContext(); - virtual void setResultCapture( IResultCapture* resultCapture ) = 0; - virtual void setRunner( IRunner* runner ) = 0; - virtual void setConfig( Ptr const& config ) = 0; -}; + struct IMutableContext : IContext + { + virtual ~IMutableContext(); + virtual void setResultCapture( IResultCapture* resultCapture ) = 0; + virtual void setRunner( IRunner* runner ) = 0; + virtual void setConfig( Ptr const& config ) = 0; + }; -IContext& getCurrentContext(); -IMutableContext& getCurrentMutableContext(); -void cleanUpContext(); -Stream createStream( std::string const& streamName ); + IContext& getCurrentContext(); + IMutableContext& getCurrentMutableContext(); + void cleanUpContext(); + Stream createStream( std::string const& streamName ); } @@ -523,48 +451,41 @@ Stream createStream( std::string const& streamName ); #include -namespace Catch -{ +namespace Catch { -class TestSpec; + class TestSpec; -struct ITestCase : IShared -{ - virtual void invoke () const = 0; - protected: - virtual ~ITestCase(); -}; + struct ITestCase : IShared { + virtual void invoke () const = 0; + protected: + virtual ~ITestCase(); + }; -class TestCase; -struct IConfig; + class TestCase; + struct IConfig; -struct ITestCaseRegistry -{ - virtual ~ITestCaseRegistry(); - virtual std::vector const& getAllTests() const = 0; - virtual void getFilteredTests( TestSpec const& testSpec, IConfig const& config, - std::vector& matchingTestCases ) const = 0; + struct ITestCaseRegistry { + virtual ~ITestCaseRegistry(); + virtual std::vector const& getAllTests() const = 0; + virtual void getFilteredTests( TestSpec const& testSpec, IConfig const& config, std::vector& matchingTestCases ) const = 0; -}; + }; } -namespace Catch -{ +namespace Catch { template -class MethodTestCase : public SharedImpl -{ +class MethodTestCase : public SharedImpl { - public: +public: MethodTestCase( void (C::*method)() ) : m_method( method ) {} - virtual void invoke() const - { + virtual void invoke() const { C obj; (obj.*m_method)(); } - private: +private: virtual ~MethodTestCase() {} void (C::*m_method)(); @@ -572,18 +493,16 @@ class MethodTestCase : public SharedImpl typedef void(*TestFunction)(); -struct NameAndDesc -{ - NameAndDesc( const char* _name = "", const char* _description = "" ) - : name( _name ), description( _description ) +struct NameAndDesc { + NameAndDesc( const char* _name = "", const char* _description= "" ) + : name( _name ), description( _description ) {} const char* name; const char* description; }; -struct AutoReg -{ +struct AutoReg { AutoReg( TestFunction function, SourceLineInfo const& lineInfo, @@ -593,8 +512,7 @@ struct AutoReg AutoReg( void (C::*method)(), char const* className, NameAndDesc const& nameAndDesc, - SourceLineInfo const& lineInfo ) - { + SourceLineInfo const& lineInfo ) { registerTestCase( new MethodTestCase( method ), className, nameAndDesc, @@ -608,54 +526,54 @@ struct AutoReg ~AutoReg(); - private: - AutoReg( AutoReg const&); - void operator= ( AutoReg const&); +private: + AutoReg( AutoReg const& ); + void operator= ( AutoReg const& ); }; } // 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_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_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_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() #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_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_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_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() #endif @@ -668,14 +586,10 @@ struct AutoReg // #included from: catch_result_type.h #define TWOBLUECUBES_CATCH_RESULT_TYPE_H_INCLUDED -namespace Catch -{ +namespace Catch { -// ResultWas::OfType enum -struct ResultWas -{ - enum OfType - { + // ResultWas::OfType enum + struct ResultWas { enum OfType { Unknown = -1, Ok = 0, Info = 1, @@ -691,49 +605,31 @@ struct ResultWas ThrewException = Exception | 1, DidntThrowException = Exception | 2 - }; -}; + }; }; -inline bool isOk( ResultWas::OfType resultType ) -{ - return ( resultType & ResultWas::FailureBit ) == 0; -} -inline bool isJustInfo( int flags ) -{ - return flags == ResultWas::Info; -} + 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 - { + // ResultDisposition::Flags enum + struct ResultDisposition { enum Flags { Normal = 0x00, ContinueOnFailure = 0x01, // Failures fail test, but execution continues FalseTest = 0x02, // Prefix expression with ! SuppressFail = 0x04 // Failures are reported but do not fail the test - }; -}; + }; }; -inline ResultDisposition::Flags operator | ( ResultDisposition::Flags lhs, - ResultDisposition::Flags rhs ) -{ - return static_cast( static_cast( lhs ) | static_cast( rhs ) ); -} + inline ResultDisposition::Flags operator | ( ResultDisposition::Flags lhs, ResultDisposition::Flags rhs ) { + return static_cast( static_cast( lhs ) | static_cast( 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; -} + 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 @@ -742,146 +638,135 @@ inline bool shouldSuppressFailure( int flags ) #include -namespace Catch -{ +namespace Catch { -struct AssertionInfo -{ - AssertionInfo() {} - AssertionInfo( std::string const& _macroName, - SourceLineInfo const& _lineInfo, - std::string const& _capturedExpression, - ResultDisposition::Flags _resultDisposition ); + 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; -}; + std::string macroName; + SourceLineInfo lineInfo; + std::string capturedExpression; + ResultDisposition::Flags resultDisposition; + }; -struct AssertionResultData -{ - AssertionResultData() : resultType( ResultWas::Unknown ) {} + struct AssertionResultData + { + AssertionResultData() : resultType( ResultWas::Unknown ) {} - std::string reconstructedExpression; - std::string message; - ResultWas::OfType resultType; -}; + std::string reconstructedExpression; + std::string message; + ResultWas::OfType resultType; + }; -class AssertionResult -{ - public: - AssertionResult(); - AssertionResult( AssertionInfo const& info, AssertionResultData const& data ); - ~AssertionResult(); + class AssertionResult { + public: + AssertionResult(); + AssertionResult( AssertionInfo const& info, AssertionResultData const& data ); + ~AssertionResult(); # ifdef CATCH_CPP11_OR_GREATER - AssertionResult( AssertionResult const&) = default; - AssertionResult( AssertionResult&&) = default; - AssertionResult& operator = ( AssertionResult const&) = default; - AssertionResult& operator = ( AssertionResult&&) = default; + 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; + 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; -}; + protected: + AssertionInfo m_info; + AssertionResultData m_resultData; + }; } // end namespace Catch -namespace Catch -{ +namespace Catch { -struct TestFailureException {}; + struct TestFailureException{}; -template class ExpressionLhs; + template class ExpressionLhs; -struct STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison; + 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; -}; + 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 ); + class ResultBuilder { + public: + ResultBuilder( char const* macroName, + SourceLineInfo const& lineInfo, + char const* capturedExpression, + ResultDisposition::Flags resultDisposition ); - template - ExpressionLhs operator->* ( T const& operand ); - ExpressionLhs operator->* ( bool value ); + template + ExpressionLhs operator->* ( T const& operand ); + ExpressionLhs operator->* ( bool value ); - template - ResultBuilder& operator << ( T const& value ) - { - m_stream.oss << value; - return *this; - } + template + ResultBuilder& operator << ( T const& value ) { + m_stream.oss << value; + return *this; + } - template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& - operator && ( RhsT const&); - template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& - operator || ( RhsT const&); + template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator && ( RhsT const& ); + template 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 ); + 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(); + void endExpression(); - std::string reconstructExpression() const; - AssertionResult build() const; + std::string reconstructExpression() const; + AssertionResult build() const; - void useActiveException( ResultDisposition::Flags resultDisposition = ResultDisposition::Normal ); - void captureResult( ResultWas::OfType resultType ); - void captureExpression(); - void react(); - bool shouldDebugBreak() const; - bool allowThrows() const; + void useActiveException( ResultDisposition::Flags resultDisposition = ResultDisposition::Normal ); + void captureResult( ResultWas::OfType resultType ); + void captureExpression(); + 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; + 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; -}; + bool m_shouldDebugBreak; + bool m_shouldThrow; + }; } // namespace Catch @@ -893,254 +778,171 @@ class ResultBuilder #define TWOBLUECUBES_CATCH_EVALUATE_HPP_INCLUDED #ifdef _MSC_VER - #pragma warning(push) - #pragma warning(disable:4389) // '==' : signed/unsigned mismatch +#pragma warning(push) +#pragma warning(disable:4389) // '==' : signed/unsigned mismatch #endif #include -namespace Catch -{ -namespace Internal -{ +namespace Catch { +namespace Internal { -enum Operator -{ - IsEqualTo, - IsNotEqualTo, - IsLessThan, - IsGreaterThan, - IsLessThanOrEqualTo, - IsGreaterThanOrEqualTo -}; + enum Operator { + IsEqualTo, + IsNotEqualTo, + IsLessThan, + IsGreaterThan, + IsLessThanOrEqualTo, + IsGreaterThanOrEqualTo + }; -template struct OperatorTraits -{ - static const char* getName() - { - return "*error*"; - } -}; -template<> struct OperatorTraits -{ - static const char* getName() - { - return "=="; - } -}; -template<> struct OperatorTraits -{ - static const char* getName() - { - return "!="; - } -}; -template<> struct OperatorTraits -{ - static const char* getName() - { - return "<"; - } -}; -template<> struct OperatorTraits -{ - static const char* getName() - { - return ">"; - } -}; -template<> struct OperatorTraits -{ - static const char* getName() - { - return "<="; - } -}; -template<> struct OperatorTraits -{ - static const char* getName() - { - return ">="; - } -}; + template struct OperatorTraits { static const char* getName(){ return "*error*"; } }; + template<> struct OperatorTraits { static const char* getName(){ return "=="; } }; + template<> struct OperatorTraits { static const char* getName(){ return "!="; } }; + template<> struct OperatorTraits { static const char* getName(){ return "<"; } }; + template<> struct OperatorTraits { static const char* getName(){ return ">"; } }; + template<> struct OperatorTraits { static const char* getName(){ return "<="; } }; + template<> struct OperatorTraits{ static const char* getName(){ return ">="; } }; -template -inline T& opCast(T const& t) -{ - return const_cast(t); -} + template + inline T& opCast(T const& t) { return const_cast(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; -} + 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 -class Evaluator {}; + // 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 + class Evaluator{}; -template -struct Evaluator -{ - static bool evaluate( T1 const& lhs, T2 const& rhs) - { - return opCast( lhs ) == opCast( rhs ); + template + struct Evaluator { + static bool evaluate( T1 const& lhs, T2 const& rhs) { + return opCast( lhs ) == opCast( rhs ); + } + }; + template + struct Evaluator { + static bool evaluate( T1 const& lhs, T2 const& rhs ) { + return opCast( lhs ) != opCast( rhs ); + } + }; + template + struct Evaluator { + static bool evaluate( T1 const& lhs, T2 const& rhs ) { + return opCast( lhs ) < opCast( rhs ); + } + }; + template + struct Evaluator { + static bool evaluate( T1 const& lhs, T2 const& rhs ) { + return opCast( lhs ) > opCast( rhs ); + } + }; + template + struct Evaluator { + static bool evaluate( T1 const& lhs, T2 const& rhs ) { + return opCast( lhs ) >= opCast( rhs ); + } + }; + template + struct Evaluator { + static bool evaluate( T1 const& lhs, T2 const& rhs ) { + return opCast( lhs ) <= opCast( rhs ); + } + }; + + template + bool applyEvaluator( T1 const& lhs, T2 const& rhs ) { + return Evaluator::evaluate( lhs, rhs ); } -}; -template -struct Evaluator -{ - static bool evaluate( T1 const& lhs, T2 const& rhs ) - { - return opCast( lhs ) != opCast( rhs ); + + // This level of indirection allows us to specialise for integer types + // to avoid signed/ unsigned warnings + + // "base" overload + template + bool compare( T1 const& lhs, T2 const& rhs ) { + return Evaluator::evaluate( lhs, rhs ); } -}; -template -struct Evaluator -{ - static bool evaluate( T1 const& lhs, T2 const& rhs ) - { - return opCast( lhs ) < opCast( rhs ); + + // unsigned X to int + template bool compare( unsigned int lhs, int rhs ) { + return applyEvaluator( lhs, static_cast( rhs ) ); } -}; -template -struct Evaluator -{ - static bool evaluate( T1 const& lhs, T2 const& rhs ) - { - return opCast( lhs ) > opCast( rhs ); + template bool compare( unsigned long lhs, int rhs ) { + return applyEvaluator( lhs, static_cast( rhs ) ); } -}; -template -struct Evaluator -{ - static bool evaluate( T1 const& lhs, T2 const& rhs ) - { - return opCast( lhs ) >= opCast( rhs ); + template bool compare( unsigned char lhs, int rhs ) { + return applyEvaluator( lhs, static_cast( rhs ) ); } -}; -template -struct Evaluator -{ - static bool evaluate( T1 const& lhs, T2 const& rhs ) - { - return opCast( lhs ) <= opCast( rhs ); + + // unsigned X to long + template bool compare( unsigned int lhs, long rhs ) { + return applyEvaluator( lhs, static_cast( rhs ) ); + } + template bool compare( unsigned long lhs, long rhs ) { + return applyEvaluator( lhs, static_cast( rhs ) ); + } + template bool compare( unsigned char lhs, long rhs ) { + return applyEvaluator( lhs, static_cast( rhs ) ); } -}; -template -bool applyEvaluator( T1 const& lhs, T2 const& rhs ) -{ - return Evaluator::evaluate( lhs, rhs ); -} + // int to unsigned X + template bool compare( int lhs, unsigned int rhs ) { + return applyEvaluator( static_cast( lhs ), rhs ); + } + template bool compare( int lhs, unsigned long rhs ) { + return applyEvaluator( static_cast( lhs ), rhs ); + } + template bool compare( int lhs, unsigned char rhs ) { + return applyEvaluator( static_cast( lhs ), rhs ); + } -// This level of indirection allows us to specialise for integer types -// to avoid signed/ unsigned warnings + // long to unsigned X + template bool compare( long lhs, unsigned int rhs ) { + return applyEvaluator( static_cast( lhs ), rhs ); + } + template bool compare( long lhs, unsigned long rhs ) { + return applyEvaluator( static_cast( lhs ), rhs ); + } + template bool compare( long lhs, unsigned char rhs ) { + return applyEvaluator( static_cast( lhs ), rhs ); + } -// "base" overload -template -bool compare( T1 const& lhs, T2 const& rhs ) -{ - return Evaluator::evaluate( lhs, rhs ); -} + // pointer to long (when comparing against NULL) + template bool compare( long lhs, T* rhs ) { + return Evaluator::evaluate( reinterpret_cast( lhs ), rhs ); + } + template bool compare( T* lhs, long rhs ) { + return Evaluator::evaluate( lhs, reinterpret_cast( rhs ) ); + } -// unsigned X to int -template bool compare( unsigned int lhs, int rhs ) -{ - return applyEvaluator( lhs, static_cast( rhs ) ); -} -template bool compare( unsigned long lhs, int rhs ) -{ - return applyEvaluator( lhs, static_cast( rhs ) ); -} -template bool compare( unsigned char lhs, int rhs ) -{ - return applyEvaluator( lhs, static_cast( rhs ) ); -} - -// unsigned X to long -template bool compare( unsigned int lhs, long rhs ) -{ - return applyEvaluator( lhs, static_cast( rhs ) ); -} -template bool compare( unsigned long lhs, long rhs ) -{ - return applyEvaluator( lhs, static_cast( rhs ) ); -} -template bool compare( unsigned char lhs, long rhs ) -{ - return applyEvaluator( lhs, static_cast( rhs ) ); -} - -// int to unsigned X -template bool compare( int lhs, unsigned int rhs ) -{ - return applyEvaluator( static_cast( lhs ), rhs ); -} -template bool compare( int lhs, unsigned long rhs ) -{ - return applyEvaluator( static_cast( lhs ), rhs ); -} -template bool compare( int lhs, unsigned char rhs ) -{ - return applyEvaluator( static_cast( lhs ), rhs ); -} - -// long to unsigned X -template bool compare( long lhs, unsigned int rhs ) -{ - return applyEvaluator( static_cast( lhs ), rhs ); -} -template bool compare( long lhs, unsigned long rhs ) -{ - return applyEvaluator( static_cast( lhs ), rhs ); -} -template bool compare( long lhs, unsigned char rhs ) -{ - return applyEvaluator( static_cast( lhs ), rhs ); -} - -// pointer to long (when comparing against NULL) -template bool compare( long lhs, T* rhs ) -{ - return Evaluator::evaluate( reinterpret_cast( lhs ), rhs ); -} -template bool compare( T* lhs, long rhs ) -{ - return Evaluator::evaluate( lhs, reinterpret_cast( rhs ) ); -} - -// pointer to int (when comparing against NULL) -template bool compare( int lhs, T* rhs ) -{ - return Evaluator::evaluate( reinterpret_cast( lhs ), rhs ); -} -template bool compare( T* lhs, int rhs ) -{ - return Evaluator::evaluate( lhs, reinterpret_cast( rhs ) ); -} + // pointer to int (when comparing against NULL) + template bool compare( int lhs, T* rhs ) { + return Evaluator::evaluate( reinterpret_cast( lhs ), rhs ); + } + template bool compare( T* lhs, int rhs ) { + return Evaluator::evaluate( lhs, reinterpret_cast( rhs ) ); + } #ifdef CATCH_CONFIG_CPP11_NULLPTR -// pointer to nullptr_t (when comparing against nullptr) -template bool compare( std::nullptr_t, T* rhs ) -{ - return Evaluator::evaluate( NULL, rhs ); -} -template bool compare( T* lhs, std::nullptr_t ) -{ - return Evaluator::evaluate( lhs, NULL ); -} + // pointer to nullptr_t (when comparing against nullptr) + template bool compare( std::nullptr_t, T* rhs ) { + return Evaluator::evaluate( NULL, rhs ); + } + template bool compare( T* lhs, std::nullptr_t ) { + return Evaluator::evaluate( lhs, NULL ); + } #endif // CATCH_CONFIG_CPP11_NULLPTR } // end of namespace Internal } // end of namespace Catch #ifdef _MSC_VER - #pragma warning(pop) +#pragma warning(pop) #endif // #included from: catch_tostring.h @@ -1151,33 +953,30 @@ template bool compare( T* lhs, std::nullptr_t ) // Try to detect if the current compiler supports SFINAE -namespace Catch -{ +namespace Catch { -struct TrueType -{ - static const bool value = true; - typedef void Enable; - char sizer[1]; -}; -struct FalseType -{ - static const bool value = false; - typedef void Disable; - char sizer[2]; -}; + struct TrueType { + static const bool value = true; + typedef void Enable; + char sizer[1]; + }; + struct FalseType { + static const bool value = false; + typedef void Disable; + char sizer[2]; + }; #ifdef CATCH_CONFIG_SFINAE -template struct NotABooleanExpression; + template struct NotABooleanExpression; -template struct If : NotABooleanExpression {}; -template<> struct If : TrueType {}; -template<> struct If : FalseType {}; + template struct If : NotABooleanExpression {}; + template<> struct If : TrueType {}; + template<> struct If : FalseType {}; -template struct SizedIf; -template<> struct SizedIf : TrueType {}; -template<> struct SizedIf : FalseType {}; + template struct SizedIf; + template<> struct SizedIf : TrueType {}; + template<> struct SizedIf : FalseType {}; #endif // CATCH_CONFIG_SFINAE @@ -1196,41 +995,34 @@ template<> struct SizedIf : FalseType {}; #import #ifdef __has_feature - #define CATCH_ARC_ENABLED __has_feature(objc_arc) +#define CATCH_ARC_ENABLED __has_feature(objc_arc) #else - #define CATCH_ARC_ENABLED 0 +#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 ) -{ +inline void arcSafeRelease( NSObject* obj ) { [obj release]; } -inline id performOptionalSelector( id obj, SEL sel ) -{ - if ( [obj respondsToSelector: sel] ) - { +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 ) -{ +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] ) - { + if( [obj respondsToSelector: sel] ) return [obj performSelector: sel]; - } #ifdef __clang__ #pragma clang diagnostic pop #endif @@ -1242,83 +1034,71 @@ inline id performOptionalSelector( id obj, SEL sel ) #endif -namespace Catch -{ -namespace Detail -{ +namespace Catch { +namespace Detail { // SFINAE is currently disabled by default for all compilers. // If the non SFINAE version of IsStreamInsertable is ambiguous for you // and your compiler supports SFINAE, try #defining CATCH_CONFIG_SFINAE #ifdef CATCH_CONFIG_SFINAE -template -class IsStreamInsertableHelper -{ - template struct TrueIfSizeable : TrueType {}; + template + class IsStreamInsertableHelper { + template struct TrueIfSizeable : TrueType {}; - template - static TrueIfSizeable < sizeof((*(std::ostream*)0) << * ((T2 const*)0)) > dummy(T2*); - static FalseType dummy(...); + template + static TrueIfSizeable dummy(T2*); + static FalseType dummy(...); - public: - typedef SizedIf type; -}; + public: + typedef SizedIf type; + }; -template -struct IsStreamInsertable : IsStreamInsertableHelper::type {}; + template + struct IsStreamInsertable : IsStreamInsertableHelper::type {}; #else -struct BorgType -{ - template BorgType( T const&); -}; + struct BorgType { + template BorgType( T const& ); + }; -TrueType& testStreamable( std::ostream&); -FalseType testStreamable( FalseType ); + TrueType& testStreamable( std::ostream& ); + FalseType testStreamable( FalseType ); -FalseType operator<<( std::ostream const&, BorgType const&); + FalseType operator<<( std::ostream const&, BorgType const& ); -template -struct IsStreamInsertable -{ - static std::ostream& s; - static T const& t; - enum { value = sizeof( testStreamable(s << t) ) == sizeof( TrueType ) }; -}; + template + struct IsStreamInsertable { + static std::ostream &s; + static T const&t; + enum { value = sizeof( testStreamable(s << t) ) == sizeof( TrueType ) }; + }; #endif -template -struct StringMakerBase -{ + template + struct StringMakerBase { + template + static std::string convert( T const& ) { return "{?}"; } + }; + + template<> + struct StringMakerBase { + template + 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 - static std::string convert( T const&) - { - return "{?}"; + inline std::string rawMemoryToString( const T& object ) { + return rawMemoryToString( &object, sizeof(object) ); } -}; - -template<> -struct StringMakerBase -{ - template - 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 -inline std::string rawMemoryToString( const T& object ) -{ - return rawMemoryToString( &object, sizeof(object) ); -} } // end namespace Detail @@ -1330,60 +1110,43 @@ struct StringMaker : Detail::StringMakerBase::value> {}; template -struct StringMaker -{ +struct StringMaker { template - static std::string convert( U* p ) - { - if ( !p ) - { + static std::string convert( U* p ) { + if( !p ) return INTERNAL_CATCH_STRINGIFY( NULL ); - } else - { return Detail::rawMemoryToString( p ); - } } }; template -struct StringMaker -{ - static std::string convert( R C::* p ) - { - if ( !p ) - { +struct StringMaker { + static std::string convert( R C::* p ) { + if( !p ) return INTERNAL_CATCH_STRINGIFY( NULL ); - } else - { return Detail::rawMemoryToString( p ); - } } }; -namespace Detail -{ -template -std::string rangeToString( InputIterator first, InputIterator last ); +namespace Detail { + template + std::string rangeToString( InputIterator first, InputIterator last ); } template -struct StringMaker> -{ - static std::string convert( std::vector const& v ) - { +struct StringMaker > { + static std::string convert( std::vector const& v ) { return Detail::rangeToString( v.begin(), v.end() ); } }; -namespace Detail -{ -template -std::string makeString( T const& value ) -{ - return StringMaker::convert( value ); -} +namespace Detail { + template + std::string makeString( T const& value ) { + return StringMaker::convert( value ); + } } // end namespace Detail /// \brief converts any type to a string @@ -1394,8 +1157,7 @@ std::string makeString( T const& value ) /// Overload (not specialise) this template for custom typs that you don't want /// to provide an ostream overload for. template -std::string toString( T const& value ) -{ +std::string toString( T const& value ) { return StringMaker::convert( value ); } @@ -1418,139 +1180,117 @@ std::string toString( signed char value ); std::string toString( unsigned char value ); #ifdef CATCH_CONFIG_CPP11_NULLPTR - std::string toString( std::nullptr_t ); +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( NSString const * const& nsstring ); + std::string toString( NSString * CATCH_ARC_STRONG const& nsstring ); std::string toString( NSObject* const& nsObject ); #endif -namespace Detail -{ -template -std::string rangeToString( InputIterator first, InputIterator last ) -{ - std::ostringstream oss; - oss << "{ "; - if ( first != last ) - { - oss << toString( *first ); - for ( ++first ; first != last ; ++first ) - { - oss << ", " << toString( *first ); + namespace Detail { + template + std::string rangeToString( InputIterator first, InputIterator last ) { + std::ostringstream oss; + oss << "{ "; + if( first != last ) { + oss << toString( *first ); + for( ++first ; first != last ; ++first ) { + oss << ", " << toString( *first ); + } } + oss << " }"; + return oss.str(); } - oss << " }"; - return oss.str(); -} } } // end namespace Catch -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 -class ExpressionLhs -{ - ExpressionLhs& operator = ( ExpressionLhs const&); +class ExpressionLhs { + ExpressionLhs& operator = ( ExpressionLhs const& ); # ifdef CATCH_CPP11_OR_GREATER - ExpressionLhs& operator = ( ExpressionLhs&&) = delete; + ExpressionLhs& operator = ( ExpressionLhs && ) = delete; # endif - public: +public: ExpressionLhs( ResultBuilder& rb, T lhs ) : m_rb( rb ), m_lhs( lhs ) {} # ifdef CATCH_CPP11_OR_GREATER - ExpressionLhs( ExpressionLhs const&) = default; - ExpressionLhs( ExpressionLhs&&) = default; + ExpressionLhs( ExpressionLhs const& ) = default; + ExpressionLhs( ExpressionLhs && ) = default; # endif template - ResultBuilder& operator == ( RhsT const& rhs ) - { + ResultBuilder& operator == ( RhsT const& rhs ) { return captureExpression( rhs ); } template - ResultBuilder& operator != ( RhsT const& rhs ) - { + ResultBuilder& operator != ( RhsT const& rhs ) { return captureExpression( rhs ); } template - ResultBuilder& operator < ( RhsT const& rhs ) - { + ResultBuilder& operator < ( RhsT const& rhs ) { return captureExpression( rhs ); } template - ResultBuilder& operator > ( RhsT const& rhs ) - { + ResultBuilder& operator > ( RhsT const& rhs ) { return captureExpression( rhs ); } template - ResultBuilder& operator <= ( RhsT const& rhs ) - { + ResultBuilder& operator <= ( RhsT const& rhs ) { return captureExpression( rhs ); } template - ResultBuilder& operator >= ( RhsT const& rhs ) - { + ResultBuilder& operator >= ( RhsT const& rhs ) { return captureExpression( rhs ); } - ResultBuilder& operator == ( bool rhs ) - { + ResultBuilder& operator == ( bool rhs ) { return captureExpression( rhs ); } - ResultBuilder& operator != ( bool rhs ) - { + ResultBuilder& operator != ( bool rhs ) { return captureExpression( rhs ); } - void endExpression() - { + void endExpression() { bool value = m_lhs ? true : false; m_rb - .setLhs( Catch::toString( value ) ) - .setResultType( value ) - .endExpression(); + .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 STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& - operator + ( RhsT const&); - template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& - operator - ( RhsT const&); - template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& - operator / ( RhsT const&); - template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& - operator * ( RhsT const&); - template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& - operator && ( RhsT const&); - template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& - operator || ( RhsT const&); + template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator + ( RhsT const& ); + template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator - ( RhsT const& ); + template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator / ( RhsT const& ); + template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator * ( RhsT const& ); + template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator && ( RhsT const& ); + template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator || ( RhsT const& ); - private: +private: template - ResultBuilder& captureExpression( RhsT const& rhs ) - { + ResultBuilder& captureExpression( RhsT const& rhs ) { return m_rb - .setResultType( Internal::compare( m_lhs, rhs ) ) - .setLhs( Catch::toString( m_lhs ) ) - .setRhs( Catch::toString( rhs ) ) - .setOp( Internal::OperatorTraits::getName() ); + .setResultType( Internal::compare( m_lhs, rhs ) ) + .setLhs( Catch::toString( m_lhs ) ) + .setRhs( Catch::toString( rhs ) ) + .setOp( Internal::OperatorTraits::getName() ); } - private: +private: ResultBuilder& m_rb; T m_lhs; }; @@ -1558,19 +1298,16 @@ class ExpressionLhs } // end namespace Catch -namespace Catch -{ +namespace Catch { -template -inline ExpressionLhs ResultBuilder::operator->* ( T const& operand ) -{ - return ExpressionLhs( *this, operand ); -} + template + inline ExpressionLhs ResultBuilder::operator->* ( T const& operand ) { + return ExpressionLhs( *this, operand ); + } -inline ExpressionLhs ResultBuilder::operator->* ( bool value ) -{ - return ExpressionLhs( *this, value ); -} + inline ExpressionLhs ResultBuilder::operator->* ( bool value ) { + return ExpressionLhs( *this, value ); + } } // namespace Catch @@ -1579,61 +1316,54 @@ inline ExpressionLhs ResultBuilder::operator->* ( bool value ) #include -namespace Catch -{ +namespace Catch { -struct MessageInfo -{ - MessageInfo( std::string const& _macroName, - SourceLineInfo const& _lineInfo, - ResultWas::OfType _type ); + 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; + 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; -}; + 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 ) + struct MessageBuilder { + MessageBuilder( std::string const& macroName, + SourceLineInfo const& lineInfo, + ResultWas::OfType type ) : m_info( macroName, lineInfo, type ) - {} + {} - template - MessageBuilder& operator << ( T const& value ) - { - m_stream << value; - return *this; - } + template + MessageBuilder& operator << ( T const& value ) { + m_stream << value; + return *this; + } - MessageInfo m_info; - std::ostringstream m_stream; -}; + MessageInfo m_info; + std::ostringstream m_stream; + }; -class ScopedMessage -{ - public: - ScopedMessage( MessageBuilder const& builder ); - ScopedMessage( ScopedMessage const& other ); - ~ScopedMessage(); + class ScopedMessage { + public: + ScopedMessage( MessageBuilder const& builder ); + ScopedMessage( ScopedMessage const& other ); + ~ScopedMessage(); - MessageInfo m_info; -}; + MessageInfo m_info; + }; } // end namespace Catch @@ -1642,35 +1372,32 @@ class ScopedMessage #include -namespace Catch -{ +namespace Catch { -class TestCase; -class AssertionResult; -struct AssertionInfo; -struct SectionInfo; -struct MessageInfo; -class ScopedMessageBuilder; -struct Counts; + class TestCase; + class AssertionResult; + struct AssertionInfo; + struct SectionInfo; + struct MessageInfo; + class ScopedMessageBuilder; + struct Counts; -struct IResultCapture -{ + struct IResultCapture { - virtual ~IResultCapture(); + virtual ~IResultCapture(); - virtual void assertionEnded( AssertionResult const& result ) = 0; - virtual bool sectionStarted( SectionInfo const& sectionInfo, - Counts& assertions ) = 0; - virtual void sectionEnded( SectionInfo const& name, Counts const& assertions, - double _durationInSeconds ) = 0; - virtual void pushScopedMessage( MessageInfo const& message ) = 0; - virtual void popScopedMessage( MessageInfo const& message ) = 0; + virtual void assertionEnded( AssertionResult const& result ) = 0; + virtual bool sectionStarted( SectionInfo const& sectionInfo, + Counts& assertions ) = 0; + virtual void sectionEnded( SectionInfo const& name, Counts const& assertions, double _durationInSeconds ) = 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 std::string getCurrentTestName() const = 0; + virtual const AssertionResult* getLastResult() const = 0; + }; -IResultCapture& getResultCapture(); + IResultCapture& getResultCapture(); } // #included from: catch_debugger.h @@ -1680,61 +1407,58 @@ IResultCapture& getResultCapture(); #define TWOBLUECUBES_CATCH_PLATFORM_H_INCLUDED #if defined(__MAC_OS_X_VERSION_MIN_REQUIRED) - #define CATCH_PLATFORM_MAC +#define CATCH_PLATFORM_MAC #elif defined(__IPHONE_OS_VERSION_MIN_REQUIRED) - #define CATCH_PLATFORM_IPHONE +#define CATCH_PLATFORM_IPHONE #elif defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) - #define CATCH_PLATFORM_WINDOWS +#define CATCH_PLATFORM_WINDOWS #endif #include -namespace Catch -{ +namespace Catch{ -bool isDebuggerActive(); -void writeToDebugConsole( std::string const& text ); + 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 + // 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(); } + #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(); } + 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(); +#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; +namespace Catch { + class TestCase; -struct IRunner -{ - virtual ~IRunner(); - virtual bool aborting() const = 0; -}; + struct IRunner { + virtual ~IRunner(); + virtual bool aborting() const = 0; + }; } /////////////////////////////////////////////////////////////////////////////// @@ -1822,21 +1546,21 @@ struct IRunner /////////////////////////////////////////////////////////////////////////////// #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() ) + #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() ) + #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 /////////////////////////////////////////////////////////////////////////////// @@ -1850,10 +1574,10 @@ struct IRunner try { \ std::string matcherAsString = ::Catch::Matchers::matcher.toString(); \ __catchResult \ - .setLhs( Catch::toString( arg ) ) \ - .setRhs( matcherAsString == "{?}" ? #matcher : matcherAsString ) \ - .setOp( "matches" ) \ - .setResultType( ::Catch::Matchers::matcher.match( arg ) ); \ + .setLhs( Catch::toString( arg ) ) \ + .setRhs( matcherAsString == "{?}" ? #matcher : matcherAsString ) \ + .setOp( "matches" ) \ + .setResultType( ::Catch::Matchers::matcher.match( arg ) ); \ __catchResult.captureExpression(); \ } catch( ... ) { \ __catchResult.useActiveException( resultDisposition | Catch::ResultDisposition::ContinueOnFailure ); \ @@ -1867,20 +1591,18 @@ struct IRunner // #included from: catch_section_info.h #define TWOBLUECUBES_CATCH_SECTION_INFO_H_INCLUDED -namespace Catch -{ +namespace Catch { -struct SectionInfo -{ - SectionInfo - ( SourceLineInfo const& _lineInfo, - std::string const& _name, - std::string const& _description = std::string() ); + struct SectionInfo { + SectionInfo + ( SourceLineInfo const& _lineInfo, + std::string const& _name, + std::string const& _description = std::string() ); - std::string name; - std::string description; - SourceLineInfo lineInfo; -}; + std::string name; + std::string description; + SourceLineInfo lineInfo; + }; } // end namespace Catch @@ -1889,151 +1611,131 @@ struct SectionInfo #include -namespace Catch -{ +namespace Catch { -struct Counts -{ - Counts() : passed( 0 ), failed( 0 ), failedButOk( 0 ) {} + 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; - } - - 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; + 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; } - else if ( diff.assertions.failedButOk > 0 ) - { - ++diff.testCases.failedButOk; + Counts& operator += ( Counts const& other ) { + passed += other.passed; + failed += other.failed; + failedButOk += other.failedButOk; + return *this; } - else - { - ++diff.testCases.passed; + + std::size_t total() const { + return passed + failed + failedButOk; + } + bool allPassed() const { + return failed == 0 && failedButOk == 0; } - return diff; - } - Totals& operator += ( Totals const& other ) - { - assertions += other.assertions; - testCases += other.testCases; - return *this; - } + std::size_t passed; + std::size_t failed; + std::size_t failedButOk; + }; - Counts assertions; - Counts testCases; -}; + 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; + }; } // #included from: catch_timer.h #define TWOBLUECUBES_CATCH_TIMER_H_INCLUDED #ifdef CATCH_PLATFORM_WINDOWS - typedef unsigned long long uint64_t; +typedef unsigned long long uint64_t; #else - #include +#include #endif -namespace Catch -{ +namespace Catch { -class Timer -{ - public: - Timer() : m_ticks( 0 ) {} - void start(); - unsigned int getElapsedNanoseconds() const; - unsigned int getElapsedMilliseconds() const; - double getElapsedSeconds() const; + class Timer { + public: + Timer() : m_ticks( 0 ) {} + void start(); + unsigned int getElapsedNanoseconds() const; + unsigned int getElapsedMilliseconds() const; + double getElapsedSeconds() const; - private: - uint64_t m_ticks; -}; + private: + uint64_t m_ticks; + }; } // namespace Catch #include -namespace Catch -{ +namespace Catch { -class Section -{ - public: - Section( SectionInfo const& info ); - ~Section(); + class Section { + public: + Section( SectionInfo const& info ); + ~Section(); - // This indicates whether the section should be executed or not - operator bool() const; + // This indicates whether the section should be executed or not + operator bool() const; - private: + private: #ifdef CATCH_CPP11_OR_GREATER - Section( Section const&) = delete; - Section( Section&&) = delete; - Section& operator = ( Section const&) = delete; - Section& operator = ( Section&&) = delete; + Section( Section const& ) = delete; + Section( Section && ) = delete; + Section& operator = ( Section const& ) = delete; + Section& operator = ( Section && ) = delete; #else - Section( Section const& info ); - Section& operator = ( Section const&); + Section( Section const& info ); + Section& operator = ( Section const& ); #endif - SectionInfo m_info; + SectionInfo m_info; - std::string m_name; - Counts m_assertions; - bool m_sectionIncluded; - Timer m_timer; -}; + 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__ ) ) + #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 ) ) + #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 @@ -2044,101 +1746,88 @@ class Section #include #include -namespace Catch -{ +namespace Catch { template -struct IGenerator -{ +struct IGenerator { virtual ~IGenerator() {} virtual T getValue( std::size_t index ) const = 0; virtual std::size_t size () const = 0; }; template -class BetweenGenerator : public IGenerator -{ - public: - BetweenGenerator( T from, T to ) : m_from( from ), m_to( to ) {} +class BetweenGenerator : public IGenerator { +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( index ); + virtual T getValue( std::size_t index ) const { + return m_from+static_cast( index ); } - virtual std::size_t size() const - { - return static_cast( 1 + m_to - m_from ); + virtual std::size_t size() const { + return static_cast( 1+m_to-m_from ); } - private: +private: T m_from; T m_to; }; template -class ValuesGenerator : public IGenerator -{ - public: - ValuesGenerator() {} +class ValuesGenerator : public IGenerator { +public: + ValuesGenerator(){} - void add( T value ) - { + void add( T value ) { m_values.push_back( value ); } - virtual T getValue( std::size_t index ) const - { + virtual T getValue( std::size_t index ) const { return m_values[index]; } - virtual std::size_t size() const - { + virtual std::size_t size() const { return m_values.size(); } - private: +private: std::vector m_values; }; template -class CompositeGenerator -{ - public: +class CompositeGenerator { +public: CompositeGenerator() : m_totalSize( 0 ) {} // *** Move semantics, similar to auto_ptr *** CompositeGenerator( CompositeGenerator& other ) - : m_fileInfo( other.m_fileInfo ), - m_totalSize( 0 ) + : m_fileInfo( other.m_fileInfo ), + m_totalSize( 0 ) { move( other ); } - CompositeGenerator& setFileInfo( const char* fileInfo ) - { + CompositeGenerator& setFileInfo( const char* fileInfo ) { m_fileInfo = fileInfo; return *this; } - ~CompositeGenerator() - { + ~CompositeGenerator() { deleteAll( m_composed ); } - operator T () const - { + operator T () const { size_t overallIndex = getCurrentContext().getGeneratorIndex( m_fileInfo, m_totalSize ); typename std::vector*>::const_iterator it = m_composed.begin(); typename std::vector*>::const_iterator itEnd = m_composed.end(); - for ( size_t index = 0; it != itEnd; ++it ) + for( size_t index = 0; it != itEnd; ++it ) { const IGenerator* generator = *it; - if ( overallIndex >= index && overallIndex < index + generator->size() ) + if( overallIndex >= index && overallIndex < index + generator->size() ) { - return generator->getValue( overallIndex - index ); + return generator->getValue( overallIndex-index ); } index += generator->size(); } @@ -2146,30 +1835,26 @@ class CompositeGenerator 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* generator ) - { + void add( const IGenerator* generator ) { m_totalSize += generator->size(); m_composed.push_back( generator ); } - CompositeGenerator& then( CompositeGenerator& other ) - { + CompositeGenerator& then( CompositeGenerator& other ) { move( other ); return *this; } - CompositeGenerator& then( T value ) - { + CompositeGenerator& then( T value ) { ValuesGenerator* valuesGen = new ValuesGenerator(); valuesGen->add( value ); add( valuesGen ); return *this; } - private: +private: - void move( CompositeGenerator& other ) - { + 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(); @@ -2182,49 +1867,45 @@ class CompositeGenerator namespace Generators { -template -CompositeGenerator between( T from, T to ) -{ - CompositeGenerator generators; - generators.add( new BetweenGenerator( from, to ) ); - return generators; -} + template + CompositeGenerator between( T from, T to ) { + CompositeGenerator generators; + generators.add( new BetweenGenerator( from, to ) ); + return generators; + } -template -CompositeGenerator values( T val1, T val2 ) -{ - CompositeGenerator generators; - ValuesGenerator* valuesGen = new ValuesGenerator(); - valuesGen->add( val1 ); - valuesGen->add( val2 ); - generators.add( valuesGen ); - return generators; -} + template + CompositeGenerator values( T val1, T val2 ) { + CompositeGenerator generators; + ValuesGenerator* valuesGen = new ValuesGenerator(); + valuesGen->add( val1 ); + valuesGen->add( val2 ); + generators.add( valuesGen ); + return generators; + } -template -CompositeGenerator values( T val1, T val2, T val3 ) -{ - CompositeGenerator generators; - ValuesGenerator* valuesGen = new ValuesGenerator(); - valuesGen->add( val1 ); - valuesGen->add( val2 ); - valuesGen->add( val3 ); - generators.add( valuesGen ); - return generators; -} + template + CompositeGenerator values( T val1, T val2, T val3 ){ + CompositeGenerator generators; + ValuesGenerator* valuesGen = new ValuesGenerator(); + valuesGen->add( val1 ); + valuesGen->add( val2 ); + valuesGen->add( val3 ); + generators.add( valuesGen ); + return generators; + } -template -CompositeGenerator values( T val1, T val2, T val3, T val4 ) -{ - CompositeGenerator generators; - ValuesGenerator* valuesGen = new ValuesGenerator(); - valuesGen->add( val1 ); - valuesGen->add( val2 ); - valuesGen->add( val3 ); - valuesGen->add( val4 ); - generators.add( valuesGen ); - return generators; -} + template + CompositeGenerator values( T val1, T val2, T val3, T val4 ) { + CompositeGenerator generators; + ValuesGenerator* valuesGen = new ValuesGenerator(); + valuesGen->add( val1 ); + valuesGen->add( val2 ); + valuesGen->add( val3 ); + valuesGen->add( val4 ); + generators.add( valuesGen ); + return generators; + } } // end namespace Generators @@ -2246,94 +1927,82 @@ using namespace Generators; #include -namespace Catch -{ +namespace Catch { -class TestCase; -struct ITestCaseRegistry; -struct IExceptionTranslatorRegistry; -struct IExceptionTranslator; -struct IReporterRegistry; -struct IReporterFactory; + class TestCase; + struct ITestCaseRegistry; + struct IExceptionTranslatorRegistry; + struct IExceptionTranslator; + struct IReporterRegistry; + struct IReporterFactory; -struct IRegistryHub -{ - virtual ~IRegistryHub(); + struct IRegistryHub { + virtual ~IRegistryHub(); - virtual IReporterRegistry const& getReporterRegistry() const = 0; - virtual ITestCaseRegistry const& getTestCaseRegistry() const = 0; - virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() = 0; -}; + 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, IReporterFactory* factory ) = 0; - virtual void registerTest( TestCase const& testInfo ) = 0; - virtual void registerTranslator( const IExceptionTranslator* translator ) = 0; -}; + struct IMutableRegistryHub { + virtual ~IMutableRegistryHub(); + virtual void registerReporter( std::string const& name, IReporterFactory* 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(); + IRegistryHub& getRegistryHub(); + IMutableRegistryHub& getMutableRegistryHub(); + void cleanUp(); + std::string translateActiveException(); } -namespace Catch -{ +namespace Catch { -typedef std::string(*exceptionTranslateFunction)(); + typedef std::string(*exceptionTranslateFunction)(); -struct IExceptionTranslator -{ - virtual ~IExceptionTranslator(); - virtual std::string translate() const = 0; -}; - -struct IExceptionTranslatorRegistry -{ - virtual ~IExceptionTranslatorRegistry(); - - virtual std::string translateActiveException() const = 0; -}; - -class ExceptionTranslatorRegistrar -{ - template - class ExceptionTranslator : public IExceptionTranslator - { - public: - - ExceptionTranslator( std::string(*translateFunction)( T&) ) - : m_translateFunction( translateFunction ) - {} - - virtual std::string translate() const - { - try - { - throw; - } - catch ( T& ex ) - { - return m_translateFunction( ex ); - } - } - - protected: - std::string(*m_translateFunction)( T&); + struct IExceptionTranslator { + virtual ~IExceptionTranslator(); + virtual std::string translate() const = 0; }; - public: - template - ExceptionTranslatorRegistrar( std::string(*translateFunction)( T&) ) - { - getMutableRegistryHub().registerTranslator - ( new ExceptionTranslator( translateFunction ) ); - } -}; + struct IExceptionTranslatorRegistry { + virtual ~IExceptionTranslatorRegistry(); + + virtual std::string translateActiveException() const = 0; + }; + + class ExceptionTranslatorRegistrar { + template + class ExceptionTranslator : public IExceptionTranslator { + public: + + ExceptionTranslator( std::string(*translateFunction)( T& ) ) + : m_translateFunction( translateFunction ) + {} + + virtual std::string translate() const { + try { + throw; + } + catch( T& ex ) { + return m_translateFunction( ex ); + } + } + + protected: + std::string(*m_translateFunction)( T& ); + }; + + public: + template + ExceptionTranslatorRegistrar( std::string(*translateFunction)( T& ) ) { + getMutableRegistryHub().registerTranslator + ( new ExceptionTranslator( translateFunction ) ); + } + }; } /////////////////////////////////////////////////////////////////////////////// @@ -2348,90 +2017,76 @@ class ExceptionTranslatorRegistrar #include #include -namespace Catch -{ -namespace Detail -{ +namespace Catch { +namespace Detail { -class Approx -{ - public: - explicit Approx ( double value ) - : m_epsilon( std::numeric_limits::epsilon() * 100 ), + class Approx { + public: + explicit Approx ( double value ) + : m_epsilon( std::numeric_limits::epsilon()*100 ), m_scale( 1.0 ), m_value( value ) - {} + {} - Approx( Approx const& other ) + 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 ); - } + static Approx custom() { + return Approx( 0 ); + } - Approx operator()( double value ) - { - Approx approx( value ); - approx.epsilon( m_epsilon ); - approx.scale( m_scale ); - return approx; - } + 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 == ( 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 == ( Approx const& lhs, double rhs ) { + return operator==( rhs, lhs ); + } - friend bool operator != ( double lhs, Approx const& rhs ) - { - return !operator==( lhs, rhs ); - } + friend bool operator != ( double lhs, Approx const& rhs ) { + return !operator==( lhs, rhs ); + } - friend bool operator != ( Approx const& lhs, double rhs ) - { - return !operator==( rhs, lhs ); - } + friend bool operator != ( Approx const& lhs, double rhs ) { + return !operator==( rhs, lhs ); + } - Approx& epsilon( double newEpsilon ) - { - m_epsilon = newEpsilon; - return *this; - } + Approx& epsilon( double newEpsilon ) { + m_epsilon = newEpsilon; + return *this; + } - Approx& scale( double newScale ) - { - m_scale = newScale; - 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(); - } + 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; -}; + private: + double m_epsilon; + double m_scale; + double m_value; + }; } template<> -inline std::string toString( Detail::Approx const& value ) -{ +inline std::string toString( Detail::Approx const& value ) { return value.toString(); } @@ -2440,274 +2095,221 @@ inline std::string toString( Detail::Approx const& value ) // #included from: internal/catch_matchers.hpp #define TWOBLUECUBES_CATCH_MATCHERS_HPP_INCLUDED -namespace Catch -{ -namespace Matchers -{ -namespace Impl -{ +namespace Catch { +namespace Matchers { + namespace Impl { -template -struct Matcher : SharedImpl -{ - typedef ExpressionT ExpressionType; - - virtual ~Matcher() {} - virtual Ptr clone() const = 0; - virtual bool match( ExpressionT const& expr ) const = 0; - virtual std::string toString() const = 0; -}; - -template -struct MatcherImpl : Matcher -{ - - virtual Ptr> clone() const + template + struct Matcher : SharedImpl { - return Ptr>( new DerivedT( static_cast( *this ) ) ); - } -}; + typedef ExpressionT ExpressionType; -namespace Generic -{ + virtual ~Matcher() {} + virtual Ptr clone() const = 0; + virtual bool match( ExpressionT const& expr ) const = 0; + virtual std::string toString() const = 0; + }; -template -class AllOf : public MatcherImpl, ExpressionT> -{ - public: + template + struct MatcherImpl : Matcher { - AllOf() {} - AllOf( AllOf const& other ) : m_matchers( other.m_matchers ) {} - - AllOf& add( Matcher 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(); + virtual Ptr > clone() const { + return Ptr >( new DerivedT( static_cast( *this ) ) ); } - oss << " )"; - return oss.str(); - } + }; - private: - std::vector>> m_matchers; -}; + namespace Generic { -template -class AnyOf : public MatcherImpl, ExpressionT> -{ - public: + template + class AllOf : public MatcherImpl, ExpressionT> { + public: - AnyOf() {} - AnyOf( AnyOf const& other ) : m_matchers( other.m_matchers ) {} + AllOf() {} + AllOf( AllOf const& other ) : m_matchers( other.m_matchers ) {} - AnyOf& add( Matcher 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 ) ) + AllOf& add( Matcher 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; } - 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 "; + 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(); } - oss << m_matchers[i]->toString(); - } - oss << " )"; - return oss.str(); + + private: + std::vector > > m_matchers; + }; + + template + class AnyOf : public MatcherImpl, ExpressionT> { + public: + + AnyOf() {} + AnyOf( AnyOf const& other ) : m_matchers( other.m_matchers ) {} + + AnyOf& add( Matcher 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(); + } + + private: + std::vector > > m_matchers; + }; + } - private: - std::vector>> m_matchers; -}; + 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(); } -namespace StdString -{ + struct Equals : MatcherImpl { + Equals( std::string const& str ) : m_str( str ){} + Equals( Equals const& other ) : m_str( other.m_str ){} -inline std::string makeString( std::string const& str ) -{ - return str; -} -inline std::string makeString( const char* str ) -{ - return str ? std::string( str ) : std::string(); -} + virtual ~Equals(); -struct Equals : MatcherImpl -{ - Equals( std::string const& str ) : m_str( str ) {} - Equals( Equals const& other ) : m_str( other.m_str ) {} + virtual bool match( std::string const& expr ) const { + return m_str == expr; + } + virtual std::string toString() const { + return "equals: \"" + m_str + "\""; + } - virtual ~Equals(); + std::string m_str; + }; - virtual bool match( std::string const& expr ) const - { - return m_str == expr; + struct Contains : MatcherImpl { + Contains( std::string const& substr ) : m_substr( substr ){} + Contains( Contains const& other ) : m_substr( other.m_substr ){} + + virtual ~Contains(); + + virtual bool match( std::string const& expr ) const { + return expr.find( m_substr ) != std::string::npos; + } + virtual std::string toString() const { + return "contains: \"" + m_substr + "\""; + } + + std::string m_substr; + }; + + struct StartsWith : MatcherImpl { + StartsWith( std::string const& substr ) : m_substr( substr ){} + StartsWith( StartsWith const& other ) : m_substr( other.m_substr ){} + + virtual ~StartsWith(); + + virtual bool match( std::string const& expr ) const { + return expr.find( m_substr ) == 0; + } + virtual std::string toString() const { + return "starts with: \"" + m_substr + "\""; + } + + std::string m_substr; + }; + + struct EndsWith : MatcherImpl { + EndsWith( std::string const& substr ) : m_substr( substr ){} + EndsWith( EndsWith const& other ) : m_substr( other.m_substr ){} + + virtual ~EndsWith(); + + virtual bool match( std::string const& expr ) const { + return expr.find( m_substr ) == expr.size() - m_substr.size(); + } + virtual std::string toString() const { + return "ends with: \"" + m_substr + "\""; + } + + std::string m_substr; + }; + } // namespace StdString + } // namespace Impl + + // The following functions create the actual matcher objects. + // This allows the types to be inferred + template + inline Impl::Generic::AllOf AllOf( Impl::Matcher const& m1, + Impl::Matcher const& m2 ) { + return Impl::Generic::AllOf().add( m1 ).add( m2 ); } - virtual std::string toString() const - { - return "equals: \"" + m_str + "\""; + template + inline Impl::Generic::AllOf AllOf( Impl::Matcher const& m1, + Impl::Matcher const& m2, + Impl::Matcher const& m3 ) { + return Impl::Generic::AllOf().add( m1 ).add( m2 ).add( m3 ); + } + template + inline Impl::Generic::AnyOf AnyOf( Impl::Matcher const& m1, + Impl::Matcher const& m2 ) { + return Impl::Generic::AnyOf().add( m1 ).add( m2 ); + } + template + inline Impl::Generic::AnyOf AnyOf( Impl::Matcher const& m1, + Impl::Matcher const& m2, + Impl::Matcher const& m3 ) { + return Impl::Generic::AnyOf().add( m1 ).add( m2 ).add( m3 ); } - std::string m_str; -}; - -struct Contains : MatcherImpl -{ - Contains( std::string const& substr ) : m_substr( substr ) {} - Contains( Contains const& other ) : m_substr( other.m_substr ) {} - - virtual ~Contains(); - - virtual bool match( std::string const& expr ) const - { - return expr.find( m_substr ) != std::string::npos; + inline Impl::StdString::Equals Equals( std::string const& str ) { + return Impl::StdString::Equals( str ); } - virtual std::string toString() const - { - return "contains: \"" + m_substr + "\""; + inline Impl::StdString::Equals Equals( const char* str ) { + return Impl::StdString::Equals( Impl::StdString::makeString( str ) ); } - - std::string m_substr; -}; - -struct StartsWith : MatcherImpl -{ - StartsWith( std::string const& substr ) : m_substr( substr ) {} - StartsWith( StartsWith const& other ) : m_substr( other.m_substr ) {} - - virtual ~StartsWith(); - - virtual bool match( std::string const& expr ) const - { - return expr.find( m_substr ) == 0; + inline Impl::StdString::Contains Contains( std::string const& substr ) { + return Impl::StdString::Contains( substr ); } - virtual std::string toString() const - { - return "starts with: \"" + m_substr + "\""; + inline Impl::StdString::Contains Contains( const char* substr ) { + return Impl::StdString::Contains( Impl::StdString::makeString( substr ) ); } - - std::string m_substr; -}; - -struct EndsWith : MatcherImpl -{ - EndsWith( std::string const& substr ) : m_substr( substr ) {} - EndsWith( EndsWith const& other ) : m_substr( other.m_substr ) {} - - virtual ~EndsWith(); - - virtual bool match( std::string const& expr ) const - { - return expr.find( m_substr ) == expr.size() - m_substr.size(); + inline Impl::StdString::StartsWith StartsWith( std::string const& substr ) { + return Impl::StdString::StartsWith( substr ); } - virtual std::string toString() const - { - return "ends with: \"" + m_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 ) ); } - - std::string m_substr; -}; -} // namespace StdString -} // namespace Impl - -// The following functions create the actual matcher objects. -// This allows the types to be inferred -template -inline Impl::Generic::AllOf AllOf( Impl::Matcher const& m1, - Impl::Matcher const& m2 ) -{ - return Impl::Generic::AllOf().add( m1 ).add( m2 ); -} -template -inline Impl::Generic::AllOf AllOf( Impl::Matcher const& m1, - Impl::Matcher const& m2, - Impl::Matcher const& m3 ) -{ - return Impl::Generic::AllOf().add( m1 ).add( m2 ).add( m3 ); -} -template -inline Impl::Generic::AnyOf AnyOf( Impl::Matcher const& m1, - Impl::Matcher const& m2 ) -{ - return Impl::Generic::AnyOf().add( m1 ).add( m2 ); -} -template -inline Impl::Generic::AnyOf AnyOf( Impl::Matcher const& m1, - Impl::Matcher const& m2, - Impl::Matcher const& m3 ) -{ - return Impl::Generic::AnyOf().add( m1 ).add( m2 ).add( m3 ); -} - -inline Impl::StdString::Equals Equals( std::string const& str ) -{ - return Impl::StdString::Equals( str ); -} -inline Impl::StdString::Equals Equals( const char* str ) -{ - return Impl::StdString::Equals( Impl::StdString::makeString( str ) ); -} -inline Impl::StdString::Contains Contains( std::string const& substr ) -{ - return Impl::StdString::Contains( substr ); -} -inline Impl::StdString::Contains Contains( const char* substr ) -{ - return Impl::StdString::Contains( Impl::StdString::makeString( substr ) ); -} -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 @@ -2723,21 +2325,18 @@ using namespace Matchers; #include -namespace Catch -{ +namespace Catch { -struct TagAlias -{ - TagAlias( std::string _tag, SourceLineInfo _lineInfo ) : tag( _tag ), lineInfo( _lineInfo ) {} + struct TagAlias { + TagAlias( std::string _tag, SourceLineInfo _lineInfo ) : tag( _tag ), lineInfo( _lineInfo ) {} - std::string tag; - SourceLineInfo lineInfo; -}; + std::string tag; + SourceLineInfo lineInfo; + }; -struct RegistrarForTagAliases -{ - RegistrarForTagAliases( char const* alias, char const* tag, SourceLineInfo const& lineInfo ); -}; + struct RegistrarForTagAliases { + RegistrarForTagAliases( char const* alias, char const* tag, SourceLineInfo const& lineInfo ); + }; } // end namespace Catch @@ -2745,113 +2344,77 @@ struct RegistrarForTagAliases // #included from: catch_option.hpp #define TWOBLUECUBES_CATCH_OPTION_HPP_INCLUDED -namespace Catch -{ +namespace Catch { -// An optional type -template -class Option -{ - public: - Option() : nullableValue( NULL ) {} - Option( T const& _value ) + // An optional type + template + class Option { + public: + Option() : nullableValue( NULL ) {} + Option( T const& _value ) : nullableValue( new( storage ) T( _value ) ) - {} - Option( Option const& _other ) + {} + Option( Option const& _other ) : nullableValue( _other ? new( storage ) T( *_other ) : NULL ) - {} + {} - ~Option() - { - reset(); - } - - Option& operator= ( Option const& _other ) - { - if ( &_other != this ) - { + ~Option() { reset(); - if ( _other ) - { - nullableValue = new( storage ) T( *_other ); + } + + Option& operator= ( Option const& _other ) { + if( &_other != this ) { + reset(); + if( _other ) + nullableValue = new( storage ) T( *_other ); } + return *this; } - return *this; - } - Option& operator = ( T const& _value ) - { - reset(); - nullableValue = new( storage ) T( _value ); - return *this; - } - - void reset() - { - if ( nullableValue ) - { - nullableValue->~T(); + Option& operator = ( T const& _value ) { + reset(); + nullableValue = new( storage ) T( _value ); + return *this; } - nullableValue = NULL; - } - T& operator*() - { - return *nullableValue; - } - T const& operator*() const - { - return *nullableValue; - } - T* operator->() - { - return nullableValue; - } - const T* operator->() const - { - return nullableValue; - } + void reset() { + if( nullableValue ) + nullableValue->~T(); + nullableValue = NULL; + } - T valueOr( T const& defaultValue ) const - { - return nullableValue ? *nullableValue : defaultValue; - } + T& operator*() { return *nullableValue; } + T const& operator*() const { return *nullableValue; } + T* operator->() { return nullableValue; } + const T* operator->() const { return nullableValue; } - bool some() const - { - return nullableValue != NULL; - } - bool none() const - { - return nullableValue == NULL; - } + T valueOr( T const& defaultValue ) const { + return nullableValue ? *nullableValue : defaultValue; + } - bool operator !() const - { - return nullableValue == NULL; - } - operator SafeBool::type() const - { - return SafeBool::makeSafe( some() ); - } + bool some() const { return nullableValue != NULL; } + bool none() const { return nullableValue == NULL; } - private: - T* nullableValue; - char storage[sizeof(T)]; -}; + bool operator !() const { return nullableValue == NULL; } + operator SafeBool::type() const { + return SafeBool::makeSafe( some() ); + } + + private: + T* nullableValue; + char storage[sizeof(T)]; + }; } // end namespace Catch -namespace Catch -{ +namespace Catch { -struct ITagAliasRegistry -{ - virtual ~ITagAliasRegistry(); - virtual Option find( std::string const& alias ) const = 0; - virtual std::string expandAliases( std::string const& unexpandedTestSpec ) const = 0; + struct ITagAliasRegistry { + virtual ~ITagAliasRegistry(); + virtual Option find( std::string const& alias ) const = 0; + virtual std::string expandAliases( std::string const& unexpandedTestSpec ) const = 0; - static ITagAliasRegistry const& get(); -}; + static ITagAliasRegistry const& get(); + }; } // end namespace Catch @@ -2864,80 +2427,76 @@ struct ITagAliasRegistry #include #ifdef __clang__ - #pragma clang diagnostic push - #pragma clang diagnostic ignored "-Wpadded" +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wpadded" #endif -namespace Catch -{ +namespace Catch { -struct ITestCase; + struct ITestCase; -struct TestCaseInfo -{ - enum SpecialProperties - { - None = 0, - IsHidden = 1 << 1, - ShouldFail = 1 << 2, - MayFail = 1 << 3, - Throws = 1 << 4 + 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 const& _tags, + SourceLineInfo const& _lineInfo ); + + TestCaseInfo( TestCaseInfo const& other ); + + bool isHidden() const; + bool throws() const; + bool okToFail() const; + bool expectedToFail() const; + + std::string name; + std::string className; + std::string description; + std::set tags; + std::set lcaseTags; + std::string tagsAsString; + SourceLineInfo lineInfo; + SpecialProperties properties; }; - TestCaseInfo( std::string const& _name, - std::string const& _className, - std::string const& _description, - std::set const& _tags, - SourceLineInfo const& _lineInfo ); + class TestCase : public TestCaseInfo { + public: - TestCaseInfo( TestCaseInfo const& other ); + TestCase( ITestCase* testCase, TestCaseInfo const& info ); + TestCase( TestCase const& other ); - bool isHidden() const; - bool throws() const; - bool okToFail() const; - bool expectedToFail() const; + TestCase withName( std::string const& _newName ) const; - std::string name; - std::string className; - std::string description; - std::set tags; - std::set lcaseTags; - std::string tagsAsString; - SourceLineInfo lineInfo; - SpecialProperties properties; -}; + void invoke() const; -class TestCase : public TestCaseInfo -{ - public: + TestCaseInfo const& getTestCaseInfo() const; - TestCase( ITestCase* testCase, TestCaseInfo const& info ); - TestCase( TestCase const& other ); + void swap( TestCase& other ); + bool operator == ( TestCase const& other ) const; + bool operator < ( TestCase const& other ) const; + TestCase& operator = ( TestCase const& other ); - TestCase withName( std::string const& _newName ) const; + private: + Ptr test; + }; - 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 test; -}; - -TestCase makeTestCase( ITestCase* testCase, - std::string const& className, - std::string const& name, - std::string const& description, - SourceLineInfo const& lineInfo ); + 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 +#pragma clang diagnostic pop #endif @@ -2965,215 +2524,173 @@ TestCase makeTestCase( ITestCase* testCase, @end -namespace Catch -{ +namespace Catch { -class OcMethod : public SharedImpl -{ + class OcMethod : public SharedImpl { - public: - OcMethod( Class cls, SEL sel ) : m_cls( cls ), m_sel( sel ) {} + public: + OcMethod( Class cls, SEL sel ) : m_cls( cls ), m_sel( sel ) {} - virtual void invoke() const - { - id obj = [[m_cls alloc] init]; + virtual void invoke() const { + id obj = [[m_cls alloc] init]; - performOptionalSelector( obj, @selector(setUp) ); - performOptionalSelector( obj, m_sel ); - performOptionalSelector( obj, @selector(tearDown) ); + performOptionalSelector( obj, @selector(setUp) ); + performOptionalSelector( obj, m_sel ); + performOptionalSelector( obj, @selector(tearDown) ); - arcSafeRelease( obj ); - } - private: - virtual ~OcMethod() {} + arcSafeRelease( obj ); + } + private: + virtual ~OcMethod() {} - Class m_cls; - SEL m_sel; -}; + Class m_cls; + SEL m_sel; + }; -namespace Detail -{ + 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( 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); + 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 ""; } } - return noTestMethods; -} -namespace Matchers -{ -namespace Impl -{ -namespace NSStringMatchers -{ + inline size_t registerTestMethods() { + size_t noTestMethods = 0; + int noClasses = objc_getClassList( NULL, 0 ); -template -struct StringHolder : MatcherImpl -{ - StringHolder( NSString* substr ) : m_substr( [substr copy] ) {} - StringHolder( StringHolder const& other ) : m_substr( [other.m_substr copy] ) {} - StringHolder() - { - arcSafeRelease( m_substr ); + 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; } - NSString* m_substr; -}; + namespace Matchers { + namespace Impl { + namespace NSStringMatchers { -struct Equals : StringHolder -{ - Equals( NSString* substr ) : StringHolder( substr ) {} + template + struct StringHolder : MatcherImpl{ + StringHolder( NSString* substr ) : m_substr( [substr copy] ){} + StringHolder( StringHolder const& other ) : m_substr( [other.m_substr copy] ){} + StringHolder() { + arcSafeRelease( m_substr ); + } - virtual bool match( ExpressionType const& str ) const - { - return (str != nil || m_substr == nil ) && - [str isEqualToString:m_substr]; - } + NSString* m_substr; + }; - virtual std::string toString() const - { - return "equals string: " + Catch::toString( m_substr ); - } -}; + struct Equals : StringHolder { + Equals( NSString* substr ) : StringHolder( substr ){} -struct Contains : StringHolder -{ - Contains( NSString* substr ) : StringHolder( substr ) {} + virtual bool match( ExpressionType const& str ) const { + return (str != nil || m_substr == nil ) && + [str isEqualToString:m_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 "equals string: " + Catch::toString( m_substr ); + } + }; - virtual std::string toString() const - { - return "contains string: " + Catch::toString( m_substr ); - } -}; + struct Contains : StringHolder { + Contains( NSString* substr ) : StringHolder( substr ){} -struct StartsWith : StringHolder -{ - StartsWith( NSString* substr ) : StringHolder( substr ) {} + virtual bool match( ExpressionType const& str ) const { + return (str != nil || m_substr == nil ) && + [str rangeOfString:m_substr].location != NSNotFound; + } - 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 "contains string: " + Catch::toString( m_substr ); + } + }; - virtual std::string toString() const - { - return "starts with: " + Catch::toString( m_substr ); - } -}; -struct EndsWith : StringHolder -{ - EndsWith( NSString* substr ) : StringHolder( substr ) {} + struct StartsWith : StringHolder { + StartsWith( 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 bool match( ExpressionType const& str ) const { + return (str != nil || m_substr == nil ) && + [str rangeOfString:m_substr].location == 0; + } - virtual std::string toString() const - { - return "ends with: " + Catch::toString( m_substr ); - } -}; + virtual std::string toString() const { + return "starts with: " + Catch::toString( m_substr ); + } + }; + struct EndsWith : StringHolder { + EndsWith( NSString* substr ) : StringHolder( substr ){} -} // namespace NSStringMatchers -} // namespace Impl + virtual bool match( ExpressionType const& str ) const { + return (str != nil || m_substr == nil ) && + [str rangeOfString:m_substr].location == [str length] - [m_substr length]; + } -inline Impl::NSStringMatchers::Equals -Equals( NSString* substr ) -{ - return Impl::NSStringMatchers::Equals( substr ); -} + virtual std::string toString() const { + return "ends with: " + Catch::toString( m_substr ); + } + }; -inline Impl::NSStringMatchers::Contains -Contains( NSString* substr ) -{ - return Impl::NSStringMatchers::Contains( substr ); -} + } // namespace NSStringMatchers + } // namespace Impl -inline Impl::NSStringMatchers::StartsWith -StartsWith( NSString* substr ) -{ - return Impl::NSStringMatchers::StartsWith( substr ); -} + inline Impl::NSStringMatchers::Equals + Equals( NSString* substr ){ return Impl::NSStringMatchers::Equals( substr ); } -inline Impl::NSStringMatchers::EndsWith -EndsWith( NSString* substr ) -{ - return Impl::NSStringMatchers::EndsWith( substr ); -} + inline Impl::NSStringMatchers::Contains + Contains( NSString* substr ){ return Impl::NSStringMatchers::Contains( substr ); } -} // namespace Matchers + inline Impl::NSStringMatchers::StartsWith + StartsWith( NSString* substr ){ return Impl::NSStringMatchers::StartsWith( substr ); } -using namespace Matchers; + 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 ) ++(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 @@ -3185,8 +2702,8 @@ using namespace Matchers; // These are the equivalent of what would usually be cpp files #ifdef __clang__ - #pragma clang diagnostic push - #pragma clang diagnostic ignored "-Wweak-vtables" +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wweak-vtables" #endif // #included from: catch_runner.hpp @@ -3202,290 +2719,222 @@ using namespace Matchers; #define TWOBLUECUBES_CATCH_TEST_SPEC_PARSER_HPP_INCLUDED #ifdef __clang__ - #pragma clang diagnostic push - #pragma clang diagnostic ignored "-Wpadded" +#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" +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wpadded" #endif #include #include -namespace Catch -{ +namespace Catch { -class TestSpec -{ - struct Pattern : SharedImpl<> - { - virtual ~Pattern(); - virtual bool matches( TestCaseInfo const& testCase ) const = 0; - }; - class NamePattern : public Pattern - { - enum WildcardPosition - { - NoWildcard = 0, - WildcardAtStart = 1, - WildcardAtEnd = 2, - WildcardAtBothEnds = WildcardAtStart | WildcardAtEnd + class TestSpec { + struct Pattern : SharedImpl<> { + virtual ~Pattern(); + virtual bool matches( TestCaseInfo const& testCase ) const = 0; }; + class NamePattern : public Pattern { + enum WildcardPosition { + NoWildcard = 0, + WildcardAtStart = 1, + WildcardAtEnd = 2, + WildcardAtBothEnds = WildcardAtStart | WildcardAtEnd + }; - public: - NamePattern( std::string const& name ) : m_name( toLower( name ) ), m_wildcard( NoWildcard ) - { - if ( startsWith( m_name, "*" ) ) - { - m_name = m_name.substr( 1 ); - m_wildcard = WildcardAtStart; - } - if ( endsWith( m_name, "*" ) ) - { - m_name = m_name.substr( 0, m_name.size() - 1 ); - m_wildcard = static_cast( m_wildcard | WildcardAtEnd ); - } - } - virtual ~NamePattern(); - virtual bool matches( TestCaseInfo const& testCase ) const - { - switch ( m_wildcard ) - { - case NoWildcard: - return m_name == toLower( testCase.name ); - case WildcardAtStart: - return endsWith( toLower( testCase.name ), m_name ); - case WildcardAtEnd: - return startsWith( toLower( testCase.name ), m_name ); - case WildcardAtBothEnds: - return contains( toLower( testCase.name ), m_name ); + public: + NamePattern( std::string const& name ) : m_name( toLower( name ) ), m_wildcard( NoWildcard ) { + if( startsWith( m_name, "*" ) ) { + m_name = m_name.substr( 1 ); + m_wildcard = WildcardAtStart; + } + if( endsWith( m_name, "*" ) ) { + m_name = m_name.substr( 0, m_name.size()-1 ); + m_wildcard = static_cast( m_wildcard | WildcardAtEnd ); + } } + virtual ~NamePattern(); + virtual bool matches( TestCaseInfo const& testCase ) const { + switch( m_wildcard ) { + case NoWildcard: + return m_name == toLower( testCase.name ); + case WildcardAtStart: + return endsWith( toLower( testCase.name ), m_name ); + case WildcardAtEnd: + return startsWith( toLower( testCase.name ), m_name ); + case WildcardAtBothEnds: + return contains( toLower( testCase.name ), m_name ); + } #ifdef __clang__ #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wunreachable-code" #endif - throw std::logic_error( "Unknown enum" ); + throw std::logic_error( "Unknown enum" ); #ifdef __clang__ #pragma clang diagnostic pop #endif - } - private: - std::string m_name; - WildcardPosition m_wildcard; - }; - 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 const& underlyingPattern ) : m_underlyingPattern( - underlyingPattern ) {} - virtual ~ExcludedPattern(); - virtual bool matches( TestCaseInfo const& testCase ) const - { - return !m_underlyingPattern->matches( testCase ); - } - private: - Ptr m_underlyingPattern; - }; - - struct Filter - { - std::vector> 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>::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::const_iterator it = m_filters.begin(), itEnd = m_filters.end(); - it != itEnd; ++it ) - if ( it->matches( testCase ) ) - { - return true; } - return false; - } + private: + std::string m_name; + WildcardPosition m_wildcard; + }; + 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 const& underlyingPattern ) : m_underlyingPattern( underlyingPattern ) {} + virtual ~ExcludedPattern(); + virtual bool matches( TestCaseInfo const& testCase ) const { return !m_underlyingPattern->matches( testCase ); } + private: + Ptr m_underlyingPattern; + }; - private: - std::vector m_filters; + struct Filter { + std::vector > m_patterns; - friend class TestSpecParser; -}; + bool matches( TestCaseInfo const& testCase ) const { + // All patterns in a filter must match for the filter to be a match + for( std::vector >::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::const_iterator it = m_filters.begin(), itEnd = m_filters.end(); it != itEnd; ++it ) + if( it->matches( testCase ) ) + return true; + return false; + } + + private: + std::vector m_filters; + + friend class TestSpecParser; + }; } #ifdef __clang__ - #pragma clang diagnostic pop +#pragma clang diagnostic pop #endif -namespace Catch -{ +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; + 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 ) {} + 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(); - } - 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 == ',' ) - { + 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(); - addFilter(); - } - else if ( c == '[' ) - { - if ( subString() == "exclude:" ) - { - m_exclusion = true; + 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; } - else - { + } + if( m_mode == Name ) { + if( c == ',' ) { addPattern(); + addFilter(); } - startNewMode( Tag, ++m_pos ); + else if( c == '[' ) { + if( subString() == "exclude:" ) + m_exclusion = true; + else + addPattern(); + startNewMode( Tag, ++m_pos ); + } + } + else if( m_mode == QuotedName && c == '"' ) + addPattern(); + else if( m_mode == Tag && c == ']' ) + addPattern(); + } + 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 + void addPattern() { + std::string token = subString(); + if( startsWith( token, "exclude:" ) ) { + m_exclusion = true; + token = token.substr( 8 ); + } + if( !token.empty() ) { + Ptr 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(); } } - else if ( m_mode == QuotedName && c == '"' ) - { - addPattern(); - } - else if ( m_mode == Tag && c == ']' ) - { - addPattern(); - } + }; + inline TestSpec parseTestSpec( std::string const& arg ) { + return TestSpecParser( ITagAliasRegistry::get() ).parse( arg ).testSpec(); } - 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 - void addPattern() - { - std::string token = subString(); - if ( startsWith( token, "exclude:" ) ) - { - m_exclusion = true; - token = token.substr( 8 ); - } - if ( !token.empty() ) - { - Ptr 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 +#pragma clang diagnostic pop #endif // #included from: catch_interfaces_config.h @@ -3495,56 +2944,42 @@ inline TestSpec parseTestSpec( std::string const& arg ) #include #include -namespace Catch -{ +namespace Catch { -struct Verbosity -{ - enum Level - { + struct Verbosity { enum Level { NoOutput = 0, Quiet, Normal - }; -}; + }; }; -struct WarnAbout -{ - enum What - { + struct WarnAbout { enum What { Nothing = 0x00, NoAssertions = 0x01 - }; -}; + }; }; -struct ShowDurations -{ - enum OrNot - { + struct ShowDurations { enum OrNot { DefaultForReporter, Always, Never + }; }; + + 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; }; -}; - -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; -}; } // #included from: catch_stream.h @@ -3553,24 +2988,22 @@ struct IConfig : IShared #include #ifdef __clang__ - #pragma clang diagnostic ignored "-Wpadded" +#pragma clang diagnostic ignored "-Wpadded" #endif -namespace Catch -{ +namespace Catch { -class Stream -{ - public: - Stream(); - Stream( std::streambuf* _streamBuf, bool _isOwned ); - void release(); + class Stream { + public: + Stream(); + Stream( std::streambuf* _streamBuf, bool _isOwned ); + void release(); - std::streambuf* streamBuf; + std::streambuf* streamBuf; - private: - bool isOwned; -}; + private: + bool isOwned; + }; } #include @@ -3579,16 +3012,14 @@ class Stream #include #ifndef CATCH_CONFIG_CONSOLE_WIDTH - #define CATCH_CONFIG_CONSOLE_WIDTH 80 +#define CATCH_CONFIG_CONSOLE_WIDTH 80 #endif -namespace Catch -{ +namespace Catch { -struct ConfigData -{ + struct ConfigData { - ConfigData() + ConfigData() : listTests( false ), listTags( false ), listReporters( false ), @@ -3602,173 +3033,113 @@ struct ConfigData verbosity( Verbosity::Normal ), warnings( WarnAbout::Nothing ), showDurations( ShowDurations::DefaultForReporter ) - {} + {} - bool listTests; - bool listTags; - bool listReporters; - bool listTestNamesOnly; + bool listTests; + bool listTags; + bool listReporters; + bool listTestNamesOnly; - bool showSuccessfulTests; - bool shouldDebugBreak; - bool noThrow; - bool showHelp; - bool showInvisibles; + bool showSuccessfulTests; + bool shouldDebugBreak; + bool noThrow; + bool showHelp; + bool showInvisibles; - int abortAfter; + int abortAfter; - Verbosity::Level verbosity; - WarnAbout::What warnings; - ShowDurations::OrNot showDurations; + Verbosity::Level verbosity; + WarnAbout::What warnings; + ShowDurations::OrNot showDurations; - std::string reporterName; - std::string outputFilename; - std::string name; - std::string processName; + std::string reporterName; + std::string outputFilename; + std::string name; + std::string processName; - std::vector testsOrTags; -}; + std::vector testsOrTags; + }; -class Config : public SharedImpl -{ - private: - Config( Config const& other ); - Config& operator = ( Config const& other ); - virtual void dummy(); - public: + class Config : public SharedImpl { + private: + Config( Config const& other ); + Config& operator = ( Config const& other ); + virtual void dummy(); + public: - Config() + Config() : m_os( std::cout.rdbuf() ) - {} + {} - Config( ConfigData const& data ) + Config( ConfigData const& data ) : m_data( data ), m_os( std::cout.rdbuf() ) - { - if ( !data.testsOrTags.empty() ) { - TestSpecParser parser( ITagAliasRegistry::get() ); - for ( std::size_t i = 0; i < data.testsOrTags.size(); ++i ) - { - parser.parse( data.testsOrTags[i] ); + 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(); } - m_testSpec = parser.testSpec(); } - } - virtual ~Config() - { - m_os.rdbuf( std::cout.rdbuf() ); - m_stream.release(); - } + virtual ~Config() { + m_os.rdbuf( std::cout.rdbuf() ); + m_stream.release(); + } - void setFilename( std::string const& filename ) - { - m_data.outputFilename = filename; - } + void setFilename( std::string const& filename ) { + m_data.outputFilename = filename; + } - std::string const& getFilename() const - { - return m_data.outputFilename ; - } + 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; - } + 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; - } + std::string getProcessName() const { return m_data.processName; } - bool shouldDebugBreak() const - { - return m_data.shouldDebugBreak; - } + bool shouldDebugBreak() const { return m_data.shouldDebugBreak; } - void setStreamBuf( std::streambuf* buf ) - { - m_os.rdbuf( buf ? buf : std::cout.rdbuf() ); - } + void setStreamBuf( std::streambuf* buf ) { + m_os.rdbuf( buf ? buf : std::cout.rdbuf() ); + } - void useStream( std::string const& streamName ) - { - Stream stream = createStream( streamName ); - setStreamBuf( stream.streamBuf ); - m_stream.release(); - m_stream = stream; - } + void useStream( std::string const& streamName ) { + Stream stream = createStream( streamName ); + setStreamBuf( stream.streamBuf ); + m_stream.release(); + m_stream = stream; + } - std::string getReporterName() const - { - return m_data.reporterName; - } + std::string getReporterName() const { return m_data.reporterName; } - int abortAfter() const - { - return m_data.abortAfter; - } + int abortAfter() const { return m_data.abortAfter; } - TestSpec const& testSpec() const - { - return m_testSpec; - } + TestSpec const& testSpec() const { return m_testSpec; } - bool showHelp() const - { - return m_data.showHelp; - } - bool showInvisibles() const - { - return m_data.showInvisibles; - } + 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_os; - } - 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; - } + // IConfig interface + virtual bool allowThrows() const { return !m_data.noThrow; } + virtual std::ostream& stream() const { return m_os; } + 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; } - private: - ConfigData m_data; + private: + ConfigData m_data; - Stream m_stream; - mutable std::ostream m_os; - TestSpec m_testSpec; -}; + Stream m_stream; + mutable std::ostream m_os; + TestSpec m_testSpec; + }; } // end namespace Catch @@ -3777,8 +3148,8 @@ class Config : public SharedImpl // 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 +#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 @@ -3790,11 +3161,11 @@ class Config : public SharedImpl #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 +#define TWOBLUECUBES_CLARA_H_INCLUDED +#define STITCH_CLARA_OPEN_NAMESPACE +#define STITCH_CLARA_CLOSE_NAMESPACE #else - #define STITCH_CLARA_CLOSE_NAMESPACE } +#define STITCH_CLARA_CLOSE_NAMESPACE } #endif #define STITCH_TBC_TEXT_FORMAT_OPEN_NAMESPACE STITCH_CLARA_OPEN_NAMESPACE @@ -3804,7 +3175,7 @@ class Config : public SharedImpl // 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 +#define TBC_TEXT_FORMAT_H_INCLUDED #endif #include @@ -3813,12 +3184,10 @@ class Config : public SharedImpl // Use optional outer namespace #ifdef STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE -namespace STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE -{ +namespace STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE { #endif -namespace Tbc -{ +namespace Tbc { #ifdef TBC_TEXT_FORMAT_CONSOLE_WIDTH const unsigned int consoleWidth = TBC_TEXT_FORMAT_CONSOLE_WIDTH; @@ -3826,174 +3195,116 @@ namespace Tbc const unsigned int consoleWidth = 80; #endif -struct TextAttributes -{ - TextAttributes() + struct TextAttributes { + TextAttributes() : initialIndent( std::string::npos ), indent( 0 ), - width( consoleWidth - 1 ), + 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; - } + 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 -}; + 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() ) + 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 ); - } + std::string wrappableChars = " [({.,/|\\-"; + std::size_t indent = _attr.initialIndent != std::string::npos + ? _attr.initialIndent + : _attr.indent; + std::string remainder = _str; - 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 ); + while( !remainder.empty() ) { + if( lines.size() >= 1000 ) { + lines.push_back( "... message truncated due to excessive size" ); + return; } - 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] == ' ' ) - { + 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 ); - } - } - else - { - spliceLine( indent, remainder, width - 1 ); - lines.back() += "-"; - } - if ( lines.size() == 1 ) - { indent = _attr.indent; } - if ( tabPos != std::string::npos ) - { - indent += tabPos; + 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::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; + 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 ); } - return _stream; - } - private: - std::string str; - TextAttributes attr; - std::vector lines; -}; + typedef std::vector::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 lines; + }; } // end namespace Tbc @@ -4015,22 +3326,20 @@ class Text // Use optional outer namespace #ifdef STITCH_CLARA_OPEN_NAMESPACE - STITCH_CLARA_OPEN_NAMESPACE +STITCH_CLARA_OPEN_NAMESPACE #endif -namespace Clara -{ +namespace Clara { -struct UnpositionalTag {}; + struct UnpositionalTag {}; -extern UnpositionalTag _; + extern UnpositionalTag _; #ifdef CLARA_CONFIG_MAIN UnpositionalTag _; #endif -namespace Detail -{ + namespace Detail { #ifdef CLARA_CONSOLE_WIDTH const unsigned int consoleWidth = CLARA_CONFIG_CONSOLE_WIDTH; @@ -4038,905 +3347,654 @@ namespace Detail const unsigned int consoleWidth = 80; #endif -using namespace Tbc; + 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; -} + inline bool startsWith( std::string const& str, std::string const& prefix ) { + return str.size() >= prefix.size() && str.substr( 0, prefix.size() ) == prefix; + } -template struct RemoveConstRef -{ - typedef T type; -}; -template struct RemoveConstRef -{ - typedef T type; -}; -template struct RemoveConstRef -{ - typedef T type; -}; -template struct RemoveConstRef -{ - typedef T type; -}; + template struct RemoveConstRef{ typedef T type; }; + template struct RemoveConstRef{ typedef T type; }; + template struct RemoveConstRef{ typedef T type; }; + template struct RemoveConstRef{ typedef T type; }; -template struct IsBool -{ - static const bool value = false; -}; -template<> struct IsBool -{ - static const bool value = true; -}; + template struct IsBool { static const bool value = false; }; + template<> struct IsBool { static const bool value = true; }; -template -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 -inline void convertInto( bool, T&) -{ - throw std::runtime_error( "Invalid conversion" ); -} + template + 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 + inline void convertInto( bool, T& ) { + throw std::runtime_error( "Invalid conversion" ); + } -template -struct IArgFunction -{ - virtual ~IArgFunction() {} + template + struct IArgFunction { + virtual ~IArgFunction() {} # ifdef CATCH_CPP11_OR_GREATER - IArgFunction() = default; - IArgFunction( IArgFunction const&) = default; + 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; -}; + 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 -class BoundArgFunction -{ - public: - BoundArgFunction() : functionObj( NULL ) {} - BoundArgFunction( IArgFunction* _functionObj ) : functionObj( _functionObj ) {} - BoundArgFunction( BoundArgFunction const& other ) : functionObj( other.functionObj ? - other.functionObj->clone() : NULL ) {} - BoundArgFunction& operator = ( BoundArgFunction const& other ) - { - IArgFunction* newFunctionObj = other.functionObj ? other.functionObj->clone() : NULL; - delete functionObj; - functionObj = newFunctionObj; - return *this; - } - ~BoundArgFunction() - { - delete functionObj; - } + template + class BoundArgFunction { + public: + BoundArgFunction() : functionObj( NULL ) {} + BoundArgFunction( IArgFunction* _functionObj ) : functionObj( _functionObj ) {} + BoundArgFunction( BoundArgFunction const& other ) : functionObj( other.functionObj ? other.functionObj->clone() : NULL ) {} + BoundArgFunction& operator = ( BoundArgFunction const& other ) { + IArgFunction* newFunctionObj = other.functionObj ? other.functionObj->clone() : 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(); - } + 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 != NULL; - } - private: - IArgFunction* functionObj; -}; + bool isSet() const { + return functionObj != NULL; + } + private: + IArgFunction* functionObj; + }; -template -struct NullBinder : IArgFunction -{ - virtual void set( C&, std::string const&) const {} - virtual void setFlag( C&) const {} - virtual bool takesArg() const - { - return true; - } - virtual IArgFunction* clone() const - { - return new NullBinder( *this ); - } -}; + template + struct NullBinder : IArgFunction{ + virtual void set( C&, std::string const& ) const {} + virtual void setFlag( C& ) const {} + virtual bool takesArg() const { return true; } + virtual IArgFunction* clone() const { return new NullBinder( *this ); } + }; -template -struct BoundDataMember : IArgFunction -{ - 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::value; - } - virtual IArgFunction* clone() const - { - return new BoundDataMember( *this ); - } - M C::* member; -}; -template -struct BoundUnaryMethod : IArgFunction -{ - BoundUnaryMethod( void (C::*_member)( M ) ) : member( _member ) {} - virtual void set( C& p, std::string const& stringValue ) const - { - typename RemoveConstRef::type value; - convertInto( stringValue, value ); - (p.*member)( value ); - } - virtual void setFlag( C& p ) const - { - typename RemoveConstRef::type value; - convertInto( true, value ); - (p.*member)( value ); - } - virtual bool takesArg() const - { - return !IsBool::value; - } - virtual IArgFunction* clone() const - { - return new BoundUnaryMethod( *this ); - } - void (C::*member)( M ); -}; -template -struct BoundNullaryMethod : IArgFunction -{ - 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)(); + template + struct BoundDataMember : IArgFunction{ + 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::value; } + virtual IArgFunction* clone() const { return new BoundDataMember( *this ); } + M C::* member; + }; + template + struct BoundUnaryMethod : IArgFunction{ + BoundUnaryMethod( void (C::*_member)( M ) ) : member( _member ) {} + virtual void set( C& p, std::string const& stringValue ) const { + typename RemoveConstRef::type value; + convertInto( stringValue, value ); + (p.*member)( value ); + } + virtual void setFlag( C& p ) const { + typename RemoveConstRef::type value; + convertInto( true, value ); + (p.*member)( value ); + } + virtual bool takesArg() const { return !IsBool::value; } + virtual IArgFunction* clone() const { return new BoundUnaryMethod( *this ); } + void (C::*member)( M ); + }; + template + struct BoundNullaryMethod : IArgFunction{ + 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* clone() const { return new BoundNullaryMethod( *this ); } + void (C::*member)(); + }; + + template + struct BoundUnaryFunction : IArgFunction{ + 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* clone() const { return new BoundUnaryFunction( *this ); } + void (*function)( C& ); + }; + + template + struct BoundBinaryFunction : IArgFunction{ + BoundBinaryFunction( void (*_function)( C&, T ) ) : function( _function ) {} + virtual void set( C& obj, std::string const& stringValue ) const { + typename RemoveConstRef::type value; + convertInto( stringValue, value ); + function( obj, value ); + } + virtual void setFlag( C& obj ) const { + typename RemoveConstRef::type value; + convertInto( true, value ); + function( obj, value ); + } + virtual bool takesArg() const { return !IsBool::value; } + virtual IArgFunction* 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& tokens ) const { + const std::string doubleDash = "--"; + for( int i = 1; i < argc && argv[i] != doubleDash; ++i ) + parseIntoTokens( argv[i] , tokens); } - } - virtual void setFlag( C& p ) const - { - (p.*member)(); - } - virtual bool takesArg() const - { - return false; - } - virtual IArgFunction* clone() const - { - return new BoundNullaryMethod( *this ); - } - void (C::*member)(); -}; - -template -struct BoundUnaryFunction : IArgFunction -{ - 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* clone() const - { - return new BoundUnaryFunction( *this ); - } - void (*function)( C&); -}; - -template -struct BoundBinaryFunction : IArgFunction -{ - BoundBinaryFunction( void (*_function)( C&, T ) ) : function( _function ) {} - virtual void set( C& obj, std::string const& stringValue ) const - { - typename RemoveConstRef::type value; - convertInto( stringValue, value ); - function( obj, value ); - } - virtual void setFlag( C& obj ) const - { - typename RemoveConstRef::type value; - convertInto( true, value ); - function( obj, value ); - } - virtual bool takesArg() const - { - return !IsBool::value; - } - virtual IArgFunction* 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& 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& 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 ); + void parseIntoTokens( std::string arg, std::vector& 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 ); + 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 ); } - tokens.push_back( token ); } - } - std::string separators; -}; + std::string separators; + }; -template -struct CommonArgProperties -{ - CommonArgProperties() {} - CommonArgProperties( Detail::BoundArgFunction const& _boundField ) : boundField( - _boundField ) {} + template + struct CommonArgProperties { + CommonArgProperties() {} + CommonArgProperties( Detail::BoundArgFunction const& _boundField ) : boundField( _boundField ) {} - Detail::BoundArgFunction boundField; - std::string description; - std::string detail; - std::string placeholder; // Only value if boundField takes an arg + Detail::BoundArgFunction 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" ); + bool takesArg() const { + return !placeholder.empty(); } - } -}; -struct OptionArgProperties -{ - std::vector 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 -class CommandLine -{ - - struct Arg : CommonArgProperties, OptionArgProperties, PositionalArgProperties - { - Arg() {} - Arg( Detail::BoundArgFunction const& _boundField ) : CommonArgProperties - ( _boundField ) {} - - using CommonArgProperties::placeholder; // !TBD - - std::string dbgName() const - { - if ( !longName.empty() ) - { - return "--" + longName; - } - if ( !shortNames.empty() ) - { - return "-" + shortNames[0]; - } - return "positional args"; + void validate() const { + if( !boundField.isSet() ) + throw std::logic_error( "option not bound" ); } - std::string commands() const - { - std::ostringstream oss; - bool first = true; - std::vector::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(); + }; + struct OptionArgProperties { + std::vector 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; } }; - // NOTE: std::auto_ptr is deprecated in c++11/c++0x + template + class CommandLine { + + struct Arg : CommonArgProperties, OptionArgProperties, PositionalArgProperties { + Arg() {} + Arg( Detail::BoundArgFunction const& _boundField ) : CommonArgProperties( _boundField ) {} + + using CommonArgProperties::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::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(); + } + }; + + // NOTE: std::auto_ptr is deprecated in c++11/c++0x #if defined(__cplusplus) && __cplusplus > 199711L - typedef std::unique_ptr ArgAutoPtr; + typedef std::unique_ptr ArgAutoPtr; #else - typedef std::auto_ptr ArgAutoPtr; + typedef std::auto_ptr ArgAutoPtr; #endif - friend void addOptName( Arg& arg, std::string const& optName ) - { - if ( optName.empty() ) + friend void addOptName( Arg& arg, std::string const& optName ) { - return; + 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 + "'" ); } - if ( Detail::startsWith( optName, "--" ) ) + friend void setPositionalArg( Arg& arg, int position ) { - 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 - void bind( M C::* field, std::string const& placeholder ) - { - m_arg->boundField = new Detail::BoundDataMember( field ); - m_arg->placeholder = placeholder; - } - // Bind a boolean data member (no placeholder required) - template - void bind( bool C::* field ) - { - m_arg->boundField = new Detail::BoundDataMember( field ); + arg.position = position; } - // Bind a method taking a single, non-boolean argument (requires a placeholder string) - template - void bind( void (C::* unaryMethod)( M ), std::string const& placeholder ) - { - m_arg->boundField = new Detail::BoundUnaryMethod( unaryMethod ); - m_arg->placeholder = placeholder; - } + class ArgBuilder { + public: + ArgBuilder( Arg* arg ) : m_arg( arg ) {} - // Bind a method taking a single, boolean argument (no placeholder string required) - template - void bind( void (C::* unaryMethod)( bool ) ) - { - m_arg->boundField = new Detail::BoundUnaryMethod( unaryMethod ); - } + // Bind a non-boolean data member (requires placeholder string) + template + void bind( M C::* field, std::string const& placeholder ) { + m_arg->boundField = new Detail::BoundDataMember( field ); + m_arg->placeholder = placeholder; + } + // Bind a boolean data member (no placeholder required) + template + void bind( bool C::* field ) { + m_arg->boundField = new Detail::BoundDataMember( field ); + } - // Bind a method that takes no arguments (will be called if opt is present) - template - void bind( void (C::* nullaryMethod)() ) - { - m_arg->boundField = new Detail::BoundNullaryMethod( nullaryMethod ); - } + // Bind a method taking a single, non-boolean argument (requires a placeholder string) + template + void bind( void (C::* unaryMethod)( M ), std::string const& placeholder ) { + m_arg->boundField = new Detail::BoundUnaryMethod( unaryMethod ); + m_arg->placeholder = placeholder; + } - // Bind a free function taking a single argument - the object to operate on (no placeholder string required) - template - void bind( void (* unaryFunction)( C&) ) - { - m_arg->boundField = new Detail::BoundUnaryFunction( unaryFunction ); - } + // Bind a method taking a single, boolean argument (no placeholder string required) + template + void bind( void (C::* unaryMethod)( bool ) ) { + m_arg->boundField = new Detail::BoundUnaryMethod( unaryMethod ); + } - // Bind a free function taking a single argument - the object to operate on (requires a placeholder string) - template - void bind( void (* binaryFunction)( C&, T ), std::string const& placeholder ) - { - m_arg->boundField = new Detail::BoundBinaryFunction( binaryFunction ); - m_arg->placeholder = placeholder; - } + // Bind a method that takes no arguments (will be called if opt is present) + template + void bind( void (C::* nullaryMethod)() ) { + m_arg->boundField = new Detail::BoundNullaryMethod( nullaryMethod ); + } - ArgBuilder& describe( std::string const& description ) - { - m_arg->description = description; - return *this; - } - ArgBuilder& detail( std::string const& detail ) - { - m_arg->detail = detail; - return *this; - } + // Bind a free function taking a single argument - the object to operate on (no placeholder string required) + template + void bind( void (* unaryFunction)( C& ) ) { + m_arg->boundField = new Detail::BoundUnaryFunction( unaryFunction ); + } - protected: - Arg* m_arg; - }; + // Bind a free function taking a single argument - the object to operate on (requires a placeholder string) + template + void bind( void (* binaryFunction)( C&, T ), std::string const& placeholder ) { + m_arg->boundField = new Detail::BoundBinaryFunction( binaryFunction ); + m_arg->placeholder = placeholder; + } - class OptBuilder : public ArgBuilder - { - public: - OptBuilder( Arg* arg ) : ArgBuilder( arg ) {} - OptBuilder( OptBuilder& other ) : ArgBuilder( other ) {} + ArgBuilder& describe( std::string const& description ) { + m_arg->description = description; + return *this; + } + ArgBuilder& detail( std::string const& detail ) { + m_arg->detail = detail; + return *this; + } - OptBuilder& operator[]( std::string const& optName ) - { - addOptName( *ArgBuilder::m_arg, optName ); - return *this; - } - }; + protected: + Arg* m_arg; + }; - public: + class OptBuilder : public ArgBuilder { + public: + OptBuilder( Arg* arg ) : ArgBuilder( arg ) {} + OptBuilder( OptBuilder& other ) : ArgBuilder( other ) {} - CommandLine() + OptBuilder& operator[]( std::string const& optName ) { + addOptName( *ArgBuilder::m_arg, optName ); + return *this; + } + }; + + public: + + CommandLine() : m_boundProcessName( new Detail::NullBinder() ), m_highestSpecifiedArgPosition( 0 ), m_throwOnUnrecognisedTokens( false ) - {} - CommandLine( CommandLine const& other ) + {} + 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 = ArgAutoPtr( 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 = ArgAutoPtr( new Arg() ); - ArgBuilder builder( m_floatingArg.get() ); - return builder; - } - - template - void bindProcessName( M C::* field ) - { - m_boundProcessName = new Detail::BoundDataMember( field ); - } - template - void bindProcessName( void (C::*_unaryMethod)( M ) ) - { - m_boundProcessName = new Detail::BoundUnaryMethod( _unaryMethod ); - } - - void optUsage( std::ostream& os, std::size_t indent = 0, - std::size_t width = Detail::consoleWidth ) const - { - typename std::vector::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() ); + if( other.m_floatingArg.get() ) + m_floatingArg = ArgAutoPtr( new Arg( *other.m_floatingArg ) ); } - 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 ) ); + CommandLine& setThrowOnUnrecognisedTokens( bool shouldThrow = true ) { + m_throwOnUnrecognisedTokens = shouldThrow; + return *this; + } - for ( std::size_t i = 0; i < (std::max)( usage.size(), desc.size() ); ++i ) - { - std::string usageCol = i < usage.size() ? usage[i] : ""; - os << usageCol; + OptBuilder operator[]( std::string const& optName ) { + m_options.push_back( Arg() ); + addOptName( m_options.back(), optName ); + OptBuilder builder( &m_options.back() ); + return builder; + } - if ( i < desc.size() && !desc[i].empty() ) - os << std::string( indent + 2 + maxWidth - usageCol.size(), ' ' ) - << desc[i]; - os << "\n"; + 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 = ArgAutoPtr( new Arg() ); + ArgBuilder builder( m_floatingArg.get() ); + return builder; + } + + template + void bindProcessName( M C::* field ) { + m_boundProcessName = new Detail::BoundDataMember( field ); + } + template + void bindProcessName( void (C::*_unaryMethod)( M ) ) { + m_boundProcessName = new Detail::BoundUnaryMethod( _unaryMethod ); + } + + void optUsage( std::ostream& os, std::size_t indent = 0, std::size_t width = Detail::consoleWidth ) const { + typename std::vector::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(); - } + 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 << " "; + void argSynopsis( std::ostream& os ) const { + for( int i = 1; i <= m_highestSpecifiedArgPosition; ++i ) { + if( i > 1 ) + os << " "; + typename std::map::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" ); } - typename std::map::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 << "> ...]"; } } - // !TBD No indication of mandatory args - if ( m_floatingArg.get() ) - { - if ( m_highestSpecifiedArgPosition > 1 ) - { - os << " "; + 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 << "[<" << m_floatingArg->placeholder << "> ...]"; + os << "\n"; } - } - 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 ); + std::string usage( std::string const& procName ) const { + std::ostringstream oss; + usage( oss, procName ); + return oss.str(); } - 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 parseInto( int argc, char const* 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 ); + ConfigT parse( int argc, char const * const * argv ) const { + ConfigT config; + parseInto( argc, argv, config ); + return config; } - m_boundProcessName.set( config, processName ); - std::vector tokens; - Parser parser; - parser.parseIntoTokens( argc, argv, tokens ); - return populate( tokens, config ); - } - std::vector populate( std::vector const& tokens, - ConfigT& config ) const - { - validate(); - std::vector unusedTokens = populateOptions( tokens, config ); - unusedTokens = populateFixedArgs( unusedTokens, config ); - unusedTokens = populateFloatingArgs( unusedTokens, config ); - return unusedTokens; - } + std::vector parseInto( int argc, char const * 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 tokens; + Parser parser; + parser.parseIntoTokens( argc, argv, tokens ); + return populate( tokens, config ); + } - std::vector populateOptions( std::vector const& tokens, - ConfigT& config ) const - { - std::vector unusedTokens; - std::vector errors; - for ( std::size_t i = 0; i < tokens.size(); ++i ) - { - Parser::Token const& token = tokens[i]; - typename std::vector::const_iterator it = m_options.begin(), itEnd = m_options.end(); - for (; it != itEnd; ++it ) - { - Arg const& arg = *it; + std::vector populate( std::vector const& tokens, ConfigT& config ) const { + validate(); + std::vector unusedTokens = populateOptions( tokens, config ); + unusedTokens = populateFixedArgs( unusedTokens, config ); + unusedTokens = populateFloatingArgs( unusedTokens, config ); + return unusedTokens; + } - 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 ); + std::vector populateOptions( std::vector const& tokens, ConfigT& config ) const { + std::vector unusedTokens; + std::vector errors; + for( std::size_t i = 0; i < tokens.size(); ++i ) { + Parser::Token const& token = tokens[i]; + typename std::vector::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.set( config, tokens[++i].data ); + else { + arg.boundField.setFlag( config ); } + break; } - else - { - arg.boundField.setFlag( config ); - } - break; + } + catch( std::exception& ex ) { + errors.push_back( std::string( ex.what() ) + "\n- while parsing: (" + arg.commands() + ")" ); } } - 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( m_throwOnUnrecognisedTokens ) + errors.push_back( "unrecognised option: " + token.data ); } } - if ( it == itEnd ) - { - if ( token.type == Parser::Token::Positional || !m_throwOnUnrecognisedTokens ) - { + if( !errors.empty() ) { + std::ostringstream oss; + for( std::vector::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 populateFixedArgs( std::vector const& tokens, ConfigT& config ) const { + std::vector unusedTokens; + int position = 1; + for( std::size_t i = 0; i < tokens.size(); ++i ) { + Parser::Token const& token = tokens[i]; + typename std::map::const_iterator it = m_positionalArgs.find( position ); + if( it != m_positionalArgs.end() ) + it->second.boundField.set( config, token.data ); + else unusedTokens.push_back( token ); - } - else if ( m_throwOnUnrecognisedTokens ) - { - errors.push_back( "unrecognised option: " + token.data ); - } + if( token.type == Parser::Token::Positional ) + position++; } + return unusedTokens; } - if ( !errors.empty() ) - { - std::ostringstream oss; - for ( std::vector::const_iterator it = errors.begin(), itEnd = errors.end(); - it != itEnd; - ++it ) - { - if ( it != errors.begin() ) - { - oss << "\n"; - } - oss << *it; + std::vector populateFloatingArgs( std::vector const& tokens, ConfigT& config ) const { + if( !m_floatingArg.get() ) + return tokens; + std::vector 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 ); } - throw std::runtime_error( oss.str() ); - } - return unusedTokens; - } - std::vector populateFixedArgs( std::vector const& tokens, - ConfigT& config ) const - { - std::vector unusedTokens; - int position = 1; - for ( std::size_t i = 0; i < tokens.size(); ++i ) - { - Parser::Token const& token = tokens[i]; - typename std::map::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 populateFloatingArgs( std::vector const& tokens, - ConfigT& config ) const - { - if ( !m_floatingArg.get() ) - { - return tokens; - } - std::vector 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" ); + return unusedTokens; } - for ( typename std::vector::const_iterator it = m_options.begin(), - itEnd = m_options.end(); - it != itEnd; ++it ) + void validate() const { - it->validate(); - } - } + if( m_options.empty() && m_positionalArgs.empty() && !m_floatingArg.get() ) + throw std::logic_error( "No options or arguments specified" ); - private: - Detail::BoundArgFunction m_boundProcessName; - std::vector m_options; - std::map m_positionalArgs; - ArgAutoPtr m_floatingArg; - int m_highestSpecifiedArgPosition; - bool m_throwOnUnrecognisedTokens; -}; + for( typename std::vector::const_iterator it = m_options.begin(), + itEnd = m_options.end(); + it != itEnd; ++it ) + it->validate(); + } + + private: + Detail::BoundArgFunction m_boundProcessName; + std::vector m_options; + std::map m_positionalArgs; + ArgAutoPtr m_floatingArg; + int m_highestSpecifiedArgPosition; + bool m_throwOnUnrecognisedTokens; + }; } // end namespace Clara @@ -4949,165 +4007,141 @@ STITCH_CLARA_CLOSE_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 +#define CLARA_CONFIG_CONSOLE_WIDTH CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH +#undef CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH #endif #include -namespace Catch -{ +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" ); + 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; } - config.abortAfter = x; -} -inline void addTestOrTags( ConfigData& config, std::string const& _testSpec ) -{ - config.testsOrTags.push_back( _testSpec ); -} + inline void addTestOrTags( ConfigData& config, std::string const& _testSpec ) { config.testsOrTags.push_back( _testSpec ); } -inline void addWarning( ConfigData& config, std::string const& _warning ) -{ - if ( _warning == "NoAssertions" ) - { - config.warnings = static_cast( config.warnings | WarnAbout::NoAssertions ); - } - else - { - throw std::runtime_error( "Unrecognised warning: '" + _warning + "'" ); - } + inline void addWarning( ConfigData& config, std::string const& _warning ) { + if( _warning == "NoAssertions" ) + config.warnings = static_cast( config.warnings | WarnAbout::NoAssertions ); + else + throw std::runtime_error( "Unrecognised warning: '" + _warning + "'" ); -} -inline void setVerbosity( ConfigData& config, int level ) -{ - // !TBD: accept strings? - config.verbosity = static_cast( level ); -} -inline void setShowDurations( ConfigData& config, bool _showDurations ) -{ - config.showDurations = _showDurations - ? ShowDurations::Always - : ShowDurations::Never; -} -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 ); } + inline void setVerbosity( ConfigData& config, int level ) { + // !TBD: accept strings? + config.verbosity = static_cast( level ); + } + inline void setShowDurations( ConfigData& config, bool _showDurations ) { + config.showDurations = _showDurations + ? ShowDurations::Always + : ShowDurations::Never; + } + 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 + "\"," ); + std::string line; + while( std::getline( f, line ) ) { + line = trim(line); + if( !line.empty() && !startsWith( line, "#" ) ) + addTestOrTags( config, "\"" + line + "\"," ); } } -} -inline Clara::CommandLine makeCommandLineParser() -{ + inline Clara::CommandLine makeCommandLineParser() { - using namespace Clara; - CommandLine cli; + using namespace Clara; + CommandLine cli; - cli.bindProcessName( &ConfigData::processName ); + cli.bindProcessName( &ConfigData::processName ); - cli["-?"]["-h"]["--help"] - .describe( "display usage information" ) - .bind( &ConfigData::showHelp ); + cli["-?"]["-h"]["--help"] + .describe( "display usage information" ) + .bind( &ConfigData::showHelp ); - cli["-l"]["--list-tests"] - .describe( "list all/matching test cases" ) - .bind( &ConfigData::listTests ); + 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["-t"]["--list-tags"] + .describe( "list all/matching tags" ) + .bind( &ConfigData::listTags ); - cli["-s"]["--success"] - .describe( "include successful tests in output" ) - .bind( &ConfigData::showSuccessfulTests ); + 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["-b"]["--break"] + .describe( "break into debugger on failure" ) + .bind( &ConfigData::shouldDebugBreak ); - cli["-e"]["--nothrow"] - .describe( "skip exception tests" ) - .bind( &ConfigData::noThrow ); + cli["-e"]["--nothrow"] + .describe( "skip exception tests" ) + .bind( &ConfigData::noThrow ); - cli["-i"]["--invisibles"] - .describe( "show invisibles (tabs, newlines)" ) - .bind( &ConfigData::showInvisibles ); + cli["-i"]["--invisibles"] + .describe( "show invisibles (tabs, newlines)" ) + .bind( &ConfigData::showInvisibles ); - cli["-o"]["--out"] - .describe( "output filename" ) - .bind( &ConfigData::outputFilename, "filename" ); + cli["-o"]["--out"] + .describe( "output filename" ) + .bind( &ConfigData::outputFilename, "filename" ); - cli["-r"]["--reporter"] - // .placeholder( "name[:filename]" ) - .describe( "reporter to use (defaults to console)" ) - .bind( &ConfigData::reporterName, "name" ); + cli["-r"]["--reporter"] +// .placeholder( "name[:filename]" ) + .describe( "reporter to use (defaults to console)" ) + .bind( &ConfigData::reporterName, "name" ); - cli["-n"]["--name"] - .describe( "suite name" ) - .bind( &ConfigData::name, "name" ); + cli["-n"]["--name"] + .describe( "suite name" ) + .bind( &ConfigData::name, "name" ); - cli["-a"]["--abort"] - .describe( "abort at first failure" ) - .bind( &abortAfterFirst ); + cli["-a"]["--abort"] + .describe( "abort at first failure" ) + .bind( &abortAfterFirst ); - cli["-x"]["--abortx"] - .describe( "abort after x failures" ) - .bind( &abortAfterX, "no. failures" ); + cli["-x"]["--abortx"] + .describe( "abort after x failures" ) + .bind( &abortAfterX, "no. failures" ); - cli["-w"]["--warn"] - .describe( "enable warnings" ) - .bind( &addWarning, "warning name" ); + 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" ); +// - 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[_] + .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["-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["-f"]["--input-file"] + .describe( "load test names to run from a file" ) + .bind( &loadTestNamesFromFile, "filename" ); - // 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 ); + // 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["--list-reporters"] + .describe( "list all reporters" ) + .bind( &ConfigData::listReporters ); - return cli; -} + return cli; + } } // end namespace Catch @@ -5123,13 +4157,13 @@ inline Clara::CommandLine makeCommandLineParser() // #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 +# 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 @@ -5138,12 +4172,10 @@ inline Clara::CommandLine makeCommandLineParser() // Use optional outer namespace #ifdef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE -namespace CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE -{ +namespace CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE { #endif -namespace Tbc -{ +namespace Tbc { #ifdef TBC_TEXT_FORMAT_CONSOLE_WIDTH const unsigned int consoleWidth = TBC_TEXT_FORMAT_CONSOLE_WIDTH; @@ -5151,174 +4183,116 @@ namespace Tbc const unsigned int consoleWidth = 80; #endif -struct TextAttributes -{ - TextAttributes() + struct TextAttributes { + TextAttributes() : initialIndent( std::string::npos ), indent( 0 ), - width( consoleWidth - 1 ), + 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; - } + 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 -}; + 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() ) + 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 ); - } + std::string wrappableChars = " [({.,/|\\-"; + std::size_t indent = _attr.initialIndent != std::string::npos + ? _attr.initialIndent + : _attr.indent; + std::string remainder = _str; - 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 ); + while( !remainder.empty() ) { + if( lines.size() >= 1000 ) { + lines.push_back( "... message truncated due to excessive size" ); + return; } - 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] == ' ' ) - { + 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 ); - } - } - else - { - spliceLine( indent, remainder, width - 1 ); - lines.back() += "-"; - } - if ( lines.size() == 1 ) - { indent = _attr.indent; } - if ( tabPos != std::string::npos ) - { - indent += tabPos; + 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::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; + 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 ); } - return _stream; - } - private: - std::string str; - TextAttributes attr; - std::vector lines; -}; + typedef std::vector::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 lines; + }; } // end namespace Tbc @@ -5329,78 +4303,70 @@ class Text #endif // TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED #undef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE -namespace Catch -{ -using Tbc::Text; -using Tbc::TextAttributes; +namespace Catch { + using Tbc::Text; + using Tbc::TextAttributes; } // #included from: catch_console_colour.hpp #define TWOBLUECUBES_CATCH_CONSOLE_COLOUR_HPP_INCLUDED -namespace Catch -{ +namespace Catch { -namespace Detail -{ -struct IColourImpl; -} + namespace Detail { + struct IColourImpl; + } -struct Colour -{ - enum Code - { - None = 0, + struct Colour { + enum Code { + None = 0, - White, - Red, - Green, - Blue, - Cyan, - Yellow, - Grey, + White, + Red, + Green, + Blue, + Cyan, + Yellow, + Grey, - Bright = 0x10, + Bright = 0x10, - BrightRed = Bright | Red, - BrightGreen = Bright | Green, - LightGrey = Bright | Grey, - BrightWhite = Bright | White, + BrightRed = Bright | Red, + BrightGreen = Bright | Green, + LightGrey = Bright | Grey, + BrightWhite = Bright | White, - // By intention - FileName = LightGrey, - Warning = Yellow, - ResultError = BrightRed, - ResultSuccess = BrightGreen, - ResultExpectedFailure = Warning, + // By intention + FileName = LightGrey, + Warning = Yellow, + ResultError = BrightRed, + ResultSuccess = BrightGreen, + ResultExpectedFailure = Warning, - Error = BrightRed, - Success = Green, + Error = BrightRed, + Success = Green, - OriginalExpression = Cyan, - ReconstructedExpression = Yellow, + OriginalExpression = Cyan, + ReconstructedExpression = Yellow, - SecondaryText = LightGrey, - Headers = White + 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: + static Detail::IColourImpl* impl(); + bool m_moved; }; - // 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: - static Detail::IColourImpl* impl(); - bool m_moved; -}; - -inline std::ostream& operator << ( std::ostream& os, Colour const&) -{ - return os; -} + inline std::ostream& operator << ( std::ostream& os, Colour const& ) { return os; } } // end namespace Catch @@ -5414,471 +4380,400 @@ inline std::ostream& operator << ( std::ostream& os, Colour const&) namespace Catch { -struct ReporterConfig -{ - explicit ReporterConfig( Ptr const& _fullConfig ) + struct ReporterConfig { + explicit ReporterConfig( Ptr const& _fullConfig ) : m_stream( &_fullConfig->stream() ), m_fullConfig( _fullConfig ) {} - ReporterConfig( Ptr const& _fullConfig, std::ostream& _stream ) + ReporterConfig( Ptr const& _fullConfig, std::ostream& _stream ) : m_stream( &_stream ), m_fullConfig( _fullConfig ) {} - std::ostream& stream() const - { - return *m_stream; - } - Ptr fullConfig() const - { - return m_fullConfig; - } + std::ostream& stream() const { return *m_stream; } + Ptr fullConfig() const { return m_fullConfig; } - private: - std::ostream* m_stream; - Ptr m_fullConfig; -}; + private: + std::ostream* m_stream; + Ptr m_fullConfig; + }; -struct ReporterPreferences -{ - ReporterPreferences() + struct ReporterPreferences { + ReporterPreferences() : shouldRedirectStdOut( false ) - {} + {} - bool shouldRedirectStdOut; -}; + bool shouldRedirectStdOut; + }; -template -struct LazyStat : Option -{ - LazyStat() : used( false ) {} - LazyStat& operator=( T const& _value ) - { - Option::operator=( _value ); - used = false; - return *this; - } - void reset() - { - Option::reset(); - used = false; - } - bool used; -}; + template + struct LazyStat : Option { + LazyStat() : used( false ) {} + LazyStat& operator=( T const& _value ) { + Option::operator=( _value ); + used = false; + return *this; + } + void reset() { + Option::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 ) + 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; -}; + std::string name; + std::size_t groupIndex; + std::size_t groupsCounts; + }; -struct AssertionStats -{ - AssertionStats( AssertionResult const& _assertionResult, - std::vector const& _infoMessages, - Totals const& _totals ) + struct AssertionStats { + AssertionStats( AssertionResult const& _assertionResult, + std::vector 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(); + 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 ); + infoMessages.push_back( builder.m_info ); + } } - } - virtual ~AssertionStats(); + virtual ~AssertionStats(); # ifdef CATCH_CPP11_OR_GREATER - AssertionStats( AssertionStats const&) = default; - AssertionStats( AssertionStats&&) = default; - AssertionStats& operator = ( AssertionStats const&) = default; - AssertionStats& operator = ( AssertionStats&&) = default; + AssertionStats( AssertionStats const& ) = default; + AssertionStats( AssertionStats && ) = default; + AssertionStats& operator = ( AssertionStats const& ) = default; + AssertionStats& operator = ( AssertionStats && ) = default; # endif - AssertionResult assertionResult; - std::vector infoMessages; - Totals totals; -}; + AssertionResult assertionResult; + std::vector infoMessages; + Totals totals; + }; -struct SectionStats -{ - SectionStats( SectionInfo const& _sectionInfo, - Counts const& _assertions, - double _durationInSeconds, - bool _missingAssertions ) + struct SectionStats { + SectionStats( SectionInfo const& _sectionInfo, + Counts const& _assertions, + double _durationInSeconds, + bool _missingAssertions ) : sectionInfo( _sectionInfo ), assertions( _assertions ), durationInSeconds( _durationInSeconds ), missingAssertions( _missingAssertions ) - {} - virtual ~SectionStats(); + {} + virtual ~SectionStats(); # ifdef CATCH_CPP11_OR_GREATER - SectionStats( SectionStats const&) = default; - SectionStats( SectionStats&&) = default; - SectionStats& operator = ( SectionStats const&) = default; - SectionStats& operator = ( SectionStats&&) = default; + 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; -}; + 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 ) + 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(); + totals( _totals ), + stdOut( _stdOut ), + stdErr( _stdErr ), + aborting( _aborting ) + {} + virtual ~TestCaseStats(); # ifdef CATCH_CPP11_OR_GREATER - TestCaseStats( TestCaseStats const&) = default; - TestCaseStats( TestCaseStats&&) = default; - TestCaseStats& operator = ( TestCaseStats const&) = default; - TestCaseStats& operator = ( TestCaseStats&&) = default; + 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; -}; + TestCaseInfo testInfo; + Totals totals; + std::string stdOut; + std::string stdErr; + bool aborting; + }; -struct TestGroupStats -{ - TestGroupStats( GroupInfo const& _groupInfo, - Totals const& _totals, - bool _aborting ) + struct TestGroupStats { + TestGroupStats( GroupInfo const& _groupInfo, + Totals const& _totals, + bool _aborting ) : groupInfo( _groupInfo ), totals( _totals ), aborting( _aborting ) - {} - TestGroupStats( GroupInfo const& _groupInfo ) + {} + TestGroupStats( GroupInfo const& _groupInfo ) : groupInfo( _groupInfo ), aborting( false ) - {} - virtual ~TestGroupStats(); + {} + virtual ~TestGroupStats(); # ifdef CATCH_CPP11_OR_GREATER - TestGroupStats( TestGroupStats const&) = default; - TestGroupStats( TestGroupStats&&) = default; - TestGroupStats& operator = ( TestGroupStats const&) = default; - TestGroupStats& operator = ( TestGroupStats&&) = default; + TestGroupStats( TestGroupStats const& ) = default; + TestGroupStats( TestGroupStats && ) = default; + TestGroupStats& operator = ( TestGroupStats const& ) = default; + TestGroupStats& operator = ( TestGroupStats && ) = default; # endif - GroupInfo groupInfo; - Totals totals; - bool aborting; -}; + GroupInfo groupInfo; + Totals totals; + bool aborting; + }; -struct TestRunStats -{ - TestRunStats( TestRunInfo const& _runInfo, - Totals const& _totals, - bool _aborting ) + struct TestRunStats { + TestRunStats( TestRunInfo const& _runInfo, + Totals const& _totals, + bool _aborting ) : runInfo( _runInfo ), totals( _totals ), aborting( _aborting ) - {} - virtual ~TestRunStats(); + {} + virtual ~TestRunStats(); # ifndef CATCH_CPP11_OR_GREATER - TestRunStats( TestRunStats const& _other ) + 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; + TestRunStats( TestRunStats const& ) = default; + TestRunStats( TestRunStats && ) = default; + TestRunStats& operator = ( TestRunStats const& ) = default; + TestRunStats& operator = ( TestRunStats && ) = default; # endif - TestRunInfo runInfo; - Totals totals; - bool aborting; -}; + TestRunInfo runInfo; + Totals totals; + bool aborting; + }; -struct IStreamingReporter : IShared -{ - virtual ~IStreamingReporter(); + struct IStreamingReporter : IShared { + virtual ~IStreamingReporter(); - // Implementing class must also provide the following static method: - // static std::string getDescription(); + // Implementing class must also provide the following static method: + // static std::string getDescription(); - virtual ReporterPreferences getPreferences() const = 0; + virtual ReporterPreferences getPreferences() const = 0; - virtual void noMatchingTestCases( std::string const& spec ) = 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 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 testCaseStarting( TestCaseInfo const& testInfo ) = 0; + virtual void sectionStarting( SectionInfo const& sectionInfo ) = 0; - virtual void assertionStarting( AssertionInfo const& assertionInfo ) = 0; + virtual void assertionStarting( AssertionInfo const& assertionInfo ) = 0; - 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 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; + }; -struct IReporterFactory -{ - virtual ~IReporterFactory(); - virtual IStreamingReporter* create( ReporterConfig const& config ) const = 0; - virtual std::string getDescription() const = 0; -}; + struct IReporterFactory { + virtual ~IReporterFactory(); + virtual IStreamingReporter* create( ReporterConfig const& config ) const = 0; + virtual std::string getDescription() const = 0; + }; -struct IReporterRegistry -{ - typedef std::map FactoryMap; + struct IReporterRegistry { + typedef std::map FactoryMap; - virtual ~IReporterRegistry(); - virtual IStreamingReporter* create( std::string const& name, Ptr const& config ) const = 0; - virtual FactoryMap const& getFactories() const = 0; -}; + virtual ~IReporterRegistry(); + virtual IStreamingReporter* create( std::string const& name, Ptr const& config ) const = 0; + virtual FactoryMap const& getFactories() const = 0; + }; } #include #include -namespace Catch -{ +namespace Catch { -inline std::size_t listTests( Config const& config ) -{ + inline std::size_t listTests( Config const& config ) { - TestSpec testSpec = config.testSpec(); - if ( config.testSpec().hasFilters() ) - { - std::cout << "Matching test cases:\n"; - } - else - { - std::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 matchedTestCases; - getRegistryHub().getTestCaseRegistry().getFilteredTests( testSpec, config, matchedTestCases ); - for ( std::vector::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 ); - - std::cout << Text( testCaseInfo.name, nameAttr ) << std::endl; - if ( !testCaseInfo.tags.empty() ) - { - std::cout << Text( testCaseInfo.tagsAsString, tagsAttr ) << std::endl; + TestSpec testSpec = config.testSpec(); + if( config.testSpec().hasFilters() ) + std::cout << "Matching test cases:\n"; + else { + std::cout << "All available test cases:\n"; + testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "*" ).testSpec(); } - } - if ( !config.testSpec().hasFilters() ) - { - std::cout << pluralise( matchedTests, "test case" ) << "\n" << std::endl; - } - else - { - std::cout << pluralise( matchedTests, "matching test case" ) << "\n" << std::endl; - } - return matchedTests; -} + std::size_t matchedTests = 0; + TextAttributes nameAttr, tagsAttr; + nameAttr.setInitialIndent( 2 ).setIndent( 4 ); + tagsAttr.setIndent( 6 ); -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 matchedTestCases; - getRegistryHub().getTestCaseRegistry().getFilteredTests( testSpec, config, matchedTestCases ); - for ( std::vector::const_iterator it = matchedTestCases.begin(), - itEnd = matchedTestCases.end(); - it != itEnd; - ++it ) - { - matchedTests++; - TestCaseInfo const& testCaseInfo = it->getTestCaseInfo(); - std::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::const_iterator it = spellings.begin(), itEnd = spellings.end(); + std::vector matchedTestCases; + getRegistryHub().getTestCaseRegistry().getFilteredTests( testSpec, config, matchedTestCases ); + for( std::vector::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end(); it != itEnd; - ++it ) - { - out += "[" + *it + "]"; + ++it ) { + matchedTests++; + TestCaseInfo const& testCaseInfo = it->getTestCaseInfo(); + Colour::Code colour = testCaseInfo.isHidden() + ? Colour::SecondaryText + : Colour::None; + Colour colourGuard( colour ); + + std::cout << Text( testCaseInfo.name, nameAttr ) << std::endl; + if( !testCaseInfo.tags.empty() ) + std::cout << Text( testCaseInfo.tagsAsString, tagsAttr ) << std::endl; } - return out; - } - std::set spellings; - std::size_t count; -}; -inline std::size_t listTags( Config const& config ) -{ - TestSpec testSpec = config.testSpec(); - if ( config.testSpec().hasFilters() ) - { - std::cout << "Tags for matching test cases:\n"; - } - else - { - std::cout << "All available tags:\n"; - testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "*" ).testSpec(); + if( !config.testSpec().hasFilters() ) + std::cout << pluralise( matchedTests, "test case" ) << "\n" << std::endl; + else + std::cout << pluralise( matchedTests, "matching test case" ) << "\n" << std::endl; + return matchedTests; } - std::map tagCounts; + 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 matchedTestCases; + getRegistryHub().getTestCaseRegistry().getFilteredTests( testSpec, config, matchedTestCases ); + for( std::vector::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end(); + it != itEnd; + ++it ) { + matchedTests++; + TestCaseInfo const& testCaseInfo = it->getTestCaseInfo(); + std::cout << testCaseInfo.name << std::endl; + } + return matchedTests; + } - std::vector matchedTestCases; - getRegistryHub().getTestCaseRegistry().getFilteredTests( testSpec, config, matchedTestCases ); - for ( std::vector::const_iterator it = matchedTestCases.begin(), - itEnd = matchedTestCases.end(); - it != itEnd; - ++it ) - { - for ( std::set::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::iterator countIt = tagCounts.find( lcaseTagName ); - if ( countIt == tagCounts.end() ) - { - countIt = tagCounts.insert( std::make_pair( lcaseTagName, TagInfo() ) ).first; + 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::const_iterator it = spellings.begin(), itEnd = spellings.end(); + it != itEnd; + ++it ) + out += "[" + *it + "]"; + return out; + } + std::set spellings; + std::size_t count; + }; + + inline std::size_t listTags( Config const& config ) { + TestSpec testSpec = config.testSpec(); + if( config.testSpec().hasFilters() ) + std::cout << "Tags for matching test cases:\n"; + else { + std::cout << "All available tags:\n"; + testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "*" ).testSpec(); + } + + std::map tagCounts; + + std::vector matchedTestCases; + getRegistryHub().getTestCaseRegistry().getFilteredTests( testSpec, config, matchedTestCases ); + for( std::vector::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end(); + it != itEnd; + ++it ) { + for( std::set::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::iterator countIt = tagCounts.find( lcaseTagName ); + if( countIt == tagCounts.end() ) + countIt = tagCounts.insert( std::make_pair( lcaseTagName, TagInfo() ) ).first; + countIt->second.add( tagName ); } - countIt->second.add( tagName ); } + + for( std::map::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 ) ); + std::cout << oss.str() << wrapper << "\n"; + } + std::cout << pluralise( tagCounts.size(), "tag" ) << "\n" << std::endl; + return tagCounts.size(); } - for ( std::map::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 ) ); - std::cout << oss.str() << wrapper << "\n"; - } - std::cout << pluralise( tagCounts.size(), "tag" ) << "\n" << std::endl; - return tagCounts.size(); -} + inline std::size_t listReporters( Config const& /*config*/ ) { + std::cout << "Available reports:\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() ); -inline std::size_t listReporters( Config const& /*config*/ ) -{ - std::cout << "Available reports:\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 ) ); + std::cout << " " + << it->first + << ":" + << std::string( maxNameLen - it->first.size() + 2, ' ' ) + << wrapper << "\n"; + } + std::cout << std::endl; + return factories.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 ) ); - std::cout << " " - << it->first - << ":" - << std::string( maxNameLen - it->first.size() + 2, ' ' ) - << wrapper << "\n"; + inline Option list( Config const& config ) { + Option 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; } - std::cout << std::endl; - return factories.size(); -} - -inline Option list( Config const& config ) -{ - Option 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 @@ -5892,158 +4787,128 @@ inline Option list( Config const& config ) #include #include -namespace Catch -{ -namespace SectionTracking -{ +namespace Catch { +namespace SectionTracking { -class TrackedSection -{ + class TrackedSection { - typedef std::map TrackedSections; + typedef std::map TrackedSections; + + public: + enum RunState { + NotStarted, + Executing, + ExecutingChildren, + Completed + }; + + TrackedSection( std::string const& name, TrackedSection* parent ) + : m_name( name ), m_runState( NotStarted ), m_parent( parent ) + {} + + RunState runState() const { return m_runState; } + + TrackedSection* findChild( std::string const& childName ) { + TrackedSections::iterator it = m_children.find( childName ); + return it != m_children.end() + ? &it->second + : NULL; + } + TrackedSection* acquireChild( std::string const& childName ) { + if( TrackedSection* child = findChild( childName ) ) + return child; + m_children.insert( std::make_pair( childName, TrackedSection( childName, this ) ) ); + return findChild( childName ); + } + void enter() { + if( m_runState == NotStarted ) + m_runState = Executing; + } + void leave() { + for( TrackedSections::const_iterator it = m_children.begin(), itEnd = m_children.end(); + it != itEnd; + ++it ) + if( it->second.runState() != Completed ) { + m_runState = ExecutingChildren; + return; + } + m_runState = Completed; + } + TrackedSection* getParent() { + return m_parent; + } + bool hasChildren() const { + return !m_children.empty(); + } + + private: + std::string m_name; + RunState m_runState; + TrackedSections m_children; + TrackedSection* m_parent; - public: - enum RunState - { - NotStarted, - Executing, - ExecutingChildren, - Completed }; - TrackedSection( std::string const& name, TrackedSection* parent ) - : m_name( name ), m_runState( NotStarted ), m_parent( parent ) - {} - - RunState runState() const - { - return m_runState; - } - - TrackedSection* findChild( std::string const& childName ) - { - TrackedSections::iterator it = m_children.find( childName ); - return it != m_children.end() - ? &it->second - : NULL; - } - TrackedSection* acquireChild( std::string const& childName ) - { - if ( TrackedSection* child = findChild( childName ) ) - { - return child; - } - m_children.insert( std::make_pair( childName, TrackedSection( childName, this ) ) ); - return findChild( childName ); - } - void enter() - { - if ( m_runState == NotStarted ) - { - m_runState = Executing; - } - } - void leave() - { - for ( TrackedSections::const_iterator it = m_children.begin(), itEnd = m_children.end(); - it != itEnd; - ++it ) - if ( it->second.runState() != Completed ) - { - m_runState = ExecutingChildren; - return; - } - m_runState = Completed; - } - TrackedSection* getParent() - { - return m_parent; - } - bool hasChildren() const - { - return !m_children.empty(); - } - - private: - std::string m_name; - RunState m_runState; - TrackedSections m_children; - TrackedSection* m_parent; - -}; - -class TestCaseTracker -{ - public: - TestCaseTracker( std::string const& testCaseName ) + class TestCaseTracker { + public: + TestCaseTracker( std::string const& testCaseName ) : m_testCase( testCaseName, NULL ), m_currentSection( &m_testCase ), m_completedASectionThisRun( false ) - {} + {} - bool enterSection( std::string const& name ) - { - TrackedSection* child = m_currentSection->acquireChild( name ); - if ( m_completedASectionThisRun || child->runState() == TrackedSection::Completed ) - { - return false; + bool enterSection( std::string const& name ) { + TrackedSection* child = m_currentSection->acquireChild( name ); + if( m_completedASectionThisRun || child->runState() == TrackedSection::Completed ) + return false; + + m_currentSection = child; + m_currentSection->enter(); + return true; + } + void leaveSection() { + m_currentSection->leave(); + m_currentSection = m_currentSection->getParent(); + assert( m_currentSection != NULL ); + m_completedASectionThisRun = true; } - m_currentSection = child; - m_currentSection->enter(); - return true; - } - void leaveSection() - { - m_currentSection->leave(); - m_currentSection = m_currentSection->getParent(); - assert( m_currentSection != NULL ); - m_completedASectionThisRun = true; - } - - bool currentSectionHasChildren() const - { - return m_currentSection->hasChildren(); - } - bool isCompleted() const - { - return m_testCase.runState() == TrackedSection::Completed; - } - - class Guard - { - public: - Guard( TestCaseTracker& tracker ) : m_tracker( tracker ) - { - m_tracker.enterTestCase(); + bool currentSectionHasChildren() const { + return m_currentSection->hasChildren(); } - ~Guard() - { - m_tracker.leaveTestCase(); + bool isCompleted() const { + return m_testCase.runState() == TrackedSection::Completed; } - private: - Guard( Guard const&); - void operator = ( Guard const&); - TestCaseTracker& m_tracker; + + class Guard { + public: + Guard( TestCaseTracker& tracker ) : m_tracker( tracker ) { + m_tracker.enterTestCase(); + } + ~Guard() { + m_tracker.leaveTestCase(); + } + private: + Guard( Guard const& ); + void operator = ( Guard const& ); + TestCaseTracker& m_tracker; + }; + + private: + void enterTestCase() { + m_currentSection = &m_testCase; + m_completedASectionThisRun = false; + m_testCase.enter(); + } + void leaveTestCase() { + m_testCase.leave(); + } + + TrackedSection m_testCase; + TrackedSection* m_currentSection; + bool m_completedASectionThisRun; }; - private: - void enterTestCase() - { - m_currentSection = &m_testCase; - m_completedASectionThisRun = false; - m_testCase.enter(); - } - void leaveTestCase() - { - m_testCase.leave(); - } - - TrackedSection m_testCase; - TrackedSection* m_currentSection; - bool m_completedASectionThisRun; -}; - } // namespace SectionTracking using SectionTracking::TestCaseTracker; @@ -6053,45 +4918,41 @@ using SectionTracking::TestCaseTracker; #include #include -namespace Catch -{ +namespace Catch { -class StreamRedirect -{ + class StreamRedirect { - public: - StreamRedirect( std::ostream& stream, std::string& targetString ) + public: + StreamRedirect( std::ostream& stream, std::string& targetString ) : m_stream( stream ), m_prevBuf( stream.rdbuf() ), m_targetString( targetString ) - { - stream.rdbuf( m_oss.rdbuf() ); - } + { + stream.rdbuf( m_oss.rdbuf() ); + } - ~StreamRedirect() - { - m_targetString += m_oss.str(); - m_stream.rdbuf( m_prevBuf ); - } + ~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; -}; + private: + std::ostream& m_stream; + std::streambuf* m_prevBuf; + std::ostringstream m_oss; + std::string& m_targetString; + }; -/////////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////// -class RunContext : public IResultCapture, public IRunner -{ + class RunContext : public IResultCapture, public IRunner { - RunContext( RunContext const&); - void operator =( RunContext const&); + RunContext( RunContext const& ); + void operator =( RunContext const& ); - public: + public: - explicit RunContext( Ptr const& config, Ptr const& reporter ) + explicit RunContext( Ptr const& config, Ptr const& reporter ) : m_runInfo( config->name() ), m_context( getCurrentMutableContext() ), m_activeTestCase( NULL ), @@ -6100,563 +4961,468 @@ class RunContext : public IResultCapture, public IRunner m_prevRunner( m_context.getRunner() ), m_prevResultCapture( m_context.getResultCapture() ), m_prevConfig( m_context.getConfig() ) - { - 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() ) ); - m_context.setRunner( m_prevRunner ); - m_context.setConfig( NULL ); - m_context.setResultCapture( m_prevResultCapture ); - m_context.setConfig( m_prevConfig ); - } - - 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; - m_testCaseTracker = TestCaseTracker( testInfo.name ); - - do { - do - { - runCurrentTest( redirectedCout, redirectedCerr ); + 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() ) ); + m_context.setRunner( m_prevRunner ); + m_context.setConfig( NULL ); + m_context.setResultCapture( m_prevResultCapture ); + m_context.setConfig( m_prevConfig ); + } + + 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; + m_testCaseTracker = TestCaseTracker( testInfo.name ); + + do { + do { + runCurrentTest( redirectedCout, redirectedCerr ); + } + while( !m_testCaseTracker->isCompleted() && !aborting() ); } - while ( !m_testCaseTracker->isCompleted() && !aborting() ); + 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 = NULL; + m_testCaseTracker.reset(); + + return deltaTotals; } - 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 = NULL; - m_testCaseTracker.reset(); - - return deltaTotals; - } - - Ptr config() const - { - return m_config; - } - - private: // IResultCapture - - virtual void assertionEnded( AssertionResult const& result ) - { - if ( result.getResultType() == ResultWas::Ok ) - { - m_totals.assertions.passed++; + Ptr config() const { + return m_config; } - else if ( !result.isOk() ) + + 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; + + if( !m_testCaseTracker->enterSection( oss.str() ) ) + return false; + + m_lastAssertionInfo.lineInfo = sectionInfo.lineInfo; + + m_reporter->sectionStarting( sectionInfo ); + + assertions = m_totals.assertions; + + return true; + } + bool testForMissingAssertions( Counts& assertions ) { + if( assertions.total() != 0 || + !m_config->warnAboutMissingAssertions() || + m_testCaseTracker->currentSectionHasChildren() ) + return false; m_totals.assertions.failed++; + assertions.failed++; + return true; } - if ( m_reporter->assertionEnded( AssertionStats( result, m_messages, m_totals ) ) ) - { + virtual void sectionEnded( SectionInfo const& info, Counts const& prevAssertions, double _durationInSeconds ) { + if( std::uncaught_exception() ) { + m_unfinishedSections.push_back( UnfinishedSections( info, prevAssertions, _durationInSeconds ) ); + return; + } + + Counts assertions = m_totals.assertions - prevAssertions; + bool missingAssertions = testForMissingAssertions( assertions ); + + m_testCaseTracker->leaveSection(); + + m_reporter->sectionEnded( SectionStats( info, assertions, _durationInSeconds, missingAssertions ) ); 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; - - if ( !m_testCaseTracker->enterSection( oss.str() ) ) - { - return false; + virtual void pushScopedMessage( MessageInfo const& message ) { + m_messages.push_back( message ); } - m_lastAssertionInfo.lineInfo = sectionInfo.lineInfo; - - m_reporter->sectionStarting( sectionInfo ); - - assertions = m_totals.assertions; - - return true; - } - bool testForMissingAssertions( Counts& assertions ) - { - if ( assertions.total() != 0 || - !m_config->warnAboutMissingAssertions() || - m_testCaseTracker->currentSectionHasChildren() ) - { - return false; - } - m_totals.assertions.failed++; - assertions.failed++; - return true; - } - - virtual void sectionEnded( SectionInfo const& info, Counts const& prevAssertions, - double _durationInSeconds ) - { - if ( std::uncaught_exception() ) - { - m_unfinishedSections.push_back( UnfinishedSections( info, prevAssertions, _durationInSeconds ) ); - return; + virtual void popScopedMessage( MessageInfo const& message ) { + m_messages.erase( std::remove( m_messages.begin(), m_messages.end(), message ), m_messages.end() ); } - Counts assertions = m_totals.assertions - prevAssertions; - bool missingAssertions = testForMissingAssertions( assertions ); + virtual std::string getCurrentTestName() const { + return m_activeTestCase + ? m_activeTestCase->getTestCaseInfo().name + : ""; + } - m_testCaseTracker->leaveSection(); + virtual const AssertionResult* getLastResult() const { + return &m_lastResult; + } - m_reporter->sectionEnded( SectionStats( info, assertions, _durationInSeconds, missingAssertions ) ); - m_messages.clear(); - } + public: + // !TBD We need to do this another way! + bool aborting() const { + return m_totals.assertions.failed == static_cast( m_config->abortAfter() ); + } - virtual void pushScopedMessage( MessageInfo const& message ) - { - m_messages.push_back( message ); - } + private: - virtual void popScopedMessage( MessageInfo const& message ) - { - m_messages.erase( std::remove( m_messages.begin(), m_messages.end(), message ), m_messages.end() ); - } + 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 ); + TestCaseTracker::Guard guard( *m_testCaseTracker ); - virtual std::string getCurrentTestName() const - { - return m_activeTestCase - ? m_activeTestCase->getTestCaseInfo().name - : ""; - } - - virtual const AssertionResult* getLastResult() const - { - return &m_lastResult; - } - - public: - // !TBD We need to do this another way! - bool aborting() const - { - return m_totals.assertions.failed == static_cast( 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 ); - TestCaseTracker::Guard guard( *m_testCaseTracker ); - - Timer timer; - timer.start(); - if ( m_reporter->getPreferences().shouldRedirectStdOut ) - { - StreamRedirect coutRedir( std::cout, redirectedCout ); - StreamRedirect cerrRedir( std::cerr, redirectedCerr ); - m_activeTestCase->invoke(); + Timer timer; + timer.start(); + if( m_reporter->getPreferences().shouldRedirectStdOut ) { + StreamRedirect coutRedir( std::cout, redirectedCout ); + StreamRedirect cerrRedir( std::cerr, redirectedCerr ); + m_activeTestCase->invoke(); + } + else { + m_activeTestCase->invoke(); + } + duration = timer.getElapsedSeconds(); } - else - { - m_activeTestCase->invoke(); + catch( TestFailureException& ) { + // This just means the test was aborted due to failure } - duration = timer.getElapsedSeconds(); - } - catch ( TestFailureException&) - { - // This just means the test was aborted due to failure - } - catch (...) - { - ResultBuilder exResult( m_lastAssertionInfo.macroName.c_str(), - m_lastAssertionInfo.lineInfo, - m_lastAssertionInfo.capturedExpression.c_str(), - m_lastAssertionInfo.resultDisposition ); - exResult.useActiveException(); - } - // 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::const_reverse_iterator it = m_unfinishedSections.rbegin(), - itEnd = m_unfinishedSections.rend(); - it != itEnd; - ++it ) - { - sectionEnded( it->info, it->prevAssertions, it->durationInSeconds ); - } - m_unfinishedSections.clear(); - m_messages.clear(); + catch(...) { + ResultBuilder exResult( m_lastAssertionInfo.macroName.c_str(), + m_lastAssertionInfo.lineInfo, + m_lastAssertionInfo.capturedExpression.c_str(), + m_lastAssertionInfo.resultDisposition ); + exResult.useActiveException(); + } + // 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::const_reverse_iterator it = m_unfinishedSections.rbegin(), + itEnd = m_unfinishedSections.rend(); + it != itEnd; + ++it ) + sectionEnded( it->info, it->prevAssertions, it->durationInSeconds ); + m_unfinishedSections.clear(); + m_messages.clear(); - Counts assertions = m_totals.assertions - prevAssertions; - bool missingAssertions = testForMissingAssertions( assertions ); + 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; + 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 ); } - SectionStats testCaseSectionStats( testCaseSection, assertions, duration, missingAssertions ); - m_reporter->sectionEnded( testCaseSectionStats ); - } - - private: - struct UnfinishedSections - { - UnfinishedSections( SectionInfo const& _info, Counts const& _prevAssertions, - double _durationInSeconds ) + private: + struct UnfinishedSections { + UnfinishedSections( SectionInfo const& _info, Counts const& _prevAssertions, double _durationInSeconds ) : info( _info ), prevAssertions( _prevAssertions ), durationInSeconds( _durationInSeconds ) - {} + {} - SectionInfo info; - Counts prevAssertions; - double durationInSeconds; + SectionInfo info; + Counts prevAssertions; + double durationInSeconds; + }; + + TestRunInfo m_runInfo; + IMutableContext& m_context; + TestCase const* m_activeTestCase; + Option m_testCaseTracker; + AssertionResult m_lastResult; + + Ptr m_config; + Totals m_totals; + Ptr m_reporter; + std::vector m_messages; + IRunner* m_prevRunner; + IResultCapture* m_prevResultCapture; + Ptr m_prevConfig; + AssertionInfo m_lastAssertionInfo; + std::vector m_unfinishedSections; }; - TestRunInfo m_runInfo; - IMutableContext& m_context; - TestCase const* m_activeTestCase; - Option m_testCaseTracker; - AssertionResult m_lastResult; - - Ptr m_config; - Totals m_totals; - Ptr m_reporter; - std::vector m_messages; - IRunner* m_prevRunner; - IResultCapture* m_prevResultCapture; - Ptr m_prevConfig; - AssertionInfo m_lastAssertionInfo; - std::vector m_unfinishedSections; -}; - -IResultCapture& getResultCapture() -{ - if ( IResultCapture* capture = getCurrentContext().getResultCapture() ) - { - return *capture; + IResultCapture& getResultCapture() { + if( IResultCapture* capture = getCurrentContext().getResultCapture() ) + return *capture; + else + throw std::logic_error( "No result capture instance" ); } - 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 -{ +namespace Catch { -// Versioning information -struct Version -{ - Version( unsigned int _majorVersion, - unsigned int _minorVersion, - unsigned int _buildNumber, - char const* const _branchName ) + // Versioning information + struct Version { + Version( unsigned int _majorVersion, + unsigned int _minorVersion, + unsigned int _buildNumber, + char const* const _branchName ) : majorVersion( _majorVersion ), minorVersion( _minorVersion ), buildNumber( _buildNumber ), branchName( _branchName ) - {} + {} - unsigned int const majorVersion; - unsigned int const minorVersion; - unsigned int const buildNumber; - char const* const branchName; + unsigned int const majorVersion; + unsigned int const minorVersion; + unsigned int const buildNumber; + char const* const branchName; - private: - void operator=( Version const&); -}; + private: + void operator=( Version const& ); + }; -extern Version libraryVersion; + extern Version libraryVersion; } #include #include #include -namespace Catch -{ +namespace Catch { -class Runner -{ + class Runner { - public: - Runner( Ptr const& config ) + public: + Runner( Ptr const& config ) : m_config( config ) - { - openStream(); - makeReporter(); - } - - Totals runTests() - { - - RunContext context( m_config.get(), m_reporter ); - - Totals totals; - - context.testGroupStarting( "", 1, 1 ); // deprecated? - - TestSpec testSpec = m_config->testSpec(); - if ( !testSpec.hasFilters() ) { - testSpec = TestSpecParser( - ITagAliasRegistry::get() ).parse( "~[.]" ).testSpec(); // All not hidden tests + openStream(); + makeReporter(); } - std::vector testCases; - getRegistryHub().getTestCaseRegistry().getFilteredTests( testSpec, *m_config, testCases ); + Totals runTests() { - int testsRunForGroup = 0; - for ( std::vector::const_iterator it = testCases.begin(), itEnd = testCases.end(); - it != itEnd; - ++it ) - { - testsRunForGroup++; - if ( m_testsAlreadyRun.find( *it ) == m_testsAlreadyRun.end() ) - { + RunContext context( m_config.get(), m_reporter ); - if ( context.aborting() ) - { - break; + Totals totals; + + context.testGroupStarting( "", 1, 1 ); // deprecated? + + TestSpec testSpec = m_config->testSpec(); + if( !testSpec.hasFilters() ) + testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "~[.]" ).testSpec(); // All not hidden tests + + std::vector testCases; + getRegistryHub().getTestCaseRegistry().getFilteredTests( testSpec, *m_config, testCases ); + + int testsRunForGroup = 0; + for( std::vector::const_iterator it = testCases.begin(), itEnd = testCases.end(); + it != itEnd; + ++it ) { + testsRunForGroup++; + if( m_testsAlreadyRun.find( *it ) == m_testsAlreadyRun.end() ) { + + if( context.aborting() ) + break; + + totals += context.runTest( *it ); + m_testsAlreadyRun.insert( *it ); } + } + context.testGroupEnded( "", totals, 1, 1 ); + return totals; + } - totals += context.runTest( *it ); - m_testsAlreadyRun.insert( *it ); + private: + void openStream() { + // Open output file, if specified + if( !m_config->getFilename().empty() ) { + m_ofs.open( m_config->getFilename().c_str() ); + if( m_ofs.fail() ) { + std::ostringstream oss; + oss << "Unable to open file: '" << m_config->getFilename() << "'"; + throw std::domain_error( oss.str() ); + } + m_config->setStreamBuf( m_ofs.rdbuf() ); } } - context.testGroupEnded( "", totals, 1, 1 ); - return totals; - } + void makeReporter() { + std::string reporterName = m_config->getReporterName().empty() + ? "console" + : m_config->getReporterName(); - private: - void openStream() - { - // Open output file, if specified - if ( !m_config->getFilename().empty() ) - { - m_ofs.open( m_config->getFilename().c_str() ); - if ( m_ofs.fail() ) - { + m_reporter = getRegistryHub().getReporterRegistry().create( reporterName, m_config.get() ); + if( !m_reporter ) { std::ostringstream oss; - oss << "Unable to open file: '" << m_config->getFilename() << "'"; + oss << "No reporter registered with name: '" << reporterName << "'"; throw std::domain_error( oss.str() ); } - m_config->setStreamBuf( m_ofs.rdbuf() ); } - } - void makeReporter() - { - std::string reporterName = m_config->getReporterName().empty() - ? "console" - : m_config->getReporterName(); - m_reporter = getRegistryHub().getReporterRegistry().create( reporterName, m_config.get() ); - if ( !m_reporter ) - { - std::ostringstream oss; - oss << "No reporter registered with name: '" << reporterName << "'"; - throw std::domain_error( oss.str() ); - } - } - - private: - Ptr m_config; - std::ofstream m_ofs; - Ptr m_reporter; - std::set m_testsAlreadyRun; -}; - -class Session -{ - static bool alreadyInstantiated; - - public: - - struct OnUnusedOptions - { - enum DoWhat { Ignore, Fail }; + private: + Ptr m_config; + std::ofstream m_ofs; + Ptr m_reporter; + std::set m_testsAlreadyRun; }; - Session() - : m_cli( makeCommandLineParser() ) - { - if ( alreadyInstantiated ) - { - std::string msg = "Only one instance of Catch::Session can ever be used"; - std::cerr << msg << std::endl; - throw std::logic_error( msg ); - } - alreadyInstantiated = true; - } - ~Session() - { - Catch::cleanUp(); - } + class Session { + static bool alreadyInstantiated; - void showHelp( std::string const& processName ) - { - std::cout << "\nCatch v" << libraryVersion.majorVersion << "." - << libraryVersion.minorVersion << " build " - << libraryVersion.buildNumber; - if ( libraryVersion.branchName != std::string( "master" ) ) - { - std::cout << " (" << libraryVersion.branchName << " branch)"; - } - std::cout << "\n"; + public: - m_cli.usage( std::cout, processName ); - std::cout << "For more detail usage please see the project docs\n" << std::endl; - } + struct OnUnusedOptions { enum DoWhat { Ignore, Fail }; }; - 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 ); + Session() + : m_cli( makeCommandLineParser() ) { + if( alreadyInstantiated ) { + std::string msg = "Only one instance of Catch::Session can ever be used"; + std::cerr << msg << std::endl; + throw std::logic_error( msg ); } - m_config.reset(); + alreadyInstantiated = true; } - catch ( std::exception& ex ) - { - { - Colour colourGuard( Colour::Red ); - std::cerr << "\nError(s) in input:\n" - << Text( ex.what(), TextAttributes().setIndent(2) ) - << "\n\n"; + ~Session() { + Catch::cleanUp(); + } + + void showHelp( std::string const& processName ) { + std::cout << "\nCatch v" << libraryVersion.majorVersion << "." + << libraryVersion.minorVersion << " build " + << libraryVersion.buildNumber; + if( libraryVersion.branchName != std::string( "master" ) ) + std::cout << " (" << libraryVersion.branchName << " branch)"; + std::cout << "\n"; + + m_cli.usage( std::cout, processName ); + std::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 ); + std::cerr << "\nError(s) in input:\n" + << Text( ex.what(), TextAttributes().setIndent(2) ) + << "\n\n"; + } + m_cli.usage( std::cout, m_configData.processName ); + return (std::numeric_limits::max)(); } - m_cli.usage( std::cout, m_configData.processName ); - return (std::numeric_limits::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() - { - if ( m_configData.showHelp ) - { return 0; } - try - { - config(); // Force config to be constructed - Runner runner( m_config ); + void useConfigData( ConfigData const& _configData ) { + m_configData = _configData; + m_config.reset(); + } - // Handle list request - if ( Option listed = list( config() ) ) + int run( int argc, char* const argv[] ) { + + int returnCode = applyCommandLine( argc, argv ); + if( returnCode == 0 ) + returnCode = run(); + return returnCode; + } + + int run() { + if( m_configData.showHelp ) + return 0; + + try { - return static_cast( *listed ); + config(); // Force config to be constructed + Runner runner( m_config ); + + // Handle list request + if( Option listed = list( config() ) ) + return static_cast( *listed ); + + return static_cast( runner.runTests().assertions.failed ); + } + catch( std::exception& ex ) { + std::cerr << ex.what() << std::endl; + return (std::numeric_limits::max)(); } - - return static_cast( runner.runTests().assertions.failed ); } - catch ( std::exception& ex ) - { - std::cerr << ex.what() << std::endl; - return (std::numeric_limits::max)(); + + Clara::CommandLine const& cli() const { + return m_cli; } - } - - Clara::CommandLine const& cli() const - { - return m_cli; - } - std::vector const& unusedTokens() const - { - return m_unusedTokens; - } - ConfigData& configData() - { - return m_configData; - } - Config& config() - { - if ( !m_config ) - { - m_config = new Config( m_configData ); + std::vector 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; } - return *m_config; - } - private: - Clara::CommandLine m_cli; - std::vector m_unusedTokens; - ConfigData m_configData; - Ptr m_config; -}; + private: + Clara::CommandLine m_cli; + std::vector m_unusedTokens; + ConfigData m_configData; + Ptr m_config; + }; -bool Session::alreadyInstantiated = false; + bool Session::alreadyInstantiated = false; } // end namespace Catch @@ -6671,139 +5437,117 @@ bool Session::alreadyInstantiated = false; #include #include -namespace Catch -{ +namespace Catch { -class TestRegistry : public ITestCaseRegistry -{ - public: - TestRegistry() : m_unnamedCount( 0 ) {} - virtual ~TestRegistry(); + class TestRegistry : public ITestCaseRegistry { + public: + TestRegistry() : 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() ) ); - } + 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() ) ); + } - if ( m_functions.find( testCase ) == m_functions.end() ) - { - m_functions.insert( testCase ); - m_functionsInOrder.push_back( testCase ); - if ( !testCase.isHidden() ) - { - m_nonHiddenFunctions.push_back( testCase ); + if( m_functions.find( testCase ) == m_functions.end() ) { + m_functions.insert( testCase ); + m_functionsInOrder.push_back( testCase ); + if( !testCase.isHidden() ) + m_nonHiddenFunctions.push_back( testCase ); + } + else { + TestCase const& prev = *m_functions.find( testCase ); + { + Colour colourGuard( Colour::Red ); + std::cerr << "error: TEST_CASE( \"" << name << "\" ) already defined.\n" + << "\tFirst seen at " << prev.getTestCaseInfo().lineInfo << "\n" + << "\tRedefined at " << testCase.getTestCaseInfo().lineInfo << std::endl; + } + exit(1); } } - else - { - TestCase const& prev = *m_functions.find( testCase ); - { - Colour colourGuard( Colour::Red ); - std::cerr << "error: TEST_CASE( \"" << name << "\" ) already defined.\n" - << "\tFirst seen at " << prev.getTestCaseInfo().lineInfo << "\n" - << "\tRedefined at " << testCase.getTestCaseInfo().lineInfo << std::endl; - } - exit(1); + + virtual std::vector const& getAllTests() const { + return m_functionsInOrder; } - } - virtual std::vector const& getAllTests() const - { - return m_functionsInOrder; - } + virtual std::vector const& getAllNonHiddenTests() const { + return m_nonHiddenFunctions; + } - virtual std::vector const& getAllNonHiddenTests() const - { - return m_nonHiddenFunctions; - } - - virtual void getFilteredTests( TestSpec const& testSpec, IConfig const& config, - std::vector& matchingTestCases ) const - { - for ( std::vector::const_iterator it = m_functionsInOrder.begin(), - itEnd = m_functionsInOrder.end(); - it != itEnd; - ++it ) - { - if ( testSpec.matches( *it ) && ( config.allowThrows() || !it->throws() ) ) - { - matchingTestCases.push_back( *it ); + virtual void getFilteredTests( TestSpec const& testSpec, IConfig const& config, std::vector& matchingTestCases ) const { + for( std::vector::const_iterator it = m_functionsInOrder.begin(), + itEnd = m_functionsInOrder.end(); + it != itEnd; + ++it ) { + if( testSpec.matches( *it ) && ( config.allowThrows() || !it->throws() ) ) + matchingTestCases.push_back( *it ); } } - } - private: + private: - std::set m_functions; - std::vector m_functionsInOrder; - std::vector m_nonHiddenFunctions; - size_t m_unnamedCount; -}; + std::set m_functions; + std::vector m_functionsInOrder; + std::vector m_nonHiddenFunctions; + size_t m_unnamedCount; + }; -/////////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////// -class FreeFunctionTestCase : public SharedImpl -{ - public: + class FreeFunctionTestCase : public SharedImpl { + public: - FreeFunctionTestCase( TestFunction fun ) : m_fun( fun ) {} + 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; + virtual void invoke() const { + m_fun(); } - className = className.substr( penultimateColons, lastColons - penultimateColons ); + + 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; } - return className; -} -/////////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////// -AutoReg::AutoReg( TestFunction function, - SourceLineInfo const& lineInfo, - NameAndDesc const& nameAndDesc ) -{ - registerTestCase( new FreeFunctionTestCase( function ), "", nameAndDesc, lineInfo ); -} + AutoReg::AutoReg( TestFunction function, + SourceLineInfo const& lineInfo, + NameAndDesc const& nameAndDesc ) { + registerTestCase( new FreeFunctionTestCase( function ), "", nameAndDesc, lineInfo ); + } -AutoReg::~AutoReg() {} + AutoReg::~AutoReg() {} -void AutoReg::registerTestCase( ITestCase* testCase, - char const* classOrQualifiedMethodName, - NameAndDesc const& nameAndDesc, - SourceLineInfo const& lineInfo ) -{ + void AutoReg::registerTestCase( ITestCase* testCase, + char const* classOrQualifiedMethodName, + NameAndDesc const& nameAndDesc, + SourceLineInfo const& lineInfo ) { - getMutableRegistryHub().registerTest - ( makeTestCase( testCase, - extractClassName( classOrQualifiedMethodName ), - nameAndDesc.name, - nameAndDesc.description, - lineInfo ) ); -} + getMutableRegistryHub().registerTest + ( makeTestCase( testCase, + extractClassName( classOrQualifiedMethodName ), + nameAndDesc.name, + nameAndDesc.description, + lineInfo ) ); + } } // end namespace Catch @@ -6812,208 +5556,165 @@ void AutoReg::registerTestCase( ITestCase* testCase, #include -namespace Catch -{ +namespace Catch { -class ReporterRegistry : public IReporterRegistry -{ + class ReporterRegistry : public IReporterRegistry { - public: + public: - virtual ~ReporterRegistry() - { - deleteAllValues( m_factories ); - } - - virtual IStreamingReporter* create( std::string const& name, Ptr const& config ) const - { - FactoryMap::const_iterator it = m_factories.find( name ); - if ( it == m_factories.end() ) - { - return NULL; + virtual ~ReporterRegistry() { + deleteAllValues( m_factories ); } - return it->second->create( ReporterConfig( config ) ); - } - void registerReporter( std::string const& name, IReporterFactory* factory ) - { - m_factories.insert( std::make_pair( name, factory ) ); - } + virtual IStreamingReporter* create( std::string const& name, Ptr const& config ) const { + FactoryMap::const_iterator it = m_factories.find( name ); + if( it == m_factories.end() ) + return NULL; + return it->second->create( ReporterConfig( config ) ); + } - FactoryMap const& getFactories() const - { - return m_factories; - } + void registerReporter( std::string const& name, IReporterFactory* factory ) { + m_factories.insert( std::make_pair( name, factory ) ); + } - private: - FactoryMap m_factories; -}; + FactoryMap const& getFactories() const { + return m_factories; + } + + private: + FactoryMap m_factories; + }; } // #included from: catch_exception_translator_registry.hpp #define TWOBLUECUBES_CATCH_EXCEPTION_TRANSLATOR_REGISTRY_HPP_INCLUDED #ifdef __OBJC__ - #import "Foundation/Foundation.h" +#import "Foundation/Foundation.h" #endif -namespace Catch -{ +namespace Catch { -class ExceptionTranslatorRegistry : public IExceptionTranslatorRegistry -{ - public: - ~ExceptionTranslatorRegistry() - { - deleteAll( m_translators ); - } + class ExceptionTranslatorRegistry : public IExceptionTranslatorRegistry { + public: + ~ExceptionTranslatorRegistry() { + deleteAll( m_translators ); + } - virtual void registerTranslator( const IExceptionTranslator* translator ) - { - m_translators.push_back( translator ); - } + virtual void registerTranslator( const IExceptionTranslator* translator ) { + m_translators.push_back( translator ); + } - virtual std::string translateActiveException() const - { - try - { + virtual std::string translateActiveException() const { + try { #ifdef __OBJC__ - // In Objective-C try objective-c exceptions first - @try - { + // In Objective-C try objective-c exceptions first + @try { + throw; + } + @catch (NSException *exception) { + return toString( [exception description] ); + } +#else + throw; +#endif + } + catch( TestFailureException& ) { throw; } - @catch (NSException* exception) - { - return toString( [exception description] ); + catch( std::exception& ex ) { + return ex.what(); + } + catch( std::string& msg ) { + return msg; + } + catch( const char* msg ) { + return msg; + } + catch(...) { + return tryTranslators( m_translators.begin() ); } -#else - throw; -#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 tryTranslators( m_translators.begin() ); - } - } - - std::string tryTranslators( std::vector::const_iterator it ) const - { - if ( it == m_translators.end() ) - { - return "Unknown exception"; } - try - { - return (*it)->translate(); - } - catch (...) - { - return tryTranslators( it + 1 ); - } - } + std::string tryTranslators( std::vector::const_iterator it ) const { + if( it == m_translators.end() ) + return "Unknown exception"; - private: - std::vector m_translators; -}; + try { + return (*it)->translate(); + } + catch(...) { + return tryTranslators( it+1 ); + } + } + + private: + std::vector m_translators; + }; } -namespace Catch -{ +namespace Catch { -namespace -{ + namespace { -class RegistryHub : public IRegistryHub, public IMutableRegistryHub -{ + class RegistryHub : public IRegistryHub, public IMutableRegistryHub { - RegistryHub( RegistryHub const&); - void operator=( RegistryHub const&); + RegistryHub( RegistryHub const& ); + void operator=( RegistryHub const& ); - public: // IRegistryHub - RegistryHub() - { - } - virtual IReporterRegistry const& getReporterRegistry() const - { - return m_reporterRegistry; - } - virtual ITestCaseRegistry const& getTestCaseRegistry() const - { - return m_testCaseRegistry; - } - virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() - { - return m_exceptionTranslatorRegistry; + public: // IRegistryHub + RegistryHub() { + } + virtual IReporterRegistry const& getReporterRegistry() const { + return m_reporterRegistry; + } + virtual ITestCaseRegistry const& getTestCaseRegistry() const { + return m_testCaseRegistry; + } + virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() { + return m_exceptionTranslatorRegistry; + } + + public: // IMutableRegistryHub + virtual void registerReporter( std::string const& name, IReporterFactory* factory ) { + m_reporterRegistry.registerReporter( name, factory ); + } + virtual void registerTest( TestCase const& testInfo ) { + m_testCaseRegistry.registerTest( testInfo ); + } + virtual void registerTranslator( const IExceptionTranslator* translator ) { + m_exceptionTranslatorRegistry.registerTranslator( translator ); + } + + private: + TestRegistry m_testCaseRegistry; + ReporterRegistry m_reporterRegistry; + ExceptionTranslatorRegistry m_exceptionTranslatorRegistry; + }; + + // Single, global, instance + inline RegistryHub*& getTheRegistryHub() { + static RegistryHub* theRegistryHub = NULL; + if( !theRegistryHub ) + theRegistryHub = new RegistryHub(); + return theRegistryHub; + } } - public: // IMutableRegistryHub - virtual void registerReporter( std::string const& name, IReporterFactory* factory ) - { - m_reporterRegistry.registerReporter( name, factory ); + IRegistryHub& getRegistryHub() { + return *getTheRegistryHub(); } - virtual void registerTest( TestCase const& testInfo ) - { - m_testCaseRegistry.registerTest( testInfo ); + IMutableRegistryHub& getMutableRegistryHub() { + return *getTheRegistryHub(); } - virtual void registerTranslator( const IExceptionTranslator* translator ) - { - m_exceptionTranslatorRegistry.registerTranslator( translator ); + void cleanUp() { + delete getTheRegistryHub(); + getTheRegistryHub() = NULL; + cleanUpContext(); } - - private: - TestRegistry m_testCaseRegistry; - ReporterRegistry m_reporterRegistry; - ExceptionTranslatorRegistry m_exceptionTranslatorRegistry; -}; - -// Single, global, instance -inline RegistryHub*& getTheRegistryHub() -{ - static RegistryHub* theRegistryHub = NULL; - if ( !theRegistryHub ) - { - theRegistryHub = new RegistryHub(); + std::string translateActiveException() { + return getRegistryHub().getExceptionTranslatorRegistry().translateActiveException(); } - return theRegistryHub; -} -} - -IRegistryHub& getRegistryHub() -{ - return *getTheRegistryHub(); -} -IMutableRegistryHub& getMutableRegistryHub() -{ - return *getTheRegistryHub(); -} -void cleanUp() -{ - delete getTheRegistryHub(); - getTheRegistryHub() = NULL; - cleanUpContext(); -} -std::string translateActiveException() -{ - return getRegistryHub().getExceptionTranslatorRegistry().translateActiveException(); -} } // end namespace Catch @@ -7022,22 +5723,19 @@ std::string translateActiveException() #include -namespace Catch -{ +namespace Catch { -NotImplementedException::NotImplementedException( SourceLineInfo const& lineInfo ) - : m_lineInfo( lineInfo ) -{ - std::ostringstream oss; - oss << lineInfo << ": function "; - oss << "not implemented"; - m_what = oss.str(); -} + 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(); -} + const char* NotImplementedException::what() const CATCH_NOEXCEPT { + return m_what.c_str(); + } } // end namespace Catch @@ -7052,321 +5750,247 @@ const char* NotImplementedException::what() const CATCH_NOEXCEPT #include -namespace Catch -{ +namespace Catch { -class StreamBufBase : public std::streambuf -{ - public: - virtual ~StreamBufBase() CATCH_NOEXCEPT; -}; + class StreamBufBase : public std::streambuf { + public: + virtual ~StreamBufBase() CATCH_NOEXCEPT; + }; } #include #include -namespace Catch -{ +namespace Catch { -template -class StreamBufImpl : public StreamBufBase -{ - char data[bufferSize]; - WriterF m_writer; + template + 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( c ) ) ); - } - else - { - sputc( static_cast( c ) ); - } + public: + StreamBufImpl() { + setp( data, data + sizeof(data) ); } - return 0; - } - int sync() - { - if ( pbase() != pptr() ) - { - m_writer( std::string( pbase(), static_cast( pptr() - pbase() ) ) ); - setp( pbase(), epptr() ); + ~StreamBufImpl() CATCH_NOEXCEPT { + sync(); } - return 0; - } -}; -/////////////////////////////////////////////////////////////////////////// + private: + int overflow( int c ) { + sync(); -struct OutputDebugWriter -{ + if( c != EOF ) { + if( pbase() == epptr() ) + m_writer( std::string( 1, static_cast( c ) ) ); + else + sputc( static_cast( c ) ); + } + return 0; + } - void operator()( std::string const& str ) - { - writeToDebugConsole( str ); - } -}; + int sync() { + if( pbase() != pptr() ) { + m_writer( std::string( pbase(), static_cast( pptr() - pbase() ) ) ); + setp( pbase(), epptr() ); + } + return 0; + } + }; -Stream::Stream() + /////////////////////////////////////////////////////////////////////////// + + struct OutputDebugWriter { + + void operator()( std::string const&str ) { + writeToDebugConsole( str ); + } + }; + + Stream::Stream() : streamBuf( NULL ), isOwned( false ) -{} + {} -Stream::Stream( std::streambuf* _streamBuf, bool _isOwned ) + Stream::Stream( std::streambuf* _streamBuf, bool _isOwned ) : streamBuf( _streamBuf ), isOwned( _isOwned ) -{} + {} -void Stream::release() -{ - if ( isOwned ) - { - delete streamBuf; - streamBuf = NULL; - isOwned = false; - } -} -} - -namespace Catch -{ - -class Context : public IMutableContext -{ - - Context() : m_config( NULL ), m_runner( NULL ), m_resultCapture( 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 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 const& config ) - { - m_config = config; - } - - friend IMutableContext& getCurrentMutableContext(); - - private: - IGeneratorsForTest* findGeneratorsForCurrentTest() - { - std::string testName = getResultCapture()->getCurrentTestName(); - - std::map::const_iterator it = - m_generatorsByTestName.find( testName ); - return it != m_generatorsByTestName.end() - ? it->second - : NULL; - } - - IGeneratorsForTest& getGeneratorsForCurrentTest() - { - IGeneratorsForTest* generators = findGeneratorsForCurrentTest(); - if ( !generators ) - { - std::string testName = getResultCapture()->getCurrentTestName(); - generators = createGeneratorsForTest(); - m_generatorsByTestName.insert( std::make_pair( testName, generators ) ); + void Stream::release() { + if( isOwned ) { + delete streamBuf; + streamBuf = NULL; + isOwned = false; } - return *generators; } - - private: - Ptr m_config; - IRunner* m_runner; - IResultCapture* m_resultCapture; - std::map m_generatorsByTestName; -}; - -namespace -{ -Context* currentContext = NULL; -} -IMutableContext& getCurrentMutableContext() -{ - if ( !currentContext ) - { - currentContext = new Context(); - } - return *currentContext; -} -IContext& getCurrentContext() -{ - return getCurrentMutableContext(); } -Stream createStream( std::string const& streamName ) -{ - if ( streamName == "stdout" ) - { - return Stream( std::cout.rdbuf(), false ); +namespace Catch { + + class Context : public IMutableContext { + + Context() : m_config( NULL ), m_runner( NULL ), m_resultCapture( 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 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 const& config ) { + m_config = config; + } + + friend IMutableContext& getCurrentMutableContext(); + + private: + IGeneratorsForTest* findGeneratorsForCurrentTest() { + std::string testName = getResultCapture()->getCurrentTestName(); + + std::map::const_iterator it = + m_generatorsByTestName.find( testName ); + return it != m_generatorsByTestName.end() + ? it->second + : 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 m_config; + IRunner* m_runner; + IResultCapture* m_resultCapture; + std::map m_generatorsByTestName; + }; + + namespace { + Context* currentContext = NULL; } - if ( streamName == "stderr" ) - { - return Stream( std::cerr.rdbuf(), false ); + IMutableContext& getCurrentMutableContext() { + if( !currentContext ) + currentContext = new Context(); + return *currentContext; } - if ( streamName == "debug" ) - { - return Stream( new StreamBufImpl, true ); + IContext& getCurrentContext() { + return getCurrentMutableContext(); } - throw std::domain_error( "Unknown stream: " + streamName ); -} + Stream createStream( std::string const& streamName ) { + if( streamName == "stdout" ) return Stream( std::cout.rdbuf(), false ); + if( streamName == "stderr" ) return Stream( std::cerr.rdbuf(), false ); + if( streamName == "debug" ) return Stream( new StreamBufImpl, true ); -void cleanUpContext() -{ - delete currentContext; - currentContext = NULL; -} + throw std::domain_error( "Unknown stream: " + streamName ); + } + + void cleanUpContext() { + delete currentContext; + currentContext = NULL; + } } // #included from: catch_console_colour_impl.hpp #define TWOBLUECUBES_CATCH_CONSOLE_COLOUR_IMPL_HPP_INCLUDED -namespace Catch -{ -namespace Detail -{ -struct IColourImpl -{ - virtual ~IColourImpl() {} - virtual void use( Colour::Code _colourCode ) = 0; -}; -} -} +namespace Catch { namespace Detail { + struct IColourImpl { + virtual ~IColourImpl() {} + virtual void use( Colour::Code _colourCode ) = 0; + }; +}} #if defined ( CATCH_PLATFORM_WINDOWS ) ///////////////////////////////////////// #ifndef NOMINMAX - #define NOMINMAX +#define NOMINMAX #endif #ifdef __AFXDLL - #include +#include #else - #include +#include #endif -namespace Catch -{ -namespace -{ +namespace Catch { +namespace { -class Win32ColourImpl : public Detail::IColourImpl -{ - public: - Win32ColourImpl() : stdoutHandle( GetStdHandle(STD_OUTPUT_HANDLE) ) - { - CONSOLE_SCREEN_BUFFER_INFO csbiInfo; - GetConsoleScreenBufferInfo( stdoutHandle, &csbiInfo ); - originalAttributes = csbiInfo.wAttributes; - } - - virtual void use( Colour::Code _colourCode ) - { - switch ( _colourCode ) + class Win32ColourImpl : public Detail::IColourImpl { + public: + Win32ColourImpl() : stdoutHandle( GetStdHandle(STD_OUTPUT_HANDLE) ) { - case Colour::None: - return setTextAttribute( originalAttributes ); - 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" ); + CONSOLE_SCREEN_BUFFER_INFO csbiInfo; + GetConsoleScreenBufferInfo( stdoutHandle, &csbiInfo ); + originalAttributes = csbiInfo.wAttributes; } + + virtual void use( Colour::Code _colourCode ) { + switch( _colourCode ) { + case Colour::None: return setTextAttribute( originalAttributes ); + 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 ); + } + HANDLE stdoutHandle; + WORD originalAttributes; + }; + + inline bool shouldUseColourForPlatform() { + return true; } - private: - void setTextAttribute( WORD _textAttribute ) - { - SetConsoleTextAttribute( stdoutHandle, _textAttribute ); + static Detail::IColourImpl* platformColourInstance() { + static Win32ColourImpl s_instance; + return &s_instance; } - HANDLE stdoutHandle; - WORD originalAttributes; -}; - -inline bool shouldUseColourForPlatform() -{ - return true; -} - -static Detail::IColourImpl* platformColourInstance() -{ - static Win32ColourImpl s_instance; - return &s_instance; -} } // end anon namespace } // end namespace Catch @@ -7375,121 +5999,82 @@ static Detail::IColourImpl* platformColourInstance() #include -namespace Catch -{ -namespace -{ +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 Detail::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" ); + // 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 Detail::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::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" ); + case Colour::Bright: throw std::logic_error( "not a colour" ); + } } - } - private: - void setColour( const char* _escapeCode ) - { - std::cout << '\033' << _escapeCode; - } -}; + private: + void setColour( const char* _escapeCode ) { + std::cout << '\033' << _escapeCode; + } + }; -inline bool shouldUseColourForPlatform() -{ - return isatty(STDOUT_FILENO); -} + inline bool shouldUseColourForPlatform() { + return isatty(STDOUT_FILENO); + } -static Detail::IColourImpl* platformColourInstance() -{ - static PosixColourImpl s_instance; - return &s_instance; -} + static Detail::IColourImpl* platformColourInstance() { + static PosixColourImpl s_instance; + return &s_instance; + } } // end anon namespace } // end namespace Catch #endif // not Windows -namespace Catch -{ +namespace Catch { -namespace -{ -struct NoColourImpl : Detail::IColourImpl -{ - void use( Colour::Code ) {} + namespace { + struct NoColourImpl : Detail::IColourImpl { + void use( Colour::Code ) {} - static IColourImpl* instance() - { - static NoColourImpl s_instance; - return &s_instance; + static IColourImpl* instance() { + static NoColourImpl s_instance; + return &s_instance; + } + }; + static bool shouldUseColour() { + return shouldUseColourForPlatform() && !isDebuggerActive(); + } } -}; -static bool shouldUseColour() -{ - return shouldUseColourForPlatform() && !isDebuggerActive(); -} -} -Colour::Colour( Code _colourCode ) : m_moved( false ) -{ - use( _colourCode ); -} -Colour::Colour( Colour const& _other ) : m_moved( false ) -{ - const_cast( _other ).m_moved = true; -} -Colour::~Colour() -{ - if ( !m_moved ) - { - use( None ); + Colour::Colour( Code _colourCode ) : m_moved( false ) { use( _colourCode ); } + Colour::Colour( Colour const& _other ) : m_moved( false ) { const_cast( _other ).m_moved = true; } + Colour::~Colour(){ if( !m_moved ) use( None ); } + void Colour::use( Code _colourCode ) { + impl()->use( _colourCode ); } -} -void Colour::use( Code _colourCode ) -{ - impl()->use( _colourCode ); -} -Detail::IColourImpl* Colour::impl() -{ - return shouldUseColour() - ? platformColourInstance() - : NoColourImpl::instance(); -} + Detail::IColourImpl* Colour::impl() { + return shouldUseColour() + ? platformColourInstance() + : NoColourImpl::instance(); + } } // end namespace Catch @@ -7500,324 +6085,258 @@ Detail::IColourImpl* Colour::impl() #include #include -namespace Catch -{ +namespace Catch { -struct GeneratorInfo : IGeneratorInfo -{ + struct GeneratorInfo : IGeneratorInfo { - GeneratorInfo( std::size_t size ) + GeneratorInfo( std::size_t size ) : m_size( size ), m_currentIndex( 0 ) - {} + {} - bool moveNext() - { - if ( ++m_currentIndex == m_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::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::const_iterator it = m_generatorsInOrder.begin(); + std::vector::const_iterator itEnd = m_generatorsInOrder.end(); + for(; it != itEnd; ++it ) { + if( (*it)->moveNext() ) + return true; + } return false; } - return true; - } - std::size_t getCurrentIndex() const + private: + std::map m_generatorsByName; + std::vector m_generatorsInOrder; + }; + + IGeneratorsForTest* createGeneratorsForTest() { - return m_currentIndex; + return new GeneratorsForTest(); } - 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::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::const_iterator it = m_generatorsInOrder.begin(); - std::vector::const_iterator itEnd = m_generatorsInOrder.end(); - for (; it != itEnd; ++it ) - { - if ( (*it)->moveNext() ) - { - return true; - } - } - return false; - } - - private: - std::map m_generatorsByName; - std::vector m_generatorsInOrder; -}; - -IGeneratorsForTest* createGeneratorsForTest() -{ - return new GeneratorsForTest(); -} - } // end namespace Catch // #included from: catch_assertionresult.hpp #define TWOBLUECUBES_CATCH_ASSERTIONRESULT_HPP_INCLUDED -namespace Catch -{ +namespace Catch { -AssertionInfo::AssertionInfo( std::string const& _macroName, - SourceLineInfo const& _lineInfo, - std::string const& _capturedExpression, - ResultDisposition::Flags _resultDisposition ) + 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() {} -AssertionResult::AssertionResult( AssertionInfo const& info, AssertionResultData const& data ) + AssertionResult::AssertionResult( AssertionInfo const& info, AssertionResultData const& data ) : m_info( info ), m_resultData( data ) -{} + {} -AssertionResult::~AssertionResult() {} + 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; + // Result was a success + bool AssertionResult::succeeded() const { + return Catch::isOk( m_resultData.resultType ); } - else - { - return m_info.capturedExpression; + + // Result was a success, or failure is suppressed + bool AssertionResult::isOk() const { + return Catch::isOk( m_resultData.resultType ) || shouldSuppressFailure( m_info.resultDisposition ); } -} -std::string AssertionResult::getExpressionInMacro() const -{ - if ( m_info.macroName.empty() ) - { - return m_info.capturedExpression; + + ResultWas::OfType AssertionResult::getResultType() const { + return m_resultData.resultType; } - else - { - return m_info.macroName + "( " + m_info.capturedExpression + " )"; + + bool AssertionResult::hasExpression() const { + return !m_info.capturedExpression.empty(); } -} -bool AssertionResult::hasExpandedExpression() const -{ - return hasExpression() && getExpandedExpression() != getExpression(); -} + bool AssertionResult::hasMessage() const { + return !m_resultData.message.empty(); + } -std::string AssertionResult::getExpandedExpression() const -{ - return m_resultData.reconstructedExpression; -} + 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 + " )"; + } -std::string AssertionResult::getMessage() const -{ - return m_resultData.message; -} -SourceLineInfo AssertionResult::getSourceInfo() const -{ - return m_info.lineInfo; -} + bool AssertionResult::hasExpandedExpression() const { + return hasExpression() && getExpandedExpression() != getExpression(); + } -std::string AssertionResult::getTestMacroName() const -{ - return m_info.macroName; -} + 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 -{ +namespace Catch { -inline TestCaseInfo::SpecialProperties parseSpecialTag( std::string const& tag ) -{ - if ( tag == "." || + inline TestCaseInfo::SpecialProperties parseSpecialTag( std::string const& tag ) { + if( tag == "." || tag == "hide" || tag == "!hide" ) - { - return TestCaseInfo::IsHidden; + 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; } - else if ( tag == "!throws" ) - { - return TestCaseInfo::Throws; + inline bool isReservedTag( std::string const& tag ) { + return parseSpecialTag( tag ) == TestCaseInfo::None && tag.size() > 0 && !isalnum( tag[0] ); } - 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 ); - std::cerr + inline void enforceNotReservedTag( std::string const& tag, SourceLineInfo const& _lineInfo ) { + if( isReservedTag( tag ) ) { + { + Colour colourGuard( Colour::Red ); + std::cerr << "Tag name [" << tag << "] not allowed.\n" << "Tag names starting with non alpha-numeric characters are reserved\n"; + } + { + Colour colourGuard( Colour::FileName ); + std::cerr << _lineInfo << std::endl; + } + exit(1); } - { - Colour colourGuard( Colour::FileName ); - std::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 tags; - std::string desc, tag; - bool inTag = false; - for ( std::size_t i = 0; i < _descOrTags.size(); ++i ) + TestCase makeTestCase( ITestCase* _testCase, + std::string const& _className, + std::string const& _name, + std::string const& _descOrTags, + SourceLineInfo const& _lineInfo ) { - char c = _descOrTags[i]; - if ( !inTag ) - { - if ( c == '[' ) - { - inTag = true; - } - else - { - desc += c; - } - } - else - { - if ( c == ']' ) - { - enforceNotReservedTag( tag, _lineInfo ); + bool isHidden( startsWith( _name, "./" ) ); // Legacy support - inTag = false; - if ( tag == "hide" || tag == "." ) - { - isHidden = true; + // Parse out tags + std::set 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 == ']' ) { + enforceNotReservedTag( tag, _lineInfo ); + + inTag = false; + if( tag == "hide" || tag == "." ) + isHidden = true; + else + tags.insert( tag ); + tag.clear(); } else - { - tags.insert( tag ); - } - tag.clear(); - } - else - { - tag += c; + tag += c; } } - } - if ( isHidden ) - { - tags.insert( "hide" ); - tags.insert( "." ); + if( isHidden ) { + tags.insert( "hide" ); + tags.insert( "." ); + } + + TestCaseInfo info( _name, _className, desc, tags, _lineInfo ); + return TestCase( _testCase, info ); } - TestCaseInfo info( _name, _className, desc, tags, _lineInfo ); - return TestCase( _testCase, info ); -} - -TestCaseInfo::TestCaseInfo( std::string const& _name, - std::string const& _className, - std::string const& _description, - std::set const& _tags, - SourceLineInfo const& _lineInfo ) + TestCaseInfo::TestCaseInfo( std::string const& _name, + std::string const& _className, + std::string const& _description, + std::set const& _tags, + SourceLineInfo const& _lineInfo ) : name( _name ), className( _className ), description( _description ), tags( _tags ), lineInfo( _lineInfo ), properties( None ) -{ - std::ostringstream oss; - for ( std::set::const_iterator it = _tags.begin(), itEnd = _tags.end(); it != itEnd; - ++it ) { - oss << "[" << *it << "]"; - std::string lcaseTag = toLower( *it ); - properties = static_cast( properties | parseSpecialTag( lcaseTag ) ); - lcaseTags.insert( lcaseTag ); + std::ostringstream oss; + for( std::set::const_iterator it = _tags.begin(), itEnd = _tags.end(); it != itEnd; ++it ) { + oss << "[" << *it << "]"; + std::string lcaseTag = toLower( *it ); + properties = static_cast( properties | parseSpecialTag( lcaseTag ) ); + lcaseTags.insert( lcaseTag ); + } + tagsAsString = oss.str(); } - tagsAsString = oss.str(); -} -TestCaseInfo::TestCaseInfo( TestCaseInfo const& other ) + TestCaseInfo::TestCaseInfo( TestCaseInfo const& other ) : name( other.name ), className( other.className ), description( other.description ), @@ -7826,127 +6345,113 @@ TestCaseInfo::TestCaseInfo( TestCaseInfo const& other ) 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; -} + 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( ITestCase* testCase, TestCaseInfo const& info ) : TestCaseInfo( info ), test( testCase ) {} -TestCase::TestCase( TestCase const& other ) + 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; -} + 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( other ).properties ); - std::swap( lineInfo, other.lineInfo ); -} + 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( other ).properties ); + std::swap( lineInfo, other.lineInfo ); + } -void TestCase::invoke() const -{ - test->invoke(); -} + 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 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; -} + 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; -} + TestCaseInfo const& TestCase::getTestCaseInfo() const + { + return *this; + } } // end namespace Catch // #included from: catch_version.hpp #define TWOBLUECUBES_CATCH_VERSION_HPP_INCLUDED -namespace Catch -{ +namespace Catch { -// These numbers are maintained by a script -Version libraryVersion( 1, 0, 53, "master" ); + // These numbers are maintained by a script + Version libraryVersion( 1, 0, 53, "master" ); } // #included from: catch_message.hpp #define TWOBLUECUBES_CATCH_MESSAGE_HPP_INCLUDED -namespace Catch -{ +namespace Catch { -MessageInfo::MessageInfo( std::string const& _macroName, - SourceLineInfo const& _lineInfo, - ResultWas::OfType _type ) + 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; + // This may need protecting if threading support is added + unsigned int MessageInfo::globalCount = 0; -//////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////// -ScopedMessage::ScopedMessage( MessageBuilder const& builder ) + 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.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 ); -} + ScopedMessage::~ScopedMessage() { + getResultCapture().popScopedMessage( m_info ); + } } // end namespace Catch @@ -7958,329 +6463,278 @@ ScopedMessage::~ScopedMessage() namespace Catch { -// Deprecated -struct IReporter : IShared -{ - virtual ~IReporter(); + // Deprecated + struct IReporter : IShared { + virtual ~IReporter(); - virtual bool shouldRedirectStdout() const = 0; + 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; -}; + 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 -{ - public: - LegacyReporterAdapter( Ptr const& legacyReporter ); - virtual ~LegacyReporterAdapter(); + class LegacyReporterAdapter : public SharedImpl + { + public: + LegacyReporterAdapter( Ptr 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 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 ); - private: - Ptr m_legacyReporter; -}; + private: + Ptr m_legacyReporter; + }; } namespace Catch { -LegacyReporterAdapter::LegacyReporterAdapter( Ptr const& legacyReporter ) + LegacyReporterAdapter::LegacyReporterAdapter( Ptr const& legacyReporter ) : m_legacyReporter( legacyReporter ) -{} -LegacyReporterAdapter::~LegacyReporterAdapter() {} + {} + LegacyReporterAdapter::~LegacyReporterAdapter() {} -ReporterPreferences LegacyReporterAdapter::getPreferences() const -{ - ReporterPreferences prefs; - prefs.shouldRedirectStdOut = m_legacyReporter->shouldRedirectStdout(); - return prefs; -} + 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 -} + 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::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 ); + bool LegacyReporterAdapter::assertionEnded( AssertionStats const& assertionStats ) { + if( assertionStats.assertionResult.getResultType() != ResultWas::Ok ) { + for( std::vector::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; } - m_legacyReporter->Result( assertionStats.assertionResult ); - return true; -} -void LegacyReporterAdapter::sectionEnded( SectionStats const& sectionStats ) -{ - if ( sectionStats.missingAssertions ) - { - m_legacyReporter->NoAssertionsInSection( sectionStats.sectionInfo.name ); + void LegacyReporterAdapter::sectionEnded( SectionStats const& sectionStats ) { + if( sectionStats.missingAssertions ) + m_legacyReporter->NoAssertionsInSection( sectionStats.sectionInfo.name ); + m_legacyReporter->EndSection( sectionStats.sectionInfo.name, sectionStats.assertions ); } - 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(); + 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 ); } - m_legacyReporter->EndGroup( testGroupStats.groupInfo.name, testGroupStats.totals ); -} -void LegacyReporterAdapter::testRunEnded( TestRunStats const& testRunStats ) -{ - m_legacyReporter->EndTesting( testRunStats.totals ); -} } // #included from: catch_timer.hpp #ifdef __clang__ - #pragma clang diagnostic push - #pragma clang diagnostic ignored "-Wc++11-long-long" +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wc++11-long-long" #endif #ifdef CATCH_PLATFORM_WINDOWS - #include +#include #else - #include +#include #endif -namespace Catch -{ +namespace Catch { -namespace -{ + namespace { #ifdef CATCH_PLATFORM_WINDOWS -uint64_t getCurrentTicks() -{ - static uint64_t hz = 0, hzo = 0; - if (!hz) - { - QueryPerformanceFrequency((LARGE_INTEGER*)&hz); - QueryPerformanceCounter((LARGE_INTEGER*)&hzo); + uint64_t getCurrentTicks() { + static uint64_t hz=0, hzo=0; + if (!hz) { + QueryPerformanceFrequency((LARGE_INTEGER*)&hz); + QueryPerformanceCounter((LARGE_INTEGER*)&hzo); + } + uint64_t t; + QueryPerformanceCounter((LARGE_INTEGER*)&t); + return ((t-hzo)*1000000)/hz; + } +#else + uint64_t getCurrentTicks() { + timeval t; + gettimeofday(&t,NULL); + return static_cast( t.tv_sec ) * 1000000ull + static_cast( t.tv_usec ); + } +#endif } - uint64_t t; - QueryPerformanceCounter((LARGE_INTEGER*)&t); - return ((t - hzo) * 1000000) / hz; -} -#else -uint64_t getCurrentTicks() -{ - timeval t; - gettimeofday(&t, NULL); - return static_cast( t.tv_sec ) * 1000000ull + static_cast( t.tv_usec ); -} -#endif -} -void Timer::start() -{ - m_ticks = getCurrentTicks(); -} -unsigned int Timer::getElapsedNanoseconds() const -{ - return static_cast(getCurrentTicks() - m_ticks); -} -unsigned int Timer::getElapsedMilliseconds() const -{ - return static_cast((getCurrentTicks() - m_ticks) / 1000); -} -double Timer::getElapsedSeconds() const -{ - return (getCurrentTicks() - m_ticks) / 1000000.0; -} + void Timer::start() { + m_ticks = getCurrentTicks(); + } + unsigned int Timer::getElapsedNanoseconds() const { + return static_cast(getCurrentTicks() - m_ticks); + } + unsigned int Timer::getElapsedMilliseconds() const { + return static_cast((getCurrentTicks() - m_ticks)/1000); + } + double Timer::getElapsedSeconds() const { + return (getCurrentTicks() - m_ticks)/1000000.0; + } } // namespace Catch #ifdef __clang__ - #pragma clang diagnostic pop +#pragma clang diagnostic pop #endif // #included from: catch_common.hpp #define TWOBLUECUBES_CATCH_COMMON_HPP_INCLUDED -namespace Catch -{ +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 ); + 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 ) : ""; -} + return start != std::string::npos ? str.substr( start, 1+end-start ) : ""; + } -pluralise::pluralise( std::size_t count, std::string const& label ) + 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"; + 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; } - return os; -} -SourceLineInfo::SourceLineInfo() : line( 0 ) {} -SourceLineInfo::SourceLineInfo( char const* _file, std::size_t _line ) + SourceLineInfo::SourceLineInfo() : line( 0 ){} + SourceLineInfo::SourceLineInfo( char const* _file, std::size_t _line ) : file( _file ), line( _line ) -{} -SourceLineInfo::SourceLineInfo( SourceLineInfo const& other ) + {} + 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; -} - -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() ); + {} + bool SourceLineInfo::empty() const { + return file.empty(); + } + bool SourceLineInfo::operator == ( SourceLineInfo const& other ) const { + return line == other.line && file == other.file; + } + + 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 -{ +namespace Catch { -SectionInfo::SectionInfo -( SourceLineInfo const& _lineInfo, - std::string const& _name, - std::string const& _description ) + SectionInfo::SectionInfo + ( SourceLineInfo const& _lineInfo, + std::string const& _name, + std::string const& _description ) : name( _name ), description( _description ), lineInfo( _lineInfo ) -{} + {} -Section::Section( SectionInfo const& info ) + Section::Section( SectionInfo const& info ) : m_info( info ), m_sectionIncluded( getResultCapture().sectionStarted( m_info, m_assertions ) ) -{ - m_timer.start(); -} - -Section::~Section() -{ - if ( m_sectionIncluded ) { - getResultCapture().sectionEnded( m_info, m_assertions, m_timer.getElapsedSeconds() ); + m_timer.start(); } -} -// This indicates whether the section should be executed or not -Section::operator bool() const -{ - return m_sectionIncluded; -} + Section::~Section() { + if( m_sectionIncluded ) + getResultCapture().sectionEnded( m_info, m_assertions, m_timer.getElapsedSeconds() ); + } + + // This indicates whether the section should be executed or not + Section::operator bool() const { + return m_sectionIncluded; + } } // end namespace Catch @@ -8291,319 +6745,254 @@ Section::operator bool() const #ifdef CATCH_PLATFORM_MAC -#include -#include -#include -#include -#include + #include + #include + #include + #include + #include -namespace Catch -{ + namespace Catch{ -// The following function is taken directly from the following technical note: -// http://developer.apple.com/library/mac/#qa/qa2004/qa1361.html + // 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() -{ + // 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; + 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. + // Initialize the flags so that, if sysctl fails for some bizarre + // reason, we get a predictable result. - info.kp_proc.p_flag = 0; + 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. + // 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(); + mib[0] = CTL_KERN; + mib[1] = KERN_PROC; + mib[2] = KERN_PROC_PID; + mib[3] = getpid(); - // Call sysctl. + // Call sysctl. - size = sizeof(info); - if ( sysctl(mib, sizeof(mib) / sizeof(*mib), &info, &size, NULL, 0) != 0 ) - { - std::cerr << "\n** Call to sysctl failed - unable to determine if debugger is active **\n" << - std::endl; - return false; - } + size = sizeof(info); + if( sysctl(mib, sizeof(mib) / sizeof(*mib), &info, &size, NULL, 0) != 0 ) { + std::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. + // We're being debugged if the P_TRACED flag is set. - return ( (info.kp_proc.p_flag & P_TRACED) != 0 ); -} -} // namespace Catch + 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; -} -} + 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; -} -} + extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent(); + namespace Catch { + bool isDebuggerActive() { + return IsDebuggerPresent() != 0; + } + } #else -namespace Catch -{ -inline bool isDebuggerActive() -{ - return false; -} -} + 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() ); -} -} + 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 - std::cout << text; -} -} + namespace Catch { + void writeToDebugConsole( std::string const& text ) { + // !TBD: Need a version for Mac/ XCode and other IDEs + std::cout << text; + } + } #endif // Platform // #included from: catch_tostring.hpp #define TWOBLUECUBES_CATCH_TOSTRING_HPP_INCLUDED -namespace Catch -{ +namespace Catch { -namespace Detail -{ +namespace Detail { -namespace -{ -struct Endianness -{ - enum Arch { Big, Little }; + namespace { + struct Endianness { + enum Arch { Big, Little }; - static Arch which() - { - union _ - { - int asInt; - char asChar[sizeof (int)]; - } u; + 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( size ), inc = 1; - if ( Endianness::which() == Endianness::Little ) - { - i = end - 1; - end = inc = -1; - } - - unsigned char const* bytes = static_cast(object); - std::ostringstream os; - os << "0x" << std::setfill('0') << std::hex; - for ( ; i != end; i += inc ) - { - os << std::setw(2) << static_cast(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; + u.asInt = 1; + return ( u.asChar[sizeof(int)-1] == 1 ) ? Big : Little; } - if ( !subs.empty() ) - { - s = s.substr( 0, i ) + subs + s.substr( i + 1 ); + }; + } + + std::string rawMemoryToString( const void *object, std::size_t size ) + { + // Reverse order for little endian architectures + int i = 0, end = static_cast( size ), inc = 1; + if( Endianness::which() == Endianness::Little ) { + i = end-1; + end = inc = -1; + } + + unsigned char const *bytes = static_cast(object); + std::ostringstream os; + os << "0x" << std::setfill('0') << std::hex; + for( ; i != end; i += inc ) + os << std::setw(2) << static_cast(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 toString( std::wstring const& value ) { std::string s; s.reserve( value.size() ); - for (size_t i = 0; i < value.size(); ++i ) - { + for(size_t i = 0; i < value.size(); ++i ) s += value[i] <= 0xff ? static_cast( value[i] ) : '?'; - } return toString( s ); } -std::string toString( const char* const value ) -{ +std::string toString( const char* const value ) { return value ? Catch::toString( std::string( value ) ) : std::string( "{null string}" ); } -std::string toString( char* const value ) -{ +std::string toString( char* const value ) { return Catch::toString( static_cast( value ) ); } std::string toString( const wchar_t* const value ) { - return value ? Catch::toString( std::wstring(value) ) : std::string( "{null string}" ); + return value ? Catch::toString( std::wstring(value) ) : std::string( "{null string}" ); } std::string toString( wchar_t* const value ) { - return Catch::toString( static_cast( value ) ); + return Catch::toString( static_cast( value ) ); } -std::string toString( int value ) -{ +std::string toString( int value ) { std::ostringstream oss; oss << value; return oss.str(); } -std::string toString( unsigned long value ) -{ +std::string toString( unsigned long value ) { std::ostringstream oss; - if ( value > 8192 ) - { + if( value > 8192 ) oss << "0x" << std::hex << value; - } else - { oss << value; - } return oss.str(); } -std::string toString( unsigned int value ) -{ +std::string toString( unsigned int value ) { return toString( static_cast( value ) ); } template -std::string fpToString( T value, int precision ) -{ +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] == '.' ) - { + if( i != std::string::npos && i != d.size()-1 ) { + if( d[i] == '.' ) i++; - } - d = d.substr( 0, i + 1 ); + d = d.substr( 0, i+1 ); } return d; } -std::string toString( const double value ) -{ +std::string toString( const double value ) { return fpToString( value, 10 ); } -std::string toString( const float value ) -{ +std::string toString( const float value ) { return fpToString( value, 5 ) + "f"; } -std::string toString( bool value ) -{ +std::string toString( bool value ) { return value ? "true" : "false"; } -std::string toString( char value ) -{ +std::string toString( char value ) { return value < ' ' - ? toString( static_cast( value ) ) - : Detail::makeString( value ); + ? toString( static_cast( value ) ) + : Detail::makeString( value ); } -std::string toString( signed char value ) -{ +std::string toString( signed char value ) { return toString( static_cast( value ) ); } -std::string toString( unsigned char value ) -{ +std::string toString( unsigned char value ) { return toString( static_cast( value ) ); } #ifdef CATCH_CONFIG_CPP11_NULLPTR -std::string toString( std::nullptr_t ) -{ +std::string toString( std::nullptr_t ) { return "nullptr"; } #endif #ifdef __OBJC__ -std::string toString( NSString const* const& nsstring ) -{ - if ( !nsstring ) - { - return "nil"; + std::string toString( NSString const * const& nsstring ) { + if( !nsstring ) + return "nil"; + return "@" + toString([nsstring UTF8String]); } - return "@" + toString([nsstring UTF8String]); -} -std::string toString( NSString* CATCH_ARC_STRONG const& nsstring ) -{ - if ( !nsstring ) - { - return "nil"; + 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] ); } - return "@" + toString([nsstring UTF8String]); -} -std::string toString( NSObject* const& nsObject ) -{ - return toString( [nsObject description] ); -} #endif } // end namespace Catch @@ -8611,163 +7000,113 @@ std::string toString( NSObject* const& nsObject ) // #included from: catch_result_builder.hpp #define TWOBLUECUBES_CATCH_RESULT_BUILDER_HPP_INCLUDED -namespace Catch -{ +namespace Catch { -ResultBuilder::ResultBuilder( char const* macroName, - SourceLineInfo const& lineInfo, - char const* capturedExpression, - ResultDisposition::Flags resultDisposition ) + ResultBuilder::ResultBuilder( char const* macroName, + SourceLineInfo const& lineInfo, + char const* capturedExpression, + ResultDisposition::Flags resultDisposition ) : m_assertionInfo( macroName, lineInfo, capturedExpression, 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::captureExpression() -{ - AssertionResult result = build(); - 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; - } + ResultBuilder& ResultBuilder::setResultType( ResultWas::OfType result ) { + m_data.resultType = result; + return *this; } -} -void ResultBuilder::react() -{ - if ( m_shouldThrow ) - { - throw Catch::TestFailureException(); + ResultBuilder& ResultBuilder::setResultType( bool result ) { + m_data.resultType = result ? ResultWas::Ok : ResultWas::ExpressionFailed; + return *this; } -} - -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; - } + 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; } - 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 + ")"; + 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::captureExpression() { + AssertionResult result = build(); + 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; } } - 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; + void ResultBuilder::react() { + if( m_shouldThrow ) + throw Catch::TestFailureException(); } - else if ( m_exprComponents.op == "matches" ) + + bool ResultBuilder::shouldDebugBreak() const { return m_shouldDebugBreak; } + bool ResultBuilder::allowThrows() const { return getCurrentContext().getConfig()->allowThrows(); } + + AssertionResult ResultBuilder::build() const { - return m_exprComponents.lhs + " " + m_exprComponents.rhs; + 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 ); } - else if ( m_exprComponents.op != "!" ) - { - if ( m_exprComponents.lhs.size() + m_exprComponents.rhs.size() < 40 && + 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; + 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 m_exprComponents.lhs + "\n" + m_exprComponents.op + "\n" + m_exprComponents.rhs; - } + 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}"; } - 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 @@ -8779,110 +7118,87 @@ std::string ResultBuilder::reconstructExpression() const #include -namespace Catch -{ +namespace Catch { -class TagAliasRegistry : public ITagAliasRegistry -{ - public: - virtual ~TagAliasRegistry(); - virtual Option 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(); + class TagAliasRegistry : public ITagAliasRegistry { + public: + virtual ~TagAliasRegistry(); + virtual Option 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 m_registry; -}; + private: + std::map m_registry; + }; } // end namespace Catch #include #include -namespace Catch -{ +namespace Catch { -TagAliasRegistry::~TagAliasRegistry() {} + TagAliasRegistry::~TagAliasRegistry() {} -Option TagAliasRegistry::find( std::string const& alias ) const -{ - std::map::const_iterator it = m_registry.find( alias ); - if ( it != m_registry.end() ) - { - return it->second; + Option TagAliasRegistry::find( std::string const& alias ) const { + std::map::const_iterator it = m_registry.find( alias ); + if( it != m_registry.end() ) + return it->second; + else + return Option(); } - else - { - return Option(); - } -} -std::string TagAliasRegistry::expandAliases( std::string const& unexpandedTestSpec ) const -{ - std::string expandedTestSpec = unexpandedTestSpec; - for ( std::map::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() ); + std::string TagAliasRegistry::expandAliases( std::string const& unexpandedTestSpec ) const { + std::string expandedTestSpec = unexpandedTestSpec; + for( std::map::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() ); } } - return expandedTestSpec; -} -void TagAliasRegistry::add( char const* alias, char const* tag, SourceLineInfo const& lineInfo ) -{ + TagAliasRegistry& TagAliasRegistry::get() { + static TagAliasRegistry instance; + return instance; - 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() ); + + 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 ); + std::cerr << ex.what() << std::endl; + exit(1); + } } -} - -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 ); - std::cerr << ex.what() << std::endl; - exit(1); - } -} } // end namespace Catch @@ -8892,292 +7208,251 @@ RegistrarForTagAliases::RegistrarForTagAliases( char const* alias, char const* t // #included from: catch_reporter_bases.hpp #define TWOBLUECUBES_CATCH_REPORTER_BASES_HPP_INCLUDED -namespace Catch -{ +namespace Catch { -struct StreamingReporterBase : SharedImpl -{ + struct StreamingReporterBase : SharedImpl { - StreamingReporterBase( ReporterConfig const& _config ) + StreamingReporterBase( ReporterConfig const& _config ) : m_config( _config.fullConfig() ), stream( _config.stream() ) - {} + {} - virtual ~StreamingReporterBase(); + virtual ~StreamingReporterBase(); - virtual void noMatchingTestCases( std::string const&) {} + virtual void noMatchingTestCases( std::string const& ) {} - virtual void testRunStarting( TestRunInfo const& _testRunInfo ) - { - currentTestRunInfo = _testRunInfo; - } - virtual void testGroupStarting( GroupInfo const& _groupInfo ) - { - currentGroupInfo = _groupInfo; - } - - virtual void testCaseStarting( TestCaseInfo const& _testInfo ) - { - currentTestCaseInfo = _testInfo; - } - virtual void sectionStarting( SectionInfo const& _sectionInfo ) - { - m_sectionStack.push_back( _sectionInfo ); - } - - virtual void sectionEnded( SectionStats const& /* _sectionStats */ ) - { - m_sectionStack.pop_back(); - } - virtual void testCaseEnded( TestCaseStats const& /* _testCaseStats */ ) - { - currentTestCaseInfo.reset(); - assert( m_sectionStack.empty() ); - } - virtual void testGroupEnded( TestGroupStats const& /* _testGroupStats */ ) - { - currentGroupInfo.reset(); - } - virtual void testRunEnded( TestRunStats const& /* _testRunStats */ ) - { - currentTestCaseInfo.reset(); - currentGroupInfo.reset(); - currentTestRunInfo.reset(); - } - - Ptr m_config; - std::ostream& stream; - - LazyStat currentTestRunInfo; - LazyStat currentGroupInfo; - LazyStat currentTestCaseInfo; - - std::vector m_sectionStack; -}; - -struct CumulativeReporterBase : SharedImpl -{ - template - struct Node : SharedImpl<> - { - explicit Node( T const& _value ) : value( _value ) {} - virtual ~Node() {} - - typedef std::vector> 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; + virtual void testRunStarting( TestRunInfo const& _testRunInfo ) { + currentTestRunInfo = _testRunInfo; } - bool operator == ( Ptr const& other ) const - { - return operator==( *other ); + virtual void testGroupStarting( GroupInfo const& _groupInfo ) { + currentGroupInfo = _groupInfo; } - SectionStats stats; - typedef std::vector> ChildSections; - typedef std::vector 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 const& node ) const - { - return node->stats.sectionInfo.lineInfo == m_other.lineInfo; + virtual void testCaseStarting( TestCaseInfo const& _testInfo ) { + currentTestCaseInfo = _testInfo; } - private: - void operator=( BySectionInfo const&); - SectionInfo const& m_other; + virtual void sectionStarting( SectionInfo const& _sectionInfo ) { + m_sectionStack.push_back( _sectionInfo ); + } + + virtual void sectionEnded( SectionStats const& /* _sectionStats */ ) { + m_sectionStack.pop_back(); + } + virtual void testCaseEnded( TestCaseStats const& /* _testCaseStats */ ) { + currentTestCaseInfo.reset(); + assert( m_sectionStack.empty() ); + } + virtual void testGroupEnded( TestGroupStats const& /* _testGroupStats */ ) { + currentGroupInfo.reset(); + } + virtual void testRunEnded( TestRunStats const& /* _testRunStats */ ) { + currentTestCaseInfo.reset(); + currentGroupInfo.reset(); + currentTestRunInfo.reset(); + } + + Ptr m_config; + std::ostream& stream; + + LazyStat currentTestRunInfo; + LazyStat currentGroupInfo; + LazyStat currentTestCaseInfo; + + std::vector m_sectionStack; }; - typedef Node TestCaseNode; - typedef Node TestGroupNode; - typedef Node TestRunNode; + struct CumulativeReporterBase : SharedImpl { + template + struct Node : SharedImpl<> { + explicit Node( T const& _value ) : value( _value ) {} + virtual ~Node() {} - CumulativeReporterBase( ReporterConfig const& _config ) + typedef std::vector > 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 const& other ) const { + return operator==( *other ); + } + + SectionStats stats; + typedef std::vector > ChildSections; + typedef std::vector 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 const& node ) const { + return node->stats.sectionInfo.lineInfo == m_other.lineInfo; + } + private: + void operator=( BySectionInfo const& ); + SectionInfo const& m_other; + }; + + typedef Node TestCaseNode; + typedef Node TestGroupNode; + typedef Node TestRunNode; + + CumulativeReporterBase( ReporterConfig const& _config ) : m_config( _config.fullConfig() ), stream( _config.stream() ) - {} - ~CumulativeReporterBase(); + {} + ~CumulativeReporterBase(); - virtual void testRunStarting( TestRunInfo const&) {} - virtual void testGroupStarting( GroupInfo const&) {} + virtual void testRunStarting( TestRunInfo const& ) {} + virtual void testGroupStarting( GroupInfo const& ) {} - virtual void testCaseStarting( TestCaseInfo const&) {} + virtual void testCaseStarting( TestCaseInfo const& ) {} - virtual void sectionStarting( SectionInfo const& sectionInfo ) - { - SectionStats incompleteStats( sectionInfo, Counts(), 0, false ); - Ptr node; - if ( m_sectionStack.empty() ) - { - if ( !m_rootSection ) - { - m_rootSection = new SectionNode( incompleteStats ); + virtual void sectionStarting( SectionInfo const& sectionInfo ) { + SectionStats incompleteStats( sectionInfo, Counts(), 0, false ); + Ptr node; + if( m_sectionStack.empty() ) { + if( !m_rootSection ) + m_rootSection = new SectionNode( incompleteStats ); + node = m_rootSection; } - 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; } - 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; - } + + virtual void assertionStarting( AssertionInfo const& ) {} + + virtual bool assertionEnded( AssertionStats const& assertionStats ) { + assert( !m_sectionStack.empty() ); + SectionNode& sectionNode = *m_sectionStack.back(); + sectionNode.assertions.push_back( assertionStats ); + return true; } - m_sectionStack.push_back( node ); - m_deepestSection = node; - } + virtual void sectionEnded( SectionStats const& sectionStats ) { + assert( !m_sectionStack.empty() ); + SectionNode& node = *m_sectionStack.back(); + node.stats = sectionStats; + m_sectionStack.pop_back(); + } + virtual void testCaseEnded( TestCaseStats const& testCaseStats ) { + Ptr node = new TestCaseNode( testCaseStats ); + assert( m_sectionStack.size() == 0 ); + node->children.push_back( m_rootSection ); + m_testCases.push_back( node ); + m_rootSection.reset(); - virtual void assertionStarting( AssertionInfo const&) {} + assert( m_deepestSection ); + m_deepestSection->stdOut = testCaseStats.stdOut; + m_deepestSection->stdErr = testCaseStats.stdErr; + } + virtual void testGroupEnded( TestGroupStats const& testGroupStats ) { + Ptr node = new TestGroupNode( testGroupStats ); + node->children.swap( m_testCases ); + m_testGroups.push_back( node ); + } + virtual void testRunEnded( TestRunStats const& testRunStats ) { + Ptr node = new TestRunNode( testRunStats ); + node->children.swap( m_testGroups ); + m_testRuns.push_back( node ); + testRunEndedCumulative(); + } + virtual void testRunEndedCumulative() = 0; - 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 ) - { - assert( !m_sectionStack.empty() ); - SectionNode& node = *m_sectionStack.back(); - node.stats = sectionStats; - m_sectionStack.pop_back(); - } - virtual void testCaseEnded( TestCaseStats const& testCaseStats ) - { - Ptr node = new TestCaseNode( testCaseStats ); - assert( m_sectionStack.size() == 0 ); - node->children.push_back( m_rootSection ); - m_testCases.push_back( node ); - m_rootSection.reset(); + Ptr m_config; + std::ostream& stream; + std::vector m_assertions; + std::vector > > m_sections; + std::vector > m_testCases; + std::vector > m_testGroups; - assert( m_deepestSection ); - m_deepestSection->stdOut = testCaseStats.stdOut; - m_deepestSection->stdErr = testCaseStats.stdErr; - } - virtual void testGroupEnded( TestGroupStats const& testGroupStats ) - { - Ptr node = new TestGroupNode( testGroupStats ); - node->children.swap( m_testCases ); - m_testGroups.push_back( node ); - } - virtual void testRunEnded( TestRunStats const& testRunStats ) - { - Ptr node = new TestRunNode( testRunStats ); - node->children.swap( m_testGroups ); - m_testRuns.push_back( node ); - testRunEndedCumulative(); - } - virtual void testRunEndedCumulative() = 0; + std::vector > m_testRuns; - Ptr m_config; - std::ostream& stream; - std::vector m_assertions; - std::vector>> m_sections; - std::vector> m_testCases; - std::vector> m_testGroups; + Ptr m_rootSection; + Ptr m_deepestSection; + std::vector > m_sectionStack; - std::vector> m_testRuns; - - Ptr m_rootSection; - Ptr m_deepestSection; - std::vector> m_sectionStack; - -}; + }; } // end namespace Catch // #included from: ../internal/catch_reporter_registrars.hpp #define TWOBLUECUBES_CATCH_REPORTER_REGISTRARS_HPP_INCLUDED -namespace Catch -{ +namespace Catch { -template -class LegacyReporterRegistrar -{ + template + class LegacyReporterRegistrar { - class ReporterFactory : public IReporterFactory - { - virtual IStreamingReporter* create( ReporterConfig const& config ) const - { - return new LegacyReporterAdapter( new T( config ) ); - } + 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(); + virtual std::string getDescription() const { + return T::getDescription(); + } + }; + + public: + + LegacyReporterRegistrar( std::string const& name ) { + getMutableRegistryHub().registerReporter( name, new ReporterFactory() ); } }; - public: + template + class ReporterRegistrar { - LegacyReporterRegistrar( std::string const& name ) - { - getMutableRegistryHub().registerReporter( name, new ReporterFactory() ); - } -}; + class ReporterFactory : public IReporterFactory { -template -class ReporterRegistrar -{ + // *** 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 ); + } - class ReporterFactory : public IReporterFactory - { + virtual std::string getDescription() const { + return T::getDescription(); + } + }; - // *** 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 ); - } + public: - virtual std::string getDescription() const - { - return T::getDescription(); + ReporterRegistrar( std::string const& name ) { + getMutableRegistryHub().registerReporter( name, new ReporterFactory() ); } }; - - public: - - ReporterRegistrar( std::string const& name ) - { - getMutableRegistryHub().registerReporter( name, new ReporterFactory() ); - } -}; } #define INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) \ @@ -9193,412 +7468,348 @@ class ReporterRegistrar #include #include -namespace Catch -{ +namespace Catch { -class XmlWriter -{ - public: + class XmlWriter { + public: - class ScopedElement - { - public: - ScopedElement( XmlWriter* writer ) + class ScopedElement { + public: + ScopedElement( XmlWriter* writer ) : m_writer( writer ) + {} + + ScopedElement( ScopedElement const& other ) + : m_writer( other.m_writer ){ + other.m_writer = 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 + 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( &std::cout ) {} - ScopedElement( ScopedElement const& other ) - : m_writer( other.m_writer ) - { - other.m_writer = NULL; + XmlWriter( std::ostream& os ) + : m_tagIsOpen( false ), + m_needsNewline( false ), + m_os( &os ) + {} + + ~XmlWriter() { + while( !m_tags.empty() ) + endElement(); } - ~ScopedElement() - { - if ( m_writer ) - { - m_writer->endElement(); +//# ifndef CATCH_CPP11_OR_GREATER +// XmlWriter& operator = ( XmlWriter const& other ) { +// XmlWriter temp( other ); +// swap( temp ); +// return *this; +// } +//# else +// XmlWriter( XmlWriter const& ) = default; +// XmlWriter( XmlWriter && ) = default; +// XmlWriter& operator = ( XmlWriter const& ) = default; +// XmlWriter& operator = ( XmlWriter && ) = default; +//# endif +// +// void swap( XmlWriter& other ) { +// std::swap( m_tagIsOpen, other.m_tagIsOpen ); +// std::swap( m_needsNewline, other.m_needsNewline ); +// std::swap( m_tags, other.m_tags ); +// std::swap( m_indent, other.m_indent ); +// std::swap( m_os, other.m_os ); +// } + + 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 << "\n"; + } + m_tags.pop_back(); + return *this; } - ScopedElement& writeText( std::string const& text, bool indent = true ) - { - m_writer->writeText( text, indent ); + XmlWriter& writeAttribute( std::string const& name, std::string const& attribute ) { + if( !name.empty() && !attribute.empty() ) { + stream() << " " << name << "=\""; + writeEncodedText( attribute ); + stream() << "\""; + } + return *this; + } + + XmlWriter& writeAttribute( std::string const& name, bool attribute ) { + stream() << " " << name << "=\"" << ( attribute ? "true" : "false" ) << "\""; return *this; } template - ScopedElement& writeAttribute( std::string const& name, T const& attribute ) - { - m_writer->writeAttribute( name, attribute ); + XmlWriter& writeAttribute( std::string const& name, T const& attribute ) { + if( !name.empty() ) + stream() << " " << name << "=\"" << attribute << "\""; return *this; } - private: - mutable XmlWriter* m_writer; + XmlWriter& writeText( std::string const& text, bool indent = true ) { + if( !text.empty() ){ + bool tagWasOpen = m_tagIsOpen; + ensureTagClosed(); + if( tagWasOpen && indent ) + stream() << m_indent; + writeEncodedText( text ); + m_needsNewline = true; + } + return *this; + } + + XmlWriter& writeComment( std::string const& text ) { + ensureTagClosed(); + stream() << m_indent << ""; + 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; + } + } + + void writeEncodedText( std::string const& text ) { + static const char* charsToEncode = "<&\""; + std::string mtext = text; + std::string::size_type pos = mtext.find_first_of( charsToEncode ); + while( pos != std::string::npos ) { + stream() << mtext.substr( 0, pos ); + + switch( mtext[pos] ) { + case '<': + stream() << "<"; + break; + case '&': + stream() << "&"; + break; + case '\"': + stream() << """; + break; + } + mtext = mtext.substr( pos+1 ); + pos = mtext.find_first_of( charsToEncode ); + } + stream() << mtext; + } + + bool m_tagIsOpen; + bool m_needsNewline; + std::vector m_tags; + std::string m_indent; + std::ostream* m_os; }; - XmlWriter() - : m_tagIsOpen( false ), - m_needsNewline( false ), - m_os( &std::cout ) - {} - - XmlWriter( std::ostream& os ) - : m_tagIsOpen( false ), - m_needsNewline( false ), - m_os( &os ) - {} - - ~XmlWriter() - { - while ( !m_tags.empty() ) - { - endElement(); - } - } - - //# ifndef CATCH_CPP11_OR_GREATER - // XmlWriter& operator = ( XmlWriter const& other ) { - // XmlWriter temp( other ); - // swap( temp ); - // return *this; - // } - //# else - // XmlWriter( XmlWriter const& ) = default; - // XmlWriter( XmlWriter && ) = default; - // XmlWriter& operator = ( XmlWriter const& ) = default; - // XmlWriter& operator = ( XmlWriter && ) = default; - //# endif - // - // void swap( XmlWriter& other ) { - // std::swap( m_tagIsOpen, other.m_tagIsOpen ); - // std::swap( m_needsNewline, other.m_needsNewline ); - // std::swap( m_tags, other.m_tags ); - // std::swap( m_indent, other.m_indent ); - // std::swap( m_os, other.m_os ); - // } - - 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 << "\n"; - } - m_tags.pop_back(); - return *this; - } - - XmlWriter& writeAttribute( std::string const& name, std::string const& attribute ) - { - if ( !name.empty() && !attribute.empty() ) - { - stream() << " " << name << "=\""; - writeEncodedText( attribute ); - stream() << "\""; - } - return *this; - } - - XmlWriter& writeAttribute( std::string const& name, bool attribute ) - { - stream() << " " << name << "=\"" << ( attribute ? "true" : "false" ) << "\""; - return *this; - } - - template - XmlWriter& writeAttribute( std::string const& name, T const& attribute ) - { - if ( !name.empty() ) - { - stream() << " " << name << "=\"" << attribute << "\""; - } - return *this; - } - - XmlWriter& writeText( std::string const& text, bool indent = true ) - { - if ( !text.empty() ) - { - bool tagWasOpen = m_tagIsOpen; - ensureTagClosed(); - if ( tagWasOpen && indent ) - { - stream() << m_indent; - } - writeEncodedText( text ); - m_needsNewline = true; - } - return *this; - } - - XmlWriter& writeComment( std::string const& text ) - { - ensureTagClosed(); - stream() << m_indent << ""; - 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; - } - } - - void writeEncodedText( std::string const& text ) - { - static const char* charsToEncode = "<&\""; - std::string mtext = text; - std::string::size_type pos = mtext.find_first_of( charsToEncode ); - while ( pos != std::string::npos ) - { - stream() << mtext.substr( 0, pos ); - - switch ( mtext[pos] ) - { - case '<': - stream() << "<"; - break; - case '&': - stream() << "&"; - break; - case '\"': - stream() << """; - break; - } - mtext = mtext.substr( pos + 1 ); - pos = mtext.find_first_of( charsToEncode ); - } - stream() << mtext; - } - - bool m_tagIsOpen; - bool m_needsNewline; - std::vector m_tags; - std::string m_indent; - std::ostream* m_os; -}; - } -namespace Catch -{ -class XmlReporter : public SharedImpl -{ - public: - XmlReporter( ReporterConfig const& config ) : m_config( config ), m_sectionDepth( 0 ) {} +namespace Catch { + class XmlReporter : public SharedImpl { + public: + XmlReporter( ReporterConfig const& config ) : m_config( config ), m_sectionDepth( 0 ) {} - static std::string getDescription() - { - return "Reports test results as an XML document"; - } - virtual ~XmlReporter(); - - private: // IReporter - - virtual bool shouldRedirectStdout() const - { - return true; - } - - virtual void StartTesting() - { - m_xml.setStream( m_config.stream() ); - m_xml.startElement( "Catch" ); - if ( !m_config.fullConfig()->name().empty() ) - { - m_xml.writeAttribute( "name", m_config.fullConfig()->name() ); + static std::string getDescription() { + return "Reports test results as an XML document"; } - } + virtual ~XmlReporter(); - virtual void EndTesting( const Totals& totals ) - { - m_xml.scopedElement( "OverallResults" ) - .writeAttribute( "successes", totals.assertions.passed ) - .writeAttribute( "failures", totals.assertions.failed ) - .writeAttribute( "expectedFailures", totals.assertions.failedButOk ); - m_xml.endElement(); - } + private: // IReporter - virtual void StartGroup( const std::string& groupName ) - { - m_xml.startElement( "Group" ) - .writeAttribute( "name", groupName ); - } - - virtual void EndGroup( const std::string&, const Totals& totals ) - { - m_xml.scopedElement( "OverallResults" ) - .writeAttribute( "successes", totals.assertions.passed ) - .writeAttribute( "failures", totals.assertions.failed ) - .writeAttribute( "expectedFailures", totals.assertions.failedButOk ); - m_xml.endElement(); - } - - virtual void StartSection( const std::string& sectionName, const std::string& description ) - { - if ( m_sectionDepth++ > 0 ) - { - m_xml.startElement( "Section" ) - .writeAttribute( "name", trim( sectionName ) ) - .writeAttribute( "description", description ); + virtual bool shouldRedirectStdout() const { + return true; } - } - virtual void NoAssertionsInSection( const std::string&) {} - virtual void NoAssertionsInTestCase( const std::string&) {} - virtual void EndSection( const std::string& /*sectionName*/, const Counts& assertions ) - { - if ( --m_sectionDepth > 0 ) - { + virtual void StartTesting() { + m_xml.setStream( m_config.stream() ); + m_xml.startElement( "Catch" ); + if( !m_config.fullConfig()->name().empty() ) + m_xml.writeAttribute( "name", m_config.fullConfig()->name() ); + } + + virtual void EndTesting( const Totals& totals ) { m_xml.scopedElement( "OverallResults" ) - .writeAttribute( "successes", assertions.passed ) - .writeAttribute( "failures", assertions.failed ) - .writeAttribute( "expectedFailures", assertions.failedButOk ); + .writeAttribute( "successes", totals.assertions.passed ) + .writeAttribute( "failures", totals.assertions.failed ) + .writeAttribute( "expectedFailures", totals.assertions.failedButOk ); m_xml.endElement(); } - } - virtual void StartTestCase( const Catch::TestCaseInfo& testInfo ) - { - m_xml.startElement( "TestCase" ).writeAttribute( "name", trim( testInfo.name ) ); - m_currentTestSuccess = true; - } - - virtual void Result( const Catch::AssertionResult& assertionResult ) - { - if ( !m_config.fullConfig()->includeSuccessfulResults() - && assertionResult.getResultType() == ResultWas::Ok ) - { - return; + virtual void StartGroup( const std::string& groupName ) { + m_xml.startElement( "Group" ) + .writeAttribute( "name", groupName ); } - if ( assertionResult.hasExpression() ) - { - m_xml.startElement( "Expression" ) - .writeAttribute( "success", assertionResult.succeeded() ) - .writeAttribute( "filename", assertionResult.getSourceInfo().file ) - .writeAttribute( "line", assertionResult.getSourceInfo().line ); - - m_xml.scopedElement( "Original" ) - .writeText( assertionResult.getExpression() ); - m_xml.scopedElement( "Expanded" ) - .writeText( assertionResult.getExpandedExpression() ); - m_currentTestSuccess &= assertionResult.succeeded(); - } - - switch ( assertionResult.getResultType() ) - { - case ResultWas::ThrewException: - m_xml.scopedElement( "Exception" ) - .writeAttribute( "filename", assertionResult.getSourceInfo().file ) - .writeAttribute( "line", assertionResult.getSourceInfo().line ) - .writeText( assertionResult.getMessage() ); - m_currentTestSuccess = false; - break; - case ResultWas::Info: - m_xml.scopedElement( "Info" ) - .writeText( assertionResult.getMessage() ); - break; - case ResultWas::Warning: - m_xml.scopedElement( "Warning" ) - .writeText( assertionResult.getMessage() ); - break; - case ResultWas::ExplicitFailure: - m_xml.scopedElement( "Failure" ) - .writeText( assertionResult.getMessage() ); - m_currentTestSuccess = false; - break; - case ResultWas::Unknown: - case ResultWas::Ok: - case ResultWas::FailureBit: - case ResultWas::ExpressionFailed: - case ResultWas::Exception: - case ResultWas::DidntThrowException: - break; - } - if ( assertionResult.hasExpression() ) - { + virtual void EndGroup( const std::string&, const Totals& totals ) { + m_xml.scopedElement( "OverallResults" ) + .writeAttribute( "successes", totals.assertions.passed ) + .writeAttribute( "failures", totals.assertions.failed ) + .writeAttribute( "expectedFailures", totals.assertions.failedButOk ); m_xml.endElement(); } - } - virtual void Aborted() - { - // !TBD - } + virtual void StartSection( const std::string& sectionName, const std::string& description ) { + if( m_sectionDepth++ > 0 ) { + m_xml.startElement( "Section" ) + .writeAttribute( "name", trim( sectionName ) ) + .writeAttribute( "description", description ); + } + } + virtual void NoAssertionsInSection( const std::string& ) {} + virtual void NoAssertionsInTestCase( const std::string& ) {} - virtual void EndTestCase( const Catch::TestCaseInfo&, const Totals&, const std::string&, - const std::string&) - { - m_xml.scopedElement( "OverallResult" ).writeAttribute( "success", m_currentTestSuccess ); - m_xml.endElement(); - } + virtual void EndSection( const std::string& /*sectionName*/, const Counts& assertions ) { + if( --m_sectionDepth > 0 ) { + m_xml.scopedElement( "OverallResults" ) + .writeAttribute( "successes", assertions.passed ) + .writeAttribute( "failures", assertions.failed ) + .writeAttribute( "expectedFailures", assertions.failedButOk ); + m_xml.endElement(); + } + } - private: - ReporterConfig m_config; - bool m_currentTestSuccess; - XmlWriter m_xml; - int m_sectionDepth; -}; + virtual void StartTestCase( const Catch::TestCaseInfo& testInfo ) { + m_xml.startElement( "TestCase" ).writeAttribute( "name", trim( testInfo.name ) ); + m_currentTestSuccess = true; + } + + virtual void Result( const Catch::AssertionResult& assertionResult ) { + if( !m_config.fullConfig()->includeSuccessfulResults() && assertionResult.getResultType() == ResultWas::Ok ) + return; + + if( assertionResult.hasExpression() ) { + m_xml.startElement( "Expression" ) + .writeAttribute( "success", assertionResult.succeeded() ) + .writeAttribute( "filename", assertionResult.getSourceInfo().file ) + .writeAttribute( "line", assertionResult.getSourceInfo().line ); + + m_xml.scopedElement( "Original" ) + .writeText( assertionResult.getExpression() ); + m_xml.scopedElement( "Expanded" ) + .writeText( assertionResult.getExpandedExpression() ); + m_currentTestSuccess &= assertionResult.succeeded(); + } + + switch( assertionResult.getResultType() ) { + case ResultWas::ThrewException: + m_xml.scopedElement( "Exception" ) + .writeAttribute( "filename", assertionResult.getSourceInfo().file ) + .writeAttribute( "line", assertionResult.getSourceInfo().line ) + .writeText( assertionResult.getMessage() ); + m_currentTestSuccess = false; + break; + case ResultWas::Info: + m_xml.scopedElement( "Info" ) + .writeText( assertionResult.getMessage() ); + break; + case ResultWas::Warning: + m_xml.scopedElement( "Warning" ) + .writeText( assertionResult.getMessage() ); + break; + case ResultWas::ExplicitFailure: + m_xml.scopedElement( "Failure" ) + .writeText( assertionResult.getMessage() ); + m_currentTestSuccess = false; + break; + case ResultWas::Unknown: + case ResultWas::Ok: + case ResultWas::FailureBit: + case ResultWas::ExpressionFailed: + case ResultWas::Exception: + case ResultWas::DidntThrowException: + break; + } + if( assertionResult.hasExpression() ) + m_xml.endElement(); + } + + virtual void Aborted() { + // !TBD + } + + virtual void EndTestCase( const Catch::TestCaseInfo&, const Totals&, const std::string&, const std::string& ) { + m_xml.scopedElement( "OverallResult" ).writeAttribute( "success", m_currentTestSuccess ); + m_xml.endElement(); + } + + private: + ReporterConfig m_config; + bool m_currentTestSuccess; + XmlWriter m_xml; + int m_sectionDepth; + }; } // end namespace Catch @@ -9607,257 +7818,210 @@ class XmlReporter : public SharedImpl #include -namespace Catch -{ +namespace Catch { -class JunitReporter : public CumulativeReporterBase -{ - public: - JunitReporter( ReporterConfig const& _config ) + class JunitReporter : public CumulativeReporterBase { + public: + JunitReporter( ReporterConfig const& _config ) : CumulativeReporterBase( _config ), xml( _config.stream() ) - {} + {} - ~JunitReporter(); + ~JunitReporter(); - 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*/ ) {} - - virtual ReporterPreferences getPreferences() const - { - ReporterPreferences prefs; - prefs.shouldRedirectStdOut = true; - return prefs; - } - - virtual void testRunStarting( TestRunInfo const& runInfo ) - { - CumulativeReporterBase::testRunStarting( runInfo ); - xml.startElement( "testsuites" ); - } - - virtual void testGroupStarting( GroupInfo const& groupInfo ) - { - suiteTimer.start(); - stdOutForSuite.str(""); - stdErrForSuite.str(""); - unexpectedExceptions = 0; - CumulativeReporterBase::testGroupStarting( groupInfo ); - } - - virtual bool assertionEnded( AssertionStats const& assertionStats ) - { - if ( assertionStats.assertionResult.getResultType() == ResultWas::ThrewException ) - { - unexpectedExceptions++; - } - return CumulativeReporterBase::assertionEnded( assertionStats ); - } - - virtual void testCaseEnded( TestCaseStats const& testCaseStats ) - { - stdOutForSuite << testCaseStats.stdOut; - stdErrForSuite << testCaseStats.stdErr; - CumulativeReporterBase::testCaseEnded( testCaseStats ); - } - - virtual void testGroupEnded( TestGroupStats const& testGroupStats ) - { - double suiteTime = suiteTimer.getElapsedSeconds(); - CumulativeReporterBase::testGroupEnded( testGroupStats ); - writeGroup( *m_testGroups.back(), suiteTime ); - } - - virtual void testRunEndedCumulative() - { - 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 ); + static std::string getDescription() { + return "Reports test results in an XML format that looks like Ant's junitreport target"; } - xml.scopedElement( "system-out" ).writeText( trim( stdOutForSuite.str() ), false ); - xml.scopedElement( "system-err" ).writeText( trim( stdErrForSuite.str() ), false ); - } + virtual void noMatchingTestCases( std::string const& /*spec*/ ) {} - 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; + virtual ReporterPreferences getPreferences() const { + ReporterPreferences prefs; + prefs.shouldRedirectStdOut = true; + return prefs; } - 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" ); - } + virtual void testRunStarting( TestRunInfo const& runInfo ) { + CumulativeReporterBase::testRunStarting( runInfo ); + xml.startElement( "testsuites" ); + } + + virtual void testGroupStarting( GroupInfo const& groupInfo ) { + suiteTimer.start(); + stdOutForSuite.str(""); + stdErrForSuite.str(""); + unexpectedExceptions = 0; + CumulativeReporterBase::testGroupStarting( groupInfo ); + } + + virtual bool assertionEnded( AssertionStats const& assertionStats ) { + if( assertionStats.assertionResult.getResultType() == ResultWas::ThrewException ) + unexpectedExceptions++; + return CumulativeReporterBase::assertionEnded( assertionStats ); + } + + virtual void testCaseEnded( TestCaseStats const& testCaseStats ) { + stdOutForSuite << testCaseStats.stdOut; + stdErrForSuite << testCaseStats.stdErr; + CumulativeReporterBase::testCaseEnded( testCaseStats ); + } + + virtual void testGroupEnded( TestGroupStats const& testGroupStats ) { + double suiteTime = suiteTimer.getElapsedSeconds(); + CumulativeReporterBase::testGroupEnded( testGroupStats ); + writeGroup( *m_testGroups.back(), suiteTime ); + } + + virtual void testRunEndedCumulative() { + 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( "classname", className ); - xml.writeAttribute( "name", name ); - } - xml.writeAttribute( "time", toString( sectionNode.stats.durationInSeconds ) ); + xml.writeAttribute( "time", suiteTime ); + xml.writeAttribute( "timestamp", "tbd" ); // !TBD - 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: - 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::const_iterator - it = stats.infoMessages.begin(), - itEnd = stats.infoMessages.end(); + // Write test cases + for( TestGroupNode::ChildNodes::const_iterator + it = groupNode.children.begin(), itEnd = groupNode.children.end(); it != itEnd; ++it ) - if ( it->type == ResultWas::Info ) - { - oss << it->message << "\n"; + 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", 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: + 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; } - oss << "at " << result.getSourceInfo(); - xml.writeText( oss.str(), false ); + 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::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; -}; + XmlWriter xml; + Timer suiteTimer; + std::ostringstream stdOutForSuite; + std::ostringstream stdErrForSuite; + unsigned int unexpectedExceptions; + }; -INTERNAL_CATCH_REGISTER_REPORTER( "junit", JunitReporter ) + INTERNAL_CATCH_REGISTER_REPORTER( "junit", JunitReporter ) } // end namespace Catch @@ -9866,132 +8030,103 @@ INTERNAL_CATCH_REGISTER_REPORTER( "junit", JunitReporter ) #include -namespace Catch -{ +namespace Catch { -struct ConsoleReporter : StreamingReporterBase -{ - ConsoleReporter( ReporterConfig const& _config ) + struct ConsoleReporter : StreamingReporterBase { + ConsoleReporter( ReporterConfig const& _config ) : StreamingReporterBase( _config ), m_headerPrinted( false ) - {} + {} - virtual ~ConsoleReporter(); - static std::string getDescription() - { - return "Reports test results as plain lines of text"; - } - 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; + virtual ~ConsoleReporter(); + static std::string getDescription() { + return "Reports test results as plain lines of text"; + } + virtual ReporterPreferences getPreferences() const { + ReporterPreferences prefs; + prefs.shouldRedirectStdOut = false; + return prefs; } - lazyPrint(); + virtual void noMatchingTestCases( std::string const& spec ) { + stream << "No test cases matched '" << spec << "'" << std::endl; + } - AssertionPrinter printer( stream, _assertionStats, printInfoMessages ); - printer.print(); - stream << std::endl; - return true; - } + 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; + } - virtual void sectionStarting( SectionInfo const& _sectionInfo ) - { - m_headerPrinted = false; - StreamingReporterBase::sectionStarting( _sectionInfo ); - } - virtual void sectionEnded( SectionStats const& _sectionStats ) - { - 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; + + AssertionPrinter printer( stream, _assertionStats, printInfoMessages ); + printer.print(); + stream << std::endl; + return true; } - if ( m_headerPrinted ) - { - if ( m_config->showDurations() == ShowDurations::Always ) - { - stream << "Completed in " << _sectionStats.durationInSeconds << "s" << std::endl; + + virtual void sectionStarting( SectionInfo const& _sectionInfo ) { + m_headerPrinted = false; + StreamingReporterBase::sectionStarting( _sectionInfo ); + } + virtual void sectionEnded( SectionStats const& _sectionStats ) { + 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 ) { + StreamingReporterBase::testCaseEnded( _testCaseStats ); m_headerPrinted = false; } - else - { - if ( m_config->showDurations() == ShowDurations::Always ) - { - stream << _sectionStats.sectionInfo.name << " completed in " << _sectionStats.durationInSeconds << - "s" << std::endl; + virtual void testGroupEnded( TestGroupStats const& _testGroupStats ) { + if( currentGroupInfo.used ) { + printSummaryDivider(); + stream << "Summary for group '" << _testGroupStats.groupInfo.name << "':\n"; + printTotals( _testGroupStats.totals ); + stream << "\n" << std::endl; } + StreamingReporterBase::testGroupEnded( _testGroupStats ); } - StreamingReporterBase::sectionEnded( _sectionStats ); - } - - virtual void testCaseEnded( TestCaseStats const& _testCaseStats ) - { - StreamingReporterBase::testCaseEnded( _testCaseStats ); - m_headerPrinted = false; - } - virtual void testGroupEnded( TestGroupStats const& _testGroupStats ) - { - if ( currentGroupInfo.used ) - { - printSummaryDivider(); - stream << "Summary for group '" << _testGroupStats.groupInfo.name << "':\n"; - printTotals( _testGroupStats.totals ); - stream << "\n" << std::endl; + virtual void testRunEnded( TestRunStats const& _testRunStats ) { + printTotalsDivider( _testRunStats.totals ); + printTotals( _testRunStats.totals ); + stream << std::endl; + StreamingReporterBase::testRunEnded( _testRunStats ); } - StreamingReporterBase::testGroupEnded( _testGroupStats ); - } - virtual void testRunEnded( TestRunStats const& _testRunStats ) - { - printTotalsDivider( _testRunStats.totals ); - printTotals( _testRunStats.totals ); - stream << std::endl; - StreamingReporterBase::testRunEnded( _testRunStats ); - } - private: + private: - class AssertionPrinter - { - void operator= ( AssertionPrinter const&); - public: - AssertionPrinter( std::ostream& _stream, AssertionStats const& _stats, bool _printInfoMessages ) + class AssertionPrinter { + void operator= ( AssertionPrinter const& ); + public: + AssertionPrinter( std::ostream& _stream, AssertionStats const& _stats, bool _printInfoMessages ) : stream( _stream ), stats( _stats ), result( _stats.assertionResult ), @@ -9999,837 +8134,676 @@ struct ConsoleReporter : StreamingReporterBase 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() ) - { + switch( result.getResultType() ) { + case ResultWas::Ok: colour = Colour::Success; - passOrFail = "FAILED - but was ok"; - } - else - { + 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"; - } - 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::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; + messageLabel = "due to unexpected exception with message"; + 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() ) - { + void print() const { + printSourceInfo(); + if( stats.totals.assertions.total() > 0 ) { + if( result.isOk() ) + stream << "\n"; + printResultType(); + printOriginalExpression(); + printReconstructedExpression(); + } + else { stream << "\n"; } - printResultType(); - printOriginalExpression(); - printReconstructedExpression(); + printMessage(); } - 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::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"; + 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::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 messages; + bool printInfoMessages; + }; + + void lazyPrint() { + + if( !currentTestRunInfo.used ) + lazyPrintRunInfo(); + if( !currentGroupInfo.used ) + lazyPrintGroupInfo(); + + if( !m_headerPrinted ) { + printTestCaseAndSectionHeader(); + m_headerPrinted = true; + } } - void printSourceInfo() const - { - Colour colourGuard( Colour::FileName ); - stream << result.getSourceInfo() << ": "; + void lazyPrintRunInfo() { + stream << "\n" << getLineOfChars<'~'>() << "\n"; + Colour colour( Colour::SecondaryText ); + stream << currentTestRunInfo->name + << " is a Catch v" << libraryVersion.majorVersion << "." + << libraryVersion.minorVersion << " b" + << libraryVersion.buildNumber; + if( libraryVersion.branchName != std::string( "master" ) ) + stream << " (" << libraryVersion.branchName << ")"; + stream << " host application.\n" + << "Run with -? for options\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::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; } - std::ostream& stream; - AssertionStats const& stats; - AssertionResult const& result; - Colour::Code colour; - std::string passOrFail; - std::string messageLabel; - std::string message; - std::vector messages; - bool printInfoMessages; - }; - - void lazyPrint() - { - - if ( !currentTestRunInfo.used ) - { - lazyPrintRunInfo(); + void printClosedHeader( std::string const& _name ) { + printOpenHeader( _name ); + stream << getLineOfChars<'.'>() << "\n"; } - 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.majorVersion << "." - << libraryVersion.minorVersion << " b" - << libraryVersion.buildNumber; - if ( libraryVersion.branchName != std::string( "master" ) ) - { - stream << " (" << libraryVersion.branchName << ")"; - } - stream << " host application.\n" - << "Run with -? for options\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::const_iterator - it = m_sectionStack.begin() + 1, // Skip first section (test case) - itEnd = m_sectionStack.end(); - for ( ; it != itEnd; ++it ) + void printOpenHeader( std::string const& _name ) { + stream << getLineOfChars<'-'>() << "\n"; { - printHeaderString( it->name, 2 ); + Colour colourGuard( Colour::Headers ); + printHeaderString( _name ); } } - SourceLineInfo lineInfo = m_sectionStack.front().lineInfo; - - if ( !lineInfo.empty() ) - { - stream << getLineOfChars<'-'>() << "\n"; - Colour colourGuard( Colour::FileName ); - stream << lineInfo << "\n"; + // 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"; } - 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 ); - } - } + struct SummaryColumn { - // 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 ) + 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::iterator it = rows.begin(); it != rows.end(); ++it ) - { - while ( it->size() < row.size() ) - { - *it = " " + *it; + {} + SummaryColumn addRow( std::size_t count ) { + std::ostringstream oss; + oss << count; + std::string row = oss.str(); + for( std::vector::iterator it = rows.begin(); it != rows.end(); ++it ) { + while( it->size() < row.size() ) + *it = " " + *it; + while( it->size() > row.size() ) + row = " " + row; } - while ( it->size() > row.size() ) - { - row = " " + row; + rows.push_back( row ); + return *this; + } + + std::string label; + Colour::Code colour; + std::vector 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 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 const& cols, std::size_t row ) { + for( std::vector::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; } } - rows.push_back( row ); - return *this; + stream << "\n"; } - std::string label; - Colour::Code colour; - std::vector rows; + 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"; + } + template + static 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; + } + + private: + bool m_headerPrinted; }; - 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 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 const& cols, - std::size_t row ) - { - for ( std::vector::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"; - } - template - static 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; - } - - private: - bool m_headerPrinted; -}; - -INTERNAL_CATCH_REGISTER_REPORTER( "console", ConsoleReporter ) + 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 -{ +namespace Catch { -struct CompactReporter : StreamingReporterBase -{ + struct CompactReporter : StreamingReporterBase { - CompactReporter( ReporterConfig const& _config ) + CompactReporter( ReporterConfig const& _config ) : StreamingReporterBase( _config ) - {} + {} - virtual ~CompactReporter(); + 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; + static std::string getDescription() { + return "Reports test results on a single line, suitable for IDEs"; } - AssertionPrinter printer( stream, _assertionStats, printInfoMessages ); - printer.print(); + virtual ReporterPreferences getPreferences() const { + ReporterPreferences prefs; + prefs.shouldRedirectStdOut = false; + return prefs; + } - stream << std::endl; - return true; - } + virtual void noMatchingTestCases( std::string const& spec ) { + stream << "No test cases matched '" << spec << "'" << std::endl; + } - virtual void testRunEnded( TestRunStats const& _testRunStats ) - { - printTotals( _testRunStats.totals ); - stream << "\n" << std::endl; - StreamingReporterBase::testRunEnded( _testRunStats ); - } + virtual void assertionStarting( AssertionInfo const& ) { + } - private: - class AssertionPrinter - { - void operator= ( AssertionPrinter const&); - public: - AssertionPrinter( std::ostream& _stream, AssertionStats const& _stats, bool _printInfoMessages ) + 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(); + void print() { + printSourceInfo(); - itMessage = messages.begin(); + itMessage = messages.begin(); - switch ( result.getResultType() ) - { - case ResultWas::Ok: - printResultType( Colour::ResultSuccess, passedString() ); - printOriginalExpression(); - printReconstructedExpression(); - if ( ! result.hasExpression() ) - { - printRemainingMessages( Colour::None ); - } - else - { + 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::ExpressionFailed: - if ( result.isOk() ) - { - printResultType( Colour::ResultSuccess, failedString() + std::string( " - but was ok" ) ); - } - else - { + break; + case ResultWas::ThrewException: 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::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; + printIssue( "unexpected exception 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 + private: + // Colour::LightGrey - static Colour::Code dimColour() - { - return Colour::FileName; - } + static Colour::Code dimColour() { return Colour::FileName; } #ifdef CATCH_PLATFORM_MAC - static const char* failedString() - { - return "FAILED"; - } - static const char* passedString() - { - return "PASSED"; - } + 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"; - } + static const char* failedString() { return "failed"; } + static const char* passedString() { return "passed"; } #endif - void printSourceInfo() const - { - Colour colourGuard( Colour::FileName ); - stream << result.getSourceInfo() << ":"; - } + 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::const_iterator itEnd = messages.end(); + const std::size_t N = static_cast( std::distance( itMessage, itEnd ) ); - void printResultType( Colour::Code colour, std::string passOrFail ) const - { - if ( !passOrFail.empty() ) - { { Colour colourGuard( colour ); - stream << " " << passOrFail; + stream << " with " << pluralise( N, "message" ) << ":"; } - 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::const_iterator itEnd = messages.end(); - const std::size_t N = static_cast( 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"; + 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 messages; + std::vector::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 " ; } - private: - std::ostream& stream; - AssertionStats const& stats; - AssertionResult const& result; - std::vector messages; - std::vector::const_iterator itMessage; - bool printInfoMessages; + 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" ) << "."; + } + } }; - // 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 ) + INTERNAL_CATCH_REGISTER_REPORTER( "compact", CompactReporter ) } // end namespace Catch -namespace Catch -{ -NonCopyable::~NonCopyable() {} -IShared::~IShared() {} -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() {} +namespace Catch { + NonCopyable::~NonCopyable() {} + IShared::~IShared() {} + 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() {} -TestSpec::Pattern::~Pattern() {} -TestSpec::NamePattern::~NamePattern() {} -TestSpec::TagPattern::~TagPattern() {} -TestSpec::ExcludedPattern::~ExcludedPattern() {} + StreamingReporterBase::~StreamingReporterBase() {} + ConsoleReporter::~ConsoleReporter() {} + CompactReporter::~CompactReporter() {} + IRunner::~IRunner() {} + IMutableContext::~IMutableContext() {} + IConfig::~IConfig() {} + XmlReporter::~XmlReporter() {} + JunitReporter::~JunitReporter() {} + TestRegistry::~TestRegistry() {} + FreeFunctionTestCase::~FreeFunctionTestCase() {} + IGeneratorInfo::~IGeneratorInfo() {} + IGeneratorsForTest::~IGeneratorsForTest() {} + 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() {} + Matchers::Impl::StdString::Equals::~Equals() {} + Matchers::Impl::StdString::Contains::~Contains() {} + Matchers::Impl::StdString::StartsWith::~StartsWith() {} + Matchers::Impl::StdString::EndsWith::~EndsWith() {} -void Config::dummy() {} + void Config::dummy() {} -INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( "xml", XmlReporter ) + INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( "xml", XmlReporter ) } #ifdef __clang__ - #pragma clang diagnostic pop +#pragma clang diagnostic pop #endif #endif @@ -10841,18 +8815,16 @@ INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( "xml", XmlReporter ) #ifndef __OBJC__ // Standard C/C++ main entry point -int main (int argc, char* const argv[]) -{ +int main (int argc, char * const argv[]) { return Catch::Session().run( argc, argv ); } #else // __OBJC__ // Objective-C entry point -int main (int argc, char* const argv[]) -{ +int main (int argc, char * const argv[]) { #if !CATCH_ARC_ENABLED - NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; #endif Catch::registerTestMethods(); @@ -10870,7 +8842,7 @@ int main (int argc, char* const argv[]) #endif #ifdef CLARA_CONFIG_MAIN_NOT_DEFINED - #undef CLARA_CONFIG_MAIN +# undef CLARA_CONFIG_MAIN #endif ////// @@ -10878,118 +8850,118 @@ int main (int argc, char* const argv[]) // 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( 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_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_NOTHROW" ) +#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_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( 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_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_NOTHROW" ) +#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_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 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" ) +#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_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_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( "", "" ) +#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_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_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_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 ) +#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( "Given: " desc, "" ) - #define CATCH_WHEN( desc ) CATCH_SECTION( " When: " desc, "" ) - #define CATCH_AND_WHEN( desc ) CATCH_SECTION( " And: " desc, "" ) - #define CATCH_THEN( desc ) CATCH_SECTION( " Then: " desc, "" ) - #define CATCH_AND_THEN( desc ) CATCH_SECTION( " And: " desc, "" ) +// "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( "Given: " desc, "" ) +#define CATCH_WHEN( desc ) CATCH_SECTION( " When: " desc, "" ) +#define CATCH_AND_WHEN( desc ) CATCH_SECTION( " And: " desc, "" ) +#define CATCH_THEN( desc ) CATCH_SECTION( " Then: " desc, "" ) +#define CATCH_AND_THEN( desc ) CATCH_SECTION( " And: " desc, "" ) - // If CATCH_CONFIG_PREFIX_ALL is not defined then the CATCH_ prefix is not required +// 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( 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_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::Normal, "REQUIRE_NOTHROW" ) +#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_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( 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_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECK_NOTHROW" ) +#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_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 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" ) +#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 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 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( "", "" ) +#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 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 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 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 ) +#define GENERATE( expr) INTERNAL_CATCH_GENERATE( expr ) #endif @@ -10997,11 +8969,11 @@ int main (int argc, char* const argv[]) // "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__ ) +#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 ) +#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( " Given: " desc, "" ) #define WHEN( desc ) SECTION( " When: " desc, "" ) @@ -11016,9 +8988,9 @@ using Catch::Detail::Approx; #define TWOBLUECUBES_CATCH_REENABLE_WARNINGS_H_INCLUDED #ifdef __clang__ - #pragma clang diagnostic pop +#pragma clang diagnostic pop #elif defined __GNUC__ - #pragma GCC diagnostic pop +#pragma GCC diagnostic pop #endif #endif // TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED diff --git a/test/unit.cpp b/test/unit.cpp index 8cbd6ea9..79536c9b 100644 --- a/test/unit.cpp +++ b/test/unit.cpp @@ -9,6 +9,11 @@ using nlohmann::json; +TEST_CASE() +{ + CHECK(json::parser("[1,2,3,4,5,6]").parse().dump() == "[1,2,3,4,5,6]"); +} + TEST_CASE() { CHECK(json::escape_string("\\") == "\\\\"); @@ -18,12 +23,18 @@ TEST_CASE() CHECK(json::escape_string("\f") == "\\f"); CHECK(json::escape_string("\b") == "\\b"); CHECK(json::escape_string("\t") == "\\t"); - + + CHECK(json::escape_string("Lorem ipsum \"dolor\" sit amet,\nconsectetur \\ adipiscing elit.") + == "Lorem ipsum \\\"dolor\\\" sit amet,\\nconsectetur \\\\ adipiscing elit."); + CHECK(json::escape_string("the main said, \"cool!\"") == "the main said, \\\"cool!\\\""); + CHECK(json::escape_string("\a") == "\\u0007"); + CHECK(json::escape_string("\v") == "\\u000b"); + { json j = "AC/DC"; CHECK(j.dump() == "\"AC/DC\""); } - + { json j = {1, 2, 3, 4}; std::cerr << j << std::endl;