From e8d9963abe34a5bd2ef0431f26a88cb0a6ddfac5 Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Wed, 13 Dec 2017 22:15:53 +0100 Subject: [PATCH 1/6] :ok_hand: cosmetic changes and overworked spelling - All hex literals use upper case letters after the x. - Fixed sime typos. - Documented some more functions. --- src/json.hpp | 1422 +++++++++++++++++++++++++------------------------- 1 file changed, 703 insertions(+), 719 deletions(-) diff --git a/src/json.hpp b/src/json.hpp index b0c85dc1e..1f06b6dd5 100644 --- a/src/json.hpp +++ b/src/json.hpp @@ -109,7 +109,7 @@ SOFTWARE. #define JSON_UNLIKELY(x) x #endif -// cpp language standard detection +// C++ language standard detection #if (defined(__cplusplus) && __cplusplus >= 201703L) || (defined(_HAS_CXX17) && _HAS_CXX17 == 1) // fix for issue #464 #define JSON_HAS_CPP_17 #define JSON_HAS_CPP_14 @@ -128,20 +128,18 @@ template struct adl_serializer; // forward declaration of basic_json (required to split the class) -template class ObjectType = - std::map, - template class ArrayType = std::vector, +template class ObjectType = std::map, + template class ArrayType = std::vector, class StringType = std::string, class BooleanType = bool, class NumberIntegerType = std::int64_t, class NumberUnsignedType = std::uint64_t, class NumberFloatType = double, - template class AllocatorType = std::allocator, - template class JSONSerializer = - adl_serializer> + template class AllocatorType = std::allocator, + template class JSONSerializer = adl_serializer> class basic_json; -// Ugly macros to avoid uglier copy-paste when specializing basic_json -// This is only temporary and will be removed in 3.0 +// Ugly macros to avoid uglier copy-paste when specializing basic_json. They +// may be removed in the future once the class is split. #define NLOHMANN_BASIC_JSON_TPL_DECLARATION \ template class ObjectType, \ @@ -248,7 +246,7 @@ json.exception.parse_error.107 | parse error: JSON pointer must be empty or begi json.exception.parse_error.108 | parse error: escape character '~' must be followed with '0' or '1' | In a JSON Pointer, only `~0` and `~1` are valid escape sequences. json.exception.parse_error.109 | parse error: array index 'one' is not a number | A JSON Pointer array index must be a number. json.exception.parse_error.110 | parse error at 1: cannot read 2 bytes from vector | When parsing CBOR or MessagePack, the byte vector ends before the complete value has been read. -json.exception.parse_error.112 | parse error at 1: error reading CBOR; last byte: 0xf8 | Not all types of CBOR or MessagePack are supported. This exception occurs if an unsupported byte was read. +json.exception.parse_error.112 | parse error at 1: error reading CBOR; last byte: 0xF8 | Not all types of CBOR or MessagePack are supported. This exception occurs if an unsupported byte was read. json.exception.parse_error.113 | parse error at 2: expected a CBOR string; last byte: 0x98 | While parsing a map key, a value that is not a string has been read. @note For an input with n bytes, 1 is the index of the first character and n+1 @@ -541,20 +539,14 @@ Returns an ordering that is similar to Python: inline bool operator<(const value_t lhs, const value_t rhs) noexcept { static constexpr std::array order = {{ - 0, // null - 3, // object - 4, // array - 5, // string - 1, // boolean - 2, // integer - 2, // unsigned - 2, // float + 0 /* null */, 3 /* object */, 4 /* array */, 5 /* string */, + 1 /* boolean */, 2 /* integer */, 2 /* unsigned */, 2 /* float */ } }; const auto l_index = static_cast(lhs); const auto r_index = static_cast(rhs); - return (l_index < order.size() and r_index < order.size() and order[l_index] < order[r_index]); + return l_index < order.size() and r_index < order.size() and order[l_index] < order[r_index]; } @@ -592,17 +584,15 @@ struct merge_and_renumber; template struct merge_and_renumber, index_sequence> - : index_sequence < I1..., (sizeof...(I1) + I2)... > - {}; + : index_sequence < I1..., (sizeof...(I1) + I2)... > {}; template struct make_index_sequence : merge_and_renumber < typename make_index_sequence < N / 2 >::type, - typename make_index_sequence < N - N / 2 >::type > -{}; + typename make_index_sequence < N - N / 2 >::type > {}; -template<> struct make_index_sequence<0> : index_sequence<> { }; -template<> struct make_index_sequence<1> : index_sequence<0> { }; +template<> struct make_index_sequence<0> : index_sequence<> {}; +template<> struct make_index_sequence<1> : index_sequence<0> {}; template using index_sequence_for = make_index_sequence; @@ -625,7 +615,7 @@ template struct conjunction : B1 {}; template struct conjunction : std::conditional, B1>::type {}; -template struct negation : std::integral_constant < bool, !B::value > {}; +template struct negation : std::integral_constant {}; // dispatch utility (taken from ranges-v3) template struct priority_tag : priority_tag < N - 1 > {}; @@ -726,8 +716,7 @@ struct external_constructor } template::value, + enable_if_t::value, int> = 0> static void construct(BasicJsonType& j, const CompatibleArrayType& arr) { @@ -783,8 +772,7 @@ struct external_constructor } template::value, int> = 0> + enable_if_t::value, int> = 0> static void construct(BasicJsonType& j, const CompatibleObjectType& obj) { using std::begin; @@ -897,7 +885,7 @@ struct is_compatible_integer_type is_compatible_integer_type_impl < std::is_integral::value and not std::is_same::value, - RealIntegerType, CompatibleNumberIntegerType > ::value; + RealIntegerType, CompatibleNumberIntegerType >::value; }; @@ -923,10 +911,8 @@ template struct has_non_default_from_json { private: - template < - typename U, - typename = enable_if_t::from_json(std::declval()))>::value >> + template::from_json(std::declval()))>::value>> static int detect(U&&); static void detect(...); @@ -955,22 +941,21 @@ struct has_to_json // to_json // ///////////// -template::value, int> = 0> +template::value, int> = 0> void to_json(BasicJsonType& j, T b) noexcept { external_constructor::construct(j, b); } template::value, int> = 0> + enable_if_t::value, int> = 0> void to_json(BasicJsonType& j, const CompatibleString& s) { external_constructor::construct(j, s); } -template +template void to_json(BasicJsonType& j, typename BasicJsonType::string_t&& s) { external_constructor::construct(j, std::move(s)); @@ -983,19 +968,15 @@ void to_json(BasicJsonType& j, FloatType val) noexcept external_constructor::construct(j, static_cast(val)); } -template < - typename BasicJsonType, typename CompatibleNumberUnsignedType, - enable_if_t::value, int> = 0 > +template::value, int> = 0> void to_json(BasicJsonType& j, CompatibleNumberUnsignedType val) noexcept { external_constructor::construct(j, static_cast(val)); } -template < - typename BasicJsonType, typename CompatibleNumberIntegerType, - enable_if_t::value, int> = 0 > +template::value, int> = 0> void to_json(BasicJsonType& j, CompatibleNumberIntegerType val) noexcept { external_constructor::construct(j, static_cast(val)); @@ -1015,49 +996,44 @@ void to_json(BasicJsonType& j, const std::vector& e) external_constructor::construct(j, e); } -template < - typename BasicJsonType, typename CompatibleArrayType, - enable_if_t < - is_compatible_array_type::value or - std::is_same::value, - int > = 0 > +template::value or + std::is_same::value, + int> = 0> void to_json(BasicJsonType& j, const CompatibleArrayType& arr) { external_constructor::construct(j, arr); } -template ::value, int> = 0> +template::value, int> = 0> void to_json(BasicJsonType& j, std::valarray arr) { external_constructor::construct(j, std::move(arr)); } -template +template void to_json(BasicJsonType& j, typename BasicJsonType::array_t&& arr) { external_constructor::construct(j, std::move(arr)); } -template < - typename BasicJsonType, typename CompatibleObjectType, - enable_if_t::value, - int> = 0 > +template::value, int> = 0> void to_json(BasicJsonType& j, const CompatibleObjectType& obj) { external_constructor::construct(j, obj); } -template +template void to_json(BasicJsonType& j, typename BasicJsonType::object_t&& obj) { external_constructor::construct(j, std::move(obj)); } template::value, - int> = 0> + enable_if_t::value, int> = 0> void to_json(BasicJsonType& j, T (&arr)[N]) { external_constructor::construct(j, arr); @@ -1088,8 +1064,7 @@ void to_json(BasicJsonType& j, const std::tuple& t) // overloads for basic_json template parameters template::value and - not std::is_same::value, + not std::is_same::value, int> = 0> void get_arithmetic_value(const BasicJsonType& j, ArithmeticType& val) { @@ -1354,10 +1329,10 @@ struct to_json_fn "could not find to_json() method in T's namespace"); #ifdef _MSC_VER - // Visual Studio does not show a stacktrace for the above assert. + // MSVC does not show a stacktrace for the above assert using decayed = uncvref_t; static_assert(sizeof(typename decayed::force_msvc_stacktrace) == 0, - "forcing msvc stacktrace to show which T we're talking about."); + "forcing MSVC stacktrace to show which T we're talking about."); #endif } @@ -1387,10 +1362,10 @@ struct from_json_fn static_assert(sizeof(BasicJsonType) == 0, "could not find from_json() method in T's namespace"); #ifdef _MSC_VER - // Visual Studio does not show a stacktrace for the above assert. + // MSVC does not show a stacktrace for the above assert using decayed = uncvref_t; static_assert(sizeof(typename decayed::force_msvc_stacktrace) == 0, - "forcing msvc stacktrace to show which T we're talking about."); + "forcing MSVC stacktrace to show which T we're talking about."); #endif } @@ -1462,7 +1437,7 @@ class input_stream_adapter : public input_adapter_protocol explicit input_stream_adapter(std::istream& i) : is(i), sb(*i.rdbuf()) { - // ignore Byte Order Mark at start of input + // skip byte order mark std::char_traits::int_type c; if ((c = get_character()) == 0xEF) { @@ -1486,7 +1461,7 @@ class input_stream_adapter : public input_adapter_protocol } else if (c != std::char_traits::eof()) { - is.unget(); // Not BOM. Process as usual. + is.unget(); // no byte order mark; process as usual } } @@ -1495,8 +1470,8 @@ class input_stream_adapter : public input_adapter_protocol input_stream_adapter& operator=(input_stream_adapter&) = delete; // std::istream/std::streambuf use std::char_traits::to_int_type, to - // ensure that std::char_traits::eof() and the character 0xff do not - // end up as the same value, eg. 0xffffffff. + // ensure that std::char_traits::eof() and the character 0xFF do not + // end up as the same value, eg. 0xFFFFFFFF. std::char_traits::int_type get_character() override { return sb.sbumpc(); @@ -1575,8 +1550,7 @@ class input_adapter template::value and - std::is_integral< - typename std::remove_pointer::type>::value and + std::is_integral::type>::value and sizeof(typename std::remove_pointer::type) == 1, int>::type = 0> input_adapter(CharT b, std::size_t l) @@ -1588,8 +1562,7 @@ class input_adapter template::value and - std::is_integral< - typename std::remove_pointer::type>::value and + std::is_integral::type>::value and sizeof(typename std::remove_pointer::type) == 1, int>::type = 0> input_adapter(CharT b) @@ -1599,8 +1572,7 @@ class input_adapter /// input adapter for iterator range with contiguous storage template::iterator_category, - std::random_access_iterator_tag>::value, + std::is_same::iterator_category, std::random_access_iterator_tag>::value, int>::type = 0> input_adapter(IteratorType first, IteratorType last) { @@ -1638,13 +1610,12 @@ class input_adapter : input_adapter(std::begin(array), std::end(array)) {} /// input adapter for contiguous container - template < - class ContiguousContainer, - typename std::enable_if < - not std::is_pointer::value and - std::is_base_of()))>::iterator_category>::value, - int >::type = 0 > + template::value and + std::is_base_of()))>::iterator_category>::value, + int>::type = 0> input_adapter(const ContiguousContainer& c) : input_adapter(std::begin(c), std::end(c)) {} @@ -1818,6 +1789,12 @@ class lexer checks if it is inside the range. If a violation was detected, set up an error message and return false. Otherwise, return true. + @param[in] ranges list of integers; interpreted as list of pairs of + inclusive lower and upper bound, respectively + + @pre The passed list @a ranges must have 2, 4, or 6 elements; that is, + 1, 2, or 3 pairs. This precondition is enforced by an assertion. + @return true if and only if no range violation was detected */ bool next_byte_in_range(std::initializer_list ranges) @@ -1984,19 +1961,19 @@ class lexer // result of the above calculation yields a proper codepoint assert(0x00 <= codepoint and codepoint <= 0x10FFFF); - // translate code point to bytes + // translate codepoint into bytes if (codepoint < 0x80) { // 1-byte characters: 0xxxxxxx (ASCII) add(codepoint); } - else if (codepoint <= 0x7ff) + else if (codepoint <= 0x7FF) { // 2-byte characters: 110xxxxx 10xxxxxx add(0xC0 | (codepoint >> 6)); add(0x80 | (codepoint & 0x3F)); } - else if (codepoint <= 0xffff) + else if (codepoint <= 0xFFFF) { // 3-byte characters: 1110xxxx 10xxxxxx 10xxxxxx add(0xE0 | (codepoint >> 12)); @@ -2035,12 +2012,12 @@ class lexer case 0x07: case 0x08: case 0x09: - case 0x0a: - case 0x0b: - case 0x0c: - case 0x0d: - case 0x0e: - case 0x0f: + case 0x0A: + case 0x0B: + case 0x0C: + case 0x0D: + case 0x0E: + case 0x0F: case 0x10: case 0x11: case 0x12: @@ -2051,12 +2028,12 @@ class lexer case 0x17: case 0x18: case 0x19: - case 0x1a: - case 0x1b: - case 0x1c: - case 0x1d: - case 0x1e: - case 0x1f: + case 0x1A: + case 0x1B: + case 0x1C: + case 0x1D: + case 0x1E: + case 0x1F: { error_message = "invalid string: control character must be escaped"; return token_type::parse_error; @@ -2072,12 +2049,12 @@ class lexer case 0x27: case 0x28: case 0x29: - case 0x2a: - case 0x2b: - case 0x2c: - case 0x2d: - case 0x2e: - case 0x2f: + case 0x2A: + case 0x2B: + case 0x2C: + case 0x2D: + case 0x2E: + case 0x2F: case 0x30: case 0x31: case 0x32: @@ -2088,12 +2065,12 @@ class lexer case 0x37: case 0x38: case 0x39: - case 0x3a: - case 0x3b: - case 0x3c: - case 0x3d: - case 0x3e: - case 0x3f: + case 0x3A: + case 0x3B: + case 0x3C: + case 0x3D: + case 0x3E: + case 0x3F: case 0x40: case 0x41: case 0x42: @@ -2104,12 +2081,12 @@ class lexer case 0x47: case 0x48: case 0x49: - case 0x4a: - case 0x4b: - case 0x4c: - case 0x4d: - case 0x4e: - case 0x4f: + case 0x4A: + case 0x4B: + case 0x4C: + case 0x4D: + case 0x4E: + case 0x4F: case 0x50: case 0x51: case 0x52: @@ -2120,11 +2097,11 @@ class lexer case 0x57: case 0x58: case 0x59: - case 0x5a: - case 0x5b: - case 0x5d: - case 0x5e: - case 0x5f: + case 0x5A: + case 0x5B: + case 0x5D: + case 0x5E: + case 0x5F: case 0x60: case 0x61: case 0x62: @@ -2135,12 +2112,12 @@ class lexer case 0x67: case 0x68: case 0x69: - case 0x6a: - case 0x6b: - case 0x6c: - case 0x6d: - case 0x6e: - case 0x6f: + case 0x6A: + case 0x6B: + case 0x6C: + case 0x6D: + case 0x6E: + case 0x6F: case 0x70: case 0x71: case 0x72: @@ -2151,48 +2128,48 @@ class lexer case 0x77: case 0x78: case 0x79: - case 0x7a: - case 0x7b: - case 0x7c: - case 0x7d: - case 0x7e: - case 0x7f: + case 0x7A: + case 0x7B: + case 0x7C: + case 0x7D: + case 0x7E: + case 0x7F: { add(current); break; } // U+0080..U+07FF: bytes C2..DF 80..BF - case 0xc2: - case 0xc3: - case 0xc4: - case 0xc5: - case 0xc6: - case 0xc7: - case 0xc8: - case 0xc9: - case 0xca: - case 0xcb: - case 0xcc: - case 0xcd: - case 0xce: - case 0xcf: - case 0xd0: - case 0xd1: - case 0xd2: - case 0xd3: - case 0xd4: - case 0xd5: - case 0xd6: - case 0xd7: - case 0xd8: - case 0xd9: - case 0xda: - case 0xdb: - case 0xdc: - case 0xdd: - case 0xde: - case 0xdf: + case 0xC2: + case 0xC3: + case 0xC4: + case 0xC5: + case 0xC6: + case 0xC7: + case 0xC8: + case 0xC9: + case 0xCA: + case 0xCB: + case 0xCC: + case 0xCD: + case 0xCE: + case 0xCF: + case 0xD0: + case 0xD1: + case 0xD2: + case 0xD3: + case 0xD4: + case 0xD5: + case 0xD6: + case 0xD7: + case 0xD8: + case 0xD9: + case 0xDA: + case 0xDB: + case 0xDC: + case 0xDD: + case 0xDE: + case 0xDF: { if (JSON_UNLIKELY(not next_byte_in_range({0x80, 0xBF}))) { @@ -2202,7 +2179,7 @@ class lexer } // U+0800..U+0FFF: bytes E0 A0..BF 80..BF - case 0xe0: + case 0xE0: { if (JSON_UNLIKELY(not (next_byte_in_range({0xA0, 0xBF, 0x80, 0xBF})))) { @@ -2213,20 +2190,20 @@ class lexer // U+1000..U+CFFF: bytes E1..EC 80..BF 80..BF // U+E000..U+FFFF: bytes EE..EF 80..BF 80..BF - case 0xe1: - case 0xe2: - case 0xe3: - case 0xe4: - case 0xe5: - case 0xe6: - case 0xe7: - case 0xe8: - case 0xe9: - case 0xea: - case 0xeb: - case 0xec: - case 0xee: - case 0xef: + case 0xE1: + case 0xE2: + case 0xE3: + case 0xE4: + case 0xE5: + case 0xE6: + case 0xE7: + case 0xE8: + case 0xE9: + case 0xEA: + case 0xEB: + case 0xEC: + case 0xEE: + case 0xEF: { if (JSON_UNLIKELY(not (next_byte_in_range({0x80, 0xBF, 0x80, 0xBF})))) { @@ -2236,7 +2213,7 @@ class lexer } // U+D000..U+D7FF: bytes ED 80..9F 80..BF - case 0xed: + case 0xED: { if (JSON_UNLIKELY(not (next_byte_in_range({0x80, 0x9F, 0x80, 0xBF})))) { @@ -2246,7 +2223,7 @@ class lexer } // U+10000..U+3FFFF F0 90..BF 80..BF 80..BF - case 0xf0: + case 0xF0: { if (JSON_UNLIKELY(not (next_byte_in_range({0x90, 0xBF, 0x80, 0xBF, 0x80, 0xBF})))) { @@ -2256,9 +2233,9 @@ class lexer } // U+40000..U+FFFFF F1..F3 80..BF 80..BF 80..BF - case 0xf1: - case 0xf2: - case 0xf3: + case 0xF1: + case 0xF2: + case 0xF3: { if (JSON_UNLIKELY(not (next_byte_in_range({0x80, 0xBF, 0x80, 0xBF, 0x80, 0xBF})))) { @@ -2268,7 +2245,7 @@ class lexer } // U+100000..U+10FFFF F4 80..8F 80..BF 80..BF - case 0xf4: + case 0xF4: { if (JSON_UNLIKELY(not (next_byte_in_range({0x80, 0x8F, 0x80, 0xBF, 0x80, 0xBF})))) { @@ -2788,7 +2765,7 @@ scan_number_done: std::string result; for (auto c : token_string) { - if ('\x00' <= c and c <= '\x1f') + if ('\x00' <= c and c <= '\x1F') { // escape control characters std::stringstream ss; @@ -2891,10 +2868,10 @@ scan_number_done: std::size_t chars_read = 0; /// raw input token string (for error messages) - std::vector token_string { }; + std::vector token_string {}; /// buffer for variable-length tokens (numbers, strings) - std::string yytext { }; + std::string yytext {}; /// a description of occurred lexer errors const char* error_message = ""; @@ -4598,12 +4575,12 @@ class binary_reader case 0x07: case 0x08: case 0x09: - case 0x0a: - case 0x0b: - case 0x0c: - case 0x0d: - case 0x0e: - case 0x0f: + case 0x0A: + case 0x0B: + case 0x0C: + case 0x0D: + case 0x0E: + case 0x0F: case 0x10: case 0x11: case 0x12: @@ -4620,10 +4597,10 @@ class binary_reader case 0x19: // Unsigned integer (two-byte uint16_t follows) return get_number(); - case 0x1a: // Unsigned integer (four-byte uint32_t follows) + case 0x1A: // Unsigned integer (four-byte uint32_t follows) return get_number(); - case 0x1b: // Unsigned integer (eight-byte uint64_t follows) + case 0x1B: // Unsigned integer (eight-byte uint64_t follows) return get_number(); // Negative integer -1-0x00..-1-0x17 (-1..-24) @@ -4637,12 +4614,12 @@ class binary_reader case 0x27: case 0x28: case 0x29: - case 0x2a: - case 0x2b: - case 0x2c: - case 0x2d: - case 0x2e: - case 0x2f: + case 0x2A: + case 0x2B: + case 0x2C: + case 0x2D: + case 0x2E: + case 0x2F: case 0x30: case 0x31: case 0x32: @@ -4664,12 +4641,12 @@ class binary_reader return static_cast(-1) - get_number(); } - case 0x3a: // Negative integer -1-n (four-byte uint32_t follows) + case 0x3A: // Negative integer -1-n (four-byte uint32_t follows) { return static_cast(-1) - get_number(); } - case 0x3b: // Negative integer -1-n (eight-byte uint64_t follows) + case 0x3B: // Negative integer -1-n (eight-byte uint64_t follows) { return static_cast(-1) - static_cast(get_number()); @@ -4686,12 +4663,12 @@ class binary_reader case 0x67: case 0x68: case 0x69: - case 0x6a: - case 0x6b: - case 0x6c: - case 0x6d: - case 0x6e: - case 0x6f: + case 0x6A: + case 0x6B: + case 0x6C: + case 0x6D: + case 0x6E: + case 0x6F: case 0x70: case 0x71: case 0x72: @@ -4702,9 +4679,9 @@ class binary_reader case 0x77: case 0x78: // UTF-8 string (one-byte uint8_t for n follows) case 0x79: // UTF-8 string (two-byte uint16_t for n follow) - case 0x7a: // UTF-8 string (four-byte uint32_t for n follow) - case 0x7b: // UTF-8 string (eight-byte uint64_t for n follow) - case 0x7f: // UTF-8 string (indefinite length) + case 0x7A: // UTF-8 string (four-byte uint32_t for n follow) + case 0x7B: // UTF-8 string (eight-byte uint64_t for n follow) + case 0x7F: // UTF-8 string (indefinite length) { return get_cbor_string(); } @@ -4720,12 +4697,12 @@ class binary_reader case 0x87: case 0x88: case 0x89: - case 0x8a: - case 0x8b: - case 0x8c: - case 0x8d: - case 0x8e: - case 0x8f: + case 0x8A: + case 0x8B: + case 0x8C: + case 0x8D: + case 0x8E: + case 0x8F: case 0x90: case 0x91: case 0x92: @@ -4735,7 +4712,7 @@ class binary_reader case 0x96: case 0x97: { - return get_cbor_array(current & 0x1f); + return get_cbor_array(current & 0x1F); } case 0x98: // array (one-byte uint8_t for n follows) @@ -4748,20 +4725,20 @@ class binary_reader return get_cbor_array(get_number()); } - case 0x9a: // array (four-byte uint32_t for n follow) + case 0x9A: // array (four-byte uint32_t for n follow) { return get_cbor_array(get_number()); } - case 0x9b: // array (eight-byte uint64_t for n follow) + case 0x9B: // array (eight-byte uint64_t for n follow) { return get_cbor_array(get_number()); } - case 0x9f: // array (indefinite length) + case 0x9F: // array (indefinite length) { BasicJsonType result = value_t::array; - while (get() != 0xff) + while (get() != 0xFF) { result.push_back(parse_cbor_internal(false)); } @@ -4769,58 +4746,58 @@ class binary_reader } // map (0x00..0x17 pairs of data items follow) - case 0xa0: - case 0xa1: - case 0xa2: - case 0xa3: - case 0xa4: - case 0xa5: - case 0xa6: - case 0xa7: - case 0xa8: - case 0xa9: - case 0xaa: - case 0xab: - case 0xac: - case 0xad: - case 0xae: - case 0xaf: - case 0xb0: - case 0xb1: - case 0xb2: - case 0xb3: - case 0xb4: - case 0xb5: - case 0xb6: - case 0xb7: + case 0xA0: + case 0xA1: + case 0xA2: + case 0xA3: + case 0xA4: + case 0xA5: + case 0xA6: + case 0xA7: + case 0xA8: + case 0xA9: + case 0xAA: + case 0xAB: + case 0xAC: + case 0xAD: + case 0xAE: + case 0xAF: + case 0xB0: + case 0xB1: + case 0xB2: + case 0xB3: + case 0xB4: + case 0xB5: + case 0xB6: + case 0xB7: { - return get_cbor_object(current & 0x1f); + return get_cbor_object(current & 0x1F); } - case 0xb8: // map (one-byte uint8_t for n follows) + case 0xB8: // map (one-byte uint8_t for n follows) { return get_cbor_object(get_number()); } - case 0xb9: // map (two-byte uint16_t for n follow) + case 0xB9: // map (two-byte uint16_t for n follow) { return get_cbor_object(get_number()); } - case 0xba: // map (four-byte uint32_t for n follow) + case 0xBA: // map (four-byte uint32_t for n follow) { return get_cbor_object(get_number()); } - case 0xbb: // map (eight-byte uint64_t for n follow) + case 0xBB: // map (eight-byte uint64_t for n follow) { return get_cbor_object(get_number()); } - case 0xbf: // map (indefinite length) + case 0xBF: // map (indefinite length) { BasicJsonType result = value_t::object; - while (get() != 0xff) + while (get() != 0xFF) { auto key = get_cbor_string(); result[key] = parse_cbor_internal(); @@ -4828,22 +4805,22 @@ class binary_reader return result; } - case 0xf4: // false + case 0xF4: // false { return false; } - case 0xf5: // true + case 0xF5: // true { return true; } - case 0xf6: // null + case 0xF6: // null { return value_t::null; } - case 0xf9: // Half-Precision Float (two-byte IEEE 754) + case 0xF9: // Half-Precision Float (two-byte IEEE 754) { const int byte1 = get(); check_eof(); @@ -4859,8 +4836,8 @@ class binary_reader // half-precision floating-point numbers in the C language // is shown in Fig. 3. const int half = (byte1 << 8) + byte2; - const int exp = (half >> 10) & 0x1f; - const int mant = half & 0x3ff; + const int exp = (half >> 10) & 0x1F; + const int mant = half & 0x3FF; double val; if (exp == 0) { @@ -4878,12 +4855,12 @@ class binary_reader return (half & 0x8000) != 0 ? -val : val; } - case 0xfa: // Single-Precision Float (four-byte IEEE 754) + case 0xFA: // Single-Precision Float (four-byte IEEE 754) { return get_number(); } - case 0xfb: // Double-Precision Float (eight-byte IEEE 754) + case 0xFB: // Double-Precision Float (eight-byte IEEE 754) { return get_number(); } @@ -4916,12 +4893,12 @@ class binary_reader case 0x07: case 0x08: case 0x09: - case 0x0a: - case 0x0b: - case 0x0c: - case 0x0d: - case 0x0e: - case 0x0f: + case 0x0A: + case 0x0B: + case 0x0C: + case 0x0D: + case 0x0E: + case 0x0F: case 0x10: case 0x11: case 0x12: @@ -4932,12 +4909,12 @@ class binary_reader case 0x17: case 0x18: case 0x19: - case 0x1a: - case 0x1b: - case 0x1c: - case 0x1d: - case 0x1e: - case 0x1f: + case 0x1A: + case 0x1B: + case 0x1C: + case 0x1D: + case 0x1E: + case 0x1F: case 0x20: case 0x21: case 0x22: @@ -4948,12 +4925,12 @@ class binary_reader case 0x27: case 0x28: case 0x29: - case 0x2a: - case 0x2b: - case 0x2c: - case 0x2d: - case 0x2e: - case 0x2f: + case 0x2A: + case 0x2B: + case 0x2C: + case 0x2D: + case 0x2E: + case 0x2F: case 0x30: case 0x31: case 0x32: @@ -4964,12 +4941,12 @@ class binary_reader case 0x37: case 0x38: case 0x39: - case 0x3a: - case 0x3b: - case 0x3c: - case 0x3d: - case 0x3e: - case 0x3f: + case 0x3A: + case 0x3B: + case 0x3C: + case 0x3D: + case 0x3E: + case 0x3F: case 0x40: case 0x41: case 0x42: @@ -4980,12 +4957,12 @@ class binary_reader case 0x47: case 0x48: case 0x49: - case 0x4a: - case 0x4b: - case 0x4c: - case 0x4d: - case 0x4e: - case 0x4f: + case 0x4A: + case 0x4B: + case 0x4C: + case 0x4D: + case 0x4E: + case 0x4F: case 0x50: case 0x51: case 0x52: @@ -4996,12 +4973,12 @@ class binary_reader case 0x57: case 0x58: case 0x59: - case 0x5a: - case 0x5b: - case 0x5c: - case 0x5d: - case 0x5e: - case 0x5f: + case 0x5A: + case 0x5B: + case 0x5C: + case 0x5D: + case 0x5E: + case 0x5F: case 0x60: case 0x61: case 0x62: @@ -5012,12 +4989,12 @@ class binary_reader case 0x67: case 0x68: case 0x69: - case 0x6a: - case 0x6b: - case 0x6c: - case 0x6d: - case 0x6e: - case 0x6f: + case 0x6A: + case 0x6B: + case 0x6C: + case 0x6D: + case 0x6E: + case 0x6F: case 0x70: case 0x71: case 0x72: @@ -5028,12 +5005,12 @@ class binary_reader case 0x77: case 0x78: case 0x79: - case 0x7a: - case 0x7b: - case 0x7c: - case 0x7d: - case 0x7e: - case 0x7f: + case 0x7A: + case 0x7B: + case 0x7C: + case 0x7D: + case 0x7E: + case 0x7F: return static_cast(current); // fixmap @@ -5047,14 +5024,14 @@ class binary_reader case 0x87: case 0x88: case 0x89: - case 0x8a: - case 0x8b: - case 0x8c: - case 0x8d: - case 0x8e: - case 0x8f: + case 0x8A: + case 0x8B: + case 0x8C: + case 0x8D: + case 0x8E: + case 0x8F: { - return get_msgpack_object(current & 0x0f); + return get_msgpack_object(current & 0x0F); } // fixarray @@ -5068,148 +5045,148 @@ class binary_reader case 0x97: case 0x98: case 0x99: - case 0x9a: - case 0x9b: - case 0x9c: - case 0x9d: - case 0x9e: - case 0x9f: + case 0x9A: + case 0x9B: + case 0x9C: + case 0x9D: + case 0x9E: + case 0x9F: { - return get_msgpack_array(current & 0x0f); + return get_msgpack_array(current & 0x0F); } // fixstr - case 0xa0: - case 0xa1: - case 0xa2: - case 0xa3: - case 0xa4: - case 0xa5: - case 0xa6: - case 0xa7: - case 0xa8: - case 0xa9: - case 0xaa: - case 0xab: - case 0xac: - case 0xad: - case 0xae: - case 0xaf: - case 0xb0: - case 0xb1: - case 0xb2: - case 0xb3: - case 0xb4: - case 0xb5: - case 0xb6: - case 0xb7: - case 0xb8: - case 0xb9: - case 0xba: - case 0xbb: - case 0xbc: - case 0xbd: - case 0xbe: - case 0xbf: + case 0xA0: + case 0xA1: + case 0xA2: + case 0xA3: + case 0xA4: + case 0xA5: + case 0xA6: + case 0xA7: + case 0xA8: + case 0xA9: + case 0xAA: + case 0xAB: + case 0xAC: + case 0xAD: + case 0xAE: + case 0xAF: + case 0xB0: + case 0xB1: + case 0xB2: + case 0xB3: + case 0xB4: + case 0xB5: + case 0xB6: + case 0xB7: + case 0xB8: + case 0xB9: + case 0xBA: + case 0xBB: + case 0xBC: + case 0xBD: + case 0xBE: + case 0xBF: return get_msgpack_string(); - case 0xc0: // nil + case 0xC0: // nil return value_t::null; - case 0xc2: // false + case 0xC2: // false return false; - case 0xc3: // true + case 0xC3: // true return true; - case 0xca: // float 32 + case 0xCA: // float 32 return get_number(); - case 0xcb: // float 64 + case 0xCB: // float 64 return get_number(); - case 0xcc: // uint 8 + case 0xCC: // uint 8 return get_number(); - case 0xcd: // uint 16 + case 0xCD: // uint 16 return get_number(); - case 0xce: // uint 32 + case 0xCE: // uint 32 return get_number(); - case 0xcf: // uint 64 + case 0xCF: // uint 64 return get_number(); - case 0xd0: // int 8 + case 0xD0: // int 8 return get_number(); - case 0xd1: // int 16 + case 0xD1: // int 16 return get_number(); - case 0xd2: // int 32 + case 0xD2: // int 32 return get_number(); - case 0xd3: // int 64 + case 0xD3: // int 64 return get_number(); - case 0xd9: // str 8 - case 0xda: // str 16 - case 0xdb: // str 32 + case 0xD9: // str 8 + case 0xDA: // str 16 + case 0xDB: // str 32 return get_msgpack_string(); - case 0xdc: // array 16 + case 0xDC: // array 16 { return get_msgpack_array(get_number()); } - case 0xdd: // array 32 + case 0xDD: // array 32 { return get_msgpack_array(get_number()); } - case 0xde: // map 16 + case 0xDE: // map 16 { return get_msgpack_object(get_number()); } - case 0xdf: // map 32 + case 0xDF: // map 32 { return get_msgpack_object(get_number()); } // positive fixint - case 0xe0: - case 0xe1: - case 0xe2: - case 0xe3: - case 0xe4: - case 0xe5: - case 0xe6: - case 0xe7: - case 0xe8: - case 0xe9: - case 0xea: - case 0xeb: - case 0xec: - case 0xed: - case 0xee: - case 0xef: - case 0xf0: - case 0xf1: - case 0xf2: - case 0xf3: - case 0xf4: - case 0xf5: - case 0xf6: - case 0xf7: - case 0xf8: - case 0xf9: - case 0xfa: - case 0xfb: - case 0xfc: - case 0xfd: - case 0xfe: - case 0xff: + case 0xE0: + case 0xE1: + case 0xE2: + case 0xE3: + case 0xE4: + case 0xE5: + case 0xE6: + case 0xE7: + case 0xE8: + case 0xE9: + case 0xEA: + case 0xEB: + case 0xEC: + case 0xED: + case 0xEE: + case 0xEF: + case 0xF0: + case 0xF1: + case 0xF2: + case 0xF3: + case 0xF4: + case 0xF5: + case 0xF6: + case 0xF7: + case 0xF8: + case 0xF9: + case 0xFA: + case 0xFB: + case 0xFC: + case 0xFD: + case 0xFE: + case 0xFF: return static_cast(current); default: // anything else @@ -5331,12 +5308,12 @@ class binary_reader case 0x67: case 0x68: case 0x69: - case 0x6a: - case 0x6b: - case 0x6c: - case 0x6d: - case 0x6e: - case 0x6f: + case 0x6A: + case 0x6B: + case 0x6C: + case 0x6D: + case 0x6E: + case 0x6F: case 0x70: case 0x71: case 0x72: @@ -5346,7 +5323,7 @@ class binary_reader case 0x76: case 0x77: { - return get_string(current & 0x1f); + return get_string(current & 0x1F); } case 0x78: // UTF-8 string (one-byte uint8_t for n follows) @@ -5359,20 +5336,20 @@ class binary_reader return get_string(get_number()); } - case 0x7a: // UTF-8 string (four-byte uint32_t for n follow) + case 0x7A: // UTF-8 string (four-byte uint32_t for n follow) { return get_string(get_number()); } - case 0x7b: // UTF-8 string (eight-byte uint64_t for n follow) + case 0x7B: // UTF-8 string (eight-byte uint64_t for n follow) { return get_string(get_number()); } - case 0x7f: // UTF-8 string (indefinite length) + case 0x7F: // UTF-8 string (indefinite length) { std::string result; - while (get() != 0xff) + while (get() != 0xFF) { check_eof(); result.push_back(static_cast(current)); @@ -5434,53 +5411,53 @@ class binary_reader switch (current) { // fixstr - case 0xa0: - case 0xa1: - case 0xa2: - case 0xa3: - case 0xa4: - case 0xa5: - case 0xa6: - case 0xa7: - case 0xa8: - case 0xa9: - case 0xaa: - case 0xab: - case 0xac: - case 0xad: - case 0xae: - case 0xaf: - case 0xb0: - case 0xb1: - case 0xb2: - case 0xb3: - case 0xb4: - case 0xb5: - case 0xb6: - case 0xb7: - case 0xb8: - case 0xb9: - case 0xba: - case 0xbb: - case 0xbc: - case 0xbd: - case 0xbe: - case 0xbf: + case 0xA0: + case 0xA1: + case 0xA2: + case 0xA3: + case 0xA4: + case 0xA5: + case 0xA6: + case 0xA7: + case 0xA8: + case 0xA9: + case 0xAA: + case 0xAB: + case 0xAC: + case 0xAD: + case 0xAE: + case 0xAF: + case 0xB0: + case 0xB1: + case 0xB2: + case 0xB3: + case 0xB4: + case 0xB5: + case 0xB6: + case 0xB7: + case 0xB8: + case 0xB9: + case 0xBA: + case 0xBB: + case 0xBC: + case 0xBD: + case 0xBE: + case 0xBF: { - return get_string(current & 0x1f); + return get_string(current & 0x1F); } - case 0xd9: // str 8 + case 0xD9: // str 8 { return get_string(get_number()); } - case 0xda: // str 16 + case 0xDA: // str 16 { return get_string(get_number()); } - case 0xdb: // str 32 + case 0xDB: // str 32 { return get_string(get_number()); } @@ -5584,15 +5561,15 @@ class binary_writer { case value_t::null: { - oa->write_character(static_cast(0xf6)); + oa->write_character(static_cast(0xF6)); break; } case value_t::boolean: { oa->write_character(j.m_value.boolean - ? static_cast(0xf5) - : static_cast(0xf4)); + ? static_cast(0xF5) + : static_cast(0xF4)); break; } @@ -5619,12 +5596,12 @@ class binary_writer } else if (j.m_value.number_integer <= (std::numeric_limits::max)()) { - oa->write_character(static_cast(0x1a)); + oa->write_character(static_cast(0x1A)); write_number(static_cast(j.m_value.number_integer)); } else { - oa->write_character(static_cast(0x1b)); + oa->write_character(static_cast(0x1B)); write_number(static_cast(j.m_value.number_integer)); } } @@ -5649,12 +5626,12 @@ class binary_writer } else if (positive_number <= (std::numeric_limits::max)()) { - oa->write_character(static_cast(0x3a)); + oa->write_character(static_cast(0x3A)); write_number(static_cast(positive_number)); } else { - oa->write_character(static_cast(0x3b)); + oa->write_character(static_cast(0x3B)); write_number(static_cast(positive_number)); } } @@ -5679,12 +5656,12 @@ class binary_writer } else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) { - oa->write_character(static_cast(0x1a)); + oa->write_character(static_cast(0x1A)); write_number(static_cast(j.m_value.number_unsigned)); } else { - oa->write_character(static_cast(0x1b)); + oa->write_character(static_cast(0x1B)); write_number(static_cast(j.m_value.number_unsigned)); } break; @@ -5692,7 +5669,7 @@ class binary_writer case value_t::number_float: // Double-Precision Float { - oa->write_character(static_cast(0xfb)); + oa->write_character(static_cast(0xFB)); write_number(j.m_value.number_float); break; } @@ -5705,25 +5682,25 @@ class binary_writer { write_number(static_cast(0x60 + N)); } - else if (N <= 0xff) + else if (N <= 0xFF) { oa->write_character(static_cast(0x78)); write_number(static_cast(N)); } - else if (N <= 0xffff) + else if (N <= 0xFFFF) { oa->write_character(static_cast(0x79)); write_number(static_cast(N)); } - else if (N <= 0xffffffff) + else if (N <= 0xFFFFFFFF) { - oa->write_character(static_cast(0x7a)); + oa->write_character(static_cast(0x7A)); write_number(static_cast(N)); } // LCOV_EXCL_START - else if (N <= 0xffffffffffffffff) + else if (N <= 0xFFFFFFFFFFFFFFFF) { - oa->write_character(static_cast(0x7b)); + oa->write_character(static_cast(0x7B)); write_number(static_cast(N)); } // LCOV_EXCL_STOP @@ -5743,25 +5720,25 @@ class binary_writer { write_number(static_cast(0x80 + N)); } - else if (N <= 0xff) + else if (N <= 0xFF) { oa->write_character(static_cast(0x98)); write_number(static_cast(N)); } - else if (N <= 0xffff) + else if (N <= 0xFFFF) { oa->write_character(static_cast(0x99)); write_number(static_cast(N)); } - else if (N <= 0xffffffff) + else if (N <= 0xFFFFFFFF) { - oa->write_character(static_cast(0x9a)); + oa->write_character(static_cast(0x9A)); write_number(static_cast(N)); } // LCOV_EXCL_START - else if (N <= 0xffffffffffffffff) + else if (N <= 0xFFFFFFFFFFFFFFFF) { - oa->write_character(static_cast(0x9b)); + oa->write_character(static_cast(0x9B)); write_number(static_cast(N)); } // LCOV_EXCL_STOP @@ -5780,27 +5757,27 @@ class binary_writer const auto N = j.m_value.object->size(); if (N <= 0x17) { - write_number(static_cast(0xa0 + N)); + write_number(static_cast(0xA0 + N)); } - else if (N <= 0xff) + else if (N <= 0xFF) { - oa->write_character(static_cast(0xb8)); + oa->write_character(static_cast(0xB8)); write_number(static_cast(N)); } - else if (N <= 0xffff) + else if (N <= 0xFFFF) { - oa->write_character(static_cast(0xb9)); + oa->write_character(static_cast(0xB9)); write_number(static_cast(N)); } - else if (N <= 0xffffffff) + else if (N <= 0xFFFFFFFF) { - oa->write_character(static_cast(0xba)); + oa->write_character(static_cast(0xBA)); write_number(static_cast(N)); } // LCOV_EXCL_START - else if (N <= 0xffffffffffffffff) + else if (N <= 0xFFFFFFFFFFFFFFFF) { - oa->write_character(static_cast(0xbb)); + oa->write_character(static_cast(0xBB)); write_number(static_cast(N)); } // LCOV_EXCL_STOP @@ -5828,15 +5805,15 @@ class binary_writer { case value_t::null: // nil { - oa->write_character(static_cast(0xc0)); + oa->write_character(static_cast(0xC0)); break; } case value_t::boolean: // true and false { oa->write_character(j.m_value.boolean - ? static_cast(0xc3) - : static_cast(0xc2)); + ? static_cast(0xC3) + : static_cast(0xC2)); break; } @@ -5855,25 +5832,25 @@ class binary_writer else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) { // uint 8 - oa->write_character(static_cast(0xcc)); + oa->write_character(static_cast(0xCC)); write_number(static_cast(j.m_value.number_integer)); } else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) { // uint 16 - oa->write_character(static_cast(0xcd)); + oa->write_character(static_cast(0xCD)); write_number(static_cast(j.m_value.number_integer)); } else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) { // uint 32 - oa->write_character(static_cast(0xce)); + oa->write_character(static_cast(0xCE)); write_number(static_cast(j.m_value.number_integer)); } else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) { // uint 64 - oa->write_character(static_cast(0xcf)); + oa->write_character(static_cast(0xCF)); write_number(static_cast(j.m_value.number_integer)); } } @@ -5888,28 +5865,28 @@ class binary_writer j.m_value.number_integer <= (std::numeric_limits::max)()) { // int 8 - oa->write_character(static_cast(0xd0)); + oa->write_character(static_cast(0xD0)); write_number(static_cast(j.m_value.number_integer)); } else if (j.m_value.number_integer >= (std::numeric_limits::min)() and j.m_value.number_integer <= (std::numeric_limits::max)()) { // int 16 - oa->write_character(static_cast(0xd1)); + oa->write_character(static_cast(0xD1)); write_number(static_cast(j.m_value.number_integer)); } else if (j.m_value.number_integer >= (std::numeric_limits::min)() and j.m_value.number_integer <= (std::numeric_limits::max)()) { // int 32 - oa->write_character(static_cast(0xd2)); + oa->write_character(static_cast(0xD2)); write_number(static_cast(j.m_value.number_integer)); } else if (j.m_value.number_integer >= (std::numeric_limits::min)() and j.m_value.number_integer <= (std::numeric_limits::max)()) { // int 64 - oa->write_character(static_cast(0xd3)); + oa->write_character(static_cast(0xD3)); write_number(static_cast(j.m_value.number_integer)); } } @@ -5926,25 +5903,25 @@ class binary_writer else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) { // uint 8 - oa->write_character(static_cast(0xcc)); + oa->write_character(static_cast(0xCC)); write_number(static_cast(j.m_value.number_integer)); } else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) { // uint 16 - oa->write_character(static_cast(0xcd)); + oa->write_character(static_cast(0xCD)); write_number(static_cast(j.m_value.number_integer)); } else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) { // uint 32 - oa->write_character(static_cast(0xce)); + oa->write_character(static_cast(0xCE)); write_number(static_cast(j.m_value.number_integer)); } else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) { // uint 64 - oa->write_character(static_cast(0xcf)); + oa->write_character(static_cast(0xCF)); write_number(static_cast(j.m_value.number_integer)); } break; @@ -5952,7 +5929,7 @@ class binary_writer case value_t::number_float: // float 64 { - oa->write_character(static_cast(0xcb)); + oa->write_character(static_cast(0xCB)); write_number(j.m_value.number_float); break; } @@ -5964,24 +5941,24 @@ class binary_writer if (N <= 31) { // fixstr - write_number(static_cast(0xa0 | N)); + write_number(static_cast(0xA0 | N)); } else if (N <= 255) { // str 8 - oa->write_character(static_cast(0xd9)); + oa->write_character(static_cast(0xD9)); write_number(static_cast(N)); } else if (N <= 65535) { // str 16 - oa->write_character(static_cast(0xda)); + oa->write_character(static_cast(0xDA)); write_number(static_cast(N)); } else if (N <= 4294967295) { // str 32 - oa->write_character(static_cast(0xdb)); + oa->write_character(static_cast(0xDB)); write_number(static_cast(N)); } @@ -6001,16 +5978,16 @@ class binary_writer // fixarray write_number(static_cast(0x90 | N)); } - else if (N <= 0xffff) + else if (N <= 0xFFFF) { // array 16 - oa->write_character(static_cast(0xdc)); + oa->write_character(static_cast(0xDC)); write_number(static_cast(N)); } - else if (N <= 0xffffffff) + else if (N <= 0xFFFFFFFF) { // array 32 - oa->write_character(static_cast(0xdd)); + oa->write_character(static_cast(0xDD)); write_number(static_cast(N)); } @@ -6029,18 +6006,18 @@ class binary_writer if (N <= 15) { // fixmap - write_number(static_cast(0x80 | (N & 0xf))); + write_number(static_cast(0x80 | (N & 0xF))); } else if (N <= 65535) { // map 16 - oa->write_character(static_cast(0xde)); + oa->write_character(static_cast(0xDE)); write_number(static_cast(N)); } else if (N <= 4294967295) { // map 32 - oa->write_character(static_cast(0xdf)); + oa->write_character(static_cast(0xDF)); write_number(static_cast(N)); } @@ -6385,9 +6362,9 @@ class serializer case 0x05: case 0x06: case 0x07: - case 0x0b: - case 0x0e: - case 0x0f: + case 0x0B: + case 0x0E: + case 0x0F: case 0x10: case 0x11: case 0x12: @@ -6398,12 +6375,12 @@ class serializer case 0x17: case 0x18: case 0x19: - case 0x1a: - case 0x1b: - case 0x1c: - case 0x1d: - case 0x1e: - case 0x1f: + case 0x1A: + case 0x1B: + case 0x1C: + case 0x1D: + case 0x1E: + case 0x1F: { // from c (1 byte) to \uxxxx (6 bytes) res += 5; @@ -6534,7 +6511,7 @@ class serializer break; } - case '\\': // reverse solidus (0x5c) + case '\\': // reverse solidus (0x5C) { // nothing to change pos += 2; @@ -6548,21 +6525,21 @@ class serializer break; } - case '\f': // formfeed (0x0c) + case '\f': // formfeed (0x0C) { result[pos + 1] = 'f'; pos += 2; break; } - case '\n': // newline (0x0a) + case '\n': // newline (0x0A) { result[pos + 1] = 'n'; pos += 2; break; } - case '\r': // carriage return (0x0d) + case '\r': // carriage return (0x0D) { result[pos + 1] = 'r'; pos += 2; @@ -6657,11 +6634,10 @@ class serializer @param[in] x integer number (signed or unsigned) to dump @tparam NumberType either @a number_integer_t or @a number_unsigned_t */ - template < - typename NumberType, - detail::enable_if_t::value or - std::is_same::value, - int> = 0 > + template::value or + std::is_same::value, + int> = 0> void dump_integer(NumberType x) { // special case for "0" @@ -6784,15 +6760,15 @@ class serializer static const std::array utf8d = { { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 00..1f - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 20..3f - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 40..5f - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 60..7f - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, // 80..9f - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // a0..bf - 8, 8, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // c0..df - 0xa, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x4, 0x3, 0x3, // e0..ef - 0xb, 0x6, 0x6, 0x6, 0x5, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, // f0..ff + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 00..1F + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 20..3F + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 40..5F + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 60..7F + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, // 80..9F + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // A0..BF + 8, 8, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // C0..DF + 0xA, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x4, 0x3, 0x3, // E0..EF + 0xB, 0x6, 0x6, 0x6, 0x5, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, // F0..FF 0x0, 0x1, 0x2, 0x3, 0x5, 0x8, 0x7, 0x1, 0x1, 0x1, 0x4, 0x6, 0x1, 0x1, 0x1, 0x1, // s0..s0 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, // s1..s2 1, 2, 1, 1, 1, 1, 1, 2, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, // s3..s4 @@ -6868,27 +6844,20 @@ class json_ref using value_type = BasicJsonType; json_ref(value_type&& value) - : owned_value(std::move(value)), - value_ref(&owned_value), - is_rvalue(true) + : owned_value(std::move(value)), value_ref(&owned_value), is_rvalue(true) {} json_ref(const value_type& value) - : value_ref(const_cast(&value)), - is_rvalue(false) + : value_ref(const_cast(&value)), is_rvalue(false) {} json_ref(std::initializer_list init) - : owned_value(init), - value_ref(&owned_value), - is_rvalue(true) + : owned_value(init), value_ref(&owned_value), is_rvalue(true) {} - template + template json_ref(Args&& ... args) - : owned_value(std::forward(args)...), - value_ref(&owned_value), - is_rvalue(true) + : owned_value(std::forward(args)...), value_ref(&owned_value), is_rvalue(true) {} // class should be movable only @@ -7417,11 +7386,11 @@ class basic_json public: using value_t = detail::value_t; - // forward declarations + /// @copydoc nlohmann::json_pointer using json_pointer = ::nlohmann::json_pointer; template using json_serializer = JSONSerializer; - + /// helper type for initializer lists of basic_json values using initializer_list_t = std::initializer_list>; //////////////// @@ -7586,6 +7555,14 @@ class basic_json /// the template arguments passed to class @ref basic_json. /// @{ +#if defined(JSON_HAS_CPP_14) + // Use transparent comparator if possible, combined with perfect forwarding + // on find() and count() calls prevents unnecessary string construction. + using object_comparator_t = std::less<>; +#else + using object_comparator_t = std::less; +#endif + /*! @brief a type for an object @@ -7669,14 +7646,6 @@ class basic_json 7159](http://rfc7159.net/rfc7159), because any order implements the specified "unordered" nature of JSON objects. */ - -#if defined(JSON_HAS_CPP_14) - // Use transparent comparator if possible, combined with perfect forwarding - // on find() and count() calls prevents unnecessary string construction. - using object_comparator_t = std::less<>; -#else - using object_comparator_t = std::less; -#endif using object_t = ObjectType::type, - basic_json_t>::value, - int> = 0 > + template::type, basic_json_t>::value, + int> = 0> basic_json get() const { return *this; @@ -9656,14 +9641,12 @@ class basic_json @since version 2.1.0 */ - template < - typename ValueTypeCV, - typename ValueType = detail::uncvref_t, - detail::enable_if_t < - not std::is_same::value and - detail::has_from_json::value and - not detail::has_non_default_from_json::value, - int > = 0 > + template, + detail::enable_if_t < + not std::is_same::value and + detail::has_from_json::value and + not detail::has_non_default_from_json::value, + int> = 0> ValueType get() const noexcept(noexcept( JSONSerializer::from_json(std::declval(), std::declval()))) { @@ -9711,12 +9694,10 @@ class basic_json @since version 2.1.0 */ - template < - typename ValueTypeCV, - typename ValueType = detail::uncvref_t, - detail::enable_if_t::value and - detail::has_non_default_from_json::value, int> = 0 > + template, + detail::enable_if_t::value and + detail::has_non_default_from_json::value, + int> = 0> ValueType get() const noexcept(noexcept( JSONSerializer::from_json(std::declval()))) { @@ -10210,7 +10191,7 @@ class basic_json @return const reference to the element at index @a idx - @throw type_error.305 if the JSON value is not an array; in that cases, + @throw type_error.305 if the JSON value is not an array; in that case, using the [] operator with an index makes no sense. @complexity Constant. @@ -10293,7 +10274,7 @@ class basic_json @pre The element with key @a key must exist. **This precondition is enforced with an assertion.** - @throw type_error.305 if the JSON value is not an object; in that cases, + @throw type_error.305 if the JSON value is not an object; in that case, using the [] operator with a key makes no sense. @complexity Logarithmic in the size of the container. @@ -10382,7 +10363,7 @@ class basic_json @pre The element with key @a key must exist. **This precondition is enforced with an assertion.** - @throw type_error.305 if the JSON value is not an object; in that cases, + @throw type_error.305 if the JSON value is not an object; in that case, using the [] operator with a key makes no sense. @complexity Logarithmic in the size of the container. @@ -10442,7 +10423,7 @@ class basic_json @return copy of the element at key @a key or @a default_value if @a key is not found - @throw type_error.306 if the JSON value is not an object; in that cases, + @throw type_error.306 if the JSON value is not an object; in that case, using `value()` with a key makes no sense. @complexity Logarithmic in the size of the container. @@ -10515,7 +10496,7 @@ class basic_json @return copy of the element at key @a key or @a default_value if @a key is not found - @throw type_error.306 if the JSON value is not an objec; in that cases, + @throw type_error.306 if the JSON value is not an objec; in that case, using `value()` with a key makes no sense. @complexity Logarithmic in the size of the container. @@ -12441,7 +12422,7 @@ class basic_json [comparison function](https://github.com/mariokonrad/marnav/blob/master/src/marnav/math/floatingpoint.hpp#L34-#L39) could be used, for instance @code {.cpp} - template ::value, T>::type> + template::value, T>::type> inline bool is_same(T a, T b, T epsilon = std::numeric_limits::epsilon()) noexcept { return std::abs(a - b) <= epsilon; @@ -12879,6 +12860,9 @@ class basic_json @return the stream @a o + @throw type_error.316 if a string stored inside the JSON value is not + UTF-8 encoded + @complexity Linear. @liveexample{The example below shows the serialization with different @@ -13224,40 +13208,40 @@ class basic_json JSON value type | value/range | CBOR type | first byte --------------- | ------------------------------------------ | ---------------------------------- | --------------- - null | `null` | Null | 0xf6 - boolean | `true` | True | 0xf5 - boolean | `false` | False | 0xf4 - number_integer | -9223372036854775808..-2147483649 | Negative integer (8 bytes follow) | 0x3b - number_integer | -2147483648..-32769 | Negative integer (4 bytes follow) | 0x3a + null | `null` | Null | 0xF6 + boolean | `true` | True | 0xF5 + boolean | `false` | False | 0xF4 + number_integer | -9223372036854775808..-2147483649 | Negative integer (8 bytes follow) | 0x3B + number_integer | -2147483648..-32769 | Negative integer (4 bytes follow) | 0x3A number_integer | -32768..-129 | Negative integer (2 bytes follow) | 0x39 number_integer | -128..-25 | Negative integer (1 byte follow) | 0x38 number_integer | -24..-1 | Negative integer | 0x20..0x37 number_integer | 0..23 | Integer | 0x00..0x17 number_integer | 24..255 | Unsigned integer (1 byte follow) | 0x18 number_integer | 256..65535 | Unsigned integer (2 bytes follow) | 0x19 - number_integer | 65536..4294967295 | Unsigned integer (4 bytes follow) | 0x1a - number_integer | 4294967296..18446744073709551615 | Unsigned integer (8 bytes follow) | 0x1b + number_integer | 65536..4294967295 | Unsigned integer (4 bytes follow) | 0x1A + number_integer | 4294967296..18446744073709551615 | Unsigned integer (8 bytes follow) | 0x1B number_unsigned | 0..23 | Integer | 0x00..0x17 number_unsigned | 24..255 | Unsigned integer (1 byte follow) | 0x18 number_unsigned | 256..65535 | Unsigned integer (2 bytes follow) | 0x19 - number_unsigned | 65536..4294967295 | Unsigned integer (4 bytes follow) | 0x1a - number_unsigned | 4294967296..18446744073709551615 | Unsigned integer (8 bytes follow) | 0x1b - number_float | *any value* | Double-Precision Float | 0xfb + number_unsigned | 65536..4294967295 | Unsigned integer (4 bytes follow) | 0x1A + number_unsigned | 4294967296..18446744073709551615 | Unsigned integer (8 bytes follow) | 0x1B + number_float | *any value* | Double-Precision Float | 0xFB string | *length*: 0..23 | UTF-8 string | 0x60..0x77 string | *length*: 23..255 | UTF-8 string (1 byte follow) | 0x78 string | *length*: 256..65535 | UTF-8 string (2 bytes follow) | 0x79 - string | *length*: 65536..4294967295 | UTF-8 string (4 bytes follow) | 0x7a - string | *length*: 4294967296..18446744073709551615 | UTF-8 string (8 bytes follow) | 0x7b + string | *length*: 65536..4294967295 | UTF-8 string (4 bytes follow) | 0x7A + string | *length*: 4294967296..18446744073709551615 | UTF-8 string (8 bytes follow) | 0x7B array | *size*: 0..23 | array | 0x80..0x97 array | *size*: 23..255 | array (1 byte follow) | 0x98 array | *size*: 256..65535 | array (2 bytes follow) | 0x99 - array | *size*: 65536..4294967295 | array (4 bytes follow) | 0x9a - array | *size*: 4294967296..18446744073709551615 | array (8 bytes follow) | 0x9b - object | *size*: 0..23 | map | 0xa0..0xb7 - object | *size*: 23..255 | map (1 byte follow) | 0xb8 - object | *size*: 256..65535 | map (2 bytes follow) | 0xb9 - object | *size*: 65536..4294967295 | map (4 bytes follow) | 0xba - object | *size*: 4294967296..18446744073709551615 | map (8 bytes follow) | 0xbb + array | *size*: 65536..4294967295 | array (4 bytes follow) | 0x9A + array | *size*: 4294967296..18446744073709551615 | array (8 bytes follow) | 0x9B + object | *size*: 0..23 | map | 0xA0..0xB7 + object | *size*: 23..255 | map (1 byte follow) | 0xB8 + object | *size*: 256..65535 | map (2 bytes follow) | 0xB9 + object | *size*: 65536..4294967295 | map (4 bytes follow) | 0xBA + object | *size*: 4294967296..18446744073709551615 | map (8 bytes follow) | 0xBB @note The mapping is **complete** in the sense that any JSON value type can be converted to a CBOR value. @@ -13267,20 +13251,20 @@ class basic_json function which serializes NaN or Infinity to `null`. @note The following CBOR types are not used in the conversion: - - byte strings (0x40..0x5f) - - UTF-8 strings terminated by "break" (0x7f) - - arrays terminated by "break" (0x9f) - - maps terminated by "break" (0xbf) - - date/time (0xc0..0xc1) - - bignum (0xc2..0xc3) - - decimal fraction (0xc4) - - bigfloat (0xc5) - - tagged items (0xc6..0xd4, 0xd8..0xdb) - - expected conversions (0xd5..0xd7) - - simple values (0xe0..0xf3, 0xf8) - - undefined (0xf7) - - half and single-precision floats (0xf9-0xfa) - - break (0xff) + - byte strings (0x40..0x5F) + - UTF-8 strings terminated by "break" (0x7F) + - arrays terminated by "break" (0x9F) + - maps terminated by "break" (0xBF) + - date/time (0xC0..0xC1) + - bignum (0xC2..0xC3) + - decimal fraction (0xC4) + - bigfloat (0xC5) + - tagged items (0xC6..0xD4, 0xD8..0xDB) + - expected conversions (0xD5..0xD7) + - simple values (0xE0..0xF3, 0xF8) + - undefined (0xF7) + - half and single-precision floats (0xF9-0xFA) + - break (0xFF) @param[in] j JSON value to serialize @return MessagePack serialization as byte vector @@ -13326,35 +13310,35 @@ class basic_json JSON value type | value/range | MessagePack type | first byte --------------- | --------------------------------- | ---------------- | ---------- - null | `null` | nil | 0xc0 - boolean | `true` | true | 0xc3 - boolean | `false` | false | 0xc2 - number_integer | -9223372036854775808..-2147483649 | int64 | 0xd3 - number_integer | -2147483648..-32769 | int32 | 0xd2 - number_integer | -32768..-129 | int16 | 0xd1 - number_integer | -128..-33 | int8 | 0xd0 - number_integer | -32..-1 | negative fixint | 0xe0..0xff - number_integer | 0..127 | positive fixint | 0x00..0x7f - number_integer | 128..255 | uint 8 | 0xcc - number_integer | 256..65535 | uint 16 | 0xcd - number_integer | 65536..4294967295 | uint 32 | 0xce - number_integer | 4294967296..18446744073709551615 | uint 64 | 0xcf - number_unsigned | 0..127 | positive fixint | 0x00..0x7f - number_unsigned | 128..255 | uint 8 | 0xcc - number_unsigned | 256..65535 | uint 16 | 0xcd - number_unsigned | 65536..4294967295 | uint 32 | 0xce - number_unsigned | 4294967296..18446744073709551615 | uint 64 | 0xcf - number_float | *any value* | float 64 | 0xcb - string | *length*: 0..31 | fixstr | 0xa0..0xbf - string | *length*: 32..255 | str 8 | 0xd9 - string | *length*: 256..65535 | str 16 | 0xda - string | *length*: 65536..4294967295 | str 32 | 0xdb - array | *size*: 0..15 | fixarray | 0x90..0x9f - array | *size*: 16..65535 | array 16 | 0xdc - array | *size*: 65536..4294967295 | array 32 | 0xdd - object | *size*: 0..15 | fix map | 0x80..0x8f - object | *size*: 16..65535 | map 16 | 0xde - object | *size*: 65536..4294967295 | map 32 | 0xdf + null | `null` | nil | 0xC0 + boolean | `true` | true | 0xC3 + boolean | `false` | false | 0xC2 + number_integer | -9223372036854775808..-2147483649 | int64 | 0xD3 + number_integer | -2147483648..-32769 | int32 | 0xD2 + number_integer | -32768..-129 | int16 | 0xD1 + number_integer | -128..-33 | int8 | 0xD0 + number_integer | -32..-1 | negative fixint | 0xE0..0xFF + number_integer | 0..127 | positive fixint | 0x00..0x7F + number_integer | 128..255 | uint 8 | 0xCC + number_integer | 256..65535 | uint 16 | 0xCD + number_integer | 65536..4294967295 | uint 32 | 0xCE + number_integer | 4294967296..18446744073709551615 | uint 64 | 0xCF + number_unsigned | 0..127 | positive fixint | 0x00..0x7F + number_unsigned | 128..255 | uint 8 | 0xCC + number_unsigned | 256..65535 | uint 16 | 0xCD + number_unsigned | 65536..4294967295 | uint 32 | 0xCE + number_unsigned | 4294967296..18446744073709551615 | uint 64 | 0xCF + number_float | *any value* | float 64 | 0xCB + string | *length*: 0..31 | fixstr | 0xA0..0xBF + string | *length*: 32..255 | str 8 | 0xD9 + string | *length*: 256..65535 | str 16 | 0xDA + string | *length*: 65536..4294967295 | str 32 | 0xDB + array | *size*: 0..15 | fixarray | 0x90..0x9F + array | *size*: 16..65535 | array 16 | 0xDC + array | *size*: 65536..4294967295 | array 32 | 0xDD + object | *size*: 0..15 | fix map | 0x80..0x8F + object | *size*: 16..65535 | map 16 | 0xDE + object | *size*: 65536..4294967295 | map 32 | 0xDF @note The mapping is **complete** in the sense that any JSON value type can be converted to a MessagePack value. @@ -13365,10 +13349,10 @@ class basic_json - objects with more than 4294967295 elements @note The following MessagePack types are not used in the conversion: - - bin 8 - bin 32 (0xc4..0xc6) - - ext 8 - ext 32 (0xc7..0xc9) - - float 32 (0xca) - - fixext 1 - fixext 16 (0xd4..0xd8) + - bin 8 - bin 32 (0xC4..0xC6) + - ext 8 - ext 32 (0xC7..0xC9) + - float 32 (0xCA) + - fixext 1 - fixext 16 (0xD4..0xD8) @note Any MessagePack output created @ref to_msgpack can be successfully parsed by @ref from_msgpack. @@ -13422,51 +13406,51 @@ class basic_json Integer | number_unsigned | 0x00..0x17 Unsigned integer | number_unsigned | 0x18 Unsigned integer | number_unsigned | 0x19 - Unsigned integer | number_unsigned | 0x1a - Unsigned integer | number_unsigned | 0x1b + Unsigned integer | number_unsigned | 0x1A + Unsigned integer | number_unsigned | 0x1B Negative integer | number_integer | 0x20..0x37 Negative integer | number_integer | 0x38 Negative integer | number_integer | 0x39 - Negative integer | number_integer | 0x3a - Negative integer | number_integer | 0x3b + Negative integer | number_integer | 0x3A + Negative integer | number_integer | 0x3B Negative integer | number_integer | 0x40..0x57 UTF-8 string | string | 0x60..0x77 UTF-8 string | string | 0x78 UTF-8 string | string | 0x79 - UTF-8 string | string | 0x7a - UTF-8 string | string | 0x7b - UTF-8 string | string | 0x7f + UTF-8 string | string | 0x7A + UTF-8 string | string | 0x7B + UTF-8 string | string | 0x7F array | array | 0x80..0x97 array | array | 0x98 array | array | 0x99 - array | array | 0x9a - array | array | 0x9b - array | array | 0x9f - map | object | 0xa0..0xb7 - map | object | 0xb8 - map | object | 0xb9 - map | object | 0xba - map | object | 0xbb - map | object | 0xbf - False | `false` | 0xf4 - True | `true` | 0xf5 - Nill | `null` | 0xf6 - Half-Precision Float | number_float | 0xf9 - Single-Precision Float | number_float | 0xfa - Double-Precision Float | number_float | 0xfb + array | array | 0x9A + array | array | 0x9B + array | array | 0x9F + map | object | 0xA0..0xB7 + map | object | 0xB8 + map | object | 0xB9 + map | object | 0xBA + map | object | 0xBB + map | object | 0xBF + False | `false` | 0xF4 + True | `true` | 0xF5 + Nill | `null` | 0xF6 + Half-Precision Float | number_float | 0xF9 + Single-Precision Float | number_float | 0xFA + Double-Precision Float | number_float | 0xFB @warning The mapping is **incomplete** in the sense that not all CBOR types can be converted to a JSON value. The following CBOR types are not supported and will yield parse errors (parse_error.112): - - byte strings (0x40..0x5f) - - date/time (0xc0..0xc1) - - bignum (0xc2..0xc3) - - decimal fraction (0xc4) - - bigfloat (0xc5) - - tagged items (0xc6..0xd4, 0xd8..0xdb) - - expected conversions (0xd5..0xd7) - - simple values (0xe0..0xf3, 0xf8) - - undefined (0xf7) + - byte strings (0x40..0x5F) + - date/time (0xC0..0xC1) + - bignum (0xC2..0xC3) + - decimal fraction (0xC4) + - bigfloat (0xC5) + - tagged items (0xC6..0xD4, 0xD8..0xDB) + - expected conversions (0xD5..0xD7) + - simple values (0xE0..0xF3, 0xF8) + - undefined (0xF7) @warning CBOR allows map keys of any type, whereas JSON only allows strings as keys in object values. Therefore, CBOR maps with keys @@ -13526,38 +13510,38 @@ class basic_json MessagePack type | JSON value type | first byte ---------------- | --------------- | ---------- - positive fixint | number_unsigned | 0x00..0x7f - fixmap | object | 0x80..0x8f - fixarray | array | 0x90..0x9f - fixstr | string | 0xa0..0xbf - nil | `null` | 0xc0 - false | `false` | 0xc2 - true | `true` | 0xc3 - float 32 | number_float | 0xca - float 64 | number_float | 0xcb - uint 8 | number_unsigned | 0xcc - uint 16 | number_unsigned | 0xcd - uint 32 | number_unsigned | 0xce - uint 64 | number_unsigned | 0xcf - int 8 | number_integer | 0xd0 - int 16 | number_integer | 0xd1 - int 32 | number_integer | 0xd2 - int 64 | number_integer | 0xd3 - str 8 | string | 0xd9 - str 16 | string | 0xda - str 32 | string | 0xdb - array 16 | array | 0xdc - array 32 | array | 0xdd - map 16 | object | 0xde - map 32 | object | 0xdf - negative fixint | number_integer | 0xe0-0xff + positive fixint | number_unsigned | 0x00..0x7F + fixmap | object | 0x80..0x8F + fixarray | array | 0x90..0x9F + fixstr | string | 0xA0..0xBF + nil | `null` | 0xC0 + false | `false` | 0xC2 + true | `true` | 0xC3 + float 32 | number_float | 0xCA + float 64 | number_float | 0xCB + uint 8 | number_unsigned | 0xCC + uint 16 | number_unsigned | 0xCD + uint 32 | number_unsigned | 0xCE + uint 64 | number_unsigned | 0xCF + int 8 | number_integer | 0xD0 + int 16 | number_integer | 0xD1 + int 32 | number_integer | 0xD2 + int 64 | number_integer | 0xD3 + str 8 | string | 0xD9 + str 16 | string | 0xDA + str 32 | string | 0xDB + array 16 | array | 0xDC + array 32 | array | 0xDD + map 16 | object | 0xDE + map 32 | object | 0xDF + negative fixint | number_integer | 0xE0-0xFF @warning The mapping is **incomplete** in the sense that not all MessagePack types can be converted to a JSON value. The following MessagePack types are not supported and will yield parse errors: - - bin 8 - bin 32 (0xc4..0xc6) - - ext 8 - ext 32 (0xc7..0xc9) - - fixext 1 - fixext 16 (0xd4..0xd8) + - bin 8 - bin 32 (0xC4..0xC6) + - ext 8 - ext 32 (0xC7..0xC9) + - fixext 1 - fixext 16 (0xD4..0xD8) @note Any MessagePack output created @ref to_msgpack can be successfully parsed by @ref from_msgpack. From 293748a9a92126e5e3b054699fd1f40dc75a9d9c Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Wed, 13 Dec 2017 22:17:02 +0100 Subject: [PATCH 2/6] :memo: overworked README - Added recent contributors to thanks list. - Linked PGP key for private mails. - Updated compiler list. --- README.md | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 89ccb5a74..54f73a8db 100644 --- a/README.md +++ b/README.md @@ -741,11 +741,11 @@ json j_from_msgpack = json::from_msgpack(v_msgpack); Though it's 2016 already, the support for C++11 is still a bit sparse. Currently, the following compilers are known to work: -- GCC 4.9 - 7.1 (and possibly later) +- GCC 4.9 - 7.2 (and possibly later) - Clang 3.4 - 5.0 (and possibly later) - Intel C++ Compiler 17.0.2 (and possibly later) - Microsoft Visual C++ 2015 / Build Tools 14.0.25123.0 (and possibly later) -- Microsoft Visual C++ 2017 / Build Tools 15.1.548.43366 (and possibly later) +- Microsoft Visual C++ 2017 / Build Tools 15.5.180.51428 (and possibly later) I would be happy to learn about other compilers/versions. @@ -785,9 +785,11 @@ The following compilers are currently used in continuous integration at [Travis] | Clang Xcode 8.1 | Darwin Kernel Version 16.1.0 (macOS 10.12.1) | Apple LLVM version 8.0.0 (clang-800.0.42.1) | | Clang Xcode 8.2 | Darwin Kernel Version 16.1.0 (macOS 10.12.1) | Apple LLVM version 8.0.0 (clang-800.0.42.1) | | Clang Xcode 8.3 | Darwin Kernel Version 16.5.0 (macOS 10.12.4) | Apple LLVM version 8.1.0 (clang-802.0.38) | -| Clang Xcode 9 beta | Darwin Kernel Version 16.6.0 (macOS 10.12.5) | Apple LLVM version 9.0.0 (clang-900.0.26) | -| Visual Studio 14 2015 | Windows Server 2012 R2 (x64) | Microsoft (R) Build Engine version 14.0.25420.1 | -| Visual Studio 2017 | Windows Server 2016 | Microsoft (R) Build Engine version 15.1.1012.6693 | +| Clang Xcode 9.0 | Darwin Kernel Version 16.7.0 (macOS 10.12.6) | Apple LLVM version 9.0.0 (clang-900.0.37) | +| Clang Xcode 9.1 | Darwin Kernel Version 16.7.0 (macOS 10.12.6) | Apple LLVM version 9.0.0 (clang-900.0.38) | +| Clang Xcode 9.2 | Darwin Kernel Version 16.7.0 (macOS 10.12.6) | Apple LLVM version 8.1.0 (clang-900.0.39.2) | +| Visual Studio 14 2015 | Windows Server 2012 R2 (x64) | Microsoft (R) Build Engine version 14.0.25420.1, MSVC 19.0.24215.1 | +| Visual Studio 2017 | Windows Server 2016 | Microsoft (R) Build Engine version 15.5.180.51428, MSVC 19.12.25830.2 | ## License @@ -805,13 +807,13 @@ THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR I * * * -The class contains the UTF-8 Decoder from Bjoern Hoehrmann which is licensed under the [MIT License](http://opensource.org/licenses/MIT) (see above). Copyright © 2008-2009 [Bjoern Hoehrmann](http://bjoern.hoehrmann.de/) +The class contains the UTF-8 Decoder from Bjoern Hoehrmann which is licensed under the [MIT License](http://opensource.org/licenses/MIT) (see above). Copyright © 2008-2009 [Björn Hoehrmann](http://bjoern.hoehrmann.de/) ## Contact If you have questions regarding the library, I would like to invite you to [open an issue at Github](https://github.com/nlohmann/json/issues/new). Please describe your request, problem, or question as detailed as possible, and also mention the version of the library you are using as well as the version of your compiler and operating system. Opening an issue at Github allows other users and contributors to this library to collaborate. For instance, I have little experience with MSVC, and most issues in this regard have been solved by a growing community. If you have a look at the [closed issues](https://github.com/nlohmann/json/issues?q=is%3Aissue+is%3Aclosed), you will see that we react quite timely in most cases. -Only if your request would contain confidential information, please [send me an email](mailto:mail@nlohmann.me). +Only if your request would contain confidential information, please [send me an email](mailto:mail@nlohmann.me). For encrypted messages, please usse [this key](https://keybase.io/nlohmann/pgp_keys.asc). ## Thanks @@ -910,6 +912,9 @@ I deeply appreciate the help of the following people. - [Pavel](https://github.com/crea7or) helped fixing some warnings in MSVC. - [Jamie Seward](https://github.com/jseward) avoided unneccessary string copies in `find()` and `count()`. - [Mitja](https://github.com/Itja) fixed some typos. +- [Jorrit Wronski](https://github.com/jowr) updated the Hunter package links. +- [Matthias Möller](https://github.com/TinyTinni) added a `.natvis` for the MSVC debug view. +- [bogemic](https://github.com/bogemic) fixed some C++17 deprecation warnings. Thanks a lot for helping out! Please [let me know](mailto:mail@nlohmann.me) if I forgot someone. @@ -954,7 +959,7 @@ The library is currently used in Apple macOS Sierra and iOS 10. I am not sure wh - As the exact type of a number is not defined in the [JSON specification](http://rfc7159.net/rfc7159), this library tries to choose the best fitting C++ number type automatically. As a result, the type `double` may be used to store numbers which may yield [**floating-point exceptions**](https://github.com/nlohmann/json/issues/181) in certain rare situations if floating-point exceptions have been unmasked in the calling code. These exceptions are not caused by the library and need to be fixed in the calling code, such as by re-masking the exceptions prior to calling library functions. - The library supports **Unicode input** as follows: - Only **UTF-8** encoded input is supported which is the default encoding for JSON according to [RFC 7159](http://rfc7159.net/rfc7159#rfc.section.8.1). - - Other encodings such as Latin-1, UTF-16, or UTF-32 are not supported and will yield parse errors. + - Other encodings such as Latin-1, UTF-16, or UTF-32 are not supported and will yield parse or serialization errors. - [Unicode noncharacters](http://www.unicode.org/faq/private_use.html#nonchar1) will not be replaced by the library. - Invalid surrogates (e.g., incomplete pairs such as `\uDEAD`) will yield parse errors. - The strings stored in the library are UTF-8 encoded. When using the default string type (`std::string`), note that its length/size functions return the number of stored bytes rather than the number of characters or glyphs. From 920f64c01c126e0664b3b1905c3f60872bd518cd Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Wed, 13 Dec 2017 22:18:05 +0100 Subject: [PATCH 3/6] :arrow_up: updated to Catch 2.0.1 Update required all CHECK_THROWS_AS macros to pass the exception type without reference, because this is now done by Catch2. --- test/src/unit-algorithms.cpp | 2 +- test/src/unit-allocator.cpp | 22 +- test/src/unit-cbor.cpp | 47 +- test/src/unit-class_const_iterator.cpp | 8 +- test/src/unit-class_iterator.cpp | 8 +- test/src/unit-class_parser.cpp | 240 +- test/src/unit-constructor1.cpp | 63 +- test/src/unit-conversions.cpp | 95 +- test/src/unit-deserialization.cpp | 62 +- test/src/unit-element_access1.cpp | 166 +- test/src/unit-element_access2.cpp | 168 +- test/src/unit-iterators1.cpp | 80 +- test/src/unit-iterators2.cpp | 232 +- test/src/unit-json_patch.cpp | 78 +- test/src/unit-json_pointer.cpp | 58 +- test/src/unit-modifiers.cpp | 70 +- test/src/unit-msgpack.cpp | 42 +- test/src/unit-readme.cpp | 1 + test/src/unit-reference_access.cpp | 84 +- test/src/unit-regression.cpp | 84 +- test/src/unit-testsuites.cpp | 8 +- test/src/unit-unicode.cpp | 26 +- test/thirdparty/catch/catch.hpp | 18000 ++++++++++++----------- 23 files changed, 10021 insertions(+), 9623 deletions(-) diff --git a/test/src/unit-algorithms.cpp b/test/src/unit-algorithms.cpp index bc108dcdd..6136fefa5 100644 --- a/test/src/unit-algorithms.cpp +++ b/test/src/unit-algorithms.cpp @@ -240,7 +240,7 @@ TEST_CASE("algorithms") SECTION("sorting an object") { json j({{"one", 1}, {"two", 2}}); - CHECK_THROWS_AS(std::sort(j.begin(), j.end()), json::invalid_iterator&); + CHECK_THROWS_AS(std::sort(j.begin(), j.end()), json::invalid_iterator); CHECK_THROWS_WITH(std::sort(j.begin(), j.end()), "[json.exception.invalid_iterator.209] cannot use offsets with object iterators"); } diff --git a/test/src/unit-allocator.cpp b/test/src/unit-allocator.cpp index d2423a487..903d5950a 100644 --- a/test/src/unit-allocator.cpp +++ b/test/src/unit-allocator.cpp @@ -59,7 +59,7 @@ TEST_CASE("bad_alloc") bad_allocator>; // creating an object should throw - CHECK_THROWS_AS(bad_json(bad_json::value_t::object), std::bad_alloc&); + CHECK_THROWS_AS(bad_json(bad_json::value_t::object), std::bad_alloc); } } @@ -143,7 +143,7 @@ TEST_CASE("controlled bad_alloc") auto t = my_json::value_t::object; CHECK_NOTHROW(my_allocator_clean_up(my_json::json_value(t).object)); next_construct_fails = true; - CHECK_THROWS_AS(my_json::json_value(t), std::bad_alloc&); + CHECK_THROWS_AS(my_json::json_value(t), std::bad_alloc); next_construct_fails = false; } SECTION("array") @@ -152,7 +152,7 @@ TEST_CASE("controlled bad_alloc") auto t = my_json::value_t::array; CHECK_NOTHROW(my_allocator_clean_up(my_json::json_value(t).array)); next_construct_fails = true; - CHECK_THROWS_AS(my_json::json_value(t), std::bad_alloc&); + CHECK_THROWS_AS(my_json::json_value(t), std::bad_alloc); next_construct_fails = false; } SECTION("string") @@ -161,7 +161,7 @@ TEST_CASE("controlled bad_alloc") auto t = my_json::value_t::string; CHECK_NOTHROW(my_allocator_clean_up(my_json::json_value(t).string)); next_construct_fails = true; - CHECK_THROWS_AS(my_json::json_value(t), std::bad_alloc&); + CHECK_THROWS_AS(my_json::json_value(t), std::bad_alloc); next_construct_fails = false; } } @@ -172,7 +172,7 @@ TEST_CASE("controlled bad_alloc") my_json::string_t v("foo"); CHECK_NOTHROW(my_allocator_clean_up(my_json::json_value(v).string)); next_construct_fails = true; - CHECK_THROWS_AS(my_json::json_value(v), std::bad_alloc&); + CHECK_THROWS_AS(my_json::json_value(v), std::bad_alloc); next_construct_fails = false; } @@ -183,7 +183,7 @@ TEST_CASE("controlled bad_alloc") my_json::object_t v {{"foo", "bar"}}; CHECK_NOTHROW(my_json::json_value j(v)); next_construct_fails = true; - CHECK_THROWS_AS(my_json::json_value j(v), std::bad_alloc&); + CHECK_THROWS_AS(my_json::json_value j(v), std::bad_alloc); next_construct_fails = false; } */ @@ -194,7 +194,7 @@ TEST_CASE("controlled bad_alloc") my_json::array_t v = {"foo", "bar", "baz"}; CHECK_NOTHROW(my_json::json_value j(v)); next_construct_fails = true; - CHECK_THROWS_AS(my_json::json_value j(v), std::bad_alloc&); + CHECK_THROWS_AS(my_json::json_value j(v), std::bad_alloc); next_construct_fails = false; } */ @@ -208,7 +208,7 @@ TEST_CASE("controlled bad_alloc") std::map v {{"foo", "bar"}}; CHECK_NOTHROW(my_json(v)); next_construct_fails = true; - CHECK_THROWS_AS(my_json(v), std::bad_alloc&); + CHECK_THROWS_AS(my_json(v), std::bad_alloc); next_construct_fails = false; } @@ -218,7 +218,7 @@ TEST_CASE("controlled bad_alloc") std::vector v {"foo", "bar", "baz"}; CHECK_NOTHROW(my_json(v)); next_construct_fails = true; - CHECK_THROWS_AS(my_json(v), std::bad_alloc&); + CHECK_THROWS_AS(my_json(v), std::bad_alloc); next_construct_fails = false; } @@ -227,7 +227,7 @@ TEST_CASE("controlled bad_alloc") next_construct_fails = false; CHECK_NOTHROW(my_json("foo")); next_construct_fails = true; - CHECK_THROWS_AS(my_json("foo"), std::bad_alloc&); + CHECK_THROWS_AS(my_json("foo"), std::bad_alloc); next_construct_fails = false; } @@ -237,7 +237,7 @@ TEST_CASE("controlled bad_alloc") std::string s("foo"); CHECK_NOTHROW(my_json(s)); next_construct_fails = true; - CHECK_THROWS_AS(my_json(s), std::bad_alloc&); + CHECK_THROWS_AS(my_json(s), std::bad_alloc); next_construct_fails = false; } } diff --git a/test/src/unit-cbor.cpp b/test/src/unit-cbor.cpp index 8d28f6867..330b7ca19 100644 --- a/test/src/unit-cbor.cpp +++ b/test/src/unit-cbor.cpp @@ -31,6 +31,7 @@ SOFTWARE. #include "json.hpp" using nlohmann::json; +#include #include TEST_CASE("CBOR") @@ -739,13 +740,13 @@ TEST_CASE("CBOR") { SECTION("no byte follows") { - CHECK_THROWS_AS(json::from_cbor(std::vector({0xf9})), json::parse_error&); + CHECK_THROWS_AS(json::from_cbor(std::vector({0xf9})), json::parse_error); CHECK_THROWS_WITH(json::from_cbor(std::vector({0xf9})), "[json.exception.parse_error.110] parse error at 2: unexpected end of input"); } SECTION("only one byte follows") { - CHECK_THROWS_AS(json::from_cbor(std::vector({0xf9, 0x7c})), json::parse_error&); + CHECK_THROWS_AS(json::from_cbor(std::vector({0xf9, 0x7c})), json::parse_error); CHECK_THROWS_WITH(json::from_cbor(std::vector({0xf9, 0x7c})), "[json.exception.parse_error.110] parse error at 3: unexpected end of input"); } @@ -1226,28 +1227,28 @@ TEST_CASE("CBOR") { SECTION("empty byte vector") { - CHECK_THROWS_AS(json::from_cbor(std::vector()), json::parse_error&); + CHECK_THROWS_AS(json::from_cbor(std::vector()), json::parse_error); CHECK_THROWS_WITH(json::from_cbor(std::vector()), "[json.exception.parse_error.110] parse error at 1: unexpected end of input"); } SECTION("too short byte vector") { - CHECK_THROWS_AS(json::from_cbor(std::vector({0x18})), json::parse_error&); - CHECK_THROWS_AS(json::from_cbor(std::vector({0x19})), json::parse_error&); - CHECK_THROWS_AS(json::from_cbor(std::vector({0x19, 0x00})), json::parse_error&); - CHECK_THROWS_AS(json::from_cbor(std::vector({0x1a})), json::parse_error&); - CHECK_THROWS_AS(json::from_cbor(std::vector({0x1a, 0x00})), json::parse_error&); - CHECK_THROWS_AS(json::from_cbor(std::vector({0x1a, 0x00, 0x00})), json::parse_error&); - CHECK_THROWS_AS(json::from_cbor(std::vector({0x1a, 0x00, 0x00, 0x00})), json::parse_error&); - CHECK_THROWS_AS(json::from_cbor(std::vector({0x1b})), json::parse_error&); - CHECK_THROWS_AS(json::from_cbor(std::vector({0x1b, 0x00})), json::parse_error&); - CHECK_THROWS_AS(json::from_cbor(std::vector({0x1b, 0x00, 0x00})), json::parse_error&); - CHECK_THROWS_AS(json::from_cbor(std::vector({0x1b, 0x00, 0x00, 0x00})), json::parse_error&); - CHECK_THROWS_AS(json::from_cbor(std::vector({0x1b, 0x00, 0x00, 0x00, 0x00})), json::parse_error&); - CHECK_THROWS_AS(json::from_cbor(std::vector({0x1b, 0x00, 0x00, 0x00, 0x00, 0x00})), json::parse_error&); - CHECK_THROWS_AS(json::from_cbor(std::vector({0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00})), json::parse_error&); - CHECK_THROWS_AS(json::from_cbor(std::vector({0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00})), json::parse_error&); + CHECK_THROWS_AS(json::from_cbor(std::vector({0x18})), json::parse_error); + CHECK_THROWS_AS(json::from_cbor(std::vector({0x19})), json::parse_error); + CHECK_THROWS_AS(json::from_cbor(std::vector({0x19, 0x00})), json::parse_error); + CHECK_THROWS_AS(json::from_cbor(std::vector({0x1a})), json::parse_error); + CHECK_THROWS_AS(json::from_cbor(std::vector({0x1a, 0x00})), json::parse_error); + CHECK_THROWS_AS(json::from_cbor(std::vector({0x1a, 0x00, 0x00})), json::parse_error); + CHECK_THROWS_AS(json::from_cbor(std::vector({0x1a, 0x00, 0x00, 0x00})), json::parse_error); + CHECK_THROWS_AS(json::from_cbor(std::vector({0x1b})), json::parse_error); + CHECK_THROWS_AS(json::from_cbor(std::vector({0x1b, 0x00})), json::parse_error); + CHECK_THROWS_AS(json::from_cbor(std::vector({0x1b, 0x00, 0x00})), json::parse_error); + CHECK_THROWS_AS(json::from_cbor(std::vector({0x1b, 0x00, 0x00, 0x00})), json::parse_error); + CHECK_THROWS_AS(json::from_cbor(std::vector({0x1b, 0x00, 0x00, 0x00, 0x00})), json::parse_error); + CHECK_THROWS_AS(json::from_cbor(std::vector({0x1b, 0x00, 0x00, 0x00, 0x00, 0x00})), json::parse_error); + CHECK_THROWS_AS(json::from_cbor(std::vector({0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00})), json::parse_error); + CHECK_THROWS_AS(json::from_cbor(std::vector({0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00})), json::parse_error); CHECK_THROWS_WITH(json::from_cbor(std::vector({0x18})), "[json.exception.parse_error.110] parse error at 2: unexpected end of input"); @@ -1285,10 +1286,10 @@ TEST_CASE("CBOR") { SECTION("concrete examples") { - CHECK_THROWS_AS(json::from_cbor(std::vector({0x1c})), json::parse_error&); + CHECK_THROWS_AS(json::from_cbor(std::vector({0x1c})), json::parse_error); CHECK_THROWS_WITH(json::from_cbor(std::vector({0x1c})), "[json.exception.parse_error.112] parse error at 1: error reading CBOR; last byte: 0x1C"); - CHECK_THROWS_AS(json::from_cbor(std::vector({0xf8})), json::parse_error&); + CHECK_THROWS_AS(json::from_cbor(std::vector({0xf8})), json::parse_error); CHECK_THROWS_WITH(json::from_cbor(std::vector({0xf8})), "[json.exception.parse_error.112] parse error at 1: error reading CBOR; last byte: 0xF8"); } @@ -1339,14 +1340,14 @@ TEST_CASE("CBOR") 0xf8 }) { - CHECK_THROWS_AS(json::from_cbor(std::vector({static_cast(byte)})), json::parse_error&); + CHECK_THROWS_AS(json::from_cbor(std::vector({static_cast(byte)})), json::parse_error); } } } SECTION("invalid string in map") { - CHECK_THROWS_AS(json::from_cbor(std::vector({0xa1, 0xff, 0x01})), json::parse_error&); + CHECK_THROWS_AS(json::from_cbor(std::vector({0xa1, 0xff, 0x01})), json::parse_error); CHECK_THROWS_WITH(json::from_cbor(std::vector({0xa1, 0xff, 0x01})), "[json.exception.parse_error.113] parse error at 2: expected a CBOR string; last byte: 0xFF"); } @@ -1362,7 +1363,7 @@ TEST_CASE("CBOR") SECTION("strict mode") { - CHECK_THROWS_AS(json::from_cbor(vec), json::parse_error&); + CHECK_THROWS_AS(json::from_cbor(vec), json::parse_error); CHECK_THROWS_WITH(json::from_cbor(vec), "[json.exception.parse_error.110] parse error at 2: expected end of input"); } diff --git a/test/src/unit-class_const_iterator.cpp b/test/src/unit-class_const_iterator.cpp index 573e773bb..5356fb356 100644 --- a/test/src/unit-class_const_iterator.cpp +++ b/test/src/unit-class_const_iterator.cpp @@ -147,7 +147,7 @@ TEST_CASE("const_iterator class") { json j(json::value_t::null); json::const_iterator it = j.cbegin(); - CHECK_THROWS_AS(*it, json::invalid_iterator&); + CHECK_THROWS_AS(*it, json::invalid_iterator); CHECK_THROWS_WITH(*it, "[json.exception.invalid_iterator.214] cannot get value"); } @@ -157,7 +157,7 @@ TEST_CASE("const_iterator class") json::const_iterator it = j.cbegin(); CHECK(*it == json(17)); it = j.cend(); - CHECK_THROWS_AS(*it, json::invalid_iterator&); + CHECK_THROWS_AS(*it, json::invalid_iterator); CHECK_THROWS_WITH(*it, "[json.exception.invalid_iterator.214] cannot get value"); } @@ -182,7 +182,7 @@ TEST_CASE("const_iterator class") { json j(json::value_t::null); json::const_iterator it = j.cbegin(); - CHECK_THROWS_AS(std::string(it->type_name()), json::invalid_iterator&); + CHECK_THROWS_AS(std::string(it->type_name()), json::invalid_iterator); CHECK_THROWS_WITH(std::string(it->type_name()), "[json.exception.invalid_iterator.214] cannot get value"); } @@ -192,7 +192,7 @@ TEST_CASE("const_iterator class") json::const_iterator it = j.cbegin(); CHECK(std::string(it->type_name()) == "number"); it = j.cend(); - CHECK_THROWS_AS(std::string(it->type_name()), json::invalid_iterator&); + CHECK_THROWS_AS(std::string(it->type_name()), json::invalid_iterator); CHECK_THROWS_WITH(std::string(it->type_name()), "[json.exception.invalid_iterator.214] cannot get value"); } diff --git a/test/src/unit-class_iterator.cpp b/test/src/unit-class_iterator.cpp index 1ef4a5389..cb7f16a53 100644 --- a/test/src/unit-class_iterator.cpp +++ b/test/src/unit-class_iterator.cpp @@ -131,7 +131,7 @@ TEST_CASE("iterator class") { json j(json::value_t::null); json::iterator it = j.begin(); - CHECK_THROWS_AS(*it, json::invalid_iterator&); + CHECK_THROWS_AS(*it, json::invalid_iterator); CHECK_THROWS_WITH(*it, "[json.exception.invalid_iterator.214] cannot get value"); } @@ -141,7 +141,7 @@ TEST_CASE("iterator class") json::iterator it = j.begin(); CHECK(*it == json(17)); it = j.end(); - CHECK_THROWS_AS(*it, json::invalid_iterator&); + CHECK_THROWS_AS(*it, json::invalid_iterator); CHECK_THROWS_WITH(*it, "[json.exception.invalid_iterator.214] cannot get value"); } @@ -166,7 +166,7 @@ TEST_CASE("iterator class") { json j(json::value_t::null); json::iterator it = j.begin(); - CHECK_THROWS_AS(std::string(it->type_name()), json::invalid_iterator&); + CHECK_THROWS_AS(std::string(it->type_name()), json::invalid_iterator); CHECK_THROWS_WITH(std::string(it->type_name()), "[json.exception.invalid_iterator.214] cannot get value"); } @@ -176,7 +176,7 @@ TEST_CASE("iterator class") json::iterator it = j.begin(); CHECK(std::string(it->type_name()) == "number"); it = j.end(); - CHECK_THROWS_AS(std::string(it->type_name()), json::invalid_iterator&); + CHECK_THROWS_AS(std::string(it->type_name()), json::invalid_iterator); CHECK_THROWS_WITH(std::string(it->type_name()), "[json.exception.invalid_iterator.214] cannot get value"); } diff --git a/test/src/unit-class_parser.cpp b/test/src/unit-class_parser.cpp index 9afa7d269..7c4e635a4 100644 --- a/test/src/unit-class_parser.cpp +++ b/test/src/unit-class_parser.cpp @@ -123,56 +123,56 @@ TEST_CASE("parser class") SECTION("errors") { // error: tab in string - CHECK_THROWS_AS(parser_helper("\"\t\""), json::parse_error&); + CHECK_THROWS_AS(parser_helper("\"\t\""), json::parse_error); CHECK_THROWS_WITH(parser_helper("\"\t\""), "[json.exception.parse_error.101] parse error at 2: syntax error - invalid string: control character must be escaped; last read: '\"'"); // error: newline in string - CHECK_THROWS_AS(parser_helper("\"\n\""), json::parse_error&); - CHECK_THROWS_AS(parser_helper("\"\r\""), json::parse_error&); + CHECK_THROWS_AS(parser_helper("\"\n\""), json::parse_error); + CHECK_THROWS_AS(parser_helper("\"\r\""), json::parse_error); CHECK_THROWS_WITH(parser_helper("\"\n\""), "[json.exception.parse_error.101] parse error at 2: syntax error - invalid string: control character must be escaped; last read: '\"'"); CHECK_THROWS_WITH(parser_helper("\"\r\""), "[json.exception.parse_error.101] parse error at 2: syntax error - invalid string: control character must be escaped; last read: '\"'"); // error: backspace in string - CHECK_THROWS_AS(parser_helper("\"\b\""), json::parse_error&); + CHECK_THROWS_AS(parser_helper("\"\b\""), json::parse_error); CHECK_THROWS_WITH(parser_helper("\"\b\""), "[json.exception.parse_error.101] parse error at 2: syntax error - invalid string: control character must be escaped; last read: '\"'"); // improve code coverage - CHECK_THROWS_AS(parser_helper("\uFF01"), json::parse_error&); - CHECK_THROWS_AS(parser_helper("[-4:1,]"), json::parse_error&); + CHECK_THROWS_AS(parser_helper("\uFF01"), json::parse_error); + CHECK_THROWS_AS(parser_helper("[-4:1,]"), json::parse_error); // unescaped control characters - CHECK_THROWS_AS(parser_helper("\"\x00\""), json::parse_error&); - CHECK_THROWS_AS(parser_helper("\"\x01\""), json::parse_error&); - CHECK_THROWS_AS(parser_helper("\"\x02\""), json::parse_error&); - CHECK_THROWS_AS(parser_helper("\"\x03\""), json::parse_error&); - CHECK_THROWS_AS(parser_helper("\"\x04\""), json::parse_error&); - CHECK_THROWS_AS(parser_helper("\"\x05\""), json::parse_error&); - CHECK_THROWS_AS(parser_helper("\"\x06\""), json::parse_error&); - CHECK_THROWS_AS(parser_helper("\"\x07\""), json::parse_error&); - CHECK_THROWS_AS(parser_helper("\"\x08\""), json::parse_error&); - CHECK_THROWS_AS(parser_helper("\"\x09\""), json::parse_error&); - CHECK_THROWS_AS(parser_helper("\"\x0a\""), json::parse_error&); - CHECK_THROWS_AS(parser_helper("\"\x0b\""), json::parse_error&); - CHECK_THROWS_AS(parser_helper("\"\x0c\""), json::parse_error&); - CHECK_THROWS_AS(parser_helper("\"\x0d\""), json::parse_error&); - CHECK_THROWS_AS(parser_helper("\"\x0e\""), json::parse_error&); - CHECK_THROWS_AS(parser_helper("\"\x0f\""), json::parse_error&); - CHECK_THROWS_AS(parser_helper("\"\x10\""), json::parse_error&); - CHECK_THROWS_AS(parser_helper("\"\x11\""), json::parse_error&); - CHECK_THROWS_AS(parser_helper("\"\x12\""), json::parse_error&); - CHECK_THROWS_AS(parser_helper("\"\x13\""), json::parse_error&); - CHECK_THROWS_AS(parser_helper("\"\x14\""), json::parse_error&); - CHECK_THROWS_AS(parser_helper("\"\x15\""), json::parse_error&); - CHECK_THROWS_AS(parser_helper("\"\x16\""), json::parse_error&); - CHECK_THROWS_AS(parser_helper("\"\x17\""), json::parse_error&); - CHECK_THROWS_AS(parser_helper("\"\x18\""), json::parse_error&); - CHECK_THROWS_AS(parser_helper("\"\x19\""), json::parse_error&); - CHECK_THROWS_AS(parser_helper("\"\x1a\""), json::parse_error&); - CHECK_THROWS_AS(parser_helper("\"\x1b\""), json::parse_error&); - CHECK_THROWS_AS(parser_helper("\"\x1c\""), json::parse_error&); - CHECK_THROWS_AS(parser_helper("\"\x1d\""), json::parse_error&); - CHECK_THROWS_AS(parser_helper("\"\x1e\""), json::parse_error&); - CHECK_THROWS_AS(parser_helper("\"\x1f\""), json::parse_error&); + CHECK_THROWS_AS(parser_helper("\"\x00\""), json::parse_error); + CHECK_THROWS_AS(parser_helper("\"\x01\""), json::parse_error); + CHECK_THROWS_AS(parser_helper("\"\x02\""), json::parse_error); + CHECK_THROWS_AS(parser_helper("\"\x03\""), json::parse_error); + CHECK_THROWS_AS(parser_helper("\"\x04\""), json::parse_error); + CHECK_THROWS_AS(parser_helper("\"\x05\""), json::parse_error); + CHECK_THROWS_AS(parser_helper("\"\x06\""), json::parse_error); + CHECK_THROWS_AS(parser_helper("\"\x07\""), json::parse_error); + CHECK_THROWS_AS(parser_helper("\"\x08\""), json::parse_error); + CHECK_THROWS_AS(parser_helper("\"\x09\""), json::parse_error); + CHECK_THROWS_AS(parser_helper("\"\x0a\""), json::parse_error); + CHECK_THROWS_AS(parser_helper("\"\x0b\""), json::parse_error); + CHECK_THROWS_AS(parser_helper("\"\x0c\""), json::parse_error); + CHECK_THROWS_AS(parser_helper("\"\x0d\""), json::parse_error); + CHECK_THROWS_AS(parser_helper("\"\x0e\""), json::parse_error); + CHECK_THROWS_AS(parser_helper("\"\x0f\""), json::parse_error); + CHECK_THROWS_AS(parser_helper("\"\x10\""), json::parse_error); + CHECK_THROWS_AS(parser_helper("\"\x11\""), json::parse_error); + CHECK_THROWS_AS(parser_helper("\"\x12\""), json::parse_error); + CHECK_THROWS_AS(parser_helper("\"\x13\""), json::parse_error); + CHECK_THROWS_AS(parser_helper("\"\x14\""), json::parse_error); + CHECK_THROWS_AS(parser_helper("\"\x15\""), json::parse_error); + CHECK_THROWS_AS(parser_helper("\"\x16\""), json::parse_error); + CHECK_THROWS_AS(parser_helper("\"\x17\""), json::parse_error); + CHECK_THROWS_AS(parser_helper("\"\x18\""), json::parse_error); + CHECK_THROWS_AS(parser_helper("\"\x19\""), json::parse_error); + CHECK_THROWS_AS(parser_helper("\"\x1a\""), json::parse_error); + CHECK_THROWS_AS(parser_helper("\"\x1b\""), json::parse_error); + CHECK_THROWS_AS(parser_helper("\"\x1c\""), json::parse_error); + CHECK_THROWS_AS(parser_helper("\"\x1d\""), json::parse_error); + CHECK_THROWS_AS(parser_helper("\"\x1e\""), json::parse_error); + CHECK_THROWS_AS(parser_helper("\"\x1f\""), json::parse_error); CHECK_THROWS_WITH(parser_helper("\"\x00\""), "[json.exception.parse_error.101] parse error at 2: syntax error - invalid string: missing closing quote; last read: '\"'"); CHECK_THROWS_WITH(parser_helper("\"\x01\""), "[json.exception.parse_error.101] parse error at 2: syntax error - invalid string: control character must be escaped; last read: '\"'"); CHECK_THROWS_WITH(parser_helper("\"\x02\""), "[json.exception.parse_error.101] parse error at 2: syntax error - invalid string: control character must be escaped; last read: '\"'"); @@ -214,7 +214,7 @@ TEST_CASE("parser class") // uses an iterator range. std::string s = "\"1\""; s[1] = '\0'; - CHECK_THROWS_AS(json::parse(s.begin(), s.end()), json::parse_error&); + CHECK_THROWS_AS(json::parse(s.begin(), s.end()), json::parse_error); CHECK_THROWS_WITH(json::parse(s.begin(), s.end()), "[json.exception.parse_error.101] parse error at 2: syntax error - invalid string: control character must be escaped; last read: '\"'"); } } @@ -386,33 +386,33 @@ TEST_CASE("parser class") SECTION("overflow") { // overflows during parsing yield an exception - CHECK_THROWS_AS(parser_helper("1.18973e+4932") == json(), json::out_of_range&); + CHECK_THROWS_AS(parser_helper("1.18973e+4932") == json(), json::out_of_range); CHECK_THROWS_WITH(parser_helper("1.18973e+4932") == json(), "[json.exception.out_of_range.406] number overflow parsing '1.18973e+4932'"); } SECTION("invalid numbers") { - CHECK_THROWS_AS(parser_helper("01"), json::parse_error&); - CHECK_THROWS_AS(parser_helper("--1"), json::parse_error&); - CHECK_THROWS_AS(parser_helper("1."), json::parse_error&); - CHECK_THROWS_AS(parser_helper("1E"), json::parse_error&); - CHECK_THROWS_AS(parser_helper("1E-"), json::parse_error&); - CHECK_THROWS_AS(parser_helper("1.E1"), json::parse_error&); - CHECK_THROWS_AS(parser_helper("-1E"), json::parse_error&); - CHECK_THROWS_AS(parser_helper("-0E#"), json::parse_error&); - CHECK_THROWS_AS(parser_helper("-0E-#"), json::parse_error&); - CHECK_THROWS_AS(parser_helper("-0#"), json::parse_error&); - CHECK_THROWS_AS(parser_helper("-0.0:"), json::parse_error&); - CHECK_THROWS_AS(parser_helper("-0.0Z"), json::parse_error&); - CHECK_THROWS_AS(parser_helper("-0E123:"), json::parse_error&); - CHECK_THROWS_AS(parser_helper("-0e0-:"), json::parse_error&); - CHECK_THROWS_AS(parser_helper("-0e-:"), json::parse_error&); - CHECK_THROWS_AS(parser_helper("-0f"), json::parse_error&); + CHECK_THROWS_AS(parser_helper("01"), json::parse_error); + CHECK_THROWS_AS(parser_helper("--1"), json::parse_error); + CHECK_THROWS_AS(parser_helper("1."), json::parse_error); + CHECK_THROWS_AS(parser_helper("1E"), json::parse_error); + CHECK_THROWS_AS(parser_helper("1E-"), json::parse_error); + CHECK_THROWS_AS(parser_helper("1.E1"), json::parse_error); + CHECK_THROWS_AS(parser_helper("-1E"), json::parse_error); + CHECK_THROWS_AS(parser_helper("-0E#"), json::parse_error); + CHECK_THROWS_AS(parser_helper("-0E-#"), json::parse_error); + CHECK_THROWS_AS(parser_helper("-0#"), json::parse_error); + CHECK_THROWS_AS(parser_helper("-0.0:"), json::parse_error); + CHECK_THROWS_AS(parser_helper("-0.0Z"), json::parse_error); + CHECK_THROWS_AS(parser_helper("-0E123:"), json::parse_error); + CHECK_THROWS_AS(parser_helper("-0e0-:"), json::parse_error); + CHECK_THROWS_AS(parser_helper("-0e-:"), json::parse_error); + CHECK_THROWS_AS(parser_helper("-0f"), json::parse_error); // numbers must not begin with "+" - CHECK_THROWS_AS(parser_helper("+1"), json::parse_error&); - CHECK_THROWS_AS(parser_helper("+0"), json::parse_error&); + CHECK_THROWS_AS(parser_helper("+1"), json::parse_error); + CHECK_THROWS_AS(parser_helper("+0"), json::parse_error); CHECK_THROWS_WITH(parser_helper("01"), "[json.exception.parse_error.101] parse error at 2: syntax error - unexpected number literal; expected end of input"); @@ -717,20 +717,20 @@ TEST_CASE("parser class") SECTION("parse errors") { // unexpected end of number - CHECK_THROWS_AS(parser_helper("0."), json::parse_error&); - CHECK_THROWS_AS(parser_helper("-"), json::parse_error&); - CHECK_THROWS_AS(parser_helper("--"), json::parse_error&); - CHECK_THROWS_AS(parser_helper("-0."), json::parse_error&); - CHECK_THROWS_AS(parser_helper("-."), json::parse_error&); - CHECK_THROWS_AS(parser_helper("-:"), json::parse_error&); - CHECK_THROWS_AS(parser_helper("0.:"), json::parse_error&); - CHECK_THROWS_AS(parser_helper("e."), json::parse_error&); - CHECK_THROWS_AS(parser_helper("1e."), json::parse_error&); - CHECK_THROWS_AS(parser_helper("1e/"), json::parse_error&); - CHECK_THROWS_AS(parser_helper("1e:"), json::parse_error&); - CHECK_THROWS_AS(parser_helper("1E."), json::parse_error&); - CHECK_THROWS_AS(parser_helper("1E/"), json::parse_error&); - CHECK_THROWS_AS(parser_helper("1E:"), json::parse_error&); + CHECK_THROWS_AS(parser_helper("0."), json::parse_error); + CHECK_THROWS_AS(parser_helper("-"), json::parse_error); + CHECK_THROWS_AS(parser_helper("--"), json::parse_error); + CHECK_THROWS_AS(parser_helper("-0."), json::parse_error); + CHECK_THROWS_AS(parser_helper("-."), json::parse_error); + CHECK_THROWS_AS(parser_helper("-:"), json::parse_error); + CHECK_THROWS_AS(parser_helper("0.:"), json::parse_error); + CHECK_THROWS_AS(parser_helper("e."), json::parse_error); + CHECK_THROWS_AS(parser_helper("1e."), json::parse_error); + CHECK_THROWS_AS(parser_helper("1e/"), json::parse_error); + CHECK_THROWS_AS(parser_helper("1e:"), json::parse_error); + CHECK_THROWS_AS(parser_helper("1E."), json::parse_error); + CHECK_THROWS_AS(parser_helper("1E/"), json::parse_error); + CHECK_THROWS_AS(parser_helper("1E:"), json::parse_error); CHECK_THROWS_WITH(parser_helper("0."), "[json.exception.parse_error.101] parse error at 3: syntax error - invalid number; expected digit after '.'; last read: '0.'"); CHECK_THROWS_WITH(parser_helper("-"), @@ -761,11 +761,11 @@ TEST_CASE("parser class") "[json.exception.parse_error.101] parse error at 3: syntax error - invalid number; expected '+', '-', or digit after exponent; last read: '1E:'"); // unexpected end of null - CHECK_THROWS_AS(parser_helper("n"), json::parse_error&); - CHECK_THROWS_AS(parser_helper("nu"), json::parse_error&); - CHECK_THROWS_AS(parser_helper("nul"), json::parse_error&); - CHECK_THROWS_AS(parser_helper("nulk"), json::parse_error&); - CHECK_THROWS_AS(parser_helper("nulm"), json::parse_error&); + CHECK_THROWS_AS(parser_helper("n"), json::parse_error); + CHECK_THROWS_AS(parser_helper("nu"), json::parse_error); + CHECK_THROWS_AS(parser_helper("nul"), json::parse_error); + CHECK_THROWS_AS(parser_helper("nulk"), json::parse_error); + CHECK_THROWS_AS(parser_helper("nulm"), json::parse_error); CHECK_THROWS_WITH(parser_helper("n"), "[json.exception.parse_error.101] parse error at 2: syntax error - invalid literal; last read: 'n'"); CHECK_THROWS_WITH(parser_helper("nu"), @@ -778,11 +778,11 @@ TEST_CASE("parser class") "[json.exception.parse_error.101] parse error at 4: syntax error - invalid literal; last read: 'nulm'"); // unexpected end of true - CHECK_THROWS_AS(parser_helper("t"), json::parse_error&); - CHECK_THROWS_AS(parser_helper("tr"), json::parse_error&); - CHECK_THROWS_AS(parser_helper("tru"), json::parse_error&); - CHECK_THROWS_AS(parser_helper("trud"), json::parse_error&); - CHECK_THROWS_AS(parser_helper("truf"), json::parse_error&); + CHECK_THROWS_AS(parser_helper("t"), json::parse_error); + CHECK_THROWS_AS(parser_helper("tr"), json::parse_error); + CHECK_THROWS_AS(parser_helper("tru"), json::parse_error); + CHECK_THROWS_AS(parser_helper("trud"), json::parse_error); + CHECK_THROWS_AS(parser_helper("truf"), json::parse_error); CHECK_THROWS_WITH(parser_helper("t"), "[json.exception.parse_error.101] parse error at 2: syntax error - invalid literal; last read: 't'"); CHECK_THROWS_WITH(parser_helper("tr"), @@ -795,12 +795,12 @@ TEST_CASE("parser class") "[json.exception.parse_error.101] parse error at 4: syntax error - invalid literal; last read: 'truf'"); // unexpected end of false - CHECK_THROWS_AS(parser_helper("f"), json::parse_error&); - CHECK_THROWS_AS(parser_helper("fa"), json::parse_error&); - CHECK_THROWS_AS(parser_helper("fal"), json::parse_error&); - CHECK_THROWS_AS(parser_helper("fals"), json::parse_error&); - CHECK_THROWS_AS(parser_helper("falsd"), json::parse_error&); - CHECK_THROWS_AS(parser_helper("falsf"), json::parse_error&); + CHECK_THROWS_AS(parser_helper("f"), json::parse_error); + CHECK_THROWS_AS(parser_helper("fa"), json::parse_error); + CHECK_THROWS_AS(parser_helper("fal"), json::parse_error); + CHECK_THROWS_AS(parser_helper("fals"), json::parse_error); + CHECK_THROWS_AS(parser_helper("falsd"), json::parse_error); + CHECK_THROWS_AS(parser_helper("falsf"), json::parse_error); CHECK_THROWS_WITH(parser_helper("f"), "[json.exception.parse_error.101] parse error at 2: syntax error - invalid literal; last read: 'f'"); CHECK_THROWS_WITH(parser_helper("fa"), @@ -815,11 +815,11 @@ TEST_CASE("parser class") "[json.exception.parse_error.101] parse error at 5: syntax error - invalid literal; last read: 'falsf'"); // missing/unexpected end of array - CHECK_THROWS_AS(parser_helper("["), json::parse_error&); - CHECK_THROWS_AS(parser_helper("[1"), json::parse_error&); - CHECK_THROWS_AS(parser_helper("[1,"), json::parse_error&); - CHECK_THROWS_AS(parser_helper("[1,]"), json::parse_error&); - CHECK_THROWS_AS(parser_helper("]"), json::parse_error&); + CHECK_THROWS_AS(parser_helper("["), json::parse_error); + CHECK_THROWS_AS(parser_helper("[1"), json::parse_error); + CHECK_THROWS_AS(parser_helper("[1,"), json::parse_error); + CHECK_THROWS_AS(parser_helper("[1,]"), json::parse_error); + CHECK_THROWS_AS(parser_helper("]"), json::parse_error); CHECK_THROWS_WITH(parser_helper("["), "[json.exception.parse_error.101] parse error at 2: syntax error - unexpected end of input; expected '[', '{', or a literal"); CHECK_THROWS_WITH(parser_helper("[1"), @@ -832,12 +832,12 @@ TEST_CASE("parser class") "[json.exception.parse_error.101] parse error at 1: syntax error - unexpected ']'; expected '[', '{', or a literal"); // missing/unexpected end of object - CHECK_THROWS_AS(parser_helper("{"), json::parse_error&); - CHECK_THROWS_AS(parser_helper("{\"foo\""), json::parse_error&); - CHECK_THROWS_AS(parser_helper("{\"foo\":"), json::parse_error&); - CHECK_THROWS_AS(parser_helper("{\"foo\":}"), json::parse_error&); - CHECK_THROWS_AS(parser_helper("{\"foo\":1,}"), json::parse_error&); - CHECK_THROWS_AS(parser_helper("}"), json::parse_error&); + CHECK_THROWS_AS(parser_helper("{"), json::parse_error); + CHECK_THROWS_AS(parser_helper("{\"foo\""), json::parse_error); + CHECK_THROWS_AS(parser_helper("{\"foo\":"), json::parse_error); + CHECK_THROWS_AS(parser_helper("{\"foo\":}"), json::parse_error); + CHECK_THROWS_AS(parser_helper("{\"foo\":1,}"), json::parse_error); + CHECK_THROWS_AS(parser_helper("}"), json::parse_error); CHECK_THROWS_WITH(parser_helper("{"), "[json.exception.parse_error.101] parse error at 2: syntax error - unexpected end of input; expected string literal"); CHECK_THROWS_WITH(parser_helper("{\"foo\""), @@ -852,16 +852,16 @@ TEST_CASE("parser class") "[json.exception.parse_error.101] parse error at 1: syntax error - unexpected '}'; expected '[', '{', or a literal"); // missing/unexpected end of string - CHECK_THROWS_AS(parser_helper("\""), json::parse_error&); - CHECK_THROWS_AS(parser_helper("\"\\\""), json::parse_error&); - CHECK_THROWS_AS(parser_helper("\"\\u\""), json::parse_error&); - CHECK_THROWS_AS(parser_helper("\"\\u0\""), json::parse_error&); - CHECK_THROWS_AS(parser_helper("\"\\u01\""), json::parse_error&); - CHECK_THROWS_AS(parser_helper("\"\\u012\""), json::parse_error&); - CHECK_THROWS_AS(parser_helper("\"\\u"), json::parse_error&); - CHECK_THROWS_AS(parser_helper("\"\\u0"), json::parse_error&); - CHECK_THROWS_AS(parser_helper("\"\\u01"), json::parse_error&); - CHECK_THROWS_AS(parser_helper("\"\\u012"), json::parse_error&); + CHECK_THROWS_AS(parser_helper("\""), json::parse_error); + CHECK_THROWS_AS(parser_helper("\"\\\""), json::parse_error); + CHECK_THROWS_AS(parser_helper("\"\\u\""), json::parse_error); + CHECK_THROWS_AS(parser_helper("\"\\u0\""), json::parse_error); + CHECK_THROWS_AS(parser_helper("\"\\u01\""), json::parse_error); + CHECK_THROWS_AS(parser_helper("\"\\u012\""), json::parse_error); + CHECK_THROWS_AS(parser_helper("\"\\u"), json::parse_error); + CHECK_THROWS_AS(parser_helper("\"\\u0"), json::parse_error); + CHECK_THROWS_AS(parser_helper("\"\\u01"), json::parse_error); + CHECK_THROWS_AS(parser_helper("\"\\u012"), json::parse_error); CHECK_THROWS_WITH(parser_helper("\""), "[json.exception.parse_error.101] parse error at 2: syntax error - invalid string: missing closing quote; last read: '\"'"); CHECK_THROWS_WITH(parser_helper("\"\\\""), @@ -913,7 +913,7 @@ TEST_CASE("parser class") // any other combination of backslash and character is invalid default: { - CHECK_THROWS_AS(parser_helper(s.c_str()), json::parse_error&); + CHECK_THROWS_AS(parser_helper(s.c_str()), json::parse_error); // only check error message if c is not a control character if (c > 0x1f) { @@ -989,7 +989,7 @@ TEST_CASE("parser class") else { CAPTURE(s1); - CHECK_THROWS_AS(parser_helper(s1.c_str()), json::parse_error&); + CHECK_THROWS_AS(parser_helper(s1.c_str()), json::parse_error); // only check error message if c is not a control character if (c > 0x1f) { @@ -998,7 +998,7 @@ TEST_CASE("parser class") } CAPTURE(s2); - CHECK_THROWS_AS(parser_helper(s2.c_str()), json::parse_error&); + CHECK_THROWS_AS(parser_helper(s2.c_str()), json::parse_error); // only check error message if c is not a control character if (c > 0x1f) { @@ -1007,7 +1007,7 @@ TEST_CASE("parser class") } CAPTURE(s3); - CHECK_THROWS_AS(parser_helper(s3.c_str()), json::parse_error&); + CHECK_THROWS_AS(parser_helper(s3.c_str()), json::parse_error); // only check error message if c is not a control character if (c > 0x1f) { @@ -1016,7 +1016,7 @@ TEST_CASE("parser class") } CAPTURE(s4); - CHECK_THROWS_AS(parser_helper(s4.c_str()), json::parse_error&); + CHECK_THROWS_AS(parser_helper(s4.c_str()), json::parse_error); // only check error message if c is not a control character if (c > 0x1f) { @@ -1028,13 +1028,13 @@ TEST_CASE("parser class") } // missing part of a surrogate pair - CHECK_THROWS_AS(json::parse("\"\\uD80C\""), json::parse_error&); + CHECK_THROWS_AS(json::parse("\"\\uD80C\""), json::parse_error); CHECK_THROWS_WITH(json::parse("\"\\uD80C\""), "[json.exception.parse_error.101] parse error at 8: syntax error - invalid string: surrogate U+DC00..U+DFFF must be followed by U+DC00..U+DFFF; last read: '\"\\uD80C\"'"); // invalid surrogate pair - CHECK_THROWS_AS(json::parse("\"\\uD80C\\uD80C\""), json::parse_error&); - CHECK_THROWS_AS(json::parse("\"\\uD80C\\u0000\""), json::parse_error&); - CHECK_THROWS_AS(json::parse("\"\\uD80C\\uFFFF\""), json::parse_error&); + CHECK_THROWS_AS(json::parse("\"\\uD80C\\uD80C\""), json::parse_error); + CHECK_THROWS_AS(json::parse("\"\\uD80C\\u0000\""), json::parse_error); + CHECK_THROWS_AS(json::parse("\"\\uD80C\\uFFFF\""), json::parse_error); CHECK_THROWS_WITH(json::parse("\"\\uD80C\\uD80C\""), "[json.exception.parse_error.101] parse error at 13: syntax error - invalid string: surrogate U+DC00..U+DFFF must be followed by U+DC00..U+DFFF; last read: '\"\\uD80C\\uD80C'"); CHECK_THROWS_WITH(json::parse("\"\\uD80C\\u0000\""), @@ -1229,11 +1229,11 @@ TEST_CASE("parser class") SECTION("tests found by mutate++") { // test case to make sure no comma preceeds the first key - CHECK_THROWS_AS(parser_helper("{,\"key\": false}"), json::parse_error&); + CHECK_THROWS_AS(parser_helper("{,\"key\": false}"), json::parse_error); CHECK_THROWS_WITH(parser_helper("{,\"key\": false}"), "[json.exception.parse_error.101] parse error at 2: syntax error - unexpected ','; expected string literal"); // test case to make sure an object is properly closed - CHECK_THROWS_AS(parser_helper("[{\"key\": false true]"), json::parse_error&); + CHECK_THROWS_AS(parser_helper("[{\"key\": false true]"), json::parse_error); CHECK_THROWS_WITH(parser_helper("[{\"key\": false true]"), "[json.exception.parse_error.101] parse error at 19: syntax error - unexpected true literal; expected '}'"); diff --git a/test/src/unit-constructor1.cpp b/test/src/unit-constructor1.cpp index d8c9482cb..8840fe7e7 100644 --- a/test/src/unit-constructor1.cpp +++ b/test/src/unit-constructor1.cpp @@ -36,6 +36,7 @@ using nlohmann::json; #include #include #include +#include #include #include #include @@ -1049,7 +1050,7 @@ TEST_CASE("constructors") SECTION("object with error") { CHECK_THROWS_AS(json::object({ {"one", 1}, {"two", 1u}, {"three", 2.2}, {"four", false}, 13 }), - json::type_error&); + json::type_error); CHECK_THROWS_WITH(json::object({ {"one", 1}, {"two", 1u}, {"three", 2.2}, {"four", false}, 13 }), "[json.exception.type_error.301] cannot create object from initializer list"); } @@ -1263,16 +1264,16 @@ TEST_CASE("constructors") { json jobject = {{"a", "a"}, {"b", 1}, {"c", 17u}, {"d", false}, {"e", true}}; json jobject2 = {{"a", "a"}, {"b", 1}, {"c", 17u}}; - CHECK_THROWS_AS(json(jobject.begin(), jobject2.end()), json::invalid_iterator&); - CHECK_THROWS_AS(json(jobject2.begin(), jobject.end()), json::invalid_iterator&); + CHECK_THROWS_AS(json(jobject.begin(), jobject2.end()), json::invalid_iterator); + CHECK_THROWS_AS(json(jobject2.begin(), jobject.end()), json::invalid_iterator); CHECK_THROWS_WITH(json(jobject.begin(), jobject2.end()), "[json.exception.invalid_iterator.201] iterators are not compatible"); CHECK_THROWS_WITH(json(jobject2.begin(), jobject.end()), "[json.exception.invalid_iterator.201] iterators are not compatible"); } { json jobject = {{"a", "a"}, {"b", 1}, {"c", 17u}, {"d", false}, {"e", true}}; json jobject2 = {{"a", "a"}, {"b", 1}, {"c", 17u}}; - CHECK_THROWS_AS(json(jobject.cbegin(), jobject2.cend()), json::invalid_iterator&); - CHECK_THROWS_AS(json(jobject2.cbegin(), jobject.cend()), json::invalid_iterator&); + CHECK_THROWS_AS(json(jobject.cbegin(), jobject2.cend()), json::invalid_iterator); + CHECK_THROWS_AS(json(jobject2.cbegin(), jobject.cend()), json::invalid_iterator); CHECK_THROWS_WITH(json(jobject.cbegin(), jobject2.cend()), "[json.exception.invalid_iterator.201] iterators are not compatible"); CHECK_THROWS_WITH(json(jobject2.cbegin(), jobject.cend()), "[json.exception.invalid_iterator.201] iterators are not compatible"); } @@ -1328,16 +1329,16 @@ TEST_CASE("constructors") { json jarray = {1, 2, 3, 4}; json jarray2 = {2, 3, 4, 5}; - CHECK_THROWS_AS(json(jarray.begin(), jarray2.end()), json::invalid_iterator&); - CHECK_THROWS_AS(json(jarray2.begin(), jarray.end()), json::invalid_iterator&); + CHECK_THROWS_AS(json(jarray.begin(), jarray2.end()), json::invalid_iterator); + CHECK_THROWS_AS(json(jarray2.begin(), jarray.end()), json::invalid_iterator); CHECK_THROWS_WITH(json(jarray.begin(), jarray2.end()), "[json.exception.invalid_iterator.201] iterators are not compatible"); CHECK_THROWS_WITH(json(jarray2.begin(), jarray.end()), "[json.exception.invalid_iterator.201] iterators are not compatible"); } { json jarray = {1, 2, 3, 4}; json jarray2 = {2, 3, 4, 5}; - CHECK_THROWS_AS(json(jarray.cbegin(), jarray2.cend()), json::invalid_iterator&); - CHECK_THROWS_AS(json(jarray2.cbegin(), jarray.cend()), json::invalid_iterator&); + CHECK_THROWS_AS(json(jarray.cbegin(), jarray2.cend()), json::invalid_iterator); + CHECK_THROWS_AS(json(jarray2.cbegin(), jarray.cend()), json::invalid_iterator); CHECK_THROWS_WITH(json(jarray.cbegin(), jarray2.cend()), "[json.exception.invalid_iterator.201] iterators are not compatible"); CHECK_THROWS_WITH(json(jarray2.cbegin(), jarray.cend()), "[json.exception.invalid_iterator.201] iterators are not compatible"); } @@ -1352,13 +1353,13 @@ TEST_CASE("constructors") { { json j; - CHECK_THROWS_AS(json(j.begin(), j.end()), json::invalid_iterator&); + CHECK_THROWS_AS(json(j.begin(), j.end()), json::invalid_iterator); CHECK_THROWS_WITH(json(j.begin(), j.end()), "[json.exception.invalid_iterator.206] cannot construct with iterators from null"); } { json j; - CHECK_THROWS_AS(json(j.cbegin(), j.cend()), json::invalid_iterator&); + CHECK_THROWS_AS(json(j.cbegin(), j.cend()), json::invalid_iterator); CHECK_THROWS_WITH(json(j.cbegin(), j.cend()), "[json.exception.invalid_iterator.206] cannot construct with iterators from null"); } @@ -1441,15 +1442,15 @@ TEST_CASE("constructors") { { json j = "foo"; - CHECK_THROWS_AS(json(j.end(), j.end()), json::invalid_iterator&); - CHECK_THROWS_AS(json(j.begin(), j.begin()), json::invalid_iterator&); + CHECK_THROWS_AS(json(j.end(), j.end()), json::invalid_iterator); + CHECK_THROWS_AS(json(j.begin(), j.begin()), json::invalid_iterator); CHECK_THROWS_WITH(json(j.end(), j.end()), "[json.exception.invalid_iterator.204] iterators out of range"); CHECK_THROWS_WITH(json(j.begin(), j.begin()), "[json.exception.invalid_iterator.204] iterators out of range"); } { json j = "bar"; - CHECK_THROWS_AS(json(j.cend(), j.cend()), json::invalid_iterator&); - CHECK_THROWS_AS(json(j.cbegin(), j.cbegin()), json::invalid_iterator&); + CHECK_THROWS_AS(json(j.cend(), j.cend()), json::invalid_iterator); + CHECK_THROWS_AS(json(j.cbegin(), j.cbegin()), json::invalid_iterator); CHECK_THROWS_WITH(json(j.cend(), j.cend()), "[json.exception.invalid_iterator.204] iterators out of range"); CHECK_THROWS_WITH(json(j.cbegin(), j.cbegin()), "[json.exception.invalid_iterator.204] iterators out of range"); } @@ -1459,15 +1460,15 @@ TEST_CASE("constructors") { { json j = false; - CHECK_THROWS_AS(json(j.end(), j.end()), json::invalid_iterator&); - CHECK_THROWS_AS(json(j.begin(), j.begin()), json::invalid_iterator&); + CHECK_THROWS_AS(json(j.end(), j.end()), json::invalid_iterator); + CHECK_THROWS_AS(json(j.begin(), j.begin()), json::invalid_iterator); CHECK_THROWS_WITH(json(j.end(), j.end()), "[json.exception.invalid_iterator.204] iterators out of range"); CHECK_THROWS_WITH(json(j.begin(), j.begin()), "[json.exception.invalid_iterator.204] iterators out of range"); } { json j = true; - CHECK_THROWS_AS(json(j.cend(), j.cend()), json::invalid_iterator&); - CHECK_THROWS_AS(json(j.cbegin(), j.cbegin()), json::invalid_iterator&); + CHECK_THROWS_AS(json(j.cend(), j.cend()), json::invalid_iterator); + CHECK_THROWS_AS(json(j.cbegin(), j.cbegin()), json::invalid_iterator); CHECK_THROWS_WITH(json(j.cend(), j.cend()), "[json.exception.invalid_iterator.204] iterators out of range"); CHECK_THROWS_WITH(json(j.cbegin(), j.cbegin()), "[json.exception.invalid_iterator.204] iterators out of range"); } @@ -1477,15 +1478,15 @@ TEST_CASE("constructors") { { json j = 17; - CHECK_THROWS_AS(json(j.end(), j.end()), json::invalid_iterator&); - CHECK_THROWS_AS(json(j.begin(), j.begin()), json::invalid_iterator&); + CHECK_THROWS_AS(json(j.end(), j.end()), json::invalid_iterator); + CHECK_THROWS_AS(json(j.begin(), j.begin()), json::invalid_iterator); CHECK_THROWS_WITH(json(j.end(), j.end()), "[json.exception.invalid_iterator.204] iterators out of range"); CHECK_THROWS_WITH(json(j.begin(), j.begin()), "[json.exception.invalid_iterator.204] iterators out of range"); } { json j = 17; - CHECK_THROWS_AS(json(j.cend(), j.cend()), json::invalid_iterator&); - CHECK_THROWS_AS(json(j.cbegin(), j.cbegin()), json::invalid_iterator&); + CHECK_THROWS_AS(json(j.cend(), j.cend()), json::invalid_iterator); + CHECK_THROWS_AS(json(j.cbegin(), j.cbegin()), json::invalid_iterator); CHECK_THROWS_WITH(json(j.cend(), j.cend()), "[json.exception.invalid_iterator.204] iterators out of range"); CHECK_THROWS_WITH(json(j.cbegin(), j.cbegin()), "[json.exception.invalid_iterator.204] iterators out of range"); } @@ -1495,15 +1496,15 @@ TEST_CASE("constructors") { { json j = 17u; - CHECK_THROWS_AS(json(j.end(), j.end()), json::invalid_iterator&); - CHECK_THROWS_AS(json(j.begin(), j.begin()), json::invalid_iterator&); + CHECK_THROWS_AS(json(j.end(), j.end()), json::invalid_iterator); + CHECK_THROWS_AS(json(j.begin(), j.begin()), json::invalid_iterator); CHECK_THROWS_WITH(json(j.end(), j.end()), "[json.exception.invalid_iterator.204] iterators out of range"); CHECK_THROWS_WITH(json(j.begin(), j.begin()), "[json.exception.invalid_iterator.204] iterators out of range"); } { json j = 17u; - CHECK_THROWS_AS(json(j.cend(), j.cend()), json::invalid_iterator&); - CHECK_THROWS_AS(json(j.cbegin(), j.cbegin()), json::invalid_iterator&); + CHECK_THROWS_AS(json(j.cend(), j.cend()), json::invalid_iterator); + CHECK_THROWS_AS(json(j.cbegin(), j.cbegin()), json::invalid_iterator); CHECK_THROWS_WITH(json(j.cend(), j.cend()), "[json.exception.invalid_iterator.204] iterators out of range"); CHECK_THROWS_WITH(json(j.cbegin(), j.cbegin()), "[json.exception.invalid_iterator.204] iterators out of range"); } @@ -1513,15 +1514,15 @@ TEST_CASE("constructors") { { json j = 23.42; - CHECK_THROWS_AS(json(j.end(), j.end()), json::invalid_iterator&); - CHECK_THROWS_AS(json(j.begin(), j.begin()), json::invalid_iterator&); + CHECK_THROWS_AS(json(j.end(), j.end()), json::invalid_iterator); + CHECK_THROWS_AS(json(j.begin(), j.begin()), json::invalid_iterator); CHECK_THROWS_WITH(json(j.end(), j.end()), "[json.exception.invalid_iterator.204] iterators out of range"); CHECK_THROWS_WITH(json(j.begin(), j.begin()), "[json.exception.invalid_iterator.204] iterators out of range"); } { json j = 23.42; - CHECK_THROWS_AS(json(j.cend(), j.cend()), json::invalid_iterator&); - CHECK_THROWS_AS(json(j.cbegin(), j.cbegin()), json::invalid_iterator&); + CHECK_THROWS_AS(json(j.cend(), j.cend()), json::invalid_iterator); + CHECK_THROWS_AS(json(j.cbegin(), j.cbegin()), json::invalid_iterator); CHECK_THROWS_WITH(json(j.cend(), j.cend()), "[json.exception.invalid_iterator.204] iterators out of range"); CHECK_THROWS_WITH(json(j.cbegin(), j.cbegin()), "[json.exception.invalid_iterator.204] iterators out of range"); } diff --git a/test/src/unit-conversions.cpp b/test/src/unit-conversions.cpp index eafac3205..fdbc72890 100644 --- a/test/src/unit-conversions.cpp +++ b/test/src/unit-conversions.cpp @@ -35,6 +35,7 @@ using nlohmann::json; #include #include #include +#include #include #include #include @@ -79,13 +80,13 @@ TEST_CASE("value conversion") SECTION("exception in case of a non-object type") { - CHECK_THROWS_AS(json(json::value_t::null).get(), json::type_error&); - CHECK_THROWS_AS(json(json::value_t::array).get(), json::type_error&); - CHECK_THROWS_AS(json(json::value_t::string).get(), json::type_error&); - CHECK_THROWS_AS(json(json::value_t::boolean).get(), json::type_error&); - CHECK_THROWS_AS(json(json::value_t::number_integer).get(), json::type_error&); - CHECK_THROWS_AS(json(json::value_t::number_unsigned).get(), json::type_error&); - CHECK_THROWS_AS(json(json::value_t::number_float).get(), json::type_error&); + CHECK_THROWS_AS(json(json::value_t::null).get(), json::type_error); + CHECK_THROWS_AS(json(json::value_t::array).get(), json::type_error); + CHECK_THROWS_AS(json(json::value_t::string).get(), json::type_error); + CHECK_THROWS_AS(json(json::value_t::boolean).get(), json::type_error); + CHECK_THROWS_AS(json(json::value_t::number_integer).get(), json::type_error); + CHECK_THROWS_AS(json(json::value_t::number_unsigned).get(), json::type_error); + CHECK_THROWS_AS(json(json::value_t::number_float).get(), json::type_error); CHECK_THROWS_WITH(json(json::value_t::null).get(), "[json.exception.type_error.302] type must be object, but is null"); @@ -162,7 +163,7 @@ TEST_CASE("value conversion") std::forward_list a = j.get>(); CHECK(json(a) == j); - CHECK_THROWS_AS(json(json::value_t::null).get>(), json::type_error&); + CHECK_THROWS_AS(json(json::value_t::null).get>(), json::type_error); CHECK_THROWS_WITH(json(json::value_t::null).get>(), "[json.exception.type_error.302] type must be array, but is null"); } @@ -172,7 +173,7 @@ TEST_CASE("value conversion") std::vector a = j.get>(); CHECK(json(a) == j); - CHECK_THROWS_AS(json(json::value_t::null).get>(), json::type_error&); + CHECK_THROWS_AS(json(json::value_t::null).get>(), json::type_error); CHECK_THROWS_WITH(json(json::value_t::null).get>(), "[json.exception.type_error.302] type must be array, but is null"); @@ -181,7 +182,7 @@ TEST_CASE("value conversion") { // making the call to from_json throw in order to check capacity std::vector v; - CHECK_THROWS_AS(nlohmann::from_json(j, v), json::type_error&); + CHECK_THROWS_AS(nlohmann::from_json(j, v), json::type_error); CHECK(v.capacity() == j.size()); // make sure all values are properly copied @@ -213,13 +214,13 @@ TEST_CASE("value conversion") SECTION("exception in case of a non-array type") { - CHECK_THROWS_AS(json(json::value_t::null).get(), json::type_error&); - CHECK_THROWS_AS(json(json::value_t::object).get(), json::type_error&); - CHECK_THROWS_AS(json(json::value_t::string).get(), json::type_error&); - CHECK_THROWS_AS(json(json::value_t::boolean).get(), json::type_error&); - CHECK_THROWS_AS(json(json::value_t::number_integer).get(), json::type_error&); - CHECK_THROWS_AS(json(json::value_t::number_unsigned).get(), json::type_error&); - CHECK_THROWS_AS(json(json::value_t::number_float).get(), json::type_error&); + CHECK_THROWS_AS(json(json::value_t::null).get(), json::type_error); + CHECK_THROWS_AS(json(json::value_t::object).get(), json::type_error); + CHECK_THROWS_AS(json(json::value_t::string).get(), json::type_error); + CHECK_THROWS_AS(json(json::value_t::boolean).get(), json::type_error); + CHECK_THROWS_AS(json(json::value_t::number_integer).get(), json::type_error); + CHECK_THROWS_AS(json(json::value_t::number_unsigned).get(), json::type_error); + CHECK_THROWS_AS(json(json::value_t::number_float).get(), json::type_error); CHECK_THROWS_WITH(json(json::value_t::object).get>(), "[json.exception.type_error.302] type must be array, but is object"); @@ -295,13 +296,13 @@ TEST_CASE("value conversion") SECTION("exception in case of a non-string type") { - CHECK_THROWS_AS(json(json::value_t::null).get(), json::type_error&); - CHECK_THROWS_AS(json(json::value_t::object).get(), json::type_error&); - CHECK_THROWS_AS(json(json::value_t::array).get(), json::type_error&); - CHECK_THROWS_AS(json(json::value_t::boolean).get(), json::type_error&); - CHECK_THROWS_AS(json(json::value_t::number_integer).get(), json::type_error&); - CHECK_THROWS_AS(json(json::value_t::number_unsigned).get(), json::type_error&); - CHECK_THROWS_AS(json(json::value_t::number_float).get(), json::type_error&); + CHECK_THROWS_AS(json(json::value_t::null).get(), json::type_error); + CHECK_THROWS_AS(json(json::value_t::object).get(), json::type_error); + CHECK_THROWS_AS(json(json::value_t::array).get(), json::type_error); + CHECK_THROWS_AS(json(json::value_t::boolean).get(), json::type_error); + CHECK_THROWS_AS(json(json::value_t::number_integer).get(), json::type_error); + CHECK_THROWS_AS(json(json::value_t::number_unsigned).get(), json::type_error); + CHECK_THROWS_AS(json(json::value_t::number_float).get(), json::type_error); CHECK_THROWS_WITH(json(json::value_t::null).get(), "[json.exception.type_error.302] type must be string, but is null"); @@ -357,13 +358,13 @@ TEST_CASE("value conversion") SECTION("exception in case of a non-string type") { - CHECK_THROWS_AS(json(json::value_t::null).get(), json::type_error&); - CHECK_THROWS_AS(json(json::value_t::object).get(), json::type_error&); - CHECK_THROWS_AS(json(json::value_t::array).get(), json::type_error&); - CHECK_THROWS_AS(json(json::value_t::string).get(), json::type_error&); - CHECK_THROWS_AS(json(json::value_t::number_integer).get(), json::type_error&); - CHECK_THROWS_AS(json(json::value_t::number_unsigned).get(), json::type_error&); - CHECK_THROWS_AS(json(json::value_t::number_float).get(), json::type_error&); + CHECK_THROWS_AS(json(json::value_t::null).get(), json::type_error); + CHECK_THROWS_AS(json(json::value_t::object).get(), json::type_error); + CHECK_THROWS_AS(json(json::value_t::array).get(), json::type_error); + CHECK_THROWS_AS(json(json::value_t::string).get(), json::type_error); + CHECK_THROWS_AS(json(json::value_t::number_integer).get(), json::type_error); + CHECK_THROWS_AS(json(json::value_t::number_unsigned).get(), json::type_error); + CHECK_THROWS_AS(json(json::value_t::number_float).get(), json::type_error); CHECK_THROWS_WITH(json(json::value_t::null).get(), "[json.exception.type_error.302] type must be boolean, but is null"); @@ -613,11 +614,11 @@ TEST_CASE("value conversion") SECTION("exception in case of a non-number type") { - CHECK_THROWS_AS(json(json::value_t::null).get(), json::type_error&); - CHECK_THROWS_AS(json(json::value_t::object).get(), json::type_error&); - CHECK_THROWS_AS(json(json::value_t::array).get(), json::type_error&); - CHECK_THROWS_AS(json(json::value_t::string).get(), json::type_error&); - CHECK_THROWS_AS(json(json::value_t::boolean).get(), json::type_error&); + CHECK_THROWS_AS(json(json::value_t::null).get(), json::type_error); + CHECK_THROWS_AS(json(json::value_t::object).get(), json::type_error); + CHECK_THROWS_AS(json(json::value_t::array).get(), json::type_error); + CHECK_THROWS_AS(json(json::value_t::string).get(), json::type_error); + CHECK_THROWS_AS(json(json::value_t::boolean).get(), json::type_error); CHECK_THROWS_WITH(json(json::value_t::null).get(), "[json.exception.type_error.302] type must be number, but is null"); @@ -872,11 +873,11 @@ TEST_CASE("value conversion") SECTION("exception in case of a non-string type") { - CHECK_THROWS_AS(json(json::value_t::null).get(), json::type_error&); - CHECK_THROWS_AS(json(json::value_t::object).get(), json::type_error&); - CHECK_THROWS_AS(json(json::value_t::array).get(), json::type_error&); - CHECK_THROWS_AS(json(json::value_t::string).get(), json::type_error&); - CHECK_THROWS_AS(json(json::value_t::boolean).get(), json::type_error&); + CHECK_THROWS_AS(json(json::value_t::null).get(), json::type_error); + CHECK_THROWS_AS(json(json::value_t::object).get(), json::type_error); + CHECK_THROWS_AS(json(json::value_t::array).get(), json::type_error); + CHECK_THROWS_AS(json(json::value_t::string).get(), json::type_error); + CHECK_THROWS_AS(json(json::value_t::boolean).get(), json::type_error); CHECK_THROWS_WITH(json(json::value_t::null).get(), "[json.exception.type_error.302] type must be number, but is null"); @@ -978,7 +979,7 @@ TEST_CASE("value conversion") SECTION("exception in case of a non-object type") { - CHECK_THROWS_AS((json().get>()), json::type_error&); + CHECK_THROWS_AS((json().get>()), json::type_error); CHECK_THROWS_WITH((json().get>()), "[json.exception.type_error.302] type must be object, but is null"); } } @@ -1080,11 +1081,11 @@ TEST_CASE("value conversion") SECTION("exception in case of a non-object type") { - CHECK_THROWS_AS((json().get>()), json::type_error&); - CHECK_THROWS_AS((json().get>()), json::type_error&); - CHECK_THROWS_AS((json().get>()), json::type_error&); - CHECK_THROWS_AS((json().get>()), json::type_error&); - CHECK_THROWS_AS((json().get>()), json::type_error&); + CHECK_THROWS_AS((json().get>()), json::type_error); + CHECK_THROWS_AS((json().get>()), json::type_error); + CHECK_THROWS_AS((json().get>()), json::type_error); + CHECK_THROWS_AS((json().get>()), json::type_error); + CHECK_THROWS_AS((json().get>()), json::type_error); // does type really must be an array? or it rather must not be null? // that's what I thought when other test like this one broke diff --git a/test/src/unit-deserialization.cpp b/test/src/unit-deserialization.cpp index 2798f1020..eb347b59b 100644 --- a/test/src/unit-deserialization.cpp +++ b/test/src/unit-deserialization.cpp @@ -97,7 +97,7 @@ TEST_CASE("deserialization") ss2 << "[\"foo\",1,2,3,false,{\"one\":1}"; ss3 << "[\"foo\",1,2,3,false,{\"one\":1}"; ss4 << "[\"foo\",1,2,3,false,{\"one\":1}"; - CHECK_THROWS_AS(json::parse(ss1), json::parse_error&); + CHECK_THROWS_AS(json::parse(ss1), json::parse_error); CHECK_THROWS_WITH(json::parse(ss2), "[json.exception.parse_error.101] parse error at 29: syntax error - unexpected end of input; expected ']'"); CHECK(not json::accept(ss3)); @@ -110,7 +110,7 @@ TEST_CASE("deserialization") SECTION("string") { json::string_t s = "[\"foo\",1,2,3,false,{\"one\":1}"; - CHECK_THROWS_AS(json::parse(s), json::parse_error&); + CHECK_THROWS_AS(json::parse(s), json::parse_error); CHECK_THROWS_WITH(json::parse(s), "[json.exception.parse_error.101] parse error at 29: syntax error - unexpected end of input; expected ']'"); CHECK(not json::accept(s)); @@ -126,7 +126,7 @@ TEST_CASE("deserialization") ss1 << "[\"foo\",1,2,3,false,{\"one\":1}"; ss2 << "[\"foo\",1,2,3,false,{\"one\":1}"; json j; - CHECK_THROWS_AS(j << ss1, json::parse_error&); + CHECK_THROWS_AS(j << ss1, json::parse_error); CHECK_THROWS_WITH(j << ss2, "[json.exception.parse_error.101] parse error at 29: syntax error - unexpected end of input; expected ']'"); } @@ -137,14 +137,14 @@ TEST_CASE("deserialization") ss1 << "[\"foo\",1,2,3,false,{\"one\":1}"; ss2 << "[\"foo\",1,2,3,false,{\"one\":1}"; json j; - CHECK_THROWS_AS(ss1 >> j, json::parse_error&); + CHECK_THROWS_AS(ss1 >> j, json::parse_error); CHECK_THROWS_WITH(ss2 >> j, "[json.exception.parse_error.101] parse error at 29: syntax error - unexpected end of input; expected ']'"); } SECTION("user-defined string literal") { - CHECK_THROWS_AS("[\"foo\",1,2,3,false,{\"one\":1}"_json, json::parse_error&); + CHECK_THROWS_AS("[\"foo\",1,2,3,false,{\"one\":1}"_json, json::parse_error); CHECK_THROWS_WITH("[\"foo\",1,2,3,false,{\"one\":1}"_json, "[json.exception.parse_error.101] parse error at 29: syntax error - unexpected end of input; expected ']'"); } @@ -205,7 +205,7 @@ TEST_CASE("deserialization") SECTION("empty container") { std::vector v; - CHECK_THROWS_AS(json::parse(v), json::parse_error&); + CHECK_THROWS_AS(json::parse(v), json::parse_error); CHECK(not json::accept(v)); } } @@ -257,7 +257,7 @@ TEST_CASE("deserialization") SECTION("with empty range") { std::vector v; - CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), json::parse_error&); + CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), json::parse_error); CHECK(not json::accept(std::begin(v), std::end(v))); } } @@ -268,7 +268,7 @@ TEST_CASE("deserialization") SECTION("case 1") { uint8_t v[] = {'\"', 'a', 'a', 'a', 'a', 'a', 'a', '\\', 'u'}; - CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), json::parse_error&); + CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), json::parse_error); CHECK(not json::accept(std::begin(v), std::end(v))); json j_error; @@ -279,7 +279,7 @@ TEST_CASE("deserialization") SECTION("case 2") { uint8_t v[] = {'\"', 'a', 'a', 'a', 'a', 'a', 'a', '\\', 'u', '1'}; - CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), json::parse_error&); + CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), json::parse_error); CHECK(not json::accept(std::begin(v), std::end(v))); json j_error; @@ -290,7 +290,7 @@ TEST_CASE("deserialization") SECTION("case 3") { uint8_t v[] = {'\"', 'a', 'a', 'a', 'a', 'a', 'a', '\\', 'u', '1', '1', '1', '1', '1', '1', '1', '1'}; - CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), json::parse_error&); + CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), json::parse_error); CHECK(not json::accept(std::begin(v), std::end(v))); json j_error; @@ -301,7 +301,7 @@ TEST_CASE("deserialization") SECTION("case 4") { uint8_t v[] = {'\"', 'a', 'a', 'a', 'a', 'a', 'a', 'u', '1', '1', '1', '1', '1', '1', '1', '1', '\\'}; - CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), json::parse_error&); + CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), json::parse_error); CHECK(not json::accept(std::begin(v), std::end(v))); json j_error; @@ -312,7 +312,7 @@ TEST_CASE("deserialization") SECTION("case 5") { uint8_t v[] = {'\"', 0x7F, 0xC1}; - CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), json::parse_error&); + CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), json::parse_error); CHECK(not json::accept(std::begin(v), std::end(v))); json j_error; @@ -323,7 +323,7 @@ TEST_CASE("deserialization") SECTION("case 6") { uint8_t v[] = {'\"', 0x7F, 0xDF, 0x7F}; - CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), json::parse_error&); + CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), json::parse_error); CHECK_THROWS_WITH(json::parse(std::begin(v), std::end(v)), "[json.exception.parse_error.101] parse error at 4: syntax error - invalid string: ill-formed UTF-8 byte; last read: '\"\x7f\xdf\x7f'"); CHECK(not json::accept(std::begin(v), std::end(v))); @@ -336,7 +336,7 @@ TEST_CASE("deserialization") SECTION("case 7") { uint8_t v[] = {'\"', 0x7F, 0xDF, 0xC0}; - CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), json::parse_error&); + CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), json::parse_error); CHECK(not json::accept(std::begin(v), std::end(v))); json j_error; @@ -347,7 +347,7 @@ TEST_CASE("deserialization") SECTION("case 8") { uint8_t v[] = {'\"', 0x7F, 0xE0, 0x9F}; - CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), json::parse_error&); + CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), json::parse_error); CHECK(not json::accept(std::begin(v), std::end(v))); json j_error; @@ -358,7 +358,7 @@ TEST_CASE("deserialization") SECTION("case 9") { uint8_t v[] = {'\"', 0x7F, 0xEF, 0xC0}; - CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), json::parse_error&); + CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), json::parse_error); CHECK(not json::accept(std::begin(v), std::end(v))); json j_error; @@ -369,7 +369,7 @@ TEST_CASE("deserialization") SECTION("case 10") { uint8_t v[] = {'\"', 0x7F, 0xED, 0x7F}; - CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), json::parse_error&); + CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), json::parse_error); CHECK(not json::accept(std::begin(v), std::end(v))); json j_error; @@ -380,7 +380,7 @@ TEST_CASE("deserialization") SECTION("case 11") { uint8_t v[] = {'\"', 0x7F, 0xF0, 0x8F}; - CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), json::parse_error&); + CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), json::parse_error); CHECK(not json::accept(std::begin(v), std::end(v))); json j_error; @@ -391,7 +391,7 @@ TEST_CASE("deserialization") SECTION("case 12") { uint8_t v[] = {'\"', 0x7F, 0xF0, 0xC0}; - CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), json::parse_error&); + CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), json::parse_error); CHECK(not json::accept(std::begin(v), std::end(v))); json j_error; @@ -402,7 +402,7 @@ TEST_CASE("deserialization") SECTION("case 13") { uint8_t v[] = {'\"', 0x7F, 0xF3, 0x7F}; - CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), json::parse_error&); + CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), json::parse_error); CHECK(not json::accept(std::begin(v), std::end(v))); json j_error; @@ -413,7 +413,7 @@ TEST_CASE("deserialization") SECTION("case 14") { uint8_t v[] = {'\"', 0x7F, 0xF3, 0xC0}; - CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), json::parse_error&); + CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), json::parse_error); CHECK(not json::accept(std::begin(v), std::end(v))); json j_error; @@ -424,7 +424,7 @@ TEST_CASE("deserialization") SECTION("case 15") { uint8_t v[] = {'\"', 0x7F, 0xF4, 0x7F}; - CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), json::parse_error&); + CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), json::parse_error); CHECK(not json::accept(std::begin(v), std::end(v))); json j_error; @@ -435,7 +435,7 @@ TEST_CASE("deserialization") SECTION("case 16") { uint8_t v[] = {'{', '\"', '\"', ':', '1', '1'}; - CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), json::parse_error&); + CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), json::parse_error); CHECK(not json::accept(std::begin(v), std::end(v))); json j_error; @@ -451,11 +451,11 @@ TEST_CASE("deserialization") SECTION("BOM only") { - CHECK_THROWS_AS(json::parse(bom), json::parse_error&); + CHECK_THROWS_AS(json::parse(bom), json::parse_error); CHECK_THROWS_WITH(json::parse(bom), "[json.exception.parse_error.101] parse error at 1: syntax error - unexpected end of input; expected '[', '{', or a literal"); - CHECK_THROWS_AS(json::parse(std::istringstream(bom)), json::parse_error&); + CHECK_THROWS_AS(json::parse(std::istringstream(bom)), json::parse_error); CHECK_THROWS_WITH(json::parse(std::istringstream(bom)), "[json.exception.parse_error.101] parse error at 1: syntax error - unexpected end of input; expected '[', '{', or a literal"); } @@ -468,22 +468,22 @@ TEST_CASE("deserialization") SECTION("2 byte of BOM") { - CHECK_THROWS_AS(json::parse(bom.substr(0, 2)), json::parse_error&); + CHECK_THROWS_AS(json::parse(bom.substr(0, 2)), json::parse_error); CHECK_THROWS_WITH(json::parse(bom), "[json.exception.parse_error.101] parse error at 1: syntax error - unexpected end of input; expected '[', '{', or a literal"); - CHECK_THROWS_AS(json::parse(std::istringstream(bom.substr(0, 2))), json::parse_error&); + CHECK_THROWS_AS(json::parse(std::istringstream(bom.substr(0, 2))), json::parse_error); CHECK_THROWS_WITH(json::parse(std::istringstream(bom)), "[json.exception.parse_error.101] parse error at 1: syntax error - unexpected end of input; expected '[', '{', or a literal"); } SECTION("1 byte of BOM") { - CHECK_THROWS_AS(json::parse(bom.substr(0, 1)), json::parse_error&); + CHECK_THROWS_AS(json::parse(bom.substr(0, 1)), json::parse_error); CHECK_THROWS_WITH(json::parse(bom), "[json.exception.parse_error.101] parse error at 1: syntax error - unexpected end of input; expected '[', '{', or a literal"); - CHECK_THROWS_AS(json::parse(std::istringstream(bom.substr(0, 1))), json::parse_error&); + CHECK_THROWS_AS(json::parse(std::istringstream(bom.substr(0, 1))), json::parse_error); CHECK_THROWS_WITH(json::parse(std::istringstream(bom)), "[json.exception.parse_error.101] parse error at 1: syntax error - unexpected end of input; expected '[', '{', or a literal"); } @@ -517,8 +517,8 @@ TEST_CASE("deserialization") else { // any variation is an error - CHECK_THROWS_AS(json::parse(s + "null"), json::parse_error&); - CHECK_THROWS_AS(json::parse(std::istringstream(s + "null")), json::parse_error&); + CHECK_THROWS_AS(json::parse(s + "null"), json::parse_error); + CHECK_THROWS_AS(json::parse(std::istringstream(s + "null")), json::parse_error); } } } diff --git a/test/src/unit-element_access1.cpp b/test/src/unit-element_access1.cpp index 630b1a5e9..eb4a92cbd 100644 --- a/test/src/unit-element_access1.cpp +++ b/test/src/unit-element_access1.cpp @@ -63,8 +63,8 @@ TEST_CASE("element access 1") SECTION("access outside bounds") { - CHECK_THROWS_AS(j.at(8), json::out_of_range&); - CHECK_THROWS_AS(j_const.at(8), json::out_of_range&); + CHECK_THROWS_AS(j.at(8), json::out_of_range); + CHECK_THROWS_AS(j_const.at(8), json::out_of_range); CHECK_THROWS_WITH(j.at(8), "[json.exception.out_of_range.401] array index 8 is out of range"); @@ -78,8 +78,8 @@ TEST_CASE("element access 1") { json j_nonarray(json::value_t::null); const json j_nonarray_const(j_nonarray); - CHECK_THROWS_AS(j_nonarray.at(0), json::type_error&); - CHECK_THROWS_AS(j_nonarray_const.at(0), json::type_error&); + CHECK_THROWS_AS(j_nonarray.at(0), json::type_error); + CHECK_THROWS_AS(j_nonarray_const.at(0), json::type_error); CHECK_THROWS_WITH(j_nonarray.at(0), "[json.exception.type_error.304] cannot use at() with null"); CHECK_THROWS_WITH(j_nonarray_const.at(0), "[json.exception.type_error.304] cannot use at() with null"); @@ -89,8 +89,8 @@ TEST_CASE("element access 1") { json j_nonarray(json::value_t::boolean); const json j_nonarray_const(j_nonarray); - CHECK_THROWS_AS(j_nonarray.at(0), json::type_error&); - CHECK_THROWS_AS(j_nonarray_const.at(0), json::type_error&); + CHECK_THROWS_AS(j_nonarray.at(0), json::type_error); + CHECK_THROWS_AS(j_nonarray_const.at(0), json::type_error); CHECK_THROWS_WITH(j_nonarray.at(0), "[json.exception.type_error.304] cannot use at() with boolean"); CHECK_THROWS_WITH(j_nonarray_const.at(0), "[json.exception.type_error.304] cannot use at() with boolean"); @@ -100,8 +100,8 @@ TEST_CASE("element access 1") { json j_nonarray(json::value_t::string); const json j_nonarray_const(j_nonarray); - CHECK_THROWS_AS(j_nonarray.at(0), json::type_error&); - CHECK_THROWS_AS(j_nonarray_const.at(0), json::type_error&); + CHECK_THROWS_AS(j_nonarray.at(0), json::type_error); + CHECK_THROWS_AS(j_nonarray_const.at(0), json::type_error); CHECK_THROWS_WITH(j_nonarray.at(0), "[json.exception.type_error.304] cannot use at() with string"); CHECK_THROWS_WITH(j_nonarray_const.at(0), "[json.exception.type_error.304] cannot use at() with string"); @@ -111,8 +111,8 @@ TEST_CASE("element access 1") { json j_nonarray(json::value_t::object); const json j_nonarray_const(j_nonarray); - CHECK_THROWS_AS(j_nonarray.at(0), json::type_error&); - CHECK_THROWS_AS(j_nonarray_const.at(0), json::type_error&); + CHECK_THROWS_AS(j_nonarray.at(0), json::type_error); + CHECK_THROWS_AS(j_nonarray_const.at(0), json::type_error); CHECK_THROWS_WITH(j_nonarray.at(0), "[json.exception.type_error.304] cannot use at() with object"); CHECK_THROWS_WITH(j_nonarray_const.at(0), "[json.exception.type_error.304] cannot use at() with object"); @@ -122,8 +122,8 @@ TEST_CASE("element access 1") { json j_nonarray(json::value_t::number_integer); const json j_nonarray_const(j_nonarray); - CHECK_THROWS_AS(j_nonarray.at(0), json::type_error&); - CHECK_THROWS_AS(j_nonarray_const.at(0), json::type_error&); + CHECK_THROWS_AS(j_nonarray.at(0), json::type_error); + CHECK_THROWS_AS(j_nonarray_const.at(0), json::type_error); CHECK_THROWS_WITH(j_nonarray.at(0), "[json.exception.type_error.304] cannot use at() with number"); CHECK_THROWS_WITH(j_nonarray_const.at(0), "[json.exception.type_error.304] cannot use at() with number"); @@ -133,8 +133,8 @@ TEST_CASE("element access 1") { json j_nonarray(json::value_t::number_unsigned); const json j_nonarray_const(j_nonarray); - CHECK_THROWS_AS(j_nonarray.at(0), json::type_error&); - CHECK_THROWS_AS(j_nonarray_const.at(0), json::type_error&); + CHECK_THROWS_AS(j_nonarray.at(0), json::type_error); + CHECK_THROWS_AS(j_nonarray_const.at(0), json::type_error); CHECK_THROWS_WITH(j_nonarray.at(0), "[json.exception.type_error.304] cannot use at() with number"); CHECK_THROWS_WITH(j_nonarray_const.at(0), "[json.exception.type_error.304] cannot use at() with number"); @@ -144,8 +144,8 @@ TEST_CASE("element access 1") { json j_nonarray(json::value_t::number_float); const json j_nonarray_const(j_nonarray); - CHECK_THROWS_AS(j_nonarray.at(0), json::type_error&); - CHECK_THROWS_AS(j_nonarray_const.at(0), json::type_error&); + CHECK_THROWS_AS(j_nonarray.at(0), json::type_error); + CHECK_THROWS_AS(j_nonarray_const.at(0), json::type_error); CHECK_THROWS_WITH(j_nonarray.at(0), "[json.exception.type_error.304] cannot use at() with number"); CHECK_THROWS_WITH(j_nonarray_const.at(0), "[json.exception.type_error.304] cannot use at() with number"); @@ -193,7 +193,7 @@ TEST_CASE("element access 1") json j_nonarray(json::value_t::null); const json j_nonarray_const(j_nonarray); CHECK_NOTHROW(j_nonarray[0]); - CHECK_THROWS_AS(j_nonarray_const[0], json::type_error&); + CHECK_THROWS_AS(j_nonarray_const[0], json::type_error); CHECK_THROWS_WITH(j_nonarray_const[0], "[json.exception.type_error.305] cannot use operator[] with null"); } @@ -209,8 +209,8 @@ TEST_CASE("element access 1") { json j_nonarray(json::value_t::boolean); const json j_nonarray_const(j_nonarray); - CHECK_THROWS_AS(j_nonarray[0], json::type_error&); - CHECK_THROWS_AS(j_nonarray_const[0], json::type_error&); + CHECK_THROWS_AS(j_nonarray[0], json::type_error); + CHECK_THROWS_AS(j_nonarray_const[0], json::type_error); CHECK_THROWS_WITH(j_nonarray[0], "[json.exception.type_error.305] cannot use operator[] with boolean"); CHECK_THROWS_WITH(j_nonarray_const[0], "[json.exception.type_error.305] cannot use operator[] with boolean"); } @@ -219,8 +219,8 @@ TEST_CASE("element access 1") { json j_nonarray(json::value_t::string); const json j_nonarray_const(j_nonarray); - CHECK_THROWS_AS(j_nonarray[0], json::type_error&); - CHECK_THROWS_AS(j_nonarray_const[0], json::type_error&); + CHECK_THROWS_AS(j_nonarray[0], json::type_error); + CHECK_THROWS_AS(j_nonarray_const[0], json::type_error); CHECK_THROWS_WITH(j_nonarray[0], "[json.exception.type_error.305] cannot use operator[] with string"); CHECK_THROWS_WITH(j_nonarray_const[0], "[json.exception.type_error.305] cannot use operator[] with string"); } @@ -229,8 +229,8 @@ TEST_CASE("element access 1") { json j_nonarray(json::value_t::object); const json j_nonarray_const(j_nonarray); - CHECK_THROWS_AS(j_nonarray[0], json::type_error&); - CHECK_THROWS_AS(j_nonarray_const[0], json::type_error&); + CHECK_THROWS_AS(j_nonarray[0], json::type_error); + CHECK_THROWS_AS(j_nonarray_const[0], json::type_error); CHECK_THROWS_WITH(j_nonarray[0], "[json.exception.type_error.305] cannot use operator[] with object"); CHECK_THROWS_WITH(j_nonarray_const[0], "[json.exception.type_error.305] cannot use operator[] with object"); } @@ -239,8 +239,8 @@ TEST_CASE("element access 1") { json j_nonarray(json::value_t::number_integer); const json j_nonarray_const(j_nonarray); - CHECK_THROWS_AS(j_nonarray[0], json::type_error&); - CHECK_THROWS_AS(j_nonarray_const[0], json::type_error&); + CHECK_THROWS_AS(j_nonarray[0], json::type_error); + CHECK_THROWS_AS(j_nonarray_const[0], json::type_error); CHECK_THROWS_WITH(j_nonarray[0], "[json.exception.type_error.305] cannot use operator[] with number"); CHECK_THROWS_WITH(j_nonarray_const[0], "[json.exception.type_error.305] cannot use operator[] with number"); } @@ -249,8 +249,8 @@ TEST_CASE("element access 1") { json j_nonarray(json::value_t::number_unsigned); const json j_nonarray_const(j_nonarray); - CHECK_THROWS_AS(j_nonarray[0], json::type_error&); - CHECK_THROWS_AS(j_nonarray_const[0], json::type_error&); + CHECK_THROWS_AS(j_nonarray[0], json::type_error); + CHECK_THROWS_AS(j_nonarray_const[0], json::type_error); CHECK_THROWS_WITH(j_nonarray[0], "[json.exception.type_error.305] cannot use operator[] with number"); CHECK_THROWS_WITH(j_nonarray_const[0], "[json.exception.type_error.305] cannot use operator[] with number"); } @@ -259,8 +259,8 @@ TEST_CASE("element access 1") { json j_nonarray(json::value_t::number_float); const json j_nonarray_const(j_nonarray); - CHECK_THROWS_AS(j_nonarray[0], json::type_error&); - CHECK_THROWS_AS(j_nonarray_const[0], json::type_error&); + CHECK_THROWS_AS(j_nonarray[0], json::type_error); + CHECK_THROWS_AS(j_nonarray_const[0], json::type_error); CHECK_THROWS_WITH(j_nonarray[0], "[json.exception.type_error.305] cannot use operator[] with number"); CHECK_THROWS_WITH(j_nonarray_const[0], "[json.exception.type_error.305] cannot use operator[] with number"); } @@ -313,7 +313,7 @@ TEST_CASE("element access 1") } { json jarray = {1, 1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}}; - CHECK_THROWS_AS(jarray.erase(8), json::out_of_range&); + CHECK_THROWS_AS(jarray.erase(8), json::out_of_range); CHECK_THROWS_WITH(jarray.erase(8), "[json.exception.out_of_range.401] array index 8 is out of range"); } @@ -408,10 +408,10 @@ TEST_CASE("element access 1") { json jarray = {1, 1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}}; json jarray2 = {"foo", "bar"}; - CHECK_THROWS_AS(jarray.erase(jarray2.begin()), json::invalid_iterator&); - CHECK_THROWS_AS(jarray.erase(jarray.begin(), jarray2.end()), json::invalid_iterator&); - CHECK_THROWS_AS(jarray.erase(jarray2.begin(), jarray.end()), json::invalid_iterator&); - CHECK_THROWS_AS(jarray.erase(jarray2.begin(), jarray2.end()), json::invalid_iterator&); + CHECK_THROWS_AS(jarray.erase(jarray2.begin()), json::invalid_iterator); + CHECK_THROWS_AS(jarray.erase(jarray.begin(), jarray2.end()), json::invalid_iterator); + CHECK_THROWS_AS(jarray.erase(jarray2.begin(), jarray.end()), json::invalid_iterator); + CHECK_THROWS_AS(jarray.erase(jarray2.begin(), jarray2.end()), json::invalid_iterator); CHECK_THROWS_WITH(jarray.erase(jarray2.begin()), "[json.exception.invalid_iterator.202] iterator does not fit current value"); @@ -425,10 +425,10 @@ TEST_CASE("element access 1") { json jarray = {1, 1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}}; json jarray2 = {"foo", "bar"}; - CHECK_THROWS_AS(jarray.erase(jarray2.cbegin()), json::invalid_iterator&); - CHECK_THROWS_AS(jarray.erase(jarray.cbegin(), jarray2.cend()), json::invalid_iterator&); - CHECK_THROWS_AS(jarray.erase(jarray2.cbegin(), jarray.cend()), json::invalid_iterator&); - CHECK_THROWS_AS(jarray.erase(jarray2.cbegin(), jarray2.cend()), json::invalid_iterator&); + CHECK_THROWS_AS(jarray.erase(jarray2.cbegin()), json::invalid_iterator); + CHECK_THROWS_AS(jarray.erase(jarray.cbegin(), jarray2.cend()), json::invalid_iterator); + CHECK_THROWS_AS(jarray.erase(jarray2.cbegin(), jarray.cend()), json::invalid_iterator); + CHECK_THROWS_AS(jarray.erase(jarray2.cbegin(), jarray2.cend()), json::invalid_iterator); CHECK_THROWS_WITH(jarray.erase(jarray2.cbegin()), "[json.exception.invalid_iterator.202] iterator does not fit current value"); @@ -447,7 +447,7 @@ TEST_CASE("element access 1") SECTION("null") { json j_nonobject(json::value_t::null); - CHECK_THROWS_AS(j_nonobject.erase(0), json::type_error&); + CHECK_THROWS_AS(j_nonobject.erase(0), json::type_error); CHECK_THROWS_WITH(j_nonobject.erase(0), "[json.exception.type_error.307] cannot use erase() with null"); } @@ -455,7 +455,7 @@ TEST_CASE("element access 1") SECTION("boolean") { json j_nonobject(json::value_t::boolean); - CHECK_THROWS_AS(j_nonobject.erase(0), json::type_error&); + CHECK_THROWS_AS(j_nonobject.erase(0), json::type_error); CHECK_THROWS_WITH(j_nonobject.erase(0), "[json.exception.type_error.307] cannot use erase() with boolean"); } @@ -463,7 +463,7 @@ TEST_CASE("element access 1") SECTION("string") { json j_nonobject(json::value_t::string); - CHECK_THROWS_AS(j_nonobject.erase(0), json::type_error&); + CHECK_THROWS_AS(j_nonobject.erase(0), json::type_error); CHECK_THROWS_WITH(j_nonobject.erase(0), "[json.exception.type_error.307] cannot use erase() with string"); } @@ -471,7 +471,7 @@ TEST_CASE("element access 1") SECTION("object") { json j_nonobject(json::value_t::object); - CHECK_THROWS_AS(j_nonobject.erase(0), json::type_error&); + CHECK_THROWS_AS(j_nonobject.erase(0), json::type_error); CHECK_THROWS_WITH(j_nonobject.erase(0), "[json.exception.type_error.307] cannot use erase() with object"); } @@ -479,7 +479,7 @@ TEST_CASE("element access 1") SECTION("number (integer)") { json j_nonobject(json::value_t::number_integer); - CHECK_THROWS_AS(j_nonobject.erase(0), json::type_error&); + CHECK_THROWS_AS(j_nonobject.erase(0), json::type_error); CHECK_THROWS_WITH(j_nonobject.erase(0), "[json.exception.type_error.307] cannot use erase() with number"); } @@ -487,7 +487,7 @@ TEST_CASE("element access 1") SECTION("number (unsigned)") { json j_nonobject(json::value_t::number_unsigned); - CHECK_THROWS_AS(j_nonobject.erase(0), json::type_error&); + CHECK_THROWS_AS(j_nonobject.erase(0), json::type_error); CHECK_THROWS_WITH(j_nonobject.erase(0), "[json.exception.type_error.307] cannot use erase() with number"); } @@ -495,7 +495,7 @@ TEST_CASE("element access 1") SECTION("number (floating-point)") { json j_nonobject(json::value_t::number_float); - CHECK_THROWS_AS(j_nonobject.erase(0), json::type_error&); + CHECK_THROWS_AS(j_nonobject.erase(0), json::type_error); CHECK_THROWS_WITH(j_nonobject.erase(0), "[json.exception.type_error.307] cannot use erase() with number"); } @@ -511,15 +511,15 @@ TEST_CASE("element access 1") { { json j; - CHECK_THROWS_AS(j.front(), json::invalid_iterator&); - CHECK_THROWS_AS(j.back(), json::invalid_iterator&); + CHECK_THROWS_AS(j.front(), json::invalid_iterator); + CHECK_THROWS_AS(j.back(), json::invalid_iterator); CHECK_THROWS_WITH(j.front(), "[json.exception.invalid_iterator.214] cannot get value"); CHECK_THROWS_WITH(j.back(), "[json.exception.invalid_iterator.214] cannot get value"); } { const json j{}; - CHECK_THROWS_AS(j.front(), json::invalid_iterator&); - CHECK_THROWS_AS(j.back(), json::invalid_iterator&); + CHECK_THROWS_AS(j.front(), json::invalid_iterator); + CHECK_THROWS_AS(j.back(), json::invalid_iterator); CHECK_THROWS_WITH(j.front(), "[json.exception.invalid_iterator.214] cannot get value"); CHECK_THROWS_WITH(j.back(), "[json.exception.invalid_iterator.214] cannot get value"); } @@ -602,13 +602,13 @@ TEST_CASE("element access 1") { { json j; - CHECK_THROWS_AS(j.erase(j.begin()), json::type_error&); + CHECK_THROWS_AS(j.erase(j.begin()), json::type_error); CHECK_THROWS_WITH(j.erase(j.begin()), "[json.exception.type_error.307] cannot use erase() with null"); } { json j; - CHECK_THROWS_AS(j.erase(j.cbegin()), json::type_error&); + CHECK_THROWS_AS(j.erase(j.cbegin()), json::type_error); CHECK_THROWS_WITH(j.erase(j.begin()), "[json.exception.type_error.307] cannot use erase() with null"); } @@ -701,13 +701,13 @@ TEST_CASE("element access 1") { { json j = "foo"; - CHECK_THROWS_AS(j.erase(j.end()), json::invalid_iterator&); + CHECK_THROWS_AS(j.erase(j.end()), json::invalid_iterator); CHECK_THROWS_WITH(j.erase(j.end()), "[json.exception.invalid_iterator.205] iterator out of range"); } { json j = "bar"; - CHECK_THROWS_AS(j.erase(j.cend()), json::invalid_iterator&); + CHECK_THROWS_AS(j.erase(j.cend()), json::invalid_iterator); CHECK_THROWS_WITH(j.erase(j.cend()), "[json.exception.invalid_iterator.205] iterator out of range"); } @@ -717,13 +717,13 @@ TEST_CASE("element access 1") { { json j = false; - CHECK_THROWS_AS(j.erase(j.end()), json::invalid_iterator&); + CHECK_THROWS_AS(j.erase(j.end()), json::invalid_iterator); CHECK_THROWS_WITH(j.erase(j.end()), "[json.exception.invalid_iterator.205] iterator out of range"); } { json j = true; - CHECK_THROWS_AS(j.erase(j.cend()), json::invalid_iterator&); + CHECK_THROWS_AS(j.erase(j.cend()), json::invalid_iterator); CHECK_THROWS_WITH(j.erase(j.cend()), "[json.exception.invalid_iterator.205] iterator out of range"); } @@ -733,13 +733,13 @@ TEST_CASE("element access 1") { { json j = 17; - CHECK_THROWS_AS(j.erase(j.end()), json::invalid_iterator&); + CHECK_THROWS_AS(j.erase(j.end()), json::invalid_iterator); CHECK_THROWS_WITH(j.erase(j.end()), "[json.exception.invalid_iterator.205] iterator out of range"); } { json j = 17; - CHECK_THROWS_AS(j.erase(j.cend()), json::invalid_iterator&); + CHECK_THROWS_AS(j.erase(j.cend()), json::invalid_iterator); CHECK_THROWS_WITH(j.erase(j.cend()), "[json.exception.invalid_iterator.205] iterator out of range"); } @@ -749,13 +749,13 @@ TEST_CASE("element access 1") { { json j = 17u; - CHECK_THROWS_AS(j.erase(j.end()), json::invalid_iterator&); + CHECK_THROWS_AS(j.erase(j.end()), json::invalid_iterator); CHECK_THROWS_WITH(j.erase(j.end()), "[json.exception.invalid_iterator.205] iterator out of range"); } { json j = 17u; - CHECK_THROWS_AS(j.erase(j.cend()), json::invalid_iterator&); + CHECK_THROWS_AS(j.erase(j.cend()), json::invalid_iterator); CHECK_THROWS_WITH(j.erase(j.cend()), "[json.exception.invalid_iterator.205] iterator out of range"); } @@ -765,13 +765,13 @@ TEST_CASE("element access 1") { { json j = 23.42; - CHECK_THROWS_AS(j.erase(j.end()), json::invalid_iterator&); + CHECK_THROWS_AS(j.erase(j.end()), json::invalid_iterator); CHECK_THROWS_WITH(j.erase(j.end()), "[json.exception.invalid_iterator.205] iterator out of range"); } { json j = 23.42; - CHECK_THROWS_AS(j.erase(j.cend()), json::invalid_iterator&); + CHECK_THROWS_AS(j.erase(j.cend()), json::invalid_iterator); CHECK_THROWS_WITH(j.erase(j.cend()), "[json.exception.invalid_iterator.205] iterator out of range"); } @@ -784,13 +784,13 @@ TEST_CASE("element access 1") { { json j; - CHECK_THROWS_AS(j.erase(j.begin(), j.end()), json::type_error&); + CHECK_THROWS_AS(j.erase(j.begin(), j.end()), json::type_error); CHECK_THROWS_WITH(j.erase(j.begin(), j.end()), "[json.exception.type_error.307] cannot use erase() with null"); } { json j; - CHECK_THROWS_AS(j.erase(j.cbegin(), j.cend()), json::type_error&); + CHECK_THROWS_AS(j.erase(j.cbegin(), j.cend()), json::type_error); CHECK_THROWS_WITH(j.erase(j.cbegin(), j.cend()), "[json.exception.type_error.307] cannot use erase() with null"); } @@ -883,15 +883,15 @@ TEST_CASE("element access 1") { { json j = "foo"; - CHECK_THROWS_AS(j.erase(j.end(), j.end()), json::invalid_iterator&); - CHECK_THROWS_AS(j.erase(j.begin(), j.begin()), json::invalid_iterator&); + CHECK_THROWS_AS(j.erase(j.end(), j.end()), json::invalid_iterator); + CHECK_THROWS_AS(j.erase(j.begin(), j.begin()), json::invalid_iterator); CHECK_THROWS_WITH(j.erase(j.end(), j.end()), "[json.exception.invalid_iterator.204] iterators out of range"); CHECK_THROWS_WITH(j.erase(j.begin(), j.begin()), "[json.exception.invalid_iterator.204] iterators out of range"); } { json j = "bar"; - CHECK_THROWS_AS(j.erase(j.cend(), j.cend()), json::invalid_iterator&); - CHECK_THROWS_AS(j.erase(j.cbegin(), j.cbegin()), json::invalid_iterator&); + CHECK_THROWS_AS(j.erase(j.cend(), j.cend()), json::invalid_iterator); + CHECK_THROWS_AS(j.erase(j.cbegin(), j.cbegin()), json::invalid_iterator); CHECK_THROWS_WITH(j.erase(j.cend(), j.cend()), "[json.exception.invalid_iterator.204] iterators out of range"); CHECK_THROWS_WITH(j.erase(j.cbegin(), j.cbegin()), "[json.exception.invalid_iterator.204] iterators out of range"); } @@ -901,15 +901,15 @@ TEST_CASE("element access 1") { { json j = false; - CHECK_THROWS_AS(j.erase(j.end(), j.end()), json::invalid_iterator&); - CHECK_THROWS_AS(j.erase(j.begin(), j.begin()), json::invalid_iterator&); + CHECK_THROWS_AS(j.erase(j.end(), j.end()), json::invalid_iterator); + CHECK_THROWS_AS(j.erase(j.begin(), j.begin()), json::invalid_iterator); CHECK_THROWS_WITH(j.erase(j.end(), j.end()), "[json.exception.invalid_iterator.204] iterators out of range"); CHECK_THROWS_WITH(j.erase(j.begin(), j.begin()), "[json.exception.invalid_iterator.204] iterators out of range"); } { json j = true; - CHECK_THROWS_AS(j.erase(j.cend(), j.cend()), json::invalid_iterator&); - CHECK_THROWS_AS(j.erase(j.cbegin(), j.cbegin()), json::invalid_iterator&); + CHECK_THROWS_AS(j.erase(j.cend(), j.cend()), json::invalid_iterator); + CHECK_THROWS_AS(j.erase(j.cbegin(), j.cbegin()), json::invalid_iterator); CHECK_THROWS_WITH(j.erase(j.cend(), j.cend()), "[json.exception.invalid_iterator.204] iterators out of range"); CHECK_THROWS_WITH(j.erase(j.cbegin(), j.cbegin()), "[json.exception.invalid_iterator.204] iterators out of range"); } @@ -919,15 +919,15 @@ TEST_CASE("element access 1") { { json j = 17; - CHECK_THROWS_AS(j.erase(j.end(), j.end()), json::invalid_iterator&); - CHECK_THROWS_AS(j.erase(j.begin(), j.begin()), json::invalid_iterator&); + CHECK_THROWS_AS(j.erase(j.end(), j.end()), json::invalid_iterator); + CHECK_THROWS_AS(j.erase(j.begin(), j.begin()), json::invalid_iterator); CHECK_THROWS_WITH(j.erase(j.end(), j.end()), "[json.exception.invalid_iterator.204] iterators out of range"); CHECK_THROWS_WITH(j.erase(j.begin(), j.begin()), "[json.exception.invalid_iterator.204] iterators out of range"); } { json j = 17; - CHECK_THROWS_AS(j.erase(j.cend(), j.cend()), json::invalid_iterator&); - CHECK_THROWS_AS(j.erase(j.cbegin(), j.cbegin()), json::invalid_iterator&); + CHECK_THROWS_AS(j.erase(j.cend(), j.cend()), json::invalid_iterator); + CHECK_THROWS_AS(j.erase(j.cbegin(), j.cbegin()), json::invalid_iterator); CHECK_THROWS_WITH(j.erase(j.cend(), j.cend()), "[json.exception.invalid_iterator.204] iterators out of range"); CHECK_THROWS_WITH(j.erase(j.cbegin(), j.cbegin()), "[json.exception.invalid_iterator.204] iterators out of range"); } @@ -937,15 +937,15 @@ TEST_CASE("element access 1") { { json j = 17u; - CHECK_THROWS_AS(j.erase(j.end(), j.end()), json::invalid_iterator&); - CHECK_THROWS_AS(j.erase(j.begin(), j.begin()), json::invalid_iterator&); + CHECK_THROWS_AS(j.erase(j.end(), j.end()), json::invalid_iterator); + CHECK_THROWS_AS(j.erase(j.begin(), j.begin()), json::invalid_iterator); CHECK_THROWS_WITH(j.erase(j.end(), j.end()), "[json.exception.invalid_iterator.204] iterators out of range"); CHECK_THROWS_WITH(j.erase(j.begin(), j.begin()), "[json.exception.invalid_iterator.204] iterators out of range"); } { json j = 17u; - CHECK_THROWS_AS(j.erase(j.cend(), j.cend()), json::invalid_iterator&); - CHECK_THROWS_AS(j.erase(j.cbegin(), j.cbegin()), json::invalid_iterator&); + CHECK_THROWS_AS(j.erase(j.cend(), j.cend()), json::invalid_iterator); + CHECK_THROWS_AS(j.erase(j.cbegin(), j.cbegin()), json::invalid_iterator); CHECK_THROWS_WITH(j.erase(j.cend(), j.cend()), "[json.exception.invalid_iterator.204] iterators out of range"); CHECK_THROWS_WITH(j.erase(j.cbegin(), j.cbegin()), "[json.exception.invalid_iterator.204] iterators out of range"); } @@ -955,15 +955,15 @@ TEST_CASE("element access 1") { { json j = 23.42; - CHECK_THROWS_AS(j.erase(j.end(), j.end()), json::invalid_iterator&); - CHECK_THROWS_AS(j.erase(j.begin(), j.begin()), json::invalid_iterator&); + CHECK_THROWS_AS(j.erase(j.end(), j.end()), json::invalid_iterator); + CHECK_THROWS_AS(j.erase(j.begin(), j.begin()), json::invalid_iterator); CHECK_THROWS_WITH(j.erase(j.end(), j.end()), "[json.exception.invalid_iterator.204] iterators out of range"); CHECK_THROWS_WITH(j.erase(j.begin(), j.begin()), "[json.exception.invalid_iterator.204] iterators out of range"); } { json j = 23.42; - CHECK_THROWS_AS(j.erase(j.cend(), j.cend()), json::invalid_iterator&); - CHECK_THROWS_AS(j.erase(j.cbegin(), j.cbegin()), json::invalid_iterator&); + CHECK_THROWS_AS(j.erase(j.cend(), j.cend()), json::invalid_iterator); + CHECK_THROWS_AS(j.erase(j.cbegin(), j.cbegin()), json::invalid_iterator); CHECK_THROWS_WITH(j.erase(j.cend(), j.cend()), "[json.exception.invalid_iterator.204] iterators out of range"); CHECK_THROWS_WITH(j.erase(j.cbegin(), j.cbegin()), "[json.exception.invalid_iterator.204] iterators out of range"); } diff --git a/test/src/unit-element_access2.cpp b/test/src/unit-element_access2.cpp index 5950349bc..ec03507e5 100644 --- a/test/src/unit-element_access2.cpp +++ b/test/src/unit-element_access2.cpp @@ -63,8 +63,8 @@ TEST_CASE("element access 2") SECTION("access outside bounds") { - CHECK_THROWS_AS(j.at("foo"), json::out_of_range&); - CHECK_THROWS_AS(j_const.at("foo"), json::out_of_range&); + CHECK_THROWS_AS(j.at("foo"), json::out_of_range); + CHECK_THROWS_AS(j_const.at("foo"), json::out_of_range); CHECK_THROWS_WITH(j.at("foo"), "[json.exception.out_of_range.403] key 'foo' not found"); CHECK_THROWS_WITH(j_const.at("foo"), @@ -77,8 +77,8 @@ TEST_CASE("element access 2") { json j_nonobject(json::value_t::null); const json j_nonobject_const(j_nonobject); - CHECK_THROWS_AS(j_nonobject.at("foo"), json::type_error&); - CHECK_THROWS_AS(j_nonobject_const.at("foo"), json::type_error&); + CHECK_THROWS_AS(j_nonobject.at("foo"), json::type_error); + CHECK_THROWS_AS(j_nonobject_const.at("foo"), json::type_error); CHECK_THROWS_WITH(j_nonobject.at("foo"), "[json.exception.type_error.304] cannot use at() with null"); CHECK_THROWS_WITH(j_nonobject_const.at("foo"), "[json.exception.type_error.304] cannot use at() with null"); } @@ -87,8 +87,8 @@ TEST_CASE("element access 2") { json j_nonobject(json::value_t::boolean); const json j_nonobject_const(j_nonobject); - CHECK_THROWS_AS(j_nonobject.at("foo"), json::type_error&); - CHECK_THROWS_AS(j_nonobject_const.at("foo"), json::type_error&); + CHECK_THROWS_AS(j_nonobject.at("foo"), json::type_error); + CHECK_THROWS_AS(j_nonobject_const.at("foo"), json::type_error); CHECK_THROWS_WITH(j_nonobject.at("foo"), "[json.exception.type_error.304] cannot use at() with boolean"); CHECK_THROWS_WITH(j_nonobject_const.at("foo"), "[json.exception.type_error.304] cannot use at() with boolean"); } @@ -97,8 +97,8 @@ TEST_CASE("element access 2") { json j_nonobject(json::value_t::string); const json j_nonobject_const(j_nonobject); - CHECK_THROWS_AS(j_nonobject.at("foo"), json::type_error&); - CHECK_THROWS_AS(j_nonobject_const.at("foo"), json::type_error&); + CHECK_THROWS_AS(j_nonobject.at("foo"), json::type_error); + CHECK_THROWS_AS(j_nonobject_const.at("foo"), json::type_error); CHECK_THROWS_WITH(j_nonobject.at("foo"), "[json.exception.type_error.304] cannot use at() with string"); CHECK_THROWS_WITH(j_nonobject_const.at("foo"), "[json.exception.type_error.304] cannot use at() with string"); } @@ -107,8 +107,8 @@ TEST_CASE("element access 2") { json j_nonobject(json::value_t::array); const json j_nonobject_const(j_nonobject); - CHECK_THROWS_AS(j_nonobject.at("foo"), json::type_error&); - CHECK_THROWS_AS(j_nonobject_const.at("foo"), json::type_error&); + CHECK_THROWS_AS(j_nonobject.at("foo"), json::type_error); + CHECK_THROWS_AS(j_nonobject_const.at("foo"), json::type_error); CHECK_THROWS_WITH(j_nonobject.at("foo"), "[json.exception.type_error.304] cannot use at() with array"); CHECK_THROWS_WITH(j_nonobject_const.at("foo"), "[json.exception.type_error.304] cannot use at() with array"); } @@ -117,8 +117,8 @@ TEST_CASE("element access 2") { json j_nonobject(json::value_t::number_integer); const json j_nonobject_const(j_nonobject); - CHECK_THROWS_AS(j_nonobject.at("foo"), json::type_error&); - CHECK_THROWS_AS(j_nonobject_const.at("foo"), json::type_error&); + CHECK_THROWS_AS(j_nonobject.at("foo"), json::type_error); + CHECK_THROWS_AS(j_nonobject_const.at("foo"), json::type_error); CHECK_THROWS_WITH(j_nonobject.at("foo"), "[json.exception.type_error.304] cannot use at() with number"); CHECK_THROWS_WITH(j_nonobject_const.at("foo"), "[json.exception.type_error.304] cannot use at() with number"); } @@ -127,8 +127,8 @@ TEST_CASE("element access 2") { json j_nonobject(json::value_t::number_unsigned); const json j_nonobject_const(j_nonobject); - CHECK_THROWS_AS(j_nonobject.at("foo"), json::type_error&); - CHECK_THROWS_AS(j_nonobject_const.at("foo"), json::type_error&); + CHECK_THROWS_AS(j_nonobject.at("foo"), json::type_error); + CHECK_THROWS_AS(j_nonobject_const.at("foo"), json::type_error); CHECK_THROWS_WITH(j_nonobject.at("foo"), "[json.exception.type_error.304] cannot use at() with number"); CHECK_THROWS_WITH(j_nonobject_const.at("foo"), "[json.exception.type_error.304] cannot use at() with number"); } @@ -137,8 +137,8 @@ TEST_CASE("element access 2") { json j_nonobject(json::value_t::number_float); const json j_nonobject_const(j_nonobject); - CHECK_THROWS_AS(j_nonobject.at("foo"), json::type_error&); - CHECK_THROWS_AS(j_nonobject_const.at("foo"), json::type_error&); + CHECK_THROWS_AS(j_nonobject.at("foo"), json::type_error); + CHECK_THROWS_AS(j_nonobject_const.at("foo"), json::type_error); CHECK_THROWS_WITH(j_nonobject.at("foo"), "[json.exception.type_error.304] cannot use at() with number"); CHECK_THROWS_WITH(j_nonobject_const.at("foo"), "[json.exception.type_error.304] cannot use at() with number"); } @@ -202,8 +202,8 @@ TEST_CASE("element access 2") { json j_nonobject(json::value_t::null); const json j_nonobject_const(j_nonobject); - CHECK_THROWS_AS(j_nonobject.value("foo", 1), json::type_error&); - CHECK_THROWS_AS(j_nonobject_const.value("foo", 1), json::type_error&); + CHECK_THROWS_AS(j_nonobject.value("foo", 1), json::type_error); + CHECK_THROWS_AS(j_nonobject_const.value("foo", 1), json::type_error); CHECK_THROWS_WITH(j_nonobject.value("foo", 1), "[json.exception.type_error.306] cannot use value() with null"); CHECK_THROWS_WITH(j_nonobject_const.value("foo", 1), @@ -214,8 +214,8 @@ TEST_CASE("element access 2") { json j_nonobject(json::value_t::boolean); const json j_nonobject_const(j_nonobject); - CHECK_THROWS_AS(j_nonobject.value("foo", 1), json::type_error&); - CHECK_THROWS_AS(j_nonobject_const.value("foo", 1), json::type_error&); + CHECK_THROWS_AS(j_nonobject.value("foo", 1), json::type_error); + CHECK_THROWS_AS(j_nonobject_const.value("foo", 1), json::type_error); CHECK_THROWS_WITH(j_nonobject.value("foo", 1), "[json.exception.type_error.306] cannot use value() with boolean"); CHECK_THROWS_WITH(j_nonobject_const.value("foo", 1), @@ -226,8 +226,8 @@ TEST_CASE("element access 2") { json j_nonobject(json::value_t::string); const json j_nonobject_const(j_nonobject); - CHECK_THROWS_AS(j_nonobject.value("foo", 1), json::type_error&); - CHECK_THROWS_AS(j_nonobject_const.value("foo", 1), json::type_error&); + CHECK_THROWS_AS(j_nonobject.value("foo", 1), json::type_error); + CHECK_THROWS_AS(j_nonobject_const.value("foo", 1), json::type_error); CHECK_THROWS_WITH(j_nonobject.value("foo", 1), "[json.exception.type_error.306] cannot use value() with string"); CHECK_THROWS_WITH(j_nonobject_const.value("foo", 1), @@ -238,8 +238,8 @@ TEST_CASE("element access 2") { json j_nonobject(json::value_t::array); const json j_nonobject_const(j_nonobject); - CHECK_THROWS_AS(j_nonobject.value("foo", 1), json::type_error&); - CHECK_THROWS_AS(j_nonobject_const.value("foo", 1), json::type_error&); + CHECK_THROWS_AS(j_nonobject.value("foo", 1), json::type_error); + CHECK_THROWS_AS(j_nonobject_const.value("foo", 1), json::type_error); CHECK_THROWS_WITH(j_nonobject.value("foo", 1), "[json.exception.type_error.306] cannot use value() with array"); CHECK_THROWS_WITH(j_nonobject_const.value("foo", 1), @@ -250,8 +250,8 @@ TEST_CASE("element access 2") { json j_nonobject(json::value_t::number_integer); const json j_nonobject_const(j_nonobject); - CHECK_THROWS_AS(j_nonobject.value("foo", 1), json::type_error&); - CHECK_THROWS_AS(j_nonobject_const.value("foo", 1), json::type_error&); + CHECK_THROWS_AS(j_nonobject.value("foo", 1), json::type_error); + CHECK_THROWS_AS(j_nonobject_const.value("foo", 1), json::type_error); CHECK_THROWS_WITH(j_nonobject.value("foo", 1), "[json.exception.type_error.306] cannot use value() with number"); CHECK_THROWS_WITH(j_nonobject_const.value("foo", 1), @@ -262,8 +262,8 @@ TEST_CASE("element access 2") { json j_nonobject(json::value_t::number_unsigned); const json j_nonobject_const(j_nonobject); - CHECK_THROWS_AS(j_nonobject.value("foo", 1), json::type_error&); - CHECK_THROWS_AS(j_nonobject_const.value("foo", 1), json::type_error&); + CHECK_THROWS_AS(j_nonobject.value("foo", 1), json::type_error); + CHECK_THROWS_AS(j_nonobject_const.value("foo", 1), json::type_error); CHECK_THROWS_WITH(j_nonobject.value("foo", 1), "[json.exception.type_error.306] cannot use value() with number"); CHECK_THROWS_WITH(j_nonobject_const.value("foo", 1), @@ -274,8 +274,8 @@ TEST_CASE("element access 2") { json j_nonobject(json::value_t::number_float); const json j_nonobject_const(j_nonobject); - CHECK_THROWS_AS(j_nonobject.value("foo", 1), json::type_error&); - CHECK_THROWS_AS(j_nonobject_const.value("foo", 1), json::type_error&); + CHECK_THROWS_AS(j_nonobject.value("foo", 1), json::type_error); + CHECK_THROWS_AS(j_nonobject_const.value("foo", 1), json::type_error); CHECK_THROWS_WITH(j_nonobject.value("foo", 1), "[json.exception.type_error.306] cannot use value() with number"); CHECK_THROWS_WITH(j_nonobject_const.value("foo", 1), @@ -320,8 +320,8 @@ TEST_CASE("element access 2") { json j_nonobject(json::value_t::null); const json j_nonobject_const(j_nonobject); - CHECK_THROWS_AS(j_nonobject.value("/foo"_json_pointer, 1), json::type_error&); - CHECK_THROWS_AS(j_nonobject_const.value("/foo"_json_pointer, 1), json::type_error&); + CHECK_THROWS_AS(j_nonobject.value("/foo"_json_pointer, 1), json::type_error); + CHECK_THROWS_AS(j_nonobject_const.value("/foo"_json_pointer, 1), json::type_error); CHECK_THROWS_WITH(j_nonobject.value("/foo"_json_pointer, 1), "[json.exception.type_error.306] cannot use value() with null"); CHECK_THROWS_WITH(j_nonobject_const.value("/foo"_json_pointer, 1), @@ -332,8 +332,8 @@ TEST_CASE("element access 2") { json j_nonobject(json::value_t::boolean); const json j_nonobject_const(j_nonobject); - CHECK_THROWS_AS(j_nonobject.value("/foo"_json_pointer, 1), json::type_error&); - CHECK_THROWS_AS(j_nonobject_const.value("/foo"_json_pointer, 1), json::type_error&); + CHECK_THROWS_AS(j_nonobject.value("/foo"_json_pointer, 1), json::type_error); + CHECK_THROWS_AS(j_nonobject_const.value("/foo"_json_pointer, 1), json::type_error); CHECK_THROWS_WITH(j_nonobject.value("/foo"_json_pointer, 1), "[json.exception.type_error.306] cannot use value() with boolean"); CHECK_THROWS_WITH(j_nonobject_const.value("/foo"_json_pointer, 1), @@ -344,8 +344,8 @@ TEST_CASE("element access 2") { json j_nonobject(json::value_t::string); const json j_nonobject_const(j_nonobject); - CHECK_THROWS_AS(j_nonobject.value("/foo"_json_pointer, 1), json::type_error&); - CHECK_THROWS_AS(j_nonobject_const.value("/foo"_json_pointer, 1), json::type_error&); + CHECK_THROWS_AS(j_nonobject.value("/foo"_json_pointer, 1), json::type_error); + CHECK_THROWS_AS(j_nonobject_const.value("/foo"_json_pointer, 1), json::type_error); CHECK_THROWS_WITH(j_nonobject.value("/foo"_json_pointer, 1), "[json.exception.type_error.306] cannot use value() with string"); CHECK_THROWS_WITH(j_nonobject_const.value("/foo"_json_pointer, 1), @@ -356,8 +356,8 @@ TEST_CASE("element access 2") { json j_nonobject(json::value_t::array); const json j_nonobject_const(j_nonobject); - CHECK_THROWS_AS(j_nonobject.value("/foo"_json_pointer, 1), json::type_error&); - CHECK_THROWS_AS(j_nonobject_const.value("/foo"_json_pointer, 1), json::type_error&); + CHECK_THROWS_AS(j_nonobject.value("/foo"_json_pointer, 1), json::type_error); + CHECK_THROWS_AS(j_nonobject_const.value("/foo"_json_pointer, 1), json::type_error); CHECK_THROWS_WITH(j_nonobject.value("/foo"_json_pointer, 1), "[json.exception.type_error.306] cannot use value() with array"); CHECK_THROWS_WITH(j_nonobject_const.value("/foo"_json_pointer, 1), @@ -368,8 +368,8 @@ TEST_CASE("element access 2") { json j_nonobject(json::value_t::number_integer); const json j_nonobject_const(j_nonobject); - CHECK_THROWS_AS(j_nonobject.value("/foo"_json_pointer, 1), json::type_error&); - CHECK_THROWS_AS(j_nonobject_const.value("/foo"_json_pointer, 1), json::type_error&); + CHECK_THROWS_AS(j_nonobject.value("/foo"_json_pointer, 1), json::type_error); + CHECK_THROWS_AS(j_nonobject_const.value("/foo"_json_pointer, 1), json::type_error); CHECK_THROWS_WITH(j_nonobject.value("/foo"_json_pointer, 1), "[json.exception.type_error.306] cannot use value() with number"); CHECK_THROWS_WITH(j_nonobject_const.value("/foo"_json_pointer, 1), @@ -380,8 +380,8 @@ TEST_CASE("element access 2") { json j_nonobject(json::value_t::number_unsigned); const json j_nonobject_const(j_nonobject); - CHECK_THROWS_AS(j_nonobject.value("/foo"_json_pointer, 1), json::type_error&); - CHECK_THROWS_AS(j_nonobject_const.value("/foo"_json_pointer, 1), json::type_error&); + CHECK_THROWS_AS(j_nonobject.value("/foo"_json_pointer, 1), json::type_error); + CHECK_THROWS_AS(j_nonobject_const.value("/foo"_json_pointer, 1), json::type_error); CHECK_THROWS_WITH(j_nonobject.value("/foo"_json_pointer, 1), "[json.exception.type_error.306] cannot use value() with number"); CHECK_THROWS_WITH(j_nonobject_const.value("/foo"_json_pointer, 1), @@ -392,8 +392,8 @@ TEST_CASE("element access 2") { json j_nonobject(json::value_t::number_float); const json j_nonobject_const(j_nonobject); - CHECK_THROWS_AS(j_nonobject.value("/foo"_json_pointer, 1), json::type_error&); - CHECK_THROWS_AS(j_nonobject_const.value("/foo"_json_pointer, 1), json::type_error&); + CHECK_THROWS_AS(j_nonobject.value("/foo"_json_pointer, 1), json::type_error); + CHECK_THROWS_AS(j_nonobject_const.value("/foo"_json_pointer, 1), json::type_error); CHECK_THROWS_WITH(j_nonobject.value("/foo"_json_pointer, 1), "[json.exception.type_error.306] cannot use value() with number"); CHECK_THROWS_WITH(j_nonobject_const.value("/foo"_json_pointer, 1), @@ -472,8 +472,8 @@ TEST_CASE("element access 2") const json j_const_nonobject(j_nonobject); CHECK_NOTHROW(j_nonobject["foo"]); CHECK_NOTHROW(j_nonobject2[json::object_t::key_type("foo")]); - CHECK_THROWS_AS(j_const_nonobject["foo"], json::type_error&); - CHECK_THROWS_AS(j_const_nonobject[json::object_t::key_type("foo")], json::type_error&); + CHECK_THROWS_AS(j_const_nonobject["foo"], json::type_error); + CHECK_THROWS_AS(j_const_nonobject[json::object_t::key_type("foo")], json::type_error); CHECK_THROWS_WITH(j_const_nonobject["foo"], "[json.exception.type_error.305] cannot use operator[] with null"); CHECK_THROWS_WITH(j_const_nonobject[json::object_t::key_type("foo")], "[json.exception.type_error.305] cannot use operator[] with null"); @@ -483,10 +483,10 @@ TEST_CASE("element access 2") { json j_nonobject(json::value_t::boolean); const json j_const_nonobject(j_nonobject); - CHECK_THROWS_AS(j_nonobject["foo"], json::type_error&); - CHECK_THROWS_AS(j_nonobject[json::object_t::key_type("foo")], json::type_error&); - CHECK_THROWS_AS(j_const_nonobject["foo"], json::type_error&); - CHECK_THROWS_AS(j_const_nonobject[json::object_t::key_type("foo")], json::type_error&); + CHECK_THROWS_AS(j_nonobject["foo"], json::type_error); + CHECK_THROWS_AS(j_nonobject[json::object_t::key_type("foo")], json::type_error); + CHECK_THROWS_AS(j_const_nonobject["foo"], json::type_error); + CHECK_THROWS_AS(j_const_nonobject[json::object_t::key_type("foo")], json::type_error); CHECK_THROWS_WITH(j_nonobject["foo"], "[json.exception.type_error.305] cannot use operator[] with boolean"); CHECK_THROWS_WITH(j_nonobject[json::object_t::key_type("foo")], @@ -501,10 +501,10 @@ TEST_CASE("element access 2") { json j_nonobject(json::value_t::string); const json j_const_nonobject(j_nonobject); - CHECK_THROWS_AS(j_nonobject["foo"], json::type_error&); - CHECK_THROWS_AS(j_nonobject[json::object_t::key_type("foo")], json::type_error&); - CHECK_THROWS_AS(j_const_nonobject["foo"], json::type_error&); - CHECK_THROWS_AS(j_const_nonobject[json::object_t::key_type("foo")], json::type_error&); + CHECK_THROWS_AS(j_nonobject["foo"], json::type_error); + CHECK_THROWS_AS(j_nonobject[json::object_t::key_type("foo")], json::type_error); + CHECK_THROWS_AS(j_const_nonobject["foo"], json::type_error); + CHECK_THROWS_AS(j_const_nonobject[json::object_t::key_type("foo")], json::type_error); CHECK_THROWS_WITH(j_nonobject["foo"], "[json.exception.type_error.305] cannot use operator[] with string"); CHECK_THROWS_WITH(j_nonobject[json::object_t::key_type("foo")], @@ -519,10 +519,10 @@ TEST_CASE("element access 2") { json j_nonobject(json::value_t::array); const json j_const_nonobject(j_nonobject); - CHECK_THROWS_AS(j_nonobject["foo"], json::type_error&); - CHECK_THROWS_AS(j_nonobject[json::object_t::key_type("foo")], json::type_error&); - CHECK_THROWS_AS(j_const_nonobject["foo"], json::type_error&); - CHECK_THROWS_AS(j_const_nonobject[json::object_t::key_type("foo")], json::type_error&); + CHECK_THROWS_AS(j_nonobject["foo"], json::type_error); + CHECK_THROWS_AS(j_nonobject[json::object_t::key_type("foo")], json::type_error); + CHECK_THROWS_AS(j_const_nonobject["foo"], json::type_error); + CHECK_THROWS_AS(j_const_nonobject[json::object_t::key_type("foo")], json::type_error); CHECK_THROWS_WITH(j_nonobject["foo"], "[json.exception.type_error.305] cannot use operator[] with array"); CHECK_THROWS_WITH(j_nonobject[json::object_t::key_type("foo")], "[json.exception.type_error.305] cannot use operator[] with array"); @@ -536,10 +536,10 @@ TEST_CASE("element access 2") { json j_nonobject(json::value_t::number_integer); const json j_const_nonobject(j_nonobject); - CHECK_THROWS_AS(j_nonobject["foo"], json::type_error&); - CHECK_THROWS_AS(j_nonobject[json::object_t::key_type("foo")], json::type_error&); - CHECK_THROWS_AS(j_const_nonobject["foo"], json::type_error&); - CHECK_THROWS_AS(j_const_nonobject[json::object_t::key_type("foo")], json::type_error&); + CHECK_THROWS_AS(j_nonobject["foo"], json::type_error); + CHECK_THROWS_AS(j_nonobject[json::object_t::key_type("foo")], json::type_error); + CHECK_THROWS_AS(j_const_nonobject["foo"], json::type_error); + CHECK_THROWS_AS(j_const_nonobject[json::object_t::key_type("foo")], json::type_error); CHECK_THROWS_WITH(j_nonobject["foo"], "[json.exception.type_error.305] cannot use operator[] with number"); CHECK_THROWS_WITH(j_nonobject[json::object_t::key_type("foo")], @@ -554,10 +554,10 @@ TEST_CASE("element access 2") { json j_nonobject(json::value_t::number_unsigned); const json j_const_nonobject(j_nonobject); - CHECK_THROWS_AS(j_nonobject["foo"], json::type_error&); - CHECK_THROWS_AS(j_nonobject[json::object_t::key_type("foo")], json::type_error&); - CHECK_THROWS_AS(j_const_nonobject["foo"], json::type_error&); - CHECK_THROWS_AS(j_const_nonobject[json::object_t::key_type("foo")], json::type_error&); + CHECK_THROWS_AS(j_nonobject["foo"], json::type_error); + CHECK_THROWS_AS(j_nonobject[json::object_t::key_type("foo")], json::type_error); + CHECK_THROWS_AS(j_const_nonobject["foo"], json::type_error); + CHECK_THROWS_AS(j_const_nonobject[json::object_t::key_type("foo")], json::type_error); CHECK_THROWS_WITH(j_nonobject["foo"], "[json.exception.type_error.305] cannot use operator[] with number"); CHECK_THROWS_WITH(j_nonobject[json::object_t::key_type("foo")], @@ -572,10 +572,10 @@ TEST_CASE("element access 2") { json j_nonobject(json::value_t::number_float); const json j_const_nonobject(j_nonobject); - CHECK_THROWS_AS(j_nonobject["foo"], json::type_error&); - CHECK_THROWS_AS(j_nonobject[json::object_t::key_type("foo")], json::type_error&); - CHECK_THROWS_AS(j_const_nonobject["foo"], json::type_error&); - CHECK_THROWS_AS(j_const_nonobject[json::object_t::key_type("foo")], json::type_error&); + CHECK_THROWS_AS(j_nonobject["foo"], json::type_error); + CHECK_THROWS_AS(j_nonobject[json::object_t::key_type("foo")], json::type_error); + CHECK_THROWS_AS(j_const_nonobject["foo"], json::type_error); + CHECK_THROWS_AS(j_const_nonobject[json::object_t::key_type("foo")], json::type_error); CHECK_THROWS_WITH(j_nonobject["foo"], "[json.exception.type_error.305] cannot use operator[] with number"); CHECK_THROWS_WITH(j_nonobject[json::object_t::key_type("foo")], @@ -722,10 +722,10 @@ TEST_CASE("element access 2") { json jobject = {{"a", "a"}, {"b", 1}, {"c", 17u}, {"d", false}, {"e", true}}; json jobject2 = {{"a", "a"}, {"b", 1}, {"c", 17u}}; - CHECK_THROWS_AS(jobject.erase(jobject2.begin()), json::invalid_iterator&); - CHECK_THROWS_AS(jobject.erase(jobject.begin(), jobject2.end()), json::invalid_iterator&); - CHECK_THROWS_AS(jobject.erase(jobject2.begin(), jobject.end()), json::invalid_iterator&); - CHECK_THROWS_AS(jobject.erase(jobject2.begin(), jobject2.end()), json::invalid_iterator&); + CHECK_THROWS_AS(jobject.erase(jobject2.begin()), json::invalid_iterator); + CHECK_THROWS_AS(jobject.erase(jobject.begin(), jobject2.end()), json::invalid_iterator); + CHECK_THROWS_AS(jobject.erase(jobject2.begin(), jobject.end()), json::invalid_iterator); + CHECK_THROWS_AS(jobject.erase(jobject2.begin(), jobject2.end()), json::invalid_iterator); CHECK_THROWS_WITH(jobject.erase(jobject2.begin()), "[json.exception.invalid_iterator.202] iterator does not fit current value"); CHECK_THROWS_WITH(jobject.erase(jobject.begin(), jobject2.end()), @@ -738,10 +738,10 @@ TEST_CASE("element access 2") { json jobject = {{"a", "a"}, {"b", 1}, {"c", 17u}, {"d", false}, {"e", true}}; json jobject2 = {{"a", "a"}, {"b", 1}, {"c", 17u}}; - CHECK_THROWS_AS(jobject.erase(jobject2.cbegin()), json::invalid_iterator&); - CHECK_THROWS_AS(jobject.erase(jobject.cbegin(), jobject2.cend()), json::invalid_iterator&); - CHECK_THROWS_AS(jobject.erase(jobject2.cbegin(), jobject.cend()), json::invalid_iterator&); - CHECK_THROWS_AS(jobject.erase(jobject2.cbegin(), jobject2.cend()), json::invalid_iterator&); + CHECK_THROWS_AS(jobject.erase(jobject2.cbegin()), json::invalid_iterator); + CHECK_THROWS_AS(jobject.erase(jobject.cbegin(), jobject2.cend()), json::invalid_iterator); + CHECK_THROWS_AS(jobject.erase(jobject2.cbegin(), jobject.cend()), json::invalid_iterator); + CHECK_THROWS_AS(jobject.erase(jobject2.cbegin(), jobject2.cend()), json::invalid_iterator); CHECK_THROWS_WITH(jobject.erase(jobject2.cbegin()), "[json.exception.invalid_iterator.202] iterator does not fit current value"); CHECK_THROWS_WITH(jobject.erase(jobject.cbegin(), jobject2.cend()), @@ -759,7 +759,7 @@ TEST_CASE("element access 2") SECTION("null") { json j_nonobject(json::value_t::null); - CHECK_THROWS_AS(j_nonobject.erase("foo"), json::type_error&); + CHECK_THROWS_AS(j_nonobject.erase("foo"), json::type_error); CHECK_THROWS_WITH(j_nonobject.erase("foo"), "[json.exception.type_error.307] cannot use erase() with null"); } @@ -767,7 +767,7 @@ TEST_CASE("element access 2") SECTION("boolean") { json j_nonobject(json::value_t::boolean); - CHECK_THROWS_AS(j_nonobject.erase("foo"), json::type_error&); + CHECK_THROWS_AS(j_nonobject.erase("foo"), json::type_error); CHECK_THROWS_WITH(j_nonobject.erase("foo"), "[json.exception.type_error.307] cannot use erase() with boolean"); } @@ -775,7 +775,7 @@ TEST_CASE("element access 2") SECTION("string") { json j_nonobject(json::value_t::string); - CHECK_THROWS_AS(j_nonobject.erase("foo"), json::type_error&); + CHECK_THROWS_AS(j_nonobject.erase("foo"), json::type_error); CHECK_THROWS_WITH(j_nonobject.erase("foo"), "[json.exception.type_error.307] cannot use erase() with string"); } @@ -783,7 +783,7 @@ TEST_CASE("element access 2") SECTION("array") { json j_nonobject(json::value_t::array); - CHECK_THROWS_AS(j_nonobject.erase("foo"), json::type_error&); + CHECK_THROWS_AS(j_nonobject.erase("foo"), json::type_error); CHECK_THROWS_WITH(j_nonobject.erase("foo"), "[json.exception.type_error.307] cannot use erase() with array"); } @@ -791,7 +791,7 @@ TEST_CASE("element access 2") SECTION("number (integer)") { json j_nonobject(json::value_t::number_integer); - CHECK_THROWS_AS(j_nonobject.erase("foo"), json::type_error&); + CHECK_THROWS_AS(j_nonobject.erase("foo"), json::type_error); CHECK_THROWS_WITH(j_nonobject.erase("foo"), "[json.exception.type_error.307] cannot use erase() with number"); } @@ -799,7 +799,7 @@ TEST_CASE("element access 2") SECTION("number (floating-point)") { json j_nonobject(json::value_t::number_float); - CHECK_THROWS_AS(j_nonobject.erase("foo"), json::type_error&); + CHECK_THROWS_AS(j_nonobject.erase("foo"), json::type_error); CHECK_THROWS_WITH(j_nonobject.erase("foo"), "[json.exception.type_error.307] cannot use erase() with number"); } diff --git a/test/src/unit-iterators1.cpp b/test/src/unit-iterators1.cpp index 66ffed225..c707b2d9f 100644 --- a/test/src/unit-iterators1.cpp +++ b/test/src/unit-iterators1.cpp @@ -337,19 +337,19 @@ TEST_CASE("iterators 1") { auto it = j.begin(); auto cit = j_const.cbegin(); - CHECK_THROWS_AS(it.key(), json::invalid_iterator&); + CHECK_THROWS_AS(it.key(), json::invalid_iterator); CHECK_THROWS_WITH(it.key(), "[json.exception.invalid_iterator.207] cannot use key() for non-object iterators"); CHECK(it.value() == json(true)); - CHECK_THROWS_AS(cit.key(), json::invalid_iterator&); + CHECK_THROWS_AS(cit.key(), json::invalid_iterator); CHECK_THROWS_WITH(cit.key(), "[json.exception.invalid_iterator.207] cannot use key() for non-object iterators"); CHECK(cit.value() == json(true)); auto rit = j.rend(); auto crit = j.crend(); - CHECK_THROWS_AS(rit.key(), json::invalid_iterator&); - CHECK_THROWS_AS(rit.value(), json::invalid_iterator&); - CHECK_THROWS_AS(crit.key(), json::invalid_iterator&); - CHECK_THROWS_AS(crit.value(), json::invalid_iterator&); + CHECK_THROWS_AS(rit.key(), json::invalid_iterator); + CHECK_THROWS_AS(rit.value(), json::invalid_iterator); + CHECK_THROWS_AS(crit.key(), json::invalid_iterator); + CHECK_THROWS_AS(crit.value(), json::invalid_iterator); CHECK_THROWS_WITH(rit.key(), "[json.exception.invalid_iterator.207] cannot use key() for non-object iterators"); CHECK_THROWS_WITH(rit.value(), "[json.exception.invalid_iterator.214] cannot get value"); CHECK_THROWS_WITH(crit.key(), "[json.exception.invalid_iterator.207] cannot use key() for non-object iterators"); @@ -541,19 +541,19 @@ TEST_CASE("iterators 1") { auto it = j.begin(); auto cit = j_const.cbegin(); - CHECK_THROWS_AS(it.key(), json::invalid_iterator&); + CHECK_THROWS_AS(it.key(), json::invalid_iterator); CHECK_THROWS_WITH(it.key(), "[json.exception.invalid_iterator.207] cannot use key() for non-object iterators"); CHECK(it.value() == json("hello world")); - CHECK_THROWS_AS(cit.key(), json::invalid_iterator&); + CHECK_THROWS_AS(cit.key(), json::invalid_iterator); CHECK_THROWS_WITH(cit.key(), "[json.exception.invalid_iterator.207] cannot use key() for non-object iterators"); CHECK(cit.value() == json("hello world")); auto rit = j.rend(); auto crit = j.crend(); - CHECK_THROWS_AS(rit.key(), json::invalid_iterator&); - CHECK_THROWS_AS(rit.value(), json::invalid_iterator&); - CHECK_THROWS_AS(crit.key(), json::invalid_iterator&); - CHECK_THROWS_AS(crit.value(), json::invalid_iterator&); + CHECK_THROWS_AS(rit.key(), json::invalid_iterator); + CHECK_THROWS_AS(rit.value(), json::invalid_iterator); + CHECK_THROWS_AS(crit.key(), json::invalid_iterator); + CHECK_THROWS_AS(crit.value(), json::invalid_iterator); CHECK_THROWS_WITH(rit.key(), "[json.exception.invalid_iterator.207] cannot use key() for non-object iterators"); CHECK_THROWS_WITH(rit.value(), "[json.exception.invalid_iterator.214] cannot get value"); CHECK_THROWS_WITH(crit.key(), "[json.exception.invalid_iterator.207] cannot use key() for non-object iterators"); @@ -738,10 +738,10 @@ TEST_CASE("iterators 1") { auto it = j.begin(); auto cit = j_const.cbegin(); - CHECK_THROWS_AS(it.key(), json::invalid_iterator&); + CHECK_THROWS_AS(it.key(), json::invalid_iterator); CHECK_THROWS_WITH(it.key(), "[json.exception.invalid_iterator.207] cannot use key() for non-object iterators"); CHECK(it.value() == json(1)); - CHECK_THROWS_AS(cit.key(), json::invalid_iterator&); + CHECK_THROWS_AS(cit.key(), json::invalid_iterator); CHECK_THROWS_WITH(cit.key(), "[json.exception.invalid_iterator.207] cannot use key() for non-object iterators"); CHECK(cit.value() == json(1)); } @@ -1115,19 +1115,19 @@ TEST_CASE("iterators 1") { auto it = j.begin(); auto cit = j_const.cbegin(); - CHECK_THROWS_AS(it.key(), json::invalid_iterator&); + CHECK_THROWS_AS(it.key(), json::invalid_iterator); CHECK_THROWS_WITH(it.key(), "[json.exception.invalid_iterator.207] cannot use key() for non-object iterators"); CHECK(it.value() == json(23)); - CHECK_THROWS_AS(cit.key(), json::invalid_iterator&); + CHECK_THROWS_AS(cit.key(), json::invalid_iterator); CHECK_THROWS_WITH(cit.key(), "[json.exception.invalid_iterator.207] cannot use key() for non-object iterators"); CHECK(cit.value() == json(23)); auto rit = j.rend(); auto crit = j.crend(); - CHECK_THROWS_AS(rit.key(), json::invalid_iterator&); - CHECK_THROWS_AS(rit.value(), json::invalid_iterator&); - CHECK_THROWS_AS(crit.key(), json::invalid_iterator&); - CHECK_THROWS_AS(crit.value(), json::invalid_iterator&); + CHECK_THROWS_AS(rit.key(), json::invalid_iterator); + CHECK_THROWS_AS(rit.value(), json::invalid_iterator); + CHECK_THROWS_AS(crit.key(), json::invalid_iterator); + CHECK_THROWS_AS(crit.value(), json::invalid_iterator); CHECK_THROWS_WITH(rit.key(), "[json.exception.invalid_iterator.207] cannot use key() for non-object iterators"); CHECK_THROWS_WITH(rit.value(), "[json.exception.invalid_iterator.214] cannot get value"); CHECK_THROWS_WITH(crit.key(), "[json.exception.invalid_iterator.207] cannot use key() for non-object iterators"); @@ -1319,19 +1319,19 @@ TEST_CASE("iterators 1") { auto it = j.begin(); auto cit = j_const.cbegin(); - CHECK_THROWS_AS(it.key(), json::invalid_iterator&); + CHECK_THROWS_AS(it.key(), json::invalid_iterator); CHECK_THROWS_WITH(it.key(), "[json.exception.invalid_iterator.207] cannot use key() for non-object iterators"); CHECK(it.value() == json(23)); - CHECK_THROWS_AS(cit.key(), json::invalid_iterator&); + CHECK_THROWS_AS(cit.key(), json::invalid_iterator); CHECK_THROWS_WITH(cit.key(), "[json.exception.invalid_iterator.207] cannot use key() for non-object iterators"); CHECK(cit.value() == json(23)); auto rit = j.rend(); auto crit = j.crend(); - CHECK_THROWS_AS(rit.key(), json::invalid_iterator&); - CHECK_THROWS_AS(rit.value(), json::invalid_iterator&); - CHECK_THROWS_AS(crit.key(), json::invalid_iterator&); - CHECK_THROWS_AS(crit.value(), json::invalid_iterator&); + CHECK_THROWS_AS(rit.key(), json::invalid_iterator); + CHECK_THROWS_AS(rit.value(), json::invalid_iterator); + CHECK_THROWS_AS(crit.key(), json::invalid_iterator); + CHECK_THROWS_AS(crit.value(), json::invalid_iterator); CHECK_THROWS_WITH(rit.key(), "[json.exception.invalid_iterator.207] cannot use key() for non-object iterators"); CHECK_THROWS_WITH(rit.value(), "[json.exception.invalid_iterator.214] cannot get value"); CHECK_THROWS_WITH(crit.key(), "[json.exception.invalid_iterator.207] cannot use key() for non-object iterators"); @@ -1523,19 +1523,19 @@ TEST_CASE("iterators 1") { auto it = j.begin(); auto cit = j_const.cbegin(); - CHECK_THROWS_AS(it.key(), json::invalid_iterator&); + CHECK_THROWS_AS(it.key(), json::invalid_iterator); CHECK_THROWS_WITH(it.key(), "[json.exception.invalid_iterator.207] cannot use key() for non-object iterators"); CHECK(it.value() == json(23.42)); - CHECK_THROWS_AS(cit.key(), json::invalid_iterator&); + CHECK_THROWS_AS(cit.key(), json::invalid_iterator); CHECK_THROWS_WITH(cit.key(), "[json.exception.invalid_iterator.207] cannot use key() for non-object iterators"); CHECK(cit.value() == json(23.42)); auto rit = j.rend(); auto crit = j.crend(); - CHECK_THROWS_AS(rit.key(), json::invalid_iterator&); - CHECK_THROWS_AS(rit.value(), json::invalid_iterator&); - CHECK_THROWS_AS(crit.key(), json::invalid_iterator&); - CHECK_THROWS_AS(crit.value(), json::invalid_iterator&); + CHECK_THROWS_AS(rit.key(), json::invalid_iterator); + CHECK_THROWS_AS(rit.value(), json::invalid_iterator); + CHECK_THROWS_AS(crit.key(), json::invalid_iterator); + CHECK_THROWS_AS(crit.value(), json::invalid_iterator); CHECK_THROWS_WITH(rit.key(), "[json.exception.invalid_iterator.207] cannot use key() for non-object iterators"); CHECK_THROWS_WITH(rit.value(), "[json.exception.invalid_iterator.214] cannot get value"); CHECK_THROWS_WITH(crit.key(), "[json.exception.invalid_iterator.207] cannot use key() for non-object iterators"); @@ -1597,10 +1597,10 @@ TEST_CASE("iterators 1") { auto it = j.begin(); auto cit = j_const.cbegin(); - CHECK_THROWS_AS(it.key(), json::invalid_iterator&); - CHECK_THROWS_AS(it.value(), json::invalid_iterator&); - CHECK_THROWS_AS(cit.key(), json::invalid_iterator&); - CHECK_THROWS_AS(cit.value(), json::invalid_iterator&); + CHECK_THROWS_AS(it.key(), json::invalid_iterator); + CHECK_THROWS_AS(it.value(), json::invalid_iterator); + CHECK_THROWS_AS(cit.key(), json::invalid_iterator); + CHECK_THROWS_AS(cit.value(), json::invalid_iterator); CHECK_THROWS_WITH(it.key(), "[json.exception.invalid_iterator.207] cannot use key() for non-object iterators"); CHECK_THROWS_WITH(it.value(), "[json.exception.invalid_iterator.214] cannot get value"); CHECK_THROWS_WITH(cit.key(), "[json.exception.invalid_iterator.207] cannot use key() for non-object iterators"); @@ -1608,10 +1608,10 @@ TEST_CASE("iterators 1") auto rit = j.rend(); auto crit = j.crend(); - CHECK_THROWS_AS(rit.key(), json::invalid_iterator&); - CHECK_THROWS_AS(rit.value(), json::invalid_iterator&); - CHECK_THROWS_AS(crit.key(), json::invalid_iterator&); - CHECK_THROWS_AS(crit.value(), json::invalid_iterator&); + CHECK_THROWS_AS(rit.key(), json::invalid_iterator); + CHECK_THROWS_AS(rit.value(), json::invalid_iterator); + CHECK_THROWS_AS(crit.key(), json::invalid_iterator); + CHECK_THROWS_AS(crit.value(), json::invalid_iterator); CHECK_THROWS_WITH(rit.key(), "[json.exception.invalid_iterator.207] cannot use key() for non-object iterators"); CHECK_THROWS_WITH(rit.value(), "[json.exception.invalid_iterator.214] cannot get value"); CHECK_THROWS_WITH(crit.key(), "[json.exception.invalid_iterator.207] cannot use key() for non-object iterators"); diff --git a/test/src/unit-iterators2.cpp b/test/src/unit-iterators2.cpp index be4e27702..29d134dac 100644 --- a/test/src/unit-iterators2.cpp +++ b/test/src/unit-iterators2.cpp @@ -81,14 +81,14 @@ TEST_CASE("iterators 2") { if (j.type() == json::value_t::object) { - CHECK_THROWS_AS(it1 < it1, json::invalid_iterator&); - CHECK_THROWS_AS(it1 < it2, json::invalid_iterator&); - CHECK_THROWS_AS(it2 < it3, json::invalid_iterator&); - CHECK_THROWS_AS(it1 < it3, json::invalid_iterator&); - CHECK_THROWS_AS(it1_c < it1_c, json::invalid_iterator&); - CHECK_THROWS_AS(it1_c < it2_c, json::invalid_iterator&); - CHECK_THROWS_AS(it2_c < it3_c, json::invalid_iterator&); - CHECK_THROWS_AS(it1_c < it3_c, json::invalid_iterator&); + CHECK_THROWS_AS(it1 < it1, json::invalid_iterator); + CHECK_THROWS_AS(it1 < it2, json::invalid_iterator); + CHECK_THROWS_AS(it2 < it3, json::invalid_iterator); + CHECK_THROWS_AS(it1 < it3, json::invalid_iterator); + CHECK_THROWS_AS(it1_c < it1_c, json::invalid_iterator); + CHECK_THROWS_AS(it1_c < it2_c, json::invalid_iterator); + CHECK_THROWS_AS(it2_c < it3_c, json::invalid_iterator); + CHECK_THROWS_AS(it1_c < it3_c, json::invalid_iterator); CHECK_THROWS_WITH(it1 < it1, "[json.exception.invalid_iterator.213] cannot compare order of object iterators"); CHECK_THROWS_WITH(it1 < it2, "[json.exception.invalid_iterator.213] cannot compare order of object iterators"); CHECK_THROWS_WITH(it2 < it3, "[json.exception.invalid_iterator.213] cannot compare order of object iterators"); @@ -115,14 +115,14 @@ TEST_CASE("iterators 2") { if (j.type() == json::value_t::object) { - CHECK_THROWS_AS(it1 <= it1, json::invalid_iterator&); - CHECK_THROWS_AS(it1 <= it2, json::invalid_iterator&); - CHECK_THROWS_AS(it2 <= it3, json::invalid_iterator&); - CHECK_THROWS_AS(it1 <= it3, json::invalid_iterator&); - CHECK_THROWS_AS(it1_c <= it1_c, json::invalid_iterator&); - CHECK_THROWS_AS(it1_c <= it2_c, json::invalid_iterator&); - CHECK_THROWS_AS(it2_c <= it3_c, json::invalid_iterator&); - CHECK_THROWS_AS(it1_c <= it3_c, json::invalid_iterator&); + CHECK_THROWS_AS(it1 <= it1, json::invalid_iterator); + CHECK_THROWS_AS(it1 <= it2, json::invalid_iterator); + CHECK_THROWS_AS(it2 <= it3, json::invalid_iterator); + CHECK_THROWS_AS(it1 <= it3, json::invalid_iterator); + CHECK_THROWS_AS(it1_c <= it1_c, json::invalid_iterator); + CHECK_THROWS_AS(it1_c <= it2_c, json::invalid_iterator); + CHECK_THROWS_AS(it2_c <= it3_c, json::invalid_iterator); + CHECK_THROWS_AS(it1_c <= it3_c, json::invalid_iterator); CHECK_THROWS_WITH(it1 <= it1, "[json.exception.invalid_iterator.213] cannot compare order of object iterators"); CHECK_THROWS_WITH(it1 <= it2, "[json.exception.invalid_iterator.213] cannot compare order of object iterators"); CHECK_THROWS_WITH(it2 <= it3, "[json.exception.invalid_iterator.213] cannot compare order of object iterators"); @@ -150,14 +150,14 @@ TEST_CASE("iterators 2") { if (j.type() == json::value_t::object) { - CHECK_THROWS_AS(it1 > it1, json::invalid_iterator&); - CHECK_THROWS_AS(it1 > it2, json::invalid_iterator&); - CHECK_THROWS_AS(it2 > it3, json::invalid_iterator&); - CHECK_THROWS_AS(it1 > it3, json::invalid_iterator&); - CHECK_THROWS_AS(it1_c > it1_c, json::invalid_iterator&); - CHECK_THROWS_AS(it1_c > it2_c, json::invalid_iterator&); - CHECK_THROWS_AS(it2_c > it3_c, json::invalid_iterator&); - CHECK_THROWS_AS(it1_c > it3_c, json::invalid_iterator&); + CHECK_THROWS_AS(it1 > it1, json::invalid_iterator); + CHECK_THROWS_AS(it1 > it2, json::invalid_iterator); + CHECK_THROWS_AS(it2 > it3, json::invalid_iterator); + CHECK_THROWS_AS(it1 > it3, json::invalid_iterator); + CHECK_THROWS_AS(it1_c > it1_c, json::invalid_iterator); + CHECK_THROWS_AS(it1_c > it2_c, json::invalid_iterator); + CHECK_THROWS_AS(it2_c > it3_c, json::invalid_iterator); + CHECK_THROWS_AS(it1_c > it3_c, json::invalid_iterator); CHECK_THROWS_WITH(it1 > it1, "[json.exception.invalid_iterator.213] cannot compare order of object iterators"); CHECK_THROWS_WITH(it1 > it2, "[json.exception.invalid_iterator.213] cannot compare order of object iterators"); CHECK_THROWS_WITH(it2 > it3, "[json.exception.invalid_iterator.213] cannot compare order of object iterators"); @@ -185,14 +185,14 @@ TEST_CASE("iterators 2") { if (j.type() == json::value_t::object) { - CHECK_THROWS_AS(it1 >= it1, json::invalid_iterator&); - CHECK_THROWS_AS(it1 >= it2, json::invalid_iterator&); - CHECK_THROWS_AS(it2 >= it3, json::invalid_iterator&); - CHECK_THROWS_AS(it1 >= it3, json::invalid_iterator&); - CHECK_THROWS_AS(it1_c >= it1_c, json::invalid_iterator&); - CHECK_THROWS_AS(it1_c >= it2_c, json::invalid_iterator&); - CHECK_THROWS_AS(it2_c >= it3_c, json::invalid_iterator&); - CHECK_THROWS_AS(it1_c >= it3_c, json::invalid_iterator&); + CHECK_THROWS_AS(it1 >= it1, json::invalid_iterator); + CHECK_THROWS_AS(it1 >= it2, json::invalid_iterator); + CHECK_THROWS_AS(it2 >= it3, json::invalid_iterator); + CHECK_THROWS_AS(it1 >= it3, json::invalid_iterator); + CHECK_THROWS_AS(it1_c >= it1_c, json::invalid_iterator); + CHECK_THROWS_AS(it1_c >= it2_c, json::invalid_iterator); + CHECK_THROWS_AS(it2_c >= it3_c, json::invalid_iterator); + CHECK_THROWS_AS(it1_c >= it3_c, json::invalid_iterator); CHECK_THROWS_WITH(it1 >= it1, "[json.exception.invalid_iterator.213] cannot compare order of object iterators"); CHECK_THROWS_WITH(it1 >= it2, "[json.exception.invalid_iterator.213] cannot compare order of object iterators"); CHECK_THROWS_WITH(it2 >= it3, "[json.exception.invalid_iterator.213] cannot compare order of object iterators"); @@ -224,13 +224,13 @@ TEST_CASE("iterators 2") { if (j != k) { - CHECK_THROWS_AS(j.begin() == k.begin(), json::invalid_iterator&); - CHECK_THROWS_AS(j.cbegin() == k.cbegin(), json::invalid_iterator&); + CHECK_THROWS_AS(j.begin() == k.begin(), json::invalid_iterator); + CHECK_THROWS_AS(j.cbegin() == k.cbegin(), json::invalid_iterator); CHECK_THROWS_WITH(j.begin() == k.begin(), "[json.exception.invalid_iterator.212] cannot compare iterators of different containers"); CHECK_THROWS_WITH(j.cbegin() == k.cbegin(), "[json.exception.invalid_iterator.212] cannot compare iterators of different containers"); - CHECK_THROWS_AS(j.begin() < k.begin(), json::invalid_iterator&); - CHECK_THROWS_AS(j.cbegin() < k.cbegin(), json::invalid_iterator&); + CHECK_THROWS_AS(j.begin() < k.begin(), json::invalid_iterator); + CHECK_THROWS_AS(j.cbegin() < k.cbegin(), json::invalid_iterator); CHECK_THROWS_WITH(j.begin() < k.begin(), "[json.exception.invalid_iterator.212] cannot compare iterators of different containers"); CHECK_THROWS_WITH(j.cbegin() < k.cbegin(), "[json.exception.invalid_iterator.212] cannot compare iterators of different containers"); } @@ -251,62 +251,62 @@ TEST_CASE("iterators 2") { { auto it = j_object.begin(); - CHECK_THROWS_AS(it += 1, json::invalid_iterator&); + CHECK_THROWS_AS(it += 1, json::invalid_iterator); CHECK_THROWS_WITH(it += 1, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators"); } { auto it = j_object.cbegin(); - CHECK_THROWS_AS(it += 1, json::invalid_iterator&); + CHECK_THROWS_AS(it += 1, json::invalid_iterator); CHECK_THROWS_WITH(it += 1, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators"); } { auto it = j_object.begin(); - CHECK_THROWS_AS(it + 1, json::invalid_iterator&); + CHECK_THROWS_AS(it + 1, json::invalid_iterator); CHECK_THROWS_WITH(it + 1, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators"); } { auto it = j_object.cbegin(); - CHECK_THROWS_AS(it + 1, json::invalid_iterator&); + CHECK_THROWS_AS(it + 1, json::invalid_iterator); CHECK_THROWS_WITH(it + 1, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators"); } { auto it = j_object.begin(); - CHECK_THROWS_AS(1 + it, json::invalid_iterator&); + CHECK_THROWS_AS(1 + it, json::invalid_iterator); CHECK_THROWS_WITH(1 + it, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators"); } { auto it = j_object.cbegin(); - CHECK_THROWS_AS(1 + it, json::invalid_iterator&); + CHECK_THROWS_AS(1 + it, json::invalid_iterator); CHECK_THROWS_WITH(1 + it, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators"); } { auto it = j_object.begin(); - CHECK_THROWS_AS(it -= 1, json::invalid_iterator&); + CHECK_THROWS_AS(it -= 1, json::invalid_iterator); CHECK_THROWS_WITH(it -= 1, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators"); } { auto it = j_object.cbegin(); - CHECK_THROWS_AS(it -= 1, json::invalid_iterator&); + CHECK_THROWS_AS(it -= 1, json::invalid_iterator); CHECK_THROWS_WITH(it -= 1, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators"); } { auto it = j_object.begin(); - CHECK_THROWS_AS(it - 1, json::invalid_iterator&); + CHECK_THROWS_AS(it - 1, json::invalid_iterator); CHECK_THROWS_WITH(it - 1, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators"); } { auto it = j_object.cbegin(); - CHECK_THROWS_AS(it - 1, json::invalid_iterator&); + CHECK_THROWS_AS(it - 1, json::invalid_iterator); CHECK_THROWS_WITH(it - 1, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators"); } { auto it = j_object.begin(); - CHECK_THROWS_AS(it - it, json::invalid_iterator&); + CHECK_THROWS_AS(it - it, json::invalid_iterator); CHECK_THROWS_WITH(it - it, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators"); } { auto it = j_object.cbegin(); - CHECK_THROWS_AS(it - it, json::invalid_iterator&); + CHECK_THROWS_AS(it - it, json::invalid_iterator); CHECK_THROWS_WITH(it - it, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators"); } } @@ -396,15 +396,15 @@ TEST_CASE("iterators 2") { { auto it = j_object.begin(); - CHECK_THROWS_AS(it[0], json::invalid_iterator&); - CHECK_THROWS_AS(it[1], json::invalid_iterator&); + CHECK_THROWS_AS(it[0], json::invalid_iterator); + CHECK_THROWS_AS(it[1], json::invalid_iterator); CHECK_THROWS_WITH(it[0], "[json.exception.invalid_iterator.208] cannot use operator[] for object iterators"); CHECK_THROWS_WITH(it[1], "[json.exception.invalid_iterator.208] cannot use operator[] for object iterators"); } { auto it = j_object.cbegin(); - CHECK_THROWS_AS(it[0], json::invalid_iterator&); - CHECK_THROWS_AS(it[1], json::invalid_iterator&); + CHECK_THROWS_AS(it[0], json::invalid_iterator); + CHECK_THROWS_AS(it[1], json::invalid_iterator); CHECK_THROWS_WITH(it[0], "[json.exception.invalid_iterator.208] cannot use operator[] for object iterators"); CHECK_THROWS_WITH(it[1], "[json.exception.invalid_iterator.208] cannot use operator[] for object iterators"); } @@ -436,15 +436,15 @@ TEST_CASE("iterators 2") { { auto it = j_null.begin(); - CHECK_THROWS_AS(it[0], json::invalid_iterator&); - CHECK_THROWS_AS(it[1], json::invalid_iterator&); + CHECK_THROWS_AS(it[0], json::invalid_iterator); + CHECK_THROWS_AS(it[1], json::invalid_iterator); CHECK_THROWS_WITH(it[0], "[json.exception.invalid_iterator.214] cannot get value"); CHECK_THROWS_WITH(it[1], "[json.exception.invalid_iterator.214] cannot get value"); } { auto it = j_null.cbegin(); - CHECK_THROWS_AS(it[0], json::invalid_iterator&); - CHECK_THROWS_AS(it[1], json::invalid_iterator&); + CHECK_THROWS_AS(it[0], json::invalid_iterator); + CHECK_THROWS_AS(it[1], json::invalid_iterator); CHECK_THROWS_WITH(it[0], "[json.exception.invalid_iterator.214] cannot get value"); CHECK_THROWS_WITH(it[1], "[json.exception.invalid_iterator.214] cannot get value"); } @@ -455,13 +455,13 @@ TEST_CASE("iterators 2") { auto it = j_value.begin(); CHECK(it[0] == json(42)); - CHECK_THROWS_AS(it[1], json::invalid_iterator&); + CHECK_THROWS_AS(it[1], json::invalid_iterator); CHECK_THROWS_WITH(it[1], "[json.exception.invalid_iterator.214] cannot get value"); } { auto it = j_value.cbegin(); CHECK(it[0] == json(42)); - CHECK_THROWS_AS(it[1], json::invalid_iterator&); + CHECK_THROWS_AS(it[1], json::invalid_iterator); CHECK_THROWS_WITH(it[1], "[json.exception.invalid_iterator.214] cannot get value"); } } @@ -516,14 +516,14 @@ TEST_CASE("iterators 2") { if (j.type() == json::value_t::object) { - CHECK_THROWS_AS(it1 < it1, json::invalid_iterator&); - CHECK_THROWS_AS(it1 < it2, json::invalid_iterator&); - CHECK_THROWS_AS(it2 < it3, json::invalid_iterator&); - CHECK_THROWS_AS(it1 < it3, json::invalid_iterator&); - CHECK_THROWS_AS(it1_c < it1_c, json::invalid_iterator&); - CHECK_THROWS_AS(it1_c < it2_c, json::invalid_iterator&); - CHECK_THROWS_AS(it2_c < it3_c, json::invalid_iterator&); - CHECK_THROWS_AS(it1_c < it3_c, json::invalid_iterator&); + CHECK_THROWS_AS(it1 < it1, json::invalid_iterator); + CHECK_THROWS_AS(it1 < it2, json::invalid_iterator); + CHECK_THROWS_AS(it2 < it3, json::invalid_iterator); + CHECK_THROWS_AS(it1 < it3, json::invalid_iterator); + CHECK_THROWS_AS(it1_c < it1_c, json::invalid_iterator); + CHECK_THROWS_AS(it1_c < it2_c, json::invalid_iterator); + CHECK_THROWS_AS(it2_c < it3_c, json::invalid_iterator); + CHECK_THROWS_AS(it1_c < it3_c, json::invalid_iterator); CHECK_THROWS_WITH(it1 < it1, "[json.exception.invalid_iterator.213] cannot compare order of object iterators"); CHECK_THROWS_WITH(it1 < it2, "[json.exception.invalid_iterator.213] cannot compare order of object iterators"); CHECK_THROWS_WITH(it2 < it3, "[json.exception.invalid_iterator.213] cannot compare order of object iterators"); @@ -550,14 +550,14 @@ TEST_CASE("iterators 2") { if (j.type() == json::value_t::object) { - CHECK_THROWS_AS(it1 <= it1, json::invalid_iterator&); - CHECK_THROWS_AS(it1 <= it2, json::invalid_iterator&); - CHECK_THROWS_AS(it2 <= it3, json::invalid_iterator&); - CHECK_THROWS_AS(it1 <= it3, json::invalid_iterator&); - CHECK_THROWS_AS(it1_c <= it1_c, json::invalid_iterator&); - CHECK_THROWS_AS(it1_c <= it2_c, json::invalid_iterator&); - CHECK_THROWS_AS(it2_c <= it3_c, json::invalid_iterator&); - CHECK_THROWS_AS(it1_c <= it3_c, json::invalid_iterator&); + CHECK_THROWS_AS(it1 <= it1, json::invalid_iterator); + CHECK_THROWS_AS(it1 <= it2, json::invalid_iterator); + CHECK_THROWS_AS(it2 <= it3, json::invalid_iterator); + CHECK_THROWS_AS(it1 <= it3, json::invalid_iterator); + CHECK_THROWS_AS(it1_c <= it1_c, json::invalid_iterator); + CHECK_THROWS_AS(it1_c <= it2_c, json::invalid_iterator); + CHECK_THROWS_AS(it2_c <= it3_c, json::invalid_iterator); + CHECK_THROWS_AS(it1_c <= it3_c, json::invalid_iterator); CHECK_THROWS_WITH(it1 <= it1, "[json.exception.invalid_iterator.213] cannot compare order of object iterators"); CHECK_THROWS_WITH(it1 <= it2, "[json.exception.invalid_iterator.213] cannot compare order of object iterators"); CHECK_THROWS_WITH(it2 <= it3, "[json.exception.invalid_iterator.213] cannot compare order of object iterators"); @@ -585,14 +585,14 @@ TEST_CASE("iterators 2") { if (j.type() == json::value_t::object) { - CHECK_THROWS_AS(it1 > it1, json::invalid_iterator&); - CHECK_THROWS_AS(it1 > it2, json::invalid_iterator&); - CHECK_THROWS_AS(it2 > it3, json::invalid_iterator&); - CHECK_THROWS_AS(it1 > it3, json::invalid_iterator&); - CHECK_THROWS_AS(it1_c > it1_c, json::invalid_iterator&); - CHECK_THROWS_AS(it1_c > it2_c, json::invalid_iterator&); - CHECK_THROWS_AS(it2_c > it3_c, json::invalid_iterator&); - CHECK_THROWS_AS(it1_c > it3_c, json::invalid_iterator&); + CHECK_THROWS_AS(it1 > it1, json::invalid_iterator); + CHECK_THROWS_AS(it1 > it2, json::invalid_iterator); + CHECK_THROWS_AS(it2 > it3, json::invalid_iterator); + CHECK_THROWS_AS(it1 > it3, json::invalid_iterator); + CHECK_THROWS_AS(it1_c > it1_c, json::invalid_iterator); + CHECK_THROWS_AS(it1_c > it2_c, json::invalid_iterator); + CHECK_THROWS_AS(it2_c > it3_c, json::invalid_iterator); + CHECK_THROWS_AS(it1_c > it3_c, json::invalid_iterator); CHECK_THROWS_WITH(it1 > it1, "[json.exception.invalid_iterator.213] cannot compare order of object iterators"); CHECK_THROWS_WITH(it1 > it2, "[json.exception.invalid_iterator.213] cannot compare order of object iterators"); CHECK_THROWS_WITH(it2 > it3, "[json.exception.invalid_iterator.213] cannot compare order of object iterators"); @@ -620,14 +620,14 @@ TEST_CASE("iterators 2") { if (j.type() == json::value_t::object) { - CHECK_THROWS_AS(it1 >= it1, json::invalid_iterator&); - CHECK_THROWS_AS(it1 >= it2, json::invalid_iterator&); - CHECK_THROWS_AS(it2 >= it3, json::invalid_iterator&); - CHECK_THROWS_AS(it1 >= it3, json::invalid_iterator&); - CHECK_THROWS_AS(it1_c >= it1_c, json::invalid_iterator&); - CHECK_THROWS_AS(it1_c >= it2_c, json::invalid_iterator&); - CHECK_THROWS_AS(it2_c >= it3_c, json::invalid_iterator&); - CHECK_THROWS_AS(it1_c >= it3_c, json::invalid_iterator&); + CHECK_THROWS_AS(it1 >= it1, json::invalid_iterator); + CHECK_THROWS_AS(it1 >= it2, json::invalid_iterator); + CHECK_THROWS_AS(it2 >= it3, json::invalid_iterator); + CHECK_THROWS_AS(it1 >= it3, json::invalid_iterator); + CHECK_THROWS_AS(it1_c >= it1_c, json::invalid_iterator); + CHECK_THROWS_AS(it1_c >= it2_c, json::invalid_iterator); + CHECK_THROWS_AS(it2_c >= it3_c, json::invalid_iterator); + CHECK_THROWS_AS(it1_c >= it3_c, json::invalid_iterator); CHECK_THROWS_WITH(it1 >= it1, "[json.exception.invalid_iterator.213] cannot compare order of object iterators"); CHECK_THROWS_WITH(it1 >= it2, "[json.exception.invalid_iterator.213] cannot compare order of object iterators"); CHECK_THROWS_WITH(it2 >= it3, "[json.exception.invalid_iterator.213] cannot compare order of object iterators"); @@ -659,13 +659,13 @@ TEST_CASE("iterators 2") { if (j != k) { - CHECK_THROWS_AS(j.rbegin() == k.rbegin(), json::invalid_iterator&); - CHECK_THROWS_AS(j.crbegin() == k.crbegin(), json::invalid_iterator&); + CHECK_THROWS_AS(j.rbegin() == k.rbegin(), json::invalid_iterator); + CHECK_THROWS_AS(j.crbegin() == k.crbegin(), json::invalid_iterator); CHECK_THROWS_WITH(j.rbegin() == k.rbegin(), "[json.exception.invalid_iterator.212] cannot compare iterators of different containers"); CHECK_THROWS_WITH(j.crbegin() == k.crbegin(), "[json.exception.invalid_iterator.212] cannot compare iterators of different containers"); - CHECK_THROWS_AS(j.rbegin() < k.rbegin(), json::invalid_iterator&); - CHECK_THROWS_AS(j.crbegin() < k.crbegin(), json::invalid_iterator&); + CHECK_THROWS_AS(j.rbegin() < k.rbegin(), json::invalid_iterator); + CHECK_THROWS_AS(j.crbegin() < k.crbegin(), json::invalid_iterator); CHECK_THROWS_WITH(j.rbegin() < k.rbegin(), "[json.exception.invalid_iterator.212] cannot compare iterators of different containers"); CHECK_THROWS_WITH(j.crbegin() < k.crbegin(), "[json.exception.invalid_iterator.212] cannot compare iterators of different containers"); } @@ -686,62 +686,62 @@ TEST_CASE("iterators 2") { { auto it = j_object.rbegin(); - CHECK_THROWS_AS(it += 1, json::invalid_iterator&); + CHECK_THROWS_AS(it += 1, json::invalid_iterator); CHECK_THROWS_WITH(it += 1, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators"); } { auto it = j_object.crbegin(); - CHECK_THROWS_AS(it += 1, json::invalid_iterator&); + CHECK_THROWS_AS(it += 1, json::invalid_iterator); CHECK_THROWS_WITH(it += 1, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators"); } { auto it = j_object.rbegin(); - CHECK_THROWS_AS(it + 1, json::invalid_iterator&); + CHECK_THROWS_AS(it + 1, json::invalid_iterator); CHECK_THROWS_WITH(it + 1, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators"); } { auto it = j_object.crbegin(); - CHECK_THROWS_AS(it + 1, json::invalid_iterator&); + CHECK_THROWS_AS(it + 1, json::invalid_iterator); CHECK_THROWS_WITH(it + 1, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators"); } { auto it = j_object.rbegin(); - CHECK_THROWS_AS(1 + it, json::invalid_iterator&); + CHECK_THROWS_AS(1 + it, json::invalid_iterator); CHECK_THROWS_WITH(1 + it, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators"); } { auto it = j_object.crbegin(); - CHECK_THROWS_AS(1 + it, json::invalid_iterator&); + CHECK_THROWS_AS(1 + it, json::invalid_iterator); CHECK_THROWS_WITH(1 + it, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators"); } { auto it = j_object.rbegin(); - CHECK_THROWS_AS(it -= 1, json::invalid_iterator&); + CHECK_THROWS_AS(it -= 1, json::invalid_iterator); CHECK_THROWS_WITH(it -= 1, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators"); } { auto it = j_object.crbegin(); - CHECK_THROWS_AS(it -= 1, json::invalid_iterator&); + CHECK_THROWS_AS(it -= 1, json::invalid_iterator); CHECK_THROWS_WITH(it -= 1, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators"); } { auto it = j_object.rbegin(); - CHECK_THROWS_AS(it - 1, json::invalid_iterator&); + CHECK_THROWS_AS(it - 1, json::invalid_iterator); CHECK_THROWS_WITH(it - 1, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators"); } { auto it = j_object.crbegin(); - CHECK_THROWS_AS(it - 1, json::invalid_iterator&); + CHECK_THROWS_AS(it - 1, json::invalid_iterator); CHECK_THROWS_WITH(it - 1, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators"); } { auto it = j_object.rbegin(); - CHECK_THROWS_AS(it - it, json::invalid_iterator&); + CHECK_THROWS_AS(it - it, json::invalid_iterator); CHECK_THROWS_WITH(it - it, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators"); } { auto it = j_object.crbegin(); - CHECK_THROWS_AS(it - it, json::invalid_iterator&); + CHECK_THROWS_AS(it - it, json::invalid_iterator); CHECK_THROWS_WITH(it - it, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators"); } } @@ -831,15 +831,15 @@ TEST_CASE("iterators 2") { { auto it = j_object.rbegin(); - CHECK_THROWS_AS(it[0], json::invalid_iterator&); - CHECK_THROWS_AS(it[1], json::invalid_iterator&); + CHECK_THROWS_AS(it[0], json::invalid_iterator); + CHECK_THROWS_AS(it[1], json::invalid_iterator); CHECK_THROWS_WITH(it[0], "[json.exception.invalid_iterator.209] cannot use offsets with object iterators"); CHECK_THROWS_WITH(it[1], "[json.exception.invalid_iterator.209] cannot use offsets with object iterators"); } { auto it = j_object.crbegin(); - CHECK_THROWS_AS(it[0], json::invalid_iterator&); - CHECK_THROWS_AS(it[1], json::invalid_iterator&); + CHECK_THROWS_AS(it[0], json::invalid_iterator); + CHECK_THROWS_AS(it[1], json::invalid_iterator); CHECK_THROWS_WITH(it[0], "[json.exception.invalid_iterator.209] cannot use offsets with object iterators"); CHECK_THROWS_WITH(it[1], "[json.exception.invalid_iterator.209] cannot use offsets with object iterators"); } @@ -871,15 +871,15 @@ TEST_CASE("iterators 2") { { auto it = j_null.rbegin(); - CHECK_THROWS_AS(it[0], json::invalid_iterator&); - CHECK_THROWS_AS(it[1], json::invalid_iterator&); + CHECK_THROWS_AS(it[0], json::invalid_iterator); + CHECK_THROWS_AS(it[1], json::invalid_iterator); CHECK_THROWS_WITH(it[0], "[json.exception.invalid_iterator.214] cannot get value"); CHECK_THROWS_WITH(it[1], "[json.exception.invalid_iterator.214] cannot get value"); } { auto it = j_null.crbegin(); - CHECK_THROWS_AS(it[0], json::invalid_iterator&); - CHECK_THROWS_AS(it[1], json::invalid_iterator&); + CHECK_THROWS_AS(it[0], json::invalid_iterator); + CHECK_THROWS_AS(it[1], json::invalid_iterator); CHECK_THROWS_WITH(it[0], "[json.exception.invalid_iterator.214] cannot get value"); CHECK_THROWS_WITH(it[1], "[json.exception.invalid_iterator.214] cannot get value"); } @@ -890,13 +890,13 @@ TEST_CASE("iterators 2") { auto it = j_value.rbegin(); CHECK(it[0] == json(42)); - CHECK_THROWS_AS(it[1], json::invalid_iterator&); + CHECK_THROWS_AS(it[1], json::invalid_iterator); CHECK_THROWS_WITH(it[1], "[json.exception.invalid_iterator.214] cannot get value"); } { auto it = j_value.crbegin(); CHECK(it[0] == json(42)); - CHECK_THROWS_AS(it[1], json::invalid_iterator&); + CHECK_THROWS_AS(it[1], json::invalid_iterator); CHECK_THROWS_WITH(it[1], "[json.exception.invalid_iterator.214] cannot get value"); } } diff --git a/test/src/unit-json_patch.cpp b/test/src/unit-json_patch.cpp index 636fa2bc7..9ab86ea42 100644 --- a/test/src/unit-json_patch.cpp +++ b/test/src/unit-json_patch.cpp @@ -75,7 +75,7 @@ TEST_CASE("JSON patch") json doc2 = R"({ "q": { "bar": 2 } })"_json; // because "a" does not exist. - CHECK_THROWS_AS(doc2.patch(patch), json::out_of_range&); + CHECK_THROWS_AS(doc2.patch(patch), json::out_of_range); CHECK_THROWS_WITH(doc2.patch(patch), "[json.exception.out_of_range.403] key 'a' not found"); } @@ -337,7 +337,7 @@ TEST_CASE("JSON patch") )"_json; // check that evaluation throws - CHECK_THROWS_AS(doc.patch(patch), json::other_error&); + CHECK_THROWS_AS(doc.patch(patch), json::other_error); CHECK_THROWS_WITH(doc.patch(patch), "[json.exception.other_error.501] unsuccessful: " + patch[0].dump()); } @@ -421,7 +421,7 @@ TEST_CASE("JSON patch") // references neither the root of the document, nor a member of // an existing object, nor a member of an existing array. - CHECK_THROWS_AS(doc.patch(patch), json::out_of_range&); + CHECK_THROWS_AS(doc.patch(patch), json::out_of_range); CHECK_THROWS_WITH(doc.patch(patch), "[json.exception.out_of_range.403] key 'baz' not found"); } @@ -478,7 +478,7 @@ TEST_CASE("JSON patch") )"_json; // check that evaluation throws - CHECK_THROWS_AS(doc.patch(patch), json::other_error&); + CHECK_THROWS_AS(doc.patch(patch), json::other_error); CHECK_THROWS_WITH(doc.patch(patch), "[json.exception.other_error.501] unsuccessful: " + patch[0].dump()); } @@ -668,7 +668,7 @@ TEST_CASE("JSON patch") { json j; json patch = {{"op", "add"}, {"path", ""}, {"value", 1}}; - CHECK_THROWS_AS(j.patch(patch), json::parse_error&); + CHECK_THROWS_AS(j.patch(patch), json::parse_error); CHECK_THROWS_WITH(j.patch(patch), "[json.exception.parse_error.104] parse error: JSON patch must be an array of objects"); } @@ -677,7 +677,7 @@ TEST_CASE("JSON patch") { json j; json patch = {"op", "add", "path", "", "value", 1}; - CHECK_THROWS_AS(j.patch(patch), json::parse_error&); + CHECK_THROWS_AS(j.patch(patch), json::parse_error); CHECK_THROWS_WITH(j.patch(patch), "[json.exception.parse_error.104] parse error: JSON patch must be an array of objects"); } @@ -686,7 +686,7 @@ TEST_CASE("JSON patch") { json j; json patch = {{{"foo", "bar"}}}; - CHECK_THROWS_AS(j.patch(patch), json::parse_error&); + CHECK_THROWS_AS(j.patch(patch), json::parse_error); CHECK_THROWS_WITH(j.patch(patch), "[json.exception.parse_error.105] parse error: operation must have member 'op'"); } @@ -695,7 +695,7 @@ TEST_CASE("JSON patch") { json j; json patch = {{{"op", 1}}}; - CHECK_THROWS_AS(j.patch(patch), json::parse_error&); + CHECK_THROWS_AS(j.patch(patch), json::parse_error); CHECK_THROWS_WITH(j.patch(patch), "[json.exception.parse_error.105] parse error: operation must have string member 'op'"); } @@ -704,7 +704,7 @@ TEST_CASE("JSON patch") { json j; json patch = {{{"op", "foo"}, {"path", ""}}}; - CHECK_THROWS_AS(j.patch(patch), json::parse_error&); + CHECK_THROWS_AS(j.patch(patch), json::parse_error); CHECK_THROWS_WITH(j.patch(patch), "[json.exception.parse_error.105] parse error: operation value 'foo' is invalid"); } @@ -716,7 +716,7 @@ TEST_CASE("JSON patch") { json j; json patch = {{{"op", "add"}}}; - CHECK_THROWS_AS(j.patch(patch), json::parse_error&); + CHECK_THROWS_AS(j.patch(patch), json::parse_error); CHECK_THROWS_WITH(j.patch(patch), "[json.exception.parse_error.105] parse error: operation 'add' must have member 'path'"); } @@ -725,7 +725,7 @@ TEST_CASE("JSON patch") { json j; json patch = {{{"op", "add"}, {"path", 1}}}; - CHECK_THROWS_AS(j.patch(patch), json::parse_error&); + CHECK_THROWS_AS(j.patch(patch), json::parse_error); CHECK_THROWS_WITH(j.patch(patch), "[json.exception.parse_error.105] parse error: operation 'add' must have string member 'path'"); } @@ -734,7 +734,7 @@ TEST_CASE("JSON patch") { json j; json patch = {{{"op", "add"}, {"path", ""}}}; - CHECK_THROWS_AS(j.patch(patch), json::parse_error&); + CHECK_THROWS_AS(j.patch(patch), json::parse_error); CHECK_THROWS_WITH(j.patch(patch), "[json.exception.parse_error.105] parse error: operation 'add' must have member 'value'"); } @@ -743,7 +743,7 @@ TEST_CASE("JSON patch") { json j = {1, 2}; json patch = {{{"op", "add"}, {"path", "/4"}, {"value", 4}}}; - CHECK_THROWS_AS(j.patch(patch), json::out_of_range&); + CHECK_THROWS_AS(j.patch(patch), json::out_of_range); CHECK_THROWS_WITH(j.patch(patch), "[json.exception.out_of_range.401] array index 4 is out of range"); } @@ -755,7 +755,7 @@ TEST_CASE("JSON patch") { json j; json patch = {{{"op", "remove"}}}; - CHECK_THROWS_AS(j.patch(patch), json::parse_error&); + CHECK_THROWS_AS(j.patch(patch), json::parse_error); CHECK_THROWS_WITH(j.patch(patch), "[json.exception.parse_error.105] parse error: operation 'remove' must have member 'path'"); } @@ -764,7 +764,7 @@ TEST_CASE("JSON patch") { json j; json patch = {{{"op", "remove"}, {"path", 1}}}; - CHECK_THROWS_AS(j.patch(patch), json::parse_error&); + CHECK_THROWS_AS(j.patch(patch), json::parse_error); CHECK_THROWS_WITH(j.patch(patch), "[json.exception.parse_error.105] parse error: operation 'remove' must have string member 'path'"); } @@ -773,7 +773,7 @@ TEST_CASE("JSON patch") { json j = {1, 2, 3}; json patch = {{{"op", "remove"}, {"path", "/17"}}}; - CHECK_THROWS_AS(j.patch(patch), json::out_of_range&); + CHECK_THROWS_AS(j.patch(patch), json::out_of_range); CHECK_THROWS_WITH(j.patch(patch), "[json.exception.out_of_range.401] array index 17 is out of range"); } @@ -782,7 +782,7 @@ TEST_CASE("JSON patch") { json j = {{"foo", 1}, {"bar", 2}}; json patch = {{{"op", "remove"}, {"path", "/baz"}}}; - CHECK_THROWS_AS(j.patch(patch), json::out_of_range&); + CHECK_THROWS_AS(j.patch(patch), json::out_of_range); CHECK_THROWS_WITH(j.patch(patch), "[json.exception.out_of_range.403] key 'baz' not found"); } @@ -791,7 +791,7 @@ TEST_CASE("JSON patch") { json j = "string"; json patch = {{{"op", "remove"}, {"path", ""}}}; - CHECK_THROWS_AS(j.patch(patch), json::out_of_range&); + CHECK_THROWS_AS(j.patch(patch), json::out_of_range); CHECK_THROWS_WITH(j.patch(patch), "[json.exception.out_of_range.405] JSON pointer has no parent"); } @@ -803,7 +803,7 @@ TEST_CASE("JSON patch") { json j; json patch = {{{"op", "replace"}}}; - CHECK_THROWS_AS(j.patch(patch), json::parse_error&); + CHECK_THROWS_AS(j.patch(patch), json::parse_error); CHECK_THROWS_WITH(j.patch(patch), "[json.exception.parse_error.105] parse error: operation 'replace' must have member 'path'"); } @@ -812,7 +812,7 @@ TEST_CASE("JSON patch") { json j; json patch = {{{"op", "replace"}, {"path", 1}}}; - CHECK_THROWS_AS(j.patch(patch), json::parse_error&); + CHECK_THROWS_AS(j.patch(patch), json::parse_error); CHECK_THROWS_WITH(j.patch(patch), "[json.exception.parse_error.105] parse error: operation 'replace' must have string member 'path'"); } @@ -821,7 +821,7 @@ TEST_CASE("JSON patch") { json j; json patch = {{{"op", "replace"}, {"path", ""}}}; - CHECK_THROWS_AS(j.patch(patch), json::parse_error&); + CHECK_THROWS_AS(j.patch(patch), json::parse_error); CHECK_THROWS_WITH(j.patch(patch), "[json.exception.parse_error.105] parse error: operation 'replace' must have member 'value'"); } @@ -830,7 +830,7 @@ TEST_CASE("JSON patch") { json j = {1, 2, 3}; json patch = {{{"op", "replace"}, {"path", "/17"}, {"value", 19}}}; - CHECK_THROWS_AS(j.patch(patch), json::out_of_range&); + CHECK_THROWS_AS(j.patch(patch), json::out_of_range); CHECK_THROWS_WITH(j.patch(patch), "[json.exception.out_of_range.401] array index 17 is out of range"); } @@ -839,7 +839,7 @@ TEST_CASE("JSON patch") { json j = {{"foo", 1}, {"bar", 2}}; json patch = {{{"op", "replace"}, {"path", "/baz"}, {"value", 3}}}; - CHECK_THROWS_AS(j.patch(patch), json::out_of_range&); + CHECK_THROWS_AS(j.patch(patch), json::out_of_range); CHECK_THROWS_WITH(j.patch(patch), "[json.exception.out_of_range.403] key 'baz' not found"); } @@ -851,7 +851,7 @@ TEST_CASE("JSON patch") { json j; json patch = {{{"op", "move"}}}; - CHECK_THROWS_AS(j.patch(patch), json::parse_error&); + CHECK_THROWS_AS(j.patch(patch), json::parse_error); CHECK_THROWS_WITH(j.patch(patch), "[json.exception.parse_error.105] parse error: operation 'move' must have member 'path'"); } @@ -860,7 +860,7 @@ TEST_CASE("JSON patch") { json j; json patch = {{{"op", "move"}, {"path", 1}}}; - CHECK_THROWS_AS(j.patch(patch), json::parse_error&); + CHECK_THROWS_AS(j.patch(patch), json::parse_error); CHECK_THROWS_WITH(j.patch(patch), "[json.exception.parse_error.105] parse error: operation 'move' must have string member 'path'"); } @@ -869,7 +869,7 @@ TEST_CASE("JSON patch") { json j; json patch = {{{"op", "move"}, {"path", ""}}}; - CHECK_THROWS_AS(j.patch(patch), json::parse_error&); + CHECK_THROWS_AS(j.patch(patch), json::parse_error); CHECK_THROWS_WITH(j.patch(patch), "[json.exception.parse_error.105] parse error: operation 'move' must have member 'from'"); } @@ -878,7 +878,7 @@ TEST_CASE("JSON patch") { json j; json patch = {{{"op", "move"}, {"path", ""}, {"from", 1}}}; - CHECK_THROWS_AS(j.patch(patch), json::parse_error&); + CHECK_THROWS_AS(j.patch(patch), json::parse_error); CHECK_THROWS_WITH(j.patch(patch), "[json.exception.parse_error.105] parse error: operation 'move' must have string member 'from'"); } @@ -887,7 +887,7 @@ TEST_CASE("JSON patch") { json j = {1, 2, 3}; json patch = {{{"op", "move"}, {"path", "/0"}, {"from", "/5"}}}; - CHECK_THROWS_AS(j.patch(patch), json::out_of_range&); + CHECK_THROWS_AS(j.patch(patch), json::out_of_range); CHECK_THROWS_WITH(j.patch(patch), "[json.exception.out_of_range.401] array index 5 is out of range"); } @@ -896,7 +896,7 @@ TEST_CASE("JSON patch") { json j = {{"foo", 1}, {"bar", 2}}; json patch = {{{"op", "move"}, {"path", "/baz"}, {"from", "/baz"}}}; - CHECK_THROWS_AS(j.patch(patch), json::out_of_range&); + CHECK_THROWS_AS(j.patch(patch), json::out_of_range); CHECK_THROWS_WITH(j.patch(patch), "[json.exception.out_of_range.403] key 'baz' not found"); } @@ -908,7 +908,7 @@ TEST_CASE("JSON patch") { json j; json patch = {{{"op", "copy"}}}; - CHECK_THROWS_AS(j.patch(patch), json::parse_error&); + CHECK_THROWS_AS(j.patch(patch), json::parse_error); CHECK_THROWS_WITH(j.patch(patch), "[json.exception.parse_error.105] parse error: operation 'copy' must have member 'path'"); } @@ -917,7 +917,7 @@ TEST_CASE("JSON patch") { json j; json patch = {{{"op", "copy"}, {"path", 1}}}; - CHECK_THROWS_AS(j.patch(patch), json::parse_error&); + CHECK_THROWS_AS(j.patch(patch), json::parse_error); CHECK_THROWS_WITH(j.patch(patch), "[json.exception.parse_error.105] parse error: operation 'copy' must have string member 'path'"); } @@ -926,7 +926,7 @@ TEST_CASE("JSON patch") { json j; json patch = {{{"op", "copy"}, {"path", ""}}}; - CHECK_THROWS_AS(j.patch(patch), json::parse_error&); + CHECK_THROWS_AS(j.patch(patch), json::parse_error); CHECK_THROWS_WITH(j.patch(patch), "[json.exception.parse_error.105] parse error: operation 'copy' must have member 'from'"); } @@ -935,7 +935,7 @@ TEST_CASE("JSON patch") { json j; json patch = {{{"op", "copy"}, {"path", ""}, {"from", 1}}}; - CHECK_THROWS_AS(j.patch(patch), json::parse_error&); + CHECK_THROWS_AS(j.patch(patch), json::parse_error); CHECK_THROWS_WITH(j.patch(patch), "[json.exception.parse_error.105] parse error: operation 'copy' must have string member 'from'"); } @@ -944,7 +944,7 @@ TEST_CASE("JSON patch") { json j = {1, 2, 3}; json patch = {{{"op", "copy"}, {"path", "/0"}, {"from", "/5"}}}; - CHECK_THROWS_AS(j.patch(patch), json::out_of_range&); + CHECK_THROWS_AS(j.patch(patch), json::out_of_range); CHECK_THROWS_WITH(j.patch(patch), "[json.exception.out_of_range.401] array index 5 is out of range"); } @@ -953,7 +953,7 @@ TEST_CASE("JSON patch") { json j = {{"foo", 1}, {"bar", 2}}; json patch = {{{"op", "copy"}, {"path", "/fob"}, {"from", "/baz"}}}; - CHECK_THROWS_AS(j.patch(patch), json::out_of_range&); + CHECK_THROWS_AS(j.patch(patch), json::out_of_range); CHECK_THROWS_WITH(j.patch(patch), "[json.exception.out_of_range.403] key 'baz' not found"); } @@ -965,7 +965,7 @@ TEST_CASE("JSON patch") { json j; json patch = {{{"op", "test"}}}; - CHECK_THROWS_AS(j.patch(patch), json::parse_error&); + CHECK_THROWS_AS(j.patch(patch), json::parse_error); CHECK_THROWS_WITH(j.patch(patch), "[json.exception.parse_error.105] parse error: operation 'test' must have member 'path'"); } @@ -974,7 +974,7 @@ TEST_CASE("JSON patch") { json j; json patch = {{{"op", "test"}, {"path", 1}}}; - CHECK_THROWS_AS(j.patch(patch), json::parse_error&); + CHECK_THROWS_AS(j.patch(patch), json::parse_error); CHECK_THROWS_WITH(j.patch(patch), "[json.exception.parse_error.105] parse error: operation 'test' must have string member 'path'"); } @@ -983,7 +983,7 @@ TEST_CASE("JSON patch") { json j; json patch = {{{"op", "test"}, {"path", ""}}}; - CHECK_THROWS_AS(j.patch(patch), json::parse_error&); + CHECK_THROWS_AS(j.patch(patch), json::parse_error); CHECK_THROWS_WITH(j.patch(patch), "[json.exception.parse_error.105] parse error: operation 'test' must have member 'value'"); } @@ -1177,7 +1177,7 @@ TEST_CASE("JSON patch") )"_json; // the test will fail - CHECK_THROWS_AS(doc.patch(patch), json::other_error&); + CHECK_THROWS_AS(doc.patch(patch), json::other_error); CHECK_THROWS_WITH(doc.patch(patch), "[json.exception.other_error.501] unsuccessful: " + patch[0].dump()); } } diff --git a/test/src/unit-json_pointer.cpp b/test/src/unit-json_pointer.cpp index ee55dc58e..d42800498 100644 --- a/test/src/unit-json_pointer.cpp +++ b/test/src/unit-json_pointer.cpp @@ -36,23 +36,23 @@ TEST_CASE("JSON pointers") { SECTION("errors") { - CHECK_THROWS_AS(json::json_pointer("foo"), json::parse_error&); + CHECK_THROWS_AS(json::json_pointer("foo"), json::parse_error); CHECK_THROWS_WITH(json::json_pointer("foo"), "[json.exception.parse_error.107] parse error at 1: JSON pointer must be empty or begin with '/' - was: 'foo'"); - CHECK_THROWS_AS(json::json_pointer("/~~"), json::parse_error&); + CHECK_THROWS_AS(json::json_pointer("/~~"), json::parse_error); CHECK_THROWS_WITH(json::json_pointer("/~~"), "[json.exception.parse_error.108] parse error: escape character '~' must be followed with '0' or '1'"); - CHECK_THROWS_AS(json::json_pointer("/~"), json::parse_error&); + CHECK_THROWS_AS(json::json_pointer("/~"), json::parse_error); CHECK_THROWS_WITH(json::json_pointer("/~"), "[json.exception.parse_error.108] parse error: escape character '~' must be followed with '0' or '1'"); json::json_pointer p; - CHECK_THROWS_AS(p.top(), json::out_of_range&); + CHECK_THROWS_AS(p.top(), json::out_of_range); CHECK_THROWS_WITH(p.top(), "[json.exception.out_of_range.405] JSON pointer has no parent"); - CHECK_THROWS_AS(p.pop_back(), json::out_of_range&); + CHECK_THROWS_AS(p.pop_back(), json::out_of_range); CHECK_THROWS_WITH(p.pop_back(), "[json.exception.out_of_range.405] JSON pointer has no parent"); } @@ -126,10 +126,10 @@ TEST_CASE("JSON pointers") // unresolved access json j_primitive = 1; - CHECK_THROWS_AS(j_primitive["/foo"_json_pointer], json::out_of_range&); + CHECK_THROWS_AS(j_primitive["/foo"_json_pointer], json::out_of_range); CHECK_THROWS_WITH(j_primitive["/foo"_json_pointer], "[json.exception.out_of_range.404] unresolved reference token 'foo'"); - CHECK_THROWS_AS(j_primitive.at("/foo"_json_pointer), json::out_of_range&); + CHECK_THROWS_AS(j_primitive.at("/foo"_json_pointer), json::out_of_range); CHECK_THROWS_WITH(j_primitive.at("/foo"_json_pointer), "[json.exception.out_of_range.404] unresolved reference token 'foo'"); } @@ -189,16 +189,16 @@ TEST_CASE("JSON pointers") CHECK(j[json::json_pointer("/m~0n")] == j["m~n"]); // unescaped access - CHECK_THROWS_AS(j.at(json::json_pointer("/a/b")), json::out_of_range&); + CHECK_THROWS_AS(j.at(json::json_pointer("/a/b")), json::out_of_range); CHECK_THROWS_WITH(j.at(json::json_pointer("/a/b")), "[json.exception.out_of_range.403] key 'a' not found"); // unresolved access const json j_primitive = 1; - CHECK_THROWS_AS(j_primitive["/foo"_json_pointer], json::out_of_range&); + CHECK_THROWS_AS(j_primitive["/foo"_json_pointer], json::out_of_range); CHECK_THROWS_WITH(j_primitive["/foo"_json_pointer], "[json.exception.out_of_range.404] unresolved reference token 'foo'"); - CHECK_THROWS_AS(j_primitive.at("/foo"_json_pointer), json::out_of_range&); + CHECK_THROWS_AS(j_primitive.at("/foo"_json_pointer), json::out_of_range); CHECK_THROWS_WITH(j_primitive.at("/foo"_json_pointer), "[json.exception.out_of_range.404] unresolved reference token 'foo'"); } @@ -255,35 +255,35 @@ TEST_CASE("JSON pointers") CHECK(j == json({1, 13, 3, 33, nullptr, 55})); // error with leading 0 - CHECK_THROWS_AS(j["/01"_json_pointer], json::parse_error&); + CHECK_THROWS_AS(j["/01"_json_pointer], json::parse_error); CHECK_THROWS_WITH(j["/01"_json_pointer], "[json.exception.parse_error.106] parse error: array index '01' must not begin with '0'"); - CHECK_THROWS_AS(j_const["/01"_json_pointer], json::parse_error&); + CHECK_THROWS_AS(j_const["/01"_json_pointer], json::parse_error); CHECK_THROWS_WITH(j_const["/01"_json_pointer], "[json.exception.parse_error.106] parse error: array index '01' must not begin with '0'"); - CHECK_THROWS_AS(j.at("/01"_json_pointer), json::parse_error&); + CHECK_THROWS_AS(j.at("/01"_json_pointer), json::parse_error); CHECK_THROWS_WITH(j.at("/01"_json_pointer), "[json.exception.parse_error.106] parse error: array index '01' must not begin with '0'"); - CHECK_THROWS_AS(j_const.at("/01"_json_pointer), json::parse_error&); + CHECK_THROWS_AS(j_const.at("/01"_json_pointer), json::parse_error); CHECK_THROWS_WITH(j_const.at("/01"_json_pointer), "[json.exception.parse_error.106] parse error: array index '01' must not begin with '0'"); // error with incorrect numbers - CHECK_THROWS_AS(j["/one"_json_pointer] = 1, json::parse_error&); + CHECK_THROWS_AS(j["/one"_json_pointer] = 1, json::parse_error); CHECK_THROWS_WITH(j["/one"_json_pointer] = 1, "[json.exception.parse_error.109] parse error: array index 'one' is not a number"); - CHECK_THROWS_AS(j_const["/one"_json_pointer] == 1, json::parse_error&); + CHECK_THROWS_AS(j_const["/one"_json_pointer] == 1, json::parse_error); CHECK_THROWS_WITH(j_const["/one"_json_pointer] == 1, "[json.exception.parse_error.109] parse error: array index 'one' is not a number"); - CHECK_THROWS_AS(j.at("/one"_json_pointer) = 1, json::parse_error&); + CHECK_THROWS_AS(j.at("/one"_json_pointer) = 1, json::parse_error); CHECK_THROWS_WITH(j.at("/one"_json_pointer) = 1, "[json.exception.parse_error.109] parse error: array index 'one' is not a number"); - CHECK_THROWS_AS(j_const.at("/one"_json_pointer) == 1, json::parse_error&); + CHECK_THROWS_AS(j_const.at("/one"_json_pointer) == 1, json::parse_error); CHECK_THROWS_WITH(j_const.at("/one"_json_pointer) == 1, "[json.exception.parse_error.109] parse error: array index 'one' is not a number"); - CHECK_THROWS_AS(json({{"/list/0", 1}, {"/list/1", 2}, {"/list/three", 3}}).unflatten(), json::parse_error&); + CHECK_THROWS_AS(json({{"/list/0", 1}, {"/list/1", 2}, {"/list/three", 3}}).unflatten(), json::parse_error); CHECK_THROWS_WITH(json({{"/list/0", 1}, {"/list/1", 2}, {"/list/three", 3}}).unflatten(), "[json.exception.parse_error.109] parse error: array index 'three' is not a number"); @@ -292,15 +292,15 @@ TEST_CASE("JSON pointers") CHECK(j == json({1, 13, 3, 33, nullptr, 55, 99})); // error when using "-" in const object - CHECK_THROWS_AS(j_const["/-"_json_pointer], json::out_of_range&); + CHECK_THROWS_AS(j_const["/-"_json_pointer], json::out_of_range); CHECK_THROWS_WITH(j_const["/-"_json_pointer], "[json.exception.out_of_range.402] array index '-' (3) is out of range"); // error when using "-" with at - CHECK_THROWS_AS(j.at("/-"_json_pointer), json::out_of_range&); + CHECK_THROWS_AS(j.at("/-"_json_pointer), json::out_of_range); CHECK_THROWS_WITH(j.at("/-"_json_pointer), "[json.exception.out_of_range.402] array index '-' (7) is out of range"); - CHECK_THROWS_AS(j_const.at("/-"_json_pointer), json::out_of_range&); + CHECK_THROWS_AS(j_const.at("/-"_json_pointer), json::out_of_range); CHECK_THROWS_WITH(j_const.at("/-"_json_pointer), "[json.exception.out_of_range.402] array index '-' (3) is out of range"); } @@ -315,20 +315,20 @@ TEST_CASE("JSON pointers") CHECK(j["/2"_json_pointer] == j[2]); // assign to nonexisting index - CHECK_THROWS_AS(j.at("/3"_json_pointer), json::out_of_range&); + CHECK_THROWS_AS(j.at("/3"_json_pointer), json::out_of_range); CHECK_THROWS_WITH(j.at("/3"_json_pointer), "[json.exception.out_of_range.401] array index 3 is out of range"); // assign to nonexisting index (with gap) - CHECK_THROWS_AS(j.at("/5"_json_pointer), json::out_of_range&); + CHECK_THROWS_AS(j.at("/5"_json_pointer), json::out_of_range); CHECK_THROWS_WITH(j.at("/5"_json_pointer), "[json.exception.out_of_range.401] array index 5 is out of range"); // assign to "-" - CHECK_THROWS_AS(j["/-"_json_pointer], json::out_of_range&); + CHECK_THROWS_AS(j["/-"_json_pointer], json::out_of_range); CHECK_THROWS_WITH(j["/-"_json_pointer], "[json.exception.out_of_range.402] array index '-' (3) is out of range"); - CHECK_THROWS_AS(j.at("/-"_json_pointer), json::out_of_range&); + CHECK_THROWS_AS(j.at("/-"_json_pointer), json::out_of_range); CHECK_THROWS_WITH(j.at("/-"_json_pointer), "[json.exception.out_of_range.402] array index '-' (3) is out of range"); } @@ -386,18 +386,18 @@ TEST_CASE("JSON pointers") CHECK(j_flatten.unflatten() == j); // error for nonobjects - CHECK_THROWS_AS(json(1).unflatten(), json::type_error&); + CHECK_THROWS_AS(json(1).unflatten(), json::type_error); CHECK_THROWS_WITH(json(1).unflatten(), "[json.exception.type_error.314] only objects can be unflattened"); // error for nonprimitve values - CHECK_THROWS_AS(json({{"/1", {1, 2, 3}}}).unflatten(), json::type_error&); + CHECK_THROWS_AS(json({{"/1", {1, 2, 3}}}).unflatten(), json::type_error); CHECK_THROWS_WITH(json({{"/1", {1, 2, 3}}}).unflatten(), "[json.exception.type_error.315] values in object must be primitive"); // error for conflicting values json j_error = {{"", 42}, {"/foo", 17}}; - CHECK_THROWS_AS(j_error.unflatten(), json::type_error&); + CHECK_THROWS_AS(j_error.unflatten(), json::type_error); CHECK_THROWS_WITH(j_error.unflatten(), "[json.exception.type_error.313] invalid value to unflatten"); diff --git a/test/src/unit-modifiers.cpp b/test/src/unit-modifiers.cpp index 01dfa4152..f0eb09c6f 100644 --- a/test/src/unit-modifiers.cpp +++ b/test/src/unit-modifiers.cpp @@ -172,7 +172,7 @@ TEST_CASE("modifiers") SECTION("other type") { json j = 1; - CHECK_THROWS_AS(j.push_back("Hello"), json::type_error&); + CHECK_THROWS_AS(j.push_back("Hello"), json::type_error); CHECK_THROWS_WITH(j.push_back("Hello"), "[json.exception.type_error.308] cannot use push_back() with number"); } } @@ -202,7 +202,7 @@ TEST_CASE("modifiers") { json j = 1; json k("Hello"); - CHECK_THROWS_AS(j.push_back(k), json::type_error&); + CHECK_THROWS_AS(j.push_back(k), json::type_error); CHECK_THROWS_WITH(j.push_back(k), "[json.exception.type_error.308] cannot use push_back() with number"); } } @@ -235,7 +235,7 @@ TEST_CASE("modifiers") { json j = 1; json k("Hello"); - CHECK_THROWS_AS(j.push_back(json::object_t::value_type({"one", 1})), json::type_error&); + CHECK_THROWS_AS(j.push_back(json::object_t::value_type({"one", 1})), json::type_error); CHECK_THROWS_WITH(j.push_back(json::object_t::value_type({"one", 1})), "[json.exception.type_error.308] cannot use push_back() with number"); } @@ -272,11 +272,11 @@ TEST_CASE("modifiers") CHECK(j == json({{"key1", 1}, {"key2", "bar"}})); // invalid values (no string/val pair) - CHECK_THROWS_AS(j.push_back({1}), json::type_error&); + CHECK_THROWS_AS(j.push_back({1}), json::type_error); CHECK_THROWS_WITH(j.push_back({1}), "[json.exception.type_error.308] cannot use push_back() with object"); - CHECK_THROWS_AS(j.push_back({1, 2}), json::type_error&); + CHECK_THROWS_AS(j.push_back({1, 2}), json::type_error); CHECK_THROWS_WITH(j.push_back({1, 2}), "[json.exception.type_error.308] cannot use push_back() with object"); - CHECK_THROWS_AS(j.push_back({1, 2, 3, 4}), json::type_error&); + CHECK_THROWS_AS(j.push_back({1, 2, 3, 4}), json::type_error); CHECK_THROWS_WITH(j.push_back({1, 2, 3, 4}), "[json.exception.type_error.308] cannot use push_back() with object"); } } @@ -315,7 +315,7 @@ TEST_CASE("modifiers") SECTION("other type") { json j = 1; - CHECK_THROWS_AS(j.emplace_back("Hello"), json::type_error&); + CHECK_THROWS_AS(j.emplace_back("Hello"), json::type_error); CHECK_THROWS_WITH(j.emplace_back("Hello"), "[json.exception.type_error.311] cannot use emplace_back() with number"); } @@ -375,7 +375,7 @@ TEST_CASE("modifiers") SECTION("other type") { json j = 1; - CHECK_THROWS_AS(j.emplace("foo", "bar"), json::type_error&); + CHECK_THROWS_AS(j.emplace("foo", "bar"), json::type_error); CHECK_THROWS_WITH(j.emplace("foo", "bar"), "[json.exception.type_error.311] cannot use emplace() with number"); } @@ -407,7 +407,7 @@ TEST_CASE("modifiers") SECTION("other type") { json j = 1; - CHECK_THROWS_AS(j += "Hello", json::type_error&); + CHECK_THROWS_AS(j += "Hello", json::type_error); CHECK_THROWS_WITH(j += "Hello", "[json.exception.type_error.308] cannot use push_back() with number"); } } @@ -437,7 +437,7 @@ TEST_CASE("modifiers") { json j = 1; json k("Hello"); - CHECK_THROWS_AS(j += k, json::type_error&); + CHECK_THROWS_AS(j += k, json::type_error); CHECK_THROWS_WITH(j += k, "[json.exception.type_error.308] cannot use push_back() with number"); } } @@ -470,7 +470,7 @@ TEST_CASE("modifiers") { json j = 1; json k("Hello"); - CHECK_THROWS_AS(j += json::object_t::value_type({"one", 1}), json::type_error&); + CHECK_THROWS_AS(j += json::object_t::value_type({"one", 1}), json::type_error); CHECK_THROWS_WITH(j += json::object_t::value_type({"one", 1}), "[json.exception.type_error.308] cannot use push_back() with number"); } @@ -507,7 +507,7 @@ TEST_CASE("modifiers") CHECK(j == json({{"key1", 1}, {"key2", "bar"}})); json k = {{"key1", 1}}; - CHECK_THROWS_AS((k += {1, 2, 3, 4}), json::type_error&); + CHECK_THROWS_AS((k += {1, 2, 3, 4}), json::type_error); CHECK_THROWS_WITH((k += {1, 2, 3, 4}), "[json.exception.type_error.308] cannot use push_back() with object"); } } @@ -644,9 +644,9 @@ TEST_CASE("modifiers") json j_other_array2 = {"first", "second"}; CHECK_THROWS_AS(j_array.insert(j_array.end(), j_array.begin(), j_array.end()), - json::invalid_iterator&); + json::invalid_iterator); CHECK_THROWS_AS(j_array.insert(j_array.end(), j_other_array.begin(), j_other_array2.end()), - json::invalid_iterator&); + json::invalid_iterator); CHECK_THROWS_WITH(j_array.insert(j_array.end(), j_array.begin(), j_array.end()), "[json.exception.invalid_iterator.211] passed iterators may not belong to container"); @@ -676,9 +676,9 @@ TEST_CASE("modifiers") { json j_other_array2 = {"first", "second"}; - CHECK_THROWS_AS(j_array.insert(j_object2.begin(), j_object2.end()), json::type_error&); - CHECK_THROWS_AS(j_object1.insert(j_object1.begin(), j_object2.end()), json::invalid_iterator&); - CHECK_THROWS_AS(j_object1.insert(j_array.begin(), j_array.end()), json::invalid_iterator&); + CHECK_THROWS_AS(j_array.insert(j_object2.begin(), j_object2.end()), json::type_error); + CHECK_THROWS_AS(j_object1.insert(j_object1.begin(), j_object2.end()), json::invalid_iterator); + CHECK_THROWS_AS(j_object1.insert(j_array.begin(), j_array.end()), json::invalid_iterator); CHECK_THROWS_WITH(j_array.insert(j_object2.begin(), j_object2.end()), "[json.exception.type_error.309] cannot use insert() with array"); @@ -724,11 +724,11 @@ TEST_CASE("modifiers") // pass iterator to a different array json j_another_array = {1, 2}; json j_yet_another_array = {"first", "second"}; - CHECK_THROWS_AS(j_array.insert(j_another_array.end(), 10), json::invalid_iterator&); - CHECK_THROWS_AS(j_array.insert(j_another_array.end(), j_value), json::invalid_iterator&); - CHECK_THROWS_AS(j_array.insert(j_another_array.end(), 10, 11), json::invalid_iterator&); - CHECK_THROWS_AS(j_array.insert(j_another_array.end(), j_yet_another_array.begin(), j_yet_another_array.end()), json::invalid_iterator&); - CHECK_THROWS_AS(j_array.insert(j_another_array.end(), {1, 2, 3, 4}), json::invalid_iterator&); + CHECK_THROWS_AS(j_array.insert(j_another_array.end(), 10), json::invalid_iterator); + CHECK_THROWS_AS(j_array.insert(j_another_array.end(), j_value), json::invalid_iterator); + CHECK_THROWS_AS(j_array.insert(j_another_array.end(), 10, 11), json::invalid_iterator); + CHECK_THROWS_AS(j_array.insert(j_another_array.end(), j_yet_another_array.begin(), j_yet_another_array.end()), json::invalid_iterator); + CHECK_THROWS_AS(j_array.insert(j_another_array.end(), {1, 2, 3, 4}), json::invalid_iterator); CHECK_THROWS_WITH(j_array.insert(j_another_array.end(), 10), "[json.exception.invalid_iterator.202] iterator does not fit current value"); @@ -747,12 +747,12 @@ TEST_CASE("modifiers") // call insert on a non-array type json j_nonarray = 3; json j_yet_another_array = {"first", "second"}; - CHECK_THROWS_AS(j_nonarray.insert(j_nonarray.end(), 10), json::type_error&); - CHECK_THROWS_AS(j_nonarray.insert(j_nonarray.end(), j_value), json::type_error&); - CHECK_THROWS_AS(j_nonarray.insert(j_nonarray.end(), 10, 11), json::type_error&); + CHECK_THROWS_AS(j_nonarray.insert(j_nonarray.end(), 10), json::type_error); + CHECK_THROWS_AS(j_nonarray.insert(j_nonarray.end(), j_value), json::type_error); + CHECK_THROWS_AS(j_nonarray.insert(j_nonarray.end(), 10, 11), json::type_error); CHECK_THROWS_AS(j_nonarray.insert(j_nonarray.end(), j_yet_another_array.begin(), - j_yet_another_array.end()), json::type_error&); - CHECK_THROWS_AS(j_nonarray.insert(j_nonarray.end(), {1, 2, 3, 4}), json::type_error&); + j_yet_another_array.end()), json::type_error); + CHECK_THROWS_AS(j_nonarray.insert(j_nonarray.end(), {1, 2, 3, 4}), json::type_error); CHECK_THROWS_WITH(j_nonarray.insert(j_nonarray.end(), 10), "[json.exception.type_error.309] cannot use insert() with number"); CHECK_THROWS_WITH(j_nonarray.insert(j_nonarray.end(), j_value), "[json.exception.type_error.309] cannot use insert() with number"); @@ -784,10 +784,10 @@ TEST_CASE("modifiers") SECTION("wrong types") { - CHECK_THROWS_AS(j_array.update(j_object1), json::type_error&); + CHECK_THROWS_AS(j_array.update(j_object1), json::type_error); CHECK_THROWS_WITH(j_array.update(j_object1), "[json.exception.type_error.312] cannot use update() with array"); - CHECK_THROWS_AS(j_object1.update(j_array), json::type_error&); + CHECK_THROWS_AS(j_object1.update(j_array), json::type_error); CHECK_THROWS_WITH(j_object1.update(j_array), "[json.exception.type_error.312] cannot use update() with array"); } } @@ -814,9 +814,9 @@ TEST_CASE("modifiers") { json j_other_array2 = {"first", "second"}; - CHECK_THROWS_AS(j_array.update(j_object2.begin(), j_object2.end()), json::type_error&); - CHECK_THROWS_AS(j_object1.update(j_object1.begin(), j_object2.end()), json::invalid_iterator&); - CHECK_THROWS_AS(j_object1.update(j_array.begin(), j_array.end()), json::invalid_iterator&); + CHECK_THROWS_AS(j_array.update(j_object2.begin(), j_object2.end()), json::type_error); + CHECK_THROWS_AS(j_object1.update(j_object1.begin(), j_object2.end()), json::invalid_iterator); + CHECK_THROWS_AS(j_object1.update(j_array.begin(), j_array.end()), json::invalid_iterator); CHECK_THROWS_WITH(j_array.update(j_object2.begin(), j_object2.end()), "[json.exception.type_error.312] cannot use update() with array"); @@ -876,7 +876,7 @@ TEST_CASE("modifiers") json j = 17; json::array_t a = {"foo", "bar", "baz"}; - CHECK_THROWS_AS(j.swap(a), json::type_error&); + CHECK_THROWS_AS(j.swap(a), json::type_error); CHECK_THROWS_WITH(j.swap(a), "[json.exception.type_error.310] cannot use swap() with number"); } } @@ -902,7 +902,7 @@ TEST_CASE("modifiers") json j = 17; json::object_t o = {{"cow", "Kuh"}, {"chicken", "Huhn"}}; - CHECK_THROWS_AS(j.swap(o), json::type_error&); + CHECK_THROWS_AS(j.swap(o), json::type_error); CHECK_THROWS_WITH(j.swap(o), "[json.exception.type_error.310] cannot use swap() with number"); } } @@ -928,7 +928,7 @@ TEST_CASE("modifiers") json j = 17; json::string_t s = "Hallo Welt"; - CHECK_THROWS_AS(j.swap(s), json::type_error&); + CHECK_THROWS_AS(j.swap(s), json::type_error); CHECK_THROWS_WITH(j.swap(s), "[json.exception.type_error.310] cannot use swap() with number"); } } diff --git a/test/src/unit-msgpack.cpp b/test/src/unit-msgpack.cpp index 148bb180a..c363069f0 100644 --- a/test/src/unit-msgpack.cpp +++ b/test/src/unit-msgpack.cpp @@ -1016,28 +1016,28 @@ TEST_CASE("MessagePack") { SECTION("empty byte vector") { - CHECK_THROWS_AS(json::from_msgpack(std::vector()), json::parse_error&); + CHECK_THROWS_AS(json::from_msgpack(std::vector()), json::parse_error); CHECK_THROWS_WITH(json::from_msgpack(std::vector()), "[json.exception.parse_error.110] parse error at 1: unexpected end of input"); } SECTION("too short byte vector") { - CHECK_THROWS_AS(json::from_msgpack(std::vector({0xcc})), json::parse_error&); - CHECK_THROWS_AS(json::from_msgpack(std::vector({0xcd})), json::parse_error&); - CHECK_THROWS_AS(json::from_msgpack(std::vector({0xcd, 0x00})), json::parse_error&); - CHECK_THROWS_AS(json::from_msgpack(std::vector({0xce})), json::parse_error&); - CHECK_THROWS_AS(json::from_msgpack(std::vector({0xce, 0x00})), json::parse_error&); - CHECK_THROWS_AS(json::from_msgpack(std::vector({0xce, 0x00, 0x00})), json::parse_error&); - CHECK_THROWS_AS(json::from_msgpack(std::vector({0xce, 0x00, 0x00, 0x00})), json::parse_error&); - CHECK_THROWS_AS(json::from_msgpack(std::vector({0xcf})), json::parse_error&); - CHECK_THROWS_AS(json::from_msgpack(std::vector({0xcf, 0x00})), json::parse_error&); - CHECK_THROWS_AS(json::from_msgpack(std::vector({0xcf, 0x00, 0x00})), json::parse_error&); - CHECK_THROWS_AS(json::from_msgpack(std::vector({0xcf, 0x00, 0x00, 0x00})), json::parse_error&); - CHECK_THROWS_AS(json::from_msgpack(std::vector({0xcf, 0x00, 0x00, 0x00, 0x00})), json::parse_error&); - CHECK_THROWS_AS(json::from_msgpack(std::vector({0xcf, 0x00, 0x00, 0x00, 0x00, 0x00})), json::parse_error&); - CHECK_THROWS_AS(json::from_msgpack(std::vector({0xcf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00})), json::parse_error&); - CHECK_THROWS_AS(json::from_msgpack(std::vector({0xcf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00})), json::parse_error&); + CHECK_THROWS_AS(json::from_msgpack(std::vector({0xcc})), json::parse_error); + CHECK_THROWS_AS(json::from_msgpack(std::vector({0xcd})), json::parse_error); + CHECK_THROWS_AS(json::from_msgpack(std::vector({0xcd, 0x00})), json::parse_error); + CHECK_THROWS_AS(json::from_msgpack(std::vector({0xce})), json::parse_error); + CHECK_THROWS_AS(json::from_msgpack(std::vector({0xce, 0x00})), json::parse_error); + CHECK_THROWS_AS(json::from_msgpack(std::vector({0xce, 0x00, 0x00})), json::parse_error); + CHECK_THROWS_AS(json::from_msgpack(std::vector({0xce, 0x00, 0x00, 0x00})), json::parse_error); + CHECK_THROWS_AS(json::from_msgpack(std::vector({0xcf})), json::parse_error); + CHECK_THROWS_AS(json::from_msgpack(std::vector({0xcf, 0x00})), json::parse_error); + CHECK_THROWS_AS(json::from_msgpack(std::vector({0xcf, 0x00, 0x00})), json::parse_error); + CHECK_THROWS_AS(json::from_msgpack(std::vector({0xcf, 0x00, 0x00, 0x00})), json::parse_error); + CHECK_THROWS_AS(json::from_msgpack(std::vector({0xcf, 0x00, 0x00, 0x00, 0x00})), json::parse_error); + CHECK_THROWS_AS(json::from_msgpack(std::vector({0xcf, 0x00, 0x00, 0x00, 0x00, 0x00})), json::parse_error); + CHECK_THROWS_AS(json::from_msgpack(std::vector({0xcf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00})), json::parse_error); + CHECK_THROWS_AS(json::from_msgpack(std::vector({0xcf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00})), json::parse_error); CHECK_THROWS_WITH(json::from_msgpack(std::vector({0xcc})), "[json.exception.parse_error.110] parse error at 2: unexpected end of input"); @@ -1075,10 +1075,10 @@ TEST_CASE("MessagePack") { SECTION("concrete examples") { - CHECK_THROWS_AS(json::from_msgpack(std::vector({0xc1})), json::parse_error&); + CHECK_THROWS_AS(json::from_msgpack(std::vector({0xc1})), json::parse_error); CHECK_THROWS_WITH(json::from_msgpack(std::vector({0xc1})), "[json.exception.parse_error.112] parse error at 1: error reading MessagePack; last byte: 0xC1"); - CHECK_THROWS_AS(json::from_msgpack(std::vector({0xc6})), json::parse_error&); + CHECK_THROWS_AS(json::from_msgpack(std::vector({0xc6})), json::parse_error); CHECK_THROWS_WITH(json::from_msgpack(std::vector({0xc6})), "[json.exception.parse_error.112] parse error at 1: error reading MessagePack; last byte: 0xC6"); } @@ -1097,14 +1097,14 @@ TEST_CASE("MessagePack") 0xd4, 0xd5, 0xd6, 0xd7, 0xd8 }) { - CHECK_THROWS_AS(json::from_msgpack(std::vector({static_cast(byte)})), json::parse_error&); + CHECK_THROWS_AS(json::from_msgpack(std::vector({static_cast(byte)})), json::parse_error); } } } SECTION("invalid string in map") { - CHECK_THROWS_AS(json::from_msgpack(std::vector({0x81, 0xff, 0x01})), json::parse_error&); + CHECK_THROWS_AS(json::from_msgpack(std::vector({0x81, 0xff, 0x01})), json::parse_error); CHECK_THROWS_WITH(json::from_msgpack(std::vector({0x81, 0xff, 0x01})), "[json.exception.parse_error.113] parse error at 2: expected a MessagePack string; last byte: 0xFF"); } @@ -1120,7 +1120,7 @@ TEST_CASE("MessagePack") SECTION("strict mode") { - CHECK_THROWS_AS(json::from_msgpack(vec), json::parse_error&); + CHECK_THROWS_AS(json::from_msgpack(vec), json::parse_error); CHECK_THROWS_WITH(json::from_msgpack(vec), "[json.exception.parse_error.110] parse error at 2: expected end of input"); } diff --git a/test/src/unit-readme.cpp b/test/src/unit-readme.cpp index 1ce6ee1dc..8d126824a 100644 --- a/test/src/unit-readme.cpp +++ b/test/src/unit-readme.cpp @@ -31,6 +31,7 @@ SOFTWARE. #include "json.hpp" using nlohmann::json; +#include #include #include #include diff --git a/test/src/unit-reference_access.cpp b/test/src/unit-reference_access.cpp index c05ae7234..2e1759d62 100644 --- a/test/src/unit-reference_access.cpp +++ b/test/src/unit-reference_access.cpp @@ -64,22 +64,22 @@ TEST_CASE("reference access") // check if mismatching references throw correctly CHECK_NOTHROW(value.get_ref()); - CHECK_THROWS_AS(value.get_ref(), json::type_error&); + CHECK_THROWS_AS(value.get_ref(), json::type_error); CHECK_THROWS_WITH(value.get_ref(), "[json.exception.type_error.303] incompatible ReferenceType for get_ref, actual type is object"); - CHECK_THROWS_AS(value.get_ref(), json::type_error&); + CHECK_THROWS_AS(value.get_ref(), json::type_error); CHECK_THROWS_WITH(value.get_ref(), "[json.exception.type_error.303] incompatible ReferenceType for get_ref, actual type is object"); - CHECK_THROWS_AS(value.get_ref(), json::type_error&); + CHECK_THROWS_AS(value.get_ref(), json::type_error); CHECK_THROWS_WITH(value.get_ref(), "[json.exception.type_error.303] incompatible ReferenceType for get_ref, actual type is object"); - CHECK_THROWS_AS(value.get_ref(), json::type_error&); + CHECK_THROWS_AS(value.get_ref(), json::type_error); CHECK_THROWS_WITH(value.get_ref(), "[json.exception.type_error.303] incompatible ReferenceType for get_ref, actual type is object"); - CHECK_THROWS_AS(value.get_ref(), json::type_error&); + CHECK_THROWS_AS(value.get_ref(), json::type_error); CHECK_THROWS_WITH(value.get_ref(), "[json.exception.type_error.303] incompatible ReferenceType for get_ref, actual type is object"); - CHECK_THROWS_AS(value.get_ref(), json::type_error&); + CHECK_THROWS_AS(value.get_ref(), json::type_error); CHECK_THROWS_WITH(value.get_ref(), "[json.exception.type_error.303] incompatible ReferenceType for get_ref, actual type is object"); } @@ -113,23 +113,23 @@ TEST_CASE("reference access") CHECK(p2 == value.get()); // check if mismatching references throw correctly - CHECK_THROWS_AS(value.get_ref(), json::type_error&); + CHECK_THROWS_AS(value.get_ref(), json::type_error); CHECK_THROWS_WITH(value.get_ref(), "[json.exception.type_error.303] incompatible ReferenceType for get_ref, actual type is array"); CHECK_NOTHROW(value.get_ref()); - CHECK_THROWS_AS(value.get_ref(), json::type_error&); + CHECK_THROWS_AS(value.get_ref(), json::type_error); CHECK_THROWS_WITH(value.get_ref(), "[json.exception.type_error.303] incompatible ReferenceType for get_ref, actual type is array"); - CHECK_THROWS_AS(value.get_ref(), json::type_error&); + CHECK_THROWS_AS(value.get_ref(), json::type_error); CHECK_THROWS_WITH(value.get_ref(), "[json.exception.type_error.303] incompatible ReferenceType for get_ref, actual type is array"); - CHECK_THROWS_AS(value.get_ref(), json::type_error&); + CHECK_THROWS_AS(value.get_ref(), json::type_error); CHECK_THROWS_WITH(value.get_ref(), "[json.exception.type_error.303] incompatible ReferenceType for get_ref, actual type is array"); - CHECK_THROWS_AS(value.get_ref(), json::type_error&); + CHECK_THROWS_AS(value.get_ref(), json::type_error); CHECK_THROWS_WITH(value.get_ref(), "[json.exception.type_error.303] incompatible ReferenceType for get_ref, actual type is array"); - CHECK_THROWS_AS(value.get_ref(), json::type_error&); + CHECK_THROWS_AS(value.get_ref(), json::type_error); CHECK_THROWS_WITH(value.get_ref(), "[json.exception.type_error.303] incompatible ReferenceType for get_ref, actual type is array"); } @@ -149,23 +149,23 @@ TEST_CASE("reference access") CHECK(p2 == value.get()); // check if mismatching references throw correctly - CHECK_THROWS_AS(value.get_ref(), json::type_error&); + CHECK_THROWS_AS(value.get_ref(), json::type_error); CHECK_THROWS_WITH(value.get_ref(), "[json.exception.type_error.303] incompatible ReferenceType for get_ref, actual type is string"); - CHECK_THROWS_AS(value.get_ref(), json::type_error&); + CHECK_THROWS_AS(value.get_ref(), json::type_error); CHECK_THROWS_WITH(value.get_ref(), "[json.exception.type_error.303] incompatible ReferenceType for get_ref, actual type is string"); CHECK_NOTHROW(value.get_ref()); - CHECK_THROWS_AS(value.get_ref(), json::type_error&); + CHECK_THROWS_AS(value.get_ref(), json::type_error); CHECK_THROWS_WITH(value.get_ref(), "[json.exception.type_error.303] incompatible ReferenceType for get_ref, actual type is string"); - CHECK_THROWS_AS(value.get_ref(), json::type_error&); + CHECK_THROWS_AS(value.get_ref(), json::type_error); CHECK_THROWS_WITH(value.get_ref(), "[json.exception.type_error.303] incompatible ReferenceType for get_ref, actual type is string"); - CHECK_THROWS_AS(value.get_ref(), json::type_error&); + CHECK_THROWS_AS(value.get_ref(), json::type_error); CHECK_THROWS_WITH(value.get_ref(), "[json.exception.type_error.303] incompatible ReferenceType for get_ref, actual type is string"); - CHECK_THROWS_AS(value.get_ref(), json::type_error&); + CHECK_THROWS_AS(value.get_ref(), json::type_error); CHECK_THROWS_WITH(value.get_ref(), "[json.exception.type_error.303] incompatible ReferenceType for get_ref, actual type is string"); } @@ -185,23 +185,23 @@ TEST_CASE("reference access") CHECK(p2 == value.get()); // check if mismatching references throw correctly - CHECK_THROWS_AS(value.get_ref(), json::type_error&); + CHECK_THROWS_AS(value.get_ref(), json::type_error); CHECK_THROWS_WITH(value.get_ref(), "[json.exception.type_error.303] incompatible ReferenceType for get_ref, actual type is boolean"); - CHECK_THROWS_AS(value.get_ref(), json::type_error&); + CHECK_THROWS_AS(value.get_ref(), json::type_error); CHECK_THROWS_WITH(value.get_ref(), "[json.exception.type_error.303] incompatible ReferenceType for get_ref, actual type is boolean"); - CHECK_THROWS_AS(value.get_ref(), json::type_error&); + CHECK_THROWS_AS(value.get_ref(), json::type_error); CHECK_THROWS_WITH(value.get_ref(), "[json.exception.type_error.303] incompatible ReferenceType for get_ref, actual type is boolean"); CHECK_NOTHROW(value.get_ref()); - CHECK_THROWS_AS(value.get_ref(), json::type_error&); + CHECK_THROWS_AS(value.get_ref(), json::type_error); CHECK_THROWS_WITH(value.get_ref(), "[json.exception.type_error.303] incompatible ReferenceType for get_ref, actual type is boolean"); - CHECK_THROWS_AS(value.get_ref(), json::type_error&); + CHECK_THROWS_AS(value.get_ref(), json::type_error); CHECK_THROWS_WITH(value.get_ref(), "[json.exception.type_error.303] incompatible ReferenceType for get_ref, actual type is boolean"); - CHECK_THROWS_AS(value.get_ref(), json::type_error&); + CHECK_THROWS_AS(value.get_ref(), json::type_error); CHECK_THROWS_WITH(value.get_ref(), "[json.exception.type_error.303] incompatible ReferenceType for get_ref, actual type is boolean"); } @@ -221,23 +221,23 @@ TEST_CASE("reference access") CHECK(p2 == value.get()); // check if mismatching references throw correctly - CHECK_THROWS_AS(value.get_ref(), json::type_error&); + CHECK_THROWS_AS(value.get_ref(), json::type_error); CHECK_THROWS_WITH(value.get_ref(), "[json.exception.type_error.303] incompatible ReferenceType for get_ref, actual type is number"); - CHECK_THROWS_AS(value.get_ref(), json::type_error&); + CHECK_THROWS_AS(value.get_ref(), json::type_error); CHECK_THROWS_WITH(value.get_ref(), "[json.exception.type_error.303] incompatible ReferenceType for get_ref, actual type is number"); - CHECK_THROWS_AS(value.get_ref(), json::type_error&); + CHECK_THROWS_AS(value.get_ref(), json::type_error); CHECK_THROWS_WITH(value.get_ref(), "[json.exception.type_error.303] incompatible ReferenceType for get_ref, actual type is number"); - CHECK_THROWS_AS(value.get_ref(), json::type_error&); + CHECK_THROWS_AS(value.get_ref(), json::type_error); CHECK_THROWS_WITH(value.get_ref(), "[json.exception.type_error.303] incompatible ReferenceType for get_ref, actual type is number"); CHECK_NOTHROW(value.get_ref()); - CHECK_THROWS_AS(value.get_ref(), json::type_error&); + CHECK_THROWS_AS(value.get_ref(), json::type_error); CHECK_THROWS_WITH(value.get_ref(), "[json.exception.type_error.303] incompatible ReferenceType for get_ref, actual type is number"); - CHECK_THROWS_AS(value.get_ref(), json::type_error&); + CHECK_THROWS_AS(value.get_ref(), json::type_error); CHECK_THROWS_WITH(value.get_ref(), "[json.exception.type_error.303] incompatible ReferenceType for get_ref, actual type is number"); } @@ -257,23 +257,23 @@ TEST_CASE("reference access") CHECK(p2 == value.get()); // check if mismatching references throw correctly - CHECK_THROWS_AS(value.get_ref(), json::type_error&); + CHECK_THROWS_AS(value.get_ref(), json::type_error); CHECK_THROWS_WITH(value.get_ref(), "[json.exception.type_error.303] incompatible ReferenceType for get_ref, actual type is number"); - CHECK_THROWS_AS(value.get_ref(), json::type_error&); + CHECK_THROWS_AS(value.get_ref(), json::type_error); CHECK_THROWS_WITH(value.get_ref(), "[json.exception.type_error.303] incompatible ReferenceType for get_ref, actual type is number"); - CHECK_THROWS_AS(value.get_ref(), json::type_error&); + CHECK_THROWS_AS(value.get_ref(), json::type_error); CHECK_THROWS_WITH(value.get_ref(), "[json.exception.type_error.303] incompatible ReferenceType for get_ref, actual type is number"); - CHECK_THROWS_AS(value.get_ref(), json::type_error&); + CHECK_THROWS_AS(value.get_ref(), json::type_error); CHECK_THROWS_WITH(value.get_ref(), "[json.exception.type_error.303] incompatible ReferenceType for get_ref, actual type is number"); - //CHECK_THROWS_AS(value.get_ref(), json::type_error&); + //CHECK_THROWS_AS(value.get_ref(), json::type_error); //CHECK_THROWS_WITH(value.get_ref(), // "[json.exception.type_error.303] incompatible ReferenceType for get_ref, actual type is number"); CHECK_NOTHROW(value.get_ref()); - CHECK_THROWS_AS(value.get_ref(), json::type_error&); + CHECK_THROWS_AS(value.get_ref(), json::type_error); CHECK_THROWS_WITH(value.get_ref(), "[json.exception.type_error.303] incompatible ReferenceType for get_ref, actual type is number"); } @@ -293,22 +293,22 @@ TEST_CASE("reference access") CHECK(p2 == value.get()); // check if mismatching references throw correctly - CHECK_THROWS_AS(value.get_ref(), json::type_error&); + CHECK_THROWS_AS(value.get_ref(), json::type_error); CHECK_THROWS_WITH(value.get_ref(), "[json.exception.type_error.303] incompatible ReferenceType for get_ref, actual type is number"); - CHECK_THROWS_AS(value.get_ref(), json::type_error&); + CHECK_THROWS_AS(value.get_ref(), json::type_error); CHECK_THROWS_WITH(value.get_ref(), "[json.exception.type_error.303] incompatible ReferenceType for get_ref, actual type is number"); - CHECK_THROWS_AS(value.get_ref(), json::type_error&); + CHECK_THROWS_AS(value.get_ref(), json::type_error); CHECK_THROWS_WITH(value.get_ref(), "[json.exception.type_error.303] incompatible ReferenceType for get_ref, actual type is number"); - CHECK_THROWS_AS(value.get_ref(), json::type_error&); + CHECK_THROWS_AS(value.get_ref(), json::type_error); CHECK_THROWS_WITH(value.get_ref(), "[json.exception.type_error.303] incompatible ReferenceType for get_ref, actual type is number"); - CHECK_THROWS_AS(value.get_ref(), json::type_error&); + CHECK_THROWS_AS(value.get_ref(), json::type_error); CHECK_THROWS_WITH(value.get_ref(), "[json.exception.type_error.303] incompatible ReferenceType for get_ref, actual type is number"); - CHECK_THROWS_AS(value.get_ref(), json::type_error&); + CHECK_THROWS_AS(value.get_ref(), json::type_error); CHECK_THROWS_WITH(value.get_ref(), "[json.exception.type_error.303] incompatible ReferenceType for get_ref, actual type is number"); CHECK_NOTHROW(value.get_ref()); diff --git a/test/src/unit-regression.cpp b/test/src/unit-regression.cpp index 177281608..4fd3fb523 100644 --- a/test/src/unit-regression.cpp +++ b/test/src/unit-regression.cpp @@ -588,7 +588,7 @@ TEST_CASE("regression tests") SECTION("issue #329 - serialized value not always can be parsed") { - CHECK_THROWS_AS(json::parse("22e2222"), json::out_of_range&); + CHECK_THROWS_AS(json::parse("22e2222"), json::out_of_range); CHECK_THROWS_WITH(json::parse("22e2222"), "[json.exception.out_of_range.406] number overflow parsing '22e2222'"); } @@ -596,7 +596,7 @@ TEST_CASE("regression tests") SECTION("issue #366 - json::parse on failed stream gets stuck") { std::ifstream f("file_not_found.json"); - CHECK_THROWS_AS(json::parse(f), json::parse_error&); + CHECK_THROWS_AS(json::parse(f), json::parse_error); CHECK_THROWS_WITH(json::parse(f), "[json.exception.parse_error.101] parse error at 1: syntax error - unexpected end of input; expected '[', '{', or a literal"); } @@ -611,7 +611,7 @@ TEST_CASE("regression tests") // ss is not at EOF; this yielded an error before the fix // (threw basic_string::append). No, it should just throw // a parse error because of the EOF. - CHECK_THROWS_AS(ss >> j, json::parse_error&); + CHECK_THROWS_AS(ss >> j, json::parse_error); CHECK_THROWS_WITH(ss >> j, "[json.exception.parse_error.101] parse error at 1: syntax error - unexpected end of input; expected '[', '{', or a literal"); } @@ -622,7 +622,7 @@ TEST_CASE("regression tests") { std::stringstream ss; json j; - CHECK_THROWS_AS(ss >> j, json::parse_error&); + CHECK_THROWS_AS(ss >> j, json::parse_error); CHECK_THROWS_WITH(ss >> j, "[json.exception.parse_error.101] parse error at 1: syntax error - unexpected end of input; expected '[', '{', or a literal"); } @@ -632,7 +632,7 @@ TEST_CASE("regression tests") std::stringstream ss; ss << " "; json j; - CHECK_THROWS_AS(ss >> j, json::parse_error&); + CHECK_THROWS_AS(ss >> j, json::parse_error); CHECK_THROWS_WITH(ss >> j, "[json.exception.parse_error.101] parse error at 1: syntax error - unexpected end of input; expected '[', '{', or a literal"); } @@ -645,7 +645,7 @@ TEST_CASE("regression tests") CHECK_NOTHROW(ss >> j); CHECK(j == 111); - CHECK_THROWS_AS(ss >> j, json::parse_error&); + CHECK_THROWS_AS(ss >> j, json::parse_error); CHECK_THROWS_WITH(ss >> j, "[json.exception.parse_error.101] parse error at 1: syntax error - unexpected end of input; expected '[', '{', or a literal"); } @@ -658,7 +658,7 @@ TEST_CASE("regression tests") CHECK_NOTHROW(ss >> j); CHECK(j == 222); - CHECK_THROWS_AS(ss >> j, json::parse_error&); + CHECK_THROWS_AS(ss >> j, json::parse_error); CHECK_THROWS_WITH(ss >> j, "[json.exception.parse_error.101] parse error at 1: syntax error - unexpected end of input; expected '[', '{', or a literal"); } @@ -671,7 +671,7 @@ TEST_CASE("regression tests") CHECK_NOTHROW(ss >> j); CHECK(j == 333); - CHECK_THROWS_AS(ss >> j, json::parse_error&); + CHECK_THROWS_AS(ss >> j, json::parse_error); CHECK_THROWS_WITH(ss >> j, "[json.exception.parse_error.101] parse error at 1: syntax error - unexpected end of input; expected '[', '{', or a literal"); } @@ -688,7 +688,7 @@ TEST_CASE("regression tests") CHECK_NOTHROW(ss >> j); CHECK(j == 333); - CHECK_THROWS_AS(ss >> j, json::parse_error&); + CHECK_THROWS_AS(ss >> j, json::parse_error); CHECK_THROWS_WITH(ss >> j, "[json.exception.parse_error.101] parse error at 1: syntax error - unexpected end of input; expected '[', '{', or a literal"); } @@ -707,7 +707,7 @@ TEST_CASE("regression tests") CHECK_NOTHROW(ss >> j); CHECK(j == ""); - CHECK_THROWS_AS(ss >> j, json::parse_error&); + CHECK_THROWS_AS(ss >> j, json::parse_error); CHECK_THROWS_WITH(ss >> j, "[json.exception.parse_error.101] parse error at 1: syntax error - unexpected end of input; expected '[', '{', or a literal"); } @@ -722,7 +722,7 @@ TEST_CASE("regression tests") CHECK_NOTHROW(ss >> j); CHECK(j == json({{"three", 3}})); - CHECK_THROWS_AS(ss >> j, json::parse_error&); + CHECK_THROWS_AS(ss >> j, json::parse_error); CHECK_THROWS_WITH(ss >> j, "[json.exception.parse_error.101] parse error at 1: syntax error - unexpected end of input; expected '[', '{', or a literal"); } @@ -792,7 +792,7 @@ TEST_CASE("regression tests") { // original test case std::vector vec {0x65, 0xf5, 0x0a, 0x48, 0x21}; - CHECK_THROWS_AS(json::from_cbor(vec), json::parse_error&); + CHECK_THROWS_AS(json::from_cbor(vec), json::parse_error); CHECK_THROWS_WITH(json::from_cbor(vec), "[json.exception.parse_error.110] parse error at 6: unexpected end of input"); } @@ -801,31 +801,31 @@ TEST_CASE("regression tests") { // original test case: incomplete float64 std::vector vec1 {0xcb, 0x8f, 0x0a}; - CHECK_THROWS_AS(json::from_msgpack(vec1), json::parse_error&); + CHECK_THROWS_AS(json::from_msgpack(vec1), json::parse_error); CHECK_THROWS_WITH(json::from_msgpack(vec1), "[json.exception.parse_error.110] parse error at 4: unexpected end of input"); // related test case: incomplete float32 std::vector vec2 {0xca, 0x8f, 0x0a}; - CHECK_THROWS_AS(json::from_msgpack(vec2), json::parse_error&); + CHECK_THROWS_AS(json::from_msgpack(vec2), json::parse_error); CHECK_THROWS_WITH(json::from_msgpack(vec2), "[json.exception.parse_error.110] parse error at 4: unexpected end of input"); // related test case: incomplete Half-Precision Float (CBOR) std::vector vec3 {0xf9, 0x8f}; - CHECK_THROWS_AS(json::from_cbor(vec3), json::parse_error&); + CHECK_THROWS_AS(json::from_cbor(vec3), json::parse_error); CHECK_THROWS_WITH(json::from_cbor(vec3), "[json.exception.parse_error.110] parse error at 3: unexpected end of input"); // related test case: incomplete Single-Precision Float (CBOR) std::vector vec4 {0xfa, 0x8f, 0x0a}; - CHECK_THROWS_AS(json::from_cbor(vec4), json::parse_error&); + CHECK_THROWS_AS(json::from_cbor(vec4), json::parse_error); CHECK_THROWS_WITH(json::from_cbor(vec4), "[json.exception.parse_error.110] parse error at 4: unexpected end of input"); // related test case: incomplete Double-Precision Float (CBOR) std::vector vec5 {0xfb, 0x8f, 0x0a}; - CHECK_THROWS_AS(json::from_cbor(vec5), json::parse_error&); + CHECK_THROWS_AS(json::from_cbor(vec5), json::parse_error); CHECK_THROWS_WITH(json::from_cbor(vec5), "[json.exception.parse_error.110] parse error at 4: unexpected end of input"); } @@ -834,7 +834,7 @@ TEST_CASE("regression tests") { // original test case std::vector vec1 {0x87}; - CHECK_THROWS_AS(json::from_msgpack(vec1), json::parse_error&); + CHECK_THROWS_AS(json::from_msgpack(vec1), json::parse_error); CHECK_THROWS_WITH(json::from_msgpack(vec1), "[json.exception.parse_error.110] parse error at 2: unexpected end of input"); @@ -848,7 +848,7 @@ TEST_CASE("regression tests") }) { std::vector vec(1, static_cast(b)); - CHECK_THROWS_AS(json::from_msgpack(vec), json::parse_error&); + CHECK_THROWS_AS(json::from_msgpack(vec), json::parse_error); } // more test cases for CBOR @@ -863,15 +863,15 @@ TEST_CASE("regression tests") }) { std::vector vec(1, static_cast(b)); - CHECK_THROWS_AS(json::from_cbor(vec), json::parse_error&); + CHECK_THROWS_AS(json::from_cbor(vec), json::parse_error); } // special case: empty input std::vector vec2; - CHECK_THROWS_AS(json::from_cbor(vec2), json::parse_error&); + CHECK_THROWS_AS(json::from_cbor(vec2), json::parse_error); CHECK_THROWS_WITH(json::from_cbor(vec2), "[json.exception.parse_error.110] parse error at 1: unexpected end of input"); - CHECK_THROWS_AS(json::from_msgpack(vec2), json::parse_error&); + CHECK_THROWS_AS(json::from_msgpack(vec2), json::parse_error); CHECK_THROWS_WITH(json::from_msgpack(vec2), "[json.exception.parse_error.110] parse error at 1: unexpected end of input"); } @@ -880,19 +880,19 @@ TEST_CASE("regression tests") { // original test case: empty UTF-8 string (indefinite length) std::vector vec1 {0x7f}; - CHECK_THROWS_AS(json::from_cbor(vec1), json::parse_error&); + CHECK_THROWS_AS(json::from_cbor(vec1), json::parse_error); CHECK_THROWS_WITH(json::from_cbor(vec1), "[json.exception.parse_error.110] parse error at 2: unexpected end of input"); // related test case: empty array (indefinite length) std::vector vec2 {0x9f}; - CHECK_THROWS_AS(json::from_cbor(vec2), json::parse_error&); + CHECK_THROWS_AS(json::from_cbor(vec2), json::parse_error); CHECK_THROWS_WITH(json::from_cbor(vec2), "[json.exception.parse_error.110] parse error at 2: unexpected end of input"); // related test case: empty map (indefinite length) std::vector vec3 {0xbf}; - CHECK_THROWS_AS(json::from_cbor(vec3), json::parse_error&); + CHECK_THROWS_AS(json::from_cbor(vec3), json::parse_error); CHECK_THROWS_WITH(json::from_cbor(vec3), "[json.exception.parse_error.110] parse error at 2: unexpected end of input"); } @@ -920,25 +920,25 @@ TEST_CASE("regression tests") 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60 }; - CHECK_THROWS_AS(json::from_cbor(vec), json::parse_error&); + CHECK_THROWS_AS(json::from_cbor(vec), json::parse_error); CHECK_THROWS_WITH(json::from_cbor(vec), "[json.exception.parse_error.113] parse error at 2: expected a CBOR string; last byte: 0x98"); // related test case: nonempty UTF-8 string (indefinite length) std::vector vec1 {0x7f, 0x61, 0x61}; - CHECK_THROWS_AS(json::from_cbor(vec1), json::parse_error&); + CHECK_THROWS_AS(json::from_cbor(vec1), json::parse_error); CHECK_THROWS_WITH(json::from_cbor(vec1), "[json.exception.parse_error.110] parse error at 4: unexpected end of input"); // related test case: nonempty array (indefinite length) std::vector vec2 {0x9f, 0x01}; - CHECK_THROWS_AS(json::from_cbor(vec2), json::parse_error&); + CHECK_THROWS_AS(json::from_cbor(vec2), json::parse_error); CHECK_THROWS_WITH(json::from_cbor(vec2), "[json.exception.parse_error.110] parse error at 3: unexpected end of input"); // related test case: nonempty map (indefinite length) std::vector vec3 {0xbf, 0x61, 0x61, 0x01}; - CHECK_THROWS_AS(json::from_cbor(vec3), json::parse_error&); + CHECK_THROWS_AS(json::from_cbor(vec3), json::parse_error); CHECK_THROWS_WITH(json::from_cbor(vec3), "[json.exception.parse_error.110] parse error at 5: unexpected end of input"); } @@ -973,7 +973,7 @@ TEST_CASE("regression tests") 0x96, 0x96, 0xb4, 0xb4, 0xfa, 0x94, 0x94, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0xfa }; - CHECK_THROWS_AS(json::from_cbor(vec1), json::parse_error&); + CHECK_THROWS_AS(json::from_cbor(vec1), json::parse_error); CHECK_THROWS_WITH(json::from_cbor(vec1), "[json.exception.parse_error.113] parse error at 13: expected a CBOR string; last byte: 0xB4"); @@ -987,7 +987,7 @@ TEST_CASE("regression tests") 0x96, 0x96, 0xb4, 0xb4, 0xfa, 0x94, 0x94, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0xfb }; - CHECK_THROWS_AS(json::from_cbor(vec2), json::parse_error&); + CHECK_THROWS_AS(json::from_cbor(vec2), json::parse_error); CHECK_THROWS_WITH(json::from_cbor(vec2), "[json.exception.parse_error.113] parse error at 13: expected a CBOR string; last byte: 0xB4"); } @@ -995,7 +995,7 @@ TEST_CASE("regression tests") SECTION("issue #452 - Heap-buffer-overflow (OSS-Fuzz issue 585)") { std::vector vec = {'-', '0', '1', '2', '2', '7', '4'}; - CHECK_THROWS_AS(json::parse(vec), json::parse_error&); + CHECK_THROWS_AS(json::parse(vec), json::parse_error); } SECTION("issue #454 - doubles are printed as integers") @@ -1035,9 +1035,9 @@ TEST_CASE("regression tests") }; CHECK_NOTHROW(create(j_array)); - CHECK_THROWS_AS(create(j_number), json::type_error&); + CHECK_THROWS_AS(create(j_number), json::type_error); CHECK_THROWS_WITH(create(j_number), "[json.exception.type_error.302] type must be array, but is number"); - CHECK_THROWS_AS(create(j_null), json::type_error&); + CHECK_THROWS_AS(create(j_null), json::type_error); CHECK_THROWS_WITH(create(j_null), "[json.exception.type_error.302] type must be array, but is null"); } @@ -1049,9 +1049,9 @@ TEST_CASE("regression tests") }; CHECK_NOTHROW(create(j_array)); - CHECK_THROWS_AS(create(j_number), json::type_error&); + CHECK_THROWS_AS(create(j_number), json::type_error); CHECK_THROWS_WITH(create(j_number), "[json.exception.type_error.302] type must be array, but is number"); - CHECK_THROWS_AS(create(j_null), json::type_error&); + CHECK_THROWS_AS(create(j_null), json::type_error); CHECK_THROWS_WITH(create(j_null), "[json.exception.type_error.302] type must be array, but is null"); } @@ -1063,9 +1063,9 @@ TEST_CASE("regression tests") }; CHECK_NOTHROW(create(j_array)); - CHECK_THROWS_AS(create(j_number), json::type_error&); + CHECK_THROWS_AS(create(j_number), json::type_error); CHECK_THROWS_WITH(create(j_number), "[json.exception.type_error.302] type must be array, but is number"); - CHECK_THROWS_AS(create(j_null), json::type_error&); + CHECK_THROWS_AS(create(j_null), json::type_error); CHECK_THROWS_WITH(create(j_null), "[json.exception.type_error.302] type must be array, but is null"); } } @@ -1100,7 +1100,7 @@ TEST_CASE("regression tests") l.m_stream->setstate(std::ios_base::failbit); - CHECK_THROWS_AS(l.fill_line_buffer(), json::parse_error&); + CHECK_THROWS_AS(l.fill_line_buffer(), json::parse_error); CHECK_THROWS_WITH(l.fill_line_buffer(), "[json.exception.parse_error.111] parse error: bad input stream"); } @@ -1115,7 +1115,7 @@ TEST_CASE("regression tests") l.m_stream->setstate(std::ios_base::badbit); - CHECK_THROWS_AS(l.fill_line_buffer(), json::parse_error&); + CHECK_THROWS_AS(l.fill_line_buffer(), json::parse_error); CHECK_THROWS_WITH(l.fill_line_buffer(), "[json.exception.parse_error.111] parse error: bad input stream"); } } @@ -1179,7 +1179,7 @@ TEST_CASE("regression tests") SECTION("issue #575 - heap-buffer-overflow (OSS-Fuzz 1400)") { std::vector vec = {'"', '\\', '"', 'X', '"', '"'}; - CHECK_THROWS_AS(json::parse(vec), json::parse_error&); + CHECK_THROWS_AS(json::parse(vec), json::parse_error); } SECTION("issue #600 - how does one convert a map in Json back to std::map?") @@ -1244,7 +1244,7 @@ TEST_CASE("regression tests") CHECK(v[i] == j[i]); } - CHECK_THROWS_AS(json().get>(), json::type_error&); + CHECK_THROWS_AS(json().get>(), json::type_error); CHECK_THROWS_WITH(json().get>(), "[json.exception.type_error.302] type must be array, but is null"); } diff --git a/test/src/unit-testsuites.cpp b/test/src/unit-testsuites.cpp index d281c679f..d3dbaf4b1 100644 --- a/test/src/unit-testsuites.cpp +++ b/test/src/unit-testsuites.cpp @@ -78,7 +78,7 @@ TEST_CASE("compliance tests from json.org") { CAPTURE(filename); std::ifstream f(filename); - CHECK_THROWS_AS(json::parse(f), json::parse_error&); + CHECK_THROWS_AS(json::parse(f), json::parse_error); } } @@ -772,7 +772,7 @@ TEST_CASE("nst's JSONTestSuite") { CAPTURE(filename); std::ifstream f(filename); - CHECK_THROWS_AS(json::parse(f), json::parse_error&); + CHECK_THROWS_AS(json::parse(f), json::parse_error); } } @@ -848,7 +848,7 @@ TEST_CASE("nst's JSONTestSuite") CAPTURE(filename); std::ifstream f(filename); json j; - CHECK_THROWS_AS(f >> j, json::out_of_range&); + CHECK_THROWS_AS(f >> j, json::out_of_range); } } @@ -875,7 +875,7 @@ TEST_CASE("nst's JSONTestSuite") CAPTURE(filename); std::ifstream f(filename); json j; - CHECK_THROWS_AS(f >> j, json::parse_error&); + CHECK_THROWS_AS(f >> j, json::parse_error); } } } diff --git a/test/src/unit-unicode.cpp b/test/src/unit-unicode.cpp index b51a1579e..9d4d65ca9 100644 --- a/test/src/unit-unicode.cpp +++ b/test/src/unit-unicode.cpp @@ -81,7 +81,7 @@ void check_utf8string(bool success_expected, int byte1, int byte2 = -1, int byte } else { - CHECK_THROWS_AS(json::parse(json_string), json::parse_error&); + CHECK_THROWS_AS(json::parse(json_string), json::parse_error); } } @@ -928,31 +928,31 @@ TEST_CASE("Unicode", "[hide]") { SECTION("incorrect surrogate values") { - CHECK_THROWS_AS(json::parse("\"\\uDC00\\uDC00\""), json::parse_error&); + CHECK_THROWS_AS(json::parse("\"\\uDC00\\uDC00\""), json::parse_error); CHECK_THROWS_WITH(json::parse("\"\\uDC00\\uDC00\""), "[json.exception.parse_error.101] parse error at 7: syntax error - invalid string: surrogate U+DC00..U+DFFF must follow U+D800..U+DBFF; last read: '\"\\uDC00'"); - CHECK_THROWS_AS(json::parse("\"\\uD7FF\\uDC00\""), json::parse_error&); + CHECK_THROWS_AS(json::parse("\"\\uD7FF\\uDC00\""), json::parse_error); CHECK_THROWS_WITH(json::parse("\"\\uD7FF\\uDC00\""), "[json.exception.parse_error.101] parse error at 13: syntax error - invalid string: surrogate U+DC00..U+DFFF must follow U+D800..U+DBFF; last read: '\"\\uD7FF\\uDC00'"); - CHECK_THROWS_AS(json::parse("\"\\uD800]\""), json::parse_error&); + CHECK_THROWS_AS(json::parse("\"\\uD800]\""), json::parse_error); CHECK_THROWS_WITH(json::parse("\"\\uD800]\""), "[json.exception.parse_error.101] parse error at 8: syntax error - invalid string: surrogate U+DC00..U+DFFF must be followed by U+DC00..U+DFFF; last read: '\"\\uD800]'"); - CHECK_THROWS_AS(json::parse("\"\\uD800\\v\""), json::parse_error&); + CHECK_THROWS_AS(json::parse("\"\\uD800\\v\""), json::parse_error); CHECK_THROWS_WITH(json::parse("\"\\uD800\\v\""), "[json.exception.parse_error.101] parse error at 9: syntax error - invalid string: surrogate U+DC00..U+DFFF must be followed by U+DC00..U+DFFF; last read: '\"\\uD800\\v'"); - CHECK_THROWS_AS(json::parse("\"\\uD800\\u123\""), json::parse_error&); + CHECK_THROWS_AS(json::parse("\"\\uD800\\u123\""), json::parse_error); CHECK_THROWS_WITH(json::parse("\"\\uD800\\u123\""), "[json.exception.parse_error.101] parse error at 13: syntax error - invalid string: '\\u' must be followed by 4 hex digits; last read: '\"\\uD800\\u123\"'"); - CHECK_THROWS_AS(json::parse("\"\\uD800\\uDBFF\""), json::parse_error&); + CHECK_THROWS_AS(json::parse("\"\\uD800\\uDBFF\""), json::parse_error); CHECK_THROWS_WITH(json::parse("\"\\uD800\\uDBFF\""), "[json.exception.parse_error.101] parse error at 13: syntax error - invalid string: surrogate U+DC00..U+DFFF must be followed by U+DC00..U+DFFF; last read: '\"\\uD800\\uDBFF'"); - CHECK_THROWS_AS(json::parse("\"\\uD800\\uE000\""), json::parse_error&); + CHECK_THROWS_AS(json::parse("\"\\uD800\\uE000\""), json::parse_error); CHECK_THROWS_WITH(json::parse("\"\\uD800\\uE000\""), "[json.exception.parse_error.101] parse error at 13: syntax error - invalid string: surrogate U+DC00..U+DFFF must be followed by U+DC00..U+DFFF; last read: '\"\\uD800\\uE000'"); } @@ -969,7 +969,7 @@ TEST_CASE("Unicode", "[hide]") { std::string json_text = "\"" + codepoint_to_unicode(cp) + "\""; CAPTURE(json_text); - CHECK_THROWS_AS(json::parse(json_text), json::parse_error&); + CHECK_THROWS_AS(json::parse(json_text), json::parse_error); } } @@ -988,7 +988,7 @@ TEST_CASE("Unicode", "[hide]") std::string json_text = "\"" + codepoint_to_unicode(cp1) + codepoint_to_unicode(cp2) + "\""; CAPTURE(json_text); - CHECK_THROWS_AS(json::parse(json_text), json::parse_error&); + CHECK_THROWS_AS(json::parse(json_text), json::parse_error); } } } @@ -1001,7 +1001,7 @@ TEST_CASE("Unicode", "[hide]") { std::string json_text = "\"" + codepoint_to_unicode(cp) + "\""; CAPTURE(json_text); - CHECK_THROWS_AS(json::parse(json_text), json::parse_error&); + CHECK_THROWS_AS(json::parse(json_text), json::parse_error); } } @@ -1072,7 +1072,7 @@ TEST_CASE("Unicode", "[hide]") SECTION("error for incomplete/wrong BOM") { - CHECK_THROWS_AS(json::parse("\xef\xbb"), json::parse_error&); - CHECK_THROWS_AS(json::parse("\xef\xbb\xbb"), json::parse_error&); + CHECK_THROWS_AS(json::parse("\xef\xbb"), json::parse_error); + CHECK_THROWS_AS(json::parse("\xef\xbb\xbb"), json::parse_error); } } diff --git a/test/thirdparty/catch/catch.hpp b/test/thirdparty/catch/catch.hpp index 7c351e931..362f8693f 100644 --- a/test/thirdparty/catch/catch.hpp +++ b/test/thirdparty/catch/catch.hpp @@ -1,17 +1,17 @@ /* - * Catch v1.9.7 - * Generated: 2017-08-10 23:49:15.233907 + * Catch v2.0.1 + * Generated: 2017-11-03 11:53:39.642003 * ---------------------------------------------------------- * This file has been merged from multiple headers. Please don't edit it directly - * Copyright (c) 2012 Two Blue Cubes Ltd. All rights reserved. + * Copyright (c) 2017 Two Blue Cubes Ltd. All rights reserved. * * Distributed under the Boost Software License, Version 1.0. (See accompanying * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) */ #ifndef TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED #define TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED +// start catch.hpp -#define TWOBLUECUBES_CATCH_HPP_INCLUDED #ifdef __clang__ # pragma clang system_header @@ -19,7 +19,7 @@ # pragma GCC system_header #endif -// #included from: internal/catch_suppress_warnings.h +// start catch_suppress_warnings.h #ifdef __clang__ # ifdef __ICC // icpc defines the __clang__ macro @@ -32,8 +32,6 @@ # pragma clang diagnostic ignored "-Wunused-variable" # pragma clang diagnostic push # pragma clang diagnostic ignored "-Wpadded" -# pragma clang diagnostic ignored "-Wc++98-compat" -# pragma clang diagnostic ignored "-Wc++98-compat-pedantic" # pragma clang diagnostic ignored "-Wswitch-enum" # pragma clang diagnostic ignored "-Wcovered-switch-default" # endif @@ -45,10 +43,33 @@ # pragma GCC diagnostic push # pragma GCC diagnostic ignored "-Wpadded" #endif +// end catch_suppress_warnings.h #if defined(CATCH_CONFIG_MAIN) || defined(CATCH_CONFIG_RUNNER) # define CATCH_IMPL +# define CATCH_CONFIG_EXTERNAL_INTERFACES +# if defined(CATCH_CONFIG_DISABLE_MATCHERS) +# undef CATCH_CONFIG_DISABLE_MATCHERS +# endif #endif +// start catch_platform.h + +#ifdef __APPLE__ +# include +# if TARGET_OS_MAC == 1 +# define CATCH_PLATFORM_MAC +# elif TARGET_OS_IPHONE == 1 +# define CATCH_PLATFORM_IPHONE +# endif + +#elif defined(linux) || defined(__linux) || defined(__linux__) +# define CATCH_PLATFORM_LINUX + +#elif defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) +# define CATCH_PLATFORM_WINDOWS +#endif + +// end catch_platform.h #ifdef CATCH_IMPL # ifndef CLARA_CONFIG_MAIN # define CLARA_CONFIG_MAIN_NOT_DEFINED @@ -56,32 +77,15 @@ # endif #endif -// #included from: internal/catch_notimplemented_exception.h -#define TWOBLUECUBES_CATCH_NOTIMPLEMENTED_EXCEPTION_H_INCLUDED +// start catch_tag_alias_autoregistrar.h -// #included from: catch_common.h -#define TWOBLUECUBES_CATCH_COMMON_H_INCLUDED +// start catch_common.h -// #included from: catch_compiler_capabilities.h -#define TWOBLUECUBES_CATCH_COMPILER_CAPABILITIES_HPP_INCLUDED +// start catch_compiler_capabilities.h -// Detect a number of compiler features - mostly C++11/14 conformance - by compiler +// Detect a number of compiler features - by compiler // The following features are defined: // -// CATCH_CONFIG_CPP11_NULLPTR : is nullptr supported? -// CATCH_CONFIG_CPP11_NOEXCEPT : is noexcept supported? -// CATCH_CONFIG_CPP11_GENERATED_METHODS : The delete and default keywords for compiler generated methods -// CATCH_CONFIG_CPP11_IS_ENUM : std::is_enum is supported? -// CATCH_CONFIG_CPP11_TUPLE : std::tuple is supported -// CATCH_CONFIG_CPP11_LONG_LONG : is long long supported? -// CATCH_CONFIG_CPP11_OVERRIDE : is override supported? -// CATCH_CONFIG_CPP11_UNIQUE_PTR : is unique_ptr supported (otherwise use auto_ptr) -// CATCH_CONFIG_CPP11_SHUFFLE : is std::shuffle supported? -// CATCH_CONFIG_CPP11_TYPE_TRAITS : are type_traits and enable_if supported? - -// CATCH_CONFIG_CPP11_OR_GREATER : Is C++11 supported? - -// CATCH_CONFIG_VARIADIC_MACROS : are variadic macros supported? // CATCH_CONFIG_COUNTER : is the __COUNTER__ macro supported? // CATCH_CONFIG_WINDOWS_SEH : is Windows SEH supported? // CATCH_CONFIG_POSIX_SIGNALS : are POSIX signals supported? @@ -91,18 +95,12 @@ // **************** // In general each macro has a _NO_ form -// (e.g. CATCH_CONFIG_CPP11_NO_NULLPTR) which disables the feature. +// (e.g. CATCH_CONFIG_NO_POSIX_SIGNALS) which disables the feature. // Many features, at point of detection, define an _INTERNAL_ macro, so they // can be combined, en-mass, with the _NO_ forms later. -// All the C++11 features can be disabled with CATCH_CONFIG_NO_CPP11 - #ifdef __cplusplus -# if __cplusplus >= 201103L -# define CATCH_CPP11_OR_GREATER -# endif - # if __cplusplus >= 201402L # define CATCH_CPP14_OR_GREATER # endif @@ -111,19 +109,11 @@ #ifdef __clang__ -# if __has_feature(cxx_nullptr) -# define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR -# endif - -# if __has_feature(cxx_noexcept) -# define CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT -# endif - -# if defined(CATCH_CPP11_OR_GREATER) -# define CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS \ +# define CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ _Pragma( "clang diagnostic push" ) \ - _Pragma( "clang diagnostic ignored \"-Wexit-time-destructors\"" ) -# define CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS \ + _Pragma( "clang diagnostic ignored \"-Wexit-time-destructors\"" ) \ + _Pragma( "clang diagnostic ignored \"-Wglobal-constructors\"") +# define CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS \ _Pragma( "clang diagnostic pop" ) # define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \ @@ -131,7 +121,6 @@ _Pragma( "clang diagnostic ignored \"-Wparentheses\"" ) # define CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS \ _Pragma( "clang diagnostic pop" ) -# endif #endif // __clang__ @@ -160,167 +149,34 @@ #endif // __CYGWIN__ -//////////////////////////////////////////////////////////////////////////////// -// Borland -#ifdef __BORLANDC__ - -#endif // __BORLANDC__ - -//////////////////////////////////////////////////////////////////////////////// -// EDG -#ifdef __EDG_VERSION__ - -#endif // __EDG_VERSION__ - -//////////////////////////////////////////////////////////////////////////////// -// Digital Mars -#ifdef __DMC__ - -#endif // __DMC__ - -//////////////////////////////////////////////////////////////////////////////// -// GCC -#ifdef __GNUC__ - -# if __GNUC__ == 4 && __GNUC_MINOR__ >= 6 && defined(__GXX_EXPERIMENTAL_CXX0X__) -# define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR -# endif - -// - otherwise more recent versions define __cplusplus >= 201103L -// and will get picked up below - -#endif // __GNUC__ - //////////////////////////////////////////////////////////////////////////////// // Visual C++ #ifdef _MSC_VER -#define CATCH_INTERNAL_CONFIG_WINDOWS_SEH - -#if (_MSC_VER >= 1600) -# define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR -# define CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR -#endif - -#if (_MSC_VER >= 1900 ) // (VC++ 13 (VS2015)) -#define CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT -#define CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS -#define CATCH_INTERNAL_CONFIG_CPP11_SHUFFLE -#define CATCH_INTERNAL_CONFIG_CPP11_TYPE_TRAITS -#endif +// Universal Windows platform does not support SEH +// Or console colours (or console at all...) +# if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_APP) +# define CATCH_CONFIG_COLOUR_NONE +# else +# define CATCH_INTERNAL_CONFIG_WINDOWS_SEH +# endif #endif // _MSC_VER //////////////////////////////////////////////////////////////////////////////// -// Use variadic macros if the compiler supports them -#if ( defined _MSC_VER && _MSC_VER > 1400 && !defined __EDGE__) || \ - ( defined __WAVE__ && __WAVE_HAS_VARIADICS ) || \ - ( defined __GNUC__ && __GNUC__ >= 3 ) || \ - ( !defined __cplusplus && __STDC_VERSION__ >= 199901L || __cplusplus >= 201103L ) - -#define CATCH_INTERNAL_CONFIG_VARIADIC_MACROS - +// Use of __COUNTER__ is suppressed during code analysis in +// CLion/AppCode 2017.2.x and former, because __COUNTER__ is not properly +// handled by it. +// Otherwise all supported compilers support COUNTER macro, +// but user still might want to turn it off +#if ( !defined(__JETBRAINS_IDE__) || __JETBRAINS_IDE__ >= 20170300L ) + #define CATCH_INTERNAL_CONFIG_COUNTER #endif -// Use __COUNTER__ if the compiler supports it -#if ( defined _MSC_VER && _MSC_VER >= 1300 ) || \ - ( defined __GNUC__ && ( __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3 )) ) || \ - ( defined __clang__ && __clang_major__ >= 3 ) - -#define CATCH_INTERNAL_CONFIG_COUNTER - -#endif - -//////////////////////////////////////////////////////////////////////////////// -// C++ language feature support - -// catch all support for C++11 -#if defined(CATCH_CPP11_OR_GREATER) - -# if !defined(CATCH_INTERNAL_CONFIG_CPP11_NULLPTR) -# define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR -# endif - -# ifndef CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT -# define CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT -# endif - -# ifndef CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS -# define CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS -# endif - -# ifndef CATCH_INTERNAL_CONFIG_CPP11_IS_ENUM -# define CATCH_INTERNAL_CONFIG_CPP11_IS_ENUM -# endif - -# ifndef CATCH_INTERNAL_CONFIG_CPP11_TUPLE -# define CATCH_INTERNAL_CONFIG_CPP11_TUPLE -# endif - -# ifndef CATCH_INTERNAL_CONFIG_VARIADIC_MACROS -# define CATCH_INTERNAL_CONFIG_VARIADIC_MACROS -# endif - -# if !defined(CATCH_INTERNAL_CONFIG_CPP11_LONG_LONG) -# define CATCH_INTERNAL_CONFIG_CPP11_LONG_LONG -# endif - -# if !defined(CATCH_INTERNAL_CONFIG_CPP11_OVERRIDE) -# define CATCH_INTERNAL_CONFIG_CPP11_OVERRIDE -# endif -# if !defined(CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR) -# define CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR -# endif -# if !defined(CATCH_INTERNAL_CONFIG_CPP11_SHUFFLE) -# define CATCH_INTERNAL_CONFIG_CPP11_SHUFFLE -# endif -# if !defined(CATCH_INTERNAL_CONFIG_CPP11_TYPE_TRAITS) -# define CATCH_INTERNAL_CONFIG_CPP11_TYPE_TRAITS -# endif - -#endif // __cplusplus >= 201103L - -// Now set the actual defines based on the above + anything the user has configured -#if defined(CATCH_INTERNAL_CONFIG_CPP11_NULLPTR) && !defined(CATCH_CONFIG_CPP11_NO_NULLPTR) && !defined(CATCH_CONFIG_CPP11_NULLPTR) && !defined(CATCH_CONFIG_NO_CPP11) -# define CATCH_CONFIG_CPP11_NULLPTR -#endif -#if defined(CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT) && !defined(CATCH_CONFIG_CPP11_NO_NOEXCEPT) && !defined(CATCH_CONFIG_CPP11_NOEXCEPT) && !defined(CATCH_CONFIG_NO_CPP11) -# define CATCH_CONFIG_CPP11_NOEXCEPT -#endif -#if defined(CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS) && !defined(CATCH_CONFIG_CPP11_NO_GENERATED_METHODS) && !defined(CATCH_CONFIG_CPP11_GENERATED_METHODS) && !defined(CATCH_CONFIG_NO_CPP11) -# define CATCH_CONFIG_CPP11_GENERATED_METHODS -#endif -#if defined(CATCH_INTERNAL_CONFIG_CPP11_IS_ENUM) && !defined(CATCH_CONFIG_CPP11_NO_IS_ENUM) && !defined(CATCH_CONFIG_CPP11_IS_ENUM) && !defined(CATCH_CONFIG_NO_CPP11) -# define CATCH_CONFIG_CPP11_IS_ENUM -#endif -#if defined(CATCH_INTERNAL_CONFIG_CPP11_TUPLE) && !defined(CATCH_CONFIG_CPP11_NO_TUPLE) && !defined(CATCH_CONFIG_CPP11_TUPLE) && !defined(CATCH_CONFIG_NO_CPP11) -# define CATCH_CONFIG_CPP11_TUPLE -#endif -#if defined(CATCH_INTERNAL_CONFIG_VARIADIC_MACROS) && !defined(CATCH_CONFIG_NO_VARIADIC_MACROS) && !defined(CATCH_CONFIG_VARIADIC_MACROS) -# define CATCH_CONFIG_VARIADIC_MACROS -#endif -#if defined(CATCH_INTERNAL_CONFIG_CPP11_LONG_LONG) && !defined(CATCH_CONFIG_CPP11_NO_LONG_LONG) && !defined(CATCH_CONFIG_CPP11_LONG_LONG) && !defined(CATCH_CONFIG_NO_CPP11) -# define CATCH_CONFIG_CPP11_LONG_LONG -#endif -#if defined(CATCH_INTERNAL_CONFIG_CPP11_OVERRIDE) && !defined(CATCH_CONFIG_CPP11_NO_OVERRIDE) && !defined(CATCH_CONFIG_CPP11_OVERRIDE) && !defined(CATCH_CONFIG_NO_CPP11) -# define CATCH_CONFIG_CPP11_OVERRIDE -#endif -#if defined(CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR) && !defined(CATCH_CONFIG_CPP11_NO_UNIQUE_PTR) && !defined(CATCH_CONFIG_CPP11_UNIQUE_PTR) && !defined(CATCH_CONFIG_NO_CPP11) -# define CATCH_CONFIG_CPP11_UNIQUE_PTR -#endif -// Use of __COUNTER__ is suppressed if __JETBRAINS_IDE__ is #defined (meaning we're being parsed by a JetBrains IDE for -// analytics) because, at time of writing, __COUNTER__ is not properly handled by it. -// This does not affect compilation -#if defined(CATCH_INTERNAL_CONFIG_COUNTER) && !defined(CATCH_CONFIG_NO_COUNTER) && !defined(CATCH_CONFIG_COUNTER) && !defined(__JETBRAINS_IDE__) +#if defined(CATCH_INTERNAL_CONFIG_COUNTER) && !defined(CATCH_CONFIG_NO_COUNTER) && !defined(CATCH_CONFIG_COUNTER) # define CATCH_CONFIG_COUNTER #endif -#if defined(CATCH_INTERNAL_CONFIG_CPP11_SHUFFLE) && !defined(CATCH_CONFIG_CPP11_NO_SHUFFLE) && !defined(CATCH_CONFIG_CPP11_SHUFFLE) && !defined(CATCH_CONFIG_NO_CPP11) -# define CATCH_CONFIG_CPP11_SHUFFLE -#endif -# if defined(CATCH_INTERNAL_CONFIG_CPP11_TYPE_TRAITS) && !defined(CATCH_CONFIG_CPP11_NO_TYPE_TRAITS) && !defined(CATCH_CONFIG_CPP11_TYPE_TRAITS) && !defined(CATCH_CONFIG_NO_CPP11) -# define CATCH_CONFIG_CPP11_TYPE_TRAITS -# endif #if defined(CATCH_INTERNAL_CONFIG_WINDOWS_SEH) && !defined(CATCH_CONFIG_NO_WINDOWS_SEH) && !defined(CATCH_CONFIG_WINDOWS_SEH) # define CATCH_CONFIG_WINDOWS_SEH #endif @@ -333,41 +189,12 @@ # define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS # define CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS #endif -#if !defined(CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS) -# define CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS -# define CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS -#endif - -// noexcept support: -#if defined(CATCH_CONFIG_CPP11_NOEXCEPT) && !defined(CATCH_NOEXCEPT) -# define CATCH_NOEXCEPT noexcept -# define CATCH_NOEXCEPT_IS(x) noexcept(x) -#else -# define CATCH_NOEXCEPT throw() -# define CATCH_NOEXCEPT_IS(x) -#endif - -// nullptr support -#ifdef CATCH_CONFIG_CPP11_NULLPTR -# define CATCH_NULL nullptr -#else -# define CATCH_NULL NULL -#endif - -// override support -#ifdef CATCH_CONFIG_CPP11_OVERRIDE -# define CATCH_OVERRIDE override -#else -# define CATCH_OVERRIDE -#endif - -// unique_ptr support -#ifdef CATCH_CONFIG_CPP11_UNIQUE_PTR -# define CATCH_AUTO_PTR( T ) std::unique_ptr -#else -# define CATCH_AUTO_PTR( T ) std::auto_ptr +#if !defined(CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS) +# define CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS +# define CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS #endif +// end catch_compiler_capabilities.h #define INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) name##line #define INTERNAL_CATCH_UNIQUE_NAME_LINE( name, line ) INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) #ifdef CATCH_CONFIG_COUNTER @@ -376,95 +203,41 @@ # define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __LINE__ ) #endif -#define INTERNAL_CATCH_STRINGIFY2( expr ) #expr -#define INTERNAL_CATCH_STRINGIFY( expr ) INTERNAL_CATCH_STRINGIFY2( expr ) - -#include -#include +#include +#include +#include namespace Catch { - struct IConfig; - struct CaseSensitive { enum Choice { Yes, No }; }; class NonCopyable { -#ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS NonCopyable( NonCopyable const& ) = delete; NonCopyable( NonCopyable && ) = delete; NonCopyable& operator = ( NonCopyable const& ) = delete; NonCopyable& operator = ( NonCopyable && ) = delete; -#else - NonCopyable( NonCopyable const& info ); - NonCopyable& operator = ( NonCopyable const& ); -#endif protected: - NonCopyable() {} + NonCopyable(); virtual ~NonCopyable(); }; - class SafeBool { - public: - typedef void (SafeBool::*type)() const; - - static type makeSafe( bool value ) { - return value ? &SafeBool::trueValue : 0; - } - private: - void trueValue() const {} - }; - - template - 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 - 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 startsWith( std::string const& s, char prefix ); - bool endsWith( std::string const& s, std::string const& suffix ); - bool endsWith( std::string const& s, char suffix ); - bool contains( std::string const& s, std::string const& infix ); - void toLowerInPlace( std::string& s ); - std::string toLower( std::string const& s ); - std::string trim( std::string const& str ); - bool replaceInPlace( std::string& str, std::string const& replaceThis, std::string const& withThis ); - - struct pluralise { - pluralise( std::size_t count, std::string const& label ); - - friend std::ostream& operator << ( std::ostream& os, pluralise const& pluraliser ); - - std::size_t m_count; - std::string m_label; - }; - struct SourceLineInfo { - SourceLineInfo(); - SourceLineInfo( char const* _file, std::size_t _line ); -# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS - SourceLineInfo(SourceLineInfo const& other) = default; + SourceLineInfo() = delete; + SourceLineInfo( char const* _file, std::size_t _line ) noexcept; + + SourceLineInfo( SourceLineInfo const& other ) = default; SourceLineInfo( SourceLineInfo && ) = default; SourceLineInfo& operator = ( SourceLineInfo const& ) = default; SourceLineInfo& operator = ( SourceLineInfo && ) = default; -# endif - bool empty() const; - bool operator == ( SourceLineInfo const& other ) const; - bool operator < ( SourceLineInfo const& other ) const; + + bool empty() const noexcept; + bool operator == ( SourceLineInfo const& other ) const noexcept; + bool operator < ( SourceLineInfo const& other ) const noexcept; char const* file; std::size_t line; @@ -473,23 +246,16 @@ namespace Catch { std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info ); // This is just here to avoid compiler warnings with macro constants and boolean literals - inline bool isTrue( bool value ){ return value; } - inline bool alwaysTrue() { return true; } - inline bool alwaysFalse() { return false; } - - void throwLogicError( std::string const& message, SourceLineInfo const& locationInfo ); - - void seedRng( IConfig const& config ); - unsigned int rngSeed(); + bool isTrue( bool value ); + bool alwaysTrue(); + bool alwaysFalse(); // Use this in variadic streaming macros to allow // >> +StreamEndStop // as well as // >> stuff +StreamEndStop struct StreamEndStop { - std::string operator+() { - return std::string(); - } + std::string operator+() const; }; template T const& operator + ( T const& value, StreamEndStop ) { @@ -497,193 +263,39 @@ namespace Catch { } } -#define CATCH_INTERNAL_LINEINFO ::Catch::SourceLineInfo( __FILE__, static_cast( __LINE__ ) ) -#define CATCH_INTERNAL_ERROR( msg ) ::Catch::throwLogicError( msg, CATCH_INTERNAL_LINEINFO ); +#define CATCH_INTERNAL_LINEINFO \ + ::Catch::SourceLineInfo( __FILE__, static_cast( __LINE__ ) ) +// end catch_common.h namespace Catch { - class NotImplementedException : public std::exception - { - public: - NotImplementedException( SourceLineInfo const& lineInfo ); - - virtual ~NotImplementedException() CATCH_NOEXCEPT {} - - virtual const char* what() const CATCH_NOEXCEPT; - - private: - std::string m_what; - SourceLineInfo m_lineInfo; + struct RegistrarForTagAliases { + RegistrarForTagAliases( char const* alias, char const* tag, SourceLineInfo const& lineInfo ); }; } // end namespace Catch -/////////////////////////////////////////////////////////////////////////////// -#define CATCH_NOT_IMPLEMENTED throw Catch::NotImplementedException( CATCH_INTERNAL_LINEINFO ) +#define CATCH_REGISTER_TAG_ALIAS( alias, spec ) namespace{ Catch::RegistrarForTagAliases INTERNAL_CATCH_UNIQUE_NAME( AutoRegisterTagAlias )( alias, spec, CATCH_INTERNAL_LINEINFO ); } -// #included from: internal/catch_context.h -#define TWOBLUECUBES_CATCH_CONTEXT_H_INCLUDED +// end catch_tag_alias_autoregistrar.h +// start catch_test_registry.h -// #included from: catch_interfaces_generators.h -#define TWOBLUECUBES_CATCH_INTERFACES_GENERATORS_H_INCLUDED - -#include - -namespace Catch { - - struct IGeneratorInfo { - virtual ~IGeneratorInfo(); - virtual bool moveNext() = 0; - virtual std::size_t getCurrentIndex() const = 0; - }; - - struct IGeneratorsForTest { - virtual ~IGeneratorsForTest(); - - virtual IGeneratorInfo& getGeneratorInfo( std::string const& fileInfo, std::size_t size ) = 0; - virtual bool moveNext() = 0; - }; - - IGeneratorsForTest* createGeneratorsForTest(); - -} // end namespace Catch - -// #included from: catch_ptr.hpp -#define TWOBLUECUBES_CATCH_PTR_HPP_INCLUDED - -#ifdef __clang__ -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wpadded" -#endif - -namespace Catch { - - // An intrusive reference counting smart pointer. - // T must implement addRef() and release() methods - // typically implementing the IShared interface - template - class Ptr { - public: - Ptr() : m_p( CATCH_NULL ){} - Ptr( T* p ) : m_p( p ){ - if( m_p ) - m_p->addRef(); - } - Ptr( Ptr const& other ) : m_p( other.m_p ){ - if( m_p ) - m_p->addRef(); - } - ~Ptr(){ - if( m_p ) - m_p->release(); - } - void reset() { - if( m_p ) - m_p->release(); - m_p = CATCH_NULL; - } - Ptr& operator = ( T* p ){ - Ptr temp( p ); - swap( temp ); - return *this; - } - Ptr& operator = ( Ptr const& other ){ - Ptr temp( other ); - swap( temp ); - return *this; - } - void swap( Ptr& other ) { std::swap( m_p, other.m_p ); } - T* get() const{ return m_p; } - T& operator*() const { return *m_p; } - T* operator->() const { return m_p; } - bool operator !() const { return m_p == CATCH_NULL; } - operator SafeBool::type() const { return SafeBool::makeSafe( m_p != CATCH_NULL ); } - - private: - T* m_p; - }; - - struct IShared : NonCopyable { - virtual ~IShared(); - virtual void addRef() const = 0; - virtual void release() const = 0; - }; - - template - struct SharedImpl : T { - - SharedImpl() : m_rc( 0 ){} - - virtual void addRef() const { - ++m_rc; - } - virtual void release() const { - if( --m_rc == 0 ) - delete this; - } - - mutable unsigned int m_rc; - }; - -} // end namespace Catch - -#ifdef __clang__ -#pragma clang diagnostic pop -#endif - -namespace Catch { - - class TestCase; - class Stream; - struct IResultCapture; - struct IRunner; - struct IGeneratorsForTest; - struct IConfig; - - struct IContext - { - virtual ~IContext(); - - virtual IResultCapture* getResultCapture() = 0; - virtual IRunner* getRunner() = 0; - virtual size_t getGeneratorIndex( std::string const& fileInfo, size_t totalSize ) = 0; - virtual bool advanceGeneratorsForCurrentTest() = 0; - virtual Ptr 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; - }; - - IContext& getCurrentContext(); - IMutableContext& getCurrentMutableContext(); - void cleanUpContext(); - Stream createStream( std::string const& streamName ); - -} - -// #included from: internal/catch_test_registry.hpp -#define TWOBLUECUBES_CATCH_TEST_REGISTRY_HPP_INCLUDED - -// #included from: catch_interfaces_testcase.h -#define TWOBLUECUBES_CATCH_INTERFACES_TESTCASE_H_INCLUDED +// start catch_interfaces_testcase.h #include +#include namespace Catch { class TestSpec; - struct ITestCase : IShared { + struct ITestInvoker { virtual void invoke () const = 0; - protected: - virtual ~ITestCase(); + virtual ~ITestInvoker(); }; + using ITestCasePtr = std::shared_ptr; + class TestCase; struct IConfig; @@ -699,814 +311,180 @@ namespace Catch { } +// end catch_interfaces_testcase.h +// start catch_stringref.h + +#include +#include +#include + +namespace Catch { + + class StringData; + + /// A non-owning string class (similar to the forthcoming std::string_view) + /// Note that, because a StringRef may be a substring of another string, + /// it may not be null terminated. c_str() must return a null terminated + /// string, however, and so the StringRef will internally take ownership + /// (taking a copy), if necessary. In theory this ownership is not externally + /// visible - but it does mean (substring) StringRefs should not be shared between + /// threads. + class StringRef { + friend struct StringRefTestAccess; + + using size_type = std::size_t; + + char const* m_start; + size_type m_size; + + char* m_data = nullptr; + + void takeOwnership(); + + public: // construction/ assignment + StringRef() noexcept; + StringRef( StringRef const& other ) noexcept; + StringRef( StringRef&& other ) noexcept; + StringRef( char const* rawChars ) noexcept; + StringRef( char const* rawChars, size_type size ) noexcept; + StringRef( std::string const& stdString ) noexcept; + ~StringRef() noexcept; + + auto operator = ( StringRef other ) noexcept -> StringRef&; + operator std::string() const; + + void swap( StringRef& other ) noexcept; + + public: // operators + auto operator == ( StringRef const& other ) const noexcept -> bool; + auto operator != ( StringRef const& other ) const noexcept -> bool; + + auto operator[] ( size_type index ) const noexcept -> char; + + public: // named queries + auto empty() const noexcept -> bool; + auto size() const noexcept -> size_type; + auto numberOfCharacters() const noexcept -> size_type; + auto c_str() const -> char const*; + + public: // substrings and searches + auto substr( size_type start, size_type size ) const noexcept -> StringRef; + + private: // ownership queries - may not be consistent between calls + auto isOwned() const noexcept -> bool; + auto isSubstring() const noexcept -> bool; + auto data() const noexcept -> char const*; + }; + + auto operator + ( StringRef const& lhs, StringRef const& rhs ) -> std::string; + auto operator + ( StringRef const& lhs, char const* rhs ) -> std::string; + auto operator + ( char const* lhs, StringRef const& rhs ) -> std::string; + + auto operator << ( std::ostream& os, StringRef const& sr ) -> std::ostream&; + +} // namespace Catch + +// end catch_stringref.h namespace Catch { template -class MethodTestCase : public SharedImpl { - +class TestInvokerAsMethod : public ITestInvoker { + void (C::*m_testAsMethod)(); public: - MethodTestCase( void (C::*method)() ) : m_method( method ) {} + TestInvokerAsMethod( void (C::*testAsMethod)() ) noexcept : m_testAsMethod( testAsMethod ) {} - virtual void invoke() const { + void invoke() const override { C obj; - (obj.*m_method)(); + (obj.*m_testAsMethod)(); } - -private: - virtual ~MethodTestCase() {} - - void (C::*m_method)(); }; -typedef void(*TestFunction)(); +auto makeTestInvoker( void(*testAsFunction)() ) noexcept -> ITestInvoker*; -struct NameAndDesc { - NameAndDesc( const char* _name = "", const char* _description= "" ) - : name( _name ), description( _description ) - {} +template +auto makeTestInvoker( void (C::*testAsMethod)() ) noexcept -> ITestInvoker* { + return new(std::nothrow) TestInvokerAsMethod( testAsMethod ); +} - const char* name; - const char* description; +struct NameAndTags { + NameAndTags( StringRef name_ = "", StringRef tags_ = "" ) noexcept; + StringRef name; + StringRef tags; }; -void registerTestCase - ( ITestCase* testCase, - char const* className, - NameAndDesc const& nameAndDesc, - SourceLineInfo const& lineInfo ); - -struct AutoReg { - - AutoReg - ( TestFunction function, - SourceLineInfo const& lineInfo, - NameAndDesc const& nameAndDesc ); - - template - AutoReg - ( void (C::*method)(), - char const* className, - NameAndDesc const& nameAndDesc, - SourceLineInfo const& lineInfo ) { - - registerTestCase - ( new MethodTestCase( method ), - className, - nameAndDesc, - lineInfo ); - } - +struct AutoReg : NonCopyable { + AutoReg( ITestInvoker* invoker, SourceLineInfo const& lineInfo, StringRef classOrMethod, NameAndTags const& nameAndTags ) noexcept; ~AutoReg(); - -private: - AutoReg( AutoReg const& ); - void operator= ( AutoReg const& ); }; -void registerTestCaseFunction - ( TestFunction function, - SourceLineInfo const& lineInfo, - NameAndDesc const& nameAndDesc ); - } // end namespace Catch -#ifdef CATCH_CONFIG_VARIADIC_MACROS +#if defined(CATCH_CONFIG_DISABLE) + #define INTERNAL_CATCH_TESTCASE_NO_REGISTRATION( TestName, ... ) \ + static void TestName() + #define INTERNAL_CATCH_TESTCASE_METHOD_NO_REGISTRATION( TestName, ClassName, ... ) \ + namespace{ \ + struct TestName : ClassName { \ + void test(); \ + }; \ + } \ + void TestName::test() + +#endif + /////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CATCH_TESTCASE2( TestName, ... ) \ static void TestName(); \ - CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS \ - namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &TestName, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( __VA_ARGS__ ) ); } /* NOLINT */ \ - CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS \ + CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ + namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( Catch::makeTestInvoker( &TestName ), CATCH_INTERNAL_LINEINFO, "", Catch::NameAndTags{ __VA_ARGS__ } ); } /* NOLINT */ \ + CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS \ static void TestName() #define INTERNAL_CATCH_TESTCASE( ... ) \ INTERNAL_CATCH_TESTCASE2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), __VA_ARGS__ ) /////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, ... ) \ - CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS \ - namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &QualifiedMethod, "&" #QualifiedMethod, Catch::NameAndDesc( __VA_ARGS__ ), CATCH_INTERNAL_LINEINFO ); } /* NOLINT */ \ - CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS + CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ + namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( Catch::makeTestInvoker( &QualifiedMethod ), CATCH_INTERNAL_LINEINFO, "&" #QualifiedMethod, Catch::NameAndTags{ __VA_ARGS__ } ); } /* NOLINT */ \ + CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS /////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CATCH_TEST_CASE_METHOD2( TestName, ClassName, ... )\ - CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS \ + CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ namespace{ \ struct TestName : ClassName{ \ void test(); \ }; \ - Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( &TestName::test, #ClassName, Catch::NameAndDesc( __VA_ARGS__ ), CATCH_INTERNAL_LINEINFO ); /* NOLINT */ \ + Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( Catch::makeTestInvoker( &TestName::test ), CATCH_INTERNAL_LINEINFO, #ClassName, Catch::NameAndTags{ __VA_ARGS__ } ); /* NOLINT */ \ } \ - CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS \ + CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS \ void TestName::test() #define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, ... ) \ INTERNAL_CATCH_TEST_CASE_METHOD2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), ClassName, __VA_ARGS__ ) /////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CATCH_REGISTER_TESTCASE( Function, ... ) \ - CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS \ - Catch::AutoReg( Function, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( __VA_ARGS__ ) ); /* NOLINT */ \ - CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS + CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ + Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( Catch::makeTestInvoker( Function ), CATCH_INTERNAL_LINEINFO, "", Catch::NameAndTags{ __VA_ARGS__ } ); /* NOLINT */ \ + CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS -#else - /////////////////////////////////////////////////////////////////////////////// - #define INTERNAL_CATCH_TESTCASE2( TestName, Name, Desc ) \ - static void TestName(); \ - CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS \ - namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &TestName, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( Name, Desc ) ); } /* NOLINT */ \ - CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS \ - static void TestName() - #define INTERNAL_CATCH_TESTCASE( Name, Desc ) \ - INTERNAL_CATCH_TESTCASE2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), Name, Desc ) +// end catch_test_registry.h +// start catch_capture.hpp - /////////////////////////////////////////////////////////////////////////////// - #define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, Name, Desc ) \ - CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS \ - namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &QualifiedMethod, "&" #QualifiedMethod, Catch::NameAndDesc( Name, Desc ), CATCH_INTERNAL_LINEINFO ); } /* NOLINT */ \ - CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS +// start catch_assertionhandler.h - /////////////////////////////////////////////////////////////////////////////// - #define INTERNAL_CATCH_TEST_CASE_METHOD2( TestCaseName, ClassName, TestName, Desc )\ - CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS \ - namespace{ \ - struct TestCaseName : ClassName{ \ - void test(); \ - }; \ - Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( &TestCaseName::test, #ClassName, Catch::NameAndDesc( TestName, Desc ), CATCH_INTERNAL_LINEINFO ); /* NOLINT */ \ - } \ - CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS \ - void TestCaseName::test() - #define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, TestName, Desc )\ - INTERNAL_CATCH_TEST_CASE_METHOD2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), ClassName, TestName, Desc ) +// start catch_decomposer.h - /////////////////////////////////////////////////////////////////////////////// - #define INTERNAL_CATCH_REGISTER_TESTCASE( Function, Name, Desc ) \ - CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS \ - Catch::AutoReg( Function, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( Name, Desc ) ); /* NOLINT */ \ - CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS - -#endif - -// #included from: internal/catch_capture.hpp -#define TWOBLUECUBES_CATCH_CAPTURE_HPP_INCLUDED - -// #included from: catch_result_builder.h -#define TWOBLUECUBES_CATCH_RESULT_BUILDER_H_INCLUDED - -// #included from: catch_result_type.h -#define TWOBLUECUBES_CATCH_RESULT_TYPE_H_INCLUDED - -namespace Catch { - - // ResultWas::OfType enum - struct ResultWas { enum OfType { - Unknown = -1, - Ok = 0, - Info = 1, - Warning = 2, - - FailureBit = 0x10, - - ExpressionFailed = FailureBit | 1, - ExplicitFailure = FailureBit | 2, - - Exception = 0x100 | FailureBit, - - ThrewException = Exception | 1, - DidntThrowException = Exception | 2, - - FatalErrorCondition = 0x200 | FailureBit - - }; }; - - inline bool isOk( ResultWas::OfType resultType ) { - return ( resultType & ResultWas::FailureBit ) == 0; - } - inline bool isJustInfo( int flags ) { - return flags == ResultWas::Info; - } - - // ResultDisposition::Flags enum - struct ResultDisposition { enum Flags { - Normal = 0x01, - - ContinueOnFailure = 0x02, // Failures fail test, but execution continues - FalseTest = 0x04, // Prefix expression with ! - SuppressFail = 0x08 // Failures are reported but do not fail the test - }; }; - - inline ResultDisposition::Flags operator | ( ResultDisposition::Flags lhs, ResultDisposition::Flags rhs ) { - return static_cast( 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; } - -} // end namespace Catch - -// #included from: catch_assertionresult.h -#define TWOBLUECUBES_CATCH_ASSERTIONRESULT_H_INCLUDED - -#include - -namespace Catch { - - struct STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison; - - struct DecomposedExpression - { - virtual ~DecomposedExpression() {} - virtual bool isBinaryExpression() const { - return false; - } - virtual void reconstructExpression( std::string& dest ) const = 0; - - // Only simple binary comparisons can be decomposed. - // If more complex check is required then wrap sub-expressions in parentheses. - template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator + ( T const& ); - template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator - ( T const& ); - template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator * ( T const& ); - template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator / ( T const& ); - template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator % ( T const& ); - template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator && ( T const& ); - template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator || ( T const& ); - - private: - DecomposedExpression& operator = (DecomposedExpression const&); - }; - - struct AssertionInfo - { - AssertionInfo(); - AssertionInfo( char const * _macroName, - SourceLineInfo const& _lineInfo, - char const * _capturedExpression, - ResultDisposition::Flags _resultDisposition, - char const * _secondArg = ""); - - char const * macroName; - SourceLineInfo lineInfo; - char const * capturedExpression; - ResultDisposition::Flags resultDisposition; - char const * secondArg; - }; - - struct AssertionResultData - { - AssertionResultData() : decomposedExpression( CATCH_NULL ) - , resultType( ResultWas::Unknown ) - , negated( false ) - , parenthesized( false ) {} - - void negate( bool parenthesize ) { - negated = !negated; - parenthesized = parenthesize; - if( resultType == ResultWas::Ok ) - resultType = ResultWas::ExpressionFailed; - else if( resultType == ResultWas::ExpressionFailed ) - resultType = ResultWas::Ok; - } - - std::string const& reconstructExpression() const { - if( decomposedExpression != CATCH_NULL ) { - decomposedExpression->reconstructExpression( reconstructedExpression ); - if( parenthesized ) { - reconstructedExpression.insert( 0, 1, '(' ); - reconstructedExpression.append( 1, ')' ); - } - if( negated ) { - reconstructedExpression.insert( 0, 1, '!' ); - } - decomposedExpression = CATCH_NULL; - } - return reconstructedExpression; - } - - mutable DecomposedExpression const* decomposedExpression; - mutable std::string reconstructedExpression; - std::string message; - ResultWas::OfType resultType; - bool negated; - bool parenthesized; - }; - - class AssertionResult { - public: - AssertionResult(); - AssertionResult( AssertionInfo const& info, AssertionResultData const& data ); - ~AssertionResult(); -# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS - AssertionResult( AssertionResult const& ) = default; - AssertionResult( AssertionResult && ) = default; - AssertionResult& operator = ( AssertionResult const& ) = default; - AssertionResult& operator = ( AssertionResult && ) = default; -# endif - - bool isOk() const; - bool succeeded() const; - ResultWas::OfType getResultType() const; - bool hasExpression() const; - bool hasMessage() const; - std::string getExpression() const; - std::string getExpressionInMacro() const; - bool hasExpandedExpression() const; - std::string getExpandedExpression() const; - std::string getMessage() const; - SourceLineInfo getSourceInfo() const; - std::string getTestMacroName() const; - void discardDecomposedExpression() const; - void expandDecomposedExpression() const; - - protected: - AssertionInfo m_info; - AssertionResultData m_resultData; - }; - -} // end namespace Catch - -// #included from: catch_matchers.hpp -#define TWOBLUECUBES_CATCH_MATCHERS_HPP_INCLUDED - -namespace Catch { -namespace Matchers { - namespace Impl { - - template struct MatchAllOf; - template struct MatchAnyOf; - template struct MatchNotOf; - - class MatcherUntypedBase { - public: - std::string toString() const { - if( m_cachedToString.empty() ) - m_cachedToString = describe(); - return m_cachedToString; - } - - protected: - virtual ~MatcherUntypedBase(); - virtual std::string describe() const = 0; - mutable std::string m_cachedToString; - private: - MatcherUntypedBase& operator = ( MatcherUntypedBase const& ); - }; - - template - struct MatcherMethod { - virtual bool match( ObjectT const& arg ) const = 0; - }; - template - struct MatcherMethod { - virtual bool match( PtrT* arg ) const = 0; - }; - - template - struct MatcherBase : MatcherUntypedBase, MatcherMethod { - - MatchAllOf operator && ( MatcherBase const& other ) const; - MatchAnyOf operator || ( MatcherBase const& other ) const; - MatchNotOf operator ! () const; - }; - - template - struct MatchAllOf : MatcherBase { - virtual bool match( ArgT const& arg ) const CATCH_OVERRIDE { - for( std::size_t i = 0; i < m_matchers.size(); ++i ) { - if (!m_matchers[i]->match(arg)) - return false; - } - return true; - } - virtual std::string describe() const CATCH_OVERRIDE { - std::string description; - description.reserve( 4 + m_matchers.size()*32 ); - description += "( "; - for( std::size_t i = 0; i < m_matchers.size(); ++i ) { - if( i != 0 ) - description += " and "; - description += m_matchers[i]->toString(); - } - description += " )"; - return description; - } - - MatchAllOf& operator && ( MatcherBase const& other ) { - m_matchers.push_back( &other ); - return *this; - } - - std::vector const*> m_matchers; - }; - template - struct MatchAnyOf : MatcherBase { - - virtual bool match( ArgT const& arg ) const CATCH_OVERRIDE { - for( std::size_t i = 0; i < m_matchers.size(); ++i ) { - if (m_matchers[i]->match(arg)) - return true; - } - return false; - } - virtual std::string describe() const CATCH_OVERRIDE { - std::string description; - description.reserve( 4 + m_matchers.size()*32 ); - description += "( "; - for( std::size_t i = 0; i < m_matchers.size(); ++i ) { - if( i != 0 ) - description += " or "; - description += m_matchers[i]->toString(); - } - description += " )"; - return description; - } - - MatchAnyOf& operator || ( MatcherBase const& other ) { - m_matchers.push_back( &other ); - return *this; - } - - std::vector const*> m_matchers; - }; - - template - struct MatchNotOf : MatcherBase { - - MatchNotOf( MatcherBase const& underlyingMatcher ) : m_underlyingMatcher( underlyingMatcher ) {} - - virtual bool match( ArgT const& arg ) const CATCH_OVERRIDE { - return !m_underlyingMatcher.match( arg ); - } - - virtual std::string describe() const CATCH_OVERRIDE { - return "not " + m_underlyingMatcher.toString(); - } - MatcherBase const& m_underlyingMatcher; - }; - - template - MatchAllOf MatcherBase::operator && ( MatcherBase const& other ) const { - return MatchAllOf() && *this && other; - } - template - MatchAnyOf MatcherBase::operator || ( MatcherBase const& other ) const { - return MatchAnyOf() || *this || other; - } - template - MatchNotOf MatcherBase::operator ! () const { - return MatchNotOf( *this ); - } - - } // namespace Impl - - // The following functions create the actual matcher objects. - // This allows the types to be inferred - // - deprecated: prefer ||, && and ! - template - Impl::MatchNotOf Not( Impl::MatcherBase const& underlyingMatcher ) { - return Impl::MatchNotOf( underlyingMatcher ); - } - template - Impl::MatchAllOf AllOf( Impl::MatcherBase const& m1, Impl::MatcherBase const& m2 ) { - return Impl::MatchAllOf() && m1 && m2; - } - template - Impl::MatchAllOf AllOf( Impl::MatcherBase const& m1, Impl::MatcherBase const& m2, Impl::MatcherBase const& m3 ) { - return Impl::MatchAllOf() && m1 && m2 && m3; - } - template - Impl::MatchAnyOf AnyOf( Impl::MatcherBase const& m1, Impl::MatcherBase const& m2 ) { - return Impl::MatchAnyOf() || m1 || m2; - } - template - Impl::MatchAnyOf AnyOf( Impl::MatcherBase const& m1, Impl::MatcherBase const& m2, Impl::MatcherBase const& m3 ) { - return Impl::MatchAnyOf() || m1 || m2 || m3; - } - -} // namespace Matchers - -using namespace Matchers; -using Matchers::Impl::MatcherBase; - -} // namespace Catch - -namespace Catch { - - struct TestFailureException{}; - - template class ExpressionLhs; - - struct CopyableStream { - CopyableStream() {} - CopyableStream( CopyableStream const& other ) { - oss << other.oss.str(); - } - CopyableStream& operator=( CopyableStream const& other ) { - oss.str(std::string()); - oss << other.oss.str(); - return *this; - } - std::ostringstream oss; - }; - - class ResultBuilder : public DecomposedExpression { - public: - ResultBuilder( char const* macroName, - SourceLineInfo const& lineInfo, - char const* capturedExpression, - ResultDisposition::Flags resultDisposition, - char const* secondArg = "" ); - ~ResultBuilder(); - - template - ExpressionLhs operator <= ( T const& operand ); - ExpressionLhs operator <= ( bool value ); - - template - ResultBuilder& operator << ( T const& value ) { - stream().oss << value; - return *this; - } - - ResultBuilder& setResultType( ResultWas::OfType result ); - ResultBuilder& setResultType( bool result ); - - void endExpression( DecomposedExpression const& expr ); - - virtual void reconstructExpression( std::string& dest ) const CATCH_OVERRIDE; - - AssertionResult build() const; - AssertionResult build( DecomposedExpression const& expr ) const; - - void useActiveException( ResultDisposition::Flags resultDisposition = ResultDisposition::Normal ); - void captureResult( ResultWas::OfType resultType ); - void captureExpression(); - void captureExpectedException( std::string const& expectedMessage ); - void captureExpectedException( Matchers::Impl::MatcherBase const& matcher ); - void handleResult( AssertionResult const& result ); - void react(); - bool shouldDebugBreak() const; - bool allowThrows() const; - - template - void captureMatch( ArgT const& arg, MatcherT const& matcher, char const* matcherString ); - - void setExceptionGuard(); - void unsetExceptionGuard(); - - private: - AssertionInfo m_assertionInfo; - AssertionResultData m_data; - - CopyableStream &stream() - { - if(!m_usedStream) - { - m_usedStream = true; - m_stream().oss.str(""); - } - return m_stream(); - } - - static CopyableStream &m_stream() - { - static CopyableStream s; - return s; - } - - bool m_shouldDebugBreak; - bool m_shouldThrow; - bool m_guardException; - bool m_usedStream; - }; - -} // namespace Catch - -// Include after due to circular dependency: -// #included from: catch_expression_lhs.hpp -#define TWOBLUECUBES_CATCH_EXPRESSION_LHS_HPP_INCLUDED - -// #included from: catch_evaluate.hpp -#define TWOBLUECUBES_CATCH_EVALUATE_HPP_INCLUDED - -#ifdef _MSC_VER -#pragma warning(push) -#pragma warning(disable:4389) // '==' : signed/unsigned mismatch -#pragma warning(disable:4312) // Converting int to T* using reinterpret_cast (issue on x64 platform) -#endif - -#include - -namespace Catch { -namespace Internal { - - 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 - 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; } -#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 - struct Evaluator{}; - - template - struct Evaluator { - static bool evaluate( T1 const& lhs, T2 const& rhs) { - return bool( opCast( lhs ) == opCast( rhs ) ); - } - }; - template - struct Evaluator { - static bool evaluate( T1 const& lhs, T2 const& rhs ) { - return bool( opCast( lhs ) != opCast( rhs ) ); - } - }; - template - struct Evaluator { - static bool evaluate( T1 const& lhs, T2 const& rhs ) { - return bool( opCast( lhs ) < opCast( rhs ) ); - } - }; - template - struct Evaluator { - static bool evaluate( T1 const& lhs, T2 const& rhs ) { - return bool( opCast( lhs ) > opCast( rhs ) ); - } - }; - template - struct Evaluator { - static bool evaluate( T1 const& lhs, T2 const& rhs ) { - return bool( opCast( lhs ) >= opCast( rhs ) ); - } - }; - template - struct Evaluator { - static bool evaluate( T1 const& lhs, T2 const& rhs ) { - return bool( opCast( lhs ) <= opCast( rhs ) ); - } - }; - - template - bool applyEvaluator( T1 const& lhs, T2 const& rhs ) { - return Evaluator::evaluate( lhs, 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 ); - } - - // 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 ) ); - } - -#ifdef CATCH_CONFIG_CPP11_LONG_LONG - // long long to unsigned X - template bool compare( long long lhs, unsigned int rhs ) { - return applyEvaluator( static_cast( lhs ), rhs ); - } - template bool compare( long long lhs, unsigned long rhs ) { - return applyEvaluator( static_cast( lhs ), rhs ); - } - template bool compare( long long lhs, unsigned long long rhs ) { - return applyEvaluator( static_cast( lhs ), rhs ); - } - template bool compare( long long lhs, unsigned char rhs ) { - return applyEvaluator( static_cast( lhs ), rhs ); - } - - // unsigned long long to X - template bool compare( unsigned long long lhs, int rhs ) { - return applyEvaluator( static_cast( lhs ), rhs ); - } - template bool compare( unsigned long long lhs, long rhs ) { - return applyEvaluator( static_cast( lhs ), rhs ); - } - template bool compare( unsigned long long lhs, long long rhs ) { - return applyEvaluator( static_cast( lhs ), rhs ); - } - template bool compare( unsigned long long lhs, char rhs ) { - return applyEvaluator( static_cast( lhs ), rhs ); - } - - // pointer to long long (when comparing against NULL) - template bool compare( long long lhs, T* rhs ) { - return Evaluator::evaluate( reinterpret_cast( lhs ), rhs ); - } - template bool compare( T* lhs, long long rhs ) { - return Evaluator::evaluate( lhs, reinterpret_cast( rhs ) ); - } -#endif // CATCH_CONFIG_CPP11_LONG_LONG - -#ifdef CATCH_CONFIG_CPP11_NULLPTR - // pointer to nullptr_t (when comparing against nullptr) - template bool compare( std::nullptr_t, T* rhs ) { - return Evaluator::evaluate( nullptr, rhs ); - } - template bool compare( T* lhs, std::nullptr_t ) { - return Evaluator::evaluate( lhs, nullptr ); - } -#endif // CATCH_CONFIG_CPP11_NULLPTR - -} // end of namespace Internal -} // end of namespace Catch - -#ifdef _MSC_VER -#pragma warning(pop) -#endif - -// #included from: catch_tostring.h -#define TWOBLUECUBES_CATCH_TOSTRING_H_INCLUDED +// start catch_tostring.h #include -#include -#include #include #include +#include +#include #ifdef __OBJC__ -// #included from: catch_objc_arc.hpp -#define TWOBLUECUBES_CATCH_OBJC_ARC_HPP_INCLUDED +// start catch_objc_arc.hpp #import @@ -1548,451 +526,735 @@ inline id performOptionalSelector( id obj, SEL sel ) { #define CATCH_ARC_STRONG __strong #endif +// end catch_objc_arc.hpp #endif -#ifdef CATCH_CONFIG_CPP11_TUPLE -#include +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable:4180) // We attempt to stream a function (address) by const&, which MSVC complains about but is harmless #endif -#ifdef CATCH_CONFIG_CPP11_IS_ENUM -#include -#endif +// We need a dummy global operator<< so we can bring it into Catch namespace later +struct Catch_global_namespace_dummy; +std::ostream& operator<<(std::ostream&, Catch_global_namespace_dummy); namespace Catch { + // Bring in operator<< from global namespace into Catch namespace + using ::operator<<; -// Why we're here. -template -std::string toString( T const& value ); + namespace Detail { -// Built in overloads + extern const std::string unprintableString; -std::string toString( std::string const& value ); -std::string toString( std::wstring const& value ); -std::string toString( const char* const value ); -std::string toString( char* const value ); -std::string toString( const wchar_t* const value ); -std::string toString( wchar_t* const value ); -std::string toString( int value ); -std::string toString( unsigned long value ); -std::string toString( unsigned int value ); -std::string toString( const double value ); -std::string toString( const float value ); -std::string toString( bool value ); -std::string toString( char value ); -std::string toString( signed char value ); -std::string toString( unsigned char value ); + std::string rawMemoryToString( const void *object, std::size_t size ); -#ifdef CATCH_CONFIG_CPP11_LONG_LONG -std::string toString( long long value ); -std::string toString( unsigned long long value ); -#endif + template + std::string rawMemoryToString( const T& object ) { + return rawMemoryToString( &object, sizeof(object) ); + } -#ifdef CATCH_CONFIG_CPP11_NULLPTR -std::string toString( std::nullptr_t ); -#endif + template + class IsStreamInsertable { + template + static auto test(int) + -> decltype(std::declval() << std::declval(), std::true_type()); -#ifdef __OBJC__ - std::string toString( NSString const * const& nsstring ); - std::string toString( NSString * CATCH_ARC_STRONG & nsstring ); - std::string toString( NSObject* const& nsObject ); -#endif + template + static auto test(...)->std::false_type; -namespace Detail { + public: + static const bool value = decltype(test(0))::value; + }; - extern const std::string unprintableString; + } // namespace Detail - #if !defined(CATCH_CONFIG_CPP11_STREAM_INSERTABLE_CHECK) - struct BorgType { - template BorgType( T const& ); - }; + // If we decide for C++14, change these to enable_if_ts + template + struct StringMaker { + template + static + typename std::enable_if<::Catch::Detail::IsStreamInsertable::value, std::string>::type + convert(const Fake& t) { + std::ostringstream sstr; + sstr << t; + return sstr.str(); + } - struct TrueType { char sizer[1]; }; - struct FalseType { char sizer[2]; }; - - TrueType& testStreamable( std::ostream& ); - FalseType testStreamable( FalseType ); - - FalseType operator<<( std::ostream const&, BorgType const& ); - - template - struct IsStreamInsertable { - static std::ostream &s; - static T const&t; - enum { value = sizeof( testStreamable(s << t) ) == sizeof( TrueType ) }; - }; -#else - template - class IsStreamInsertable { - template - static auto test(int) - -> decltype( std::declval() << std::declval(), std::true_type() ); - - template - static auto test(...) -> std::false_type; - - public: - static const bool value = decltype(test(0))::value; - }; -#endif - -#if defined(CATCH_CONFIG_CPP11_IS_ENUM) - template::value - > - struct EnumStringMaker - { - static std::string convert( T const& ) { return unprintableString; } - }; - - template - struct EnumStringMaker - { - static std::string convert( T const& v ) - { - return ::Catch::toString( - static_cast::type>(v) - ); + template + static + typename std::enable_if::value, std::string>::type + convert(const Fake&) { + return Detail::unprintableString; } }; -#endif - template - struct StringMakerBase { -#if defined(CATCH_CONFIG_CPP11_IS_ENUM) - template - static std::string convert( T const& v ) - { - return EnumStringMaker::convert( v ); + + namespace Detail { + + // This function dispatches all stringification requests inside of Catch. + // Should be preferably called fully qualified, like ::Catch::Detail::stringify + template + std::string stringify(const T& e) { + return ::Catch::StringMaker::type>::type>::convert(e); } -#else - template - static std::string convert( T const& ) { return unprintableString; } -#endif + + } // namespace Detail + + // Some predefined specializations + + template<> + struct StringMaker { + static std::string convert(const std::string& str); + }; + template<> + struct StringMaker { + static std::string convert(const std::wstring& wstr); }; template<> - struct StringMakerBase { - template - static std::string convert( T const& _value ) { + struct StringMaker { + static std::string convert(char const * str); + }; + template<> + struct StringMaker { + static std::string convert(char * str); + }; + template<> + struct StringMaker { + static std::string convert(wchar_t const * str); + }; + template<> + struct StringMaker { + static std::string convert(wchar_t * str); + }; + + template + struct StringMaker { + static std::string convert(const char* str) { + return ::Catch::Detail::stringify(std::string{ str }); + } + }; + template + struct StringMaker { + static std::string convert(const char* str) { + return ::Catch::Detail::stringify(std::string{ str }); + } + }; + template + struct StringMaker { + static std::string convert(const char* str) { + return ::Catch::Detail::stringify(std::string{ str }); + } + }; + + template<> + struct StringMaker { + static std::string convert(int value); + }; + template<> + struct StringMaker { + static std::string convert(long value); + }; + template<> + struct StringMaker { + static std::string convert(long long value); + }; + template<> + struct StringMaker { + static std::string convert(unsigned int value); + }; + template<> + struct StringMaker { + static std::string convert(unsigned long value); + }; + template<> + struct StringMaker { + static std::string convert(unsigned long long value); + }; + + template<> + struct StringMaker { + static std::string convert(bool b); + }; + + template<> + struct StringMaker { + static std::string convert(char c); + }; + template<> + struct StringMaker { + static std::string convert(signed char c); + }; + template<> + struct StringMaker { + static std::string convert(unsigned char c); + }; + + template<> + struct StringMaker { + static std::string convert(std::nullptr_t); + }; + + template<> + struct StringMaker { + static std::string convert(float value); + }; + template<> + struct StringMaker { + static std::string convert(double value); + }; + + template + struct StringMaker { + template + static std::string convert(U* p) { + if (p) { + return ::Catch::Detail::rawMemoryToString(p); + } else { + return "nullptr"; + } + } + }; + + template + struct StringMaker { + static std::string convert(R C::* p) { + if (p) { + return ::Catch::Detail::rawMemoryToString(p); + } else { + return "nullptr"; + } + } + }; + + namespace Detail { + template + std::string rangeToString(InputIterator first, InputIterator last) { std::ostringstream oss; - oss << _value; + oss << "{ "; + if (first != last) { + oss << ::Catch::Detail::stringify(*first); + for (++first; first != last; ++first) + oss << ", " << ::Catch::Detail::stringify(*first); + } + oss << " }"; + return oss.str(); + } + } + + template + struct StringMaker > { + static std::string convert( std::vector const& v ) { + return ::Catch::Detail::rangeToString( v.begin(), v.end() ); + } + }; + + template + struct EnumStringMaker { + static std::string convert(const T& t) { + return ::Catch::Detail::stringify(static_cast::type>(t)); + } + }; + +#ifdef __OBJC__ + template<> + struct StringMaker { + static std::string convert(NSString * nsstring) { + if (!nsstring) + return "nil"; + return std::string("@") + [nsstring UTF8String]; + } + }; + template<> + struct StringMaker { + static std::string convert(NSObject* nsObject) { + return ::Catch::Detail::stringify([nsObject description]); + } + + }; + namespace Detail { + inline std::string stringify( NSString* nsstring ) { + return StringMaker::convert( nsstring ); + } + + } // namespace Detail +#endif // __OBJC__ + +} // namespace Catch + +////////////////////////////////////////////////////// +// Separate std-lib types stringification, so it can be selectively enabled +// This means that we do not bring in + +#if defined(CATCH_CONFIG_ENABLE_ALL_STRINGMAKERS) +# define CATCH_CONFIG_ENABLE_PAIR_STRINGMAKER +# define CATCH_CONFIG_ENABLE_TUPLE_STRINGMAKER +# define CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER +#endif + +// Separate std::pair specialization +#if defined(CATCH_CONFIG_ENABLE_PAIR_STRINGMAKER) +#include +namespace Catch { + template + struct StringMaker > { + static std::string convert(const std::pair& pair) { + std::ostringstream oss; + oss << "{ " + << ::Catch::Detail::stringify(pair.first) + << ", " + << ::Catch::Detail::stringify(pair.second) + << " }"; + return oss.str(); + } + }; +} +#endif // CATCH_CONFIG_ENABLE_PAIR_STRINGMAKER + +// Separate std::tuple specialization +#if defined(CATCH_CONFIG_ENABLE_TUPLE_STRINGMAKER) +#include +namespace Catch { + namespace Detail { + template< + typename Tuple, + std::size_t N = 0, + bool = (N < std::tuple_size::value) + > + struct TupleElementPrinter { + static void print(const Tuple& tuple, std::ostream& os) { + os << (N ? ", " : " ") + << ::Catch::Detail::stringify(std::get(tuple)); + TupleElementPrinter::print(tuple, os); + } + }; + + template< + typename Tuple, + std::size_t N + > + struct TupleElementPrinter { + static void print(const Tuple&, std::ostream&) {} + }; + + } + + template + struct StringMaker> { + static std::string convert(const std::tuple& tuple) { + std::ostringstream os; + os << '{'; + Detail::TupleElementPrinter>::print(tuple, os); + os << " }"; + return os.str(); + } + }; +} +#endif // CATCH_CONFIG_ENABLE_TUPLE_STRINGMAKER + +// Separate std::chrono::duration specialization +#if defined(CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER) +#include +#include +#include + +template +struct ratio_string { + static std::string symbol(); +}; + +template +std::string ratio_string::symbol() { + std::ostringstream oss; + oss << '[' << Ratio::num << '/' + << Ratio::den << ']'; + return oss.str(); +} +template <> +struct ratio_string { + static std::string symbol() { return "a"; } +}; +template <> +struct ratio_string { + static std::string symbol() { return "f"; } +}; +template <> +struct ratio_string { + static std::string symbol() { return "p"; } +}; +template <> +struct ratio_string { + static std::string symbol() { return "n"; } +}; +template <> +struct ratio_string { + static std::string symbol() { return "u"; } +}; +template <> +struct ratio_string { + static std::string symbol() { return "m"; } +}; + +namespace Catch { + //////////// + // std::chrono::duration specializations + template + struct StringMaker> { + static std::string convert(std::chrono::duration const& duration) { + std::ostringstream oss; + oss << duration.count() << ' ' << ratio_string::symbol() << 's'; + return oss.str(); + } + }; + template + struct StringMaker>> { + static std::string convert(std::chrono::duration> const& duration) { + std::ostringstream oss; + oss << duration.count() << " s"; + return oss.str(); + } + }; + template + struct StringMaker>> { + static std::string convert(std::chrono::duration> const& duration) { + std::ostringstream oss; + oss << duration.count() << " m"; + return oss.str(); + } + }; + template + struct StringMaker>> { + static std::string convert(std::chrono::duration> const& duration) { + std::ostringstream oss; + oss << duration.count() << " h"; return oss.str(); } }; - std::string rawMemoryToString( const void *object, std::size_t size ); - - template - std::string rawMemoryToString( const T& object ) { - return rawMemoryToString( &object, sizeof(object) ); - } - -} // end namespace Detail - -template -struct StringMaker : - Detail::StringMakerBase::value> {}; - -template -struct StringMaker { - template - static std::string convert( U* p ) { - if( !p ) - return "NULL"; - else - return Detail::rawMemoryToString( p ); - } -}; - -template -struct StringMaker { - static std::string convert( R C::* p ) { - if( !p ) - return "NULL"; - else - return Detail::rawMemoryToString( p ); - } -}; - -namespace Detail { - template - std::string rangeToString( InputIterator first, InputIterator last ); -} - -//template -//struct StringMaker > { -// static std::string convert( std::vector const& v ) { -// return Detail::rangeToString( v.begin(), v.end() ); -// } -//}; - -template -std::string toString( std::vector const& v ) { - return Detail::rangeToString( v.begin(), v.end() ); -} - -#ifdef CATCH_CONFIG_CPP11_TUPLE - -// toString for tuples -namespace TupleDetail { - template< - typename Tuple, - std::size_t N = 0, - bool = (N < std::tuple_size::value) - > - struct ElementPrinter { - static void print( const Tuple& tuple, std::ostream& os ) - { - os << ( N ? ", " : " " ) - << Catch::toString(std::get(tuple)); - ElementPrinter::print(tuple,os); - } - }; - - template< - typename Tuple, - std::size_t N - > - struct ElementPrinter { - static void print( const Tuple&, std::ostream& ) {} - }; - -} - -template -struct StringMaker> { - - static std::string convert( const std::tuple& tuple ) - { - std::ostringstream os; - os << '{'; - TupleDetail::ElementPrinter>::print( tuple, os ); - os << " }"; - return os.str(); - } -}; -#endif // CATCH_CONFIG_CPP11_TUPLE - -namespace Detail { - template - std::string makeString( T const& value ) { - return StringMaker::convert( value ); - } -} // end namespace Detail - -/// \brief converts any type to a string -/// -/// The default template forwards on to ostringstream - except when an -/// ostringstream overload does not exist - in which case it attempts to detect -/// that and writes {?}. -/// Overload (not specialise) this template for custom typs that you don't want -/// to provide an ostream overload for. -template -std::string toString( T const& value ) { - return StringMaker::convert( value ); -} - - namespace Detail { - template - std::string rangeToString( InputIterator first, InputIterator last ) { - std::ostringstream oss; - oss << "{ "; - if( first != last ) { - oss << Catch::toString( *first ); - for( ++first ; first != last ; ++first ) - oss << ", " << Catch::toString( *first ); + //////////// + // std::chrono::time_point specialization + // Generic time_point cannot be specialized, only std::chrono::time_point + template + struct StringMaker> { + static std::string convert(std::chrono::time_point const& time_point) { + return ::Catch::Detail::stringify(time_point.time_since_epoch()) + " since epoch"; } - oss << " }"; - return oss.str(); - } + }; + // std::chrono::time_point specialization + template + struct StringMaker> { + static std::string convert(std::chrono::time_point const& time_point) { + auto converted = std::chrono::system_clock::to_time_t(time_point); + +#ifdef _MSC_VER + std::tm timeInfo = {}; + gmtime_s(&timeInfo, &converted); +#else + std::tm* timeInfo = std::gmtime(&converted); +#endif + + auto const timeStampSize = sizeof("2017-01-16T17:06:45Z"); + char timeStamp[timeStampSize]; + const char * const fmt = "%Y-%m-%dT%H:%M:%SZ"; + +#ifdef _MSC_VER + std::strftime(timeStamp, timeStampSize, fmt, &timeInfo); +#else + std::strftime(timeStamp, timeStampSize, fmt, timeInfo); +#endif + return std::string(timeStamp); + } + }; } +#endif // CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER -} // end namespace Catch +#ifdef _MSC_VER +#pragma warning(pop) +#endif + +// end catch_tostring.h +#include + +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable:4389) // '==' : signed/unsigned mismatch +#pragma warning(disable:4018) // more "signed/unsigned mismatch" +#pragma warning(disable:4312) // Converting int to T* using reinterpret_cast (issue on x64 platform) +#pragma warning(disable:4180) // qualifier applied to function type has no meaning +#endif namespace Catch { -template -class BinaryExpression; + struct ITransientExpression { + virtual auto isBinaryExpression() const -> bool = 0; + virtual auto getResult() const -> bool = 0; + virtual void streamReconstructedExpression( std::ostream &os ) const = 0; -template -class MatchExpression; + // We don't actually need a virtual destructore, but many static analysers + // complain if it's not here :-( + virtual ~ITransientExpression(); + }; -// Wraps the LHS of an expression and overloads comparison operators -// for also capturing those and RHS (if any) -template -class ExpressionLhs : public DecomposedExpression { -public: - ExpressionLhs( ResultBuilder& rb, T lhs ) : m_rb( rb ), m_lhs( lhs ), m_truthy(false) {} + void formatReconstructedExpression( std::ostream &os, std::string const& lhs, StringRef op, std::string const& rhs ); - ExpressionLhs& operator = ( const ExpressionLhs& ); + template + class BinaryExpr : public ITransientExpression { + bool m_result; + LhsT m_lhs; + StringRef m_op; + RhsT m_rhs; - template - BinaryExpression - operator == ( RhsT const& rhs ) { - return captureExpression( rhs ); - } + auto isBinaryExpression() const -> bool override { return true; } + auto getResult() const -> bool override { return m_result; } - template - BinaryExpression - operator != ( RhsT const& rhs ) { - return captureExpression( rhs ); - } + void streamReconstructedExpression( std::ostream &os ) const override { + formatReconstructedExpression + ( os, Catch::Detail::stringify( m_lhs ), m_op, Catch::Detail::stringify( m_rhs ) ); + } - template - BinaryExpression - operator < ( RhsT const& rhs ) { - return captureExpression( rhs ); - } + public: + BinaryExpr( bool comparisonResult, LhsT lhs, StringRef op, RhsT rhs ) + : m_result( comparisonResult ), + m_lhs( lhs ), + m_op( op ), + m_rhs( rhs ) + {} + }; - template - BinaryExpression - operator > ( RhsT const& rhs ) { - return captureExpression( rhs ); - } + template + class UnaryExpr : public ITransientExpression { + LhsT m_lhs; - template - BinaryExpression - operator <= ( RhsT const& rhs ) { - return captureExpression( rhs ); - } + auto isBinaryExpression() const -> bool override { return false; } + auto getResult() const -> bool override { return m_lhs ? true : false; } - template - BinaryExpression - operator >= ( RhsT const& rhs ) { - return captureExpression( rhs ); - } + void streamReconstructedExpression( std::ostream &os ) const override { + os << Catch::Detail::stringify( m_lhs ); + } - BinaryExpression operator == ( bool rhs ) { - return captureExpression( rhs ); - } + public: + UnaryExpr( LhsT lhs ) : m_lhs( lhs ) {} + }; - BinaryExpression operator != ( bool rhs ) { - return captureExpression( rhs ); - } + // Specialised comparison functions to handle equality comparisons between ints and pointers (NULL deduces as an int) + template + auto compareEqual( LhsT const& lhs, RhsT const& rhs ) -> bool { return lhs == rhs; }; + template + auto compareEqual( T* const& lhs, int rhs ) -> bool { return lhs == reinterpret_cast( rhs ); } + template + auto compareEqual( T* const& lhs, long rhs ) -> bool { return lhs == reinterpret_cast( rhs ); } + template + auto compareEqual( int lhs, T* const& rhs ) -> bool { return reinterpret_cast( lhs ) == rhs; } + template + auto compareEqual( long lhs, T* const& rhs ) -> bool { return reinterpret_cast( lhs ) == rhs; } - void endExpression() { - m_truthy = m_lhs ? true : false; - m_rb - .setResultType( m_truthy ) - .endExpression( *this ); - } + template + auto compareNotEqual( LhsT const& lhs, RhsT&& rhs ) -> bool { return lhs != rhs; }; + template + auto compareNotEqual( T* const& lhs, int rhs ) -> bool { return lhs != reinterpret_cast( rhs ); } + template + auto compareNotEqual( T* const& lhs, long rhs ) -> bool { return lhs != reinterpret_cast( rhs ); } + template + auto compareNotEqual( int lhs, T* const& rhs ) -> bool { return reinterpret_cast( lhs ) != rhs; } + template + auto compareNotEqual( long lhs, T* const& rhs ) -> bool { return reinterpret_cast( lhs ) != rhs; } - virtual void reconstructExpression( std::string& dest ) const CATCH_OVERRIDE { - dest = Catch::toString( m_lhs ); - } + template + class ExprLhs { + LhsT m_lhs; + public: + ExprLhs( LhsT lhs ) : m_lhs( lhs ) {} -private: - template - BinaryExpression captureExpression( RhsT& rhs ) const { - return BinaryExpression( m_rb, m_lhs, rhs ); - } + template + auto operator == ( RhsT const& rhs ) -> BinaryExpr const { + return BinaryExpr( compareEqual( m_lhs, rhs ), m_lhs, "==", rhs ); + } + auto operator == ( bool rhs ) -> BinaryExpr const { + return BinaryExpr( m_lhs == rhs, m_lhs, "==", rhs ); + } - template - BinaryExpression captureExpression( bool rhs ) const { - return BinaryExpression( m_rb, m_lhs, rhs ); - } + template + auto operator != ( RhsT const& rhs ) -> BinaryExpr const { + return BinaryExpr( compareNotEqual( m_lhs, rhs ), m_lhs, "!=", rhs ); + } + auto operator != ( bool rhs ) -> BinaryExpr const { + return BinaryExpr( m_lhs != rhs, m_lhs, "!=", rhs ); + } -private: - ResultBuilder& m_rb; - T m_lhs; - bool m_truthy; -}; + template + auto operator > ( RhsT const& rhs ) -> BinaryExpr const { + return BinaryExpr( m_lhs > rhs, m_lhs, ">", rhs ); + } + template + auto operator < ( RhsT const& rhs ) -> BinaryExpr const { + return BinaryExpr( m_lhs < rhs, m_lhs, "<", rhs ); + } + template + auto operator >= ( RhsT const& rhs ) -> BinaryExpr const { + return BinaryExpr( m_lhs >= rhs, m_lhs, ">=", rhs ); + } + template + auto operator <= ( RhsT const& rhs ) -> BinaryExpr const { + return BinaryExpr( m_lhs <= rhs, m_lhs, "<=", rhs ); + } -template -class BinaryExpression : public DecomposedExpression { -public: - BinaryExpression( ResultBuilder& rb, LhsT lhs, RhsT rhs ) - : m_rb( rb ), m_lhs( lhs ), m_rhs( rhs ) {} + auto makeUnaryExpr() const -> UnaryExpr { + return UnaryExpr( m_lhs ); + } + }; - BinaryExpression& operator = ( BinaryExpression& ); - - void endExpression() const { - m_rb - .setResultType( Internal::compare( m_lhs, m_rhs ) ) - .endExpression( *this ); - } - - virtual bool isBinaryExpression() const CATCH_OVERRIDE { - return true; - } - - virtual void reconstructExpression( std::string& dest ) const CATCH_OVERRIDE { - std::string lhs = Catch::toString( m_lhs ); - std::string rhs = Catch::toString( m_rhs ); - char delim = lhs.size() + rhs.size() < 40 && - lhs.find('\n') == std::string::npos && - rhs.find('\n') == std::string::npos ? ' ' : '\n'; - dest.reserve( 7 + lhs.size() + rhs.size() ); - // 2 for spaces around operator - // 2 for operator - // 2 for parentheses (conditionally added later) - // 1 for negation (conditionally added later) - dest = lhs; - dest += delim; - dest += Internal::OperatorTraits::getName(); - dest += delim; - dest += rhs; - } - -private: - ResultBuilder& m_rb; - LhsT m_lhs; - RhsT m_rhs; -}; - -template -class MatchExpression : public DecomposedExpression { -public: - MatchExpression( ArgT arg, MatcherT matcher, char const* matcherString ) - : m_arg( arg ), m_matcher( matcher ), m_matcherString( matcherString ) {} - - virtual bool isBinaryExpression() const CATCH_OVERRIDE { - return true; - } - - virtual void reconstructExpression( std::string& dest ) const CATCH_OVERRIDE { - std::string matcherAsString = m_matcher.toString(); - dest = Catch::toString( m_arg ); - dest += ' '; - if( matcherAsString == Detail::unprintableString ) - dest += m_matcherString; - else - dest += matcherAsString; - } - -private: - ArgT m_arg; - MatcherT m_matcher; - char const* m_matcherString; -}; - -} // end namespace Catch - - -namespace Catch { + void handleExpression( ITransientExpression const& expr ); template - ExpressionLhs ResultBuilder::operator <= ( T const& operand ) { - return ExpressionLhs( *this, operand ); + void handleExpression( ExprLhs const& expr ) { + handleExpression( expr.makeUnaryExpr() ); } - inline ExpressionLhs ResultBuilder::operator <= ( bool value ) { - return ExpressionLhs( *this, value ); - } + struct Decomposer { + template + auto operator <= ( T const& lhs ) -> ExprLhs { + return ExprLhs( lhs ); + } + auto operator <=( bool value ) -> ExprLhs { + return ExprLhs( value ); + } + }; - template - void ResultBuilder::captureMatch( ArgT const& arg, MatcherT const& matcher, - char const* matcherString ) { - MatchExpression expr( arg, matcher, matcherString ); - setResultType( matcher.match( arg ) ); - endExpression( expr ); - } +} // end namespace Catch + +#ifdef _MSC_VER +#pragma warning(pop) +#endif + +// end catch_decomposer.h +// start catch_assertioninfo.h + +// start catch_result_type.h + +namespace Catch { + + // ResultWas::OfType enum + struct ResultWas { enum OfType { + Unknown = -1, + Ok = 0, + Info = 1, + Warning = 2, + + FailureBit = 0x10, + + ExpressionFailed = FailureBit | 1, + ExplicitFailure = FailureBit | 2, + + Exception = 0x100 | FailureBit, + + ThrewException = Exception | 1, + DidntThrowException = Exception | 2, + + FatalErrorCondition = 0x200 | FailureBit + + }; }; + + bool isOk( ResultWas::OfType resultType ); + bool isJustInfo( int flags ); + + // ResultDisposition::Flags enum + struct ResultDisposition { enum Flags { + Normal = 0x01, + + ContinueOnFailure = 0x02, // Failures fail test, but execution continues + FalseTest = 0x04, // Prefix expression with ! + SuppressFail = 0x08 // Failures are reported but do not fail the test + }; }; + + ResultDisposition::Flags operator | ( ResultDisposition::Flags lhs, ResultDisposition::Flags rhs ); + + bool shouldContinueOnFailure( int flags ); + bool isFalseTest( int flags ); + bool shouldSuppressFailure( int flags ); + +} // end namespace Catch + +// end catch_result_type.h +namespace Catch { + + struct AssertionInfo + { + StringRef macroName; + SourceLineInfo lineInfo; + StringRef capturedExpression; + ResultDisposition::Flags resultDisposition; + + // We want to delete this constructor but a compiler bug in 4.8 means + // the struct is then treated as non-aggregate + //AssertionInfo() = delete; + }; + +} // end namespace Catch + +// end catch_assertioninfo.h +namespace Catch { + + struct TestFailureException{}; + struct AssertionResultData; + + class LazyExpression { + friend class AssertionHandler; + friend struct AssertionStats; + + ITransientExpression const* m_transientExpression = nullptr; + bool m_isNegated; + public: + LazyExpression( bool isNegated ); + LazyExpression( LazyExpression const& other ); + LazyExpression& operator = ( LazyExpression const& ) = delete; + + explicit operator bool() const; + + friend auto operator << ( std::ostream& os, LazyExpression const& lazyExpr ) -> std::ostream&; + }; + + class AssertionHandler { + AssertionInfo m_assertionInfo; + bool m_shouldDebugBreak = false; + bool m_shouldThrow = false; + bool m_inExceptionGuard = false; + + public: + AssertionHandler + ( StringRef macroName, + SourceLineInfo const& lineInfo, + StringRef capturedExpression, + ResultDisposition::Flags resultDisposition ); + ~AssertionHandler(); + + void handle( ITransientExpression const& expr ); + + template + void handle( ExprLhs const& expr ) { + handle( expr.makeUnaryExpr() ); + } + void handle( ResultWas::OfType resultType ); + void handle( ResultWas::OfType resultType, StringRef const& message ); + void handle( ResultWas::OfType resultType, ITransientExpression const* expr, bool negated ); + void handle( AssertionResultData const& resultData, ITransientExpression const* expr ); + + auto shouldDebugBreak() const -> bool; + auto allowThrows() const -> bool; + void reactWithDebugBreak() const; + void reactWithoutDebugBreak() const; + void useActiveException(); + void setExceptionGuard(); + void unsetExceptionGuard(); + }; + + void handleExceptionMatchExpr( AssertionHandler& handler, std::string const& str, StringRef matcherString ); } // namespace Catch -// #included from: catch_message.h -#define TWOBLUECUBES_CATCH_MESSAGE_H_INCLUDED +// end catch_assertionhandler.h +// start catch_message.h #include +#include namespace Catch { @@ -2002,27 +1264,33 @@ namespace Catch { ResultWas::OfType _type ); std::string macroName; + std::string message; 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; - } + bool operator == ( MessageInfo const& other ) const; + bool operator < ( MessageInfo const& other ) const; private: static unsigned int globalCount; }; - struct MessageBuilder { + struct MessageStream { + + template + MessageStream& operator << ( T const& value ) { + m_stream << value; + return *this; + } + + // !TBD reuse a global/ thread-local stream + std::ostringstream m_stream; + }; + + struct MessageBuilder : MessageStream { MessageBuilder( std::string const& macroName, SourceLineInfo const& lineInfo, - ResultWas::OfType type ) - : m_info( macroName, lineInfo, type ) - {} + ResultWas::OfType type ); template MessageBuilder& operator << ( T const& value ) { @@ -2031,13 +1299,11 @@ namespace Catch { } MessageInfo m_info; - std::ostringstream m_stream; }; class ScopedMessage { public: ScopedMessage( MessageBuilder const& builder ); - ScopedMessage( ScopedMessage const& other ); ~ScopedMessage(); MessageInfo m_info; @@ -2045,31 +1311,36 @@ namespace Catch { } // end namespace Catch -// #included from: catch_interfaces_capture.h -#define TWOBLUECUBES_CATCH_INTERFACES_CAPTURE_H_INCLUDED +// end catch_message.h +// start catch_interfaces_capture.h #include namespace Catch { - class TestCase; class AssertionResult; struct AssertionInfo; struct SectionInfo; struct SectionEndInfo; struct MessageInfo; - class ScopedMessageBuilder; struct Counts; + struct BenchmarkInfo; + struct BenchmarkStats; struct IResultCapture { virtual ~IResultCapture(); + virtual void assertionStarting( AssertionInfo const& info ) = 0; virtual void assertionEnded( AssertionResult const& result ) = 0; virtual bool sectionStarted( SectionInfo const& sectionInfo, Counts& assertions ) = 0; virtual void sectionEnded( SectionEndInfo const& endInfo ) = 0; virtual void sectionEndedEarly( SectionEndInfo const& endInfo ) = 0; + + virtual void benchmarkStarting( BenchmarkInfo const& info ) = 0; + virtual void benchmarkEnded( BenchmarkStats const& stats ) = 0; + virtual void pushScopedMessage( MessageInfo const& message ) = 0; virtual void popScopedMessage( MessageInfo const& message ) = 0; @@ -2078,7 +1349,7 @@ namespace Catch { virtual void exceptionEarlyReported() = 0; - virtual void handleFatalErrorCondition( std::string const& message ) = 0; + virtual void handleFatalErrorCondition( StringRef message ) = 0; virtual bool lastAssertionPassed() = 0; virtual void assertionPassed() = 0; @@ -2088,47 +1359,16 @@ namespace Catch { IResultCapture& getResultCapture(); } -// #included from: catch_debugger.h -#define TWOBLUECUBES_CATCH_DEBUGGER_H_INCLUDED - -// #included from: catch_platform.h -#define TWOBLUECUBES_CATCH_PLATFORM_H_INCLUDED - -#if defined(__MAC_OS_X_VERSION_MIN_REQUIRED) -# define CATCH_PLATFORM_MAC -#elif defined(__IPHONE_OS_VERSION_MIN_REQUIRED) -# define CATCH_PLATFORM_IPHONE -#elif defined(linux) || defined(__linux) || defined(__linux__) -# define CATCH_PLATFORM_LINUX -#elif defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) -# define CATCH_PLATFORM_WINDOWS -# if !defined(NOMINMAX) && !defined(CATCH_CONFIG_NO_NOMINMAX) -# define CATCH_DEFINES_NOMINMAX -# endif -# if !defined(WIN32_LEAN_AND_MEAN) && !defined(CATCH_CONFIG_NO_WIN32_LEAN_AND_MEAN) -# define CATCH_DEFINES_WIN32_LEAN_AND_MEAN -# endif -#endif - -#include - -namespace Catch{ +// end catch_interfaces_capture.h +// start catch_debugger.h +namespace Catch { bool isDebuggerActive(); - void writeToDebugConsole( std::string const& text ); } #ifdef CATCH_PLATFORM_MAC - // The following code snippet based on: - // http://cocoawithlove.com/2008/03/break-into-debugger.html - #if defined(__ppc64__) || defined(__ppc__) - #define CATCH_TRAP() \ - __asm__("li r0, 20\nsc\nnop\nli r0, 37\nli r4, 2\nsc\nnop\n" \ - : : : "memory","r0","r3","r4" ) /* NOLINT */ - #else - #define CATCH_TRAP() __asm__("int $3\n" : : /* NOLINT */ ) - #endif + #define CATCH_TRAP() __asm__("int $3\n" : : ) /* NOLINT */ #elif defined(CATCH_PLATFORM_LINUX) // If we can use inline assembler, do it because this allows us to break @@ -2154,251 +1394,190 @@ namespace Catch{ #define CATCH_BREAK_INTO_DEBUGGER() Catch::alwaysTrue(); #endif -// #included from: catch_interfaces_runner.h -#define TWOBLUECUBES_CATCH_INTERFACES_RUNNER_H_INCLUDED +// end catch_debugger.h +#if !defined(CATCH_CONFIG_DISABLE) -namespace Catch { - class TestCase; - - struct IRunner { - virtual ~IRunner(); - virtual bool aborting() const = 0; - }; -} +#if !defined(CATCH_CONFIG_DISABLE_STRINGIFICATION) + #define CATCH_INTERNAL_STRINGIFY(...) #__VA_ARGS__ +#else + #define CATCH_INTERNAL_STRINGIFY(...) "Disabled by CATCH_CONFIG_DISABLE_STRINGIFICATION" +#endif #if defined(CATCH_CONFIG_FAST_COMPILE) /////////////////////////////////////////////////////////////////////////////// // We can speedup compilation significantly by breaking into debugger lower in // the callstack, because then we don't have to expand CATCH_BREAK_INTO_DEBUGGER // macro in each assertion -#define INTERNAL_CATCH_REACT( resultBuilder ) \ - resultBuilder.react(); +#define INTERNAL_CATCH_REACT( handler ) \ + handler.reactWithDebugBreak(); /////////////////////////////////////////////////////////////////////////////// // Another way to speed-up compilation is to omit local try-catch for REQUIRE* // macros. // This can potentially cause false negative, if the test code catches // the exception before it propagates back up to the runner. -#define INTERNAL_CATCH_TEST_NO_TRY( macroName, resultDisposition, expr ) \ - do { \ - Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \ - __catchResult.setExceptionGuard(); \ - CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \ - ( __catchResult <= expr ).endExpression(); \ - CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS \ - __catchResult.unsetExceptionGuard(); \ - INTERNAL_CATCH_REACT( __catchResult ) \ - } while( Catch::isTrue( false && static_cast( !!(expr) ) ) ) // expr here is never evaluated at runtime but it forces the compiler to give it a look -// The double negation silences MSVC's C4800 warning, the static_cast forces short-circuit evaluation if the type has overloaded &&. +#define INTERNAL_CATCH_TRY( capturer ) capturer.setExceptionGuard(); +#define INTERNAL_CATCH_CATCH( capturer ) capturer.unsetExceptionGuard(); -#define INTERNAL_CHECK_THAT_NO_TRY( macroName, matcher, resultDisposition, arg ) \ - do { \ - Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #arg ", " #matcher, resultDisposition ); \ - __catchResult.setExceptionGuard(); \ - __catchResult.captureMatch( arg, matcher, #matcher ); \ - __catchResult.unsetExceptionGuard(); \ - INTERNAL_CATCH_REACT( __catchResult ) \ - } while( Catch::alwaysFalse() ) +#else // CATCH_CONFIG_FAST_COMPILE -#else /////////////////////////////////////////////////////////////////////////////// // In the event of a failure works out if the debugger needs to be invoked // and/or an exception thrown and takes appropriate action. // This needs to be done as a macro so the debugger will stop in the user // source code rather than in Catch library code -#define INTERNAL_CATCH_REACT( resultBuilder ) \ - if( resultBuilder.shouldDebugBreak() ) CATCH_BREAK_INTO_DEBUGGER(); \ - resultBuilder.react(); +#define INTERNAL_CATCH_REACT( handler ) \ + if( handler.shouldDebugBreak() ) CATCH_BREAK_INTO_DEBUGGER(); \ + handler.reactWithoutDebugBreak(); + +#define INTERNAL_CATCH_TRY( capturer ) try +#define INTERNAL_CATCH_CATCH( capturer ) catch(...) { capturer.useActiveException(); } + #endif /////////////////////////////////////////////////////////////////////////////// -#define INTERNAL_CATCH_TEST( macroName, resultDisposition, expr ) \ +#define INTERNAL_CATCH_TEST( macroName, resultDisposition, ... ) \ do { \ - Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \ - try { \ + Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__), resultDisposition ); \ + INTERNAL_CATCH_TRY( catchAssertionHandler ) { \ CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \ - ( __catchResult <= expr ).endExpression(); \ + catchAssertionHandler.handle( Catch::Decomposer() <= __VA_ARGS__ ); \ CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS \ - } \ - catch( ... ) { \ - __catchResult.useActiveException( resultDisposition ); \ - } \ - INTERNAL_CATCH_REACT( __catchResult ) \ - } while( Catch::isTrue( false && static_cast( !!(expr) ) ) ) // expr here is never evaluated at runtime but it forces the compiler to give it a look + } INTERNAL_CATCH_CATCH( catchAssertionHandler ) \ + INTERNAL_CATCH_REACT( catchAssertionHandler ) \ + } while( Catch::isTrue( false && static_cast( !!(__VA_ARGS__) ) ) ) // the expression here is never evaluated at runtime but it forces the compiler to give it a look // The double negation silences MSVC's C4800 warning, the static_cast forces short-circuit evaluation if the type has overloaded &&. /////////////////////////////////////////////////////////////////////////////// -#define INTERNAL_CATCH_IF( macroName, resultDisposition, expr ) \ - INTERNAL_CATCH_TEST( macroName, resultDisposition, expr ); \ +#define INTERNAL_CATCH_IF( macroName, resultDisposition, ... ) \ + INTERNAL_CATCH_TEST( macroName, resultDisposition, __VA_ARGS__ ); \ if( Catch::getResultCapture().lastAssertionPassed() ) /////////////////////////////////////////////////////////////////////////////// -#define INTERNAL_CATCH_ELSE( macroName, resultDisposition, expr ) \ - INTERNAL_CATCH_TEST( macroName, resultDisposition, expr ); \ +#define INTERNAL_CATCH_ELSE( macroName, resultDisposition, ... ) \ + INTERNAL_CATCH_TEST( macroName, resultDisposition, __VA_ARGS__ ); \ if( !Catch::getResultCapture().lastAssertionPassed() ) /////////////////////////////////////////////////////////////////////////////// -#define INTERNAL_CATCH_NO_THROW( macroName, resultDisposition, expr ) \ +#define INTERNAL_CATCH_NO_THROW( macroName, resultDisposition, ... ) \ do { \ - Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \ + Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__), resultDisposition ); \ try { \ - static_cast(expr); \ - __catchResult.captureResult( Catch::ResultWas::Ok ); \ + static_cast(__VA_ARGS__); \ + catchAssertionHandler.handle( Catch::ResultWas::Ok ); \ } \ catch( ... ) { \ - __catchResult.useActiveException( resultDisposition ); \ + catchAssertionHandler.useActiveException(); \ } \ - INTERNAL_CATCH_REACT( __catchResult ) \ + INTERNAL_CATCH_REACT( catchAssertionHandler ) \ } while( Catch::alwaysFalse() ) /////////////////////////////////////////////////////////////////////////////// -#define INTERNAL_CATCH_THROWS( macroName, resultDisposition, matcher, expr ) \ +#define INTERNAL_CATCH_THROWS( macroName, resultDisposition, ... ) \ do { \ - Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition, #matcher ); \ - if( __catchResult.allowThrows() ) \ + Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__), resultDisposition); \ + if( catchAssertionHandler.allowThrows() ) \ try { \ - static_cast(expr); \ - __catchResult.captureResult( Catch::ResultWas::DidntThrowException ); \ + static_cast(__VA_ARGS__); \ + catchAssertionHandler.handle( Catch::ResultWas::DidntThrowException ); \ } \ catch( ... ) { \ - __catchResult.captureExpectedException( matcher ); \ + catchAssertionHandler.handle( Catch::ResultWas::Ok ); \ } \ else \ - __catchResult.captureResult( Catch::ResultWas::Ok ); \ - INTERNAL_CATCH_REACT( __catchResult ) \ + catchAssertionHandler.handle( Catch::ResultWas::Ok ); \ + INTERNAL_CATCH_REACT( catchAssertionHandler ) \ } while( Catch::alwaysFalse() ) /////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CATCH_THROWS_AS( macroName, exceptionType, resultDisposition, expr ) \ do { \ - Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr ", " #exceptionType, resultDisposition ); \ - if( __catchResult.allowThrows() ) \ + Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(expr) ", " CATCH_INTERNAL_STRINGIFY(exceptionType), resultDisposition ); \ + if( catchAssertionHandler.allowThrows() ) \ try { \ static_cast(expr); \ - __catchResult.captureResult( Catch::ResultWas::DidntThrowException ); \ + catchAssertionHandler.handle( Catch::ResultWas::DidntThrowException ); \ } \ - catch( exceptionType ) { \ - __catchResult.captureResult( Catch::ResultWas::Ok ); \ + catch( exceptionType const& ) { \ + catchAssertionHandler.handle( Catch::ResultWas::Ok ); \ } \ catch( ... ) { \ - __catchResult.useActiveException( resultDisposition ); \ + catchAssertionHandler.useActiveException(); \ } \ else \ - __catchResult.captureResult( Catch::ResultWas::Ok ); \ - INTERNAL_CATCH_REACT( __catchResult ) \ + catchAssertionHandler.handle( Catch::ResultWas::Ok ); \ + INTERNAL_CATCH_REACT( catchAssertionHandler ) \ } while( Catch::alwaysFalse() ) /////////////////////////////////////////////////////////////////////////////// -#ifdef CATCH_CONFIG_VARIADIC_MACROS - #define INTERNAL_CATCH_MSG( macroName, messageType, resultDisposition, ... ) \ - 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( macroName, messageType, resultDisposition, log ) \ - do { \ - Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, "", resultDisposition ); \ - __catchResult << log + ::Catch::StreamEndStop(); \ - __catchResult.captureResult( messageType ); \ - INTERNAL_CATCH_REACT( __catchResult ) \ - } while( Catch::alwaysFalse() ) -#endif +#define INTERNAL_CATCH_MSG( macroName, messageType, resultDisposition, ... ) \ + do { \ + Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, "", resultDisposition ); \ + catchAssertionHandler.handle( messageType, ( Catch::MessageStream() << __VA_ARGS__ + ::Catch::StreamEndStop() ).m_stream.str() ); \ + INTERNAL_CATCH_REACT( catchAssertionHandler ) \ + } while( Catch::alwaysFalse() ) /////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CATCH_INFO( macroName, log ) \ Catch::ScopedMessage INTERNAL_CATCH_UNIQUE_NAME( scopedMessage ) = Catch::MessageBuilder( macroName, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info ) << log; /////////////////////////////////////////////////////////////////////////////// -#define INTERNAL_CHECK_THAT( macroName, matcher, resultDisposition, arg ) \ +// Although this is matcher-based, it can be used with just a string +#define INTERNAL_CATCH_THROWS_STR_MATCHES( macroName, resultDisposition, matcher, ... ) \ do { \ - Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #arg ", " #matcher, resultDisposition ); \ - try { \ - __catchResult.captureMatch( arg, matcher, #matcher ); \ - } catch( ... ) { \ - __catchResult.useActiveException( resultDisposition | Catch::ResultDisposition::ContinueOnFailure ); \ - } \ - INTERNAL_CATCH_REACT( __catchResult ) \ + Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__) ", " CATCH_INTERNAL_STRINGIFY(matcher), resultDisposition ); \ + if( catchAssertionHandler.allowThrows() ) \ + try { \ + static_cast(__VA_ARGS__); \ + catchAssertionHandler.handle( Catch::ResultWas::DidntThrowException ); \ + } \ + catch( ... ) { \ + handleExceptionMatchExpr( catchAssertionHandler, matcher, #matcher ); \ + } \ + else \ + catchAssertionHandler.handle( Catch::ResultWas::Ok ); \ + INTERNAL_CATCH_REACT( catchAssertionHandler ) \ } while( Catch::alwaysFalse() ) -// #included from: internal/catch_section.h -#define TWOBLUECUBES_CATCH_SECTION_H_INCLUDED +#endif // CATCH_CONFIG_DISABLE -// #included from: catch_section_info.h -#define TWOBLUECUBES_CATCH_SECTION_INFO_H_INCLUDED +// end catch_capture.hpp +// start catch_section.h -// #included from: catch_totals.hpp -#define TWOBLUECUBES_CATCH_TOTALS_HPP_INCLUDED +// start catch_section_info.h + +// start catch_totals.h #include namespace Catch { struct Counts { - Counts() : passed( 0 ), failed( 0 ), failedButOk( 0 ) {} + Counts operator - ( Counts const& other ) const; + Counts& operator += ( Counts const& other ); - 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; + bool allPassed() const; + bool allOk() const; - std::size_t total() const { - return passed + failed + failedButOk; - } - bool allPassed() const { - return failed == 0 && failedButOk == 0; - } - bool allOk() const { - return failed == 0; - } - - std::size_t passed; - std::size_t failed; - std::size_t failedButOk; + std::size_t passed = 0; + std::size_t failed = 0; + std::size_t failedButOk = 0; }; struct Totals { - Totals operator - ( Totals const& other ) const { - Totals diff; - diff.assertions = assertions - other.assertions; - diff.testCases = testCases - other.testCases; - return diff; - } + Totals operator - ( Totals const& other ) const; + Totals& operator += ( Totals const& other ); - 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; - } + Totals delta( Totals const& prevTotals ) const; Counts assertions; Counts testCases; }; } +// end catch_totals.h #include namespace Catch { @@ -2415,9 +1594,7 @@ namespace Catch { }; struct SectionEndInfo { - SectionEndInfo( SectionInfo const& _sectionInfo, Counts const& _prevAssertions, double _durationInSeconds ) - : sectionInfo( _sectionInfo ), prevAssertions( _prevAssertions ), durationInSeconds( _durationInSeconds ) - {} + SectionEndInfo( SectionInfo const& _sectionInfo, Counts const& _prevAssertions, double _durationInSeconds ); SectionInfo sectionInfo; Counts prevAssertions; @@ -2426,36 +1603,29 @@ namespace Catch { } // end namespace Catch -// #included from: catch_timer.h -#define TWOBLUECUBES_CATCH_TIMER_H_INCLUDED +// end catch_section_info.h +// start catch_timer.h -#ifdef _MSC_VER +#include namespace Catch { - typedef unsigned long long UInt64; -} -#else -#include -namespace Catch { - typedef uint64_t UInt64; -} -#endif -namespace Catch { + auto getCurrentNanosecondsSinceEpoch() -> uint64_t; + auto getEstimatedClockResolution() -> uint64_t; + class Timer { + uint64_t m_nanoseconds = 0; public: - Timer() : m_ticks( 0 ) {} void start(); - unsigned int getElapsedMicroseconds() const; - unsigned int getElapsedMilliseconds() const; - double getElapsedSeconds() const; - - private: - UInt64 m_ticks; + auto getElapsedNanoseconds() const -> unsigned int; + auto getElapsedMicroseconds() const -> unsigned int; + auto getElapsedMilliseconds() const -> unsigned int; + auto getElapsedSeconds() const -> double; }; } // namespace Catch +// end catch_timer.h #include namespace Catch { @@ -2466,7 +1636,7 @@ namespace Catch { ~Section(); // This indicates whether the section should be executed or not - operator bool() const; + explicit operator bool() const; private: SectionInfo m_info; @@ -2479,203 +1649,62 @@ namespace Catch { } // end namespace Catch -#ifdef CATCH_CONFIG_VARIADIC_MACROS #define INTERNAL_CATCH_SECTION( ... ) \ if( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::SectionInfo( CATCH_INTERNAL_LINEINFO, __VA_ARGS__ ) ) -#else - #define INTERNAL_CATCH_SECTION( name, desc ) \ - if( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::SectionInfo( CATCH_INTERNAL_LINEINFO, name, desc ) ) -#endif -// #included from: internal/catch_generators.hpp -#define TWOBLUECUBES_CATCH_GENERATORS_HPP_INCLUDED +// end catch_section.h +// start catch_benchmark.h -#include +#include #include -#include namespace Catch { -template -struct IGenerator { - virtual ~IGenerator() {} - virtual T getValue( std::size_t index ) const = 0; - virtual std::size_t size () const = 0; -}; + class BenchmarkLooper { -template -class BetweenGenerator : public IGenerator { -public: - BetweenGenerator( T from, T to ) : m_from( from ), m_to( to ){} + std::string m_name; + std::size_t m_count = 0; + std::size_t m_iterationsToRun = 1; + uint64_t m_resolution; + Timer m_timer; - 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 ); - } - -private: - - T m_from; - T m_to; -}; - -template -class ValuesGenerator : public IGenerator { -public: - ValuesGenerator(){} - - void add( T value ) { - m_values.push_back( value ); - } - - virtual T getValue( std::size_t index ) const { - return m_values[index]; - } - - virtual std::size_t size() const { - return m_values.size(); - } - -private: - std::vector m_values; -}; - -template -class CompositeGenerator { -public: - CompositeGenerator() : m_totalSize( 0 ) {} - - // *** Move semantics, similar to auto_ptr *** - CompositeGenerator( CompositeGenerator& other ) - : m_fileInfo( other.m_fileInfo ), - m_totalSize( 0 ) - { - move( other ); - } - - CompositeGenerator& setFileInfo( const char* fileInfo ) { - m_fileInfo = fileInfo; - return *this; - } - - ~CompositeGenerator() { - deleteAll( m_composed ); - } - - operator T () const { - size_t overallIndex = getCurrentContext().getGeneratorIndex( m_fileInfo, m_totalSize ); - - typename std::vector*>::const_iterator it = m_composed.begin(); - typename std::vector*>::const_iterator itEnd = m_composed.end(); - for( size_t index = 0; it != itEnd; ++it ) + static auto getResolution() -> uint64_t; + public: + // Keep most of this inline as it's on the code path that is being timed + BenchmarkLooper( StringRef name ) + : m_name( name ), + m_resolution( getResolution() ) { - const IGenerator* generator = *it; - if( overallIndex >= index && overallIndex < index + generator->size() ) - { - return generator->getValue( overallIndex-index ); - } - index += generator->size(); + reportStart(); + m_timer.start(); } - CATCH_INTERNAL_ERROR( "Indexed past end of generated range" ); - return T(); // Suppress spurious "not all control paths return a value" warning in Visual Studio - if you know how to fix this please do so - } - void add( const IGenerator* generator ) { - m_totalSize += generator->size(); - m_composed.push_back( generator ); - } + explicit operator bool() { + if( m_count < m_iterationsToRun ) + return true; + return needsMoreIterations(); + } - CompositeGenerator& then( CompositeGenerator& other ) { - move( other ); - return *this; - } + void increment() { + ++m_count; + } - CompositeGenerator& then( T value ) { - ValuesGenerator* valuesGen = new ValuesGenerator(); - valuesGen->add( value ); - add( valuesGen ); - return *this; - } - -private: - - void move( CompositeGenerator& other ) { - m_composed.insert( m_composed.end(), other.m_composed.begin(), other.m_composed.end() ); - m_totalSize += other.m_totalSize; - other.m_composed.clear(); - } - - std::vector*> m_composed; - std::string m_fileInfo; - size_t m_totalSize; -}; - -namespace 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, 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; - } - -} // end namespace Generators - -using namespace Generators; + void reportStart(); + auto needsMoreIterations() -> bool; + }; } // end namespace Catch -#define INTERNAL_CATCH_LINESTR2( line ) #line -#define INTERNAL_CATCH_LINESTR( line ) INTERNAL_CATCH_LINESTR2( line ) +#define BENCHMARK( name ) \ + for( Catch::BenchmarkLooper looper( name ); looper; looper.increment() ) -#define INTERNAL_CATCH_GENERATE( expr ) expr.setFileInfo( __FILE__ "(" INTERNAL_CATCH_LINESTR( __LINE__ ) ")" ) +// end catch_benchmark.h +// start catch_interfaces_exception.h -// #included from: internal/catch_interfaces_exception.h -#define TWOBLUECUBES_CATCH_INTERFACES_EXCEPTION_H_INCLUDED - -#include -#include - -// #included from: catch_interfaces_registry_hub.h -#define TWOBLUECUBES_CATCH_INTERFACES_REGISTRY_HUB_H_INCLUDED +// start catch_interfaces_registry_hub.h #include +#include namespace Catch { @@ -2686,6 +1715,9 @@ namespace Catch { struct IReporterRegistry; struct IReporterFactory; struct ITagAliasRegistry; + class StartupExceptionRegistry; + + using IReporterFactoryPtr = std::shared_ptr; struct IRegistryHub { virtual ~IRegistryHub(); @@ -2695,15 +1727,18 @@ namespace Catch { virtual ITagAliasRegistry const& getTagAliasRegistry() const = 0; virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() = 0; + + virtual StartupExceptionRegistry const& getStartupExceptionRegistry() const = 0; }; struct IMutableRegistryHub { virtual ~IMutableRegistryHub(); - virtual void registerReporter( std::string const& name, Ptr const& factory ) = 0; - virtual void registerListener( Ptr const& factory ) = 0; + virtual void registerReporter( std::string const& name, IReporterFactoryPtr const& factory ) = 0; + virtual void registerListener( IReporterFactoryPtr const& factory ) = 0; virtual void registerTest( TestCase const& testInfo ) = 0; virtual void registerTranslator( const IExceptionTranslator* translator ) = 0; virtual void registerTagAlias( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo ) = 0; + virtual void registerStartupException() noexcept = 0; }; IRegistryHub& getRegistryHub(); @@ -2713,12 +1748,21 @@ namespace Catch { } -namespace Catch { +// end catch_interfaces_registry_hub.h +#if defined(CATCH_CONFIG_DISABLE) + #define INTERNAL_CATCH_TRANSLATE_EXCEPTION_NO_REG( translatorName, signature) \ + static std::string translatorName( signature ) +#endif - typedef std::string(*exceptionTranslateFunction)(); +#include +#include +#include + +namespace Catch { + using exceptionTranslateFunction = std::string(*)(); struct IExceptionTranslator; - typedef std::vector ExceptionTranslators; + using ExceptionTranslators = std::vector>; struct IExceptionTranslator { virtual ~IExceptionTranslator(); @@ -2740,10 +1784,10 @@ namespace Catch { : m_translateFunction( translateFunction ) {} - virtual std::string translate( ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd ) const CATCH_OVERRIDE { + std::string translate( ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd ) const override { try { if( it == itEnd ) - throw; + std::rethrow_exception(std::current_exception()); else return (*it)->translate( it+1, itEnd ); } @@ -2773,36 +1817,40 @@ namespace Catch { #define INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION2( INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator ), signature ) -// #included from: internal/catch_approx.hpp -#define TWOBLUECUBES_CATCH_APPROX_HPP_INCLUDED +// end catch_interfaces_exception.h +// start catch_approx.h -#include -#include +// start catch_enforce.h -#if defined(CATCH_CONFIG_CPP11_TYPE_TRAITS) +#include +#include + +#define CATCH_PREPARE_EXCEPTION( type, msg ) \ + type( static_cast( std::ostringstream() << msg ).str() ) +#define CATCH_INTERNAL_ERROR( msg ) \ + throw CATCH_PREPARE_EXCEPTION( std::logic_error, CATCH_INTERNAL_LINEINFO << ": Internal Catch error: " << msg); +#define CATCH_ERROR( msg ) \ + throw CATCH_PREPARE_EXCEPTION( std::domain_error, msg ) +#define CATCH_ENFORCE( condition, msg ) \ + do{ if( !(condition) ) CATCH_ERROR( msg ); } while(false) + +// end catch_enforce.h #include -#endif namespace Catch { namespace Detail { class Approx { + private: + bool equalityComparisonImpl(double other) const; + public: - explicit Approx ( double value ) - : m_epsilon( std::numeric_limits::epsilon()*100 ), - m_margin( 0.0 ), - m_scale( 1.0 ), - m_value( value ) - {} + explicit Approx ( double value ); - static Approx custom() { - return Approx( 0 ); - } - -#if defined(CATCH_CONFIG_CPP11_TYPE_TRAITS) + static Approx custom(); template ::value>::type> - Approx operator()( T value ) { + Approx operator()( T const& value ) { Approx approx( static_cast(value) ); approx.epsilon( m_epsilon ); approx.margin( m_margin ); @@ -2811,18 +1859,13 @@ namespace Detail { } template ::value>::type> - explicit Approx( T value ): Approx(static_cast(value)) + explicit Approx( T const& value ): Approx(static_cast(value)) {} template ::value>::type> friend bool operator == ( const T& lhs, Approx const& rhs ) { - // Thanks to Richard Harris for his help refining this formula - auto lhs_v = double(lhs); - bool relativeOK = std::fabs(lhs_v - rhs.m_value) < rhs.m_epsilon * (rhs.m_scale + (std::max)(std::fabs(lhs_v), std::fabs(rhs.m_value))); - if (relativeOK) { - return true; - } - return std::fabs(lhs_v - rhs.m_value) < rhs.m_margin; + auto lhs_v = static_cast(lhs); + return rhs.equalityComparisonImpl(lhs_v); } template ::value>::type> @@ -2831,121 +1874,62 @@ namespace Detail { } template ::value>::type> - friend bool operator != ( T lhs, Approx const& rhs ) { + friend bool operator != ( T const& lhs, Approx const& rhs ) { return !operator==( lhs, rhs ); } template ::value>::type> - friend bool operator != ( Approx const& lhs, T rhs ) { + friend bool operator != ( Approx const& lhs, T const& rhs ) { return !operator==( rhs, lhs ); } template ::value>::type> - friend bool operator <= ( T lhs, Approx const& rhs ) { - return double(lhs) < rhs.m_value || lhs == rhs; + friend bool operator <= ( T const& lhs, Approx const& rhs ) { + return static_cast(lhs) < rhs.m_value || lhs == rhs; } template ::value>::type> - friend bool operator <= ( Approx const& lhs, T rhs ) { - return lhs.m_value < double(rhs) || lhs == rhs; + friend bool operator <= ( Approx const& lhs, T const& rhs ) { + return lhs.m_value < static_cast(rhs) || lhs == rhs; } template ::value>::type> - friend bool operator >= ( T lhs, Approx const& rhs ) { - return double(lhs) > rhs.m_value || lhs == rhs; + friend bool operator >= ( T const& lhs, Approx const& rhs ) { + return static_cast(lhs) > rhs.m_value || lhs == rhs; } template ::value>::type> - friend bool operator >= ( Approx const& lhs, T rhs ) { - return lhs.m_value > double(rhs) || lhs == rhs; + friend bool operator >= ( Approx const& lhs, T const& rhs ) { + return lhs.m_value > static_cast(rhs) || lhs == rhs; } template ::value>::type> - Approx& epsilon( T newEpsilon ) { - m_epsilon = double(newEpsilon); + Approx& epsilon( T const& newEpsilon ) { + double epsilonAsDouble = static_cast(newEpsilon); + CATCH_ENFORCE(epsilonAsDouble >= 0 && epsilonAsDouble <= 1.0, + "Invalid Approx::epsilon: " << epsilonAsDouble + << ", Approx::epsilon has to be between 0 and 1"); + m_epsilon = epsilonAsDouble; return *this; } template ::value>::type> - Approx& margin( T newMargin ) { - m_margin = double(newMargin); + Approx& margin( T const& newMargin ) { + double marginAsDouble = static_cast(newMargin); + CATCH_ENFORCE(marginAsDouble >= 0, + "Invalid Approx::margin: " << marginAsDouble + << ", Approx::Margin has to be non-negative."); + m_margin = marginAsDouble; return *this; } template ::value>::type> - Approx& scale( T newScale ) { - m_scale = double(newScale); + Approx& scale( T const& newScale ) { + m_scale = static_cast(newScale); return *this; } -#else - - Approx operator()( double value ) { - Approx approx( value ); - approx.epsilon( m_epsilon ); - approx.margin( m_margin ); - approx.scale( m_scale ); - return approx; - } - - friend bool operator == ( double lhs, Approx const& rhs ) { - // Thanks to Richard Harris for his help refining this formula - bool relativeOK = std::fabs( lhs - rhs.m_value ) < rhs.m_epsilon * (rhs.m_scale + (std::max)( std::fabs(lhs), std::fabs(rhs.m_value) ) ); - if (relativeOK) { - return true; - } - return std::fabs(lhs - rhs.m_value) < rhs.m_margin; - } - - friend bool operator == ( Approx const& lhs, double rhs ) { - return operator==( rhs, lhs ); - } - - friend bool operator != ( double lhs, Approx const& rhs ) { - return !operator==( lhs, rhs ); - } - - friend bool operator != ( Approx const& lhs, double rhs ) { - return !operator==( rhs, lhs ); - } - - friend bool operator <= ( double lhs, Approx const& rhs ) { - return lhs < rhs.m_value || lhs == rhs; - } - - friend bool operator <= ( Approx const& lhs, double rhs ) { - return lhs.m_value < rhs || lhs == rhs; - } - - friend bool operator >= ( double lhs, Approx const& rhs ) { - return lhs > rhs.m_value || lhs == rhs; - } - - friend bool operator >= ( Approx const& lhs, double rhs ) { - return lhs.m_value > rhs || lhs == rhs; - } - - Approx& epsilon( double newEpsilon ) { - m_epsilon = newEpsilon; - return *this; - } - - Approx& margin( double newMargin ) { - m_margin = newMargin; - return *this; - } - - Approx& scale( double newScale ) { - m_scale = newScale; - return *this; - } -#endif - - std::string toString() const { - std::ostringstream oss; - oss << "Approx( " << Catch::toString( m_value ) << " )"; - return oss.str(); - } + std::string toString() const; private: double m_epsilon; @@ -2956,14 +1940,194 @@ namespace Detail { } template<> -inline std::string toString( Detail::Approx const& value ) { - return value.toString(); -} +struct StringMaker { + static std::string convert(Catch::Detail::Approx const& value); +}; } // end namespace Catch -// #included from: internal/catch_matchers_string.h -#define TWOBLUECUBES_CATCH_MATCHERS_STRING_H_INCLUDED +// end catch_approx.h +// start catch_string_manip.h + +#include +#include + +namespace Catch { + + bool startsWith( std::string const& s, std::string const& prefix ); + bool startsWith( std::string const& s, char prefix ); + bool endsWith( std::string const& s, std::string const& suffix ); + bool endsWith( std::string const& s, char suffix ); + bool contains( std::string const& s, std::string const& infix ); + void toLowerInPlace( std::string& s ); + std::string toLower( std::string const& s ); + std::string trim( std::string const& str ); + bool replaceInPlace( std::string& str, std::string const& replaceThis, std::string const& withThis ); + + struct pluralise { + pluralise( std::size_t count, std::string const& label ); + + friend std::ostream& operator << ( std::ostream& os, pluralise const& pluraliser ); + + std::size_t m_count; + std::string m_label; + }; +} + +// end catch_string_manip.h +#ifndef CATCH_CONFIG_DISABLE_MATCHERS +// start catch_capture_matchers.h + +// start catch_matchers.h + +#include +#include + +namespace Catch { +namespace Matchers { + namespace Impl { + + template struct MatchAllOf; + template struct MatchAnyOf; + template struct MatchNotOf; + + class MatcherUntypedBase { + public: + MatcherUntypedBase() = default; + MatcherUntypedBase ( MatcherUntypedBase const& ) = default; + MatcherUntypedBase& operator = ( MatcherUntypedBase const& ) = delete; + std::string toString() const; + + protected: + virtual ~MatcherUntypedBase(); + virtual std::string describe() const = 0; + mutable std::string m_cachedToString; + }; + + template + struct MatcherMethod { + virtual bool match( ObjectT const& arg ) const = 0; + }; + template + struct MatcherMethod { + virtual bool match( PtrT* arg ) const = 0; + }; + + template + struct MatcherBase : MatcherUntypedBase, MatcherMethod { + + MatchAllOf operator && ( MatcherBase const& other ) const; + MatchAnyOf operator || ( MatcherBase const& other ) const; + MatchNotOf operator ! () const; + }; + + template + struct MatchAllOf : MatcherBase { + bool match( ArgT const& arg ) const override { + for( auto matcher : m_matchers ) { + if (!matcher->match(arg)) + return false; + } + return true; + } + std::string describe() const override { + std::string description; + description.reserve( 4 + m_matchers.size()*32 ); + description += "( "; + bool first = true; + for( auto matcher : m_matchers ) { + if( first ) + first = false; + else + description += " and "; + description += matcher->toString(); + } + description += " )"; + return description; + } + + MatchAllOf& operator && ( MatcherBase const& other ) { + m_matchers.push_back( &other ); + return *this; + } + + std::vector const*> m_matchers; + }; + template + struct MatchAnyOf : MatcherBase { + + bool match( ArgT const& arg ) const override { + for( auto matcher : m_matchers ) { + if (matcher->match(arg)) + return true; + } + return false; + } + std::string describe() const override { + std::string description; + description.reserve( 4 + m_matchers.size()*32 ); + description += "( "; + bool first = true; + for( auto matcher : m_matchers ) { + if( first ) + first = false; + else + description += " or "; + description += matcher->toString(); + } + description += " )"; + return description; + } + + MatchAnyOf& operator || ( MatcherBase const& other ) { + m_matchers.push_back( &other ); + return *this; + } + + std::vector const*> m_matchers; + }; + + template + struct MatchNotOf : MatcherBase { + + MatchNotOf( MatcherBase const& underlyingMatcher ) : m_underlyingMatcher( underlyingMatcher ) {} + + bool match( ArgT const& arg ) const override { + return !m_underlyingMatcher.match( arg ); + } + + std::string describe() const override { + return "not " + m_underlyingMatcher.toString(); + } + MatcherBase const& m_underlyingMatcher; + }; + + template + MatchAllOf MatcherBase::operator && ( MatcherBase const& other ) const { + return MatchAllOf() && *this && other; + } + template + MatchAnyOf MatcherBase::operator || ( MatcherBase const& other ) const { + return MatchAnyOf() || *this || other; + } + template + MatchNotOf MatcherBase::operator ! () const { + return MatchNotOf( *this ); + } + + } // namespace Impl + +} // namespace Matchers + +using namespace Matchers; +using Matchers::Impl::MatcherBase; + +} // namespace Catch + +// end catch_matchers.h +// start catch_matchers_string.h + +#include namespace Catch { namespace Matchers { @@ -2982,7 +2146,7 @@ namespace Matchers { struct StringMatcherBase : MatcherBase { StringMatcherBase( std::string const& operation, CasedString const& comparator ); - virtual std::string describe() const CATCH_OVERRIDE; + std::string describe() const override; CasedString m_comparator; std::string m_operation; @@ -2990,19 +2154,19 @@ namespace Matchers { struct EqualsMatcher : StringMatcherBase { EqualsMatcher( CasedString const& comparator ); - virtual bool match( std::string const& source ) const CATCH_OVERRIDE; + bool match( std::string const& source ) const override; }; struct ContainsMatcher : StringMatcherBase { ContainsMatcher( CasedString const& comparator ); - virtual bool match( std::string const& source ) const CATCH_OVERRIDE; + bool match( std::string const& source ) const override; }; struct StartsWithMatcher : StringMatcherBase { StartsWithMatcher( CasedString const& comparator ); - virtual bool match( std::string const& source ) const CATCH_OVERRIDE; + bool match( std::string const& source ) const override; }; struct EndsWithMatcher : StringMatcherBase { EndsWithMatcher( CasedString const& comparator ); - virtual bool match( std::string const& source ) const CATCH_OVERRIDE; + bool match( std::string const& source ) const override; }; } // namespace StdString @@ -3018,8 +2182,8 @@ namespace Matchers { } // namespace Matchers } // namespace Catch -// #included from: internal/catch_matchers_vector.h -#define TWOBLUECUBES_CATCH_MATCHERS_VECTOR_H_INCLUDED +// end catch_matchers_string.h +// start catch_matchers_vector.h namespace Catch { namespace Matchers { @@ -3031,12 +2195,17 @@ namespace Matchers { ContainsElementMatcher(T const &comparator) : m_comparator( comparator) {} - bool match(std::vector const &v) const CATCH_OVERRIDE { - return std::find(v.begin(), v.end(), m_comparator) != v.end(); + bool match(std::vector const &v) const override { + for (auto const& el : v) { + if (el == m_comparator) { + return true; + } + } + return false; } - virtual std::string describe() const CATCH_OVERRIDE { - return "Contains: " + Catch::toString( m_comparator ); + std::string describe() const override { + return "Contains: " + ::Catch::Detail::stringify( m_comparator ); } T const& m_comparator; @@ -3047,17 +2216,26 @@ namespace Matchers { ContainsMatcher(std::vector const &comparator) : m_comparator( comparator ) {} - bool match(std::vector const &v) const CATCH_OVERRIDE { + bool match(std::vector const &v) const override { // !TBD: see note in EqualsMatcher if (m_comparator.size() > v.size()) return false; - for (size_t i = 0; i < m_comparator.size(); ++i) - if (std::find(v.begin(), v.end(), m_comparator[i]) == v.end()) + for (auto const& comparator : m_comparator) { + auto present = false; + for (const auto& el : v) { + if (el == comparator) { + present = true; + break; + } + } + if (!present) { return false; + } + } return true; } - virtual std::string describe() const CATCH_OVERRIDE { - return "Contains: " + Catch::toString( m_comparator ); + std::string describe() const override { + return "Contains: " + ::Catch::Detail::stringify( m_comparator ); } std::vector const& m_comparator; @@ -3068,20 +2246,20 @@ namespace Matchers { EqualsMatcher(std::vector const &comparator) : m_comparator( comparator ) {} - bool match(std::vector const &v) const CATCH_OVERRIDE { + bool match(std::vector const &v) const override { // !TBD: This currently works if all elements can be compared using != // - a more general approach would be via a compare template that defaults // to using !=. but could be specialised for, e.g. std::vector etc // - then just call that directly if (m_comparator.size() != v.size()) return false; - for (size_t i = 0; i < v.size(); ++i) + for (std::size_t i = 0; i < v.size(); ++i) if (m_comparator[i] != v[i]) return false; return true; } - virtual std::string describe() const CATCH_OVERRIDE { - return "Equals: " + Catch::toString( m_comparator ); + std::string describe() const override { + return "Equals: " + ::Catch::Detail::stringify( m_comparator ); } std::vector const& m_comparator; }; @@ -3109,124 +2287,87 @@ namespace Matchers { } // namespace Matchers } // namespace Catch -// #included from: internal/catch_interfaces_tag_alias_registry.h -#define TWOBLUECUBES_CATCH_INTERFACES_TAG_ALIAS_REGISTRY_H_INCLUDED - -// #included from: catch_tag_alias.h -#define TWOBLUECUBES_CATCH_TAG_ALIAS_H_INCLUDED - -#include - +// end catch_matchers_vector.h namespace Catch { - struct TagAlias { - TagAlias( std::string const& _tag, SourceLineInfo _lineInfo ) : tag( _tag ), lineInfo( _lineInfo ) {} - - std::string tag; - SourceLineInfo lineInfo; - }; - - struct RegistrarForTagAliases { - RegistrarForTagAliases( char const* alias, char const* tag, SourceLineInfo const& lineInfo ); - }; - -} // end namespace Catch - -#define CATCH_REGISTER_TAG_ALIAS( alias, spec ) namespace{ Catch::RegistrarForTagAliases INTERNAL_CATCH_UNIQUE_NAME( AutoRegisterTagAlias )( alias, spec, CATCH_INTERNAL_LINEINFO ); } -// #included from: catch_option.hpp -#define TWOBLUECUBES_CATCH_OPTION_HPP_INCLUDED - -namespace Catch { - - // An optional type - template - class Option { + template + class MatchExpr : public ITransientExpression { + ArgT const& m_arg; + MatcherT m_matcher; + StringRef m_matcherString; + bool m_result; public: - Option() : nullableValue( CATCH_NULL ) {} - Option( T const& _value ) - : nullableValue( new( storage ) T( _value ) ) - {} - Option( Option const& _other ) - : nullableValue( _other ? new( storage ) T( *_other ) : CATCH_NULL ) + MatchExpr( ArgT const& arg, MatcherT const& matcher, StringRef matcherString ) + : m_arg( arg ), + m_matcher( matcher ), + m_matcherString( matcherString ), + m_result( matcher.match( arg ) ) {} - ~Option() { - reset(); + auto isBinaryExpression() const -> bool override { return true; } + auto getResult() const -> bool override { return m_result; } + + void streamReconstructedExpression( std::ostream &os ) const override { + auto matcherAsString = m_matcher.toString(); + os << Catch::Detail::stringify( m_arg ) << ' '; + if( matcherAsString == Detail::unprintableString ) + os << m_matcherString; + else + os << matcherAsString; } + }; - Option& operator= ( Option const& _other ) { - if( &_other != this ) { - reset(); - if( _other ) - nullableValue = new( storage ) T( *_other ); - } - return *this; - } - Option& operator = ( T const& _value ) { - reset(); - nullableValue = new( storage ) T( _value ); - return *this; - } + using StringMatcher = Matchers::Impl::MatcherBase; - void reset() { - if( nullableValue ) - nullableValue->~T(); - nullableValue = CATCH_NULL; - } + void handleExceptionMatchExpr( AssertionHandler& handler, StringMatcher const& matcher, StringRef matcherString ); - T& operator*() { return *nullableValue; } - T const& operator*() const { return *nullableValue; } - T* operator->() { return nullableValue; } - const T* operator->() const { return nullableValue; } + template + auto makeMatchExpr( ArgT const& arg, MatcherT const& matcher, StringRef matcherString ) -> MatchExpr { + return MatchExpr( arg, matcher, matcherString ); + } - T valueOr( T const& defaultValue ) const { - return nullableValue ? *nullableValue : defaultValue; - } +} // namespace Catch - bool some() const { return nullableValue != CATCH_NULL; } - bool none() const { return nullableValue == CATCH_NULL; } +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CHECK_THAT( macroName, matcher, resultDisposition, arg ) \ + do { \ + Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(arg) ", " CATCH_INTERNAL_STRINGIFY(matcher), resultDisposition ); \ + INTERNAL_CATCH_TRY( catchAssertionHandler ) { \ + catchAssertionHandler.handle( Catch::makeMatchExpr( arg, matcher, #matcher ) ); \ + } INTERNAL_CATCH_CATCH( catchAssertionHandler ) \ + INTERNAL_CATCH_REACT( catchAssertionHandler ) \ + } while( Catch::alwaysFalse() ) - bool operator !() const { return nullableValue == CATCH_NULL; } - operator SafeBool::type() const { - return SafeBool::makeSafe( some() ); - } +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_THROWS_MATCHES( macroName, exceptionType, resultDisposition, matcher, ... ) \ + do { \ + Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__) ", " CATCH_INTERNAL_STRINGIFY(exceptionType) ", " CATCH_INTERNAL_STRINGIFY(matcher), resultDisposition ); \ + if( catchAssertionHandler.allowThrows() ) \ + try { \ + static_cast(__VA_ARGS__ ); \ + catchAssertionHandler.handle( Catch::ResultWas::DidntThrowException ); \ + } \ + catch( exceptionType const& ex ) { \ + catchAssertionHandler.handle( Catch::makeMatchExpr( ex, matcher, #matcher ) ); \ + } \ + catch( ... ) { \ + catchAssertionHandler.useActiveException(); \ + } \ + else \ + catchAssertionHandler.handle( Catch::ResultWas::Ok ); \ + INTERNAL_CATCH_REACT( catchAssertionHandler ) \ + } while( Catch::alwaysFalse() ) - private: - T *nullableValue; - union { - char storage[sizeof(T)]; - - // These are here to force alignment for the storage - long double dummy1; - void (*dummy2)(); - long double dummy3; -#ifdef CATCH_CONFIG_CPP11_LONG_LONG - long long dummy4; +// end catch_capture_matchers.h #endif - }; - }; - -} // end 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; - - static ITagAliasRegistry const& get(); - }; - -} // end namespace Catch // These files are included here so the single_include script doesn't put them // in the conditionally compiled sections -// #included from: internal/catch_test_case_info.h -#define TWOBLUECUBES_CATCH_TEST_CASE_INFO_H_INCLUDED +// start catch_test_case_info.h #include -#include +#include +#include #ifdef __clang__ #pragma clang diagnostic push @@ -3235,7 +2376,7 @@ namespace Catch { namespace Catch { - struct ITestCase; + struct ITestInvoker; struct TestCaseInfo { enum SpecialProperties{ @@ -3244,30 +2385,30 @@ namespace Catch { ShouldFail = 1 << 2, MayFail = 1 << 3, Throws = 1 << 4, - NonPortable = 1 << 5 + NonPortable = 1 << 5, + Benchmark = 1 << 6 }; TestCaseInfo( std::string const& _name, std::string const& _className, std::string const& _description, - std::set const& _tags, + std::vector const& _tags, SourceLineInfo const& _lineInfo ); - TestCaseInfo( TestCaseInfo const& other ); - - friend void setTags( TestCaseInfo& testCaseInfo, std::set const& tags ); + friend void setTags( TestCaseInfo& testCaseInfo, std::vector tags ); bool isHidden() const; bool throws() const; bool okToFail() const; bool expectedToFail() const; + std::string tagsAsString() const; + std::string name; std::string className; std::string description; - std::set tags; - std::set lcaseTags; - std::string tagsAsString; + std::vector tags; + std::vector lcaseTags; SourceLineInfo lineInfo; SpecialProperties properties; }; @@ -3275,8 +2416,7 @@ namespace Catch { class TestCase : public TestCaseInfo { public: - TestCase( ITestCase* testCase, TestCaseInfo const& info ); - TestCase( TestCase const& other ); + TestCase( ITestInvoker* testCase, TestCaseInfo const& info ); TestCase withName( std::string const& _newName ) const; @@ -3284,16 +2424,14 @@ namespace Catch { 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; + std::shared_ptr test; }; - TestCase makeTestCase( ITestCase* testCase, + TestCase makeTestCase( ITestInvoker* testCase, std::string const& className, std::string const& name, std::string const& description, @@ -3304,10 +2442,21 @@ namespace Catch { #pragma clang diagnostic pop #endif +// end catch_test_case_info.h +// start catch_interfaces_runner.h + +namespace Catch { + + struct IRunner { + virtual ~IRunner(); + virtual bool aborting() const = 0; + }; +} + +// end catch_interfaces_runner.h #ifdef __OBJC__ -// #included from: internal/catch_objc.hpp -#define TWOBLUECUBES_CATCH_OBJC_HPP_INCLUDED +// start catch_objc.hpp #import @@ -3331,7 +2480,7 @@ namespace Catch { namespace Catch { - class OcMethod : public SharedImpl { + class OcMethod : public ITestInvoker { public: OcMethod( Class cls, SEL sel ) : m_cls( cls ), m_sel( sel ) {} @@ -3367,9 +2516,9 @@ namespace Catch { } } - inline size_t registerTestMethods() { - size_t noTestMethods = 0; - int noClasses = objc_getClassList( CATCH_NULL, 0 ); + inline std::size_t registerTestMethods() { + std::size_t noTestMethods = 0; + int noClasses = objc_getClassList( nullptr, 0 ); Class* classes = (CATCH_UNSAFE_UNRETAINED Class *)malloc( sizeof(Class) * noClasses); objc_getClassList( classes, noClasses ); @@ -3388,7 +2537,7 @@ namespace Catch { 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() ) ); + getMutableRegistryHub().registerTest( makeTestCase( new OcMethod( cls, selector ), className, name.c_str(), desc.c_str(), SourceLineInfo("",0) ) ); noTestMethods++; } } @@ -3398,6 +2547,8 @@ namespace Catch { return noTestMethods; } +#if !defined(CATCH_CONFIG_DISABLE_MATCHERS) + namespace Matchers { namespace Impl { namespace NSStringMatchers { @@ -3409,61 +2560,61 @@ namespace Catch { arcSafeRelease( m_substr ); } - virtual bool match( NSString* arg ) const CATCH_OVERRIDE { + bool match( NSString* arg ) const override { return false; } - NSString* m_substr; + NSString* CATCH_ARC_STRONG m_substr; }; struct Equals : StringHolder { Equals( NSString* substr ) : StringHolder( substr ){} - virtual bool match( NSString* str ) const CATCH_OVERRIDE { + bool match( NSString* str ) const override { return (str != nil || m_substr == nil ) && [str isEqualToString:m_substr]; } - virtual std::string describe() const CATCH_OVERRIDE { - return "equals string: " + Catch::toString( m_substr ); + std::string describe() const override { + return "equals string: " + Catch::Detail::stringify( m_substr ); } }; struct Contains : StringHolder { Contains( NSString* substr ) : StringHolder( substr ){} - virtual bool match( NSString* str ) const { + bool match( NSString* str ) const { return (str != nil || m_substr == nil ) && [str rangeOfString:m_substr].location != NSNotFound; } - virtual std::string describe() const CATCH_OVERRIDE { - return "contains string: " + Catch::toString( m_substr ); + std::string describe() const override { + return "contains string: " + Catch::Detail::stringify( m_substr ); } }; struct StartsWith : StringHolder { StartsWith( NSString* substr ) : StringHolder( substr ){} - virtual bool match( NSString* str ) const { + bool match( NSString* str ) const override { return (str != nil || m_substr == nil ) && [str rangeOfString:m_substr].location == 0; } - virtual std::string describe() const CATCH_OVERRIDE { - return "starts with: " + Catch::toString( m_substr ); + std::string describe() const override { + return "starts with: " + Catch::Detail::stringify( m_substr ); } }; struct EndsWith : StringHolder { EndsWith( NSString* substr ) : StringHolder( substr ){} - virtual bool match( NSString* str ) const { + bool match( NSString* str ) const override { return (str != nil || m_substr == nil ) && [str rangeOfString:m_substr].location == [str length] - [m_substr length]; } - virtual std::string describe() const CATCH_OVERRIDE { - return "ends with: " + Catch::toString( m_substr ); + std::string describe() const override { + return "ends with: " + Catch::Detail::stringify( m_substr ); } }; @@ -3486,86 +2637,52 @@ namespace Catch { using namespace Matchers; +#endif // CATCH_CONFIG_DISABLE_MATCHERS + } // namespace Catch /////////////////////////////////////////////////////////////////////////////// -#define OC_TEST_CASE( name, desc )\ -+(NSString*) INTERNAL_CATCH_UNIQUE_NAME( Catch_Name_test ) \ -{\ +#define OC_MAKE_UNIQUE_NAME( root, uniqueSuffix ) root##uniqueSuffix +#define OC_TEST_CASE2( name, desc, uniqueSuffix ) \ ++(NSString*) OC_MAKE_UNIQUE_NAME( Catch_Name_test_, uniqueSuffix ) \ +{ \ return @ name; \ -}\ -+(NSString*) INTERNAL_CATCH_UNIQUE_NAME( Catch_Description_test ) \ +} \ ++(NSString*) OC_MAKE_UNIQUE_NAME( Catch_Description_test_, uniqueSuffix ) \ { \ return @ desc; \ } \ --(void) INTERNAL_CATCH_UNIQUE_NAME( Catch_TestCase_test ) +-(void) OC_MAKE_UNIQUE_NAME( Catch_TestCase_test_, uniqueSuffix ) +#define OC_TEST_CASE( name, desc ) OC_TEST_CASE2( name, desc, __LINE__ ) + +// end catch_objc.hpp #endif -#ifdef CATCH_IMPL +#ifdef CATCH_CONFIG_EXTERNAL_INTERFACES +// start catch_external_interfaces.h -// !TBD: Move the leak detector code into a separate header -#ifdef CATCH_CONFIG_WINDOWS_CRTDBG -#include -class LeakDetector { -public: - LeakDetector() { - int flag = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG); - flag |= _CRTDBG_LEAK_CHECK_DF; - flag |= _CRTDBG_ALLOC_MEM_DF; - _CrtSetDbgFlag(flag); - _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG); - _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR); - // Change this to leaking allocation's number to break there - _CrtSetBreakAlloc(-1); - } -}; -#else -class LeakDetector {}; -#endif +// start catch_reporter_bases.hpp -LeakDetector leakDetector; +// start catch_interfaces_reporter.h -// #included from: internal/catch_impl.hpp -#define TWOBLUECUBES_CATCH_IMPL_HPP_INCLUDED +// start catch_config.hpp -// Collect all the implementation files together here -// These are the equivalent of what would usually be cpp files - -#ifdef __clang__ -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wweak-vtables" -#endif - -// #included from: ../catch_session.hpp -#define TWOBLUECUBES_CATCH_RUNNER_HPP_INCLUDED - -// #included from: internal/catch_commandline.hpp -#define TWOBLUECUBES_CATCH_COMMANDLINE_HPP_INCLUDED - -// #included from: catch_config.hpp -#define TWOBLUECUBES_CATCH_CONFIG_HPP_INCLUDED - -// #included from: catch_test_spec_parser.hpp -#define TWOBLUECUBES_CATCH_TEST_SPEC_PARSER_HPP_INCLUDED +// start catch_test_spec_parser.h #ifdef __clang__ #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wpadded" #endif -// #included from: catch_test_spec.hpp -#define TWOBLUECUBES_CATCH_TEST_SPEC_HPP_INCLUDED +// start catch_test_spec.h #ifdef __clang__ #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wpadded" #endif -// #included from: catch_wildcard_pattern.hpp -#define TWOBLUECUBES_CATCH_WILDCARD_PATTERN_HPP_INCLUDED - -#include +// start catch_wildcard_pattern.h namespace Catch { @@ -3579,119 +2696,68 @@ namespace Catch public: - WildcardPattern( std::string const& pattern, CaseSensitive::Choice caseSensitivity ) - : m_caseSensitivity( caseSensitivity ), - m_wildcard( NoWildcard ), - m_pattern( adjustCase( pattern ) ) - { - if( startsWith( m_pattern, '*' ) ) { - m_pattern = m_pattern.substr( 1 ); - m_wildcard = WildcardAtStart; - } - if( endsWith( m_pattern, '*' ) ) { - m_pattern = m_pattern.substr( 0, m_pattern.size()-1 ); - m_wildcard = static_cast( m_wildcard | WildcardAtEnd ); - } - } - virtual ~WildcardPattern(); - virtual bool matches( std::string const& str ) const { - switch( m_wildcard ) { - case NoWildcard: - return m_pattern == adjustCase( str ); - case WildcardAtStart: - return endsWith( adjustCase( str ), m_pattern ); - case WildcardAtEnd: - return startsWith( adjustCase( str ), m_pattern ); - case WildcardAtBothEnds: - return contains( adjustCase( str ), m_pattern ); - } + WildcardPattern( std::string const& pattern, CaseSensitive::Choice caseSensitivity ); + virtual ~WildcardPattern() = default; + virtual bool matches( std::string const& str ) const; -#ifdef __clang__ -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wunreachable-code" -#endif - throw std::logic_error( "Unknown enum" ); -#ifdef __clang__ -#pragma clang diagnostic pop -#endif - } private: - std::string adjustCase( std::string const& str ) const { - return m_caseSensitivity == CaseSensitive::No ? toLower( str ) : str; - } + std::string adjustCase( std::string const& str ) const; CaseSensitive::Choice m_caseSensitivity; - WildcardPosition m_wildcard; + WildcardPosition m_wildcard = NoWildcard; std::string m_pattern; }; } +// end catch_wildcard_pattern.h #include #include +#include namespace Catch { class TestSpec { - struct Pattern : SharedImpl<> { + struct Pattern { virtual ~Pattern(); virtual bool matches( TestCaseInfo const& testCase ) const = 0; }; + using PatternPtr = std::shared_ptr; + class NamePattern : public Pattern { public: - NamePattern( std::string const& name ) - : m_wildcardPattern( toLower( name ), CaseSensitive::No ) - {} + NamePattern( std::string const& name ); virtual ~NamePattern(); - virtual bool matches( TestCaseInfo const& testCase ) const { - return m_wildcardPattern.matches( toLower( testCase.name ) ); - } + virtual bool matches( TestCaseInfo const& testCase ) const override; private: WildcardPattern m_wildcardPattern; }; class TagPattern : public Pattern { public: - TagPattern( std::string const& tag ) : m_tag( toLower( tag ) ) {} + TagPattern( std::string const& tag ); virtual ~TagPattern(); - virtual bool matches( TestCaseInfo const& testCase ) const { - return testCase.lcaseTags.find( m_tag ) != testCase.lcaseTags.end(); - } + virtual bool matches( TestCaseInfo const& testCase ) const override; private: std::string m_tag; }; class ExcludedPattern : public Pattern { public: - ExcludedPattern( Ptr const& underlyingPattern ) : m_underlyingPattern( underlyingPattern ) {} + ExcludedPattern( PatternPtr const& underlyingPattern ); virtual ~ExcludedPattern(); - virtual bool matches( TestCaseInfo const& testCase ) const { return !m_underlyingPattern->matches( testCase ); } + virtual bool matches( TestCaseInfo const& testCase ) const override; private: - Ptr m_underlyingPattern; + PatternPtr m_underlyingPattern; }; struct Filter { - std::vector > m_patterns; + 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; - } + bool matches( TestCaseInfo const& testCase ) const; }; 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; - } + bool hasFilters() const; + bool matches( TestCaseInfo const& testCase ) const; private: std::vector m_filters; @@ -3704,87 +2770,56 @@ namespace Catch { #pragma clang diagnostic pop #endif +// end catch_test_spec.h +// start catch_interfaces_tag_alias_registry.h + +#include + +namespace Catch { + + struct TagAlias; + + struct ITagAliasRegistry { + virtual ~ITagAliasRegistry(); + // Nullptr if not present + virtual TagAlias const* find( std::string const& alias ) const = 0; + virtual std::string expandAliases( std::string const& unexpandedTestSpec ) const = 0; + + static ITagAliasRegistry const& get(); + }; + +} // end namespace Catch + +// end catch_interfaces_tag_alias_registry.h namespace Catch { class TestSpecParser { enum Mode{ None, Name, QuotedName, Tag, EscapedName }; - Mode m_mode; - bool m_exclusion; - std::size_t m_start, m_pos; + Mode m_mode = None; + bool m_exclusion = false; + std::size_t m_start = std::string::npos, m_pos = 0; std::string m_arg; std::vector m_escapeChars; TestSpec::Filter m_currentFilter; TestSpec m_testSpec; - ITagAliasRegistry const* m_tagAliases; + ITagAliasRegistry const* m_tagAliases = nullptr; public: - TestSpecParser( ITagAliasRegistry const& tagAliases ) :m_mode(None), m_exclusion(false), m_start(0), m_pos(0), m_tagAliases( &tagAliases ) {} + TestSpecParser( ITagAliasRegistry const& tagAliases ); + + TestSpecParser& parse( std::string const& arg ); + TestSpec testSpec(); - TestSpecParser& parse( std::string const& arg ) { - m_mode = None; - m_exclusion = false; - m_start = std::string::npos; - m_arg = m_tagAliases->expandAliases( arg ); - m_escapeChars.clear(); - 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 ); - case '\\': return escape(); - default: startNewMode( Name, m_pos ); break; - } - } - if( m_mode == Name ) { - if( c == ',' ) { - addPattern(); - addFilter(); - } - else if( c == '[' ) { - if( subString() == "exclude:" ) - m_exclusion = true; - else - addPattern(); - startNewMode( Tag, ++m_pos ); - } - else if( c == '\\' ) - escape(); - } - else if( m_mode == EscapedName ) - m_mode = Name; - 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; - } - void escape() { - if( m_mode == None ) - m_start = m_pos; - m_mode = EscapedName; - m_escapeChars.push_back( m_pos ); - } - std::string subString() const { return m_arg.substr( m_start, m_pos - m_start ); } + void visitChar( char c ); + void startNewMode( Mode mode, std::size_t start ); + void escape(); + std::string subString() const; + template void addPattern() { std::string token = subString(); - for( size_t i = 0; i < m_escapeChars.size(); ++i ) + for( std::size_t i = 0; i < m_escapeChars.size(); ++i ) token = token.substr( 0, m_escapeChars[i]-m_start-i ) + token.substr( m_escapeChars[i]-m_start-i+1 ); m_escapeChars.clear(); if( startsWith( token, "exclude:" ) ) { @@ -3792,24 +2827,18 @@ namespace Catch { token = token.substr( 8 ); } if( !token.empty() ) { - Ptr pattern = new T( token ); + TestSpec::PatternPtr pattern = std::make_shared( token ); if( m_exclusion ) - pattern = new TestSpec::ExcludedPattern( pattern ); + pattern = std::make_shared( 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(); - } - } + + void addFilter(); }; - inline TestSpec parseTestSpec( std::string const& arg ) { - return TestSpecParser( ITagAliasRegistry::get() ).parse( arg ).testSpec(); - } + TestSpec parseTestSpec( std::string const& arg ); } // namespace Catch @@ -3817,20 +2846,21 @@ namespace Catch { #pragma clang diagnostic pop #endif -// #included from: catch_interfaces_config.h -#define TWOBLUECUBES_CATCH_INTERFACES_CONFIG_H_INCLUDED +// end catch_test_spec_parser.h +// start catch_interfaces_config.h #include #include #include +#include namespace Catch { - struct Verbosity { enum Level { - NoOutput = 0, - Quiet, - Normal - }; }; + enum class Verbosity { + Quiet = 0, + Normal, + High + }; struct WarnAbout { enum What { Nothing = 0x00, @@ -3852,10 +2882,16 @@ namespace Catch { Yes, No }; }; + struct WaitForKeypress { enum When { + Never, + BeforeStart = 1, + BeforeExit = 2, + BeforeStartAndExit = BeforeStart | BeforeExit + }; }; class TestSpec; - struct IConfig : IShared { + struct IConfig : NonCopyable { virtual ~IConfig(); @@ -3871,17 +2907,20 @@ namespace Catch { virtual TestSpec const& testSpec() const = 0; virtual RunTests::InWhatOrder runOrder() const = 0; virtual unsigned int rngSeed() const = 0; + virtual int benchmarkResolutionMultiple() const = 0; virtual UseColour::YesOrNo useColour() const = 0; virtual std::vector const& getSectionsToRun() const = 0; - + virtual Verbosity verbosity() const = 0; }; + + using IConfigPtr = std::shared_ptr; } -// #included from: catch_stream.h -#define TWOBLUECUBES_CATCH_STREAM_H_INCLUDED +// end catch_interfaces_config.h +// Libstdc++ doesn't like incomplete classes for unique_ptr +// start catch_stream.h -// #included from: catch_streambuf.h -#define TWOBLUECUBES_CATCH_STREAMBUF_H_INCLUDED +// start catch_streambuf.h #include @@ -3889,10 +2928,11 @@ namespace Catch { class StreamBufBase : public std::streambuf { public: - virtual ~StreamBufBase() CATCH_NOEXCEPT; + virtual ~StreamBufBase(); }; } +// end catch_streambuf.h #include #include #include @@ -3905,7 +2945,7 @@ namespace Catch { std::ostream& clog(); struct IStream { - virtual ~IStream() CATCH_NOEXCEPT; + virtual ~IStream(); virtual std::ostream& stream() const = 0; }; @@ -3913,37 +2953,38 @@ namespace Catch { mutable std::ofstream m_ofs; public: FileStream( std::string const& filename ); - virtual ~FileStream() CATCH_NOEXCEPT; + ~FileStream() override = default; public: // IStream - virtual std::ostream& stream() const CATCH_OVERRIDE; + std::ostream& stream() const override; }; class CoutStream : public IStream { mutable std::ostream m_os; public: CoutStream(); - virtual ~CoutStream() CATCH_NOEXCEPT; + ~CoutStream() override = default; public: // IStream - virtual std::ostream& stream() const CATCH_OVERRIDE; + std::ostream& stream() const override; }; class DebugOutStream : public IStream { - CATCH_AUTO_PTR( StreamBufBase ) m_streamBuf; + std::unique_ptr m_streamBuf; mutable std::ostream m_os; public: DebugOutStream(); - virtual ~DebugOutStream() CATCH_NOEXCEPT; + ~DebugOutStream() override = default; public: // IStream - virtual std::ostream& stream() const CATCH_OVERRIDE; + std::ostream& stream() const override; }; } +// end catch_stream.h + #include #include #include -#include #ifndef CATCH_CONFIG_CONSOLE_WIDTH #define CATCH_CONFIG_CONSOLE_WIDTH 80 @@ -3951,50 +2992,32 @@ namespace Catch { namespace Catch { + struct IStream; + struct ConfigData { + bool listTests = false; + bool listTags = false; + bool listReporters = false; + bool listTestNamesOnly = false; - ConfigData() - : listTests( false ), - listTags( false ), - listReporters( false ), - listTestNamesOnly( false ), - listExtraInfo( false ), - showSuccessfulTests( false ), - shouldDebugBreak( false ), - noThrow( false ), - showHelp( false ), - showInvisibles( false ), - filenamesAsTags( false ), - abortAfter( -1 ), - rngSeed( 0 ), - verbosity( Verbosity::Normal ), - warnings( WarnAbout::Nothing ), - showDurations( ShowDurations::DefaultForReporter ), - runOrder( RunTests::InDeclarationOrder ), - useColour( UseColour::Auto ) - {} + bool showSuccessfulTests = false; + bool shouldDebugBreak = false; + bool noThrow = false; + bool showHelp = false; + bool showInvisibles = false; + bool filenamesAsTags = false; + bool libIdentify = false; - bool listTests; - bool listTags; - bool listReporters; - bool listTestNamesOnly; - bool listExtraInfo; + int abortAfter = -1; + unsigned int rngSeed = 0; + int benchmarkResolutionMultiple = 100; - bool showSuccessfulTests; - bool shouldDebugBreak; - bool noThrow; - bool showHelp; - bool showInvisibles; - bool filenamesAsTags; - - int abortAfter; - unsigned int rngSeed; - - Verbosity::Level verbosity; - WarnAbout::What warnings; - ShowDurations::OrNot showDurations; - RunTests::InWhatOrder runOrder; - UseColour::YesOrNo useColour; + Verbosity verbosity = Verbosity::Normal; + WarnAbout::What warnings = WarnAbout::Nothing; + ShowDurations::OrNot showDurations = ShowDurations::DefaultForReporter; + RunTests::InWhatOrder runOrder = RunTests::InDeclarationOrder; + UseColour::YesOrNo useColour = UseColour::Auto; + WaitForKeypress::When waitForKeypress = WaitForKeypress::Never; std::string outputFilename; std::string name; @@ -4005,1505 +3028,638 @@ namespace Catch { std::vector sectionsToRun; }; - class Config : public SharedImpl { - private: - Config( Config const& other ); - Config& operator = ( Config const& other ); - virtual void dummy(); + class Config : public IConfig { public: - Config() - {} + Config() = default; + Config( ConfigData const& data ); + virtual ~Config() = default; - Config( ConfigData const& data ) - : m_data( data ), - m_stream( openStream() ) - { - if( !data.testsOrTags.empty() ) { - TestSpecParser parser( ITagAliasRegistry::get() ); - for( std::size_t i = 0; i < data.testsOrTags.size(); ++i ) - parser.parse( data.testsOrTags[i] ); - m_testSpec = parser.testSpec(); - } - } + std::string const& getFilename() const; - virtual ~Config() {} + bool listTests() const; + bool listTestNamesOnly() const; + bool listTags() const; + bool listReporters() const; - std::string const& getFilename() const { - return m_data.outputFilename ; - } + std::string getProcessName() const; - 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 listExtraInfo() const { return m_data.listExtraInfo; } + std::vector const& getReporterNames() const; + std::vector const& getSectionsToRun() const override; - std::string getProcessName() const { return m_data.processName; } + virtual TestSpec const& testSpec() const override; - std::vector const& getReporterNames() const { return m_data.reporterNames; } - std::vector const& getSectionsToRun() const CATCH_OVERRIDE { return m_data.sectionsToRun; } - - virtual TestSpec const& testSpec() const CATCH_OVERRIDE { return m_testSpec; } - - bool showHelp() const { return m_data.showHelp; } + bool showHelp() const; // IConfig interface - virtual bool allowThrows() const CATCH_OVERRIDE { return !m_data.noThrow; } - virtual std::ostream& stream() const CATCH_OVERRIDE { return m_stream->stream(); } - virtual std::string name() const CATCH_OVERRIDE { return m_data.name.empty() ? m_data.processName : m_data.name; } - virtual bool includeSuccessfulResults() const CATCH_OVERRIDE { return m_data.showSuccessfulTests; } - virtual bool warnAboutMissingAssertions() const CATCH_OVERRIDE { return m_data.warnings & WarnAbout::NoAssertions; } - virtual ShowDurations::OrNot showDurations() const CATCH_OVERRIDE { return m_data.showDurations; } - virtual RunTests::InWhatOrder runOrder() const CATCH_OVERRIDE { return m_data.runOrder; } - virtual unsigned int rngSeed() const CATCH_OVERRIDE { return m_data.rngSeed; } - virtual UseColour::YesOrNo useColour() const CATCH_OVERRIDE { return m_data.useColour; } - virtual bool shouldDebugBreak() const CATCH_OVERRIDE { return m_data.shouldDebugBreak; } - virtual int abortAfter() const CATCH_OVERRIDE { return m_data.abortAfter; } - virtual bool showInvisibles() const CATCH_OVERRIDE { return m_data.showInvisibles; } + bool allowThrows() const override; + std::ostream& stream() const override; + std::string name() const override; + bool includeSuccessfulResults() const override; + bool warnAboutMissingAssertions() const override; + ShowDurations::OrNot showDurations() const override; + RunTests::InWhatOrder runOrder() const override; + unsigned int rngSeed() const override; + int benchmarkResolutionMultiple() const override; + UseColour::YesOrNo useColour() const override; + bool shouldDebugBreak() const override; + int abortAfter() const override; + bool showInvisibles() const override; + Verbosity verbosity() const override; private: - IStream const* openStream() { - if( m_data.outputFilename.empty() ) - return new CoutStream(); - else if( m_data.outputFilename[0] == '%' ) { - if( m_data.outputFilename == "%debug" ) - return new DebugOutStream(); - else - throw std::domain_error( "Unrecognised stream: " + m_data.outputFilename ); - } - else - return new FileStream( m_data.outputFilename ); - } + IStream const* openStream(); ConfigData m_data; - CATCH_AUTO_PTR( IStream const ) m_stream; + std::unique_ptr m_stream; TestSpec m_testSpec; }; } // end namespace Catch -// #included from: catch_clara.h -#define TWOBLUECUBES_CATCH_CLARA_H_INCLUDED - -// Use Catch's value for console width (store Clara's off to the side, if present) -#ifdef CLARA_CONFIG_CONSOLE_WIDTH -#define CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH CLARA_CONFIG_CONSOLE_WIDTH -#undef CLARA_CONFIG_CONSOLE_WIDTH -#endif -#define CLARA_CONFIG_CONSOLE_WIDTH CATCH_CONFIG_CONSOLE_WIDTH - -// Declare Clara inside the Catch namespace -#define STITCH_CLARA_OPEN_NAMESPACE namespace Catch { -// #included from: ../external/clara.h - -// Version 0.0.2.4 - -// Only use header guard if we are not using an outer namespace -#if !defined(TWOBLUECUBES_CLARA_H_INCLUDED) || defined(STITCH_CLARA_OPEN_NAMESPACE) - -#ifndef STITCH_CLARA_OPEN_NAMESPACE -#define TWOBLUECUBES_CLARA_H_INCLUDED -#define STITCH_CLARA_OPEN_NAMESPACE -#define STITCH_CLARA_CLOSE_NAMESPACE -#else -#define STITCH_CLARA_CLOSE_NAMESPACE } -#endif - -#define STITCH_TBC_TEXT_FORMAT_OPEN_NAMESPACE STITCH_CLARA_OPEN_NAMESPACE - -// ----------- #included from tbc_text_format.h ----------- - -// Only use header guard if we are not using an outer namespace -#if !defined(TBC_TEXT_FORMAT_H_INCLUDED) || defined(STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE) -#ifndef STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE -#define TBC_TEXT_FORMAT_H_INCLUDED -#endif +// end catch_config.hpp +// start catch_assertionresult.h #include -#include -#include -#include -#include - -// Use optional outer namespace -#ifdef STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE -namespace STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE { -#endif - -namespace Tbc { - -#ifdef TBC_TEXT_FORMAT_CONSOLE_WIDTH - const unsigned int consoleWidth = TBC_TEXT_FORMAT_CONSOLE_WIDTH; -#else - const unsigned int consoleWidth = 80; -#endif - - struct TextAttributes { - TextAttributes() - : initialIndent( std::string::npos ), - indent( 0 ), - width( consoleWidth-1 ), - tabChar( '\t' ) - {} - - TextAttributes& setInitialIndent( std::size_t _value ) { initialIndent = _value; return *this; } - TextAttributes& setIndent( std::size_t _value ) { indent = _value; return *this; } - TextAttributes& setWidth( std::size_t _value ) { width = _value; return *this; } - TextAttributes& setTabChar( char _value ) { tabChar = _value; return *this; } - - std::size_t initialIndent; // indent of first line, or npos - std::size_t indent; // indent of subsequent lines, or all if initialIndent is npos - std::size_t width; // maximum width of text, including indent. Longer text will wrap - char tabChar; // If this char is seen the indent is changed to current pos - }; - - class Text { - public: - Text( std::string const& _str, TextAttributes const& _attr = TextAttributes() ) - : attr( _attr ) - { - std::string wrappableChars = " [({.,/|\\-"; - std::size_t indent = _attr.initialIndent != std::string::npos - ? _attr.initialIndent - : _attr.indent; - std::string remainder = _str; - - while( !remainder.empty() ) { - if( lines.size() >= 1000 ) { - lines.push_back( "... message truncated due to excessive size" ); - return; - } - std::size_t tabPos = std::string::npos; - std::size_t width = (std::min)( remainder.size(), _attr.width - indent ); - std::size_t pos = remainder.find_first_of( '\n' ); - if( pos <= width ) { - width = pos; - } - pos = remainder.find_last_of( _attr.tabChar, width ); - if( pos != std::string::npos ) { - tabPos = pos; - if( remainder[width] == '\n' ) - width--; - remainder = remainder.substr( 0, tabPos ) + remainder.substr( tabPos+1 ); - } - - if( width == remainder.size() ) { - spliceLine( indent, remainder, width ); - } - else if( remainder[width] == '\n' ) { - spliceLine( indent, remainder, width ); - if( width <= 1 || remainder.size() != 1 ) - remainder = remainder.substr( 1 ); - indent = _attr.indent; - } - else { - pos = remainder.find_last_of( wrappableChars, width ); - if( pos != std::string::npos && pos > 0 ) { - spliceLine( indent, remainder, pos ); - if( remainder[0] == ' ' ) - remainder = remainder.substr( 1 ); - } - else { - spliceLine( indent, remainder, width-1 ); - lines.back() += "-"; - } - if( lines.size() == 1 ) - indent = _attr.indent; - if( tabPos != std::string::npos ) - indent += tabPos; - } - } - } - - void spliceLine( std::size_t _indent, std::string& _remainder, std::size_t _pos ) { - lines.push_back( std::string( _indent, ' ' ) + _remainder.substr( 0, _pos ) ); - _remainder = _remainder.substr( _pos ); - } - - typedef std::vector::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(); - } - - 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 - -#ifdef STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE -} // end outer namespace -#endif - -#endif // TBC_TEXT_FORMAT_H_INCLUDED - -// ----------- end of #include from tbc_text_format.h ----------- -// ........... back in clara.h - -#undef STITCH_TBC_TEXT_FORMAT_OPEN_NAMESPACE - -// ----------- #included from clara_compilers.h ----------- - -#ifndef TWOBLUECUBES_CLARA_COMPILERS_H_INCLUDED -#define TWOBLUECUBES_CLARA_COMPILERS_H_INCLUDED - -// Detect a number of compiler features - mostly C++11/14 conformance - by compiler -// The following features are defined: -// -// CLARA_CONFIG_CPP11_NULLPTR : is nullptr supported? -// CLARA_CONFIG_CPP11_NOEXCEPT : is noexcept supported? -// CLARA_CONFIG_CPP11_GENERATED_METHODS : The delete and default keywords for compiler generated methods -// CLARA_CONFIG_CPP11_OVERRIDE : is override supported? -// CLARA_CONFIG_CPP11_UNIQUE_PTR : is unique_ptr supported (otherwise use auto_ptr) - -// CLARA_CONFIG_CPP11_OR_GREATER : Is C++11 supported? - -// CLARA_CONFIG_VARIADIC_MACROS : are variadic macros supported? - -// In general each macro has a _NO_ form -// (e.g. CLARA_CONFIG_CPP11_NO_NULLPTR) which disables the feature. -// Many features, at point of detection, define an _INTERNAL_ macro, so they -// can be combined, en-mass, with the _NO_ forms later. - -// All the C++11 features can be disabled with CLARA_CONFIG_NO_CPP11 - -#ifdef __clang__ - -#if __has_feature(cxx_nullptr) -#define CLARA_INTERNAL_CONFIG_CPP11_NULLPTR -#endif - -#if __has_feature(cxx_noexcept) -#define CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT -#endif - -#endif // __clang__ - -//////////////////////////////////////////////////////////////////////////////// -// GCC -#ifdef __GNUC__ - -#if __GNUC__ == 4 && __GNUC_MINOR__ >= 6 && defined(__GXX_EXPERIMENTAL_CXX0X__) -#define CLARA_INTERNAL_CONFIG_CPP11_NULLPTR -#endif - -// - otherwise more recent versions define __cplusplus >= 201103L -// and will get picked up below - -#endif // __GNUC__ - -//////////////////////////////////////////////////////////////////////////////// -// Visual C++ -#ifdef _MSC_VER - -#if (_MSC_VER >= 1600) -#define CLARA_INTERNAL_CONFIG_CPP11_NULLPTR -#define CLARA_INTERNAL_CONFIG_CPP11_UNIQUE_PTR -#endif - -#if (_MSC_VER >= 1900 ) // (VC++ 13 (VS2015)) -#define CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT -#define CLARA_INTERNAL_CONFIG_CPP11_GENERATED_METHODS -#endif - -#endif // _MSC_VER - -//////////////////////////////////////////////////////////////////////////////// -// C++ language feature support - -// catch all support for C++11 -#if defined(__cplusplus) && __cplusplus >= 201103L - -#define CLARA_CPP11_OR_GREATER - -#if !defined(CLARA_INTERNAL_CONFIG_CPP11_NULLPTR) -#define CLARA_INTERNAL_CONFIG_CPP11_NULLPTR -#endif - -#ifndef CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT -#define CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT -#endif - -#ifndef CLARA_INTERNAL_CONFIG_CPP11_GENERATED_METHODS -#define CLARA_INTERNAL_CONFIG_CPP11_GENERATED_METHODS -#endif - -#if !defined(CLARA_INTERNAL_CONFIG_CPP11_OVERRIDE) -#define CLARA_INTERNAL_CONFIG_CPP11_OVERRIDE -#endif -#if !defined(CLARA_INTERNAL_CONFIG_CPP11_UNIQUE_PTR) -#define CLARA_INTERNAL_CONFIG_CPP11_UNIQUE_PTR -#endif - -#endif // __cplusplus >= 201103L - -// Now set the actual defines based on the above + anything the user has configured -#if defined(CLARA_INTERNAL_CONFIG_CPP11_NULLPTR) && !defined(CLARA_CONFIG_CPP11_NO_NULLPTR) && !defined(CLARA_CONFIG_CPP11_NULLPTR) && !defined(CLARA_CONFIG_NO_CPP11) -#define CLARA_CONFIG_CPP11_NULLPTR -#endif -#if defined(CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT) && !defined(CLARA_CONFIG_CPP11_NO_NOEXCEPT) && !defined(CLARA_CONFIG_CPP11_NOEXCEPT) && !defined(CLARA_CONFIG_NO_CPP11) -#define CLARA_CONFIG_CPP11_NOEXCEPT -#endif -#if defined(CLARA_INTERNAL_CONFIG_CPP11_GENERATED_METHODS) && !defined(CLARA_CONFIG_CPP11_NO_GENERATED_METHODS) && !defined(CLARA_CONFIG_CPP11_GENERATED_METHODS) && !defined(CLARA_CONFIG_NO_CPP11) -#define CLARA_CONFIG_CPP11_GENERATED_METHODS -#endif -#if defined(CLARA_INTERNAL_CONFIG_CPP11_OVERRIDE) && !defined(CLARA_CONFIG_NO_OVERRIDE) && !defined(CLARA_CONFIG_CPP11_OVERRIDE) && !defined(CLARA_CONFIG_NO_CPP11) -#define CLARA_CONFIG_CPP11_OVERRIDE -#endif -#if defined(CLARA_INTERNAL_CONFIG_CPP11_UNIQUE_PTR) && !defined(CLARA_CONFIG_NO_UNIQUE_PTR) && !defined(CLARA_CONFIG_CPP11_UNIQUE_PTR) && !defined(CLARA_CONFIG_NO_CPP11) -#define CLARA_CONFIG_CPP11_UNIQUE_PTR -#endif - -// noexcept support: -#if defined(CLARA_CONFIG_CPP11_NOEXCEPT) && !defined(CLARA_NOEXCEPT) -#define CLARA_NOEXCEPT noexcept -# define CLARA_NOEXCEPT_IS(x) noexcept(x) -#else -#define CLARA_NOEXCEPT throw() -# define CLARA_NOEXCEPT_IS(x) -#endif - -// nullptr support -#ifdef CLARA_CONFIG_CPP11_NULLPTR -#define CLARA_NULL nullptr -#else -#define CLARA_NULL NULL -#endif - -// override support -#ifdef CLARA_CONFIG_CPP11_OVERRIDE -#define CLARA_OVERRIDE override -#else -#define CLARA_OVERRIDE -#endif - -// unique_ptr support -#ifdef CLARA_CONFIG_CPP11_UNIQUE_PTR -# define CLARA_AUTO_PTR( T ) std::unique_ptr -#else -# define CLARA_AUTO_PTR( T ) std::auto_ptr -#endif - -#endif // TWOBLUECUBES_CLARA_COMPILERS_H_INCLUDED - -// ----------- end of #include from clara_compilers.h ----------- -// ........... back in clara.h - -#include -#include -#include - -#if defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) -#define CLARA_PLATFORM_WINDOWS -#endif - -// Use optional outer namespace -#ifdef STITCH_CLARA_OPEN_NAMESPACE -STITCH_CLARA_OPEN_NAMESPACE -#endif - -namespace Clara { - - struct UnpositionalTag {}; - - extern UnpositionalTag _; - -#ifdef CLARA_CONFIG_MAIN - UnpositionalTag _; -#endif - - namespace Detail { - -#ifdef CLARA_CONSOLE_WIDTH - const unsigned int consoleWidth = CLARA_CONFIG_CONSOLE_WIDTH; -#else - const unsigned int consoleWidth = 80; -#endif - - using namespace Tbc; - - inline bool startsWith( std::string const& str, std::string const& prefix ) { - return str.size() >= prefix.size() && str.substr( 0, prefix.size() ) == prefix; - } - - template 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 - 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; - } - char toLowerCh(char c) { - return static_cast( std::tolower( c ) ); - } - inline void convertInto( std::string const& _source, bool& _dest ) { - std::string sourceLC = _source; - std::transform( sourceLC.begin(), sourceLC.end(), sourceLC.begin(), toLowerCh ); - 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 + "'" ); - } - - template - struct IArgFunction { - virtual ~IArgFunction() {} -#ifdef CLARA_CONFIG_CPP11_GENERATED_METHODS - IArgFunction() = default; - IArgFunction( IArgFunction const& ) = default; -#endif - virtual void set( ConfigT& config, std::string const& value ) const = 0; - virtual bool takesArg() const = 0; - virtual IArgFunction* clone() const = 0; - }; - - template - class BoundArgFunction { - public: - BoundArgFunction() : functionObj( CLARA_NULL ) {} - BoundArgFunction( IArgFunction* _functionObj ) : functionObj( _functionObj ) {} - BoundArgFunction( BoundArgFunction const& other ) : functionObj( other.functionObj ? other.functionObj->clone() : CLARA_NULL ) {} - BoundArgFunction& operator = ( BoundArgFunction const& other ) { - IArgFunction* newFunctionObj = other.functionObj ? other.functionObj->clone() : CLARA_NULL; - delete functionObj; - functionObj = newFunctionObj; - return *this; - } - ~BoundArgFunction() { delete functionObj; } - - void set( ConfigT& config, std::string const& value ) const { - functionObj->set( config, value ); - } - bool takesArg() const { return functionObj->takesArg(); } - - bool isSet() const { - return functionObj != CLARA_NULL; - } - private: - IArgFunction* functionObj; - }; - - template - struct NullBinder : IArgFunction{ - virtual void set( C&, std::string const& ) 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 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 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 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 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 bool takesArg() const { return !IsBool::value; } - virtual IArgFunction* clone() const { return new BoundBinaryFunction( *this ); } - void (*function)( C&, T ); - }; - - } // namespace Detail - - inline std::vector argsToVector( int argc, char const* const* const argv ) { - std::vector args( static_cast( argc ) ); - for( std::size_t i = 0; i < static_cast( argc ); ++i ) - args[i] = argv[i]; - - return args; - } - - class Parser { - enum Mode { None, MaybeShortOpt, SlashOpt, ShortOpt, LongOpt, Positional }; - Mode mode; - std::size_t from; - bool inQuotes; - public: - - struct Token { - enum Type { Positional, ShortOpt, LongOpt }; - Token( Type _type, std::string const& _data ) : type( _type ), data( _data ) {} - Type type; - std::string data; - }; - - Parser() : mode( None ), from( 0 ), inQuotes( false ){} - - void parseIntoTokens( std::vector const& args, std::vector& tokens ) { - const std::string doubleDash = "--"; - for( std::size_t i = 1; i < args.size() && args[i] != doubleDash; ++i ) - parseIntoTokens( args[i], tokens); - } - - void parseIntoTokens( std::string const& arg, std::vector& tokens ) { - for( std::size_t i = 0; i < arg.size(); ++i ) { - char c = arg[i]; - if( c == '"' ) - inQuotes = !inQuotes; - mode = handleMode( i, c, arg, tokens ); - } - mode = handleMode( arg.size(), '\0', arg, tokens ); - } - Mode handleMode( std::size_t i, char c, std::string const& arg, std::vector& tokens ) { - switch( mode ) { - case None: return handleNone( i, c ); - case MaybeShortOpt: return handleMaybeShortOpt( i, c ); - case ShortOpt: - case LongOpt: - case SlashOpt: return handleOpt( i, c, arg, tokens ); - case Positional: return handlePositional( i, c, arg, tokens ); - default: throw std::logic_error( "Unknown mode" ); - } - } - - Mode handleNone( std::size_t i, char c ) { - if( inQuotes ) { - from = i; - return Positional; - } - switch( c ) { - case '-': return MaybeShortOpt; -#ifdef CLARA_PLATFORM_WINDOWS - case '/': from = i+1; return SlashOpt; -#endif - default: from = i; return Positional; - } - } - Mode handleMaybeShortOpt( std::size_t i, char c ) { - switch( c ) { - case '-': from = i+1; return LongOpt; - default: from = i; return ShortOpt; - } - } - - Mode handleOpt( std::size_t i, char c, std::string const& arg, std::vector& tokens ) { - if( std::string( ":=\0", 3 ).find( c ) == std::string::npos ) - return mode; - - std::string optName = arg.substr( from, i-from ); - if( mode == ShortOpt ) - for( std::size_t j = 0; j < optName.size(); ++j ) - tokens.push_back( Token( Token::ShortOpt, optName.substr( j, 1 ) ) ); - else if( mode == SlashOpt && optName.size() == 1 ) - tokens.push_back( Token( Token::ShortOpt, optName ) ); - else - tokens.push_back( Token( Token::LongOpt, optName ) ); - return None; - } - Mode handlePositional( std::size_t i, char c, std::string const& arg, std::vector& tokens ) { - if( inQuotes || std::string( "\0", 1 ).find( c ) == std::string::npos ) - return mode; - - std::string data = arg.substr( from, i-from ); - tokens.push_back( Token( Token::Positional, data ) ); - return None; - } - }; - - 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 - - bool takesArg() const { - return !placeholder.empty(); - } - void validate() const { - if( !boundField.isSet() ) - throw std::logic_error( "option not bound" ); - } - }; - 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"; - } - 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(); - } - }; - - typedef CLARA_AUTO_PTR( Arg ) ArgAutoPtr; - - friend void addOptName( Arg& arg, std::string const& optName ) - { - if( optName.empty() ) - return; - if( Detail::startsWith( optName, "--" ) ) { - if( !arg.longName.empty() ) - throw std::logic_error( "Only one long opt may be specified. '" - + arg.longName - + "' already specified, now attempting to add '" - + optName + "'" ); - arg.longName = optName.substr( 2 ); - } - else if( Detail::startsWith( optName, "-" ) ) - arg.shortNames.push_back( optName.substr( 1 ) ); - else - throw std::logic_error( "option must begin with - or --. Option was: '" + optName + "'" ); - } - friend void setPositionalArg( Arg& arg, int position ) - { - arg.position = position; - } - - class ArgBuilder { - public: - ArgBuilder( Arg* arg ) : m_arg( arg ) {} - - // Bind a non-boolean data member (requires placeholder string) - template - 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 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 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 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 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 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; - } - - ArgBuilder& describe( std::string const& description ) { - m_arg->description = description; - return *this; - } - ArgBuilder& detail( std::string const& detail ) { - m_arg->detail = detail; - return *this; - } - - protected: - Arg* m_arg; - }; - - class OptBuilder : public ArgBuilder { - public: - OptBuilder( Arg* arg ) : ArgBuilder( arg ) {} - OptBuilder( OptBuilder& other ) : ArgBuilder( other ) {} - - OptBuilder& operator[]( std::string const& optName ) { - addOptName( *ArgBuilder::m_arg, optName ); - return *this; - } - }; - - public: - - CommandLine() - : m_boundProcessName( new Detail::NullBinder() ), - m_highestSpecifiedArgPosition( 0 ), - m_throwOnUnrecognisedTokens( false ) - {} - CommandLine( CommandLine const& other ) - : m_boundProcessName( other.m_boundProcessName ), - m_options ( other.m_options ), - m_positionalArgs( other.m_positionalArgs ), - m_highestSpecifiedArgPosition( other.m_highestSpecifiedArgPosition ), - m_throwOnUnrecognisedTokens( other.m_throwOnUnrecognisedTokens ) - { - if( other.m_floatingArg.get() ) - m_floatingArg.reset( new Arg( *other.m_floatingArg ) ); - } - - CommandLine& setThrowOnUnrecognisedTokens( bool shouldThrow = true ) { - m_throwOnUnrecognisedTokens = shouldThrow; - return *this; - } - - OptBuilder operator[]( std::string const& optName ) { - m_options.push_back( Arg() ); - addOptName( m_options.back(), optName ); - OptBuilder builder( &m_options.back() ); - return builder; - } - - ArgBuilder operator[]( int position ) { - m_positionalArgs.insert( std::make_pair( position, Arg() ) ); - if( position > m_highestSpecifiedArgPosition ) - m_highestSpecifiedArgPosition = position; - setPositionalArg( m_positionalArgs[position], position ); - ArgBuilder builder( &m_positionalArgs[position] ); - return builder; - } - - // Invoke this with the _ instance - ArgBuilder operator[]( UnpositionalTag ) { - if( m_floatingArg.get() ) - throw std::logic_error( "Only one unpositional argument can be added" ); - m_floatingArg.reset( new Arg() ); - ArgBuilder builder( m_floatingArg.get() ); - return builder; - } - - template - 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(); - } - - 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" ); - } - // !TBD No indication of mandatory args - if( m_floatingArg.get() ) { - if( m_highestSpecifiedArgPosition > 1 ) - os << " "; - os << "[<" << m_floatingArg->placeholder << "> ...]"; - } - } - std::string argSynopsis() const { - std::ostringstream oss; - argSynopsis( oss ); - return oss.str(); - } - - void usage( std::ostream& os, std::string const& procName ) const { - validate(); - os << "usage:\n " << procName << " "; - argSynopsis( os ); - if( !m_options.empty() ) { - os << " [options]\n\nwhere options are: \n"; - optUsage( os, 2 ); - } - os << "\n"; - } - std::string usage( std::string const& procName ) const { - std::ostringstream oss; - usage( oss, procName ); - return oss.str(); - } - - ConfigT parse( std::vector const& args ) const { - ConfigT config; - parseInto( args, config ); - return config; - } - - std::vector parseInto( std::vector const& args, ConfigT& config ) const { - std::string processName = args.empty() ? std::string() : args[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( args, 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 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, "true" ); - } - break; - } - } - catch( std::exception& ex ) { - errors.push_back( std::string( ex.what() ) + "\n- while parsing: (" + arg.commands() + ")" ); - } - } - if( it == itEnd ) { - if( token.type == Parser::Token::Positional || !m_throwOnUnrecognisedTokens ) - unusedTokens.push_back( token ); - else if( errors.empty() && m_throwOnUnrecognisedTokens ) - errors.push_back( "unrecognised option: " + token.data ); - } - } - if( !errors.empty() ) { - std::ostringstream oss; - for( std::vector::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 ); - 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" ); - - 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 - -STITCH_CLARA_CLOSE_NAMESPACE -#undef STITCH_CLARA_OPEN_NAMESPACE -#undef STITCH_CLARA_CLOSE_NAMESPACE - -#endif // TWOBLUECUBES_CLARA_H_INCLUDED -#undef STITCH_CLARA_OPEN_NAMESPACE - -// Restore Clara's value for console width, if present -#ifdef CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH -#define CLARA_CONFIG_CONSOLE_WIDTH CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH -#undef CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH -#endif - -#include -#include namespace Catch { - inline void abortAfterFirst( ConfigData& config ) { config.abortAfter = 1; } - inline void abortAfterX( ConfigData& config, int x ) { - if( x < 1 ) - throw std::runtime_error( "Value after -x or --abortAfter must be greater than zero" ); - config.abortAfter = x; - } - inline void addTestOrTags( ConfigData& config, std::string const& _testSpec ) { config.testsOrTags.push_back( _testSpec ); } - inline void addSectionToRun( ConfigData& config, std::string const& sectionName ) { config.sectionsToRun.push_back( sectionName ); } - inline void addReporterName( ConfigData& config, std::string const& _reporterName ) { config.reporterNames.push_back( _reporterName ); } + struct AssertionResultData + { + AssertionResultData() = delete; - 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 setOrder( ConfigData& config, std::string const& order ) { - if( startsWith( "declared", order ) ) - config.runOrder = RunTests::InDeclarationOrder; - else if( startsWith( "lexical", order ) ) - config.runOrder = RunTests::InLexicographicalOrder; - else if( startsWith( "random", order ) ) - config.runOrder = RunTests::InRandomOrder; - else - throw std::runtime_error( "Unrecognised ordering: '" + order + '\'' ); - } - inline void setRngSeed( ConfigData& config, std::string const& seed ) { - if( seed == "time" ) { - config.rngSeed = static_cast( std::time(0) ); - } - else { - std::stringstream ss; - ss << seed; - ss >> config.rngSeed; - if( ss.fail() ) - throw std::runtime_error( "Argument to --rng-seed should be the word 'time' or a number" ); - } - } - inline void setVerbosity( ConfigData& config, int level ) { - // !TBD: accept strings? - config.verbosity = static_cast( level ); - } - inline void setShowDurations( ConfigData& config, bool _showDurations ) { - config.showDurations = _showDurations - ? ShowDurations::Always - : ShowDurations::Never; - } - inline void setUseColour( ConfigData& config, std::string const& value ) { - std::string mode = toLower( value ); + AssertionResultData( ResultWas::OfType _resultType, LazyExpression const& _lazyExpression ); - if( mode == "yes" ) - config.useColour = UseColour::Yes; - else if( mode == "no" ) - config.useColour = UseColour::No; - else if( mode == "auto" ) - config.useColour = UseColour::Auto; - else - throw std::runtime_error( "colour mode must be one of: auto, yes or no" ); - } - inline void forceColour( ConfigData& config ) { - config.useColour = UseColour::Yes; - } - inline void loadTestNamesFromFile( ConfigData& config, std::string const& _filename ) { - std::ifstream f( _filename.c_str() ); - if( !f.is_open() ) - throw std::domain_error( "Unable to load input file: " + _filename ); + std::string message; + mutable std::string reconstructedExpression; + LazyExpression lazyExpression; + ResultWas::OfType resultType; - std::string line; - while( std::getline( f, line ) ) { - line = trim(line); - if( !line.empty() && !startsWith( line, '#' ) ) { - if( !startsWith( line, '"' ) ) - line = '"' + line + '"'; - addTestOrTags( config, line + ',' ); - } - } - } + std::string reconstructExpression() const; + }; - inline Clara::CommandLine makeCommandLineParser() { + class AssertionResult { + public: + AssertionResult() = delete; + AssertionResult( AssertionInfo const& info, AssertionResultData const& data ); - using namespace Clara; - CommandLine cli; + 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; - cli.bindProcessName( &ConfigData::processName ); - - cli["-?"]["-h"]["--help"] - .describe( "display usage information" ) - .bind( &ConfigData::showHelp ); - - cli["-l"]["--list-tests"] - .describe( "list all/matching test cases" ) - .bind( &ConfigData::listTests ); - - cli["-t"]["--list-tags"] - .describe( "list all/matching tags" ) - .bind( &ConfigData::listTags ); - - cli["-s"]["--success"] - .describe( "include successful tests in output" ) - .bind( &ConfigData::showSuccessfulTests ); - - cli["-b"]["--break"] - .describe( "break into debugger on failure" ) - .bind( &ConfigData::shouldDebugBreak ); - - cli["-e"]["--nothrow"] - .describe( "skip exception tests" ) - .bind( &ConfigData::noThrow ); - - cli["-i"]["--invisibles"] - .describe( "show invisibles (tabs, newlines)" ) - .bind( &ConfigData::showInvisibles ); - - cli["-o"]["--out"] - .describe( "output filename" ) - .bind( &ConfigData::outputFilename, "filename" ); - - cli["-r"]["--reporter"] -// .placeholder( "name[:filename]" ) - .describe( "reporter to use (defaults to console)" ) - .bind( &addReporterName, "name" ); - - cli["-n"]["--name"] - .describe( "suite name" ) - .bind( &ConfigData::name, "name" ); - - cli["-a"]["--abort"] - .describe( "abort at first failure" ) - .bind( &abortAfterFirst ); - - cli["-x"]["--abortx"] - .describe( "abort after x failures" ) - .bind( &abortAfterX, "no. failures" ); - - cli["-w"]["--warn"] - .describe( "enable warnings" ) - .bind( &addWarning, "warning name" ); - -// - needs updating if reinstated -// cli.into( &setVerbosity ) -// .describe( "level of verbosity (0=no output)" ) -// .shortOpt( "v") -// .longOpt( "verbosity" ) -// .placeholder( "level" ); - - cli[_] - .describe( "which test or tests to use" ) - .bind( &addTestOrTags, "test name, pattern or tags" ); - - cli["-d"]["--durations"] - .describe( "show test durations" ) - .bind( &setShowDurations, "yes|no" ); - - cli["-f"]["--input-file"] - .describe( "load test names to run from a file" ) - .bind( &loadTestNamesFromFile, "filename" ); - - cli["-#"]["--filenames-as-tags"] - .describe( "adds a tag for the filename" ) - .bind( &ConfigData::filenamesAsTags ); - - cli["-c"]["--section"] - .describe( "specify section to run" ) - .bind( &addSectionToRun, "section name" ); - - // 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-extra-info"] - .describe( "list all/matching test cases with more info" ) - .bind( &ConfigData::listExtraInfo ); - - cli["--list-reporters"] - .describe( "list all reporters" ) - .bind( &ConfigData::listReporters ); - - cli["--order"] - .describe( "test case order (defaults to decl)" ) - .bind( &setOrder, "decl|lex|rand" ); - - cli["--rng-seed"] - .describe( "set a specific seed for random numbers" ) - .bind( &setRngSeed, "'time'|number" ); - - cli["--force-colour"] - .describe( "force colourised output (deprecated)" ) - .bind( &forceColour ); - - cli["--use-colour"] - .describe( "should output be colourised" ) - .bind( &setUseColour, "yes|no" ); - - return cli; - } + //protected: + AssertionInfo m_info; + AssertionResultData m_resultData; + }; } // end namespace Catch -// #included from: internal/catch_list.hpp -#define TWOBLUECUBES_CATCH_LIST_HPP_INCLUDED +// end catch_assertionresult.h +// start catch_option.hpp -// #included from: catch_text.h -#define TWOBLUECUBES_CATCH_TEXT_H_INCLUDED +namespace Catch { -#define TBC_TEXT_FORMAT_CONSOLE_WIDTH CATCH_CONFIG_CONSOLE_WIDTH - -#define CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE Catch -// #included from: ../external/tbc_text_format.h -// Only use header guard if we are not using an outer namespace -#ifndef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE -# ifdef TWOBLUECUBES_TEXT_FORMAT_H_INCLUDED -# ifndef TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED -# define TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED -# endif -# else -# define TWOBLUECUBES_TEXT_FORMAT_H_INCLUDED -# endif -#endif -#ifndef TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED -#include -#include -#include - -// Use optional outer namespace -#ifdef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE -namespace CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE { -#endif - -namespace Tbc { - -#ifdef TBC_TEXT_FORMAT_CONSOLE_WIDTH - const unsigned int consoleWidth = TBC_TEXT_FORMAT_CONSOLE_WIDTH; -#else - const unsigned int consoleWidth = 80; -#endif - - struct TextAttributes { - TextAttributes() - : initialIndent( std::string::npos ), - indent( 0 ), - width( consoleWidth-1 ) + // An optional type + template + class Option { + public: + Option() : nullableValue( nullptr ) {} + Option( T const& _value ) + : nullableValue( new( storage ) T( _value ) ) + {} + Option( Option const& _other ) + : nullableValue( _other ? new( storage ) T( *_other ) : nullptr ) {} - 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; } - - 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 - }; - - class Text { - public: - Text( std::string const& _str, TextAttributes const& _attr = TextAttributes() ) - : attr( _attr ) - { - const std::string wrappableBeforeChars = "[({<\t"; - const std::string wrappableAfterChars = "])}>-,./|\\"; - const std::string wrappableInsteadOfChars = " \n\r"; - std::string indent = _attr.initialIndent != std::string::npos - ? std::string( _attr.initialIndent, ' ' ) - : std::string( _attr.indent, ' ' ); - - typedef std::string::const_iterator iterator; - iterator it = _str.begin(); - const iterator strEnd = _str.end(); - - while( it != strEnd ) { - - if( lines.size() >= 1000 ) { - lines.push_back( "... message truncated due to excessive size" ); - return; - } - - std::string suffix; - std::size_t width = (std::min)( static_cast( strEnd-it ), _attr.width-static_cast( indent.size() ) ); - iterator itEnd = it+width; - iterator itNext = _str.end(); - - iterator itNewLine = std::find( it, itEnd, '\n' ); - if( itNewLine != itEnd ) - itEnd = itNewLine; - - if( itEnd != strEnd ) { - bool foundWrapPoint = false; - iterator findIt = itEnd; - do { - if( wrappableAfterChars.find( *findIt ) != std::string::npos && findIt != itEnd ) { - itEnd = findIt+1; - itNext = findIt+1; - foundWrapPoint = true; - } - else if( findIt > it && wrappableBeforeChars.find( *findIt ) != std::string::npos ) { - itEnd = findIt; - itNext = findIt; - foundWrapPoint = true; - } - else if( wrappableInsteadOfChars.find( *findIt ) != std::string::npos ) { - itNext = findIt+1; - itEnd = findIt; - foundWrapPoint = true; - } - if( findIt == it ) - break; - else - --findIt; - } - while( !foundWrapPoint ); - - if( !foundWrapPoint ) { - // No good wrap char, so we'll break mid word and add a hyphen - --itEnd; - itNext = itEnd; - suffix = "-"; - } - else { - while( itEnd > it && wrappableInsteadOfChars.find( *(itEnd-1) ) != std::string::npos ) - --itEnd; - } - } - lines.push_back( indent + std::string( it, itEnd ) + suffix ); - - if( indent.size() != _attr.indent ) - indent = std::string( _attr.indent, ' ' ); - it = itNext; - } + ~Option() { + reset(); } - 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(); + Option& operator= ( Option const& _other ) { + if( &_other != this ) { + reset(); + if( _other ) + nullableValue = new( storage ) T( *_other ); + } + return *this; + } + Option& operator = ( T const& _value ) { + reset(); + nullableValue = new( storage ) T( _value ); + return *this; } - 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; + void reset() { + if( nullableValue ) + nullableValue->~T(); + nullableValue = nullptr; + } + + T& operator*() { return *nullableValue; } + T const& operator*() const { return *nullableValue; } + T* operator->() { return nullableValue; } + const T* operator->() const { return nullableValue; } + + T valueOr( T const& defaultValue ) const { + return nullableValue ? *nullableValue : defaultValue; + } + + bool some() const { return nullableValue != nullptr; } + bool none() const { return nullableValue == nullptr; } + + bool operator !() const { return nullableValue == nullptr; } + explicit operator bool() const { + return some(); } private: - std::string str; - TextAttributes attr; - std::vector lines; + T *nullableValue; + alignas(alignof(T)) char storage[sizeof(T)]; }; -} // end namespace Tbc +} // end namespace Catch -#ifdef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE -} // end outer namespace -#endif - -#endif // TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED -#undef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE +// end catch_option.hpp +#include +#include +#include +#include +#include namespace Catch { - using Tbc::Text; - using Tbc::TextAttributes; -} -// #included from: catch_console_colour.hpp -#define TWOBLUECUBES_CATCH_CONSOLE_COLOUR_HPP_INCLUDED + struct ReporterConfig { + explicit ReporterConfig( IConfigPtr const& _fullConfig ); + + ReporterConfig( IConfigPtr const& _fullConfig, std::ostream& _stream ); + + std::ostream& stream() const; + IConfigPtr fullConfig() const; + + private: + std::ostream* m_stream; + IConfigPtr m_fullConfig; + }; + + struct ReporterPreferences { + bool shouldRedirectStdOut = false; + }; + + template + struct LazyStat : Option { + LazyStat& operator=( T const& _value ) { + Option::operator=( _value ); + used = false; + return *this; + } + void reset() { + Option::reset(); + used = false; + } + bool used = false; + }; + + struct TestRunInfo { + TestRunInfo( std::string const& _name ); + std::string name; + }; + struct GroupInfo { + GroupInfo( std::string const& _name, + std::size_t _groupIndex, + std::size_t _groupsCount ); + + std::string name; + std::size_t groupIndex; + std::size_t groupsCounts; + }; + + struct AssertionStats { + AssertionStats( AssertionResult const& _assertionResult, + std::vector const& _infoMessages, + Totals const& _totals ); + + AssertionStats( AssertionStats const& ) = default; + AssertionStats( AssertionStats && ) = default; + AssertionStats& operator = ( AssertionStats const& ) = default; + AssertionStats& operator = ( AssertionStats && ) = default; + virtual ~AssertionStats(); + + AssertionResult assertionResult; + std::vector infoMessages; + Totals totals; + }; + + struct SectionStats { + SectionStats( SectionInfo const& _sectionInfo, + Counts const& _assertions, + double _durationInSeconds, + bool _missingAssertions ); + SectionStats( SectionStats const& ) = default; + SectionStats( SectionStats && ) = default; + SectionStats& operator = ( SectionStats const& ) = default; + SectionStats& operator = ( SectionStats && ) = default; + virtual ~SectionStats(); + + 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 ); + + TestCaseStats( TestCaseStats const& ) = default; + TestCaseStats( TestCaseStats && ) = default; + TestCaseStats& operator = ( TestCaseStats const& ) = default; + TestCaseStats& operator = ( TestCaseStats && ) = default; + virtual ~TestCaseStats(); + + TestCaseInfo testInfo; + Totals totals; + std::string stdOut; + std::string stdErr; + bool aborting; + }; + + struct TestGroupStats { + TestGroupStats( GroupInfo const& _groupInfo, + Totals const& _totals, + bool _aborting ); + TestGroupStats( GroupInfo const& _groupInfo ); + + TestGroupStats( TestGroupStats const& ) = default; + TestGroupStats( TestGroupStats && ) = default; + TestGroupStats& operator = ( TestGroupStats const& ) = default; + TestGroupStats& operator = ( TestGroupStats && ) = default; + virtual ~TestGroupStats(); + + GroupInfo groupInfo; + Totals totals; + bool aborting; + }; + + struct TestRunStats { + TestRunStats( TestRunInfo const& _runInfo, + Totals const& _totals, + bool _aborting ); + + TestRunStats( TestRunStats const& ) = default; + TestRunStats( TestRunStats && ) = default; + TestRunStats& operator = ( TestRunStats const& ) = default; + TestRunStats& operator = ( TestRunStats && ) = default; + virtual ~TestRunStats(); + + TestRunInfo runInfo; + Totals totals; + bool aborting; + }; + + struct BenchmarkInfo { + std::string name; + }; + struct BenchmarkStats { + BenchmarkInfo info; + std::size_t iterations; + uint64_t elapsedTimeInNanoseconds; + }; + + struct IStreamingReporter { + virtual ~IStreamingReporter() = default; + + // Implementing class must also provide the following static methods: + // static std::string getDescription(); + // static std::set getSupportedVerbosities() + + virtual ReporterPreferences getPreferences() const = 0; + + virtual void noMatchingTestCases( std::string const& spec ) = 0; + + virtual void testRunStarting( TestRunInfo const& testRunInfo ) = 0; + virtual void testGroupStarting( GroupInfo const& groupInfo ) = 0; + + virtual void testCaseStarting( TestCaseInfo const& testInfo ) = 0; + virtual void sectionStarting( SectionInfo const& sectionInfo ) = 0; + + // *** experimental *** + virtual void benchmarkStarting( BenchmarkInfo const& ) {} + + virtual void assertionStarting( AssertionInfo const& assertionInfo ) = 0; + + // The return value indicates if the messages buffer should be cleared: + virtual bool assertionEnded( AssertionStats const& assertionStats ) = 0; + + // *** experimental *** + virtual void benchmarkEnded( BenchmarkStats const& ) {} + + virtual void sectionEnded( SectionStats const& sectionStats ) = 0; + virtual void testCaseEnded( TestCaseStats const& testCaseStats ) = 0; + virtual void testGroupEnded( TestGroupStats const& testGroupStats ) = 0; + virtual void testRunEnded( TestRunStats const& testRunStats ) = 0; + + virtual void skipTest( TestCaseInfo const& testInfo ) = 0; + + // Default empty implementation provided + virtual void fatalErrorEncountered( StringRef name ); + + virtual bool isMulti() const; + }; + using IStreamingReporterPtr = std::unique_ptr; + + struct IReporterFactory { + virtual ~IReporterFactory(); + virtual IStreamingReporterPtr create( ReporterConfig const& config ) const = 0; + virtual std::string getDescription() const = 0; + }; + using IReporterFactoryPtr = std::shared_ptr; + + struct IReporterRegistry { + using FactoryMap = std::map; + using Listeners = std::vector; + + virtual ~IReporterRegistry(); + virtual IStreamingReporterPtr create( std::string const& name, IConfigPtr const& config ) const = 0; + virtual FactoryMap const& getFactories() const = 0; + virtual Listeners const& getListeners() const = 0; + }; + + void addReporter( IStreamingReporterPtr& existingReporter, IStreamingReporterPtr&& additionalReporter ); + +} // end namespace Catch + +// end catch_interfaces_reporter.h +#include +#include +#include +#include +#include +#include + +namespace Catch { + void prepareExpandedExpression(AssertionResult& result); + + // Returns double formatted as %.3f (format expected on output) + std::string getFormattedDuration( double duration ); + + template + struct StreamingReporterBase : IStreamingReporter { + + StreamingReporterBase( ReporterConfig const& _config ) + : m_config( _config.fullConfig() ), + stream( _config.stream() ) + { + m_reporterPrefs.shouldRedirectStdOut = false; + CATCH_ENFORCE( DerivedT::getSupportedVerbosities().count( m_config->verbosity() ), "Verbosity level not supported by this reporter" ); + } + + ReporterPreferences getPreferences() const override { + return m_reporterPrefs; + } + + static std::set getSupportedVerbosities() { + return { Verbosity::Normal }; + } + + ~StreamingReporterBase() override = default; + + void noMatchingTestCases(std::string const&) override {} + + void testRunStarting(TestRunInfo const& _testRunInfo) override { + currentTestRunInfo = _testRunInfo; + } + void testGroupStarting(GroupInfo const& _groupInfo) override { + currentGroupInfo = _groupInfo; + } + + void testCaseStarting(TestCaseInfo const& _testInfo) override { + currentTestCaseInfo = _testInfo; + } + void sectionStarting(SectionInfo const& _sectionInfo) override { + m_sectionStack.push_back(_sectionInfo); + } + + void sectionEnded(SectionStats const& /* _sectionStats */) override { + m_sectionStack.pop_back(); + } + void testCaseEnded(TestCaseStats const& /* _testCaseStats */) override { + currentTestCaseInfo.reset(); + } + void testGroupEnded(TestGroupStats const& /* _testGroupStats */) override { + currentGroupInfo.reset(); + } + void testRunEnded(TestRunStats const& /* _testRunStats */) override { + currentTestCaseInfo.reset(); + currentGroupInfo.reset(); + currentTestRunInfo.reset(); + } + + void skipTest(TestCaseInfo const&) override { + // Don't do anything with this by default. + // It can optionally be overridden in the derived class. + } + + IConfigPtr m_config; + std::ostream& stream; + + LazyStat currentTestRunInfo; + LazyStat currentGroupInfo; + LazyStat currentTestCaseInfo; + + std::vector m_sectionStack; + ReporterPreferences m_reporterPrefs; + }; + + template + struct CumulativeReporterBase : IStreamingReporter { + template + struct Node { + explicit Node( T const& _value ) : value( _value ) {} + virtual ~Node() {} + + using ChildNodes = std::vector>; + T value; + ChildNodes children; + }; + struct SectionNode { + explicit SectionNode(SectionStats const& _stats) : stats(_stats) {} + virtual ~SectionNode() = default; + + bool operator == (SectionNode const& other) const { + return stats.sectionInfo.lineInfo == other.stats.sectionInfo.lineInfo; + } + bool operator == (std::shared_ptr const& other) const { + return operator==(*other); + } + + SectionStats stats; + using ChildSections = std::vector>; + using Assertions = std::vector; + 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() (std::shared_ptr const& node) const { + return ((node->stats.sectionInfo.name == m_other.name) && + (node->stats.sectionInfo.lineInfo == m_other.lineInfo)); + } + void operator=(BySectionInfo const&) = delete; + + private: + SectionInfo const& m_other; + }; + + using TestCaseNode = Node; + using TestGroupNode = Node; + using TestRunNode = Node; + + CumulativeReporterBase( ReporterConfig const& _config ) + : m_config( _config.fullConfig() ), + stream( _config.stream() ) + { + m_reporterPrefs.shouldRedirectStdOut = false; + CATCH_ENFORCE( DerivedT::getSupportedVerbosities().count( m_config->verbosity() ), "Verbosity level not supported by this reporter" ); + } + ~CumulativeReporterBase() override = default; + + ReporterPreferences getPreferences() const override { + return m_reporterPrefs; + } + + static std::set getSupportedVerbosities() { + return { Verbosity::Normal }; + } + + void testRunStarting( TestRunInfo const& ) override {} + void testGroupStarting( GroupInfo const& ) override {} + + void testCaseStarting( TestCaseInfo const& ) override {} + + void sectionStarting( SectionInfo const& sectionInfo ) override { + SectionStats incompleteStats( sectionInfo, Counts(), 0, false ); + std::shared_ptr node; + if( m_sectionStack.empty() ) { + if( !m_rootSection ) + m_rootSection = std::make_shared( incompleteStats ); + node = m_rootSection; + } + else { + SectionNode& parentNode = *m_sectionStack.back(); + auto it = + std::find_if( parentNode.childSections.begin(), + parentNode.childSections.end(), + BySectionInfo( sectionInfo ) ); + if( it == parentNode.childSections.end() ) { + node = std::make_shared( incompleteStats ); + parentNode.childSections.push_back( node ); + } + else + node = *it; + } + m_sectionStack.push_back( node ); + m_deepestSection = std::move(node); + } + + void assertionStarting(AssertionInfo const&) override {} + + bool assertionEnded(AssertionStats const& assertionStats) override { + assert(!m_sectionStack.empty()); + // AssertionResult holds a pointer to a temporary DecomposedExpression, + // which getExpandedExpression() calls to build the expression string. + // Our section stack copy of the assertionResult will likely outlive the + // temporary, so it must be expanded or discarded now to avoid calling + // a destroyed object later. + prepareExpandedExpression(const_cast( assertionStats.assertionResult ) ); + SectionNode& sectionNode = *m_sectionStack.back(); + sectionNode.assertions.push_back(assertionStats); + return true; + } + void sectionEnded(SectionStats const& sectionStats) override { + assert(!m_sectionStack.empty()); + SectionNode& node = *m_sectionStack.back(); + node.stats = sectionStats; + m_sectionStack.pop_back(); + } + void testCaseEnded(TestCaseStats const& testCaseStats) override { + auto node = std::make_shared(testCaseStats); + assert(m_sectionStack.size() == 0); + node->children.push_back(m_rootSection); + m_testCases.push_back(node); + m_rootSection.reset(); + + assert(m_deepestSection); + m_deepestSection->stdOut = testCaseStats.stdOut; + m_deepestSection->stdErr = testCaseStats.stdErr; + } + void testGroupEnded(TestGroupStats const& testGroupStats) override { + auto node = std::make_shared(testGroupStats); + node->children.swap(m_testCases); + m_testGroups.push_back(node); + } + void testRunEnded(TestRunStats const& testRunStats) override { + auto node = std::make_shared(testRunStats); + node->children.swap(m_testGroups); + m_testRuns.push_back(node); + testRunEndedCumulative(); + } + virtual void testRunEndedCumulative() = 0; + + void skipTest(TestCaseInfo const&) override {} + + IConfigPtr m_config; + std::ostream& stream; + std::vector m_assertions; + std::vector>> m_sections; + std::vector> m_testCases; + std::vector> m_testGroups; + + std::vector> m_testRuns; + + std::shared_ptr m_rootSection; + std::shared_ptr m_deepestSection; + std::vector> m_sectionStack; + ReporterPreferences m_reporterPrefs; + }; + + template + char const* getLineOfChars() { + static char line[CATCH_CONFIG_CONSOLE_WIDTH] = {0}; + if( !*line ) { + std::memset( line, C, CATCH_CONFIG_CONSOLE_WIDTH-1 ); + line[CATCH_CONFIG_CONSOLE_WIDTH-1] = 0; + } + return line; + } + + struct TestEventListenerBase : StreamingReporterBase { + TestEventListenerBase( ReporterConfig const& _config ); + + void assertionStarting(AssertionInfo const&) override; + bool assertionEnded(AssertionStats const&) override; + }; + +} // end namespace Catch + +// end catch_reporter_bases.hpp +// start catch_console_colour.h namespace Catch { @@ -5545,462 +3701,105 @@ namespace Catch { // Use constructed object for RAII guard Colour( Code _colourCode ); - Colour( Colour const& other ); + Colour( Colour&& other ) noexcept; + Colour& operator=( Colour&& other ) noexcept; ~Colour(); // Use static method for one-shot changes static void use( Code _colourCode ); private: - bool m_moved; + bool m_moved = false; }; - inline std::ostream& operator << ( std::ostream& os, Colour const& ) { return os; } + std::ostream& operator << ( std::ostream& os, Colour const& ); } // end namespace Catch -// #included from: catch_interfaces_reporter.h -#define TWOBLUECUBES_CATCH_INTERFACES_REPORTER_H_INCLUDED +// end catch_console_colour.h +// start catch_reporter_registrars.hpp -#include -#include -#include - -namespace Catch -{ - struct ReporterConfig { - explicit ReporterConfig( Ptr const& _fullConfig ) - : m_stream( &_fullConfig->stream() ), m_fullConfig( _fullConfig ) {} - - 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; } - - private: - std::ostream* m_stream; - Ptr m_fullConfig; - }; - - struct ReporterPreferences { - ReporterPreferences() - : shouldRedirectStdOut( false ) - {} - - 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; - }; - - struct TestRunInfo { - TestRunInfo( std::string const& _name ) : name( _name ) {} - std::string name; - }; - struct GroupInfo { - GroupInfo( std::string const& _name, - std::size_t _groupIndex, - std::size_t _groupsCount ) - : name( _name ), - groupIndex( _groupIndex ), - groupsCounts( _groupsCount ) - {} - - std::string name; - std::size_t groupIndex; - std::size_t groupsCounts; - }; - - struct AssertionStats { - AssertionStats( AssertionResult const& _assertionResult, - std::vector const& _infoMessages, - Totals const& _totals ) - : assertionResult( _assertionResult ), - infoMessages( _infoMessages ), - totals( _totals ) - { - if( assertionResult.hasMessage() ) { - // Copy message into messages list. - // !TBD This should have been done earlier, somewhere - MessageBuilder builder( assertionResult.getTestMacroName(), assertionResult.getSourceInfo(), assertionResult.getResultType() ); - builder << assertionResult.getMessage(); - builder.m_info.message = builder.m_stream.str(); - - infoMessages.push_back( builder.m_info ); - } - } - virtual ~AssertionStats(); - -# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS - AssertionStats( AssertionStats const& ) = default; - AssertionStats( AssertionStats && ) = default; - AssertionStats& operator = ( AssertionStats const& ) = default; - AssertionStats& operator = ( AssertionStats && ) = default; -# endif - - AssertionResult assertionResult; - std::vector infoMessages; - Totals totals; - }; - - struct SectionStats { - SectionStats( SectionInfo const& _sectionInfo, - Counts const& _assertions, - double _durationInSeconds, - bool _missingAssertions ) - : sectionInfo( _sectionInfo ), - assertions( _assertions ), - durationInSeconds( _durationInSeconds ), - missingAssertions( _missingAssertions ) - {} - virtual ~SectionStats(); -# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS - SectionStats( SectionStats const& ) = default; - SectionStats( SectionStats && ) = default; - SectionStats& operator = ( SectionStats const& ) = default; - SectionStats& operator = ( SectionStats && ) = default; -# endif - - SectionInfo sectionInfo; - Counts assertions; - double durationInSeconds; - bool missingAssertions; - }; - - struct TestCaseStats { - TestCaseStats( TestCaseInfo const& _testInfo, - Totals const& _totals, - std::string const& _stdOut, - std::string const& _stdErr, - bool _aborting ) - : testInfo( _testInfo ), - totals( _totals ), - stdOut( _stdOut ), - stdErr( _stdErr ), - aborting( _aborting ) - {} - virtual ~TestCaseStats(); - -# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS - TestCaseStats( TestCaseStats const& ) = default; - TestCaseStats( TestCaseStats && ) = default; - TestCaseStats& operator = ( TestCaseStats const& ) = default; - TestCaseStats& operator = ( TestCaseStats && ) = default; -# endif - - TestCaseInfo testInfo; - Totals totals; - std::string stdOut; - std::string stdErr; - bool aborting; - }; - - struct TestGroupStats { - TestGroupStats( GroupInfo const& _groupInfo, - Totals const& _totals, - bool _aborting ) - : groupInfo( _groupInfo ), - totals( _totals ), - aborting( _aborting ) - {} - TestGroupStats( GroupInfo const& _groupInfo ) - : groupInfo( _groupInfo ), - aborting( false ) - {} - virtual ~TestGroupStats(); - -# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS - TestGroupStats( TestGroupStats const& ) = default; - TestGroupStats( TestGroupStats && ) = default; - TestGroupStats& operator = ( TestGroupStats const& ) = default; - TestGroupStats& operator = ( TestGroupStats && ) = default; -# endif - - GroupInfo groupInfo; - Totals totals; - bool aborting; - }; - - struct TestRunStats { - TestRunStats( TestRunInfo const& _runInfo, - Totals const& _totals, - bool _aborting ) - : runInfo( _runInfo ), - totals( _totals ), - aborting( _aborting ) - {} - virtual ~TestRunStats(); - -# ifndef CATCH_CONFIG_CPP11_GENERATED_METHODS - TestRunStats( TestRunStats const& _other ) - : runInfo( _other.runInfo ), - totals( _other.totals ), - aborting( _other.aborting ) - {} -# else - TestRunStats( TestRunStats const& ) = default; - TestRunStats( TestRunStats && ) = default; - TestRunStats& operator = ( TestRunStats const& ) = default; - TestRunStats& operator = ( TestRunStats && ) = default; -# endif - - TestRunInfo runInfo; - Totals totals; - bool aborting; - }; - - class MultipleReporters; - - struct IStreamingReporter : IShared { - virtual ~IStreamingReporter(); - - // Implementing class must also provide the following static method: - // static std::string getDescription(); - - virtual ReporterPreferences getPreferences() const = 0; - - virtual void noMatchingTestCases( std::string const& spec ) = 0; - - virtual void testRunStarting( TestRunInfo const& testRunInfo ) = 0; - virtual void testGroupStarting( GroupInfo const& groupInfo ) = 0; - - virtual void testCaseStarting( TestCaseInfo const& testInfo ) = 0; - virtual void sectionStarting( SectionInfo const& sectionInfo ) = 0; - - virtual void assertionStarting( AssertionInfo const& assertionInfo ) = 0; - - // The return value indicates if the messages buffer should be cleared: - virtual bool assertionEnded( AssertionStats const& assertionStats ) = 0; - - virtual void sectionEnded( SectionStats const& sectionStats ) = 0; - virtual void testCaseEnded( TestCaseStats const& testCaseStats ) = 0; - virtual void testGroupEnded( TestGroupStats const& testGroupStats ) = 0; - virtual void testRunEnded( TestRunStats const& testRunStats ) = 0; - - virtual void skipTest( TestCaseInfo const& testInfo ) = 0; - - virtual MultipleReporters* tryAsMulti() { return CATCH_NULL; } - }; - - struct IReporterFactory : IShared { - virtual ~IReporterFactory(); - virtual IStreamingReporter* create( ReporterConfig const& config ) const = 0; - virtual std::string getDescription() const = 0; - }; - - struct IReporterRegistry { - typedef std::map > FactoryMap; - typedef std::vector > Listeners; - - virtual ~IReporterRegistry(); - virtual IStreamingReporter* create( std::string const& name, Ptr const& config ) const = 0; - virtual FactoryMap const& getFactories() const = 0; - virtual Listeners const& getListeners() const = 0; - }; - - Ptr addReporter( Ptr const& existingReporter, Ptr const& additionalReporter ); - -} - -#include -#include namespace Catch { - inline std::size_t listTests( Config const& config ) { + template + class ReporterRegistrar { - TestSpec testSpec = config.testSpec(); - if( config.testSpec().hasFilters() ) - Catch::cout() << "Matching test cases:\n"; - else { - Catch::cout() << "All available test cases:\n"; - testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "*" ).testSpec(); - } + class ReporterFactory : public IReporterFactory { - std::size_t matchedTests = 0; - TextAttributes nameAttr, descAttr, tagsAttr; - nameAttr.setInitialIndent( 2 ).setIndent( 4 ); - descAttr.setIndent( 4 ); - tagsAttr.setIndent( 6 ); - - std::vector matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config ); - 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 ); - - Catch::cout() << Text( testCaseInfo.name, nameAttr ) << std::endl; - if( config.listExtraInfo() ) { - Catch::cout() << " " << testCaseInfo.lineInfo << std::endl; - std::string description = testCaseInfo.description; - if( description.empty() ) - description = "(NO DESCRIPTION)"; - Catch::cout() << Text( description, descAttr ) << std::endl; + virtual IStreamingReporterPtr create( ReporterConfig const& config ) const override { + return std::unique_ptr( new T( config ) ); } - if( !testCaseInfo.tags.empty() ) - Catch::cout() << Text( testCaseInfo.tagsAsString, tagsAttr ) << std::endl; - } - if( !config.testSpec().hasFilters() ) - Catch::cout() << pluralise( matchedTests, "test case" ) << '\n' << std::endl; - else - Catch::cout() << pluralise( matchedTests, "matching test case" ) << '\n' << std::endl; - return matchedTests; - } + virtual std::string getDescription() const override { + return T::getDescription(); + } + }; - 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 = filterTests( getAllTestCasesSorted( config ), testSpec, config ); - for( std::vector::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end(); - it != itEnd; - ++it ) { - matchedTests++; - TestCaseInfo const& testCaseInfo = it->getTestCaseInfo(); - if( startsWith( testCaseInfo.name, '#' ) ) - Catch::cout() << '"' << testCaseInfo.name << '"'; - else - Catch::cout() << testCaseInfo.name; - if ( config.listExtraInfo() ) - Catch::cout() << "\t@" << testCaseInfo.lineInfo; - Catch::cout() << std::endl; - } - return matchedTests; - } + public: - struct TagInfo { - TagInfo() : count ( 0 ) {} - void add( std::string const& spelling ) { - ++count; - spellings.insert( spelling ); + ReporterRegistrar( std::string const& name ) { + getMutableRegistryHub().registerReporter( name, std::make_shared() ); } - 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() ) - Catch::cout() << "Tags for matching test cases:\n"; - else { - Catch::cout() << "All available tags:\n"; - testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "*" ).testSpec(); - } + template + class ListenerRegistrar { - std::map tagCounts; + class ListenerFactory : public IReporterFactory { - std::vector matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config ); - 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 ); + virtual IStreamingReporterPtr create( ReporterConfig const& config ) const override { + return std::unique_ptr( new T( config ) ); } + virtual std::string getDescription() const override { + return std::string(); + } + }; + + public: + + ListenerRegistrar() { + getMutableRegistryHub().registerListener( std::make_shared() ); } + }; +} - 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 ) ); - Catch::cout() << oss.str() << wrapper << '\n'; - } - Catch::cout() << pluralise( tagCounts.size(), "tag" ) << '\n' << std::endl; - return tagCounts.size(); - } +#if !defined(CATCH_CONFIG_DISABLE) - inline std::size_t listReporters( Config const& /*config*/ ) { - Catch::cout() << "Available reporters:\n"; - IReporterRegistry::FactoryMap const& factories = getRegistryHub().getReporterRegistry().getFactories(); - IReporterRegistry::FactoryMap::const_iterator itBegin = factories.begin(), itEnd = factories.end(), it; - std::size_t maxNameLen = 0; - for(it = itBegin; it != itEnd; ++it ) - maxNameLen = (std::max)( maxNameLen, it->first.size() ); +#define CATCH_REGISTER_REPORTER( name, reporterType ) \ + CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ + namespace{ Catch::ReporterRegistrar catch_internal_RegistrarFor##reporterType( name ); } \ + CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS - for(it = itBegin; it != itEnd; ++it ) { - Text wrapper( it->second->getDescription(), TextAttributes() - .setInitialIndent( 0 ) - .setIndent( 7+maxNameLen ) - .setWidth( CATCH_CONFIG_CONSOLE_WIDTH - maxNameLen-8 ) ); - Catch::cout() << " " - << it->first - << ':' - << std::string( maxNameLen - it->first.size() + 2, ' ' ) - << wrapper << '\n'; - } - Catch::cout() << std::endl; - return factories.size(); - } +#define CATCH_REGISTER_LISTENER( listenerType ) \ + CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ + namespace{ Catch::ListenerRegistrar catch_internal_RegistrarFor##listenerType; } \ + CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS +#else // CATCH_CONFIG_DISABLE - inline Option list( Config const& config ) { - Option listedCount; - if( config.listTests() || ( config.listExtraInfo() && !config.listTestNamesOnly() ) ) - 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; - } +#define CATCH_REGISTER_REPORTER(name, reporterType) +#define CATCH_REGISTER_LISTENER(listenerType) -} // end namespace Catch +#endif // CATCH_CONFIG_DISABLE -// #included from: internal/catch_run_context.hpp -#define TWOBLUECUBES_CATCH_RUNNER_IMPL_HPP_INCLUDED +// end catch_reporter_registrars.hpp +// end catch_external_interfaces.h +#endif -// #included from: catch_test_case_tracker.hpp -#define TWOBLUECUBES_CATCH_TEST_CASE_TRACKER_HPP_INCLUDED +#ifdef CATCH_IMPL +// start catch_impl.hpp + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wweak-vtables" +#endif + +// Keep these here for external reporters +// start catch_test_case_tracker.h -#include #include -#include #include -#include - -CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS +#include namespace Catch { namespace TestCaseTracking { @@ -6009,13 +3808,14 @@ namespace TestCaseTracking { std::string name; SourceLineInfo location; - NameAndLocation( std::string const& _name, SourceLineInfo const& _location ) - : name( _name ), - location( _location ) - {} + NameAndLocation( std::string const& _name, SourceLineInfo const& _location ); }; - struct ITracker : SharedImpl<> { + struct ITracker; + + using ITrackerPtr = std::shared_ptr; + + struct ITracker { virtual ~ITracker(); // static queries @@ -6034,8 +3834,8 @@ namespace TestCaseTracking { virtual void fail() = 0; virtual void markAsNeedingAnotherRun() = 0; - virtual void addChild( Ptr const& child ) = 0; - virtual ITracker* findChild( NameAndLocation const& nameAndLocation ) = 0; + virtual void addChild( ITrackerPtr const& child ) = 0; + virtual ITrackerPtr findChild( NameAndLocation const& nameAndLocation ) = 0; virtual void openChild() = 0; // Debug/ checking @@ -6043,7 +3843,7 @@ namespace TestCaseTracking { virtual bool isIndexTracker() const = 0; }; - class TrackerContext { + class TrackerContext { enum RunState { NotStarted, @@ -6051,47 +3851,23 @@ namespace TestCaseTracking { CompletedCycle }; - Ptr m_rootTracker; - ITracker* m_currentTracker; - RunState m_runState; + ITrackerPtr m_rootTracker; + ITracker* m_currentTracker = nullptr; + RunState m_runState = NotStarted; public: - static TrackerContext& instance() { - static TrackerContext s_instance; - return s_instance; - } - - TrackerContext() - : m_currentTracker( CATCH_NULL ), - m_runState( NotStarted ) - {} + static TrackerContext& instance(); ITracker& startRun(); + void endRun(); - void endRun() { - m_rootTracker.reset(); - m_currentTracker = CATCH_NULL; - m_runState = NotStarted; - } + void startCycle(); + void completeCycle(); - void startCycle() { - m_currentTracker = m_rootTracker.get(); - m_runState = Executing; - } - void completeCycle() { - m_runState = CompletedCycle; - } - - bool completedCycle() const { - return m_runState == CompletedCycle; - } - ITracker& currentTracker() { - return *m_currentTracker; - } - void setCurrentTracker( ITracker* tracker ) { - m_currentTracker = tracker; - } + bool completedCycle() const; + ITracker& currentTracker(); + void setCurrentTracker( ITracker* tracker ); }; class TrackerBase : public ITracker { @@ -6104,240 +3880,82 @@ namespace TestCaseTracking { CompletedSuccessfully, Failed }; + class TrackerHasName { NameAndLocation m_nameAndLocation; public: - TrackerHasName( NameAndLocation const& nameAndLocation ) : m_nameAndLocation( nameAndLocation ) {} - bool operator ()( Ptr const& tracker ) { - return - tracker->nameAndLocation().name == m_nameAndLocation.name && - tracker->nameAndLocation().location == m_nameAndLocation.location; - } + TrackerHasName( NameAndLocation const& nameAndLocation ); + bool operator ()( ITrackerPtr const& tracker ) const; }; - typedef std::vector > Children; + + using Children = std::vector; NameAndLocation m_nameAndLocation; TrackerContext& m_ctx; ITracker* m_parent; Children m_children; - CycleState m_runState; + CycleState m_runState = NotStarted; + public: - TrackerBase( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent ) - : m_nameAndLocation( nameAndLocation ), - m_ctx( ctx ), - m_parent( parent ), - m_runState( NotStarted ) - {} - virtual ~TrackerBase(); + TrackerBase( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent ); - virtual NameAndLocation const& nameAndLocation() const CATCH_OVERRIDE { - return m_nameAndLocation; - } - virtual bool isComplete() const CATCH_OVERRIDE { - return m_runState == CompletedSuccessfully || m_runState == Failed; - } - virtual bool isSuccessfullyCompleted() const CATCH_OVERRIDE { - return m_runState == CompletedSuccessfully; - } - virtual bool isOpen() const CATCH_OVERRIDE { - return m_runState != NotStarted && !isComplete(); - } - virtual bool hasChildren() const CATCH_OVERRIDE { - return !m_children.empty(); - } + NameAndLocation const& nameAndLocation() const override; + bool isComplete() const override; + bool isSuccessfullyCompleted() const override; + bool isOpen() const override; + bool hasChildren() const override; - virtual void addChild( Ptr const& child ) CATCH_OVERRIDE { - m_children.push_back( child ); - } + void addChild( ITrackerPtr const& child ) override; - virtual ITracker* findChild( NameAndLocation const& nameAndLocation ) CATCH_OVERRIDE { - Children::const_iterator it = std::find_if( m_children.begin(), m_children.end(), TrackerHasName( nameAndLocation ) ); - return( it != m_children.end() ) - ? it->get() - : CATCH_NULL; - } - virtual ITracker& parent() CATCH_OVERRIDE { - assert( m_parent ); // Should always be non-null except for root - return *m_parent; - } + ITrackerPtr findChild( NameAndLocation const& nameAndLocation ) override; + ITracker& parent() override; - virtual void openChild() CATCH_OVERRIDE { - if( m_runState != ExecutingChildren ) { - m_runState = ExecutingChildren; - if( m_parent ) - m_parent->openChild(); - } - } + void openChild() override; - virtual bool isSectionTracker() const CATCH_OVERRIDE { return false; } - virtual bool isIndexTracker() const CATCH_OVERRIDE { return false; } + bool isSectionTracker() const override; + bool isIndexTracker() const override; - void open() { - m_runState = Executing; - moveToThis(); - if( m_parent ) - m_parent->openChild(); - } + void open(); - virtual void close() CATCH_OVERRIDE { + void close() override; + void fail() override; + void markAsNeedingAnotherRun() override; - // Close any still open children (e.g. generators) - while( &m_ctx.currentTracker() != this ) - m_ctx.currentTracker().close(); - - switch( m_runState ) { - case NotStarted: - case CompletedSuccessfully: - case Failed: - throw std::logic_error( "Illogical state" ); - - case NeedsAnotherRun: - break;; - - case Executing: - m_runState = CompletedSuccessfully; - break; - case ExecutingChildren: - if( m_children.empty() || m_children.back()->isComplete() ) - m_runState = CompletedSuccessfully; - break; - - default: - throw std::logic_error( "Unexpected state" ); - } - moveToParent(); - m_ctx.completeCycle(); - } - virtual void fail() CATCH_OVERRIDE { - m_runState = Failed; - if( m_parent ) - m_parent->markAsNeedingAnotherRun(); - moveToParent(); - m_ctx.completeCycle(); - } - virtual void markAsNeedingAnotherRun() CATCH_OVERRIDE { - m_runState = NeedsAnotherRun; - } private: - void moveToParent() { - assert( m_parent ); - m_ctx.setCurrentTracker( m_parent ); - } - void moveToThis() { - m_ctx.setCurrentTracker( this ); - } + void moveToParent(); + void moveToThis(); }; class SectionTracker : public TrackerBase { std::vector m_filters; public: - SectionTracker( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent ) - : TrackerBase( nameAndLocation, ctx, parent ) - { - if( parent ) { - while( !parent->isSectionTracker() ) - parent = &parent->parent(); + SectionTracker( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent ); - SectionTracker& parentSection = static_cast( *parent ); - addNextFilters( parentSection.m_filters ); - } - } - virtual ~SectionTracker(); + bool isSectionTracker() const override; - virtual bool isSectionTracker() const CATCH_OVERRIDE { return true; } + static SectionTracker& acquire( TrackerContext& ctx, NameAndLocation const& nameAndLocation ); - static SectionTracker& acquire( TrackerContext& ctx, NameAndLocation const& nameAndLocation ) { - SectionTracker* section = CATCH_NULL; + void tryOpen(); - ITracker& currentTracker = ctx.currentTracker(); - if( ITracker* childTracker = currentTracker.findChild( nameAndLocation ) ) { - assert( childTracker ); - assert( childTracker->isSectionTracker() ); - section = static_cast( childTracker ); - } - else { - section = new SectionTracker( nameAndLocation, ctx, ¤tTracker ); - currentTracker.addChild( section ); - } - if( !ctx.completedCycle() ) - section->tryOpen(); - return *section; - } - - void tryOpen() { - if( !isComplete() && (m_filters.empty() || m_filters[0].empty() || m_filters[0] == m_nameAndLocation.name ) ) - open(); - } - - void addInitialFilters( std::vector const& filters ) { - if( !filters.empty() ) { - m_filters.push_back(""); // Root - should never be consulted - m_filters.push_back(""); // Test Case - not a section filter - m_filters.insert( m_filters.end(), filters.begin(), filters.end() ); - } - } - void addNextFilters( std::vector const& filters ) { - if( filters.size() > 1 ) - m_filters.insert( m_filters.end(), ++filters.begin(), filters.end() ); - } + void addInitialFilters( std::vector const& filters ); + void addNextFilters( std::vector const& filters ); }; class IndexTracker : public TrackerBase { int m_size; - int m_index; + int m_index = -1; public: - IndexTracker( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent, int size ) - : TrackerBase( nameAndLocation, ctx, parent ), - m_size( size ), - m_index( -1 ) - {} - virtual ~IndexTracker(); + IndexTracker( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent, int size ); - virtual bool isIndexTracker() const CATCH_OVERRIDE { return true; } + bool isIndexTracker() const override; + void close() override; - static IndexTracker& acquire( TrackerContext& ctx, NameAndLocation const& nameAndLocation, int size ) { - IndexTracker* tracker = CATCH_NULL; + static IndexTracker& acquire( TrackerContext& ctx, NameAndLocation const& nameAndLocation, int size ); - ITracker& currentTracker = ctx.currentTracker(); - if( ITracker* childTracker = currentTracker.findChild( nameAndLocation ) ) { - assert( childTracker ); - assert( childTracker->isIndexTracker() ); - tracker = static_cast( childTracker ); - } - else { - tracker = new IndexTracker( nameAndLocation, ctx, ¤tTracker, size ); - currentTracker.addChild( tracker ); - } + int index() const; - if( !ctx.completedCycle() && !tracker->isComplete() ) { - if( tracker->m_runState != ExecutingChildren && tracker->m_runState != NeedsAnotherRun ) - tracker->moveNext(); - tracker->open(); - } - - return *tracker; - } - - int index() const { return m_index; } - - void moveNext() { - m_index++; - m_children.clear(); - } - - virtual void close() CATCH_OVERRIDE { - TrackerBase::close(); - if( m_runState == CompletedSuccessfully && m_index < m_size-1 ) - m_runState = Executing; - } + void moveNext(); }; - inline ITracker& TrackerContext::startRun() { - m_rootTracker = new SectionTracker( NameAndLocation( "{root}", CATCH_INTERNAL_LINEINFO ), *this, CATCH_NULL ); - m_currentTracker = CATCH_NULL; - m_runState = Executing; - return *m_rootTracker; - } - } // namespace TestCaseTracking using TestCaseTracking::ITracker; @@ -6347,31 +3965,1941 @@ using TestCaseTracking::IndexTracker; } // namespace Catch -CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS +// end catch_test_case_tracker.h -// #included from: catch_fatal_condition.hpp -#define TWOBLUECUBES_CATCH_FATAL_CONDITION_H_INCLUDED +// start catch_leak_detector.h namespace Catch { - // Report the error condition - inline void reportFatal( std::string const& message ) { - IContext& context = Catch::getCurrentContext(); - IResultCapture* resultCapture = context.getResultCapture(); - resultCapture->handleFatalErrorCondition( message ); + struct LeakDetector { + LeakDetector(); + }; + +} +// end catch_leak_detector.h +// Cpp files will be included in the single-header file here +// start catch_approx.cpp + +#include +#include + +namespace { + +// Performs equivalent check of std::fabs(lhs - rhs) <= margin +// But without the subtraction to allow for INFINITY in comparison +bool marginComparison(double lhs, double rhs, double margin) { + return (lhs + margin >= rhs) && (rhs + margin >= lhs); +} + +} + +namespace Catch { +namespace Detail { + + Approx::Approx ( double value ) + : m_epsilon( std::numeric_limits::epsilon()*100 ), + m_margin( 0.0 ), + m_scale( 0.0 ), + m_value( value ) + {} + + Approx Approx::custom() { + return Approx( 0 ); + } + + std::string Approx::toString() const { + std::ostringstream oss; + oss << "Approx( " << ::Catch::Detail::stringify( m_value ) << " )"; + return oss.str(); + } + + bool Approx::equalityComparisonImpl(const double other) const { + // First try with fixed margin, then compute margin based on epsilon, scale and Approx's value + // Thanks to Richard Harris for his help refining the scaled margin value + return marginComparison(m_value, other, m_margin) || marginComparison(m_value, other, m_epsilon * (m_scale + std::fabs(m_value))); + } + +} // end namespace Detail + +std::string StringMaker::convert(Catch::Detail::Approx const& value) { + return value.toString(); +} + +} // end namespace Catch +// end catch_approx.cpp +// start catch_assertionhandler.cpp + +// start catch_context.h + +#include + +namespace Catch { + + struct IResultCapture; + struct IRunner; + struct IConfig; + + using IConfigPtr = std::shared_ptr; + + struct IContext + { + virtual ~IContext(); + + virtual IResultCapture* getResultCapture() = 0; + virtual IRunner* getRunner() = 0; + virtual IConfigPtr getConfig() const = 0; + }; + + struct IMutableContext : IContext + { + virtual ~IMutableContext(); + virtual void setResultCapture( IResultCapture* resultCapture ) = 0; + virtual void setRunner( IRunner* runner ) = 0; + virtual void setConfig( IConfigPtr const& config ) = 0; + }; + + IContext& getCurrentContext(); + IMutableContext& getCurrentMutableContext(); + void cleanUpContext(); +} + +// end catch_context.h +#include + +namespace Catch { + + auto operator <<( std::ostream& os, ITransientExpression const& expr ) -> std::ostream& { + expr.streamReconstructedExpression( os ); + return os; + } + + LazyExpression::LazyExpression( bool isNegated ) + : m_isNegated( isNegated ) + {} + + LazyExpression::LazyExpression( LazyExpression const& other ) : m_isNegated( other.m_isNegated ) {} + + LazyExpression::operator bool() const { + return m_transientExpression != nullptr; + } + + auto operator << ( std::ostream& os, LazyExpression const& lazyExpr ) -> std::ostream& { + if( lazyExpr.m_isNegated ) + os << "!"; + + if( lazyExpr ) { + if( lazyExpr.m_isNegated && lazyExpr.m_transientExpression->isBinaryExpression() ) + os << "(" << *lazyExpr.m_transientExpression << ")"; + else + os << *lazyExpr.m_transientExpression; + } + else { + os << "{** error - unchecked empty expression requested **}"; + } + return os; + } + + AssertionHandler::AssertionHandler + ( StringRef macroName, + SourceLineInfo const& lineInfo, + StringRef capturedExpression, + ResultDisposition::Flags resultDisposition ) + : m_assertionInfo{ macroName, lineInfo, capturedExpression, resultDisposition } + { + getCurrentContext().getResultCapture()->assertionStarting( m_assertionInfo ); + } + AssertionHandler::~AssertionHandler() { + if ( m_inExceptionGuard ) { + handle( ResultWas::ThrewException, "Exception translation was disabled by CATCH_CONFIG_FAST_COMPILE" ); + getCurrentContext().getResultCapture()->exceptionEarlyReported(); + } + } + + void AssertionHandler::handle( ITransientExpression const& expr ) { + + bool negated = isFalseTest( m_assertionInfo.resultDisposition ); + bool result = expr.getResult() != negated; + + handle( result ? ResultWas::Ok : ResultWas::ExpressionFailed, &expr, negated ); + } + void AssertionHandler::handle( ResultWas::OfType resultType ) { + handle( resultType, nullptr, false ); + } + void AssertionHandler::handle( ResultWas::OfType resultType, StringRef const& message ) { + AssertionResultData data( resultType, LazyExpression( false ) ); + data.message = message; + handle( data, nullptr ); + } + void AssertionHandler::handle( ResultWas::OfType resultType, ITransientExpression const* expr, bool negated ) { + AssertionResultData data( resultType, LazyExpression( negated ) ); + handle( data, expr ); + } + void AssertionHandler::handle( AssertionResultData const& resultData, ITransientExpression const* expr ) { + + getResultCapture().assertionRun(); + + AssertionResult assertionResult{ m_assertionInfo, resultData }; + assertionResult.m_resultData.lazyExpression.m_transientExpression = expr; + + getResultCapture().assertionEnded( assertionResult ); + + if( !assertionResult.isOk() ) { + m_shouldDebugBreak = getCurrentContext().getConfig()->shouldDebugBreak(); + m_shouldThrow = + getCurrentContext().getRunner()->aborting() || + (m_assertionInfo.resultDisposition & ResultDisposition::Normal); + } + } + + auto AssertionHandler::allowThrows() const -> bool { + return getCurrentContext().getConfig()->allowThrows(); + } + + auto AssertionHandler::shouldDebugBreak() const -> bool { + return m_shouldDebugBreak; + } + void AssertionHandler::reactWithDebugBreak() const { + if (m_shouldDebugBreak) { + /////////////////////////////////////////////////////////////////// + // To inspect the state during test, you need to go one level up the callstack + // To go back to the test and change execution, jump over the reactWithoutDebugBreak() call + /////////////////////////////////////////////////////////////////// + CATCH_BREAK_INTO_DEBUGGER(); + } + reactWithoutDebugBreak(); + } + void AssertionHandler::reactWithoutDebugBreak() const { + if( m_shouldThrow ) + throw Catch::TestFailureException(); + } + + void AssertionHandler::useActiveException() { + handle( ResultWas::ThrewException, Catch::translateActiveException() ); + } + + void AssertionHandler::setExceptionGuard() { + assert( m_inExceptionGuard == false ); + m_inExceptionGuard = true; + } + void AssertionHandler::unsetExceptionGuard() { + assert( m_inExceptionGuard == true ); + m_inExceptionGuard = false; + } + + // This is the overload that takes a string and infers the Equals matcher from it + // The more general overload, that takes any string matcher, is in catch_capture_matchers.cpp + void handleExceptionMatchExpr( AssertionHandler& handler, std::string const& str, StringRef matcherString ) { + handleExceptionMatchExpr( handler, Matchers::Equals( str ), matcherString ); } } // namespace Catch +// end catch_assertionhandler.cpp +// start catch_assertionresult.cpp -#if defined ( CATCH_PLATFORM_WINDOWS ) ///////////////////////////////////////// -// #included from: catch_windows_h_proxy.h +namespace Catch { + AssertionResultData::AssertionResultData(ResultWas::OfType _resultType, LazyExpression const & _lazyExpression): + lazyExpression(_lazyExpression), + resultType(_resultType) {} -#define TWOBLUECUBES_CATCH_WINDOWS_H_PROXY_H_INCLUDED + std::string AssertionResultData::reconstructExpression() const { -#ifdef CATCH_DEFINES_NOMINMAX + if( reconstructedExpression.empty() ) { + if( lazyExpression ) { + // !TBD Use stringstream for now, but rework above to pass stream in + std::ostringstream oss; + oss << lazyExpression; + reconstructedExpression = oss.str(); + } + } + return reconstructedExpression; + } + + AssertionResult::AssertionResult( AssertionInfo const& info, AssertionResultData const& data ) + : m_info( info ), + m_resultData( data ) + {} + + // 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[0] != 0; + } + + bool AssertionResult::hasMessage() const { + return !m_resultData.message.empty(); + } + + std::string AssertionResult::getExpression() const { + if( isFalseTest( m_info.resultDisposition ) ) + return "!(" + std::string(m_info.capturedExpression) + ")"; + else + return m_info.capturedExpression; + } + + std::string AssertionResult::getExpressionInMacro() const { + std::string expr; + if( m_info.macroName[0] == 0 ) + expr = m_info.capturedExpression; + else { + expr.reserve( m_info.macroName.size() + m_info.capturedExpression.size() + 4 ); + expr += m_info.macroName; + expr += "( "; + expr += m_info.capturedExpression; + expr += " )"; + } + return expr; + } + + bool AssertionResult::hasExpandedExpression() const { + return hasExpression() && getExpandedExpression() != getExpression(); + } + + std::string AssertionResult::getExpandedExpression() const { + std::string expr = m_resultData.reconstructExpression(); + return expr.empty() + ? getExpression() + : expr; + } + + 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 +// end catch_assertionresult.cpp +// start catch_benchmark.cpp + +namespace Catch { + + auto BenchmarkLooper::getResolution() -> uint64_t { + return getEstimatedClockResolution() * getCurrentContext().getConfig()->benchmarkResolutionMultiple(); + } + + void BenchmarkLooper::reportStart() { + getResultCapture().benchmarkStarting( { m_name } ); + } + auto BenchmarkLooper::needsMoreIterations() -> bool { + auto elapsed = m_timer.getElapsedNanoseconds(); + + // Exponentially increasing iterations until we're confident in our timer resolution + if( elapsed < m_resolution ) { + m_iterationsToRun *= 10; + return true; + } + + getResultCapture().benchmarkEnded( { { m_name }, m_count, elapsed } ); + return false; + } + +} // end namespace Catch +// end catch_benchmark.cpp +// start catch_capture_matchers.cpp + +namespace Catch { + + using StringMatcher = Matchers::Impl::MatcherBase; + + // This is the general overload that takes a any string matcher + // There is another overload, in catch_assertinhandler.h/.cpp, that only takes a string and infers + // the Equals matcher (so the header does not mention matchers) + void handleExceptionMatchExpr( AssertionHandler& handler, StringMatcher const& matcher, StringRef matcherString ) { + std::string exceptionMessage = Catch::translateActiveException(); + MatchExpr expr( exceptionMessage, matcher, matcherString ); + handler.handle( expr ); + } + +} // namespace Catch +// end catch_capture_matchers.cpp +// start catch_commandline.cpp + +// start catch_commandline.h + +// start catch_clara.h + +// 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 CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH +#undef CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH +#endif +#define CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH CATCH_CONFIG_CONSOLE_WIDTH-1 + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wweak-vtables" +#pragma clang diagnostic ignored "-Wexit-time-destructors" +#pragma clang diagnostic ignored "-Wshadow" +#endif + +// start clara.hpp +// v1.0-develop.2 +// See https://github.com/philsquared/Clara + + +#ifndef CATCH_CLARA_CONFIG_CONSOLE_WIDTH +#define CATCH_CLARA_CONFIG_CONSOLE_WIDTH 80 +#endif + +#ifndef CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH +#define CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH CATCH_CLARA_CONFIG_CONSOLE_WIDTH +#endif + +// ----------- #included from clara_textflow.hpp ----------- + +// TextFlowCpp +// +// A single-header library for wrapping and laying out basic text, by Phil Nash +// +// This work is licensed under the BSD 2-Clause license. +// See the accompanying LICENSE file, or the one at https://opensource.org/licenses/BSD-2-Clause +// +// This project is hosted at https://github.com/philsquared/textflowcpp + + +#include +#include +#include +#include + +#ifndef CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH +#define CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH 80 +#endif + +namespace Catch { namespace clara { namespace TextFlow { + + inline auto isWhitespace( char c ) -> bool { + static std::string chars = " \t\n\r"; + return chars.find( c ) != std::string::npos; + } + inline auto isBreakableBefore( char c ) -> bool { + static std::string chars = "[({<|"; + return chars.find( c ) != std::string::npos; + } + inline auto isBreakableAfter( char c ) -> bool { + static std::string chars = "])}>.,:;*+-=&/\\"; + return chars.find( c ) != std::string::npos; + } + + class Columns; + + class Column { + std::vector m_strings; + size_t m_width = CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH; + size_t m_indent = 0; + size_t m_initialIndent = std::string::npos; + + public: + class iterator { + friend Column; + + Column const& m_column; + size_t m_stringIndex = 0; + size_t m_pos = 0; + + size_t m_len = 0; + size_t m_end = 0; + bool m_suffix = false; + + iterator( Column const& column, size_t stringIndex ) + : m_column( column ), + m_stringIndex( stringIndex ) + {} + + auto line() const -> std::string const& { return m_column.m_strings[m_stringIndex]; } + + auto isBoundary( size_t at ) const -> bool { + assert( at > 0 ); + assert( at <= line().size() ); + + return at == line().size() || + ( isWhitespace( line()[at] ) && !isWhitespace( line()[at-1] ) ) || + isBreakableBefore( line()[at] ) || + isBreakableAfter( line()[at-1] ); + } + + void calcLength() { + assert( m_stringIndex < m_column.m_strings.size() ); + + m_suffix = false; + auto width = m_column.m_width-indent(); + m_end = m_pos; + while( m_end < line().size() && line()[m_end] != '\n' ) + ++m_end; + + if( m_end < m_pos + width ) { + m_len = m_end - m_pos; + } + else { + size_t len = width; + while (len > 0 && !isBoundary(m_pos + len)) + --len; + while (len > 0 && isWhitespace( line()[m_pos + len - 1] )) + --len; + + if (len > 0) { + m_len = len; + } else { + m_suffix = true; + m_len = width - 1; + } + } + } + + auto indent() const -> size_t { + auto initial = m_pos == 0 && m_stringIndex == 0 ? m_column.m_initialIndent : std::string::npos; + return initial == std::string::npos ? m_column.m_indent : initial; + } + + auto addIndentAndSuffix(std::string const &plain) const -> std::string { + return std::string( indent(), ' ' ) + (m_suffix ? plain + "-" : plain); + } + + public: + explicit iterator( Column const& column ) : m_column( column ) { + assert( m_column.m_width > m_column.m_indent ); + assert( m_column.m_initialIndent == std::string::npos || m_column.m_width > m_column.m_initialIndent ); + calcLength(); + if( m_len == 0 ) + m_stringIndex++; // Empty string + } + + auto operator *() const -> std::string { + assert( m_stringIndex < m_column.m_strings.size() ); + assert( m_pos <= m_end ); + if( m_pos + m_column.m_width < m_end ) + return addIndentAndSuffix(line().substr(m_pos, m_len)); + else + return addIndentAndSuffix(line().substr(m_pos, m_end - m_pos)); + } + + auto operator ++() -> iterator& { + m_pos += m_len; + if( m_pos < line().size() && line()[m_pos] == '\n' ) + m_pos += 1; + else + while( m_pos < line().size() && isWhitespace( line()[m_pos] ) ) + ++m_pos; + + if( m_pos == line().size() ) { + m_pos = 0; + ++m_stringIndex; + } + if( m_stringIndex < m_column.m_strings.size() ) + calcLength(); + return *this; + } + auto operator ++(int) -> iterator { + iterator prev( *this ); + operator++(); + return prev; + } + + auto operator ==( iterator const& other ) const -> bool { + return + m_pos == other.m_pos && + m_stringIndex == other.m_stringIndex && + &m_column == &other.m_column; + } + auto operator !=( iterator const& other ) const -> bool { + return !operator==( other ); + } + }; + using const_iterator = iterator; + + explicit Column( std::string const& text ) { m_strings.push_back( text ); } + + auto width( size_t newWidth ) -> Column& { + assert( newWidth > 0 ); + m_width = newWidth; + return *this; + } + auto indent( size_t newIndent ) -> Column& { + m_indent = newIndent; + return *this; + } + auto initialIndent( size_t newIndent ) -> Column& { + m_initialIndent = newIndent; + return *this; + } + + auto width() const -> size_t { return m_width; } + auto begin() const -> iterator { return iterator( *this ); } + auto end() const -> iterator { return { *this, m_strings.size() }; } + + inline friend std::ostream& operator << ( std::ostream& os, Column const& col ) { + bool first = true; + for( auto line : col ) { + if( first ) + first = false; + else + os << "\n"; + os << line; + } + return os; + } + + auto operator + ( Column const& other ) -> Columns; + + auto toString() const -> std::string { + std::ostringstream oss; + oss << *this; + return oss.str(); + } + }; + + class Spacer : public Column { + + public: + explicit Spacer( size_t spaceWidth ) : Column( "" ) { + width( spaceWidth ); + } + }; + + class Columns { + std::vector m_columns; + + public: + + class iterator { + friend Columns; + struct EndTag {}; + + std::vector const& m_columns; + std::vector m_iterators; + size_t m_activeIterators; + + iterator( Columns const& columns, EndTag ) + : m_columns( columns.m_columns ), + m_activeIterators( 0 ) + { + m_iterators.reserve( m_columns.size() ); + + for( auto const& col : m_columns ) + m_iterators.push_back( col.end() ); + } + + public: + explicit iterator( Columns const& columns ) + : m_columns( columns.m_columns ), + m_activeIterators( m_columns.size() ) + { + m_iterators.reserve( m_columns.size() ); + + for( auto const& col : m_columns ) + m_iterators.push_back( col.begin() ); + } + + auto operator ==( iterator const& other ) const -> bool { + return m_iterators == other.m_iterators; + } + auto operator !=( iterator const& other ) const -> bool { + return m_iterators != other.m_iterators; + } + auto operator *() const -> std::string { + std::string row, padding; + + for( size_t i = 0; i < m_columns.size(); ++i ) { + auto width = m_columns[i].width(); + if( m_iterators[i] != m_columns[i].end() ) { + std::string col = *m_iterators[i]; + row += padding + col; + if( col.size() < width ) + padding = std::string( width - col.size(), ' ' ); + else + padding = ""; + } + else { + padding += std::string( width, ' ' ); + } + } + return row; + } + auto operator ++() -> iterator& { + for( size_t i = 0; i < m_columns.size(); ++i ) { + if (m_iterators[i] != m_columns[i].end()) + ++m_iterators[i]; + } + return *this; + } + auto operator ++(int) -> iterator { + iterator prev( *this ); + operator++(); + return prev; + } + }; + using const_iterator = iterator; + + auto begin() const -> iterator { return iterator( *this ); } + auto end() const -> iterator { return { *this, iterator::EndTag() }; } + + auto operator += ( Column const& col ) -> Columns& { + m_columns.push_back( col ); + return *this; + } + auto operator + ( Column const& col ) -> Columns { + Columns combined = *this; + combined += col; + return combined; + } + + inline friend std::ostream& operator << ( std::ostream& os, Columns const& cols ) { + + bool first = true; + for( auto line : cols ) { + if( first ) + first = false; + else + os << "\n"; + os << line; + } + return os; + } + + auto toString() const -> std::string { + std::ostringstream oss; + oss << *this; + return oss.str(); + } + }; + + inline auto Column::operator + ( Column const& other ) -> Columns { + Columns cols; + cols += *this; + cols += other; + return cols; + } +}}} // namespace Catch::clara::TextFlow + +// ----------- end of #include from clara_textflow.hpp ----------- +// ........... back in clara.hpp + +#include +#include +#include + +#if !defined(CATCH_PLATFORM_WINDOWS) && ( defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) ) +#define CATCH_PLATFORM_WINDOWS +#endif + +namespace Catch { namespace clara { +namespace detail { + + // Traits for extracting arg and return type of lambdas (for single argument lambdas) + template + struct UnaryLambdaTraits : UnaryLambdaTraits {}; + + template + struct UnaryLambdaTraits { + static const bool isValid = false; + }; + + template + struct UnaryLambdaTraits { + static const bool isValid = true; + using ArgType = typename std::remove_const::type>::type;; + using ReturnType = ReturnT; + }; + + class TokenStream; + + // Transport for raw args (copied from main args, or supplied via init list for testing) + class Args { + friend TokenStream; + std::string m_exeName; + std::vector m_args; + + public: + Args( int argc, char *argv[] ) { + m_exeName = argv[0]; + for( int i = 1; i < argc; ++i ) + m_args.push_back( argv[i] ); + } + + Args( std::initializer_list args ) + : m_exeName( *args.begin() ), + m_args( args.begin()+1, args.end() ) + {} + + auto exeName() const -> std::string { + return m_exeName; + } + }; + + // Wraps a token coming from a token stream. These may not directly correspond to strings as a single string + // may encode an option + its argument if the : or = form is used + enum class TokenType { + Option, Argument + }; + struct Token { + TokenType type; + std::string token; + }; + + inline auto isOptPrefix( char c ) -> bool { + return c == '-' +#ifdef CATCH_PLATFORM_WINDOWS + || c == '/' +#endif + ; + } + + // Abstracts iterators into args as a stream of tokens, with option arguments uniformly handled + class TokenStream { + using Iterator = std::vector::const_iterator; + Iterator it; + Iterator itEnd; + std::vector m_tokenBuffer; + + void loadBuffer() { + m_tokenBuffer.resize( 0 ); + + // Skip any empty strings + while( it != itEnd && it->empty() ) + ++it; + + if( it != itEnd ) { + auto const &next = *it; + if( isOptPrefix( next[0] ) ) { + auto delimiterPos = next.find_first_of( " :=" ); + if( delimiterPos != std::string::npos ) { + m_tokenBuffer.push_back( { TokenType::Option, next.substr( 0, delimiterPos ) } ); + m_tokenBuffer.push_back( { TokenType::Argument, next.substr( delimiterPos + 1 ) } ); + } else { + if( next[1] != '-' && next.size() > 2 ) { + std::string opt = "- "; + for( size_t i = 1; i < next.size(); ++i ) { + opt[1] = next[i]; + m_tokenBuffer.push_back( { TokenType::Option, opt } ); + } + } else { + m_tokenBuffer.push_back( { TokenType::Option, next } ); + } + } + } else { + m_tokenBuffer.push_back( { TokenType::Argument, next } ); + } + } + } + + public: + explicit TokenStream( Args const &args ) : TokenStream( args.m_args.begin(), args.m_args.end() ) {} + + TokenStream( Iterator it, Iterator itEnd ) : it( it ), itEnd( itEnd ) { + loadBuffer(); + } + + explicit operator bool() const { + return !m_tokenBuffer.empty() || it != itEnd; + } + + auto count() const -> size_t { return m_tokenBuffer.size() + (itEnd - it); } + + auto operator*() const -> Token { + assert( !m_tokenBuffer.empty() ); + return m_tokenBuffer.front(); + } + + auto operator->() const -> Token const * { + assert( !m_tokenBuffer.empty() ); + return &m_tokenBuffer.front(); + } + + auto operator++() -> TokenStream & { + if( m_tokenBuffer.size() >= 2 ) { + m_tokenBuffer.erase( m_tokenBuffer.begin() ); + } else { + if( it != itEnd ) + ++it; + loadBuffer(); + } + return *this; + } + }; + + class ResultBase { + public: + enum Type { + Ok, LogicError, RuntimeError + }; + + protected: + ResultBase( Type type ) : m_type( type ) {} + virtual ~ResultBase() = default; + + virtual void enforceOk() const = 0; + + Type m_type; + }; + + template + class ResultValueBase : public ResultBase { + public: + auto value() const -> T const & { + enforceOk(); + return m_value; + } + + protected: + ResultValueBase( Type type ) : ResultBase( type ) {} + + ResultValueBase( ResultValueBase const &other ) : ResultBase( other ) { + if( m_type == ResultBase::Ok ) + new( &m_value ) T( other.m_value ); + } + + ResultValueBase( Type, T const &value ) : ResultBase( Ok ) { + new( &m_value ) T( value ); + } + + auto operator=( ResultValueBase const &other ) -> ResultValueBase & { + if( m_type == ResultBase::Ok ) + m_value.~T(); + ResultBase::operator=(other); + if( m_type == ResultBase::Ok ) + new( &m_value ) T( other.m_value ); + return *this; + } + + ~ResultValueBase() { + if( m_type == Ok ) + m_value.~T(); + } + + union { + T m_value; + }; + }; + + template<> + class ResultValueBase : public ResultBase { + protected: + using ResultBase::ResultBase; + }; + + template + class BasicResult : public ResultValueBase { + public: + template + explicit BasicResult( BasicResult const &other ) + : ResultValueBase( other.type() ), + m_errorMessage( other.errorMessage() ) + { + assert( type() != ResultBase::Ok ); + } + + template + static auto ok( U const &value ) -> BasicResult { return { ResultBase::Ok, value }; } + static auto ok() -> BasicResult { return { ResultBase::Ok }; } + static auto logicError( std::string const &message ) -> BasicResult { return { ResultBase::LogicError, message }; } + static auto runtimeError( std::string const &message ) -> BasicResult { return { ResultBase::RuntimeError, message }; } + + explicit operator bool() const { return m_type == ResultBase::Ok; } + auto type() const -> ResultBase::Type { return m_type; } + auto errorMessage() const -> std::string { return m_errorMessage; } + + protected: + virtual void enforceOk() const { + // !TBD: If no exceptions, std::terminate here or something + switch( m_type ) { + case ResultBase::LogicError: + throw std::logic_error( m_errorMessage ); + case ResultBase::RuntimeError: + throw std::runtime_error( m_errorMessage ); + case ResultBase::Ok: + break; + } + } + + std::string m_errorMessage; // Only populated if resultType is an error + + BasicResult( ResultBase::Type type, std::string const &message ) + : ResultValueBase(type), + m_errorMessage(message) + { + assert( m_type != ResultBase::Ok ); + } + + using ResultValueBase::ResultValueBase; + using ResultBase::m_type; + }; + + enum class ParseResultType { + Matched, NoMatch, ShortCircuitAll, ShortCircuitSame + }; + + class ParseState { + public: + + ParseState( ParseResultType type, TokenStream const &remainingTokens ) + : m_type(type), + m_remainingTokens( remainingTokens ) + {} + + auto type() const -> ParseResultType { return m_type; } + auto remainingTokens() const -> TokenStream { return m_remainingTokens; } + + private: + ParseResultType m_type; + TokenStream m_remainingTokens; + }; + + using Result = BasicResult; + using ParserResult = BasicResult; + using InternalParseResult = BasicResult; + + struct HelpColumns { + std::string left; + std::string right; + }; + + template + inline auto convertInto( std::string const &source, T& target ) -> ParserResult { + std::stringstream ss; + ss << source; + ss >> target; + if( ss.fail() ) + return ParserResult::runtimeError( "Unable to convert '" + source + "' to destination type" ); + else + return ParserResult::ok( ParseResultType::Matched ); + } + inline auto convertInto( std::string const &source, std::string& target ) -> ParserResult { + target = source; + return ParserResult::ok( ParseResultType::Matched ); + } + inline auto convertInto( std::string const &source, bool &target ) -> ParserResult { + std::string srcLC = source; + std::transform( srcLC.begin(), srcLC.end(), srcLC.begin(), []( char c ) { return static_cast( ::tolower(c) ); } ); + if (srcLC == "y" || srcLC == "1" || srcLC == "true" || srcLC == "yes" || srcLC == "on") + target = true; + else if (srcLC == "n" || srcLC == "0" || srcLC == "false" || srcLC == "no" || srcLC == "off") + target = false; + else + return ParserResult::runtimeError( "Expected a boolean value but did not recognise: '" + source + "'" ); + return ParserResult::ok( ParseResultType::Matched ); + } + + struct BoundRefBase { + BoundRefBase() = default; + BoundRefBase( BoundRefBase const & ) = delete; + BoundRefBase( BoundRefBase && ) = delete; + BoundRefBase &operator=( BoundRefBase const & ) = delete; + BoundRefBase &operator=( BoundRefBase && ) = delete; + + virtual ~BoundRefBase() = default; + + virtual auto isFlag() const -> bool = 0; + virtual auto isContainer() const -> bool { return false; } + virtual auto setValue( std::string const &arg ) -> ParserResult = 0; + virtual auto setFlag( bool flag ) -> ParserResult = 0; + }; + + struct BoundValueRefBase : BoundRefBase { + auto isFlag() const -> bool override { return false; } + + auto setFlag( bool ) -> ParserResult override { + return ParserResult::logicError( "Flags can only be set on boolean fields" ); + } + }; + + struct BoundFlagRefBase : BoundRefBase { + auto isFlag() const -> bool override { return true; } + + auto setValue( std::string const &arg ) -> ParserResult override { + bool flag; + auto result = convertInto( arg, flag ); + if( result ) + setFlag( flag ); + return result; + } + }; + + template + struct BoundRef : BoundValueRefBase { + T &m_ref; + + explicit BoundRef( T &ref ) : m_ref( ref ) {} + + auto setValue( std::string const &arg ) -> ParserResult override { + return convertInto( arg, m_ref ); + } + }; + + template + struct BoundRef> : BoundValueRefBase { + std::vector &m_ref; + + explicit BoundRef( std::vector &ref ) : m_ref( ref ) {} + + auto isContainer() const -> bool override { return true; } + + auto setValue( std::string const &arg ) -> ParserResult override { + T temp; + auto result = convertInto( arg, temp ); + if( result ) + m_ref.push_back( temp ); + return result; + } + }; + + struct BoundFlagRef : BoundFlagRefBase { + bool &m_ref; + + explicit BoundFlagRef( bool &ref ) : m_ref( ref ) {} + + auto setFlag( bool flag ) -> ParserResult override { + m_ref = flag; + return ParserResult::ok( ParseResultType::Matched ); + } + }; + + template + struct LambdaInvoker { + static_assert( std::is_same::value, "Lambda must return void or clara::ParserResult" ); + + template + static auto invoke( L const &lambda, ArgType const &arg ) -> ParserResult { + return lambda( arg ); + } + }; + + template<> + struct LambdaInvoker { + template + static auto invoke( L const &lambda, ArgType const &arg ) -> ParserResult { + lambda( arg ); + return ParserResult::ok( ParseResultType::Matched ); + } + }; + + template + inline auto invokeLambda( L const &lambda, std::string const &arg ) -> ParserResult { + ArgType temp; + auto result = convertInto( arg, temp ); + return !result + ? result + : LambdaInvoker::ReturnType>::invoke( lambda, temp ); + }; + + template + struct BoundLambda : BoundValueRefBase { + L m_lambda; + + static_assert( UnaryLambdaTraits::isValid, "Supplied lambda must take exactly one argument" ); + explicit BoundLambda( L const &lambda ) : m_lambda( lambda ) {} + + auto setValue( std::string const &arg ) -> ParserResult override { + return invokeLambda::ArgType>( m_lambda, arg ); + } + }; + + template + struct BoundFlagLambda : BoundFlagRefBase { + L m_lambda; + + static_assert( UnaryLambdaTraits::isValid, "Supplied lambda must take exactly one argument" ); + static_assert( std::is_same::ArgType, bool>::value, "flags must be boolean" ); + + explicit BoundFlagLambda( L const &lambda ) : m_lambda( lambda ) {} + + auto setFlag( bool flag ) -> ParserResult override { + return LambdaInvoker::ReturnType>::invoke( m_lambda, flag ); + } + }; + + enum class Optionality { Optional, Required }; + + struct Parser; + + class ParserBase { + public: + virtual ~ParserBase() = default; + virtual auto validate() const -> Result { return Result::ok(); } + virtual auto parse( std::string const& exeName, TokenStream const &tokens) const -> InternalParseResult = 0; + virtual auto cardinality() const -> size_t { return 1; } + + auto parse( Args const &args ) const -> InternalParseResult { + return parse( args.exeName(), TokenStream( args ) ); + } + }; + + template + class ComposableParserImpl : public ParserBase { + public: + template + auto operator|( T const &other ) const -> Parser; + }; + + // Common code and state for Args and Opts + template + class ParserRefImpl : public ComposableParserImpl { + protected: + Optionality m_optionality = Optionality::Optional; + std::shared_ptr m_ref; + std::string m_hint; + std::string m_description; + + explicit ParserRefImpl( std::shared_ptr const &ref ) : m_ref( ref ) {} + + public: + template + ParserRefImpl( T &ref, std::string const &hint ) + : m_ref( std::make_shared>( ref ) ), + m_hint( hint ) + {} + + template + ParserRefImpl( LambdaT const &ref, std::string const &hint ) + : m_ref( std::make_shared>( ref ) ), + m_hint(hint) + {} + + auto operator()( std::string const &description ) -> DerivedT & { + m_description = description; + return static_cast( *this ); + } + + auto optional() -> DerivedT & { + m_optionality = Optionality::Optional; + return static_cast( *this ); + }; + + auto required() -> DerivedT & { + m_optionality = Optionality::Required; + return static_cast( *this ); + }; + + auto isOptional() const -> bool { + return m_optionality == Optionality::Optional; + } + + auto cardinality() const -> size_t override { + if( m_ref->isContainer() ) + return 0; + else + return 1; + } + + auto hint() const -> std::string { return m_hint; } + }; + + class ExeName : public ComposableParserImpl { + std::shared_ptr m_name; + std::shared_ptr m_ref; + + template + static auto makeRef(LambdaT const &lambda) -> std::shared_ptr { + return std::make_shared>( lambda) ; + } + + public: + ExeName() : m_name( std::make_shared( "" ) ) {} + + explicit ExeName( std::string &ref ) : ExeName() { + m_ref = std::make_shared>( ref ); + } + + template + explicit ExeName( LambdaT const& lambda ) : ExeName() { + m_ref = std::make_shared>( lambda ); + } + + // The exe name is not parsed out of the normal tokens, but is handled specially + auto parse( std::string const&, TokenStream const &tokens ) const -> InternalParseResult override { + return InternalParseResult::ok( ParseState( ParseResultType::NoMatch, tokens ) ); + } + + auto name() const -> std::string { return *m_name; } + auto set( std::string const& newName ) -> ParserResult { + + auto lastSlash = newName.find_last_of( "\\/" ); + auto filename = ( lastSlash == std::string::npos ) + ? newName + : newName.substr( lastSlash+1 ); + + *m_name = filename; + if( m_ref ) + return m_ref->setValue( filename ); + else + return ParserResult::ok( ParseResultType::Matched ); + } + }; + + class Arg : public ParserRefImpl { + public: + using ParserRefImpl::ParserRefImpl; + + auto parse( std::string const &, TokenStream const &tokens ) const -> InternalParseResult override { + auto validationResult = validate(); + if( !validationResult ) + return InternalParseResult( validationResult ); + + auto remainingTokens = tokens; + auto const &token = *remainingTokens; + if( token.type != TokenType::Argument ) + return InternalParseResult::ok( ParseState( ParseResultType::NoMatch, remainingTokens ) ); + + auto result = m_ref->setValue( remainingTokens->token ); + if( !result ) + return InternalParseResult( result ); + else + return InternalParseResult::ok( ParseState( ParseResultType::Matched, ++remainingTokens ) ); + } + }; + + inline auto normaliseOpt( std::string const &optName ) -> std::string { +#ifdef CATCH_PLATFORM_WINDOWS + if( optName[0] == '/' ) + return "-" + optName.substr( 1 ); + else +#endif + return optName; + } + + class Opt : public ParserRefImpl { + protected: + std::vector m_optNames; + + public: + template + explicit Opt( LambdaT const &ref ) : ParserRefImpl( std::make_shared>( ref ) ) {} + + explicit Opt( bool &ref ) : ParserRefImpl( std::make_shared( ref ) ) {} + + template + Opt( LambdaT const &ref, std::string const &hint ) : ParserRefImpl( ref, hint ) {} + + template + Opt( T &ref, std::string const &hint ) : ParserRefImpl( ref, hint ) {} + + auto operator[]( std::string const &optName ) -> Opt & { + m_optNames.push_back( optName ); + return *this; + } + + auto getHelpColumns() const -> std::vector { + std::ostringstream oss; + bool first = true; + for( auto const &opt : m_optNames ) { + if (first) + first = false; + else + oss << ", "; + oss << opt; + } + if( !m_hint.empty() ) + oss << " <" << m_hint << ">"; + return { { oss.str(), m_description } }; + } + + auto isMatch( std::string const &optToken ) const -> bool { + auto normalisedToken = normaliseOpt( optToken ); + for( auto const &name : m_optNames ) { + if( normaliseOpt( name ) == normalisedToken ) + return true; + } + return false; + } + + using ParserBase::parse; + + auto parse( std::string const&, TokenStream const &tokens ) const -> InternalParseResult override { + auto validationResult = validate(); + if( !validationResult ) + return InternalParseResult( validationResult ); + + auto remainingTokens = tokens; + if( remainingTokens && remainingTokens->type == TokenType::Option ) { + auto const &token = *remainingTokens; + if( isMatch(token.token ) ) { + if( m_ref->isFlag() ) { + auto result = m_ref->setFlag( true ); + if( !result ) + return InternalParseResult( result ); + if( result.value() == ParseResultType::ShortCircuitAll ) + return InternalParseResult::ok( ParseState( result.value(), remainingTokens ) ); + } else { + ++remainingTokens; + if( !remainingTokens ) + return InternalParseResult::runtimeError( "Expected argument following " + token.token ); + auto const &argToken = *remainingTokens; + if( argToken.type != TokenType::Argument ) + return InternalParseResult::runtimeError( "Expected argument following " + token.token ); + auto result = m_ref->setValue( argToken.token ); + if( !result ) + return InternalParseResult( result ); + if( result.value() == ParseResultType::ShortCircuitAll ) + return InternalParseResult::ok( ParseState( result.value(), remainingTokens ) ); + } + return InternalParseResult::ok( ParseState( ParseResultType::Matched, ++remainingTokens ) ); + } + } + return InternalParseResult::ok( ParseState( ParseResultType::NoMatch, remainingTokens ) ); + } + + auto validate() const -> Result override { + if( m_optNames.empty() ) + return Result::logicError( "No options supplied to Opt" ); + for( auto const &name : m_optNames ) { + if( name.empty() ) + return Result::logicError( "Option name cannot be empty" ); +#ifdef CATCH_PLATFORM_WINDOWS + if( name[0] != '-' && name[0] != '/' ) + return Result::logicError( "Option name must begin with '-' or '/'" ); +#else + if( name[0] != '-' ) + return Result::logicError( "Option name must begin with '-'" ); +#endif + } + return ParserRefImpl::validate(); + } + }; + + struct Help : Opt { + Help( bool &showHelpFlag ) + : Opt([&]( bool flag ) { + showHelpFlag = flag; + return ParserResult::ok( ParseResultType::ShortCircuitAll ); + }) + { + static_cast( *this ) + ("display usage information") + ["-?"]["-h"]["--help"] + .optional(); + } + }; + + struct Parser : ParserBase { + + mutable ExeName m_exeName; + std::vector m_options; + std::vector m_args; + + auto operator|=( ExeName const &exeName ) -> Parser & { + m_exeName = exeName; + return *this; + } + + auto operator|=( Arg const &arg ) -> Parser & { + m_args.push_back(arg); + return *this; + } + + auto operator|=( Opt const &opt ) -> Parser & { + m_options.push_back(opt); + return *this; + } + + auto operator|=( Parser const &other ) -> Parser & { + m_options.insert(m_options.end(), other.m_options.begin(), other.m_options.end()); + m_args.insert(m_args.end(), other.m_args.begin(), other.m_args.end()); + return *this; + } + + template + auto operator|( T const &other ) const -> Parser { + return Parser( *this ) |= other; + } + + auto getHelpColumns() const -> std::vector { + std::vector cols; + for (auto const &o : m_options) { + auto childCols = o.getHelpColumns(); + cols.insert( cols.end(), childCols.begin(), childCols.end() ); + } + return cols; + } + + void writeToStream( std::ostream &os ) const { + if (!m_exeName.name().empty()) { + os << "usage:\n" << " " << m_exeName.name() << " "; + bool required = true, first = true; + for( auto const &arg : m_args ) { + if (first) + first = false; + else + os << " "; + if( arg.isOptional() && required ) { + os << "["; + required = false; + } + os << "<" << arg.hint() << ">"; + if( arg.cardinality() == 0 ) + os << " ... "; + } + if( !required ) + os << "]"; + if( !m_options.empty() ) + os << " options"; + os << "\n\nwhere options are:" << std::endl; + } + + auto rows = getHelpColumns(); + size_t consoleWidth = CATCH_CLARA_CONFIG_CONSOLE_WIDTH; + size_t optWidth = 0; + for( auto const &cols : rows ) + optWidth = (std::max)(optWidth, cols.left.size() + 2); + + for( auto const &cols : rows ) { + auto row = + TextFlow::Column( cols.left ).width( optWidth ).indent( 2 ) + + TextFlow::Spacer(4) + + TextFlow::Column( cols.right ).width( consoleWidth - 7 - optWidth ); + os << row << std::endl; + } + } + + friend auto operator<<( std::ostream &os, Parser const &parser ) -> std::ostream& { + parser.writeToStream( os ); + return os; + } + + auto validate() const -> Result override { + for( auto const &opt : m_options ) { + auto result = opt.validate(); + if( !result ) + return result; + } + for( auto const &arg : m_args ) { + auto result = arg.validate(); + if( !result ) + return result; + } + return Result::ok(); + } + + using ParserBase::parse; + + auto parse( std::string const& exeName, TokenStream const &tokens ) const -> InternalParseResult override { + + struct ParserInfo { + ParserBase const* parser = nullptr; + size_t count = 0; + }; + const size_t totalParsers = m_options.size() + m_args.size(); + assert( totalParsers < 512 ); + // ParserInfo parseInfos[totalParsers]; // <-- this is what we really want to do + ParserInfo parseInfos[512]; + + { + size_t i = 0; + for (auto const &opt : m_options) parseInfos[i++].parser = &opt; + for (auto const &arg : m_args) parseInfos[i++].parser = &arg; + } + + m_exeName.set( exeName ); + + auto result = InternalParseResult::ok( ParseState( ParseResultType::NoMatch, tokens ) ); + while( result.value().remainingTokens() ) { + bool tokenParsed = false; + + for( size_t i = 0; i < totalParsers; ++i ) { + auto& parseInfo = parseInfos[i]; + if( parseInfo.parser->cardinality() == 0 || parseInfo.count < parseInfo.parser->cardinality() ) { + result = parseInfo.parser->parse(exeName, result.value().remainingTokens()); + if (!result) + return result; + if (result.value().type() != ParseResultType::NoMatch) { + tokenParsed = true; + ++parseInfo.count; + break; + } + } + } + + if( result.value().type() == ParseResultType::ShortCircuitAll ) + return result; + if( !tokenParsed ) + return InternalParseResult::runtimeError( "Unrecognised token: " + result.value().remainingTokens()->token ); + } + // !TBD Check missing required options + return result; + } + }; + + template + template + auto ComposableParserImpl::operator|( T const &other ) const -> Parser { + return Parser() | static_cast( *this ) | other; + } +} // namespace detail + +// A Combined parser +using detail::Parser; + +// A parser for options +using detail::Opt; + +// A parser for arguments +using detail::Arg; + +// Wrapper for argc, argv from main() +using detail::Args; + +// Specifies the name of the executable +using detail::ExeName; + +// Convenience wrapper for option parser that specifies the help option +using detail::Help; + +// enum of result types from a parse +using detail::ParseResultType; + +// Result type for parser operation +using detail::ParserResult; + +}} // namespace Catch::clara + +// end clara.hpp +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + +// Restore Clara's value for console width, if present +#ifdef CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH +#define CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH +#undef CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH +#endif + +// end catch_clara.h +namespace Catch { + + clara::Parser makeCommandLineParser( ConfigData& config ); + +} // end namespace Catch + +// end catch_commandline.h +#include +#include + +namespace Catch { + + clara::Parser makeCommandLineParser( ConfigData& config ) { + + using namespace clara; + + auto const setWarning = [&]( std::string const& warning ) { + if( warning != "NoAssertions" ) + return ParserResult::runtimeError( "Unrecognised warning: '" + warning + "'" ); + config.warnings = static_cast( config.warnings | WarnAbout::NoAssertions ); + return ParserResult::ok( ParseResultType::Matched ); + }; + auto const loadTestNamesFromFile = [&]( std::string const& filename ) { + std::ifstream f( filename.c_str() ); + if( !f.is_open() ) + return ParserResult::runtimeError( "Unable to load input file: '" + filename + "'" ); + + std::string line; + while( std::getline( f, line ) ) { + line = trim(line); + if( !line.empty() && !startsWith( line, '#' ) ) { + if( !startsWith( line, '"' ) ) + line = '"' + line + '"'; + config.testsOrTags.push_back( line + ',' ); + } + } + return ParserResult::ok( ParseResultType::Matched ); + }; + auto const setTestOrder = [&]( std::string const& order ) { + if( startsWith( "declared", order ) ) + config.runOrder = RunTests::InDeclarationOrder; + else if( startsWith( "lexical", order ) ) + config.runOrder = RunTests::InLexicographicalOrder; + else if( startsWith( "random", order ) ) + config.runOrder = RunTests::InRandomOrder; + else + return clara::ParserResult::runtimeError( "Unrecognised ordering: '" + order + "'" ); + return ParserResult::ok( ParseResultType::Matched ); + }; + auto const setRngSeed = [&]( std::string const& seed ) { + if( seed != "time" ) + return clara::detail::convertInto( seed, config.rngSeed ); + config.rngSeed = static_cast( std::time(nullptr) ); + return ParserResult::ok( ParseResultType::Matched ); + }; + auto const setColourUsage = [&]( std::string const& useColour ) { + auto mode = toLower( useColour ); + + if( mode == "yes" ) + config.useColour = UseColour::Yes; + else if( mode == "no" ) + config.useColour = UseColour::No; + else if( mode == "auto" ) + config.useColour = UseColour::Auto; + else + return ParserResult::runtimeError( "colour mode must be one of: auto, yes or no. '" + useColour + "' not recognised" ); + return ParserResult::ok( ParseResultType::Matched ); + }; + auto const setWaitForKeypress = [&]( std::string const& keypress ) { + auto keypressLc = toLower( keypress ); + if( keypressLc == "start" ) + config.waitForKeypress = WaitForKeypress::BeforeStart; + else if( keypressLc == "exit" ) + config.waitForKeypress = WaitForKeypress::BeforeExit; + else if( keypressLc == "both" ) + config.waitForKeypress = WaitForKeypress::BeforeStartAndExit; + else + return ParserResult::runtimeError( "keypress argument must be one of: start, exit or both. '" + keypress + "' not recognised" ); + return ParserResult::ok( ParseResultType::Matched ); + }; + auto const setVerbosity = [&]( std::string const& verbosity ) { + auto lcVerbosity = toLower( verbosity ); + if( lcVerbosity == "quiet" ) + config.verbosity = Verbosity::Quiet; + else if( lcVerbosity == "normal" ) + config.verbosity = Verbosity::Normal; + else if( lcVerbosity == "high" ) + config.verbosity = Verbosity::High; + else + return ParserResult::runtimeError( "Unrecognised verbosity, '" + verbosity + "'" ); + return ParserResult::ok( ParseResultType::Matched ); + }; + + auto cli + = ExeName( config.processName ) + | Help( config.showHelp ) + | Opt( config.listTests ) + ["-l"]["--list-tests"] + ( "list all/matching test cases" ) + | Opt( config.listTags ) + ["-t"]["--list-tags"] + ( "list all/matching tags" ) + | Opt( config.showSuccessfulTests ) + ["-s"]["--success"] + ( "include successful tests in output" ) + | Opt( config.shouldDebugBreak ) + ["-b"]["--break"] + ( "break into debugger on failure" ) + | Opt( config.noThrow ) + ["-e"]["--nothrow"] + ( "skip exception tests" ) + | Opt( config.showInvisibles ) + ["-i"]["--invisibles"] + ( "show invisibles (tabs, newlines)" ) + | Opt( config.outputFilename, "filename" ) + ["-o"]["--out"] + ( "output filename" ) + | Opt( config.reporterNames, "name" ) + ["-r"]["--reporter"] + ( "reporter to use (defaults to console)" ) + | Opt( config.name, "name" ) + ["-n"]["--name"] + ( "suite name" ) + | Opt( [&]( bool ){ config.abortAfter = 1; } ) + ["-a"]["--abort"] + ( "abort at first failure" ) + | Opt( [&]( int x ){ config.abortAfter = x; }, "no. failures" ) + ["-x"]["--abortx"] + ( "abort after x failures" ) + | Opt( setWarning, "warning name" ) + ["-w"]["--warn"] + ( "enable warnings" ) + | Opt( [&]( bool flag ) { config.showDurations = flag ? ShowDurations::Always : ShowDurations::Never; }, "yes|no" ) + ["-d"]["--durations"] + ( "show test durations" ) + | Opt( loadTestNamesFromFile, "filename" ) + ["-f"]["--input-file"] + ( "load test names to run from a file" ) + | Opt( config.filenamesAsTags ) + ["-#"]["--filenames-as-tags"] + ( "adds a tag for the filename" ) + | Opt( config.sectionsToRun, "section name" ) + ["-c"]["--section"] + ( "specify section to run" ) + | Opt( setVerbosity, "quiet|normal|high" ) + ["-v"]["--verbosity"] + ( "set output verbosity" ) + | Opt( config.listTestNamesOnly ) + ["--list-test-names-only"] + ( "list all/matching test cases names only" ) + | Opt( config.listReporters ) + ["--list-reporters"] + ( "list all reporters" ) + | Opt( setTestOrder, "decl|lex|rand" ) + ["--order"] + ( "test case order (defaults to decl)" ) + | Opt( setRngSeed, "'time'|number" ) + ["--rng-seed"] + ( "set a specific seed for random numbers" ) + | Opt( setColourUsage, "yes|no" ) + ["--use-colour"] + ( "should output be colourised" ) + | Opt( config.libIdentify ) + ["--libidentify"] + ( "report name and version according to libidentify standard" ) + | Opt( setWaitForKeypress, "start|exit|both" ) + ["--wait-for-keypress"] + ( "waits for a keypress before exiting" ) + | Opt( config.benchmarkResolutionMultiple, "multiplier" ) + ["--benchmark-resolution-multiple"] + ( "multiple of clock resolution to run benchmarks" ) + + | Arg( config.testsOrTags, "test name|pattern|tags" ) + ( "which test or tests to use" ); + + return cli; + } + +} // end namespace Catch +// end catch_commandline.cpp +// start catch_common.cpp + +#include +#include + +namespace Catch { + + SourceLineInfo::SourceLineInfo( char const* _file, std::size_t _line ) noexcept + : file( _file ), + line( _line ) + {} + bool SourceLineInfo::empty() const noexcept { + return file[0] == '\0'; + } + bool SourceLineInfo::operator == ( SourceLineInfo const& other ) const noexcept { + return line == other.line && (file == other.file || std::strcmp(file, other.file) == 0); + } + bool SourceLineInfo::operator < ( SourceLineInfo const& other ) const noexcept { + return line < other.line || ( line == other.line && (std::strcmp(file, other.file) < 0)); + } + + 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; + } + + bool isTrue( bool value ){ return value; } + bool alwaysTrue() { return true; } + bool alwaysFalse() { return false; } + + std::string StreamEndStop::operator+() const { + return std::string(); + } + + NonCopyable::NonCopyable() = default; + NonCopyable::~NonCopyable() = default; + +} +// end catch_common.cpp +// start catch_config.cpp + +namespace Catch { + + Config::Config( ConfigData const& data ) + : m_data( data ), + m_stream( openStream() ) + { + if( !data.testsOrTags.empty() ) { + TestSpecParser parser( ITagAliasRegistry::get() ); + for( auto const& testOrTags : data.testsOrTags ) + parser.parse( testOrTags ); + m_testSpec = parser.testSpec(); + } + } + + std::string const& Config::getFilename() const { + return m_data.outputFilename ; + } + + bool Config::listTests() const { return m_data.listTests; } + bool Config::listTestNamesOnly() const { return m_data.listTestNamesOnly; } + bool Config::listTags() const { return m_data.listTags; } + bool Config::listReporters() const { return m_data.listReporters; } + + std::string Config::getProcessName() const { return m_data.processName; } + + std::vector const& Config::getReporterNames() const { return m_data.reporterNames; } + std::vector const& Config::getSectionsToRun() const { return m_data.sectionsToRun; } + + TestSpec const& Config::testSpec() const { return m_testSpec; } + + bool Config::showHelp() const { return m_data.showHelp; } + + // IConfig interface + bool Config::allowThrows() const { return !m_data.noThrow; } + std::ostream& Config::stream() const { return m_stream->stream(); } + std::string Config::name() const { return m_data.name.empty() ? m_data.processName : m_data.name; } + bool Config::includeSuccessfulResults() const { return m_data.showSuccessfulTests; } + bool Config::warnAboutMissingAssertions() const { return m_data.warnings & WarnAbout::NoAssertions; } + ShowDurations::OrNot Config::showDurations() const { return m_data.showDurations; } + RunTests::InWhatOrder Config::runOrder() const { return m_data.runOrder; } + unsigned int Config::rngSeed() const { return m_data.rngSeed; } + int Config::benchmarkResolutionMultiple() const { return m_data.benchmarkResolutionMultiple; } + UseColour::YesOrNo Config::useColour() const { return m_data.useColour; } + bool Config::shouldDebugBreak() const { return m_data.shouldDebugBreak; } + int Config::abortAfter() const { return m_data.abortAfter; } + bool Config::showInvisibles() const { return m_data.showInvisibles; } + Verbosity Config::verbosity() const { return m_data.verbosity; } + + IStream const* Config::openStream() { + if( m_data.outputFilename.empty() ) + return new CoutStream(); + else if( m_data.outputFilename[0] == '%' ) { + if( m_data.outputFilename == "%debug" ) + return new DebugOutStream(); + else + CATCH_ERROR( "Unrecognised stream: '" << m_data.outputFilename << "'" ); + } + else + return new FileStream( m_data.outputFilename ); + } + +} // end namespace Catch +// end catch_config.cpp +// start catch_console_colour.cpp + +#if defined(__clang__) +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wexit-time-destructors" +#endif + +// start catch_errno_guard.h + +namespace Catch { + + class ErrnoGuard { + public: + ErrnoGuard(); + ~ErrnoGuard(); + private: + int m_oldErrno; + }; + +} + +// end catch_errno_guard.h +// start catch_windows_h_proxy.h + + +#if defined(CATCH_PLATFORM_WINDOWS) + +#if !defined(NOMINMAX) && !defined(CATCH_CONFIG_NO_NOMINMAX) +# define CATCH_DEFINED_NOMINMAX # define NOMINMAX #endif -#ifdef CATCH_DEFINES_WIN32_LEAN_AND_MEAN +#if !defined(WIN32_LEAN_AND_MEAN) && !defined(CATCH_CONFIG_NO_WIN32_LEAN_AND_MEAN) +# define CATCH_DEFINED_WIN32_LEAN_AND_MEAN # define WIN32_LEAN_AND_MEAN #endif @@ -6381,1471 +5909,21 @@ namespace Catch { #include #endif -#ifdef CATCH_DEFINES_NOMINMAX +#ifdef CATCH_DEFINED_NOMINMAX # undef NOMINMAX #endif -#ifdef CATCH_DEFINES_WIN32_LEAN_AND_MEAN +#ifdef CATCH_DEFINED_WIN32_LEAN_AND_MEAN # undef WIN32_LEAN_AND_MEAN #endif +#endif // defined(CATCH_PLATFORM_WINDOWS) -# if !defined ( CATCH_CONFIG_WINDOWS_SEH ) - -namespace Catch { - struct FatalConditionHandler { - void reset() {} - }; -} - -# else // CATCH_CONFIG_WINDOWS_SEH is defined - -namespace Catch { - - struct SignalDefs { DWORD id; const char* name; }; - extern SignalDefs signalDefs[]; - // There is no 1-1 mapping between signals and windows exceptions. - // Windows can easily distinguish between SO and SigSegV, - // but SigInt, SigTerm, etc are handled differently. - SignalDefs signalDefs[] = { - { EXCEPTION_ILLEGAL_INSTRUCTION, "SIGILL - Illegal instruction signal" }, - { EXCEPTION_STACK_OVERFLOW, "SIGSEGV - Stack overflow" }, - { EXCEPTION_ACCESS_VIOLATION, "SIGSEGV - Segmentation violation signal" }, - { EXCEPTION_INT_DIVIDE_BY_ZERO, "Divide by zero error" }, - }; - - struct FatalConditionHandler { - - static LONG CALLBACK handleVectoredException(PEXCEPTION_POINTERS ExceptionInfo) { - for (int i = 0; i < sizeof(signalDefs) / sizeof(SignalDefs); ++i) { - if (ExceptionInfo->ExceptionRecord->ExceptionCode == signalDefs[i].id) { - reportFatal(signalDefs[i].name); - } - } - // If its not an exception we care about, pass it along. - // This stops us from eating debugger breaks etc. - return EXCEPTION_CONTINUE_SEARCH; - } - - FatalConditionHandler() { - isSet = true; - // 32k seems enough for Catch to handle stack overflow, - // but the value was found experimentally, so there is no strong guarantee - guaranteeSize = 32 * 1024; - exceptionHandlerHandle = CATCH_NULL; - // Register as first handler in current chain - exceptionHandlerHandle = AddVectoredExceptionHandler(1, handleVectoredException); - // Pass in guarantee size to be filled - SetThreadStackGuarantee(&guaranteeSize); - } - - static void reset() { - if (isSet) { - // Unregister handler and restore the old guarantee - RemoveVectoredExceptionHandler(exceptionHandlerHandle); - SetThreadStackGuarantee(&guaranteeSize); - exceptionHandlerHandle = CATCH_NULL; - isSet = false; - } - } - - ~FatalConditionHandler() { - reset(); - } - private: - static bool isSet; - static ULONG guaranteeSize; - static PVOID exceptionHandlerHandle; - }; - - bool FatalConditionHandler::isSet = false; - ULONG FatalConditionHandler::guaranteeSize = 0; - PVOID FatalConditionHandler::exceptionHandlerHandle = CATCH_NULL; - -} // namespace Catch - -# endif // CATCH_CONFIG_WINDOWS_SEH - -#else // Not Windows - assumed to be POSIX compatible ////////////////////////// - -# if !defined(CATCH_CONFIG_POSIX_SIGNALS) - -namespace Catch { - struct FatalConditionHandler { - void reset() {} - }; -} - -# else // CATCH_CONFIG_POSIX_SIGNALS is defined - -#include - -namespace Catch { - - struct SignalDefs { - int id; - const char* name; - }; - extern SignalDefs signalDefs[]; - SignalDefs signalDefs[] = { - { SIGINT, "SIGINT - Terminal interrupt signal" }, - { SIGILL, "SIGILL - Illegal instruction signal" }, - { SIGFPE, "SIGFPE - Floating point error signal" }, - { SIGSEGV, "SIGSEGV - Segmentation violation signal" }, - { SIGTERM, "SIGTERM - Termination request signal" }, - { SIGABRT, "SIGABRT - Abort (abnormal termination) signal" } - }; - - struct FatalConditionHandler { - - static bool isSet; - static struct sigaction oldSigActions [sizeof(signalDefs)/sizeof(SignalDefs)]; - static stack_t oldSigStack; - static char altStackMem[SIGSTKSZ]; - - static void handleSignal( int sig ) { - std::string name = ""; - for (std::size_t i = 0; i < sizeof(signalDefs) / sizeof(SignalDefs); ++i) { - SignalDefs &def = signalDefs[i]; - if (sig == def.id) { - name = def.name; - break; - } - } - reset(); - reportFatal(name); - raise( sig ); - } - - FatalConditionHandler() { - isSet = true; - stack_t sigStack; - sigStack.ss_sp = altStackMem; - sigStack.ss_size = SIGSTKSZ; - sigStack.ss_flags = 0; - sigaltstack(&sigStack, &oldSigStack); - struct sigaction sa = { 0 }; - - sa.sa_handler = handleSignal; - sa.sa_flags = SA_ONSTACK; - for (std::size_t i = 0; i < sizeof(signalDefs)/sizeof(SignalDefs); ++i) { - sigaction(signalDefs[i].id, &sa, &oldSigActions[i]); - } - } - - ~FatalConditionHandler() { - reset(); - } - static void reset() { - if( isSet ) { - // Set signals back to previous values -- hopefully nobody overwrote them in the meantime - for( std::size_t i = 0; i < sizeof(signalDefs)/sizeof(SignalDefs); ++i ) { - sigaction(signalDefs[i].id, &oldSigActions[i], CATCH_NULL); - } - // Return the old stack - sigaltstack(&oldSigStack, CATCH_NULL); - isSet = false; - } - } - }; - - bool FatalConditionHandler::isSet = false; - struct sigaction FatalConditionHandler::oldSigActions[sizeof(signalDefs)/sizeof(SignalDefs)] = {}; - stack_t FatalConditionHandler::oldSigStack = {}; - char FatalConditionHandler::altStackMem[SIGSTKSZ] = {}; - -} // namespace Catch - -# endif // CATCH_CONFIG_POSIX_SIGNALS - -#endif // not Windows - -#include -#include - -namespace Catch { - - class StreamRedirect { - - public: - StreamRedirect( std::ostream& stream, std::string& targetString ) - : m_stream( stream ), - m_prevBuf( stream.rdbuf() ), - m_targetString( targetString ) - { - stream.rdbuf( m_oss.rdbuf() ); - } - - ~StreamRedirect() { - m_targetString += m_oss.str(); - m_stream.rdbuf( m_prevBuf ); - } - - private: - std::ostream& m_stream; - std::streambuf* m_prevBuf; - std::ostringstream m_oss; - std::string& m_targetString; - }; - - // StdErr has two constituent streams in C++, std::cerr and std::clog - // This means that we need to redirect 2 streams into 1 to keep proper - // order of writes and cannot use StreamRedirect on its own - class StdErrRedirect { - public: - StdErrRedirect(std::string& targetString) - :m_cerrBuf( cerr().rdbuf() ), m_clogBuf(clog().rdbuf()), - m_targetString(targetString){ - cerr().rdbuf(m_oss.rdbuf()); - clog().rdbuf(m_oss.rdbuf()); - } - ~StdErrRedirect() { - m_targetString += m_oss.str(); - cerr().rdbuf(m_cerrBuf); - clog().rdbuf(m_clogBuf); - } - private: - std::streambuf* m_cerrBuf; - std::streambuf* m_clogBuf; - std::ostringstream m_oss; - std::string& m_targetString; - }; - - /////////////////////////////////////////////////////////////////////////// - - class RunContext : public IResultCapture, public IRunner { - - RunContext( RunContext const& ); - void operator =( RunContext const& ); - - public: - - explicit RunContext( Ptr const& _config, Ptr const& reporter ) - : m_runInfo( _config->name() ), - m_context( getCurrentMutableContext() ), - m_activeTestCase( CATCH_NULL ), - m_config( _config ), - m_reporter( reporter ), - m_shouldReportUnexpected ( true ) - { - m_context.setRunner( this ); - m_context.setConfig( m_config ); - m_context.setResultCapture( this ); - m_reporter->testRunStarting( m_runInfo ); - } - - virtual ~RunContext() { - m_reporter->testRunEnded( TestRunStats( m_runInfo, m_totals, aborting() ) ); - } - - void testGroupStarting( std::string const& testSpec, std::size_t groupIndex, std::size_t groupsCount ) { - m_reporter->testGroupStarting( GroupInfo( testSpec, groupIndex, groupsCount ) ); - } - void testGroupEnded( std::string const& testSpec, Totals const& totals, std::size_t groupIndex, std::size_t groupsCount ) { - m_reporter->testGroupEnded( TestGroupStats( GroupInfo( testSpec, groupIndex, groupsCount ), totals, aborting() ) ); - } - - Totals runTest( TestCase const& testCase ) { - Totals prevTotals = m_totals; - - std::string redirectedCout; - std::string redirectedCerr; - - TestCaseInfo testInfo = testCase.getTestCaseInfo(); - - m_reporter->testCaseStarting( testInfo ); - - m_activeTestCase = &testCase; - - do { - ITracker& rootTracker = m_trackerContext.startRun(); - assert( rootTracker.isSectionTracker() ); - static_cast( rootTracker ).addInitialFilters( m_config->getSectionsToRun() ); - do { - m_trackerContext.startCycle(); - m_testCaseTracker = &SectionTracker::acquire( m_trackerContext, TestCaseTracking::NameAndLocation( testInfo.name, testInfo.lineInfo ) ); - runCurrentTest( redirectedCout, redirectedCerr ); - } - while( !m_testCaseTracker->isSuccessfullyCompleted() && !aborting() ); - } - // !TBD: deprecated - this will be replaced by indexed trackers - while( getCurrentContext().advanceGeneratorsForCurrentTest() && !aborting() ); - - Totals deltaTotals = m_totals.delta( prevTotals ); - if( testInfo.expectedToFail() && deltaTotals.testCases.passed > 0 ) { - deltaTotals.assertions.failed++; - deltaTotals.testCases.passed--; - deltaTotals.testCases.failed++; - } - m_totals.testCases += deltaTotals.testCases; - m_reporter->testCaseEnded( TestCaseStats( testInfo, - deltaTotals, - redirectedCout, - redirectedCerr, - aborting() ) ); - - m_activeTestCase = CATCH_NULL; - m_testCaseTracker = CATCH_NULL; - - return deltaTotals; - } - - Ptr config() const { - return m_config; - } - - private: // IResultCapture - - virtual void assertionEnded( AssertionResult const& result ) { - if( result.getResultType() == ResultWas::Ok ) { - m_totals.assertions.passed++; - } - else if( !result.isOk() ) { - m_totals.assertions.failed++; - } - - // We have no use for the return value (whether messages should be cleared), because messages were made scoped - // and should be let to clear themselves out. - static_cast(m_reporter->assertionEnded(AssertionStats(result, m_messages, m_totals))); - - // Reset working state - m_lastAssertionInfo = AssertionInfo( "", m_lastAssertionInfo.lineInfo, "{Unknown expression after the reported line}" , m_lastAssertionInfo.resultDisposition ); - m_lastResult = result; - } - - virtual bool lastAssertionPassed() - { - return m_totals.assertions.passed == (m_prevPassed + 1); - } - - virtual void assertionPassed() - { - m_totals.assertions.passed++; - m_lastAssertionInfo.capturedExpression = "{Unknown expression after the reported line}"; - m_lastAssertionInfo.macroName = ""; - } - - virtual void assertionRun() - { - m_prevPassed = m_totals.assertions.passed; - } - - virtual bool sectionStarted ( - SectionInfo const& sectionInfo, - Counts& assertions - ) - { - ITracker& sectionTracker = SectionTracker::acquire( m_trackerContext, TestCaseTracking::NameAndLocation( sectionInfo.name, sectionInfo.lineInfo ) ); - if( !sectionTracker.isOpen() ) - return false; - m_activeSections.push_back( §ionTracker ); - - m_lastAssertionInfo.lineInfo = sectionInfo.lineInfo; - - m_reporter->sectionStarting( sectionInfo ); - - assertions = m_totals.assertions; - - return true; - } - bool testForMissingAssertions( Counts& assertions ) { - if( assertions.total() != 0 ) - return false; - if( !m_config->warnAboutMissingAssertions() ) - return false; - if( m_trackerContext.currentTracker().hasChildren() ) - return false; - m_totals.assertions.failed++; - assertions.failed++; - return true; - } - - virtual void sectionEnded( SectionEndInfo const& endInfo ) { - Counts assertions = m_totals.assertions - endInfo.prevAssertions; - bool missingAssertions = testForMissingAssertions( assertions ); - - if( !m_activeSections.empty() ) { - m_activeSections.back()->close(); - m_activeSections.pop_back(); - } - - m_reporter->sectionEnded( SectionStats( endInfo.sectionInfo, assertions, endInfo.durationInSeconds, missingAssertions ) ); - m_messages.clear(); - } - - virtual void sectionEndedEarly( SectionEndInfo const& endInfo ) { - if( m_unfinishedSections.empty() ) - m_activeSections.back()->fail(); - else - m_activeSections.back()->close(); - m_activeSections.pop_back(); - - m_unfinishedSections.push_back( endInfo ); - } - - virtual void pushScopedMessage( MessageInfo const& message ) { - m_messages.push_back( message ); - } - - virtual void popScopedMessage( MessageInfo const& message ) { - m_messages.erase( std::remove( m_messages.begin(), m_messages.end(), message ), m_messages.end() ); - } - - virtual std::string getCurrentTestName() const { - return m_activeTestCase - ? m_activeTestCase->getTestCaseInfo().name - : std::string(); - } - - virtual const AssertionResult* getLastResult() const { - return &m_lastResult; - } - - virtual void exceptionEarlyReported() { - m_shouldReportUnexpected = false; - } - - virtual void handleFatalErrorCondition( std::string const& message ) { - // Don't rebuild the result -- the stringification itself can cause more fatal errors - // Instead, fake a result data. - AssertionResultData tempResult; - tempResult.resultType = ResultWas::FatalErrorCondition; - tempResult.message = message; - AssertionResult result(m_lastAssertionInfo, tempResult); - - getResultCapture().assertionEnded(result); - - handleUnfinishedSections(); - - // Recreate section for test case (as we will lose the one that was in scope) - TestCaseInfo const& testCaseInfo = m_activeTestCase->getTestCaseInfo(); - SectionInfo testCaseSection( testCaseInfo.lineInfo, testCaseInfo.name, testCaseInfo.description ); - - Counts assertions; - assertions.failed = 1; - SectionStats testCaseSectionStats( testCaseSection, assertions, 0, false ); - m_reporter->sectionEnded( testCaseSectionStats ); - - TestCaseInfo testInfo = m_activeTestCase->getTestCaseInfo(); - - Totals deltaTotals; - deltaTotals.testCases.failed = 1; - deltaTotals.assertions.failed = 1; - m_reporter->testCaseEnded( TestCaseStats( testInfo, - deltaTotals, - std::string(), - std::string(), - false ) ); - m_totals.testCases.failed++; - testGroupEnded( std::string(), m_totals, 1, 1 ); - m_reporter->testRunEnded( TestRunStats( m_runInfo, m_totals, false ) ); - } - - public: - // !TBD We need to do this another way! - bool aborting() const { - return m_totals.assertions.failed == static_cast( 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; - m_shouldReportUnexpected = true; - try { - m_lastAssertionInfo = AssertionInfo( "TEST_CASE", testCaseInfo.lineInfo, "", ResultDisposition::Normal ); - - seedRng( *m_config ); - - Timer timer; - timer.start(); - if( m_reporter->getPreferences().shouldRedirectStdOut ) { - StreamRedirect coutRedir( Catch::cout(), redirectedCout ); - StdErrRedirect errRedir( redirectedCerr ); - invokeActiveTestCase(); - } - else { - invokeActiveTestCase(); - } - duration = timer.getElapsedSeconds(); - } - catch( TestFailureException& ) { - // This just means the test was aborted due to failure - } - catch(...) { - // Under CATCH_CONFIG_FAST_COMPILE, unexpected exceptions under REQUIRE assertions - // are reported without translation at the point of origin. - if (m_shouldReportUnexpected) { - makeUnexpectedResultBuilder().useActiveException(); - } - } - m_testCaseTracker->close(); - handleUnfinishedSections(); - m_messages.clear(); - - Counts assertions = m_totals.assertions - prevAssertions; - bool missingAssertions = testForMissingAssertions( assertions ); - - if( testCaseInfo.okToFail() ) { - std::swap( assertions.failedButOk, assertions.failed ); - m_totals.assertions.failed -= assertions.failedButOk; - m_totals.assertions.failedButOk += assertions.failedButOk; - } - - SectionStats testCaseSectionStats( testCaseSection, assertions, duration, missingAssertions ); - m_reporter->sectionEnded( testCaseSectionStats ); - } - - void invokeActiveTestCase() { - FatalConditionHandler fatalConditionHandler; // Handle signals - m_activeTestCase->invoke(); - fatalConditionHandler.reset(); - } - - private: - - ResultBuilder makeUnexpectedResultBuilder() const { - return ResultBuilder( m_lastAssertionInfo.macroName, - m_lastAssertionInfo.lineInfo, - m_lastAssertionInfo.capturedExpression, - m_lastAssertionInfo.resultDisposition ); - } - - void handleUnfinishedSections() { - // If sections ended prematurely due to an exception we stored their - // infos here so we can tear them down outside the unwind process. - for( std::vector::const_reverse_iterator it = m_unfinishedSections.rbegin(), - itEnd = m_unfinishedSections.rend(); - it != itEnd; - ++it ) - sectionEnded( *it ); - m_unfinishedSections.clear(); - } - - TestRunInfo m_runInfo; - IMutableContext& m_context; - TestCase const* m_activeTestCase; - ITracker* m_testCaseTracker; - ITracker* m_currentSectionTracker; - AssertionResult m_lastResult; - - Ptr m_config; - Totals m_totals; - Ptr m_reporter; - std::vector m_messages; - AssertionInfo m_lastAssertionInfo; - std::vector m_unfinishedSections; - std::vector m_activeSections; - TrackerContext m_trackerContext; - size_t m_prevPassed; - bool m_shouldReportUnexpected; - }; - - IResultCapture& getResultCapture() { - if( IResultCapture* capture = getCurrentContext().getResultCapture() ) - return *capture; - else - throw std::logic_error( "No result capture instance" ); - } - -} // end namespace Catch - -// #included from: internal/catch_version.h -#define TWOBLUECUBES_CATCH_VERSION_H_INCLUDED - -namespace Catch { - - // Versioning information - struct Version { - Version( unsigned int _majorVersion, - unsigned int _minorVersion, - unsigned int _patchNumber, - char const * const _branchName, - unsigned int _buildNumber ); - - unsigned int const majorVersion; - unsigned int const minorVersion; - unsigned int const patchNumber; - - // buildNumber is only used if branchName is not null - char const * const branchName; - unsigned int const buildNumber; - - friend std::ostream& operator << ( std::ostream& os, Version const& version ); - - private: - void operator=( Version const& ); - }; - - inline Version libraryVersion(); -} - -#include -#include -#include - -namespace Catch { - - Ptr createReporter( std::string const& reporterName, Ptr const& config ) { - Ptr reporter = getRegistryHub().getReporterRegistry().create( reporterName, config.get() ); - if( !reporter ) { - std::ostringstream oss; - oss << "No reporter registered with name: '" << reporterName << "'"; - throw std::domain_error( oss.str() ); - } - return reporter; - } - -#if !defined(CATCH_CONFIG_DEFAULT_REPORTER) -#define CATCH_CONFIG_DEFAULT_REPORTER "console" -#endif - - Ptr makeReporter( Ptr const& config ) { - std::vector reporters = config->getReporterNames(); - if( reporters.empty() ) - reporters.push_back( CATCH_CONFIG_DEFAULT_REPORTER ); - - Ptr reporter; - for( std::vector::const_iterator it = reporters.begin(), itEnd = reporters.end(); - it != itEnd; - ++it ) - reporter = addReporter( reporter, createReporter( *it, config ) ); - return reporter; - } - Ptr addListeners( Ptr const& config, Ptr reporters ) { - IReporterRegistry::Listeners listeners = getRegistryHub().getReporterRegistry().getListeners(); - for( IReporterRegistry::Listeners::const_iterator it = listeners.begin(), itEnd = listeners.end(); - it != itEnd; - ++it ) - reporters = addReporter(reporters, (*it)->create( ReporterConfig( config ) ) ); - return reporters; - } - - Totals runTests( Ptr const& config ) { - - Ptr iconfig = config.get(); - - Ptr reporter = makeReporter( config ); - reporter = addListeners( iconfig, reporter ); - - RunContext context( iconfig, reporter ); - - Totals totals; - - context.testGroupStarting( config->name(), 1, 1 ); - - TestSpec testSpec = config->testSpec(); - if( !testSpec.hasFilters() ) - testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "~[.]" ).testSpec(); // All not hidden tests - - std::vector const& allTestCases = getAllTestCasesSorted( *iconfig ); - for( std::vector::const_iterator it = allTestCases.begin(), itEnd = allTestCases.end(); - it != itEnd; - ++it ) { - if( !context.aborting() && matchTest( *it, testSpec, *iconfig ) ) - totals += context.runTest( *it ); - else - reporter->skipTest( *it ); - } - - context.testGroupEnded( iconfig->name(), totals, 1, 1 ); - return totals; - } - - void applyFilenamesAsTags( IConfig const& config ) { - std::vector const& tests = getAllTestCasesSorted( config ); - for(std::size_t i = 0; i < tests.size(); ++i ) { - TestCase& test = const_cast( tests[i] ); - std::set tags = test.tags; - - std::string filename = test.lineInfo.file; - std::string::size_type lastSlash = filename.find_last_of( "\\/" ); - if( lastSlash != std::string::npos ) - filename = filename.substr( lastSlash+1 ); - - std::string::size_type lastDot = filename.find_last_of( '.' ); - if( lastDot != std::string::npos ) - filename = filename.substr( 0, lastDot ); - - tags.insert( '#' + filename ); - setTags( test, tags ); - } - } - - class Session : NonCopyable { - static bool alreadyInstantiated; - - public: - - struct OnUnusedOptions { enum DoWhat { Ignore, Fail }; }; - - Session() - : m_cli( makeCommandLineParser() ) { - if( alreadyInstantiated ) { - std::string msg = "Only one instance of Catch::Session can ever be used"; - Catch::cerr() << msg << std::endl; - throw std::logic_error( msg ); - } - alreadyInstantiated = true; - } - ~Session() { - Catch::cleanUp(); - } - - void showHelp( std::string const& processName ) { - Catch::cout() << "\nCatch v" << libraryVersion() << "\n"; - - m_cli.usage( Catch::cout(), processName ); - Catch::cout() << "For more detail usage please see the project docs\n" << std::endl; - } - - int applyCommandLine( int argc, char const* const* const argv, OnUnusedOptions::DoWhat unusedOptionBehaviour = OnUnusedOptions::Fail ) { - try { - m_cli.setThrowOnUnrecognisedTokens( unusedOptionBehaviour == OnUnusedOptions::Fail ); - m_unusedTokens = m_cli.parseInto( Clara::argsToVector( argc, argv ), m_configData ); - if( m_configData.showHelp ) - showHelp( m_configData.processName ); - m_config.reset(); - } - catch( std::exception& ex ) { - { - Colour colourGuard( Colour::Red ); - Catch::cerr() - << "\nError(s) in input:\n" - << Text( ex.what(), TextAttributes().setIndent(2) ) - << "\n\n"; - } - m_cli.usage( Catch::cout(), m_configData.processName ); - return (std::numeric_limits::max)(); - } - return 0; - } - - void useConfigData( ConfigData const& _configData ) { - m_configData = _configData; - m_config.reset(); - } - - int run( int argc, char const* const* const argv ) { - - int returnCode = applyCommandLine( argc, argv ); - if( returnCode == 0 ) - returnCode = run(); - return returnCode; - } - - #if defined(WIN32) && defined(UNICODE) - int run( int argc, wchar_t const* const* const argv ) { - - char **utf8Argv = new char *[ argc ]; - - for ( int i = 0; i < argc; ++i ) { - int bufSize = WideCharToMultiByte( CP_UTF8, 0, argv[i], -1, NULL, 0, NULL, NULL ); - - utf8Argv[ i ] = new char[ bufSize ]; - - WideCharToMultiByte( CP_UTF8, 0, argv[i], -1, utf8Argv[i], bufSize, NULL, NULL ); - } - - int returnCode = applyCommandLine( argc, utf8Argv ); - if( returnCode == 0 ) - returnCode = run(); - - for ( int i = 0; i < argc; ++i ) - delete [] utf8Argv[ i ]; - - delete [] utf8Argv; - - return returnCode; - } - #endif - - int run() { - if( m_configData.showHelp ) - return 0; - - try - { - config(); // Force config to be constructed - - seedRng( *m_config ); - - if( m_configData.filenamesAsTags ) - applyFilenamesAsTags( *m_config ); - - // Handle list request - if( Option listed = list( config() ) ) - return static_cast( *listed ); - - return static_cast( runTests( m_config ).assertions.failed ); - } - catch( std::exception& ex ) { - Catch::cerr() << ex.what() << std::endl; - return (std::numeric_limits::max)(); - } - } - - 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 ); - return *m_config; - } - private: - Clara::CommandLine m_cli; - std::vector m_unusedTokens; - ConfigData m_configData; - Ptr m_config; - }; - - bool Session::alreadyInstantiated = false; - -} // end namespace Catch - -// #included from: catch_registry_hub.hpp -#define TWOBLUECUBES_CATCH_REGISTRY_HUB_HPP_INCLUDED - -// #included from: catch_test_case_registry_impl.hpp -#define TWOBLUECUBES_CATCH_TEST_CASE_REGISTRY_IMPL_HPP_INCLUDED - -#include -#include -#include -#include - -namespace Catch { - - struct RandomNumberGenerator { - typedef std::ptrdiff_t result_type; - - result_type operator()( result_type n ) const { return std::rand() % n; } - -#ifdef CATCH_CONFIG_CPP11_SHUFFLE - static constexpr result_type min() { return 0; } - static constexpr result_type max() { return 1000000; } - result_type operator()() const { return std::rand() % max(); } -#endif - template - static void shuffle( V& vector ) { - RandomNumberGenerator rng; -#ifdef CATCH_CONFIG_CPP11_SHUFFLE - std::shuffle( vector.begin(), vector.end(), rng ); -#else - std::random_shuffle( vector.begin(), vector.end(), rng ); -#endif - } - }; - - inline std::vector sortTests( IConfig const& config, std::vector const& unsortedTestCases ) { - - std::vector sorted = unsortedTestCases; - - switch( config.runOrder() ) { - case RunTests::InLexicographicalOrder: - std::sort( sorted.begin(), sorted.end() ); - break; - case RunTests::InRandomOrder: - { - seedRng( config ); - RandomNumberGenerator::shuffle( sorted ); - } - break; - case RunTests::InDeclarationOrder: - // already in declaration order - break; - } - return sorted; - } - bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config ) { - return testSpec.matches( testCase ) && ( config.allowThrows() || !testCase.throws() ); - } - - void enforceNoDuplicateTestCases( std::vector const& functions ) { - std::set seenFunctions; - for( std::vector::const_iterator it = functions.begin(), itEnd = functions.end(); - it != itEnd; - ++it ) { - std::pair::const_iterator, bool> prev = seenFunctions.insert( *it ); - if( !prev.second ) { - std::ostringstream ss; - - ss << Colour( Colour::Red ) - << "error: TEST_CASE( \"" << it->name << "\" ) already defined.\n" - << "\tFirst seen at " << prev.first->getTestCaseInfo().lineInfo << '\n' - << "\tRedefined at " << it->getTestCaseInfo().lineInfo << std::endl; - - throw std::runtime_error(ss.str()); - } - } - } - - std::vector filterTests( std::vector const& testCases, TestSpec const& testSpec, IConfig const& config ) { - std::vector filtered; - filtered.reserve( testCases.size() ); - for( std::vector::const_iterator it = testCases.begin(), itEnd = testCases.end(); - it != itEnd; - ++it ) - if( matchTest( *it, testSpec, config ) ) - filtered.push_back( *it ); - return filtered; - } - std::vector const& getAllTestCasesSorted( IConfig const& config ) { - return getRegistryHub().getTestCaseRegistry().getAllTestsSorted( config ); - } - - class TestRegistry : public ITestCaseRegistry { - public: - TestRegistry() - : m_currentSortOrder( RunTests::InDeclarationOrder ), - m_unnamedCount( 0 ) - {} - virtual ~TestRegistry(); - - virtual void registerTest( TestCase const& testCase ) { - std::string name = testCase.getTestCaseInfo().name; - if( name.empty() ) { - std::ostringstream oss; - oss << "Anonymous test case " << ++m_unnamedCount; - return registerTest( testCase.withName( oss.str() ) ); - } - m_functions.push_back( testCase ); - } - - virtual std::vector const& getAllTests() const { - return m_functions; - } - virtual std::vector const& getAllTestsSorted( IConfig const& config ) const { - if( m_sortedFunctions.empty() ) - enforceNoDuplicateTestCases( m_functions ); - - if( m_currentSortOrder != config.runOrder() || m_sortedFunctions.empty() ) { - m_sortedFunctions = sortTests( config, m_functions ); - m_currentSortOrder = config.runOrder(); - } - return m_sortedFunctions; - } - - private: - std::vector m_functions; - mutable RunTests::InWhatOrder m_currentSortOrder; - mutable std::vector m_sortedFunctions; - size_t m_unnamedCount; - std::ios_base::Init m_ostreamInit; // Forces cout/ cerr to be initialised - }; - - /////////////////////////////////////////////////////////////////////////// - - class FreeFunctionTestCase : public SharedImpl { - public: - - FreeFunctionTestCase( TestFunction fun ) : m_fun( fun ) {} - - virtual void invoke() const { - m_fun(); - } - - private: - virtual ~FreeFunctionTestCase(); - - TestFunction m_fun; - }; - - inline std::string extractClassName( std::string const& classOrQualifiedMethodName ) { - std::string className = classOrQualifiedMethodName; - if( startsWith( className, '&' ) ) - { - std::size_t lastColons = className.rfind( "::" ); - std::size_t penultimateColons = className.rfind( "::", lastColons-1 ); - if( penultimateColons == std::string::npos ) - penultimateColons = 1; - className = className.substr( penultimateColons, lastColons-penultimateColons ); - } - return className; - } - - void registerTestCase - ( ITestCase* testCase, - char const* classOrQualifiedMethodName, - NameAndDesc const& nameAndDesc, - SourceLineInfo const& lineInfo ) { - - getMutableRegistryHub().registerTest - ( makeTestCase - ( testCase, - extractClassName( classOrQualifiedMethodName ), - nameAndDesc.name, - nameAndDesc.description, - lineInfo ) ); - } - void registerTestCaseFunction - ( TestFunction function, - SourceLineInfo const& lineInfo, - NameAndDesc const& nameAndDesc ) { - registerTestCase( new FreeFunctionTestCase( function ), "", nameAndDesc, lineInfo ); - } - - /////////////////////////////////////////////////////////////////////////// - - AutoReg::AutoReg - ( TestFunction function, - SourceLineInfo const& lineInfo, - NameAndDesc const& nameAndDesc ) { - registerTestCaseFunction( function, lineInfo, nameAndDesc ); - } - - AutoReg::~AutoReg() {} - -} // end namespace Catch - -// #included from: catch_reporter_registry.hpp -#define TWOBLUECUBES_CATCH_REPORTER_REGISTRY_HPP_INCLUDED - -#include - -namespace Catch { - - class ReporterRegistry : public IReporterRegistry { - - public: - - virtual ~ReporterRegistry() CATCH_OVERRIDE {} - - virtual IStreamingReporter* create( std::string const& name, Ptr const& config ) const CATCH_OVERRIDE { - FactoryMap::const_iterator it = m_factories.find( name ); - if( it == m_factories.end() ) - return CATCH_NULL; - return it->second->create( ReporterConfig( config ) ); - } - - void registerReporter( std::string const& name, Ptr const& factory ) { - m_factories.insert( std::make_pair( name, factory ) ); - } - void registerListener( Ptr const& factory ) { - m_listeners.push_back( factory ); - } - - virtual FactoryMap const& getFactories() const CATCH_OVERRIDE { - return m_factories; - } - virtual Listeners const& getListeners() const CATCH_OVERRIDE { - return m_listeners; - } - - private: - FactoryMap m_factories; - Listeners m_listeners; - }; -} - -// #included from: catch_exception_translator_registry.hpp -#define TWOBLUECUBES_CATCH_EXCEPTION_TRANSLATOR_REGISTRY_HPP_INCLUDED - -#ifdef __OBJC__ -#import "Foundation/Foundation.h" -#endif - -namespace Catch { - - class ExceptionTranslatorRegistry : public IExceptionTranslatorRegistry { - public: - ~ExceptionTranslatorRegistry() { - deleteAll( m_translators ); - } - - virtual void registerTranslator( const IExceptionTranslator* translator ) { - m_translators.push_back( translator ); - } - - virtual std::string translateActiveException() const { - try { -#ifdef __OBJC__ - // In Objective-C try objective-c exceptions first - @try { - return tryTranslators(); - } - @catch (NSException *exception) { - return Catch::toString( [exception description] ); - } -#else - return tryTranslators(); -#endif - } - catch( TestFailureException& ) { - throw; - } - catch( std::exception& ex ) { - return ex.what(); - } - catch( std::string& msg ) { - return msg; - } - catch( const char* msg ) { - return msg; - } - catch(...) { - return "Unknown exception"; - } - } - - std::string tryTranslators() const { - if( m_translators.empty() ) - throw; - else - return m_translators[0]->translate( m_translators.begin()+1, m_translators.end() ); - } - - private: - std::vector m_translators; - }; -} - -// #included from: catch_tag_alias_registry.h -#define TWOBLUECUBES_CATCH_TAG_ALIAS_REGISTRY_H_INCLUDED - -#include - -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( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo ); - - private: - std::map m_registry; - }; - -} // end namespace Catch - -namespace Catch { - - namespace { - - class RegistryHub : public IRegistryHub, public IMutableRegistryHub { - - RegistryHub( RegistryHub const& ); - void operator=( RegistryHub const& ); - - public: // IRegistryHub - RegistryHub() { - } - virtual IReporterRegistry const& getReporterRegistry() const CATCH_OVERRIDE { - return m_reporterRegistry; - } - virtual ITestCaseRegistry const& getTestCaseRegistry() const CATCH_OVERRIDE { - return m_testCaseRegistry; - } - virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() CATCH_OVERRIDE { - return m_exceptionTranslatorRegistry; - } - virtual ITagAliasRegistry const& getTagAliasRegistry() const CATCH_OVERRIDE { - return m_tagAliasRegistry; - } - - public: // IMutableRegistryHub - virtual void registerReporter( std::string const& name, Ptr const& factory ) CATCH_OVERRIDE { - m_reporterRegistry.registerReporter( name, factory ); - } - virtual void registerListener( Ptr const& factory ) CATCH_OVERRIDE { - m_reporterRegistry.registerListener( factory ); - } - virtual void registerTest( TestCase const& testInfo ) CATCH_OVERRIDE { - m_testCaseRegistry.registerTest( testInfo ); - } - virtual void registerTranslator( const IExceptionTranslator* translator ) CATCH_OVERRIDE { - m_exceptionTranslatorRegistry.registerTranslator( translator ); - } - virtual void registerTagAlias( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo ) CATCH_OVERRIDE { - m_tagAliasRegistry.add( alias, tag, lineInfo ); - } - - private: - TestRegistry m_testCaseRegistry; - ReporterRegistry m_reporterRegistry; - ExceptionTranslatorRegistry m_exceptionTranslatorRegistry; - TagAliasRegistry m_tagAliasRegistry; - }; - - // Single, global, instance - inline RegistryHub*& getTheRegistryHub() { - static RegistryHub* theRegistryHub = CATCH_NULL; - if( !theRegistryHub ) - theRegistryHub = new RegistryHub(); - return theRegistryHub; - } - } - - IRegistryHub& getRegistryHub() { - return *getTheRegistryHub(); - } - IMutableRegistryHub& getMutableRegistryHub() { - return *getTheRegistryHub(); - } - void cleanUp() { - delete getTheRegistryHub(); - getTheRegistryHub() = CATCH_NULL; - cleanUpContext(); - } - std::string translateActiveException() { - return getRegistryHub().getExceptionTranslatorRegistry().translateActiveException(); - } - -} // end namespace Catch - -// #included from: catch_notimplemented_exception.hpp -#define TWOBLUECUBES_CATCH_NOTIMPLEMENTED_EXCEPTION_HPP_INCLUDED - -#include - -namespace Catch { - - NotImplementedException::NotImplementedException( SourceLineInfo const& lineInfo ) - : m_lineInfo( lineInfo ) { - std::ostringstream oss; - oss << lineInfo << ": function "; - oss << "not implemented"; - m_what = oss.str(); - } - - const char* NotImplementedException::what() const CATCH_NOEXCEPT { - return m_what.c_str(); - } - -} // end namespace Catch - -// #included from: catch_context_impl.hpp -#define TWOBLUECUBES_CATCH_CONTEXT_IMPL_HPP_INCLUDED - -// #included from: catch_stream.hpp -#define TWOBLUECUBES_CATCH_STREAM_HPP_INCLUDED - -#include -#include -#include - -namespace Catch { - - 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 ) ); - } - return 0; - } - - int sync() { - if( pbase() != pptr() ) { - m_writer( std::string( pbase(), static_cast( pptr() - pbase() ) ) ); - setp( pbase(), epptr() ); - } - return 0; - } - }; - - /////////////////////////////////////////////////////////////////////////// - - FileStream::FileStream( std::string const& filename ) { - m_ofs.open( filename.c_str() ); - if( m_ofs.fail() ) { - std::ostringstream oss; - oss << "Unable to open file: '" << filename << '\''; - throw std::domain_error( oss.str() ); - } - } - - std::ostream& FileStream::stream() const { - return m_ofs; - } - - struct OutputDebugWriter { - - void operator()( std::string const&str ) { - writeToDebugConsole( str ); - } - }; - - DebugOutStream::DebugOutStream() - : m_streamBuf( new StreamBufImpl() ), - m_os( m_streamBuf.get() ) - {} - - std::ostream& DebugOutStream::stream() const { - return m_os; - } - - // Store the streambuf from cout up-front because - // cout may get redirected when running tests - CoutStream::CoutStream() - : m_os( Catch::cout().rdbuf() ) - {} - - std::ostream& CoutStream::stream() const { - return m_os; - } - -#ifndef CATCH_CONFIG_NOSTDOUT // If you #define this you must implement these functions - std::ostream& cout() { - return std::cout; - } - std::ostream& cerr() { - return std::cerr; - } - std::ostream& clog() { - return std::clog; - } -#endif -} - -namespace Catch { - - class Context : public IMutableContext { - - Context() : m_config( CATCH_NULL ), m_runner( CATCH_NULL ), m_resultCapture( CATCH_NULL ) {} - Context( Context const& ); - void operator=( Context const& ); - - public: - virtual ~Context() { - deleteAllValues( m_generatorsByTestName ); - } - - 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 - : CATCH_NULL; - } - - IGeneratorsForTest& getGeneratorsForCurrentTest() { - IGeneratorsForTest* generators = findGeneratorsForCurrentTest(); - if( !generators ) { - std::string testName = getResultCapture()->getCurrentTestName(); - generators = createGeneratorsForTest(); - m_generatorsByTestName.insert( std::make_pair( testName, generators ) ); - } - return *generators; - } - - private: - Ptr m_config; - IRunner* m_runner; - IResultCapture* m_resultCapture; - std::map m_generatorsByTestName; - }; - - namespace { - Context* currentContext = CATCH_NULL; - } - IMutableContext& getCurrentMutableContext() { - if( !currentContext ) - currentContext = new Context(); - return *currentContext; - } - IContext& getCurrentContext() { - return getCurrentMutableContext(); - } - - void cleanUpContext() { - delete currentContext; - currentContext = CATCH_NULL; - } -} - -// #included from: catch_console_colour_impl.hpp -#define TWOBLUECUBES_CATCH_CONSOLE_COLOUR_IMPL_HPP_INCLUDED - -// #included from: catch_errno_guard.hpp -#define TWOBLUECUBES_CATCH_ERRNO_GUARD_HPP_INCLUDED - -#include - -namespace Catch { - - class ErrnoGuard { - public: - ErrnoGuard():m_oldErrno(errno){} - ~ErrnoGuard() { errno = m_oldErrno; } - private: - int m_oldErrno; - }; - -} - +// end catch_windows_h_proxy.h namespace Catch { namespace { struct IColourImpl { - virtual ~IColourImpl() {} + virtual ~IColourImpl() = default; virtual void use( Colour::Code _colourCode ) = 0; }; @@ -7884,7 +5962,7 @@ namespace { originalBackgroundAttributes = csbiInfo.wAttributes & ~( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY ); } - virtual void use( Colour::Code _colourCode ) { + virtual void use( Colour::Code _colourCode ) override { switch( _colourCode ) { case Colour::None: return setTextAttribute( originalForegroundAttributes ); case Colour::White: return setTextAttribute( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE ); @@ -7900,7 +5978,7 @@ namespace { 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" ); + case Colour::Bright: CATCH_INTERNAL_ERROR( "not a colour" ); } } @@ -7916,14 +5994,12 @@ namespace { IColourImpl* platformColourInstance() { static Win32ColourImpl s_instance; - Ptr config = getCurrentContext().getConfig(); + IConfigPtr config = getCurrentContext().getConfig(); UseColour::YesOrNo colourMode = config ? config->useColour() : UseColour::Auto; if( colourMode == UseColour::Auto ) - colourMode = !isDebuggerActive() - ? UseColour::Yes - : UseColour::No; + colourMode = UseColour::Yes; return colourMode == UseColour::Yes ? &s_instance : NoColourImpl::instance(); @@ -7945,7 +6021,7 @@ namespace { // https://github.com/philsquared/Catch/pull/131 class PosixColourImpl : public IColourImpl { public: - virtual void use( Colour::Code _colourCode ) { + virtual void use( Colour::Code _colourCode ) override { switch( _colourCode ) { case Colour::None: case Colour::White: return setColour( "[0m" ); @@ -7961,7 +6037,7 @@ namespace { 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: CATCH_INTERNAL_ERROR( "not a colour" ); } } static IColourImpl* instance() { @@ -7975,14 +6051,21 @@ namespace { } }; + bool useColourOnPlatform() { + return +#ifdef CATCH_PLATFORM_MAC + !isDebuggerActive() && +#endif + isatty(STDOUT_FILENO); + } IColourImpl* platformColourInstance() { ErrnoGuard guard; - Ptr config = getCurrentContext().getConfig(); + IConfigPtr config = getCurrentContext().getConfig(); UseColour::YesOrNo colourMode = config ? config->useColour() : UseColour::Auto; if( colourMode == UseColour::Auto ) - colourMode = (!isDebuggerActive() && isatty(STDOUT_FILENO) ) + colourMode = useColourOnPlatform() ? UseColour::Yes : UseColour::No; return colourMode == UseColour::Yes @@ -8005,8 +6088,17 @@ namespace Catch { namespace Catch { - 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( Code _colourCode ) { use( _colourCode ); } + Colour::Colour( Colour&& rhs ) noexcept { + m_moved = rhs.m_moved; + rhs.m_moved = true; + } + Colour& Colour::operator=( Colour&& rhs ) noexcept { + m_moved = rhs.m_moved; + rhs.m_moved = true; + return *this; + } + Colour::~Colour(){ if( !m_moved ) use( None ); } void Colour::use( Code _colourCode ) { @@ -8014,776 +6106,105 @@ namespace Catch { impl->use( _colourCode ); } -} // end namespace Catch - -// #included from: catch_generators_impl.hpp -#define TWOBLUECUBES_CATCH_GENERATORS_IMPL_HPP_INCLUDED - -#include -#include -#include - -namespace Catch { - - struct GeneratorInfo : IGeneratorInfo { - - GeneratorInfo( std::size_t size ) - : m_size( size ), - m_currentIndex( 0 ) - {} - - bool moveNext() { - if( ++m_currentIndex == m_size ) { - m_currentIndex = 0; - return false; - } - return true; - } - - std::size_t getCurrentIndex() const { - return m_currentIndex; - } - - std::size_t m_size; - std::size_t m_currentIndex; - }; - - /////////////////////////////////////////////////////////////////////////// - - class GeneratorsForTest : public IGeneratorsForTest { - - public: - ~GeneratorsForTest() { - deleteAll( m_generatorsInOrder ); - } - - IGeneratorInfo& getGeneratorInfo( std::string const& fileInfo, std::size_t size ) { - std::map::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 { - - AssertionInfo::AssertionInfo():macroName(""), capturedExpression(""), resultDisposition(ResultDisposition::Normal), secondArg(""){} - - AssertionInfo::AssertionInfo( char const * _macroName, - SourceLineInfo const& _lineInfo, - char const * _capturedExpression, - ResultDisposition::Flags _resultDisposition, - char const * _secondArg) - : macroName( _macroName ), - lineInfo( _lineInfo ), - capturedExpression( _capturedExpression ), - resultDisposition( _resultDisposition ), - secondArg( _secondArg ) - {} - - AssertionResult::AssertionResult() {} - - AssertionResult::AssertionResult( AssertionInfo const& info, AssertionResultData const& data ) - : m_info( info ), - m_resultData( data ) - {} - - AssertionResult::~AssertionResult() {} - - // Result was a success - bool AssertionResult::succeeded() const { - return Catch::isOk( m_resultData.resultType ); - } - - // Result was a success, or failure is suppressed - bool AssertionResult::isOk() const { - return Catch::isOk( m_resultData.resultType ) || shouldSuppressFailure( m_info.resultDisposition ); - } - - ResultWas::OfType AssertionResult::getResultType() const { - return m_resultData.resultType; - } - - bool AssertionResult::hasExpression() const { - return m_info.capturedExpression[0] != 0; - } - - bool AssertionResult::hasMessage() const { - return !m_resultData.message.empty(); - } - - std::string capturedExpressionWithSecondArgument( char const * capturedExpression, char const * secondArg ) { - return (secondArg[0] == 0 || secondArg[0] == '"' && secondArg[1] == '"') - ? capturedExpression - : std::string(capturedExpression) + ", " + secondArg; - } - - std::string AssertionResult::getExpression() const { - if( isFalseTest( m_info.resultDisposition ) ) - return '!' + capturedExpressionWithSecondArgument(m_info.capturedExpression, m_info.secondArg); - else - return capturedExpressionWithSecondArgument(m_info.capturedExpression, m_info.secondArg); - } - std::string AssertionResult::getExpressionInMacro() const { - if( m_info.macroName[0] == 0 ) - return capturedExpressionWithSecondArgument(m_info.capturedExpression, m_info.secondArg); - else - return std::string(m_info.macroName) + "( " + capturedExpressionWithSecondArgument(m_info.capturedExpression, m_info.secondArg) + " )"; - } - - bool AssertionResult::hasExpandedExpression() const { - return hasExpression() && getExpandedExpression() != getExpression(); - } - - std::string AssertionResult::getExpandedExpression() const { - return m_resultData.reconstructExpression(); - } - - 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; - } - - void AssertionResult::discardDecomposedExpression() const { - m_resultData.decomposedExpression = CATCH_NULL; - } - - void AssertionResult::expandDecomposedExpression() const { - m_resultData.reconstructExpression(); - } - -} // end namespace Catch - -// #included from: catch_test_case_info.hpp -#define TWOBLUECUBES_CATCH_TEST_CASE_INFO_HPP_INCLUDED - -#include - -namespace Catch { - - inline TestCaseInfo::SpecialProperties parseSpecialTag( std::string const& tag ) { - if( startsWith( tag, '.' ) || - tag == "hide" || - tag == "!hide" ) - return TestCaseInfo::IsHidden; - else if( tag == "!throws" ) - return TestCaseInfo::Throws; - else if( tag == "!shouldfail" ) - return TestCaseInfo::ShouldFail; - else if( tag == "!mayfail" ) - return TestCaseInfo::MayFail; - else if( tag == "!nonportable" ) - return TestCaseInfo::NonPortable; - else - return TestCaseInfo::None; - } - inline bool isReservedTag( std::string const& tag ) { - return parseSpecialTag( tag ) == TestCaseInfo::None && tag.size() > 0 && !std::isalnum( tag[0] ); - } - inline void enforceNotReservedTag( std::string const& tag, SourceLineInfo const& _lineInfo ) { - if( isReservedTag( tag ) ) { - std::ostringstream ss; - ss << Colour(Colour::Red) - << "Tag name [" << tag << "] not allowed.\n" - << "Tag names starting with non alpha-numeric characters are reserved\n" - << Colour(Colour::FileName) - << _lineInfo << '\n'; - throw std::runtime_error(ss.str()); - } - } - - 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 ) { - char c = _descOrTags[i]; - if( !inTag ) { - if( c == '[' ) - inTag = true; - else - desc += c; - } - else { - if( c == ']' ) { - TestCaseInfo::SpecialProperties prop = parseSpecialTag( tag ); - if( prop == TestCaseInfo::IsHidden ) - isHidden = true; - else if( prop == TestCaseInfo::None ) - enforceNotReservedTag( tag, _lineInfo ); - - tags.insert( tag ); - tag.clear(); - inTag = false; - } - else - tag += c; - } - } - if( isHidden ) { - tags.insert( "hide" ); - tags.insert( "." ); - } - - TestCaseInfo info( _name, _className, desc, tags, _lineInfo ); - return TestCase( _testCase, info ); - } - - void setTags( TestCaseInfo& testCaseInfo, std::set const& tags ) - { - testCaseInfo.tags = tags; - testCaseInfo.lcaseTags.clear(); - - std::ostringstream oss; - for( std::set::const_iterator it = tags.begin(), itEnd = tags.end(); it != itEnd; ++it ) { - oss << '[' << *it << ']'; - std::string lcaseTag = toLower( *it ); - testCaseInfo.properties = static_cast( testCaseInfo.properties | parseSpecialTag( lcaseTag ) ); - testCaseInfo.lcaseTags.insert( lcaseTag ); - } - testCaseInfo.tagsAsString = oss.str(); - } - - TestCaseInfo::TestCaseInfo( std::string const& _name, - std::string const& _className, - std::string const& _description, - std::set const& _tags, - SourceLineInfo const& _lineInfo ) - : name( _name ), - className( _className ), - description( _description ), - lineInfo( _lineInfo ), - properties( None ) - { - setTags( *this, _tags ); - } - - TestCaseInfo::TestCaseInfo( TestCaseInfo const& other ) - : name( other.name ), - className( other.className ), - description( other.description ), - tags( other.tags ), - lcaseTags( other.lcaseTags ), - tagsAsString( other.tagsAsString ), - lineInfo( other.lineInfo ), - properties( other.properties ) - {} - - bool TestCaseInfo::isHidden() const { - return ( properties & IsHidden ) != 0; - } - bool TestCaseInfo::throws() const { - return ( properties & Throws ) != 0; - } - bool TestCaseInfo::okToFail() const { - return ( properties & (ShouldFail | MayFail ) ) != 0; - } - bool TestCaseInfo::expectedToFail() const { - return ( properties & (ShouldFail ) ) != 0; - } - - TestCase::TestCase( ITestCase* testCase, TestCaseInfo const& info ) : TestCaseInfo( info ), test( testCase ) {} - - TestCase::TestCase( TestCase const& other ) - : TestCaseInfo( other ), - test( other.test ) - {} - - TestCase TestCase::withName( std::string const& _newName ) const { - TestCase other( *this ); - other.name = _newName; - return other; - } - - void TestCase::swap( TestCase& other ) { - test.swap( other.test ); - name.swap( other.name ); - className.swap( other.className ); - description.swap( other.description ); - tags.swap( other.tags ); - lcaseTags.swap( other.lcaseTags ); - tagsAsString.swap( other.tagsAsString ); - std::swap( TestCaseInfo::properties, static_cast( other ).properties ); - std::swap( lineInfo, other.lineInfo ); - } - - void TestCase::invoke() const { - test->invoke(); - } - - bool TestCase::operator == ( TestCase const& other ) const { - return test.get() == other.test.get() && - name == other.name && - className == other.className; - } - - bool TestCase::operator < ( TestCase const& other ) const { - return name < other.name; - } - TestCase& TestCase::operator = ( TestCase const& other ) { - TestCase temp( other ); - swap( temp ); - return *this; - } - - TestCaseInfo const& TestCase::getTestCaseInfo() const - { - return *this; - } - -} // end namespace Catch - -// #included from: catch_version.hpp -#define TWOBLUECUBES_CATCH_VERSION_HPP_INCLUDED - -namespace Catch { - - Version::Version - ( unsigned int _majorVersion, - unsigned int _minorVersion, - unsigned int _patchNumber, - char const * const _branchName, - unsigned int _buildNumber ) - : majorVersion( _majorVersion ), - minorVersion( _minorVersion ), - patchNumber( _patchNumber ), - branchName( _branchName ), - buildNumber( _buildNumber ) - {} - - std::ostream& operator << ( std::ostream& os, Version const& version ) { - os << version.majorVersion << '.' - << version.minorVersion << '.' - << version.patchNumber; - // branchName is never null -> 0th char is \0 if it is empty - if (version.branchName[0]) { - os << '-' << version.branchName - << '.' << version.buildNumber; - } + std::ostream& operator << ( std::ostream& os, Colour const& ) { return os; } - inline Version libraryVersion() { - static Version version( 1, 9, 7, "", 0 ); - return version; - } - -} - -// #included from: catch_message.hpp -#define TWOBLUECUBES_CATCH_MESSAGE_HPP_INCLUDED - -namespace Catch { - - MessageInfo::MessageInfo( std::string const& _macroName, - SourceLineInfo const& _lineInfo, - ResultWas::OfType _type ) - : macroName( _macroName ), - lineInfo( _lineInfo ), - type( _type ), - sequence( ++globalCount ) - {} - - // This may need protecting if threading support is added - unsigned int MessageInfo::globalCount = 0; - - //////////////////////////////////////////////////////////////////////////// - - ScopedMessage::ScopedMessage( MessageBuilder const& builder ) - : m_info( builder.m_info ) - { - m_info.message = builder.m_stream.str(); - getResultCapture().pushScopedMessage( m_info ); - } - ScopedMessage::ScopedMessage( ScopedMessage const& other ) - : m_info( other.m_info ) - {} - - ScopedMessage::~ScopedMessage() { - if ( !std::uncaught_exception() ){ - getResultCapture().popScopedMessage(m_info); - } - } - } // end namespace Catch -// #included from: catch_legacy_reporter_adapter.hpp -#define TWOBLUECUBES_CATCH_LEGACY_REPORTER_ADAPTER_HPP_INCLUDED - -// #included from: catch_legacy_reporter_adapter.h -#define TWOBLUECUBES_CATCH_LEGACY_REPORTER_ADAPTER_H_INCLUDED - -namespace Catch -{ - // Deprecated - struct IReporter : IShared { - virtual ~IReporter(); - - virtual bool shouldRedirectStdout() const = 0; - - virtual void StartTesting() = 0; - virtual void EndTesting( Totals const& totals ) = 0; - virtual void StartGroup( std::string const& groupName ) = 0; - virtual void EndGroup( std::string const& groupName, Totals const& totals ) = 0; - virtual void StartTestCase( TestCaseInfo const& testInfo ) = 0; - virtual void EndTestCase( TestCaseInfo const& testInfo, Totals const& totals, std::string const& stdOut, std::string const& stdErr ) = 0; - virtual void StartSection( std::string const& sectionName, std::string const& description ) = 0; - virtual void EndSection( std::string const& sectionName, Counts const& assertions ) = 0; - virtual void NoAssertionsInSection( std::string const& sectionName ) = 0; - virtual void NoAssertionsInTestCase( std::string const& testName ) = 0; - virtual void Aborted() = 0; - virtual void Result( AssertionResult const& result ) = 0; - }; - - class LegacyReporterAdapter : public SharedImpl - { - 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 void skipTest( TestCaseInfo const& ); - - private: - Ptr m_legacyReporter; - }; -} - -namespace Catch -{ - LegacyReporterAdapter::LegacyReporterAdapter( Ptr const& legacyReporter ) - : m_legacyReporter( legacyReporter ) - {} - LegacyReporterAdapter::~LegacyReporterAdapter() {} - - ReporterPreferences LegacyReporterAdapter::getPreferences() const { - ReporterPreferences prefs; - prefs.shouldRedirectStdOut = m_legacyReporter->shouldRedirectStdout(); - return prefs; - } - - void LegacyReporterAdapter::noMatchingTestCases( std::string const& ) {} - void LegacyReporterAdapter::testRunStarting( TestRunInfo const& ) { - m_legacyReporter->StartTesting(); - } - void LegacyReporterAdapter::testGroupStarting( GroupInfo const& groupInfo ) { - m_legacyReporter->StartGroup( groupInfo.name ); - } - void LegacyReporterAdapter::testCaseStarting( TestCaseInfo const& testInfo ) { - m_legacyReporter->StartTestCase( testInfo ); - } - void LegacyReporterAdapter::sectionStarting( SectionInfo const& sectionInfo ) { - m_legacyReporter->StartSection( sectionInfo.name, sectionInfo.description ); - } - void LegacyReporterAdapter::assertionStarting( AssertionInfo const& ) { - // Not on legacy interface - } - - bool LegacyReporterAdapter::assertionEnded( AssertionStats const& assertionStats ) { - if( assertionStats.assertionResult.getResultType() != ResultWas::Ok ) { - for( std::vector::const_iterator it = assertionStats.infoMessages.begin(), itEnd = assertionStats.infoMessages.end(); - it != itEnd; - ++it ) { - if( it->type == ResultWas::Info ) { - ResultBuilder rb( it->macroName.c_str(), it->lineInfo, "", ResultDisposition::Normal ); - rb << it->message; - rb.setResultType( ResultWas::Info ); - AssertionResult result = rb.build(); - m_legacyReporter->Result( result ); - } - } - } - m_legacyReporter->Result( assertionStats.assertionResult ); - return true; - } - void LegacyReporterAdapter::sectionEnded( SectionStats const& sectionStats ) { - if( sectionStats.missingAssertions ) - m_legacyReporter->NoAssertionsInSection( sectionStats.sectionInfo.name ); - m_legacyReporter->EndSection( sectionStats.sectionInfo.name, sectionStats.assertions ); - } - void LegacyReporterAdapter::testCaseEnded( TestCaseStats const& testCaseStats ) { - m_legacyReporter->EndTestCase - ( testCaseStats.testInfo, - testCaseStats.totals, - testCaseStats.stdOut, - testCaseStats.stdErr ); - } - void LegacyReporterAdapter::testGroupEnded( TestGroupStats const& testGroupStats ) { - if( testGroupStats.aborting ) - m_legacyReporter->Aborted(); - m_legacyReporter->EndGroup( testGroupStats.groupInfo.name, testGroupStats.totals ); - } - void LegacyReporterAdapter::testRunEnded( TestRunStats const& testRunStats ) { - m_legacyReporter->EndTesting( testRunStats.totals ); - } - void LegacyReporterAdapter::skipTest( TestCaseInfo const& ) { - } -} - -// #included from: catch_timer.hpp - -#ifdef __clang__ -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wc++11-long-long" +#if defined(__clang__) +# pragma clang diagnostic pop #endif -#ifdef CATCH_PLATFORM_WINDOWS - -#else - -#include - -#endif +// end catch_console_colour.cpp +// start catch_context.cpp namespace Catch { + class Context : public IMutableContext, NonCopyable { + + public: // IContext + virtual IResultCapture* getResultCapture() override { + return m_resultCapture; + } + virtual IRunner* getRunner() override { + return m_runner; + } + + virtual IConfigPtr getConfig() const override { + return m_config; + } + + virtual ~Context() override; + + public: // IMutableContext + virtual void setResultCapture( IResultCapture* resultCapture ) override { + m_resultCapture = resultCapture; + } + virtual void setRunner( IRunner* runner ) override { + m_runner = runner; + } + virtual void setConfig( IConfigPtr const& config ) override { + m_config = config; + } + + friend IMutableContext& getCurrentMutableContext(); + + private: + IConfigPtr m_config; + IRunner* m_runner = nullptr; + IResultCapture* m_resultCapture = nullptr; + }; + namespace { -#ifdef CATCH_PLATFORM_WINDOWS - UInt64 getCurrentTicks() { - static UInt64 hz=0, hzo=0; - if (!hz) { - QueryPerformanceFrequency( reinterpret_cast( &hz ) ); - QueryPerformanceCounter( reinterpret_cast( &hzo ) ); - } - UInt64 t; - QueryPerformanceCounter( reinterpret_cast( &t ) ); - return ((t-hzo)*1000000)/hz; - } -#else - UInt64 getCurrentTicks() { - timeval t; - gettimeofday(&t,CATCH_NULL); - return static_cast( t.tv_sec ) * 1000000ull + static_cast( t.tv_usec ); - } -#endif + Context* currentContext = nullptr; + } + IMutableContext& getCurrentMutableContext() { + if( !currentContext ) + currentContext = new Context(); + return *currentContext; + } + IContext& getCurrentContext() { + return getCurrentMutableContext(); } - void Timer::start() { - m_ticks = getCurrentTicks(); - } - unsigned int Timer::getElapsedMicroseconds() const { - return static_cast(getCurrentTicks() - m_ticks); - } - unsigned int Timer::getElapsedMilliseconds() const { - return static_cast(getElapsedMicroseconds()/1000); - } - double Timer::getElapsedSeconds() const { - return getElapsedMicroseconds()/1000000.0; + void cleanUpContext() { + delete currentContext; + currentContext = nullptr; } + IContext::~IContext() = default; + IMutableContext::~IMutableContext() = default; + Context::~Context() = default; +} +// end catch_context.cpp +// start catch_debug_console.cpp -} // namespace Catch +// start catch_debug_console.h -#ifdef __clang__ -#pragma clang diagnostic pop -#endif -// #included from: catch_common.hpp -#define TWOBLUECUBES_CATCH_COMMON_HPP_INCLUDED - -#include -#include +#include namespace Catch { - - bool startsWith( std::string const& s, std::string const& prefix ) { - return s.size() >= prefix.size() && std::equal(prefix.begin(), prefix.end(), s.begin()); - } - bool startsWith( std::string const& s, char prefix ) { - return !s.empty() && s[0] == prefix; - } - bool endsWith( std::string const& s, std::string const& suffix ) { - return s.size() >= suffix.size() && std::equal(suffix.rbegin(), suffix.rend(), s.rbegin()); - } - bool endsWith( std::string const& s, char suffix ) { - return !s.empty() && s[s.size()-1] == suffix; - } - bool contains( std::string const& s, std::string const& infix ) { - return s.find( infix ) != std::string::npos; - } - char toLowerCh(char c) { - return static_cast( std::tolower( c ) ); - } - void toLowerInPlace( std::string& s ) { - std::transform( s.begin(), s.end(), s.begin(), toLowerCh ); - } - 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 ) : std::string(); - } - - bool replaceInPlace( std::string& str, std::string const& replaceThis, std::string const& withThis ) { - bool replaced = false; - std::size_t i = str.find( replaceThis ); - while( i != std::string::npos ) { - replaced = true; - str = str.substr( 0, i ) + withThis + str.substr( i+replaceThis.size() ); - if( i < str.size()-withThis.size() ) - i = str.find( replaceThis, i+withThis.size() ); - else - i = std::string::npos; - } - return replaced; - } - - pluralise::pluralise( std::size_t count, std::string const& label ) - : m_count( count ), - m_label( label ) - {} - - std::ostream& operator << ( std::ostream& os, pluralise const& pluraliser ) { - os << pluraliser.m_count << ' ' << pluraliser.m_label; - if( pluraliser.m_count != 1 ) - os << 's'; - return os; - } - - SourceLineInfo::SourceLineInfo() : file(""), line( 0 ){} - SourceLineInfo::SourceLineInfo( char const* _file, std::size_t _line ) - : file( _file ), - line( _line ) - {} - bool SourceLineInfo::empty() const { - return file[0] == '\0'; - } - bool SourceLineInfo::operator == ( SourceLineInfo const& other ) const { - return line == other.line && (file == other.file || std::strcmp(file, other.file) == 0); - } - bool SourceLineInfo::operator < ( SourceLineInfo const& other ) const { - return line < other.line || ( line == other.line && (std::strcmp(file, other.file) < 0)); - } - - void seedRng( IConfig const& config ) { - if( config.rngSeed() != 0 ) - std::srand( config.rngSeed() ); - } - unsigned int rngSeed() { - return getCurrentContext().getConfig()->rngSeed(); - } - - std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info ) { -#ifndef __GNUG__ - os << info.file << '(' << info.line << ')'; -#else - os << info.file << ':' << info.line; -#endif - return os; - } - - void throwLogicError( std::string const& message, SourceLineInfo const& locationInfo ) { - std::ostringstream oss; - oss << locationInfo << ": Internal Catch error: '" << message << '\''; - if( alwaysTrue() ) - throw std::logic_error( oss.str() ); - } + void writeToDebugConsole( std::string const& text ); } -// #included from: catch_section.hpp -#define TWOBLUECUBES_CATCH_SECTION_HPP_INCLUDED +// end catch_debug_console.h +#ifdef CATCH_PLATFORM_WINDOWS -namespace Catch { - - SectionInfo::SectionInfo - ( SourceLineInfo const& _lineInfo, - std::string const& _name, - std::string const& _description ) - : name( _name ), - description( _description ), - lineInfo( _lineInfo ) - {} - - Section::Section( SectionInfo const& info ) - : m_info( info ), - m_sectionIncluded( getResultCapture().sectionStarted( m_info, m_assertions ) ) - { - m_timer.start(); - } - -#if defined(_MSC_VER) -#pragma warning(push) -#pragma warning(disable:4996) // std::uncaught_exception is deprecated in C++17 -#endif - Section::~Section() { - if( m_sectionIncluded ) { - SectionEndInfo endInfo( m_info, m_assertions, m_timer.getElapsedSeconds() ); - if( std::uncaught_exception() ) - getResultCapture().sectionEndedEarly( endInfo ); - else - getResultCapture().sectionEnded( endInfo ); + namespace Catch { + void writeToDebugConsole( std::string const& text ) { + ::OutputDebugStringA( text.c_str() ); } } -#if defined(_MSC_VER) -#pragma warning(pop) -#endif - - // This indicates whether the section should be executed or not - Section::operator bool() const { - return m_sectionIncluded; +#else + namespace Catch { + void writeToDebugConsole( std::string const& text ) { + // !TBD: Need a version for Mac/ XCode and other IDEs + Catch::cout() << text; + } } - -} // end namespace Catch - -// #included from: catch_debugger.hpp -#define TWOBLUECUBES_CATCH_DEBUGGER_HPP_INCLUDED +#endif // Platform +// end catch_debug_console.cpp +// start catch_debugger.cpp #ifdef CATCH_PLATFORM_MAC @@ -8793,7 +6214,7 @@ namespace Catch { #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 @@ -8804,7 +6225,7 @@ namespace Catch { int mib[4]; struct kinfo_proc info; - size_t size; + std::size_t size; // Initialize the flags so that, if sysctl fails for some bizarre // reason, we get a predictable result. @@ -8822,7 +6243,7 @@ namespace Catch { // Call sysctl. size = sizeof(info); - if( sysctl(mib, sizeof(mib) / sizeof(*mib), &info, &size, CATCH_NULL, 0) != 0 ) { + if( sysctl(mib, sizeof(mib) / sizeof(*mib), &info, &size, nullptr, 0) != 0 ) { Catch::cerr() << "\n** Call to sysctl failed - unable to determine if debugger is active **\n" << std::endl; return false; } @@ -8879,449 +6300,778 @@ namespace Catch { } #else namespace Catch { - inline bool isDebuggerActive() { return false; } + bool isDebuggerActive() { return false; } } #endif // Platform - -#ifdef CATCH_PLATFORM_WINDOWS - - namespace Catch { - void writeToDebugConsole( std::string const& text ) { - ::OutputDebugStringA( text.c_str() ); - } - } -#else - namespace Catch { - void writeToDebugConsole( std::string const& text ) { - // !TBD: Need a version for Mac/ XCode and other IDEs - Catch::cout() << text; - } - } -#endif // Platform - -// #included from: catch_tostring.hpp -#define TWOBLUECUBES_CATCH_TOSTRING_HPP_INCLUDED +// end catch_debugger.cpp +// start catch_decomposer.cpp namespace Catch { -namespace Detail { + ITransientExpression::~ITransientExpression() = default; - const std::string unprintableString = "{?}"; - - namespace { - const int hexThreshold = 255; - - struct Endianness { - enum Arch { Big, Little }; - - static Arch which() { - union _{ - int asInt; - char asChar[sizeof (int)]; - } u; - - u.asInt = 1; - return ( u.asChar[sizeof(int)-1] == 1 ) ? Big : Little; - } - }; - } - - std::string rawMemoryToString( const void *object, std::size_t size ) - { - // Reverse order for little endian architectures - int i = 0, end = static_cast( 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(); + void formatReconstructedExpression( std::ostream &os, std::string const& lhs, StringRef op, std::string const& rhs ) { + if( lhs.size() + rhs.size() < 40 && + lhs.find('\n') == std::string::npos && + rhs.find('\n') == std::string::npos ) + os << lhs << " " << op << " " << rhs; + else + os << lhs << "\n" << op << "\n" << rhs; } } +// end catch_decomposer.cpp +// start catch_errno_guard.cpp -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 + '"'; +#include + +namespace Catch { + ErrnoGuard::ErrnoGuard():m_oldErrno(errno){} + ErrnoGuard::~ErrnoGuard() { errno = m_oldErrno; } } -std::string toString( std::wstring const& value ) { +// end catch_errno_guard.cpp +// start catch_exception_translator_registry.cpp - std::string s; - s.reserve( value.size() ); - for(size_t i = 0; i < value.size(); ++i ) - s += value[i] <= 0xff ? static_cast( value[i] ) : '?'; - return Catch::toString( s ); +// start catch_exception_translator_registry.h + +#include +#include +#include + +namespace Catch { + + class ExceptionTranslatorRegistry : public IExceptionTranslatorRegistry { + public: + ~ExceptionTranslatorRegistry(); + virtual void registerTranslator( const IExceptionTranslator* translator ); + virtual std::string translateActiveException() const override; + std::string tryTranslators() const; + + private: + std::vector> m_translators; + }; } -std::string toString( const char* const value ) { - return value ? Catch::toString( std::string( value ) ) : std::string( "{null string}" ); -} - -std::string toString( char* const value ) { - return Catch::toString( static_cast( value ) ); -} - -std::string toString( const wchar_t* const value ) -{ - return value ? Catch::toString( std::wstring(value) ) : std::string( "{null string}" ); -} - -std::string toString( wchar_t* const value ) -{ - return Catch::toString( static_cast( value ) ); -} - -std::string toString( int value ) { - std::ostringstream oss; - oss << value; - if( value > Detail::hexThreshold ) - oss << " (0x" << std::hex << value << ')'; - return oss.str(); -} - -std::string toString( unsigned long value ) { - std::ostringstream oss; - oss << value; - if( value > Detail::hexThreshold ) - oss << " (0x" << std::hex << value << ')'; - return oss.str(); -} - -std::string toString( unsigned int value ) { - return Catch::toString( static_cast( value ) ); -} - -template -std::string fpToString( T value, int precision ) { - std::ostringstream oss; - oss << std::setprecision( precision ) - << std::fixed - << value; - std::string d = oss.str(); - std::size_t i = d.find_last_not_of( '0' ); - if( i != std::string::npos && i != d.size()-1 ) { - if( d[i] == '.' ) - i++; - d = d.substr( 0, i+1 ); - } - return d; -} - -std::string toString( const double value ) { - return fpToString( value, 10 ); -} -std::string toString( const float value ) { - return fpToString( value, 5 ) + 'f'; -} - -std::string toString( bool value ) { - return value ? "true" : "false"; -} - -std::string toString( char value ) { - if ( value == '\r' ) - return "'\\r'"; - if ( value == '\f' ) - return "'\\f'"; - if ( value == '\n' ) - return "'\\n'"; - if ( value == '\t' ) - return "'\\t'"; - if ( '\0' <= value && value < ' ' ) - return toString( static_cast( value ) ); - char chstr[] = "' '"; - chstr[1] = value; - return chstr; -} - -std::string toString( signed char value ) { - return toString( static_cast( value ) ); -} - -std::string toString( unsigned char value ) { - return toString( static_cast( value ) ); -} - -#ifdef CATCH_CONFIG_CPP11_LONG_LONG -std::string toString( long long value ) { - std::ostringstream oss; - oss << value; - if( value > Detail::hexThreshold ) - oss << " (0x" << std::hex << value << ')'; - return oss.str(); -} -std::string toString( unsigned long long value ) { - std::ostringstream oss; - oss << value; - if( value > Detail::hexThreshold ) - oss << " (0x" << std::hex << value << ')'; - return oss.str(); -} -#endif - -#ifdef CATCH_CONFIG_CPP11_NULLPTR -std::string toString( std::nullptr_t ) { - return "nullptr"; -} -#endif - +// end catch_exception_translator_registry.h #ifdef __OBJC__ - std::string toString( NSString const * const& nsstring ) { - if( !nsstring ) - return "nil"; - return "@" + toString([nsstring UTF8String]); - } - std::string toString( NSString * CATCH_ARC_STRONG & nsstring ) { - if( !nsstring ) - return "nil"; - return "@" + toString([nsstring UTF8String]); - } - std::string toString( NSObject* const& nsObject ) { - return toString( [nsObject description] ); - } +#import "Foundation/Foundation.h" #endif +namespace Catch { + + ExceptionTranslatorRegistry::~ExceptionTranslatorRegistry() { + } + + void ExceptionTranslatorRegistry::registerTranslator( const IExceptionTranslator* translator ) { + m_translators.push_back( std::unique_ptr( translator ) ); + } + + std::string ExceptionTranslatorRegistry::translateActiveException() const { + try { +#ifdef __OBJC__ + // In Objective-C try objective-c exceptions first + @try { + return tryTranslators(); + } + @catch (NSException *exception) { + return Catch::Detail::stringify( [exception description] ); + } +#else + return tryTranslators(); +#endif + } + catch( TestFailureException& ) { + std::rethrow_exception(std::current_exception()); + } + catch( std::exception& ex ) { + return ex.what(); + } + catch( std::string& msg ) { + return msg; + } + catch( const char* msg ) { + return msg; + } + catch(...) { + return "Unknown exception"; + } + } + + std::string ExceptionTranslatorRegistry::tryTranslators() const { + if( m_translators.empty() ) + std::rethrow_exception(std::current_exception()); + else + return m_translators[0]->translate( m_translators.begin()+1, m_translators.end() ); + } +} +// end catch_exception_translator_registry.cpp +// start catch_fatal_condition.cpp + +// start catch_fatal_condition.h + +#include + +#if defined ( CATCH_PLATFORM_WINDOWS ) ///////////////////////////////////////// + +# if !defined ( CATCH_CONFIG_WINDOWS_SEH ) + +namespace Catch { + struct FatalConditionHandler { + void reset(); + }; +} + +# else // CATCH_CONFIG_WINDOWS_SEH is defined + +namespace Catch { + + struct FatalConditionHandler { + + static LONG CALLBACK handleVectoredException(PEXCEPTION_POINTERS ExceptionInfo); + FatalConditionHandler(); + static void reset(); + ~FatalConditionHandler(); + + private: + static bool isSet; + static ULONG guaranteeSize; + static PVOID exceptionHandlerHandle; + }; + +} // namespace Catch + +# endif // CATCH_CONFIG_WINDOWS_SEH + +#else // Not Windows - assumed to be POSIX compatible ////////////////////////// + +# if !defined(CATCH_CONFIG_POSIX_SIGNALS) + +namespace Catch { + struct FatalConditionHandler { + void reset(); + }; +} + +# else // CATCH_CONFIG_POSIX_SIGNALS is defined + +#include + +namespace Catch { + + struct FatalConditionHandler { + + static bool isSet; + static struct sigaction oldSigActions[];// [sizeof(signalDefs) / sizeof(SignalDefs)]; + static stack_t oldSigStack; + static char altStackMem[]; + + static void handleSignal( int sig ); + + FatalConditionHandler(); + ~FatalConditionHandler(); + static void reset(); + }; + +} // namespace Catch + +# endif // CATCH_CONFIG_POSIX_SIGNALS + +#endif // not Windows + +// end catch_fatal_condition.h +namespace { + // Report the error condition + void reportFatal( char const * const message ) { + Catch::getCurrentContext().getResultCapture()->handleFatalErrorCondition( message ); + } +} + +#if defined ( CATCH_PLATFORM_WINDOWS ) ///////////////////////////////////////// + +# if !defined ( CATCH_CONFIG_WINDOWS_SEH ) + +namespace Catch { + void FatalConditionHandler::reset() {} +} + +# else // CATCH_CONFIG_WINDOWS_SEH is defined + +namespace Catch { + struct SignalDefs { DWORD id; const char* name; }; + + // There is no 1-1 mapping between signals and windows exceptions. + // Windows can easily distinguish between SO and SigSegV, + // but SigInt, SigTerm, etc are handled differently. + static SignalDefs signalDefs[] = { + { EXCEPTION_ILLEGAL_INSTRUCTION, "SIGILL - Illegal instruction signal" }, + { EXCEPTION_STACK_OVERFLOW, "SIGSEGV - Stack overflow" }, + { EXCEPTION_ACCESS_VIOLATION, "SIGSEGV - Segmentation violation signal" }, + { EXCEPTION_INT_DIVIDE_BY_ZERO, "Divide by zero error" }, + }; + + LONG CALLBACK FatalConditionHandler::handleVectoredException(PEXCEPTION_POINTERS ExceptionInfo) { + for (auto const& def : signalDefs) { + if (ExceptionInfo->ExceptionRecord->ExceptionCode == def.id) { + reportFatal(def.name); + } + } + // If its not an exception we care about, pass it along. + // This stops us from eating debugger breaks etc. + return EXCEPTION_CONTINUE_SEARCH; + } + + FatalConditionHandler::FatalConditionHandler() { + isSet = true; + // 32k seems enough for Catch to handle stack overflow, + // but the value was found experimentally, so there is no strong guarantee + guaranteeSize = 32 * 1024; + exceptionHandlerHandle = nullptr; + // Register as first handler in current chain + exceptionHandlerHandle = AddVectoredExceptionHandler(1, handleVectoredException); + // Pass in guarantee size to be filled + SetThreadStackGuarantee(&guaranteeSize); + } + + void FatalConditionHandler::reset() { + if (isSet) { + // Unregister handler and restore the old guarantee + RemoveVectoredExceptionHandler(exceptionHandlerHandle); + SetThreadStackGuarantee(&guaranteeSize); + exceptionHandlerHandle = nullptr; + isSet = false; + } + } + + FatalConditionHandler::~FatalConditionHandler() { + reset(); + } + +bool FatalConditionHandler::isSet = false; +ULONG FatalConditionHandler::guaranteeSize = 0; +PVOID FatalConditionHandler::exceptionHandlerHandle = nullptr; + +} // namespace Catch + +# endif // CATCH_CONFIG_WINDOWS_SEH + +#else // Not Windows - assumed to be POSIX compatible ////////////////////////// + +# if !defined(CATCH_CONFIG_POSIX_SIGNALS) + +namespace Catch { + void FatalConditionHandler::reset() {} +} + +# else // CATCH_CONFIG_POSIX_SIGNALS is defined + +#include + +namespace Catch { + + struct SignalDefs { + int id; + const char* name; + }; + static SignalDefs signalDefs[] = { + { SIGINT, "SIGINT - Terminal interrupt signal" }, + { SIGILL, "SIGILL - Illegal instruction signal" }, + { SIGFPE, "SIGFPE - Floating point error signal" }, + { SIGSEGV, "SIGSEGV - Segmentation violation signal" }, + { SIGTERM, "SIGTERM - Termination request signal" }, + { SIGABRT, "SIGABRT - Abort (abnormal termination) signal" } + }; + + void FatalConditionHandler::handleSignal( int sig ) { + char const * name = ""; + for (auto const& def : signalDefs) { + if (sig == def.id) { + name = def.name; + break; + } + } + reset(); + reportFatal(name); + raise( sig ); + } + + FatalConditionHandler::FatalConditionHandler() { + isSet = true; + stack_t sigStack; + sigStack.ss_sp = altStackMem; + sigStack.ss_size = SIGSTKSZ; + sigStack.ss_flags = 0; + sigaltstack(&sigStack, &oldSigStack); + struct sigaction sa = { }; + + sa.sa_handler = handleSignal; + sa.sa_flags = SA_ONSTACK; + for (std::size_t i = 0; i < sizeof(signalDefs)/sizeof(SignalDefs); ++i) { + sigaction(signalDefs[i].id, &sa, &oldSigActions[i]); + } + } + + FatalConditionHandler::~FatalConditionHandler() { + reset(); + } + + void FatalConditionHandler::reset() { + if( isSet ) { + // Set signals back to previous values -- hopefully nobody overwrote them in the meantime + for( std::size_t i = 0; i < sizeof(signalDefs)/sizeof(SignalDefs); ++i ) { + sigaction(signalDefs[i].id, &oldSigActions[i], nullptr); + } + // Return the old stack + sigaltstack(&oldSigStack, nullptr); + isSet = false; + } + } + + bool FatalConditionHandler::isSet = false; + struct sigaction FatalConditionHandler::oldSigActions[sizeof(signalDefs)/sizeof(SignalDefs)] = {}; + stack_t FatalConditionHandler::oldSigStack = {}; + char FatalConditionHandler::altStackMem[SIGSTKSZ] = {}; + +} // namespace Catch + +# endif // CATCH_CONFIG_POSIX_SIGNALS + +#endif // not Windows +// end catch_fatal_condition.cpp +// start catch_interfaces_capture.cpp + +namespace Catch { + IResultCapture::~IResultCapture() = default; +} +// end catch_interfaces_capture.cpp +// start catch_interfaces_config.cpp + +namespace Catch { + IConfig::~IConfig() = default; +} +// end catch_interfaces_config.cpp +// start catch_interfaces_exception.cpp + +namespace Catch { + IExceptionTranslator::~IExceptionTranslator() = default; + IExceptionTranslatorRegistry::~IExceptionTranslatorRegistry() = default; +} +// end catch_interfaces_exception.cpp +// start catch_interfaces_registry_hub.cpp + +namespace Catch { + IRegistryHub::~IRegistryHub() = default; + IMutableRegistryHub::~IMutableRegistryHub() = default; +} +// end catch_interfaces_registry_hub.cpp +// start catch_interfaces_reporter.cpp + +// start catch_reporter_multi.h + +namespace Catch { + + class MultipleReporters : public IStreamingReporter { + using Reporters = std::vector; + Reporters m_reporters; + + public: + void add( IStreamingReporterPtr&& reporter ); + + public: // IStreamingReporter + + ReporterPreferences getPreferences() const override; + + void noMatchingTestCases( std::string const& spec ) override; + + static std::set getSupportedVerbosities(); + + void benchmarkStarting( BenchmarkInfo const& benchmarkInfo ) override; + void benchmarkEnded( BenchmarkStats const& benchmarkStats ) override; + + void testRunStarting( TestRunInfo const& testRunInfo ) override; + void testGroupStarting( GroupInfo const& groupInfo ) override; + void testCaseStarting( TestCaseInfo const& testInfo ) override; + void sectionStarting( SectionInfo const& sectionInfo ) override; + void assertionStarting( AssertionInfo const& assertionInfo ) override; + + // The return value indicates if the messages buffer should be cleared: + bool assertionEnded( AssertionStats const& assertionStats ) override; + void sectionEnded( SectionStats const& sectionStats ) override; + void testCaseEnded( TestCaseStats const& testCaseStats ) override; + void testGroupEnded( TestGroupStats const& testGroupStats ) override; + void testRunEnded( TestRunStats const& testRunStats ) override; + + void skipTest( TestCaseInfo const& testInfo ) override; + bool isMulti() const override; + + }; + } // end namespace Catch -// #included from: catch_result_builder.hpp -#define TWOBLUECUBES_CATCH_RESULT_BUILDER_HPP_INCLUDED - +// end catch_reporter_multi.h namespace Catch { - ResultBuilder::ResultBuilder( char const* macroName, - SourceLineInfo const& lineInfo, - char const* capturedExpression, - ResultDisposition::Flags resultDisposition, - char const* secondArg ) - : m_assertionInfo( macroName, lineInfo, capturedExpression, resultDisposition, secondArg ), - m_shouldDebugBreak( false ), - m_shouldThrow( false ), - m_guardException( false ), - m_usedStream( false ) + ReporterConfig::ReporterConfig( IConfigPtr const& _fullConfig ) + : m_stream( &_fullConfig->stream() ), m_fullConfig( _fullConfig ) {} + + ReporterConfig::ReporterConfig( IConfigPtr const& _fullConfig, std::ostream& _stream ) + : m_stream( &_stream ), m_fullConfig( _fullConfig ) {} + + std::ostream& ReporterConfig::stream() const { return *m_stream; } + IConfigPtr ReporterConfig::fullConfig() const { return m_fullConfig; } + + TestRunInfo::TestRunInfo( std::string const& _name ) : name( _name ) {} + + GroupInfo::GroupInfo( std::string const& _name, + std::size_t _groupIndex, + std::size_t _groupsCount ) + : name( _name ), + groupIndex( _groupIndex ), + groupsCounts( _groupsCount ) {} - ResultBuilder::~ResultBuilder() { -#if defined(CATCH_CONFIG_FAST_COMPILE) - if ( m_guardException ) { - stream().oss << "Exception translation was disabled by CATCH_CONFIG_FAST_COMPILE"; - captureResult( ResultWas::ThrewException ); - getCurrentContext().getResultCapture()->exceptionEarlyReported(); - } -#endif - } - - 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; - } - - void ResultBuilder::endExpression( DecomposedExpression const& expr ) { - // Flip bool results if FalseTest flag is set - if( isFalseTest( m_assertionInfo.resultDisposition ) ) { - m_data.negate( expr.isBinaryExpression() ); - } - - getResultCapture().assertionRun(); - - if(getCurrentContext().getConfig()->includeSuccessfulResults() || m_data.resultType != ResultWas::Ok) - { - AssertionResult result = build( expr ); - handleResult( result ); - } - else - getResultCapture().assertionPassed(); - } - - void ResultBuilder::useActiveException( ResultDisposition::Flags resultDisposition ) { - m_assertionInfo.resultDisposition = resultDisposition; - stream().oss << Catch::translateActiveException(); - captureResult( ResultWas::ThrewException ); - } - - void ResultBuilder::captureResult( ResultWas::OfType resultType ) { - setResultType( resultType ); - captureExpression(); - } - - void ResultBuilder::captureExpectedException( std::string const& expectedMessage ) { - if( expectedMessage.empty() ) - captureExpectedException( Matchers::Impl::MatchAllOf() ); - else - captureExpectedException( Matchers::Equals( expectedMessage ) ); - } - - void ResultBuilder::captureExpectedException( Matchers::Impl::MatcherBase const& matcher ) { - - assert( !isFalseTest( m_assertionInfo.resultDisposition ) ); - AssertionResultData data = m_data; - data.resultType = ResultWas::Ok; - data.reconstructedExpression = capturedExpressionWithSecondArgument(m_assertionInfo.capturedExpression, m_assertionInfo.secondArg); - - std::string actualMessage = Catch::translateActiveException(); - if( !matcher.match( actualMessage ) ) { - data.resultType = ResultWas::ExpressionFailed; - data.reconstructedExpression = actualMessage; - } - AssertionResult result( m_assertionInfo, data ); - handleResult( result ); - } - - void ResultBuilder::captureExpression() { - AssertionResult result = build(); - handleResult( result ); - } - - void ResultBuilder::handleResult( AssertionResult const& result ) + AssertionStats::AssertionStats( AssertionResult const& _assertionResult, + std::vector const& _infoMessages, + Totals const& _totals ) + : assertionResult( _assertionResult ), + infoMessages( _infoMessages ), + totals( _totals ) { - getResultCapture().assertionEnded( result ); + assertionResult.m_resultData.lazyExpression.m_transientExpression = _assertionResult.m_resultData.lazyExpression.m_transientExpression; - if( !result.isOk() ) { - if( getCurrentContext().getConfig()->shouldDebugBreak() ) - m_shouldDebugBreak = true; - if( getCurrentContext().getRunner()->aborting() || (m_assertionInfo.resultDisposition & ResultDisposition::Normal) ) - m_shouldThrow = true; + 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 ); } } - void ResultBuilder::react() { -#if defined(CATCH_CONFIG_FAST_COMPILE) - if (m_shouldDebugBreak) { - /////////////////////////////////////////////////////////////////// - // To inspect the state during test, you need to go one level up the callstack - // To go back to the test and change execution, jump over the throw statement - /////////////////////////////////////////////////////////////////// - CATCH_BREAK_INTO_DEBUGGER(); + AssertionStats::~AssertionStats() = default; + + SectionStats::SectionStats( SectionInfo const& _sectionInfo, + Counts const& _assertions, + double _durationInSeconds, + bool _missingAssertions ) + : sectionInfo( _sectionInfo ), + assertions( _assertions ), + durationInSeconds( _durationInSeconds ), + missingAssertions( _missingAssertions ) + {} + + SectionStats::~SectionStats() = default; + + 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 ) + {} + + TestCaseStats::~TestCaseStats() = default; + + TestGroupStats::TestGroupStats( GroupInfo const& _groupInfo, + Totals const& _totals, + bool _aborting ) + : groupInfo( _groupInfo ), + totals( _totals ), + aborting( _aborting ) + {} + + TestGroupStats::TestGroupStats( GroupInfo const& _groupInfo ) + : groupInfo( _groupInfo ), + aborting( false ) + {} + + TestGroupStats::~TestGroupStats() = default; + + TestRunStats::TestRunStats( TestRunInfo const& _runInfo, + Totals const& _totals, + bool _aborting ) + : runInfo( _runInfo ), + totals( _totals ), + aborting( _aborting ) + {} + + TestRunStats::~TestRunStats() = default; + + void IStreamingReporter::fatalErrorEncountered( StringRef ) {} + bool IStreamingReporter::isMulti() const { return false; } + + IReporterFactory::~IReporterFactory() = default; + IReporterRegistry::~IReporterRegistry() = default; + + void addReporter( IStreamingReporterPtr& existingReporter, IStreamingReporterPtr&& additionalReporter ) { + + if( !existingReporter ) { + existingReporter = std::move( additionalReporter ); + return; } -#endif - if( m_shouldThrow ) - throw Catch::TestFailureException(); - } - bool ResultBuilder::shouldDebugBreak() const { return m_shouldDebugBreak; } - bool ResultBuilder::allowThrows() const { return getCurrentContext().getConfig()->allowThrows(); } + MultipleReporters* multi = nullptr; - AssertionResult ResultBuilder::build() const - { - return build( *this ); - } - - // CAVEAT: The returned AssertionResult stores a pointer to the argument expr, - // a temporary DecomposedExpression, which in turn holds references to - // operands, possibly temporary as well. - // It should immediately be passed to handleResult; if the expression - // needs to be reported, its string expansion must be composed before - // the temporaries are destroyed. - AssertionResult ResultBuilder::build( DecomposedExpression const& expr ) const - { - assert( m_data.resultType != ResultWas::Unknown ); - AssertionResultData data = m_data; - - if(m_usedStream) - data.message = m_stream().oss.str(); - data.decomposedExpression = &expr; // for lazy reconstruction - return AssertionResult( m_assertionInfo, data ); - } - - void ResultBuilder::reconstructExpression( std::string& dest ) const { - dest = capturedExpressionWithSecondArgument(m_assertionInfo.capturedExpression, m_assertionInfo.secondArg); - } - - void ResultBuilder::setExceptionGuard() { - m_guardException = true; - } - void ResultBuilder::unsetExceptionGuard() { - m_guardException = false; + if( existingReporter->isMulti() ) { + multi = static_cast( existingReporter.get() ); + } + else { + auto newMulti = std::unique_ptr( new MultipleReporters ); + newMulti->add( std::move( existingReporter ) ); + multi = newMulti.get(); + existingReporter = std::move( newMulti ); + } + multi->add( std::move( additionalReporter ) ); } } // end namespace Catch +// end catch_interfaces_reporter.cpp +// start catch_interfaces_runner.cpp -// #included from: catch_tag_alias_registry.hpp -#define TWOBLUECUBES_CATCH_TAG_ALIAS_REGISTRY_HPP_INCLUDED +namespace Catch { + IRunner::~IRunner() = default; +} +// end catch_interfaces_runner.cpp +// start catch_interfaces_testcase.cpp + +namespace Catch { + ITestInvoker::~ITestInvoker() = default; + ITestCaseRegistry::~ITestCaseRegistry() = default; +} +// end catch_interfaces_testcase.cpp +// start catch_leak_detector.cpp namespace Catch { - TagAliasRegistry::~TagAliasRegistry() {} +#ifdef CATCH_CONFIG_WINDOWS_CRTDBG +#include - 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(); - } + LeakDetector::LeakDetector() { + int flag = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG); + flag |= _CRTDBG_LEAK_CHECK_DF; + flag |= _CRTDBG_ALLOC_MEM_DF; + _CrtSetDbgFlag(flag); + _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG); + _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR); + // Change this to leaking allocation's number to break there + _CrtSetBreakAlloc(-1); + } - 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; - } +#else - void TagAliasRegistry::add( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo ) { + LeakDetector::LeakDetector(){} - if( !startsWith( alias, "[@" ) || !endsWith( alias, ']' ) ) { - std::ostringstream oss; - oss << Colour( Colour::Red ) - << "error: tag alias, \"" << alias << "\" is not of the form [@alias name].\n" - << Colour( Colour::FileName ) - << lineInfo << '\n'; - throw std::domain_error( oss.str().c_str() ); - } - if( !m_registry.insert( std::make_pair( alias, TagAlias( tag, lineInfo ) ) ).second ) { - std::ostringstream oss; - oss << Colour( Colour::Red ) - << "error: tag alias, \"" << alias << "\" already registered.\n" - << "\tFirst seen at " - << Colour( Colour::Red ) << find(alias)->lineInfo << '\n' - << Colour( Colour::Red ) << "\tRedefined at " - << Colour( Colour::FileName) << lineInfo << '\n'; - throw std::domain_error( oss.str().c_str() ); - } - } +#endif - ITagAliasRegistry::~ITagAliasRegistry() {} +} +// end catch_leak_detector.cpp +// start catch_list.cpp - ITagAliasRegistry const& ITagAliasRegistry::get() { - return getRegistryHub().getTagAliasRegistry(); - } +// start catch_list.h - RegistrarForTagAliases::RegistrarForTagAliases( char const* alias, char const* tag, SourceLineInfo const& lineInfo ) { - getMutableRegistryHub().registerTagAlias( alias, tag, lineInfo ); - } +#include + +namespace Catch { + + std::size_t listTests( Config const& config ); + + std::size_t listTestsNamesOnly( Config const& config ); + + struct TagInfo { + void add( std::string const& spelling ); + std::string all() const; + + std::set spellings; + std::size_t count = 0; + }; + + std::size_t listTags( Config const& config ); + + std::size_t listReporters( Config const& /*config*/ ); + + Option list( Config const& config ); } // end namespace Catch -// #included from: catch_matchers_string.hpp +// end catch_list.h +// start catch_text.h + +namespace Catch { + using namespace clara::TextFlow; +} + +// end catch_text.h +#include +#include +#include + +namespace Catch { + + std::size_t listTests( Config const& config ) { + TestSpec testSpec = config.testSpec(); + if( config.testSpec().hasFilters() ) + Catch::cout() << "Matching test cases:\n"; + else { + Catch::cout() << "All available test cases:\n"; + testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "*" ).testSpec(); + } + + auto matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config ); + for( auto const& testCaseInfo : matchedTestCases ) { + Colour::Code colour = testCaseInfo.isHidden() + ? Colour::SecondaryText + : Colour::None; + Colour colourGuard( colour ); + + Catch::cout() << Column( testCaseInfo.name ).initialIndent( 2 ).indent( 4 ) << "\n"; + if( config.verbosity() >= Verbosity::High ) { + Catch::cout() << Column( Catch::Detail::stringify( testCaseInfo.lineInfo ) ).indent(4) << std::endl; + std::string description = testCaseInfo.description; + if( description.empty() ) + description = "(NO DESCRIPTION)"; + Catch::cout() << Column( description ).indent(4) << std::endl; + } + if( !testCaseInfo.tags.empty() ) + Catch::cout() << Column( testCaseInfo.tagsAsString() ).indent( 6 ) << "\n"; + } + + if( !config.testSpec().hasFilters() ) + Catch::cout() << pluralise( matchedTestCases.size(), "test case" ) << '\n' << std::endl; + else + Catch::cout() << pluralise( matchedTestCases.size(), "matching test case" ) << '\n' << std::endl; + return matchedTestCases.size(); + } + + 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 = filterTests( getAllTestCasesSorted( config ), testSpec, config ); + for( auto const& testCaseInfo : matchedTestCases ) { + matchedTests++; + if( startsWith( testCaseInfo.name, '#' ) ) + Catch::cout() << '"' << testCaseInfo.name << '"'; + else + Catch::cout() << testCaseInfo.name; + if ( config.verbosity() >= Verbosity::High ) + Catch::cout() << "\t@" << testCaseInfo.lineInfo; + Catch::cout() << std::endl; + } + return matchedTests; + } + + void TagInfo::add( std::string const& spelling ) { + ++count; + spellings.insert( spelling ); + } + + std::string TagInfo::all() const { + std::string out; + for( auto const& spelling : spellings ) + out += "[" + spelling + "]"; + return out; + } + + std::size_t listTags( Config const& config ) { + TestSpec testSpec = config.testSpec(); + if( config.testSpec().hasFilters() ) + Catch::cout() << "Tags for matching test cases:\n"; + else { + Catch::cout() << "All available tags:\n"; + testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "*" ).testSpec(); + } + + std::map tagCounts; + + std::vector matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config ); + for( auto const& testCase : matchedTestCases ) { + for( auto const& tagName : testCase.getTestCaseInfo().tags ) { + std::string lcaseTagName = toLower( tagName ); + auto countIt = tagCounts.find( lcaseTagName ); + if( countIt == tagCounts.end() ) + countIt = tagCounts.insert( std::make_pair( lcaseTagName, TagInfo() ) ).first; + countIt->second.add( tagName ); + } + } + + for( auto const& tagCount : tagCounts ) { + std::ostringstream oss; + oss << " " << std::setw(2) << tagCount.second.count << " "; + auto wrapper = Column( tagCount.second.all() ) + .initialIndent( 0 ) + .indent( oss.str().size() ) + .width( CATCH_CONFIG_CONSOLE_WIDTH-10 ); + Catch::cout() << oss.str() << wrapper << '\n'; + } + Catch::cout() << pluralise( tagCounts.size(), "tag" ) << '\n' << std::endl; + return tagCounts.size(); + } + + std::size_t listReporters( Config const& /*config*/ ) { + Catch::cout() << "Available reporters:\n"; + IReporterRegistry::FactoryMap const& factories = getRegistryHub().getReporterRegistry().getFactories(); + std::size_t maxNameLen = 0; + for( auto const& factoryKvp : factories ) + maxNameLen = (std::max)( maxNameLen, factoryKvp.first.size() ); + + for( auto const& factoryKvp : factories ) { + Catch::cout() + << Column( factoryKvp.first + ":" ) + .indent(2) + .width( 5+maxNameLen ) + + Column( factoryKvp.second->getDescription() ) + .initialIndent(0) + .indent(2) + .width( CATCH_CONFIG_CONSOLE_WIDTH - maxNameLen-8 ) + << "\n"; + } + Catch::cout() << std::endl; + return factories.size(); + } + + 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 +// end catch_list.cpp +// start catch_matchers.cpp + +namespace Catch { +namespace Matchers { + namespace Impl { + + std::string MatcherUntypedBase::toString() const { + if( m_cachedToString.empty() ) + m_cachedToString = describe(); + return m_cachedToString; + } + + MatcherUntypedBase::~MatcherUntypedBase() = default; + + } // namespace Impl +} // namespace Matchers + +using namespace Matchers; +using Matchers::Impl::MatcherBase; + +} // namespace Catch +// end catch_matchers.cpp +// start catch_matchers_string.cpp namespace Catch { namespace Matchers { @@ -9401,573 +7151,2744 @@ namespace Matchers { } // namespace Matchers } // namespace Catch -// #included from: ../reporters/catch_reporter_multi.hpp -#define TWOBLUECUBES_CATCH_REPORTER_MULTI_HPP_INCLUDED +// end catch_matchers_string.cpp +// start catch_message.cpp namespace Catch { -class MultipleReporters : public SharedImpl { - typedef std::vector > Reporters; - Reporters m_reporters; + MessageInfo::MessageInfo( std::string const& _macroName, + SourceLineInfo const& _lineInfo, + ResultWas::OfType _type ) + : macroName( _macroName ), + lineInfo( _lineInfo ), + type( _type ), + sequence( ++globalCount ) + {} -public: - void add( Ptr const& reporter ) { - m_reporters.push_back( reporter ); + bool MessageInfo::operator==( MessageInfo const& other ) const { + return sequence == other.sequence; } -public: // IStreamingReporter - - virtual ReporterPreferences getPreferences() const CATCH_OVERRIDE { - return m_reporters[0]->getPreferences(); + bool MessageInfo::operator<( MessageInfo const& other ) const { + return sequence < other.sequence; } - virtual void noMatchingTestCases( std::string const& spec ) CATCH_OVERRIDE { - for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); - it != itEnd; - ++it ) - (*it)->noMatchingTestCases( spec ); + // This may need protecting if threading support is added + unsigned int MessageInfo::globalCount = 0; + + //////////////////////////////////////////////////////////////////////////// + + Catch::MessageBuilder::MessageBuilder( std::string const& macroName, + SourceLineInfo const& lineInfo, + ResultWas::OfType type ) + :m_info(macroName, lineInfo, type) {} + + //////////////////////////////////////////////////////////////////////////// + + ScopedMessage::ScopedMessage( MessageBuilder const& builder ) + : m_info( builder.m_info ) + { + m_info.message = builder.m_stream.str(); + getResultCapture().pushScopedMessage( m_info ); } - virtual void testRunStarting( TestRunInfo const& testRunInfo ) CATCH_OVERRIDE { - for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); - it != itEnd; - ++it ) - (*it)->testRunStarting( testRunInfo ); - } - - virtual void testGroupStarting( GroupInfo const& groupInfo ) CATCH_OVERRIDE { - for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); - it != itEnd; - ++it ) - (*it)->testGroupStarting( groupInfo ); - } - - virtual void testCaseStarting( TestCaseInfo const& testInfo ) CATCH_OVERRIDE { - for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); - it != itEnd; - ++it ) - (*it)->testCaseStarting( testInfo ); - } - - virtual void sectionStarting( SectionInfo const& sectionInfo ) CATCH_OVERRIDE { - for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); - it != itEnd; - ++it ) - (*it)->sectionStarting( sectionInfo ); - } - - virtual void assertionStarting( AssertionInfo const& assertionInfo ) CATCH_OVERRIDE { - for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); - it != itEnd; - ++it ) - (*it)->assertionStarting( assertionInfo ); - } - - // The return value indicates if the messages buffer should be cleared: - virtual bool assertionEnded( AssertionStats const& assertionStats ) CATCH_OVERRIDE { - bool clearBuffer = false; - for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); - it != itEnd; - ++it ) - clearBuffer |= (*it)->assertionEnded( assertionStats ); - return clearBuffer; - } - - virtual void sectionEnded( SectionStats const& sectionStats ) CATCH_OVERRIDE { - for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); - it != itEnd; - ++it ) - (*it)->sectionEnded( sectionStats ); - } - - virtual void testCaseEnded( TestCaseStats const& testCaseStats ) CATCH_OVERRIDE { - for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); - it != itEnd; - ++it ) - (*it)->testCaseEnded( testCaseStats ); - } - - virtual void testGroupEnded( TestGroupStats const& testGroupStats ) CATCH_OVERRIDE { - for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); - it != itEnd; - ++it ) - (*it)->testGroupEnded( testGroupStats ); - } - - virtual void testRunEnded( TestRunStats const& testRunStats ) CATCH_OVERRIDE { - for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); - it != itEnd; - ++it ) - (*it)->testRunEnded( testRunStats ); - } - - virtual void skipTest( TestCaseInfo const& testInfo ) CATCH_OVERRIDE { - for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); - it != itEnd; - ++it ) - (*it)->skipTest( testInfo ); - } - - virtual MultipleReporters* tryAsMulti() CATCH_OVERRIDE { - return this; - } - -}; - -Ptr addReporter( Ptr const& existingReporter, Ptr const& additionalReporter ) { - Ptr resultingReporter; - - if( existingReporter ) { - MultipleReporters* multi = existingReporter->tryAsMulti(); - if( !multi ) { - multi = new MultipleReporters; - resultingReporter = Ptr( multi ); - if( existingReporter ) - multi->add( existingReporter ); + ScopedMessage::~ScopedMessage() { + if ( !std::uncaught_exception() ){ + getResultCapture().popScopedMessage(m_info); } - else - resultingReporter = existingReporter; - multi->add( additionalReporter ); } - else - resultingReporter = additionalReporter; - return resultingReporter; +} // end namespace Catch +// end catch_message.cpp +// start catch_random_number_generator.cpp + +// start catch_random_number_generator.h + +#include + +namespace Catch { + + struct IConfig; + + void seedRng( IConfig const& config ); + + unsigned int rngSeed(); + + struct RandomNumberGenerator { + using result_type = unsigned int; + + static constexpr result_type (min)() { return 0; } + static constexpr result_type (max)() { return 1000000; } + + result_type operator()( result_type n ) const; + result_type operator()() const; + + template + static void shuffle( V& vector ) { + RandomNumberGenerator rng; + std::shuffle( vector.begin(), vector.end(), rng ); + } + }; + } +// end catch_random_number_generator.h +#include + +namespace Catch { + + void seedRng( IConfig const& config ) { + if( config.rngSeed() != 0 ) + std::srand( config.rngSeed() ); + } + unsigned int rngSeed() { + return getCurrentContext().getConfig()->rngSeed(); + } + + RandomNumberGenerator::result_type RandomNumberGenerator::operator()( result_type n ) const { + return std::rand() % n; + } + RandomNumberGenerator::result_type RandomNumberGenerator::operator()() const { + return std::rand() % (max)(); + } + +} +// end catch_random_number_generator.cpp +// start catch_registry_hub.cpp + +// start catch_test_case_registry_impl.h + +#include +#include +#include +#include + +namespace Catch { + + class TestCase; + struct IConfig; + + std::vector sortTests( IConfig const& config, std::vector const& unsortedTestCases ); + bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config ); + + void enforceNoDuplicateTestCases( std::vector const& functions ); + + std::vector filterTests( std::vector const& testCases, TestSpec const& testSpec, IConfig const& config ); + std::vector const& getAllTestCasesSorted( IConfig const& config ); + + class TestRegistry : public ITestCaseRegistry { + public: + virtual ~TestRegistry() = default; + + virtual void registerTest( TestCase const& testCase ); + + std::vector const& getAllTests() const override; + std::vector const& getAllTestsSorted( IConfig const& config ) const override; + + private: + std::vector m_functions; + mutable RunTests::InWhatOrder m_currentSortOrder = RunTests::InDeclarationOrder; + mutable std::vector m_sortedFunctions; + std::size_t m_unnamedCount = 0; + std::ios_base::Init m_ostreamInit; // Forces cout/ cerr to be initialised + }; + + /////////////////////////////////////////////////////////////////////////// + + class TestInvokerAsFunction : public ITestInvoker { + void(*m_testAsFunction)(); + public: + TestInvokerAsFunction( void(*testAsFunction)() ) noexcept; + + void invoke() const override; + }; + + std::string extractClassName( std::string const& classOrQualifiedMethodName ); + + /////////////////////////////////////////////////////////////////////////// + } // end namespace Catch -// #included from: ../reporters/catch_reporter_xml.hpp -#define TWOBLUECUBES_CATCH_REPORTER_XML_HPP_INCLUDED +// end catch_test_case_registry_impl.h +// start catch_reporter_registry.h -// #included from: catch_reporter_bases.hpp -#define TWOBLUECUBES_CATCH_REPORTER_BASES_HPP_INCLUDED +#include -#include -#include -#include -#include +namespace Catch { + class ReporterRegistry : public IReporterRegistry { + + public: + + ~ReporterRegistry() override; + + IStreamingReporterPtr create( std::string const& name, IConfigPtr const& config ) const override; + + void registerReporter( std::string const& name, IReporterFactoryPtr const& factory ); + void registerListener( IReporterFactoryPtr const& factory ); + + FactoryMap const& getFactories() const override; + Listeners const& getListeners() const override; + + private: + FactoryMap m_factories; + Listeners m_listeners; + }; +} + +// end catch_reporter_registry.h +// start catch_tag_alias_registry.h + +// start catch_tag_alias.h + +#include + +namespace Catch { + + struct TagAlias { + TagAlias(std::string const& _tag, SourceLineInfo _lineInfo); + + std::string tag; + SourceLineInfo lineInfo; + }; + +} // end namespace Catch + +// end catch_tag_alias.h +#include + +namespace Catch { + + class TagAliasRegistry : public ITagAliasRegistry { + public: + ~TagAliasRegistry() override; + TagAlias const* find( std::string const& alias ) const override; + std::string expandAliases( std::string const& unexpandedTestSpec ) const override; + void add( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo ); + + private: + std::map m_registry; + }; + +} // end namespace Catch + +// end catch_tag_alias_registry.h +// start catch_startup_exception_registry.h + +#include +#include + +namespace Catch { + + class StartupExceptionRegistry { + public: + void add(std::exception_ptr const& exception) noexcept; + std::vector const& getExceptions() const noexcept; + private: + std::vector m_exceptions; + }; + +} // end namespace Catch + +// end catch_startup_exception_registry.h namespace Catch { namespace { - // Because formatting using c++ streams is stateful, drop down to C is required - // Alternatively we could use stringstream, but its performance is... not good. - std::string getFormattedDuration( double duration ) { - // Max exponent + 1 is required to represent the whole part - // + 1 for decimal point - // + 3 for the 3 decimal places - // + 1 for null terminator - const size_t maxDoubleSize = DBL_MAX_10_EXP + 1 + 1 + 3 + 1; - char buffer[maxDoubleSize]; - // Save previous errno, to prevent sprintf from overwriting it - ErrnoGuard guard; -#ifdef _MSC_VER - sprintf_s(buffer, "%.3f", duration); -#else - sprintf(buffer, "%.3f", duration); -#endif - return std::string(buffer); - } - } + class RegistryHub : public IRegistryHub, public IMutableRegistryHub, + private NonCopyable { - struct StreamingReporterBase : SharedImpl { - - StreamingReporterBase( ReporterConfig const& _config ) - : m_config( _config.fullConfig() ), - stream( _config.stream() ) - { - m_reporterPrefs.shouldRedirectStdOut = false; - } - - virtual ReporterPreferences getPreferences() const CATCH_OVERRIDE { - return m_reporterPrefs; - } - - virtual ~StreamingReporterBase() CATCH_OVERRIDE; - - virtual void noMatchingTestCases( std::string const& ) CATCH_OVERRIDE {} - - virtual void testRunStarting( TestRunInfo const& _testRunInfo ) CATCH_OVERRIDE { - currentTestRunInfo = _testRunInfo; - } - virtual void testGroupStarting( GroupInfo const& _groupInfo ) CATCH_OVERRIDE { - currentGroupInfo = _groupInfo; - } - - virtual void testCaseStarting( TestCaseInfo const& _testInfo ) CATCH_OVERRIDE { - currentTestCaseInfo = _testInfo; - } - virtual void sectionStarting( SectionInfo const& _sectionInfo ) CATCH_OVERRIDE { - m_sectionStack.push_back( _sectionInfo ); - } - - virtual void sectionEnded( SectionStats const& /* _sectionStats */ ) CATCH_OVERRIDE { - m_sectionStack.pop_back(); - } - virtual void testCaseEnded( TestCaseStats const& /* _testCaseStats */ ) CATCH_OVERRIDE { - currentTestCaseInfo.reset(); - } - virtual void testGroupEnded( TestGroupStats const& /* _testGroupStats */ ) CATCH_OVERRIDE { - currentGroupInfo.reset(); - } - virtual void testRunEnded( TestRunStats const& /* _testRunStats */ ) CATCH_OVERRIDE { - currentTestCaseInfo.reset(); - currentGroupInfo.reset(); - currentTestRunInfo.reset(); - } - - virtual void skipTest( TestCaseInfo const& ) CATCH_OVERRIDE { - // Don't do anything with this by default. - // It can optionally be overridden in the derived class. - } - - Ptr m_config; - std::ostream& stream; - - LazyStat currentTestRunInfo; - LazyStat currentGroupInfo; - LazyStat currentTestCaseInfo; - - std::vector m_sectionStack; - ReporterPreferences m_reporterPrefs; - }; - - 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; + public: // IRegistryHub + RegistryHub() = default; + IReporterRegistry const& getReporterRegistry() const override { + return m_reporterRegistry; } - bool operator == ( Ptr const& other ) const { - return operator==( *other ); + ITestCaseRegistry const& getTestCaseRegistry() const override { + return m_testCaseRegistry; + } + IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() override { + return m_exceptionTranslatorRegistry; + } + ITagAliasRegistry const& getTagAliasRegistry() const override { + return m_tagAliasRegistry; + } + StartupExceptionRegistry const& getStartupExceptionRegistry() const override { + return m_exceptionRegistry; } - 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.name == m_other.name) && - (node->stats.sectionInfo.lineInfo == m_other.lineInfo)); + public: // IMutableRegistryHub + void registerReporter( std::string const& name, IReporterFactoryPtr const& factory ) override { + m_reporterRegistry.registerReporter( name, factory ); } + void registerListener( IReporterFactoryPtr const& factory ) override { + m_reporterRegistry.registerListener( factory ); + } + void registerTest( TestCase const& testInfo ) override { + m_testCaseRegistry.registerTest( testInfo ); + } + void registerTranslator( const IExceptionTranslator* translator ) override { + m_exceptionTranslatorRegistry.registerTranslator( translator ); + } + void registerTagAlias( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo ) override { + m_tagAliasRegistry.add( alias, tag, lineInfo ); + } + void registerStartupException() noexcept override { + m_exceptionRegistry.add(std::current_exception()); + } + private: - void operator=( BySectionInfo const& ); - SectionInfo const& m_other; + TestRegistry m_testCaseRegistry; + ReporterRegistry m_reporterRegistry; + ExceptionTranslatorRegistry m_exceptionTranslatorRegistry; + TagAliasRegistry m_tagAliasRegistry; + StartupExceptionRegistry m_exceptionRegistry; }; - typedef Node TestCaseNode; - typedef Node TestGroupNode; - typedef Node TestRunNode; - - CumulativeReporterBase( ReporterConfig const& _config ) - : m_config( _config.fullConfig() ), - stream( _config.stream() ) - { - m_reporterPrefs.shouldRedirectStdOut = false; + // Single, global, instance + RegistryHub*& getTheRegistryHub() { + static RegistryHub* theRegistryHub = nullptr; + if( !theRegistryHub ) + theRegistryHub = new RegistryHub(); + return theRegistryHub; } - ~CumulativeReporterBase(); - - virtual ReporterPreferences getPreferences() const CATCH_OVERRIDE { - return m_reporterPrefs; - } - - virtual void testRunStarting( TestRunInfo const& ) CATCH_OVERRIDE {} - virtual void testGroupStarting( GroupInfo const& ) CATCH_OVERRIDE {} - - virtual void testCaseStarting( TestCaseInfo const& ) CATCH_OVERRIDE {} - - virtual void sectionStarting( SectionInfo const& sectionInfo ) CATCH_OVERRIDE { - SectionStats incompleteStats( sectionInfo, Counts(), 0, false ); - Ptr node; - if( m_sectionStack.empty() ) { - if( !m_rootSection ) - m_rootSection = new SectionNode( incompleteStats ); - node = m_rootSection; - } - else { - SectionNode& parentNode = *m_sectionStack.back(); - SectionNode::ChildSections::const_iterator it = - std::find_if( parentNode.childSections.begin(), - parentNode.childSections.end(), - BySectionInfo( sectionInfo ) ); - if( it == parentNode.childSections.end() ) { - node = new SectionNode( incompleteStats ); - parentNode.childSections.push_back( node ); - } - else - node = *it; - } - m_sectionStack.push_back( node ); - m_deepestSection = node; - } - - virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE {} - - virtual bool assertionEnded( AssertionStats const& assertionStats ) CATCH_OVERRIDE { - assert( !m_sectionStack.empty() ); - SectionNode& sectionNode = *m_sectionStack.back(); - sectionNode.assertions.push_back( assertionStats ); - // AssertionResult holds a pointer to a temporary DecomposedExpression, - // which getExpandedExpression() calls to build the expression string. - // Our section stack copy of the assertionResult will likely outlive the - // temporary, so it must be expanded or discarded now to avoid calling - // a destroyed object later. - prepareExpandedExpression( sectionNode.assertions.back().assertionResult ); - return true; - } - virtual void sectionEnded( SectionStats const& sectionStats ) CATCH_OVERRIDE { - assert( !m_sectionStack.empty() ); - SectionNode& node = *m_sectionStack.back(); - node.stats = sectionStats; - m_sectionStack.pop_back(); - } - virtual void testCaseEnded( TestCaseStats const& testCaseStats ) CATCH_OVERRIDE { - Ptr node = new TestCaseNode( testCaseStats ); - assert( m_sectionStack.size() == 0 ); - node->children.push_back( m_rootSection ); - m_testCases.push_back( node ); - m_rootSection.reset(); - - assert( m_deepestSection ); - m_deepestSection->stdOut = testCaseStats.stdOut; - m_deepestSection->stdErr = testCaseStats.stdErr; - } - virtual void testGroupEnded( TestGroupStats const& testGroupStats ) CATCH_OVERRIDE { - Ptr node = new TestGroupNode( testGroupStats ); - node->children.swap( m_testCases ); - m_testGroups.push_back( node ); - } - virtual void testRunEnded( TestRunStats const& testRunStats ) CATCH_OVERRIDE { - Ptr node = new TestRunNode( testRunStats ); - node->children.swap( m_testGroups ); - m_testRuns.push_back( node ); - testRunEndedCumulative(); - } - virtual void testRunEndedCumulative() = 0; - - virtual void skipTest( TestCaseInfo const& ) CATCH_OVERRIDE {} - - virtual void prepareExpandedExpression( AssertionResult& result ) const { - if( result.isOk() ) - result.discardDecomposedExpression(); - else - result.expandDecomposedExpression(); - } - - Ptr m_config; - std::ostream& stream; - std::vector m_assertions; - std::vector > > m_sections; - std::vector > m_testCases; - std::vector > m_testGroups; - - std::vector > m_testRuns; - - Ptr m_rootSection; - Ptr m_deepestSection; - std::vector > m_sectionStack; - ReporterPreferences m_reporterPrefs; - - }; - - template - char const* getLineOfChars() { - static char line[CATCH_CONFIG_CONSOLE_WIDTH] = {0}; - if( !*line ) { - std::memset( line, C, CATCH_CONFIG_CONSOLE_WIDTH-1 ); - line[CATCH_CONFIG_CONSOLE_WIDTH-1] = 0; - } - return line; } - struct TestEventListenerBase : StreamingReporterBase { - TestEventListenerBase( ReporterConfig const& _config ) - : StreamingReporterBase( _config ) - {} + IRegistryHub& getRegistryHub() { + return *getTheRegistryHub(); + } + IMutableRegistryHub& getMutableRegistryHub() { + return *getTheRegistryHub(); + } + void cleanUp() { + delete getTheRegistryHub(); + getTheRegistryHub() = nullptr; + cleanUpContext(); + } + std::string translateActiveException() { + return getRegistryHub().getExceptionTranslatorRegistry().translateActiveException(); + } - virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE {} - virtual bool assertionEnded( AssertionStats const& ) CATCH_OVERRIDE { - return false; +} // end namespace Catch +// end catch_registry_hub.cpp +// start catch_reporter_registry.cpp + +namespace Catch { + + ReporterRegistry::~ReporterRegistry() = default; + + IStreamingReporterPtr ReporterRegistry::create( std::string const& name, IConfigPtr const& config ) const { + auto it = m_factories.find( name ); + if( it == m_factories.end() ) + return nullptr; + return it->second->create( ReporterConfig( config ) ); + } + + void ReporterRegistry::registerReporter( std::string const& name, IReporterFactoryPtr const& factory ) { + m_factories.emplace(name, factory); + } + void ReporterRegistry::registerListener( IReporterFactoryPtr const& factory ) { + m_listeners.push_back( factory ); + } + + IReporterRegistry::FactoryMap const& ReporterRegistry::getFactories() const { + return m_factories; + } + IReporterRegistry::Listeners const& ReporterRegistry::getListeners() const { + return m_listeners; + } + +} +// end catch_reporter_registry.cpp +// start catch_result_type.cpp + +namespace Catch { + + bool isOk( ResultWas::OfType resultType ) { + return ( resultType & ResultWas::FailureBit ) == 0; + } + bool isJustInfo( int flags ) { + return flags == ResultWas::Info; + } + + ResultDisposition::Flags operator | ( ResultDisposition::Flags lhs, ResultDisposition::Flags rhs ) { + return static_cast( static_cast( lhs ) | static_cast( rhs ) ); + } + + bool shouldContinueOnFailure( int flags ) { return ( flags & ResultDisposition::ContinueOnFailure ) != 0; } + bool isFalseTest( int flags ) { return ( flags & ResultDisposition::FalseTest ) != 0; } + bool shouldSuppressFailure( int flags ) { return ( flags & ResultDisposition::SuppressFail ) != 0; } + +} // end namespace Catch +// end catch_result_type.cpp +// start catch_run_context.cpp +// start catch_run_context.h + +#include + +namespace Catch { + + struct IMutableContext; + + class StreamRedirect { + + public: + StreamRedirect(std::ostream& stream, std::string& targetString); + + ~StreamRedirect(); + + private: + std::ostream& m_stream; + std::streambuf* m_prevBuf; + std::ostringstream m_oss; + std::string& m_targetString; + }; + + // StdErr has two constituent streams in C++, std::cerr and std::clog + // This means that we need to redirect 2 streams into 1 to keep proper + // order of writes and cannot use StreamRedirect on its own + class StdErrRedirect { + public: + StdErrRedirect(std::string& targetString); + ~StdErrRedirect(); + private: + std::streambuf* m_cerrBuf; + std::streambuf* m_clogBuf; + std::ostringstream m_oss; + std::string& m_targetString; + }; + + /////////////////////////////////////////////////////////////////////////// + + class RunContext : public IResultCapture, public IRunner { + + public: + RunContext( RunContext const& ) = delete; + RunContext& operator =( RunContext const& ) = delete; + + explicit RunContext(IConfigPtr const& _config, IStreamingReporterPtr&& reporter); + + virtual ~RunContext(); + + void testGroupStarting(std::string const& testSpec, std::size_t groupIndex, std::size_t groupsCount); + void testGroupEnded(std::string const& testSpec, Totals const& totals, std::size_t groupIndex, std::size_t groupsCount); + + Totals runTest(TestCase const& testCase); + + IConfigPtr config() const; + IStreamingReporter& reporter() const; + + private: // IResultCapture + + void assertionStarting(AssertionInfo const& info) override; + void assertionEnded(AssertionResult const& result) override; + + bool sectionStarted( SectionInfo const& sectionInfo, Counts& assertions ) override; + bool testForMissingAssertions(Counts& assertions); + + void sectionEnded(SectionEndInfo const& endInfo) override; + void sectionEndedEarly(SectionEndInfo const& endInfo) override; + + void benchmarkStarting( BenchmarkInfo const& info ) override; + void benchmarkEnded( BenchmarkStats const& stats ) override; + + void pushScopedMessage(MessageInfo const& message) override; + void popScopedMessage(MessageInfo const& message) override; + + std::string getCurrentTestName() const override; + + const AssertionResult* getLastResult() const override; + + void exceptionEarlyReported() override; + + void handleFatalErrorCondition( StringRef message ) override; + + bool lastAssertionPassed() override; + + void assertionPassed() override; + + void assertionRun() override; + + public: + // !TBD We need to do this another way! + bool aborting() const override; + + private: + + void runCurrentTest(std::string& redirectedCout, std::string& redirectedCerr); + void invokeActiveTestCase(); + + private: + + void handleUnfinishedSections(); + + TestRunInfo m_runInfo; + IMutableContext& m_context; + TestCase const* m_activeTestCase = nullptr; + ITracker* m_testCaseTracker; + Option m_lastResult; + + IConfigPtr m_config; + Totals m_totals; + IStreamingReporterPtr m_reporter; + std::vector m_messages; + AssertionInfo m_lastAssertionInfo; + std::vector m_unfinishedSections; + std::vector m_activeSections; + TrackerContext m_trackerContext; + std::size_t m_prevPassed = 0; + bool m_shouldReportUnexpected = true; + }; + + IResultCapture& getResultCapture(); + +} // end namespace Catch + +// end catch_run_context.h + +#include +#include + +namespace Catch { + + StreamRedirect::StreamRedirect(std::ostream& stream, std::string& targetString) + : m_stream(stream), + m_prevBuf(stream.rdbuf()), + m_targetString(targetString) { + stream.rdbuf(m_oss.rdbuf()); + } + + StreamRedirect::~StreamRedirect() { + m_targetString += m_oss.str(); + m_stream.rdbuf(m_prevBuf); + } + + StdErrRedirect::StdErrRedirect(std::string & targetString) + :m_cerrBuf(cerr().rdbuf()), m_clogBuf(clog().rdbuf()), + m_targetString(targetString) { + cerr().rdbuf(m_oss.rdbuf()); + clog().rdbuf(m_oss.rdbuf()); + } + + StdErrRedirect::~StdErrRedirect() { + m_targetString += m_oss.str(); + cerr().rdbuf(m_cerrBuf); + clog().rdbuf(m_clogBuf); + } + + RunContext::RunContext(IConfigPtr const& _config, IStreamingReporterPtr&& reporter) + : m_runInfo(_config->name()), + m_context(getCurrentMutableContext()), + m_config(_config), + m_reporter(std::move(reporter)), + m_lastAssertionInfo{ "", SourceLineInfo("",0), "", ResultDisposition::Normal } + { + m_context.setRunner(this); + m_context.setConfig(m_config); + m_context.setResultCapture(this); + m_reporter->testRunStarting(m_runInfo); + } + + RunContext::~RunContext() { + m_reporter->testRunEnded(TestRunStats(m_runInfo, m_totals, aborting())); + } + + void RunContext::testGroupStarting(std::string const& testSpec, std::size_t groupIndex, std::size_t groupsCount) { + m_reporter->testGroupStarting(GroupInfo(testSpec, groupIndex, groupsCount)); + } + + void RunContext::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 RunContext::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; + + ITracker& rootTracker = m_trackerContext.startRun(); + assert(rootTracker.isSectionTracker()); + static_cast(rootTracker).addInitialFilters(m_config->getSectionsToRun()); + do { + m_trackerContext.startCycle(); + m_testCaseTracker = &SectionTracker::acquire(m_trackerContext, TestCaseTracking::NameAndLocation(testInfo.name, testInfo.lineInfo)); + runCurrentTest(redirectedCout, redirectedCerr); + } while (!m_testCaseTracker->isSuccessfullyCompleted() && !aborting()); + + Totals deltaTotals = m_totals.delta(prevTotals); + if (testInfo.expectedToFail() && deltaTotals.testCases.passed > 0) { + deltaTotals.assertions.failed++; + deltaTotals.testCases.passed--; + deltaTotals.testCases.failed++; } + m_totals.testCases += deltaTotals.testCases; + m_reporter->testCaseEnded(TestCaseStats(testInfo, + deltaTotals, + redirectedCout, + redirectedCerr, + aborting())); + + m_activeTestCase = nullptr; + m_testCaseTracker = nullptr; + + return deltaTotals; + } + + IConfigPtr RunContext::config() const { + return m_config; + } + + IStreamingReporter& RunContext::reporter() const { + return *m_reporter; + } + + void RunContext::assertionStarting(AssertionInfo const& info) { + m_reporter->assertionStarting( info ); + } + void RunContext::assertionEnded(AssertionResult const & result) { + if (result.getResultType() == ResultWas::Ok) { + m_totals.assertions.passed++; + } else if (!result.isOk()) { + if( m_activeTestCase->getTestCaseInfo().okToFail() ) + m_totals.assertions.failedButOk++; + else + m_totals.assertions.failed++; + } + + // We have no use for the return value (whether messages should be cleared), because messages were made scoped + // and should be let to clear themselves out. + static_cast(m_reporter->assertionEnded(AssertionStats(result, m_messages, m_totals))); + + // Reset working state + m_lastAssertionInfo = { "", m_lastAssertionInfo.lineInfo, "{Unknown expression after the reported line}", m_lastAssertionInfo.resultDisposition }; + m_lastResult = result; + } + + bool RunContext::sectionStarted(SectionInfo const & sectionInfo, Counts & assertions) { + ITracker& sectionTracker = SectionTracker::acquire(m_trackerContext, TestCaseTracking::NameAndLocation(sectionInfo.name, sectionInfo.lineInfo)); + if (!sectionTracker.isOpen()) + return false; + m_activeSections.push_back(§ionTracker); + + m_lastAssertionInfo.lineInfo = sectionInfo.lineInfo; + + m_reporter->sectionStarting(sectionInfo); + + assertions = m_totals.assertions; + + return true; + } + + bool RunContext::testForMissingAssertions(Counts& assertions) { + if (assertions.total() != 0) + return false; + if (!m_config->warnAboutMissingAssertions()) + return false; + if (m_trackerContext.currentTracker().hasChildren()) + return false; + m_totals.assertions.failed++; + assertions.failed++; + return true; + } + + void RunContext::sectionEnded(SectionEndInfo const & endInfo) { + Counts assertions = m_totals.assertions - endInfo.prevAssertions; + bool missingAssertions = testForMissingAssertions(assertions); + + if (!m_activeSections.empty()) { + m_activeSections.back()->close(); + m_activeSections.pop_back(); + } + + m_reporter->sectionEnded(SectionStats(endInfo.sectionInfo, assertions, endInfo.durationInSeconds, missingAssertions)); + m_messages.clear(); + } + + void RunContext::sectionEndedEarly(SectionEndInfo const & endInfo) { + if (m_unfinishedSections.empty()) + m_activeSections.back()->fail(); + else + m_activeSections.back()->close(); + m_activeSections.pop_back(); + + m_unfinishedSections.push_back(endInfo); + } + void RunContext::benchmarkStarting( BenchmarkInfo const& info ) { + m_reporter->benchmarkStarting( info ); + } + void RunContext::benchmarkEnded( BenchmarkStats const& stats ) { + m_reporter->benchmarkEnded( stats ); + } + + void RunContext::pushScopedMessage(MessageInfo const & message) { + m_messages.push_back(message); + } + + void RunContext::popScopedMessage(MessageInfo const & message) { + m_messages.erase(std::remove(m_messages.begin(), m_messages.end(), message), m_messages.end()); + } + + std::string RunContext::getCurrentTestName() const { + return m_activeTestCase + ? m_activeTestCase->getTestCaseInfo().name + : std::string(); + } + + const AssertionResult * RunContext::getLastResult() const { + return &(*m_lastResult); + } + + void RunContext::exceptionEarlyReported() { + m_shouldReportUnexpected = false; + } + + void RunContext::handleFatalErrorCondition( StringRef message ) { + // First notify reporter that bad things happened + m_reporter->fatalErrorEncountered(message); + + // Don't rebuild the result -- the stringification itself can cause more fatal errors + // Instead, fake a result data. + AssertionResultData tempResult( ResultWas::FatalErrorCondition, { false } ); + tempResult.message = message; + AssertionResult result(m_lastAssertionInfo, tempResult); + + getResultCapture().assertionEnded(result); + + handleUnfinishedSections(); + + // Recreate section for test case (as we will lose the one that was in scope) + auto const& testCaseInfo = m_activeTestCase->getTestCaseInfo(); + SectionInfo testCaseSection(testCaseInfo.lineInfo, testCaseInfo.name, testCaseInfo.description); + + Counts assertions; + assertions.failed = 1; + SectionStats testCaseSectionStats(testCaseSection, assertions, 0, false); + m_reporter->sectionEnded(testCaseSectionStats); + + auto const& testInfo = m_activeTestCase->getTestCaseInfo(); + + Totals deltaTotals; + deltaTotals.testCases.failed = 1; + deltaTotals.assertions.failed = 1; + m_reporter->testCaseEnded(TestCaseStats(testInfo, + deltaTotals, + std::string(), + std::string(), + false)); + m_totals.testCases.failed++; + testGroupEnded(std::string(), m_totals, 1, 1); + m_reporter->testRunEnded(TestRunStats(m_runInfo, m_totals, false)); + } + + bool RunContext::lastAssertionPassed() { + return m_totals.assertions.passed == (m_prevPassed + 1); + } + + void RunContext::assertionPassed() { + ++m_totals.assertions.passed; + m_lastAssertionInfo.capturedExpression = "{Unknown expression after the reported line}"; + m_lastAssertionInfo.macroName = ""; + } + + void RunContext::assertionRun() { + m_prevPassed = m_totals.assertions.passed; + } + + bool RunContext::aborting() const { + return m_totals.assertions.failed == static_cast(m_config->abortAfter()); + } + + void RunContext::runCurrentTest(std::string & redirectedCout, std::string & redirectedCerr) { + auto 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; + m_shouldReportUnexpected = true; + try { + m_lastAssertionInfo = { "TEST_CASE", testCaseInfo.lineInfo, "", ResultDisposition::Normal }; + + seedRng(*m_config); + + Timer timer; + timer.start(); + if (m_reporter->getPreferences().shouldRedirectStdOut) { + StreamRedirect coutRedir(cout(), redirectedCout); + StdErrRedirect errRedir(redirectedCerr); + invokeActiveTestCase(); + } else { + invokeActiveTestCase(); + } + duration = timer.getElapsedSeconds(); + } catch (TestFailureException&) { + // This just means the test was aborted due to failure + } catch (...) { + // Under CATCH_CONFIG_FAST_COMPILE, unexpected exceptions under REQUIRE assertions + // are reported without translation at the point of origin. + if (m_shouldReportUnexpected) { + AssertionHandler + ( m_lastAssertionInfo.macroName, + m_lastAssertionInfo.lineInfo, + m_lastAssertionInfo.capturedExpression, + m_lastAssertionInfo.resultDisposition ).useActiveException(); + } + } + m_testCaseTracker->close(); + handleUnfinishedSections(); + m_messages.clear(); + + Counts assertions = m_totals.assertions - prevAssertions; + bool missingAssertions = testForMissingAssertions(assertions); + SectionStats testCaseSectionStats(testCaseSection, assertions, duration, missingAssertions); + m_reporter->sectionEnded(testCaseSectionStats); + } + + void RunContext::invokeActiveTestCase() { + FatalConditionHandler fatalConditionHandler; // Handle signals + m_activeTestCase->invoke(); + fatalConditionHandler.reset(); + } + + void RunContext::handleUnfinishedSections() { + // If sections ended prematurely due to an exception we stored their + // infos here so we can tear them down outside the unwind process. + for (auto it = m_unfinishedSections.rbegin(), + itEnd = m_unfinishedSections.rend(); + it != itEnd; + ++it) + sectionEnded(*it); + m_unfinishedSections.clear(); + } + + IResultCapture& getResultCapture() { + if (auto* capture = getCurrentContext().getResultCapture()) + return *capture; + else + CATCH_INTERNAL_ERROR("No result capture instance"); + } +} +// end catch_run_context.cpp +// start catch_section.cpp + +namespace Catch { + + Section::Section( SectionInfo const& info ) + : m_info( info ), + m_sectionIncluded( getResultCapture().sectionStarted( m_info, m_assertions ) ) + { + m_timer.start(); + } + +#if defined(_MSC_VER) +#pragma warning(push) +#pragma warning(disable:4996) // std::uncaught_exception is deprecated in C++17 +#endif + Section::~Section() { + if( m_sectionIncluded ) { + SectionEndInfo endInfo( m_info, m_assertions, m_timer.getElapsedSeconds() ); + if( std::uncaught_exception() ) + getResultCapture().sectionEndedEarly( endInfo ); + else + getResultCapture().sectionEnded( endInfo ); + } + } +#if defined(_MSC_VER) +#pragma warning(pop) +#endif + + // This indicates whether the section should be executed or not + Section::operator bool() const { + return m_sectionIncluded; + } + +} // end namespace Catch +// end catch_section.cpp +// start catch_section_info.cpp + +namespace Catch { + + SectionInfo::SectionInfo + ( SourceLineInfo const& _lineInfo, + std::string const& _name, + std::string const& _description ) + : name( _name ), + description( _description ), + lineInfo( _lineInfo ) + {} + + SectionEndInfo::SectionEndInfo( SectionInfo const& _sectionInfo, Counts const& _prevAssertions, double _durationInSeconds ) + : sectionInfo( _sectionInfo ), prevAssertions( _prevAssertions ), durationInSeconds( _durationInSeconds ) + {} + +} // end namespace Catch +// end catch_section_info.cpp +// start catch_session.cpp + +// start catch_session.h + +#include + +namespace Catch { + + class Session : NonCopyable { + public: + + Session(); + ~Session() override; + + void showHelp() const; + void libIdentify(); + + int applyCommandLine( int argc, char* argv[] ); + + void useConfigData( ConfigData const& configData ); + + int run( int argc, char* argv[] ); + #if defined(WIN32) && defined(UNICODE) + int run( int argc, wchar_t* const argv[] ); + #endif + int run(); + + clara::Parser const& cli() const; + void cli( clara::Parser const& newParser ); + ConfigData& configData(); + Config& config(); + private: + int runInternal(); + + clara::Parser m_cli; + ConfigData m_configData; + std::shared_ptr m_config; + bool m_startupExceptions = false; }; } // end namespace Catch -// #included from: ../internal/catch_reporter_registrars.hpp -#define TWOBLUECUBES_CATCH_REPORTER_REGISTRARS_HPP_INCLUDED +// end catch_session.h +// start catch_version.h + +#include namespace Catch { - template - class LegacyReporterRegistrar { + // Versioning information + struct Version { + Version( Version const& ) = delete; + Version& operator=( Version const& ) = delete; + Version( unsigned int _majorVersion, + unsigned int _minorVersion, + unsigned int _patchNumber, + char const * const _branchName, + unsigned int _buildNumber ); - class ReporterFactory : public IReporterFactory { - virtual IStreamingReporter* create( ReporterConfig const& config ) const { - return new LegacyReporterAdapter( new T( config ) ); - } + unsigned int const majorVersion; + unsigned int const minorVersion; + unsigned int const patchNumber; - virtual std::string getDescription() const { - return T::getDescription(); - } - }; + // buildNumber is only used if branchName is not null + char const * const branchName; + unsigned int const buildNumber; - public: - - LegacyReporterRegistrar( std::string const& name ) { - getMutableRegistryHub().registerReporter( name, new ReporterFactory() ); - } + friend std::ostream& operator << ( std::ostream& os, Version const& version ); }; - template - class ReporterRegistrar { - - class ReporterFactory : public SharedImpl { - - // *** Please Note ***: - // - If you end up here looking at a compiler error because it's trying to register - // your custom reporter class be aware that the native reporter interface has changed - // to IStreamingReporter. The "legacy" interface, IReporter, is still supported via - // an adapter. Just use REGISTER_LEGACY_REPORTER to take advantage of the adapter. - // However please consider updating to the new interface as the old one is now - // deprecated and will probably be removed quite soon! - // Please contact me via github if you have any questions at all about this. - // In fact, ideally, please contact me anyway to let me know you've hit this - as I have - // no idea who is actually using custom reporters at all (possibly no-one!). - // The new interface is designed to minimise exposure to interface changes in the future. - virtual IStreamingReporter* create( ReporterConfig const& config ) const { - return new T( config ); - } - - virtual std::string getDescription() const { - return T::getDescription(); - } - }; - - public: - - ReporterRegistrar( std::string const& name ) { - getMutableRegistryHub().registerReporter( name, new ReporterFactory() ); - } - }; - - template - class ListenerRegistrar { - - class ListenerFactory : public SharedImpl { - - virtual IStreamingReporter* create( ReporterConfig const& config ) const { - return new T( config ); - } - virtual std::string getDescription() const { - return std::string(); - } - }; - - public: - - ListenerRegistrar() { - getMutableRegistryHub().registerListener( new ListenerFactory() ); - } - }; + Version const& libraryVersion(); } -#define INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) \ - namespace{ Catch::LegacyReporterRegistrar catch_internal_RegistrarFor##reporterType( name ); } +// end catch_version.h +#include +#include -#define INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType ) \ - namespace{ Catch::ReporterRegistrar catch_internal_RegistrarFor##reporterType( name ); } +namespace { + const int MaxExitCode = 255; + using Catch::IStreamingReporterPtr; + using Catch::IConfigPtr; + using Catch::Config; -// Deprecated - use the form without INTERNAL_ -#define INTERNAL_CATCH_REGISTER_LISTENER( listenerType ) \ - namespace{ Catch::ListenerRegistrar catch_internal_RegistrarFor##listenerType; } + IStreamingReporterPtr createReporter(std::string const& reporterName, IConfigPtr const& config) { + auto reporter = Catch::getRegistryHub().getReporterRegistry().create(reporterName, config); + CATCH_ENFORCE(reporter, "No reporter registered with name: '" << reporterName << "'"); -#define CATCH_REGISTER_LISTENER( listenerType ) \ - namespace{ Catch::ListenerRegistrar catch_internal_RegistrarFor##listenerType; } + return reporter; + } -// #included from: ../internal/catch_xmlwriter.hpp -#define TWOBLUECUBES_CATCH_XMLWRITER_HPP_INCLUDED +#ifndef CATCH_CONFIG_DEFAULT_REPORTER +#define CATCH_CONFIG_DEFAULT_REPORTER "console" +#endif + + IStreamingReporterPtr makeReporter(std::shared_ptr const& config) { + auto const& reporterNames = config->getReporterNames(); + if (reporterNames.empty()) + return createReporter(CATCH_CONFIG_DEFAULT_REPORTER, config); + + IStreamingReporterPtr reporter; + for (auto const& name : reporterNames) + addReporter(reporter, createReporter(name, config)); + return reporter; + } + +#undef CATCH_CONFIG_DEFAULT_REPORTER + + void addListeners(IStreamingReporterPtr& reporters, IConfigPtr const& config) { + auto const& listeners = Catch::getRegistryHub().getReporterRegistry().getListeners(); + for (auto const& listener : listeners) + addReporter(reporters, listener->create(Catch::ReporterConfig(config))); + } + + Catch::Totals runTests(std::shared_ptr const& config) { + using namespace Catch; + IStreamingReporterPtr reporter = makeReporter(config); + addListeners(reporter, config); + + RunContext context(config, std::move(reporter)); + + Totals totals; + + context.testGroupStarting(config->name(), 1, 1); + + TestSpec testSpec = config->testSpec(); + if (!testSpec.hasFilters()) + testSpec = TestSpecParser(ITagAliasRegistry::get()).parse("~[.]").testSpec(); // All not hidden tests + + auto const& allTestCases = getAllTestCasesSorted(*config); + for (auto const& testCase : allTestCases) { + if (!context.aborting() && matchTest(testCase, testSpec, *config)) + totals += context.runTest(testCase); + else + context.reporter().skipTest(testCase); + } + + context.testGroupEnded(config->name(), totals, 1, 1); + return totals; + } + + void applyFilenamesAsTags(Catch::IConfig const& config) { + using namespace Catch; + auto& tests = const_cast&>(getAllTestCasesSorted(config)); + for (auto& testCase : tests) { + auto tags = testCase.tags; + + std::string filename = testCase.lineInfo.file; + auto lastSlash = filename.find_last_of("\\/"); + if (lastSlash != std::string::npos) { + filename.erase(0, lastSlash); + filename[0] = '#'; + } + + auto lastDot = filename.find_last_of('.'); + if (lastDot != std::string::npos) { + filename.erase(lastDot); + } + + tags.push_back(std::move(filename)); + setTags(testCase, tags); + } + } + +} + +namespace Catch { + + Session::Session() { + static bool alreadyInstantiated = false; + if( alreadyInstantiated ) { + try { CATCH_INTERNAL_ERROR( "Only one instance of Catch::Session can ever be used" ); } + catch(...) { getMutableRegistryHub().registerStartupException(); } + } + + const auto& exceptions = getRegistryHub().getStartupExceptionRegistry().getExceptions(); + if ( !exceptions.empty() ) { + m_startupExceptions = true; + Colour colourGuard( Colour::Red ); + Catch::cerr() << "Errors occured during startup!" << '\n'; + // iterate over all exceptions and notify user + for ( const auto& ex_ptr : exceptions ) { + try { + std::rethrow_exception(ex_ptr); + } catch ( std::exception const& ex ) { + Catch::cerr() << Column( ex.what() ).indent(2) << '\n'; + } + } + } + + alreadyInstantiated = true; + m_cli = makeCommandLineParser( m_configData ); + } + Session::~Session() { + Catch::cleanUp(); + } + + void Session::showHelp() const { + Catch::cout() + << "\nCatch v" << libraryVersion() << "\n" + << m_cli << std::endl + << "For more detailed usage please see the project docs\n" << std::endl; + } + void Session::libIdentify() { + Catch::cout() + << std::left << std::setw(16) << "description: " << "A Catch test executable\n" + << std::left << std::setw(16) << "category: " << "testframework\n" + << std::left << std::setw(16) << "framework: " << "Catch Test\n" + << std::left << std::setw(16) << "version: " << libraryVersion() << std::endl; + } + + int Session::applyCommandLine( int argc, char* argv[] ) { + if( m_startupExceptions ) + return 1; + + auto result = m_cli.parse( clara::Args( argc, argv ) ); + if( !result ) { + Catch::cerr() + << Colour( Colour::Red ) + << "\nError(s) in input:\n" + << Column( result.errorMessage() ).indent( 2 ) + << "\n\n"; + Catch::cerr() << "Run with -? for usage\n" << std::endl; + return MaxExitCode; + } + + if( m_configData.showHelp ) + showHelp(); + if( m_configData.libIdentify ) + libIdentify(); + m_config.reset(); + return 0; + } + + void Session::useConfigData( ConfigData const& configData ) { + m_configData = configData; + m_config.reset(); + } + + int Session::run( int argc, char* argv[] ) { + if( m_startupExceptions ) + return 1; + int returnCode = applyCommandLine( argc, argv ); + if( returnCode == 0 ) + returnCode = run(); + return returnCode; + } + +#if defined(WIN32) && defined(UNICODE) + int Session::run( int argc, wchar_t* const argv[] ) { + + char **utf8Argv = new char *[ argc ]; + + for ( int i = 0; i < argc; ++i ) { + int bufSize = WideCharToMultiByte( CP_UTF8, 0, argv[i], -1, NULL, 0, NULL, NULL ); + + utf8Argv[ i ] = new char[ bufSize ]; + + WideCharToMultiByte( CP_UTF8, 0, argv[i], -1, utf8Argv[i], bufSize, NULL, NULL ); + } + + int returnCode = run( argc, utf8Argv ); + + for ( int i = 0; i < argc; ++i ) + delete [] utf8Argv[ i ]; + + delete [] utf8Argv; + + return returnCode; + } +#endif + int Session::run() { + if( ( m_configData.waitForKeypress & WaitForKeypress::BeforeStart ) != 0 ) { + Catch::cout() << "...waiting for enter/ return before starting" << std::endl; + static_cast(std::getchar()); + } + int exitCode = runInternal(); + if( ( m_configData.waitForKeypress & WaitForKeypress::BeforeExit ) != 0 ) { + Catch::cout() << "...waiting for enter/ return before exiting, with code: " << exitCode << std::endl; + static_cast(std::getchar()); + } + return exitCode; + } + + clara::Parser const& Session::cli() const { + return m_cli; + } + void Session::cli( clara::Parser const& newParser ) { + m_cli = newParser; + } + ConfigData& Session::configData() { + return m_configData; + } + Config& Session::config() { + if( !m_config ) + m_config = std::make_shared( m_configData ); + return *m_config; + } + + int Session::runInternal() { + if( m_startupExceptions ) + return 1; + + if( m_configData.showHelp || m_configData.libIdentify ) + return 0; + + try + { + config(); // Force config to be constructed + + seedRng( *m_config ); + + if( m_configData.filenamesAsTags ) + applyFilenamesAsTags( *m_config ); + + // Handle list request + if( Option listed = list( config() ) ) + return static_cast( *listed ); + + return (std::min)( MaxExitCode, static_cast( runTests( m_config ).assertions.failed ) ); + } + catch( std::exception& ex ) { + Catch::cerr() << ex.what() << std::endl; + return MaxExitCode; + } + } + +} // end namespace Catch +// end catch_session.cpp +// start catch_startup_exception_registry.cpp + +namespace Catch { + void StartupExceptionRegistry::add( std::exception_ptr const& exception ) noexcept { + try { + m_exceptions.push_back(exception); + } + catch(...) { + // If we run out of memory during start-up there's really not a lot more we can do about it + std::terminate(); + } + } + + std::vector const& StartupExceptionRegistry::getExceptions() const noexcept { + return m_exceptions; + } + +} // end namespace Catch +// end catch_startup_exception_registry.cpp +// start catch_stream.cpp + +#include +#include +#include + +namespace Catch { + + template + class StreamBufImpl : public StreamBufBase { + char data[bufferSize]; + WriterF m_writer; + + public: + StreamBufImpl() { + setp( data, data + sizeof(data) ); + } + + ~StreamBufImpl() noexcept { + StreamBufImpl::sync(); + } + + private: + int overflow( int c ) override { + sync(); + + if( c != EOF ) { + if( pbase() == epptr() ) + m_writer( std::string( 1, static_cast( c ) ) ); + else + sputc( static_cast( c ) ); + } + return 0; + } + + int sync() override { + if( pbase() != pptr() ) { + m_writer( std::string( pbase(), static_cast( pptr() - pbase() ) ) ); + setp( pbase(), epptr() ); + } + return 0; + } + }; + + /////////////////////////////////////////////////////////////////////////// + + Catch::IStream::~IStream() = default; + + FileStream::FileStream( std::string const& filename ) { + m_ofs.open( filename.c_str() ); + CATCH_ENFORCE( !m_ofs.fail(), "Unable to open file: '" << filename << "'" ); + } + + std::ostream& FileStream::stream() const { + return m_ofs; + } + + struct OutputDebugWriter { + + void operator()( std::string const&str ) { + writeToDebugConsole( str ); + } + }; + + DebugOutStream::DebugOutStream() + : m_streamBuf( new StreamBufImpl() ), + m_os( m_streamBuf.get() ) + {} + + std::ostream& DebugOutStream::stream() const { + return m_os; + } + + // Store the streambuf from cout up-front because + // cout may get redirected when running tests + CoutStream::CoutStream() + : m_os( Catch::cout().rdbuf() ) + {} + + std::ostream& CoutStream::stream() const { + return m_os; + } + +#ifndef CATCH_CONFIG_NOSTDOUT // If you #define this you must implement these functions + std::ostream& cout() { + return std::cout; + } + std::ostream& cerr() { + return std::cerr; + } + std::ostream& clog() { + return std::clog; + } +#endif +} +// end catch_stream.cpp +// start catch_streambuf.cpp + +namespace Catch { + StreamBufBase::~StreamBufBase() = default; +} +// end catch_streambuf.cpp +// start catch_string_manip.cpp + +#include +#include +#include +#include + +namespace Catch { + + bool startsWith( std::string const& s, std::string const& prefix ) { + return s.size() >= prefix.size() && std::equal(prefix.begin(), prefix.end(), s.begin()); + } + bool startsWith( std::string const& s, char prefix ) { + return !s.empty() && s[0] == prefix; + } + bool endsWith( std::string const& s, std::string const& suffix ) { + return s.size() >= suffix.size() && std::equal(suffix.rbegin(), suffix.rend(), s.rbegin()); + } + bool endsWith( std::string const& s, char suffix ) { + return !s.empty() && s[s.size()-1] == suffix; + } + bool contains( std::string const& s, std::string const& infix ) { + return s.find( infix ) != std::string::npos; + } + char toLowerCh(char c) { + return static_cast( std::tolower( c ) ); + } + void toLowerInPlace( std::string& s ) { + std::transform( s.begin(), s.end(), s.begin(), toLowerCh ); + } + 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 ) : std::string(); + } + + bool replaceInPlace( std::string& str, std::string const& replaceThis, std::string const& withThis ) { + bool replaced = false; + std::size_t i = str.find( replaceThis ); + while( i != std::string::npos ) { + replaced = true; + str = str.substr( 0, i ) + withThis + str.substr( i+replaceThis.size() ); + if( i < str.size()-withThis.size() ) + i = str.find( replaceThis, i+withThis.size() ); + else + i = std::string::npos; + } + return replaced; + } + + pluralise::pluralise( std::size_t count, std::string const& label ) + : m_count( count ), + m_label( label ) + {} + + std::ostream& operator << ( std::ostream& os, pluralise const& pluraliser ) { + os << pluraliser.m_count << ' ' << pluraliser.m_label; + if( pluraliser.m_count != 1 ) + os << 's'; + return os; + } + +} +// end catch_string_manip.cpp +// start catch_stringref.cpp + +#if defined(__clang__) +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wexit-time-destructors" +#endif + +#include +#include +#include + +namespace Catch { + + auto getEmptyStringRef() -> StringRef { + static StringRef s_emptyStringRef(""); + return s_emptyStringRef; + } + + StringRef::StringRef() noexcept + : StringRef( getEmptyStringRef() ) + {} + + StringRef::StringRef( StringRef const& other ) noexcept + : m_start( other.m_start ), + m_size( other.m_size ) + {} + + StringRef::StringRef( StringRef&& other ) noexcept + : m_start( other.m_start ), + m_size( other.m_size ), + m_data( other.m_data ) + { + other.m_data = nullptr; + } + + StringRef::StringRef( char const* rawChars ) noexcept + : m_start( rawChars ), + m_size( static_cast( std::strlen( rawChars ) ) ) + { + assert( rawChars != nullptr ); + } + + StringRef::StringRef( char const* rawChars, size_type size ) noexcept + : m_start( rawChars ), + m_size( size ) + { + size_type rawSize = rawChars == nullptr ? 0 : static_cast( std::strlen( rawChars ) ); + if( rawSize < size ) + m_size = rawSize; + } + + StringRef::StringRef( std::string const& stdString ) noexcept + : m_start( stdString.c_str() ), + m_size( stdString.size() ) + {} + + StringRef::~StringRef() noexcept { + delete[] m_data; + } + + auto StringRef::operator = ( StringRef other ) noexcept -> StringRef& { + swap( other ); + return *this; + } + StringRef::operator std::string() const { + return std::string( m_start, m_size ); + } + + void StringRef::swap( StringRef& other ) noexcept { + std::swap( m_start, other.m_start ); + std::swap( m_size, other.m_size ); + std::swap( m_data, other.m_data ); + } + + auto StringRef::c_str() const -> char const* { + if( isSubstring() ) + const_cast( this )->takeOwnership(); + return m_start; + } + auto StringRef::data() const noexcept -> char const* { + return m_start; + } + + auto StringRef::isOwned() const noexcept -> bool { + return m_data != nullptr; + } + auto StringRef::isSubstring() const noexcept -> bool { + return m_start[m_size] != '\0'; + } + + void StringRef::takeOwnership() { + if( !isOwned() ) { + m_data = new char[m_size+1]; + memcpy( m_data, m_start, m_size ); + m_data[m_size] = '\0'; + m_start = m_data; + } + } + auto StringRef::substr( size_type start, size_type size ) const noexcept -> StringRef { + if( start < m_size ) + return StringRef( m_start+start, size ); + else + return StringRef(); + } + auto StringRef::operator == ( StringRef const& other ) const noexcept -> bool { + return + size() == other.size() && + (std::strncmp( m_start, other.m_start, size() ) == 0); + } + auto StringRef::operator != ( StringRef const& other ) const noexcept -> bool { + return !operator==( other ); + } + + auto StringRef::operator[](size_type index) const noexcept -> char { + return m_start[index]; + } + + auto StringRef::empty() const noexcept -> bool { + return m_size == 0; + } + + auto StringRef::size() const noexcept -> size_type { + return m_size; + } + auto StringRef::numberOfCharacters() const noexcept -> size_type { + size_type noChars = m_size; + // Make adjustments for uft encodings + for( size_type i=0; i < m_size; ++i ) { + char c = m_start[i]; + if( ( c & 0b11000000 ) == 0b11000000 ) { + if( ( c & 0b11100000 ) == 0b11000000 ) + noChars--; + else if( ( c & 0b11110000 ) == 0b11100000 ) + noChars-=2; + else if( ( c & 0b11111000 ) == 0b11110000 ) + noChars-=3; + } + } + return noChars; + } + + auto operator + ( StringRef const& lhs, StringRef const& rhs ) -> std::string { + std::string str; + str.reserve( lhs.size() + rhs.size() ); + str += lhs; + str += rhs; + return str; + } + auto operator + ( StringRef const& lhs, const char* rhs ) -> std::string { + return std::string( lhs ) + std::string( rhs ); + } + auto operator + ( char const* lhs, StringRef const& rhs ) -> std::string { + return std::string( lhs ) + std::string( rhs ); + } + + auto operator << ( std::ostream& os, StringRef const& str ) -> std::ostream& { + return os << str.c_str(); + } + +} // namespace Catch + +#if defined(__clang__) +# pragma clang diagnostic pop +#endif +// end catch_stringref.cpp +// start catch_tag_alias.cpp + +namespace Catch { + TagAlias::TagAlias(std::string const & _tag, SourceLineInfo _lineInfo): tag(_tag), lineInfo(_lineInfo) {} +} +// end catch_tag_alias.cpp +// start catch_tag_alias_autoregistrar.cpp + +namespace Catch { + + RegistrarForTagAliases::RegistrarForTagAliases(char const* alias, char const* tag, SourceLineInfo const& lineInfo) { + try { + getMutableRegistryHub().registerTagAlias(alias, tag, lineInfo); + } catch (...) { + // Do not throw when constructing global objects, instead register the exception to be processed later + getMutableRegistryHub().registerStartupException(); + } + } + +} +// end catch_tag_alias_autoregistrar.cpp +// start catch_tag_alias_registry.cpp + +namespace Catch { + + TagAliasRegistry::~TagAliasRegistry() {} + + TagAlias const* TagAliasRegistry::find( std::string const& alias ) const { + auto it = m_registry.find( alias ); + if( it != m_registry.end() ) + return &(it->second); + else + return nullptr; + } + + std::string TagAliasRegistry::expandAliases( std::string const& unexpandedTestSpec ) const { + std::string expandedTestSpec = unexpandedTestSpec; + for( auto const& registryKvp : m_registry ) { + std::size_t pos = expandedTestSpec.find( registryKvp.first ); + if( pos != std::string::npos ) { + expandedTestSpec = expandedTestSpec.substr( 0, pos ) + + registryKvp.second.tag + + expandedTestSpec.substr( pos + registryKvp.first.size() ); + } + } + return expandedTestSpec; + } + + void TagAliasRegistry::add( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo ) { + CATCH_ENFORCE( startsWith(alias, "[@") && endsWith(alias, ']'), + "error: tag alias, '" << alias << "' is not of the form [@alias name].\n" << lineInfo ); + + CATCH_ENFORCE( m_registry.insert(std::make_pair(alias, TagAlias(tag, lineInfo))).second, + "error: tag alias, '" << alias << "' already registered.\n" + << "\tFirst seen at: " << find(alias)->lineInfo << "\n" + << "\tRedefined at: " << lineInfo ); + } + + ITagAliasRegistry::~ITagAliasRegistry() {} + + ITagAliasRegistry const& ITagAliasRegistry::get() { + return getRegistryHub().getTagAliasRegistry(); + } + +} // end namespace Catch +// end catch_tag_alias_registry.cpp +// start catch_test_case_info.cpp + +#include +#include +#include + +namespace Catch { + + TestCaseInfo::SpecialProperties parseSpecialTag( std::string const& tag ) { + if( startsWith( tag, '.' ) || + tag == "!hide" ) + return TestCaseInfo::IsHidden; + else if( tag == "!throws" ) + return TestCaseInfo::Throws; + else if( tag == "!shouldfail" ) + return TestCaseInfo::ShouldFail; + else if( tag == "!mayfail" ) + return TestCaseInfo::MayFail; + else if( tag == "!nonportable" ) + return TestCaseInfo::NonPortable; + else if( tag == "!benchmark" ) + return static_cast( TestCaseInfo::Benchmark | TestCaseInfo::IsHidden ); + else + return TestCaseInfo::None; + } + bool isReservedTag( std::string const& tag ) { + return parseSpecialTag( tag ) == TestCaseInfo::None && tag.size() > 0 && !std::isalnum( tag[0] ); + } + void enforceNotReservedTag( std::string const& tag, SourceLineInfo const& _lineInfo ) { + CATCH_ENFORCE( !isReservedTag(tag), + "Tag name: [" << tag << "] is not allowed.\n" + << "Tag names starting with non alpha-numeric characters are reserved\n" + << _lineInfo ); + } + + TestCase makeTestCase( ITestInvoker* _testCase, + std::string const& _className, + std::string const& _name, + std::string const& _descOrTags, + SourceLineInfo const& _lineInfo ) + { + bool isHidden = false; + + // Parse out tags + std::vector tags; + std::string desc, tag; + bool inTag = false; + for (char c : _descOrTags) { + if( !inTag ) { + if( c == '[' ) + inTag = true; + else + desc += c; + } + else { + if( c == ']' ) { + TestCaseInfo::SpecialProperties prop = parseSpecialTag( tag ); + if( ( prop & TestCaseInfo::IsHidden ) != 0 ) + isHidden = true; + else if( prop == TestCaseInfo::None ) + enforceNotReservedTag( tag, _lineInfo ); + + tags.push_back( tag ); + tag.clear(); + inTag = false; + } + else + tag += c; + } + } + if( isHidden ) { + tags.push_back( "." ); + } + + TestCaseInfo info( _name, _className, desc, tags, _lineInfo ); + return TestCase( _testCase, info ); + } + + void setTags( TestCaseInfo& testCaseInfo, std::vector tags ) { + std::sort(begin(tags), end(tags)); + tags.erase(std::unique(begin(tags), end(tags)), end(tags)); + testCaseInfo.lcaseTags.clear(); + + for( auto const& tag : tags ) { + std::string lcaseTag = toLower( tag ); + testCaseInfo.properties = static_cast( testCaseInfo.properties | parseSpecialTag( lcaseTag ) ); + testCaseInfo.lcaseTags.push_back( lcaseTag ); + } + testCaseInfo.tags = std::move(tags); + } + + TestCaseInfo::TestCaseInfo( std::string const& _name, + std::string const& _className, + std::string const& _description, + std::vector const& _tags, + SourceLineInfo const& _lineInfo ) + : name( _name ), + className( _className ), + description( _description ), + lineInfo( _lineInfo ), + properties( None ) + { + setTags( *this, _tags ); + } + + 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; + } + + std::string TestCaseInfo::tagsAsString() const { + std::string ret; + // '[' and ']' per tag + std::size_t full_size = 2 * tags.size(); + for (const auto& tag : tags) { + full_size += tag.size(); + } + ret.reserve(full_size); + for (const auto& tag : tags) { + ret.push_back('['); + ret.append(tag); + ret.push_back(']'); + } + + return ret; + } + + TestCase::TestCase( ITestInvoker* testCase, TestCaseInfo const& info ) : TestCaseInfo( info ), test( testCase ) {} + + TestCase TestCase::withName( std::string const& _newName ) const { + TestCase other( *this ); + other.name = _newName; + return other; + } + + void TestCase::invoke() const { + test->invoke(); + } + + bool TestCase::operator == ( TestCase const& other ) const { + return test.get() == other.test.get() && + name == other.name && + className == other.className; + } + + bool TestCase::operator < ( TestCase const& other ) const { + return name < other.name; + } + + TestCaseInfo const& TestCase::getTestCaseInfo() const + { + return *this; + } + +} // end namespace Catch +// end catch_test_case_info.cpp +// start catch_test_case_registry_impl.cpp #include + +namespace Catch { + + std::vector sortTests( IConfig const& config, std::vector const& unsortedTestCases ) { + + std::vector sorted = unsortedTestCases; + + switch( config.runOrder() ) { + case RunTests::InLexicographicalOrder: + std::sort( sorted.begin(), sorted.end() ); + break; + case RunTests::InRandomOrder: + seedRng( config ); + RandomNumberGenerator::shuffle( sorted ); + break; + case RunTests::InDeclarationOrder: + // already in declaration order + break; + } + return sorted; + } + bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config ) { + return testSpec.matches( testCase ) && ( config.allowThrows() || !testCase.throws() ); + } + + void enforceNoDuplicateTestCases( std::vector const& functions ) { + std::set seenFunctions; + for( auto const& function : functions ) { + auto prev = seenFunctions.insert( function ); + CATCH_ENFORCE( prev.second, + "error: TEST_CASE( \"" << function.name << "\" ) already defined.\n" + << "\tFirst seen at " << prev.first->getTestCaseInfo().lineInfo << "\n" + << "\tRedefined at " << function.getTestCaseInfo().lineInfo ); + } + } + + std::vector filterTests( std::vector const& testCases, TestSpec const& testSpec, IConfig const& config ) { + std::vector filtered; + filtered.reserve( testCases.size() ); + for( auto const& testCase : testCases ) + if( matchTest( testCase, testSpec, config ) ) + filtered.push_back( testCase ); + return filtered; + } + std::vector const& getAllTestCasesSorted( IConfig const& config ) { + return getRegistryHub().getTestCaseRegistry().getAllTestsSorted( config ); + } + + void TestRegistry::registerTest( TestCase const& testCase ) { + std::string name = testCase.getTestCaseInfo().name; + if( name.empty() ) { + std::ostringstream oss; + oss << "Anonymous test case " << ++m_unnamedCount; + return registerTest( testCase.withName( oss.str() ) ); + } + m_functions.push_back( testCase ); + } + + std::vector const& TestRegistry::getAllTests() const { + return m_functions; + } + std::vector const& TestRegistry::getAllTestsSorted( IConfig const& config ) const { + if( m_sortedFunctions.empty() ) + enforceNoDuplicateTestCases( m_functions ); + + if( m_currentSortOrder != config.runOrder() || m_sortedFunctions.empty() ) { + m_sortedFunctions = sortTests( config, m_functions ); + m_currentSortOrder = config.runOrder(); + } + return m_sortedFunctions; + } + + /////////////////////////////////////////////////////////////////////////// + TestInvokerAsFunction::TestInvokerAsFunction( void(*testAsFunction)() ) noexcept : m_testAsFunction( testAsFunction ) {} + + void TestInvokerAsFunction::invoke() const { + m_testAsFunction(); + } + + 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; + } + +} // end namespace Catch +// end catch_test_case_registry_impl.cpp +// start catch_test_case_tracker.cpp + +#include +#include +#include +#include + +#if defined(__clang__) +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wexit-time-destructors" +#endif + +namespace Catch { +namespace TestCaseTracking { + + NameAndLocation::NameAndLocation( std::string const& _name, SourceLineInfo const& _location ) + : name( _name ), + location( _location ) + {} + + ITracker::~ITracker() = default; + + TrackerContext& TrackerContext::instance() { + static TrackerContext s_instance; + return s_instance; + } + + ITracker& TrackerContext::startRun() { + m_rootTracker = std::make_shared( NameAndLocation( "{root}", CATCH_INTERNAL_LINEINFO ), *this, nullptr ); + m_currentTracker = nullptr; + m_runState = Executing; + return *m_rootTracker; + } + + void TrackerContext::endRun() { + m_rootTracker.reset(); + m_currentTracker = nullptr; + m_runState = NotStarted; + } + + void TrackerContext::startCycle() { + m_currentTracker = m_rootTracker.get(); + m_runState = Executing; + } + void TrackerContext::completeCycle() { + m_runState = CompletedCycle; + } + + bool TrackerContext::completedCycle() const { + return m_runState == CompletedCycle; + } + ITracker& TrackerContext::currentTracker() { + return *m_currentTracker; + } + void TrackerContext::setCurrentTracker( ITracker* tracker ) { + m_currentTracker = tracker; + } + + TrackerBase::TrackerHasName::TrackerHasName( NameAndLocation const& nameAndLocation ) : m_nameAndLocation( nameAndLocation ) {} + bool TrackerBase::TrackerHasName::operator ()( ITrackerPtr const& tracker ) const { + return + tracker->nameAndLocation().name == m_nameAndLocation.name && + tracker->nameAndLocation().location == m_nameAndLocation.location; + } + + TrackerBase::TrackerBase( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent ) + : m_nameAndLocation( nameAndLocation ), + m_ctx( ctx ), + m_parent( parent ) + {} + + NameAndLocation const& TrackerBase::nameAndLocation() const { + return m_nameAndLocation; + } + bool TrackerBase::isComplete() const { + return m_runState == CompletedSuccessfully || m_runState == Failed; + } + bool TrackerBase::isSuccessfullyCompleted() const { + return m_runState == CompletedSuccessfully; + } + bool TrackerBase::isOpen() const { + return m_runState != NotStarted && !isComplete(); + } + bool TrackerBase::hasChildren() const { + return !m_children.empty(); + } + + void TrackerBase::addChild( ITrackerPtr const& child ) { + m_children.push_back( child ); + } + + ITrackerPtr TrackerBase::findChild( NameAndLocation const& nameAndLocation ) { + auto it = std::find_if( m_children.begin(), m_children.end(), TrackerHasName( nameAndLocation ) ); + return( it != m_children.end() ) + ? *it + : nullptr; + } + ITracker& TrackerBase::parent() { + assert( m_parent ); // Should always be non-null except for root + return *m_parent; + } + + void TrackerBase::openChild() { + if( m_runState != ExecutingChildren ) { + m_runState = ExecutingChildren; + if( m_parent ) + m_parent->openChild(); + } + } + + bool TrackerBase::isSectionTracker() const { return false; } + bool TrackerBase::isIndexTracker() const { return false; } + + void TrackerBase::open() { + m_runState = Executing; + moveToThis(); + if( m_parent ) + m_parent->openChild(); + } + + void TrackerBase::close() { + + // Close any still open children (e.g. generators) + while( &m_ctx.currentTracker() != this ) + m_ctx.currentTracker().close(); + + switch( m_runState ) { + case NeedsAnotherRun: + break; + + case Executing: + m_runState = CompletedSuccessfully; + break; + case ExecutingChildren: + if( m_children.empty() || m_children.back()->isComplete() ) + m_runState = CompletedSuccessfully; + break; + + case NotStarted: + case CompletedSuccessfully: + case Failed: + CATCH_INTERNAL_ERROR( "Illogical state: " << m_runState ); + + default: + CATCH_INTERNAL_ERROR( "Unknown state: " << m_runState ); + } + moveToParent(); + m_ctx.completeCycle(); + } + void TrackerBase::fail() { + m_runState = Failed; + if( m_parent ) + m_parent->markAsNeedingAnotherRun(); + moveToParent(); + m_ctx.completeCycle(); + } + void TrackerBase::markAsNeedingAnotherRun() { + m_runState = NeedsAnotherRun; + } + + void TrackerBase::moveToParent() { + assert( m_parent ); + m_ctx.setCurrentTracker( m_parent ); + } + void TrackerBase::moveToThis() { + m_ctx.setCurrentTracker( this ); + } + + SectionTracker::SectionTracker( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent ) + : TrackerBase( nameAndLocation, ctx, parent ) + { + if( parent ) { + while( !parent->isSectionTracker() ) + parent = &parent->parent(); + + SectionTracker& parentSection = static_cast( *parent ); + addNextFilters( parentSection.m_filters ); + } + } + + bool SectionTracker::isSectionTracker() const { return true; } + + SectionTracker& SectionTracker::acquire( TrackerContext& ctx, NameAndLocation const& nameAndLocation ) { + std::shared_ptr section; + + ITracker& currentTracker = ctx.currentTracker(); + if( ITrackerPtr childTracker = currentTracker.findChild( nameAndLocation ) ) { + assert( childTracker ); + assert( childTracker->isSectionTracker() ); + section = std::static_pointer_cast( childTracker ); + } + else { + section = std::make_shared( nameAndLocation, ctx, ¤tTracker ); + currentTracker.addChild( section ); + } + if( !ctx.completedCycle() ) + section->tryOpen(); + return *section; + } + + void SectionTracker::tryOpen() { + if( !isComplete() && (m_filters.empty() || m_filters[0].empty() || m_filters[0] == m_nameAndLocation.name ) ) + open(); + } + + void SectionTracker::addInitialFilters( std::vector const& filters ) { + if( !filters.empty() ) { + m_filters.push_back(""); // Root - should never be consulted + m_filters.push_back(""); // Test Case - not a section filter + m_filters.insert( m_filters.end(), filters.begin(), filters.end() ); + } + } + void SectionTracker::addNextFilters( std::vector const& filters ) { + if( filters.size() > 1 ) + m_filters.insert( m_filters.end(), ++filters.begin(), filters.end() ); + } + + IndexTracker::IndexTracker( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent, int size ) + : TrackerBase( nameAndLocation, ctx, parent ), + m_size( size ) + {} + + bool IndexTracker::isIndexTracker() const { return true; } + + IndexTracker& IndexTracker::acquire( TrackerContext& ctx, NameAndLocation const& nameAndLocation, int size ) { + std::shared_ptr tracker; + + ITracker& currentTracker = ctx.currentTracker(); + if( ITrackerPtr childTracker = currentTracker.findChild( nameAndLocation ) ) { + assert( childTracker ); + assert( childTracker->isIndexTracker() ); + tracker = std::static_pointer_cast( childTracker ); + } + else { + tracker = std::make_shared( nameAndLocation, ctx, ¤tTracker, size ); + currentTracker.addChild( tracker ); + } + + if( !ctx.completedCycle() && !tracker->isComplete() ) { + if( tracker->m_runState != ExecutingChildren && tracker->m_runState != NeedsAnotherRun ) + tracker->moveNext(); + tracker->open(); + } + + return *tracker; + } + + int IndexTracker::index() const { return m_index; } + + void IndexTracker::moveNext() { + m_index++; + m_children.clear(); + } + + void IndexTracker::close() { + TrackerBase::close(); + if( m_runState == CompletedSuccessfully && m_index < m_size-1 ) + m_runState = Executing; + } + +} // namespace TestCaseTracking + +using TestCaseTracking::ITracker; +using TestCaseTracking::TrackerContext; +using TestCaseTracking::SectionTracker; +using TestCaseTracking::IndexTracker; + +} // namespace Catch + +#if defined(__clang__) +# pragma clang diagnostic pop +#endif +// end catch_test_case_tracker.cpp +// start catch_test_registry.cpp + +namespace Catch { + + auto makeTestInvoker( void(*testAsFunction)() ) noexcept -> ITestInvoker* { + return new(std::nothrow) TestInvokerAsFunction( testAsFunction ); + } + + NameAndTags::NameAndTags( StringRef name_ , StringRef tags_ ) noexcept : name( name_ ), tags( tags_ ) {} + + AutoReg::AutoReg( ITestInvoker* invoker, SourceLineInfo const& lineInfo, StringRef classOrMethod, NameAndTags const& nameAndTags ) noexcept { + try { + getMutableRegistryHub() + .registerTest( + makeTestCase( + invoker, + extractClassName( classOrMethod ), + nameAndTags.name, + nameAndTags.tags, + lineInfo)); + } catch (...) { + // Do not throw when constructing global objects, instead register the exception to be processed later + getMutableRegistryHub().registerStartupException(); + } + } + + AutoReg::~AutoReg() = default; +} +// end catch_test_registry.cpp +// start catch_test_spec.cpp + +#include #include #include +#include + +namespace Catch { + + TestSpec::Pattern::~Pattern() = default; + TestSpec::NamePattern::~NamePattern() = default; + TestSpec::TagPattern::~TagPattern() = default; + TestSpec::ExcludedPattern::~ExcludedPattern() = default; + + TestSpec::NamePattern::NamePattern( std::string const& name ) + : m_wildcardPattern( toLower( name ), CaseSensitive::No ) + {} + bool TestSpec::NamePattern::matches( TestCaseInfo const& testCase ) const { + return m_wildcardPattern.matches( toLower( testCase.name ) ); + } + + TestSpec::TagPattern::TagPattern( std::string const& tag ) : m_tag( toLower( tag ) ) {} + bool TestSpec::TagPattern::matches( TestCaseInfo const& testCase ) const { + return std::find(begin(testCase.lcaseTags), + end(testCase.lcaseTags), + m_tag) != end(testCase.lcaseTags); + } + + TestSpec::ExcludedPattern::ExcludedPattern( PatternPtr const& underlyingPattern ) : m_underlyingPattern( underlyingPattern ) {} + bool TestSpec::ExcludedPattern::matches( TestCaseInfo const& testCase ) const { return !m_underlyingPattern->matches( testCase ); } + + bool TestSpec::Filter::matches( TestCaseInfo const& testCase ) const { + // All patterns in a filter must match for the filter to be a match + for( auto const& pattern : m_patterns ) { + if( !pattern->matches( testCase ) ) + return false; + } + return true; + } + + bool TestSpec::hasFilters() const { + return !m_filters.empty(); + } + bool TestSpec::matches( TestCaseInfo const& testCase ) const { + // A TestSpec matches if any filter matches + for( auto const& filter : m_filters ) + if( filter.matches( testCase ) ) + return true; + return false; + } +} +// end catch_test_spec.cpp +// start catch_test_spec_parser.cpp + +namespace Catch { + + TestSpecParser::TestSpecParser( ITagAliasRegistry const& tagAliases ) : m_tagAliases( &tagAliases ) {} + + TestSpecParser& TestSpecParser::parse( std::string const& arg ) { + m_mode = None; + m_exclusion = false; + m_start = std::string::npos; + m_arg = m_tagAliases->expandAliases( arg ); + m_escapeChars.clear(); + for( m_pos = 0; m_pos < m_arg.size(); ++m_pos ) + visitChar( m_arg[m_pos] ); + if( m_mode == Name ) + addPattern(); + return *this; + } + TestSpec TestSpecParser::testSpec() { + addFilter(); + return m_testSpec; + } + + void TestSpecParser::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 ); + case '\\': return escape(); + default: startNewMode( Name, m_pos ); break; + } + } + if( m_mode == Name ) { + if( c == ',' ) { + addPattern(); + addFilter(); + } + else if( c == '[' ) { + if( subString() == "exclude:" ) + m_exclusion = true; + else + addPattern(); + startNewMode( Tag, ++m_pos ); + } + else if( c == '\\' ) + escape(); + } + else if( m_mode == EscapedName ) + m_mode = Name; + else if( m_mode == QuotedName && c == '"' ) + addPattern(); + else if( m_mode == Tag && c == ']' ) + addPattern(); + } + void TestSpecParser::startNewMode( Mode mode, std::size_t start ) { + m_mode = mode; + m_start = start; + } + void TestSpecParser::escape() { + if( m_mode == None ) + m_start = m_pos; + m_mode = EscapedName; + m_escapeChars.push_back( m_pos ); + } + std::string TestSpecParser::subString() const { return m_arg.substr( m_start, m_pos - m_start ); } + + void TestSpecParser::addFilter() { + if( !m_currentFilter.m_patterns.empty() ) { + m_testSpec.m_filters.push_back( m_currentFilter ); + m_currentFilter = TestSpec::Filter(); + } + } + + TestSpec parseTestSpec( std::string const& arg ) { + return TestSpecParser( ITagAliasRegistry::get() ).parse( arg ).testSpec(); + } + +} // namespace Catch +// end catch_test_spec_parser.cpp +// start catch_timer.cpp + +#include + +namespace Catch { + + auto getCurrentNanosecondsSinceEpoch() -> uint64_t { + return std::chrono::duration_cast( std::chrono::high_resolution_clock::now().time_since_epoch() ).count(); + } + + auto estimateClockResolution() -> uint64_t { + uint64_t sum = 0; + static const uint64_t iterations = 1000000; + + for( std::size_t i = 0; i < iterations; ++i ) { + + uint64_t ticks; + uint64_t baseTicks = getCurrentNanosecondsSinceEpoch(); + do { + ticks = getCurrentNanosecondsSinceEpoch(); + } + while( ticks == baseTicks ); + + auto delta = ticks - baseTicks; + sum += delta; + } + + // We're just taking the mean, here. To do better we could take the std. dev and exclude outliers + // - and potentially do more iterations if there's a high variance. + return sum/iterations; + } + auto getEstimatedClockResolution() -> uint64_t { + static auto s_resolution = estimateClockResolution(); + return s_resolution; + } + + void Timer::start() { + m_nanoseconds = getCurrentNanosecondsSinceEpoch(); + } + auto Timer::getElapsedNanoseconds() const -> unsigned int { + return static_cast(getCurrentNanosecondsSinceEpoch() - m_nanoseconds); + } + auto Timer::getElapsedMicroseconds() const -> unsigned int { + return static_cast(getElapsedNanoseconds()/1000); + } + auto Timer::getElapsedMilliseconds() const -> unsigned int { + return static_cast(getElapsedMicroseconds()/1000); + } + auto Timer::getElapsedSeconds() const -> double { + return getElapsedMicroseconds()/1000000.0; + } + +} // namespace Catch +// end catch_timer.cpp +// start catch_tostring.cpp + +#if defined(__clang__) +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wexit-time-destructors" +# pragma clang diagnostic ignored "-Wglobal-constructors" +#endif + #include +namespace Catch { + +namespace Detail { + + const std::string unprintableString = "{?}"; + + namespace { + const int hexThreshold = 255; + + struct Endianness { + enum Arch { Big, Little }; + + static Arch which() { + union _{ + int asInt; + char asChar[sizeof (int)]; + } u; + + u.asInt = 1; + return ( u.asChar[sizeof(int)-1] == 1 ) ? Big : Little; + } + }; + } + + std::string rawMemoryToString( const void *object, std::size_t size ) { + // Reverse order for little endian architectures + int i = 0, end = static_cast( 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(); + } +} + +template +std::string fpToString( T value, int precision ) { + std::ostringstream oss; + oss << std::setprecision( precision ) + << std::fixed + << value; + std::string d = oss.str(); + std::size_t i = d.find_last_not_of( '0' ); + if( i != std::string::npos && i != d.size()-1 ) { + if( d[i] == '.' ) + i++; + d = d.substr( 0, i+1 ); + } + return d; +} + +//// ======================================================= //// +// +// Out-of-line defs for full specialization of StringMaker +// +//// ======================================================= //// + +std::string StringMaker::convert(const std::string& str) { + if (!getCurrentContext().getConfig()->showInvisibles()) { + return '"' + str + '"'; + } + + std::string s("\""); + for (char c : str) { + switch (c) { + case '\n': + s.append("\\n"); + break; + case '\t': + s.append("\\t"); + break; + default: + s.push_back(c); + break; + } + } + s.append("\""); + return s; +} + +std::string StringMaker::convert(const std::wstring& wstr) { + std::string s; + s.reserve(wstr.size()); + for (auto c : wstr) { + s += (c <= 0xff) ? static_cast(c) : '?'; + } + return ::Catch::Detail::stringify(s); +} + +std::string StringMaker::convert(char const* str) { + if (str) { + return ::Catch::Detail::stringify(std::string{ str }); + } else { + return{ "{null string}" }; + } +} +std::string StringMaker::convert(char* str) { + if (str) { + return ::Catch::Detail::stringify(std::string{ str }); + } else { + return{ "{null string}" }; + } +} +std::string StringMaker::convert(wchar_t const * str) { + if (str) { + return ::Catch::Detail::stringify(std::wstring{ str }); + } else { + return{ "{null string}" }; + } +} +std::string StringMaker::convert(wchar_t * str) { + if (str) { + return ::Catch::Detail::stringify(std::wstring{ str }); + } else { + return{ "{null string}" }; + } +} + +std::string StringMaker::convert(int value) { + return ::Catch::Detail::stringify(static_cast(value)); +} +std::string StringMaker::convert(long value) { + return ::Catch::Detail::stringify(static_cast(value)); +} +std::string StringMaker::convert(long long value) { + std::ostringstream oss; + oss << value; + if (value > Detail::hexThreshold) { + oss << " (0x" << std::hex << value << ')'; + } + return oss.str(); +} + +std::string StringMaker::convert(unsigned int value) { + return ::Catch::Detail::stringify(static_cast(value)); +} +std::string StringMaker::convert(unsigned long value) { + return ::Catch::Detail::stringify(static_cast(value)); +} +std::string StringMaker::convert(unsigned long long value) { + std::ostringstream oss; + oss << value; + if (value > Detail::hexThreshold) { + oss << " (0x" << std::hex << value << ')'; + } + return oss.str(); +} + +std::string StringMaker::convert(bool b) { + return b ? "true" : "false"; +} + +std::string StringMaker::convert(char value) { + if (value == '\r') { + return "'\\r'"; + } else if (value == '\f') { + return "'\\f'"; + } else if (value == '\n') { + return "'\\n'"; + } else if (value == '\t') { + return "'\\t'"; + } else if ('\0' <= value && value < ' ') { + return ::Catch::Detail::stringify(static_cast(value)); + } else { + char chstr[] = "' '"; + chstr[1] = value; + return chstr; + } +} +std::string StringMaker::convert(signed char c) { + return ::Catch::Detail::stringify(static_cast(c)); +} +std::string StringMaker::convert(unsigned char c) { + return ::Catch::Detail::stringify(static_cast(c)); +} + +std::string StringMaker::convert(std::nullptr_t) { + return "nullptr"; +} + +std::string StringMaker::convert(float value) { + return fpToString(value, 5) + 'f'; +} +std::string StringMaker::convert(double value) { + return fpToString(value, 10); +} + +} // end namespace Catch + +#if defined(__clang__) +# pragma clang diagnostic pop +#endif + +// end catch_tostring.cpp +// start catch_totals.cpp + +namespace Catch { + + Counts 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& Counts::operator += ( Counts const& other ) { + passed += other.passed; + failed += other.failed; + failedButOk += other.failedButOk; + return *this; + } + + std::size_t Counts::total() const { + return passed + failed + failedButOk; + } + bool Counts::allPassed() const { + return failed == 0 && failedButOk == 0; + } + bool Counts::allOk() const { + return failed == 0; + } + + Totals Totals::operator - ( Totals const& other ) const { + Totals diff; + diff.assertions = assertions - other.assertions; + diff.testCases = testCases - other.testCases; + return diff; + } + + Totals& Totals::operator += ( Totals const& other ) { + assertions += other.assertions; + testCases += other.testCases; + return *this; + } + + Totals 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; + } + +} +// end catch_totals.cpp +// start catch_version.cpp + +#include + +namespace Catch { + + Version::Version + ( unsigned int _majorVersion, + unsigned int _minorVersion, + unsigned int _patchNumber, + char const * const _branchName, + unsigned int _buildNumber ) + : majorVersion( _majorVersion ), + minorVersion( _minorVersion ), + patchNumber( _patchNumber ), + branchName( _branchName ), + buildNumber( _buildNumber ) + {} + + std::ostream& operator << ( std::ostream& os, Version const& version ) { + os << version.majorVersion << '.' + << version.minorVersion << '.' + << version.patchNumber; + // branchName is never null -> 0th char is \0 if it is empty + if (version.branchName[0]) { + os << '-' << version.branchName + << '.' << version.buildNumber; + } + return os; + } + + Version const& libraryVersion() { + static Version version( 2, 0, 1, "", 0 ); + return version; + } + +} +// end catch_version.cpp +// start catch_wildcard_pattern.cpp + +namespace Catch { + + WildcardPattern::WildcardPattern( std::string const& pattern, + CaseSensitive::Choice caseSensitivity ) + : m_caseSensitivity( caseSensitivity ), + m_pattern( adjustCase( pattern ) ) + { + if( startsWith( m_pattern, '*' ) ) { + m_pattern = m_pattern.substr( 1 ); + m_wildcard = WildcardAtStart; + } + if( endsWith( m_pattern, '*' ) ) { + m_pattern = m_pattern.substr( 0, m_pattern.size()-1 ); + m_wildcard = static_cast( m_wildcard | WildcardAtEnd ); + } + } + + bool WildcardPattern::matches( std::string const& str ) const { + switch( m_wildcard ) { + case NoWildcard: + return m_pattern == adjustCase( str ); + case WildcardAtStart: + return endsWith( adjustCase( str ), m_pattern ); + case WildcardAtEnd: + return startsWith( adjustCase( str ), m_pattern ); + case WildcardAtBothEnds: + return contains( adjustCase( str ), m_pattern ); + default: + CATCH_INTERNAL_ERROR( "Unknown enum" ); + } + } + + std::string WildcardPattern::adjustCase( std::string const& str ) const { + return m_caseSensitivity == CaseSensitive::No ? toLower( str ) : str; + } +} +// end catch_wildcard_pattern.cpp +// start catch_xmlwriter.cpp + +// start catch_xmlwriter.h + +#include +#include + namespace Catch { class XmlEncode { public: enum ForWhat { ForTextNodes, ForAttributes }; - XmlEncode( std::string const& str, ForWhat forWhat = ForTextNodes ) - : m_str( str ), - m_forWhat( forWhat ) - {} + XmlEncode( std::string const& str, ForWhat forWhat = ForTextNodes ); - void encodeTo( std::ostream& os ) const { + void encodeTo( std::ostream& os ) const; - // Apostrophe escaping not necessary if we always use " to write attributes - // (see: http://www.w3.org/TR/xml/#syntax) - - for( std::size_t i = 0; i < m_str.size(); ++ i ) { - char c = m_str[i]; - switch( c ) { - case '<': os << "<"; break; - case '&': os << "&"; break; - - case '>': - // See: http://www.w3.org/TR/xml/#syntax - if( i > 2 && m_str[i-1] == ']' && m_str[i-2] == ']' ) - os << ">"; - else - os << c; - break; - - case '\"': - if( m_forWhat == ForAttributes ) - os << """; - else - os << c; - break; - - default: - // Escape control chars - based on contribution by @espenalb in PR #465 and - // by @mrpi PR #588 - if ( ( c >= 0 && c < '\x09' ) || ( c > '\x0D' && c < '\x20') || c=='\x7F' ) { - // see http://stackoverflow.com/questions/404107/why-are-control-characters-illegal-in-xml-1-0 - os << "\\x" << std::uppercase << std::hex << std::setfill('0') << std::setw(2) - << static_cast( c ); - } - else - os << c; - } - } - } - - friend std::ostream& operator << ( std::ostream& os, XmlEncode const& xmlEncode ) { - xmlEncode.encodeTo( os ); - return os; - } + friend std::ostream& operator << ( std::ostream& os, XmlEncode const& xmlEncode ); private: std::string m_str; @@ -9979,24 +9900,14 @@ namespace Catch { class ScopedElement { public: - ScopedElement( XmlWriter* writer ) - : m_writer( writer ) - {} + ScopedElement( XmlWriter* writer ); - ScopedElement( ScopedElement const& other ) - : m_writer( other.m_writer ){ - other.m_writer = CATCH_NULL; - } + ScopedElement( ScopedElement&& other ) noexcept; + ScopedElement& operator=( ScopedElement&& other ) noexcept; - ~ScopedElement() { - if( m_writer ) - m_writer->endElement(); - } + ~ScopedElement(); - ScopedElement& writeText( std::string const& text, bool indent = true ) { - m_writer->writeText( text, indent ); - return *this; - } + ScopedElement& writeText( std::string const& text, bool indent = true ); template ScopedElement& writeAttribute( std::string const& name, T const& attribute ) { @@ -10005,622 +9916,790 @@ namespace Catch { } private: - mutable XmlWriter* m_writer; + mutable XmlWriter* m_writer = nullptr; }; - XmlWriter() - : m_tagIsOpen( false ), - m_needsNewline( false ), - m_os( Catch::cout() ) - { - writeDeclaration(); - } + XmlWriter( std::ostream& os = Catch::cout() ); + ~XmlWriter(); - XmlWriter( std::ostream& os ) - : m_tagIsOpen( false ), - m_needsNewline( false ), - m_os( os ) - { - writeDeclaration(); - } + XmlWriter( XmlWriter const& ) = delete; + XmlWriter& operator=( XmlWriter const& ) = delete; - ~XmlWriter() { - while( !m_tags.empty() ) - endElement(); - } + XmlWriter& startElement( std::string const& name ); - XmlWriter& startElement( std::string const& name ) { - ensureTagClosed(); - newlineIfNecessary(); - m_os << m_indent << '<' << name; - m_tags.push_back( name ); - m_indent += " "; - m_tagIsOpen = true; - return *this; - } + ScopedElement scopedElement( std::string const& name ); - ScopedElement scopedElement( std::string const& name ) { - ScopedElement scoped( this ); - startElement( name ); - return scoped; - } + XmlWriter& endElement(); - XmlWriter& endElement() { - newlineIfNecessary(); - m_indent = m_indent.substr( 0, m_indent.size()-2 ); - if( m_tagIsOpen ) { - m_os << "/>"; - m_tagIsOpen = false; - } - else { - m_os << m_indent << ""; - } - m_os << std::endl; - m_tags.pop_back(); - return *this; - } + XmlWriter& writeAttribute( std::string const& name, std::string const& attribute ); - XmlWriter& writeAttribute( std::string const& name, std::string const& attribute ) { - if( !name.empty() && !attribute.empty() ) - m_os << ' ' << name << "=\"" << XmlEncode( attribute, XmlEncode::ForAttributes ) << '"'; - return *this; - } - - XmlWriter& writeAttribute( std::string const& name, bool attribute ) { - m_os << ' ' << name << "=\"" << ( attribute ? "true" : "false" ) << '"'; - return *this; - } + XmlWriter& writeAttribute( std::string const& name, bool attribute ); template XmlWriter& writeAttribute( std::string const& name, T const& attribute ) { - std::ostringstream oss; - oss << attribute; - return writeAttribute( name, oss.str() ); + m_oss.clear(); + m_oss.str(std::string()); + m_oss << attribute; + return writeAttribute( name, m_oss.str() ); } - XmlWriter& writeText( std::string const& text, bool indent = true ) { - if( !text.empty() ){ - bool tagWasOpen = m_tagIsOpen; - ensureTagClosed(); - if( tagWasOpen && indent ) - m_os << m_indent; - m_os << XmlEncode( text ); - m_needsNewline = true; - } - return *this; - } + XmlWriter& writeText( std::string const& text, bool indent = true ); - XmlWriter& writeComment( std::string const& text ) { - ensureTagClosed(); - m_os << m_indent << ""; - m_needsNewline = true; - return *this; - } + XmlWriter& writeComment( std::string const& text ); - void writeStylesheetRef( std::string const& url ) { - m_os << "\n"; - } + void writeStylesheetRef( std::string const& url ); - XmlWriter& writeBlankLine() { - ensureTagClosed(); - m_os << '\n'; - return *this; - } + XmlWriter& writeBlankLine(); - void ensureTagClosed() { - if( m_tagIsOpen ) { - m_os << ">" << std::endl; - m_tagIsOpen = false; - } - } + void ensureTagClosed(); private: - XmlWriter( XmlWriter const& ); - void operator=( XmlWriter const& ); - void writeDeclaration() { - m_os << "\n"; - } + void writeDeclaration(); - void newlineIfNecessary() { - if( m_needsNewline ) { - m_os << std::endl; - m_needsNewline = false; - } - } + void newlineIfNecessary(); - bool m_tagIsOpen; - bool m_needsNewline; + bool m_tagIsOpen = false; + bool m_needsNewline = false; std::vector m_tags; std::string m_indent; std::ostream& m_os; + std::ostringstream m_oss; }; } -namespace Catch { - class XmlReporter : public StreamingReporterBase { - public: - XmlReporter( ReporterConfig const& _config ) - : StreamingReporterBase( _config ), - m_xml(_config.stream()), - m_sectionDepth( 0 ) - { - m_reporterPrefs.shouldRedirectStdOut = true; - } +// end catch_xmlwriter.h +#include - virtual ~XmlReporter() CATCH_OVERRIDE; +namespace Catch { + + XmlEncode::XmlEncode( std::string const& str, ForWhat forWhat ) + : m_str( str ), + m_forWhat( forWhat ) + {} + + void XmlEncode::encodeTo( std::ostream& os ) const { + + // Apostrophe escaping not necessary if we always use " to write attributes + // (see: http://www.w3.org/TR/xml/#syntax) + + for( std::size_t i = 0; i < m_str.size(); ++ i ) { + char c = m_str[i]; + switch( c ) { + case '<': os << "<"; break; + case '&': os << "&"; break; + + case '>': + // See: http://www.w3.org/TR/xml/#syntax + if( i > 2 && m_str[i-1] == ']' && m_str[i-2] == ']' ) + os << ">"; + else + os << c; + break; + + case '\"': + if( m_forWhat == ForAttributes ) + os << """; + else + os << c; + break; + + default: + // Escape control chars - based on contribution by @espenalb in PR #465 and + // by @mrpi PR #588 + if ( ( c >= 0 && c < '\x09' ) || ( c > '\x0D' && c < '\x20') || c=='\x7F' ) { + // see http://stackoverflow.com/questions/404107/why-are-control-characters-illegal-in-xml-1-0 + os << "\\x" << std::uppercase << std::hex << std::setfill('0') << std::setw(2) + << static_cast( c ); + } + else + os << c; + } + } + } + + std::ostream& operator << ( std::ostream& os, XmlEncode const& xmlEncode ) { + xmlEncode.encodeTo( os ); + return os; + } + + XmlWriter::ScopedElement::ScopedElement( XmlWriter* writer ) + : m_writer( writer ) + {} + + XmlWriter::ScopedElement::ScopedElement( ScopedElement&& other ) noexcept + : m_writer( other.m_writer ){ + other.m_writer = nullptr; + } + XmlWriter::ScopedElement& XmlWriter::ScopedElement::operator=( ScopedElement&& other ) noexcept { + if ( m_writer ) { + m_writer->endElement(); + } + m_writer = other.m_writer; + other.m_writer = nullptr; + return *this; + } + + XmlWriter::ScopedElement::~ScopedElement() { + if( m_writer ) + m_writer->endElement(); + } + + XmlWriter::ScopedElement& XmlWriter::ScopedElement::writeText( std::string const& text, bool indent ) { + m_writer->writeText( text, indent ); + return *this; + } + + XmlWriter::XmlWriter( std::ostream& os ) : m_os( os ) + { + writeDeclaration(); + } + + XmlWriter::~XmlWriter() { + while( !m_tags.empty() ) + endElement(); + } + + XmlWriter& XmlWriter::startElement( std::string const& name ) { + ensureTagClosed(); + newlineIfNecessary(); + m_os << m_indent << '<' << name; + m_tags.push_back( name ); + m_indent += " "; + m_tagIsOpen = true; + return *this; + } + + XmlWriter::ScopedElement XmlWriter::scopedElement( std::string const& name ) { + ScopedElement scoped( this ); + startElement( name ); + return scoped; + } + + XmlWriter& XmlWriter::endElement() { + newlineIfNecessary(); + m_indent = m_indent.substr( 0, m_indent.size()-2 ); + if( m_tagIsOpen ) { + m_os << "/>"; + m_tagIsOpen = false; + } + else { + m_os << m_indent << ""; + } + m_os << std::endl; + m_tags.pop_back(); + return *this; + } + + XmlWriter& XmlWriter::writeAttribute( std::string const& name, std::string const& attribute ) { + if( !name.empty() && !attribute.empty() ) + m_os << ' ' << name << "=\"" << XmlEncode( attribute, XmlEncode::ForAttributes ) << '"'; + return *this; + } + + XmlWriter& XmlWriter::writeAttribute( std::string const& name, bool attribute ) { + m_os << ' ' << name << "=\"" << ( attribute ? "true" : "false" ) << '"'; + return *this; + } + + XmlWriter& XmlWriter::writeText( std::string const& text, bool indent ) { + if( !text.empty() ){ + bool tagWasOpen = m_tagIsOpen; + ensureTagClosed(); + if( tagWasOpen && indent ) + m_os << m_indent; + m_os << XmlEncode( text ); + m_needsNewline = true; + } + return *this; + } + + XmlWriter& XmlWriter::writeComment( std::string const& text ) { + ensureTagClosed(); + m_os << m_indent << ""; + m_needsNewline = true; + return *this; + } + + void XmlWriter::writeStylesheetRef( std::string const& url ) { + m_os << "\n"; + } + + XmlWriter& XmlWriter::writeBlankLine() { + ensureTagClosed(); + m_os << '\n'; + return *this; + } + + void XmlWriter::ensureTagClosed() { + if( m_tagIsOpen ) { + m_os << ">" << std::endl; + m_tagIsOpen = false; + } + } + + void XmlWriter::writeDeclaration() { + m_os << "\n"; + } + + void XmlWriter::newlineIfNecessary() { + if( m_needsNewline ) { + m_os << std::endl; + m_needsNewline = false; + } + } +} +// end catch_xmlwriter.cpp +// start catch_reporter_bases.cpp + +#include +#include +#include +#include +#include + +namespace Catch { + void prepareExpandedExpression(AssertionResult& result) { + result.getExpandedExpression(); + } + + // Because formatting using c++ streams is stateful, drop down to C is required + // Alternatively we could use stringstream, but its performance is... not good. + std::string getFormattedDuration( double duration ) { + // Max exponent + 1 is required to represent the whole part + // + 1 for decimal point + // + 3 for the 3 decimal places + // + 1 for null terminator + const std::size_t maxDoubleSize = DBL_MAX_10_EXP + 1 + 1 + 3 + 1; + char buffer[maxDoubleSize]; + + // Save previous errno, to prevent sprintf from overwriting it + ErrnoGuard guard; +#ifdef _MSC_VER + sprintf_s(buffer, "%.3f", duration); +#else + sprintf(buffer, "%.3f", duration); +#endif + return std::string(buffer); + } + + TestEventListenerBase::TestEventListenerBase(ReporterConfig const & _config) + :StreamingReporterBase(_config) {} + + void TestEventListenerBase::assertionStarting(AssertionInfo const &) {} + + bool TestEventListenerBase::assertionEnded(AssertionStats const &) { + return false; + } + +} // end namespace Catch +// end catch_reporter_bases.cpp +// start catch_reporter_compact.cpp + +namespace { + +#ifdef CATCH_PLATFORM_MAC + const char* failedString() { return "FAILED"; } + const char* passedString() { return "PASSED"; } +#else + const char* failedString() { return "failed"; } + const char* passedString() { return "passed"; } +#endif + + // Colour::LightGrey + Catch::Colour::Code dimColour() { return Catch::Colour::FileName; } + + std::string bothOrAll( std::size_t count ) { + return count == 1 ? std::string() : + count == 2 ? "both " : "all " ; + } +} + +namespace Catch { + + struct CompactReporter : StreamingReporterBase { + + using StreamingReporterBase::StreamingReporterBase; + + ~CompactReporter() override; static std::string getDescription() { - return "Reports test results as an XML document"; + return "Reports test results on a single line, suitable for IDEs"; } - virtual std::string getStylesheetRef() const { - return std::string(); + ReporterPreferences getPreferences() const override { + ReporterPreferences prefs; + prefs.shouldRedirectStdOut = false; + return prefs; } - void writeSourceInfo( SourceLineInfo const& sourceInfo ) { - m_xml - .writeAttribute( "filename", sourceInfo.file ) - .writeAttribute( "line", sourceInfo.line ); + void noMatchingTestCases( std::string const& spec ) override { + stream << "No test cases matched '" << spec << '\'' << std::endl; } - public: // StreamingReporterBase + void assertionStarting( AssertionInfo const& ) override {} - virtual void noMatchingTestCases( std::string const& s ) CATCH_OVERRIDE { - StreamingReporterBase::noMatchingTestCases( s ); + bool assertionEnded( AssertionStats const& _assertionStats ) override { + AssertionResult const& result = _assertionStats.assertionResult; + + bool printInfoMessages = true; + + // Drop out if result was successful and we're not printing those + if( !m_config->includeSuccessfulResults() && result.isOk() ) { + if( result.getResultType() != ResultWas::Warning ) + return false; + printInfoMessages = false; + } + + AssertionPrinter printer( stream, _assertionStats, printInfoMessages ); + printer.print(); + + stream << std::endl; + return true; } - virtual void testRunStarting( TestRunInfo const& testInfo ) CATCH_OVERRIDE { - StreamingReporterBase::testRunStarting( testInfo ); - std::string stylesheetRef = getStylesheetRef(); - if( !stylesheetRef.empty() ) - m_xml.writeStylesheetRef( stylesheetRef ); - m_xml.startElement( "Catch" ); - if( !m_config->name().empty() ) - m_xml.writeAttribute( "name", m_config->name() ); - } - - virtual void testGroupStarting( GroupInfo const& groupInfo ) CATCH_OVERRIDE { - StreamingReporterBase::testGroupStarting( groupInfo ); - m_xml.startElement( "Group" ) - .writeAttribute( "name", groupInfo.name ); - } - - virtual void testCaseStarting( TestCaseInfo const& testInfo ) CATCH_OVERRIDE { - StreamingReporterBase::testCaseStarting(testInfo); - m_xml.startElement( "TestCase" ) - .writeAttribute( "name", trim( testInfo.name ) ) - .writeAttribute( "description", testInfo.description ) - .writeAttribute( "tags", testInfo.tagsAsString ); - - writeSourceInfo( testInfo.lineInfo ); - - if ( m_config->showDurations() == ShowDurations::Always ) - m_testCaseTimer.start(); - m_xml.ensureTagClosed(); - } - - virtual void sectionStarting( SectionInfo const& sectionInfo ) CATCH_OVERRIDE { - StreamingReporterBase::sectionStarting( sectionInfo ); - if( m_sectionDepth++ > 0 ) { - m_xml.startElement( "Section" ) - .writeAttribute( "name", trim( sectionInfo.name ) ) - .writeAttribute( "description", sectionInfo.description ); - writeSourceInfo( sectionInfo.lineInfo ); - m_xml.ensureTagClosed(); + void sectionEnded(SectionStats const& _sectionStats) override { + if (m_config->showDurations() == ShowDurations::Always) { + stream << getFormattedDuration(_sectionStats.durationInSeconds) << " s: " << _sectionStats.sectionInfo.name << std::endl; } } - virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE { } + void testRunEnded( TestRunStats const& _testRunStats ) override { + printTotals( _testRunStats.totals ); + stream << '\n' << std::endl; + StreamingReporterBase::testRunEnded( _testRunStats ); + } - virtual bool assertionEnded( AssertionStats const& assertionStats ) CATCH_OVERRIDE { + private: + class AssertionPrinter { + public: + AssertionPrinter& operator= ( AssertionPrinter const& ) = delete; + AssertionPrinter( AssertionPrinter const& ) = delete; + AssertionPrinter( std::ostream& _stream, AssertionStats const& _stats, bool _printInfoMessages ) + : stream( _stream ) + , result( _stats.assertionResult ) + , messages( _stats.infoMessages ) + , itMessage( _stats.infoMessages.begin() ) + , printInfoMessages( _printInfoMessages ) + {} - AssertionResult const& result = assertionStats.assertionResult; + void print() { + printSourceInfo(); - bool includeResults = m_config->includeSuccessfulResults() || !result.isOk(); + itMessage = messages.begin(); - if( includeResults ) { - // Print any info messages in tags. - for( std::vector::const_iterator it = assertionStats.infoMessages.begin(), itEnd = assertionStats.infoMessages.end(); - it != itEnd; - ++it ) { - if( it->type == ResultWas::Info ) { - m_xml.scopedElement( "Info" ) - .writeText( it->message ); - } else if ( it->type == ResultWas::Warning ) { - m_xml.scopedElement( "Warning" ) - .writeText( it->message ); + switch( result.getResultType() ) { + case ResultWas::Ok: + printResultType( Colour::ResultSuccess, passedString() ); + printOriginalExpression(); + printReconstructedExpression(); + if ( ! result.hasExpression() ) + printRemainingMessages( Colour::None ); + else + printRemainingMessages(); + break; + case ResultWas::ExpressionFailed: + if( result.isOk() ) + printResultType( Colour::ResultSuccess, failedString() + std::string( " - but was ok" ) ); + else + printResultType( Colour::Error, failedString() ); + printOriginalExpression(); + printReconstructedExpression(); + printRemainingMessages(); + break; + case ResultWas::ThrewException: + printResultType( Colour::Error, failedString() ); + printIssue( "unexpected exception with message:" ); + printMessage(); + printExpressionWas(); + printRemainingMessages(); + break; + case ResultWas::FatalErrorCondition: + printResultType( Colour::Error, failedString() ); + printIssue( "fatal error condition with message:" ); + printMessage(); + printExpressionWas(); + printRemainingMessages(); + break; + case ResultWas::DidntThrowException: + printResultType( Colour::Error, failedString() ); + printIssue( "expected exception, got none" ); + printExpressionWas(); + printRemainingMessages(); + break; + case ResultWas::Info: + printResultType( Colour::None, "info" ); + printMessage(); + printRemainingMessages(); + break; + case ResultWas::Warning: + printResultType( Colour::None, "warning" ); + printMessage(); + printRemainingMessages(); + break; + case ResultWas::ExplicitFailure: + printResultType( Colour::Error, failedString() ); + printIssue( "explicitly" ); + printRemainingMessages( Colour::None ); + break; + // These cases are here to prevent compiler warnings + case ResultWas::Unknown: + case ResultWas::FailureBit: + case ResultWas::Exception: + printResultType( Colour::Error, "** internal error **" ); + break; + } + } + + private: + void printSourceInfo() const { + Colour colourGuard( Colour::FileName ); + stream << result.getSourceInfo() << ':'; + } + + void printResultType( Colour::Code colour, std::string const& passOrFail ) const { + if( !passOrFail.empty() ) { + { + Colour colourGuard( colour ); + stream << ' ' << passOrFail; + } + stream << ':'; + } + } + + void printIssue( std::string const& 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 (or auto) 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"; + } } } } - // Drop out if result was successful but we're not printing them. - if( !includeResults && result.getResultType() != ResultWas::Warning ) - return true; + private: + std::ostream& stream; + AssertionResult const& result; + std::vector messages; + std::vector::const_iterator itMessage; + bool printInfoMessages; + }; - // Print the expression if there is one. - if( result.hasExpression() ) { - m_xml.startElement( "Expression" ) - .writeAttribute( "success", result.succeeded() ) - .writeAttribute( "type", result.getTestMacroName() ); + // 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. - writeSourceInfo( result.getSourceInfo() ); - - m_xml.scopedElement( "Original" ) - .writeText( result.getExpression() ); - m_xml.scopedElement( "Expanded" ) - .writeText( result.getExpandedExpression() ); + void printTotals( const Totals& totals ) const { + if( totals.testCases.total() == 0 ) { + stream << "No tests ran."; } - - // And... Print a result applicable to each result type. - switch( result.getResultType() ) { - case ResultWas::ThrewException: - m_xml.startElement( "Exception" ); - writeSourceInfo( result.getSourceInfo() ); - m_xml.writeText( result.getMessage() ); - m_xml.endElement(); - break; - case ResultWas::FatalErrorCondition: - m_xml.startElement( "FatalErrorCondition" ); - writeSourceInfo( result.getSourceInfo() ); - m_xml.writeText( result.getMessage() ); - m_xml.endElement(); - break; - case ResultWas::Info: - m_xml.scopedElement( "Info" ) - .writeText( result.getMessage() ); - break; - case ResultWas::Warning: - // Warning will already have been written - break; - case ResultWas::ExplicitFailure: - m_xml.startElement( "Failure" ); - writeSourceInfo( result.getSourceInfo() ); - m_xml.writeText( result.getMessage() ); - m_xml.endElement(); - break; - default: - break; + 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 ) : std::string(); + stream << + "Failed " << bothOrAll( totals.testCases.failed ) + << pluralise( totals.testCases.failed, "test case" ) << ", " + "failed " << qualify_assertions_failed << + pluralise( totals.assertions.failed, "assertion" ) << '.'; } - - if( result.hasExpression() ) - m_xml.endElement(); - - return true; - } - - virtual void sectionEnded( SectionStats const& sectionStats ) CATCH_OVERRIDE { - StreamingReporterBase::sectionEnded( sectionStats ); - if( --m_sectionDepth > 0 ) { - XmlWriter::ScopedElement e = m_xml.scopedElement( "OverallResults" ); - e.writeAttribute( "successes", sectionStats.assertions.passed ); - e.writeAttribute( "failures", sectionStats.assertions.failed ); - e.writeAttribute( "expectedFailures", sectionStats.assertions.failedButOk ); - - if ( m_config->showDurations() == ShowDurations::Always ) - e.writeAttribute( "durationInSeconds", sectionStats.durationInSeconds ); - - m_xml.endElement(); + 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" ) << '.'; } } - - virtual void testCaseEnded( TestCaseStats const& testCaseStats ) CATCH_OVERRIDE { - StreamingReporterBase::testCaseEnded( testCaseStats ); - XmlWriter::ScopedElement e = m_xml.scopedElement( "OverallResult" ); - e.writeAttribute( "success", testCaseStats.totals.assertions.allOk() ); - - if ( m_config->showDurations() == ShowDurations::Always ) - e.writeAttribute( "durationInSeconds", m_testCaseTimer.getElapsedSeconds() ); - - if( !testCaseStats.stdOut.empty() ) - m_xml.scopedElement( "StdOut" ).writeText( trim( testCaseStats.stdOut ), false ); - if( !testCaseStats.stdErr.empty() ) - m_xml.scopedElement( "StdErr" ).writeText( trim( testCaseStats.stdErr ), false ); - - m_xml.endElement(); - } - - virtual void testGroupEnded( TestGroupStats const& testGroupStats ) CATCH_OVERRIDE { - StreamingReporterBase::testGroupEnded( testGroupStats ); - // TODO: Check testGroupStats.aborting and act accordingly. - m_xml.scopedElement( "OverallResults" ) - .writeAttribute( "successes", testGroupStats.totals.assertions.passed ) - .writeAttribute( "failures", testGroupStats.totals.assertions.failed ) - .writeAttribute( "expectedFailures", testGroupStats.totals.assertions.failedButOk ); - m_xml.endElement(); - } - - virtual void testRunEnded( TestRunStats const& testRunStats ) CATCH_OVERRIDE { - StreamingReporterBase::testRunEnded( testRunStats ); - m_xml.scopedElement( "OverallResults" ) - .writeAttribute( "successes", testRunStats.totals.assertions.passed ) - .writeAttribute( "failures", testRunStats.totals.assertions.failed ) - .writeAttribute( "expectedFailures", testRunStats.totals.assertions.failedButOk ); - m_xml.endElement(); - } - - private: - Timer m_testCaseTimer; - XmlWriter m_xml; - int m_sectionDepth; }; - INTERNAL_CATCH_REGISTER_REPORTER( "xml", XmlReporter ) + CompactReporter::~CompactReporter() {} + + CATCH_REGISTER_REPORTER( "compact", CompactReporter ) } // end namespace Catch - -// #included from: ../reporters/catch_reporter_junit.hpp -#define TWOBLUECUBES_CATCH_REPORTER_JUNIT_HPP_INCLUDED - -#include - -namespace Catch { - - namespace { - std::string getCurrentTimestamp() { - // Beware, this is not reentrant because of backward compatibility issues - // Also, UTC only, again because of backward compatibility (%z is C++11) - time_t rawtime; - std::time(&rawtime); - const size_t timeStampSize = sizeof("2017-01-16T17:06:45Z"); - -#ifdef _MSC_VER - std::tm timeInfo = {}; - gmtime_s(&timeInfo, &rawtime); -#else - std::tm* timeInfo; - timeInfo = std::gmtime(&rawtime); -#endif - - char timeStamp[timeStampSize]; - const char * const fmt = "%Y-%m-%dT%H:%M:%SZ"; - -#ifdef _MSC_VER - std::strftime(timeStamp, timeStampSize, fmt, &timeInfo); -#else - std::strftime(timeStamp, timeStampSize, fmt, timeInfo); -#endif - return std::string(timeStamp); - } - - } - - class JunitReporter : public CumulativeReporterBase { - public: - JunitReporter( ReporterConfig const& _config ) - : CumulativeReporterBase( _config ), - xml( _config.stream() ), - unexpectedExceptions( 0 ), - m_okToFail( false ) - { - m_reporterPrefs.shouldRedirectStdOut = true; - } - - virtual ~JunitReporter() CATCH_OVERRIDE; - - static std::string getDescription() { - return "Reports test results in an XML format that looks like Ant's junitreport target"; - } - - virtual void noMatchingTestCases( std::string const& /*spec*/ ) CATCH_OVERRIDE {} - - virtual void testRunStarting( TestRunInfo const& runInfo ) CATCH_OVERRIDE { - CumulativeReporterBase::testRunStarting( runInfo ); - xml.startElement( "testsuites" ); - } - - virtual void testGroupStarting( GroupInfo const& groupInfo ) CATCH_OVERRIDE { - suiteTimer.start(); - stdOutForSuite.str(""); - stdErrForSuite.str(""); - unexpectedExceptions = 0; - CumulativeReporterBase::testGroupStarting( groupInfo ); - } - - virtual void testCaseStarting( TestCaseInfo const& testCaseInfo ) CATCH_OVERRIDE { - m_okToFail = testCaseInfo.okToFail(); - } - virtual bool assertionEnded( AssertionStats const& assertionStats ) CATCH_OVERRIDE { - if( assertionStats.assertionResult.getResultType() == ResultWas::ThrewException && !m_okToFail ) - unexpectedExceptions++; - return CumulativeReporterBase::assertionEnded( assertionStats ); - } - - virtual void testCaseEnded( TestCaseStats const& testCaseStats ) CATCH_OVERRIDE { - stdOutForSuite << testCaseStats.stdOut; - stdErrForSuite << testCaseStats.stdErr; - CumulativeReporterBase::testCaseEnded( testCaseStats ); - } - - virtual void testGroupEnded( TestGroupStats const& testGroupStats ) CATCH_OVERRIDE { - double suiteTime = suiteTimer.getElapsedSeconds(); - CumulativeReporterBase::testGroupEnded( testGroupStats ); - writeGroup( *m_testGroups.back(), suiteTime ); - } - - virtual void testRunEndedCumulative() CATCH_OVERRIDE { - xml.endElement(); - } - - void writeGroup( TestGroupNode const& groupNode, double suiteTime ) { - XmlWriter::ScopedElement e = xml.scopedElement( "testsuite" ); - TestGroupStats const& stats = groupNode.value; - xml.writeAttribute( "name", stats.groupInfo.name ); - xml.writeAttribute( "errors", unexpectedExceptions ); - xml.writeAttribute( "failures", stats.totals.assertions.failed-unexpectedExceptions ); - xml.writeAttribute( "tests", stats.totals.assertions.total() ); - xml.writeAttribute( "hostname", "tbd" ); // !TBD - if( m_config->showDurations() == ShowDurations::Never ) - xml.writeAttribute( "time", "" ); - else - xml.writeAttribute( "time", suiteTime ); - xml.writeAttribute( "timestamp", getCurrentTimestamp() ); - - // Write test cases - for( TestGroupNode::ChildNodes::const_iterator - it = groupNode.children.begin(), itEnd = groupNode.children.end(); - it != itEnd; - ++it ) - writeTestCase( **it ); - - xml.scopedElement( "system-out" ).writeText( trim( stdOutForSuite.str() ), false ); - xml.scopedElement( "system-err" ).writeText( trim( stdErrForSuite.str() ), false ); - } - - void writeTestCase( TestCaseNode const& testCaseNode ) { - TestCaseStats const& stats = testCaseNode.value; - - // All test cases have exactly one section - which represents the - // test case itself. That section may have 0-n nested sections - assert( testCaseNode.children.size() == 1 ); - SectionNode const& rootSection = *testCaseNode.children.front(); - - std::string className = stats.testInfo.className; - - if( className.empty() ) { - if( rootSection.childSections.empty() ) - className = "global"; - } - writeSection( className, "", rootSection ); - } - - void writeSection( std::string const& className, - std::string const& rootName, - SectionNode const& sectionNode ) { - std::string name = trim( sectionNode.stats.sectionInfo.name ); - if( !rootName.empty() ) - name = rootName + '/' + name; - - if( !sectionNode.assertions.empty() || - !sectionNode.stdOut.empty() || - !sectionNode.stdErr.empty() ) { - XmlWriter::ScopedElement e = xml.scopedElement( "testcase" ); - if( className.empty() ) { - xml.writeAttribute( "classname", name ); - xml.writeAttribute( "name", "root" ); - } - else { - xml.writeAttribute( "classname", className ); - xml.writeAttribute( "name", name ); - } - xml.writeAttribute( "time", Catch::toString( sectionNode.stats.durationInSeconds ) ); - - writeAssertions( sectionNode ); - - if( !sectionNode.stdOut.empty() ) - xml.scopedElement( "system-out" ).writeText( trim( sectionNode.stdOut ), false ); - if( !sectionNode.stdErr.empty() ) - xml.scopedElement( "system-err" ).writeText( trim( sectionNode.stdErr ), false ); - } - for( SectionNode::ChildSections::const_iterator - it = sectionNode.childSections.begin(), - itEnd = sectionNode.childSections.end(); - it != itEnd; - ++it ) - if( className.empty() ) - writeSection( name, "", **it ); - else - writeSection( className, name, **it ); - } - - void writeAssertions( SectionNode const& sectionNode ) { - for( SectionNode::Assertions::const_iterator - it = sectionNode.assertions.begin(), itEnd = sectionNode.assertions.end(); - it != itEnd; - ++it ) - writeAssertion( *it ); - } - void writeAssertion( AssertionStats const& stats ) { - AssertionResult const& result = stats.assertionResult; - if( !result.isOk() ) { - std::string elementName; - switch( result.getResultType() ) { - case ResultWas::ThrewException: - case ResultWas::FatalErrorCondition: - elementName = "error"; - break; - case ResultWas::ExplicitFailure: - elementName = "failure"; - break; - case ResultWas::ExpressionFailed: - elementName = "failure"; - break; - case ResultWas::DidntThrowException: - elementName = "failure"; - break; - - // We should never see these here: - case ResultWas::Info: - case ResultWas::Warning: - case ResultWas::Ok: - case ResultWas::Unknown: - case ResultWas::FailureBit: - case ResultWas::Exception: - elementName = "internalError"; - break; - } - - XmlWriter::ScopedElement e = xml.scopedElement( elementName ); - - xml.writeAttribute( "message", result.getExpandedExpression() ); - xml.writeAttribute( "type", result.getTestMacroName() ); - - std::ostringstream oss; - if( !result.getMessage().empty() ) - oss << result.getMessage() << '\n'; - for( std::vector::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; - bool m_okToFail; - }; - - INTERNAL_CATCH_REGISTER_REPORTER( "junit", JunitReporter ) - -} // end namespace Catch - -// #included from: ../reporters/catch_reporter_console.hpp -#define TWOBLUECUBES_CATCH_REPORTER_CONSOLE_HPP_INCLUDED +// end catch_reporter_compact.cpp +// start catch_reporter_console.cpp #include #include +#if defined(_MSC_VER) +#pragma warning(push) +#pragma warning(disable:4061) // Not all labels are EXPLICITLY handled in switch + // Note that 4062 (not all labels are handled + // and default is missing) is enabled +#endif + namespace Catch { - struct ConsoleReporter : StreamingReporterBase { - ConsoleReporter( ReporterConfig const& _config ) - : StreamingReporterBase( _config ), - m_headerPrinted( false ) - {} + namespace { + 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; + } - virtual ~ConsoleReporter() CATCH_OVERRIDE; + 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; + } + + struct ColumnInfo { + enum Justification { Left, Right }; + std::string name; + int width; + Justification justification; + }; + struct ColumnBreak {}; + struct RowBreak {}; + + class TablePrinter { + std::ostream& m_os; + std::vector m_columnInfos; + std::ostringstream m_oss; + int m_currentColumn = -1; + bool m_isOpen = false; + + public: + TablePrinter( std::ostream& os, std::vector const& columnInfos ) + : m_os( os ), + m_columnInfos( columnInfos ) + {} + + auto columnInfos() const -> std::vector const& { + return m_columnInfos; + } + + void open() { + if( !m_isOpen ) { + m_isOpen = true; + *this << RowBreak(); + for( auto const& info : m_columnInfos ) + *this << info.name << ColumnBreak(); + *this << RowBreak(); + m_os << Catch::getLineOfChars<'-'>() << "\n"; + } + } + void close() { + if( m_isOpen ) { + *this << RowBreak(); + m_os << std::endl; + m_isOpen = false; + } + } + + template + friend TablePrinter& operator << ( TablePrinter& tp, T const& value ) { + tp.m_oss << value; + return tp; + } + + friend TablePrinter& operator << ( TablePrinter& tp, ColumnBreak ) { + auto colStr = tp.m_oss.str(); + // This takes account of utf8 encodings + auto strSize = Catch::StringRef( colStr ).numberOfCharacters(); + tp.m_oss.str(""); + tp.open(); + if( tp.m_currentColumn == static_cast(tp.m_columnInfos.size()-1) ) { + tp.m_currentColumn = -1; + tp.m_os << "\n"; + } + tp.m_currentColumn++; + + auto colInfo = tp.m_columnInfos[tp.m_currentColumn]; + auto padding = ( strSize+2 < static_cast( colInfo.width ) ) + ? std::string( colInfo.width-(strSize+2), ' ' ) + : std::string(); + if( colInfo.justification == ColumnInfo::Left ) + tp.m_os << colStr << padding << " "; + else + tp.m_os << padding << colStr << " "; + return tp; + } + + friend TablePrinter& operator << ( TablePrinter& tp, RowBreak ) { + if( tp.m_currentColumn > 0 ) { + tp.m_os << "\n"; + tp.m_currentColumn = -1; + } + return tp; + } + }; + + class Duration { + enum class Unit { + Auto, + Nanoseconds, + Microseconds, + Milliseconds, + Seconds, + Minutes + }; + static const uint64_t s_nanosecondsInAMicrosecond = 1000; + static const uint64_t s_nanosecondsInAMillisecond = 1000*s_nanosecondsInAMicrosecond; + static const uint64_t s_nanosecondsInASecond = 1000*s_nanosecondsInAMillisecond; + static const uint64_t s_nanosecondsInAMinute = 60*s_nanosecondsInASecond; + + uint64_t m_inNanoseconds; + Unit m_units; + + public: + Duration( uint64_t inNanoseconds, Unit units = Unit::Auto ) + : m_inNanoseconds( inNanoseconds ), + m_units( units ) + { + if( m_units == Unit::Auto ) { + if( m_inNanoseconds < s_nanosecondsInAMicrosecond ) + m_units = Unit::Nanoseconds; + else if( m_inNanoseconds < s_nanosecondsInAMillisecond ) + m_units = Unit::Microseconds; + else if( m_inNanoseconds < s_nanosecondsInASecond ) + m_units = Unit::Milliseconds; + else if( m_inNanoseconds < s_nanosecondsInAMinute ) + m_units = Unit::Seconds; + else + m_units = Unit::Minutes; + } + + } + + auto value() const -> double { + switch( m_units ) { + case Unit::Microseconds: + return m_inNanoseconds / static_cast( s_nanosecondsInAMicrosecond ); + case Unit::Milliseconds: + return m_inNanoseconds / static_cast( s_nanosecondsInAMillisecond ); + case Unit::Seconds: + return m_inNanoseconds / static_cast( s_nanosecondsInASecond ); + case Unit::Minutes: + return m_inNanoseconds / static_cast( s_nanosecondsInAMinute ); + default: + return static_cast( m_inNanoseconds ); + } + } + auto unitsAsString() const -> std::string { + switch( m_units ) { + case Unit::Nanoseconds: + return "ns"; + case Unit::Microseconds: + return "µs"; + case Unit::Milliseconds: + return "ms"; + case Unit::Seconds: + return "s"; + case Unit::Minutes: + return "m"; + default: + return "** internal error **"; + } + + } + friend auto operator << ( std::ostream& os, Duration const& duration ) -> std::ostream& { + return os << duration.value() << " " << duration.unitsAsString(); + } + }; + } // end anon namespace + + struct ConsoleReporter : StreamingReporterBase { + TablePrinter m_tablePrinter; + + ConsoleReporter( ReporterConfig const& config ) + : StreamingReporterBase( config ), + m_tablePrinter( config.stream(), + { + { "benchmark name", CATCH_CONFIG_CONSOLE_WIDTH-32, ColumnInfo::Left }, + { "iters", 8, ColumnInfo::Right }, + { "elapsed ns", 14, ColumnInfo::Right }, + { "average", 14, ColumnInfo::Right } + } ) + {} + ~ConsoleReporter() override; static std::string getDescription() { return "Reports test results as plain lines of text"; } - virtual void noMatchingTestCases( std::string const& spec ) CATCH_OVERRIDE { + void noMatchingTestCases( std::string const& spec ) override { stream << "No test cases matched '" << spec << '\'' << std::endl; } - virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE { + void assertionStarting( AssertionInfo const& ) override { } - virtual bool assertionEnded( AssertionStats const& _assertionStats ) CATCH_OVERRIDE { + bool assertionEnded( AssertionStats const& _assertionStats ) override { AssertionResult const& result = _assertionStats.assertionResult; bool includeResults = m_config->includeSuccessfulResults() || !result.isOk(); @@ -10637,11 +10716,12 @@ namespace Catch { return true; } - virtual void sectionStarting( SectionInfo const& _sectionInfo ) CATCH_OVERRIDE { + void sectionStarting( SectionInfo const& _sectionInfo ) override { m_headerPrinted = false; StreamingReporterBase::sectionStarting( _sectionInfo ); } - virtual void sectionEnded( SectionStats const& _sectionStats ) CATCH_OVERRIDE { + void sectionEnded( SectionStats const& _sectionStats ) override { + m_tablePrinter.close(); if( _sectionStats.missingAssertions ) { lazyPrint(); Colour colour( Colour::ResultError ); @@ -10660,11 +10740,35 @@ namespace Catch { StreamingReporterBase::sectionEnded( _sectionStats ); } - virtual void testCaseEnded( TestCaseStats const& _testCaseStats ) CATCH_OVERRIDE { + void benchmarkStarting( BenchmarkInfo const& info ) override { + lazyPrintWithoutClosingBenchmarkTable(); + + auto nameCol = Column( info.name ).width( m_tablePrinter.columnInfos()[0].width-2 ); + + bool firstLine = true; + for( auto line : nameCol ) { + if( !firstLine ) + m_tablePrinter << ColumnBreak() << ColumnBreak() << ColumnBreak(); + else + firstLine = false; + + m_tablePrinter << line << ColumnBreak(); + } + } + void benchmarkEnded( BenchmarkStats const& stats ) override { + Duration average( stats.elapsedTimeInNanoseconds/stats.iterations ); + m_tablePrinter + << stats.iterations << ColumnBreak() + << stats.elapsedTimeInNanoseconds << ColumnBreak() + << average << ColumnBreak(); + } + + void testCaseEnded( TestCaseStats const& _testCaseStats ) override { + m_tablePrinter.close(); StreamingReporterBase::testCaseEnded( _testCaseStats ); m_headerPrinted = false; } - virtual void testGroupEnded( TestGroupStats const& _testGroupStats ) CATCH_OVERRIDE { + void testGroupEnded( TestGroupStats const& _testGroupStats ) override { if( currentGroupInfo.used ) { printSummaryDivider(); stream << "Summary for group '" << _testGroupStats.groupInfo.name << "':\n"; @@ -10673,7 +10777,7 @@ namespace Catch { } StreamingReporterBase::testGroupEnded( _testGroupStats ); } - virtual void testRunEnded( TestRunStats const& _testRunStats ) CATCH_OVERRIDE { + void testRunEnded( TestRunStats const& _testRunStats ) override { printTotalsDivider( _testRunStats.totals ); printTotals( _testRunStats.totals ); stream << std::endl; @@ -10683,8 +10787,9 @@ namespace Catch { private: class AssertionPrinter { - void operator= ( AssertionPrinter const& ); public: + AssertionPrinter& operator= ( AssertionPrinter const& ) = delete; + AssertionPrinter( AssertionPrinter const& ) = delete; AssertionPrinter( std::ostream& _stream, AssertionStats const& _stats, bool _printInfoMessages ) : stream( _stream ), stats( _stats ), @@ -10795,18 +10900,16 @@ namespace Catch { if( result.hasExpandedExpression() ) { stream << "with expansion:\n"; Colour colourGuard( Colour::ReconstructedExpression ); - stream << Text( result.getExpandedExpression(), TextAttributes().setIndent(2) ) << '\n'; + stream << Column( result.getExpandedExpression() ).indent(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 ) { + for( auto const& msg : messages ) { // If this assertion is a warning ignore any INFO messages - if( printInfoMessages || it->type != ResultWas::Info ) - stream << Text( it->message, TextAttributes().setIndent(2) ) << '\n'; + if( printInfoMessages || msg.type != ResultWas::Info ) + stream << Column( msg.message ).indent(2) << '\n'; } } void printSourceInfo() const { @@ -10827,6 +10930,12 @@ namespace Catch { void lazyPrint() { + m_tablePrinter.close(); + lazyPrintWithoutClosingBenchmarkTable(); + } + + void lazyPrintWithoutClosingBenchmarkTable() { + if( !currentTestRunInfo.used ) lazyPrintRunInfo(); if( !currentGroupInfo.used ) @@ -10862,7 +10971,7 @@ namespace Catch { if( m_sectionStack.size() > 1 ) { Colour colourGuard( Colour::Headers ); - std::vector::const_iterator + auto it = m_sectionStack.begin()+1, // Skip first section (test case) itEnd = m_sectionStack.end(); for( ; it != itEnd; ++it ) @@ -10899,9 +11008,7 @@ namespace Catch { i+=2; else i = 0; - stream << Text( _string, TextAttributes() - .setIndent( indent+i) - .setInitialIndent( indent ) ) << '\n'; + stream << Column( _string ).indent( indent+i ).initialIndent( indent ) << '\n'; } struct SummaryColumn { @@ -10914,10 +11021,10 @@ namespace Catch { 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() ) + for( auto& oldRow : rows ) { + while( oldRow.size() < row.size() ) + oldRow = ' ' + oldRow; + while( oldRow.size() > row.size() ) row = ' ' + row; } rows.push_back( row ); @@ -10962,9 +11069,9 @@ namespace Catch { } } 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() ) { + for( auto col : cols ) { + std::string value = col.rows[row]; + if( col.label.empty() ) { stream << label << ": "; if( value != "0" ) stream << value; @@ -10973,26 +11080,13 @@ namespace Catch { } else if( value != "0" ) { stream << Colour( Colour::LightGrey ) << " | "; - stream << Colour( it->colour ) - << value << ' ' << it->label; + stream << Colour( col.colour ) + << value << ' ' << col.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() ); @@ -11020,374 +11114,594 @@ namespace Catch { } private: - bool m_headerPrinted; + bool m_headerPrinted = false; }; - INTERNAL_CATCH_REGISTER_REPORTER( "console", ConsoleReporter ) + CATCH_REGISTER_REPORTER( "console", ConsoleReporter ) + + ConsoleReporter::~ConsoleReporter() {} } // end namespace Catch -// #included from: ../reporters/catch_reporter_compact.hpp -#define TWOBLUECUBES_CATCH_REPORTER_COMPACT_HPP_INCLUDED +#if defined(_MSC_VER) +#pragma warning(pop) +#endif +// end catch_reporter_console.cpp +// start catch_reporter_junit.cpp + +#include + +#include +#include namespace Catch { - struct CompactReporter : StreamingReporterBase { + namespace { + std::string getCurrentTimestamp() { + // Beware, this is not reentrant because of backward compatibility issues + // Also, UTC only, again because of backward compatibility (%z is C++11) + time_t rawtime; + std::time(&rawtime); + auto const timeStampSize = sizeof("2017-01-16T17:06:45Z"); - CompactReporter( ReporterConfig const& _config ) - : StreamingReporterBase( _config ) - {} +#ifdef _MSC_VER + std::tm timeInfo = {}; + gmtime_s(&timeInfo, &rawtime); +#else + std::tm* timeInfo; + timeInfo = std::gmtime(&rawtime); +#endif - virtual ~CompactReporter(); + char timeStamp[timeStampSize]; + const char * const fmt = "%Y-%m-%dT%H:%M:%SZ"; + +#ifdef _MSC_VER + std::strftime(timeStamp, timeStampSize, fmt, &timeInfo); +#else + std::strftime(timeStamp, timeStampSize, fmt, timeInfo); +#endif + return std::string(timeStamp); + } + + std::string fileNameTag(const std::vector &tags) { + auto it = std::find_if(begin(tags), + end(tags), + [] (std::string const& tag) {return tag.front() == '#'; }); + if (it != tags.end()) + return it->substr(1); + return std::string(); + } + } + + class JunitReporter : public CumulativeReporterBase { + public: + JunitReporter( ReporterConfig const& _config ) + : CumulativeReporterBase( _config ), + xml( _config.stream() ) + { + m_reporterPrefs.shouldRedirectStdOut = true; + } + + ~JunitReporter() override; static std::string getDescription() { - return "Reports test results on a single line, suitable for IDEs"; + return "Reports test results in an XML format that looks like Ant's junitreport target"; } - virtual ReporterPreferences getPreferences() const { - ReporterPreferences prefs; - prefs.shouldRedirectStdOut = false; - return prefs; + void noMatchingTestCases( std::string const& /*spec*/ ) override {} + + void testRunStarting( TestRunInfo const& runInfo ) override { + CumulativeReporterBase::testRunStarting( runInfo ); + xml.startElement( "testsuites" ); } - virtual void noMatchingTestCases( std::string const& spec ) { - stream << "No test cases matched '" << spec << '\'' << std::endl; + void testGroupStarting( GroupInfo const& groupInfo ) override { + suiteTimer.start(); + stdOutForSuite.str(""); + stdErrForSuite.str(""); + unexpectedExceptions = 0; + CumulativeReporterBase::testGroupStarting( groupInfo ); } - virtual void assertionStarting( AssertionInfo const& ) {} + void testCaseStarting( TestCaseInfo const& testCaseInfo ) override { + m_okToFail = testCaseInfo.okToFail(); + } + bool assertionEnded( AssertionStats const& assertionStats ) override { + if( assertionStats.assertionResult.getResultType() == ResultWas::ThrewException && !m_okToFail ) + unexpectedExceptions++; + return CumulativeReporterBase::assertionEnded( assertionStats ); + } - virtual bool assertionEnded( AssertionStats const& _assertionStats ) { - AssertionResult const& result = _assertionStats.assertionResult; + void testCaseEnded( TestCaseStats const& testCaseStats ) override { + stdOutForSuite << testCaseStats.stdOut; + stdErrForSuite << testCaseStats.stdErr; + CumulativeReporterBase::testCaseEnded( testCaseStats ); + } - bool printInfoMessages = true; + void testGroupEnded( TestGroupStats const& testGroupStats ) override { + double suiteTime = suiteTimer.getElapsedSeconds(); + CumulativeReporterBase::testGroupEnded( testGroupStats ); + writeGroup( *m_testGroups.back(), suiteTime ); + } - // 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; + void testRunEndedCumulative() override { + xml.endElement(); + } + + void writeGroup( TestGroupNode const& groupNode, double suiteTime ) { + XmlWriter::ScopedElement e = xml.scopedElement( "testsuite" ); + TestGroupStats const& stats = groupNode.value; + xml.writeAttribute( "name", stats.groupInfo.name ); + xml.writeAttribute( "errors", unexpectedExceptions ); + xml.writeAttribute( "failures", stats.totals.assertions.failed-unexpectedExceptions ); + xml.writeAttribute( "tests", stats.totals.assertions.total() ); + xml.writeAttribute( "hostname", "tbd" ); // !TBD + if( m_config->showDurations() == ShowDurations::Never ) + xml.writeAttribute( "time", "" ); + else + xml.writeAttribute( "time", suiteTime ); + xml.writeAttribute( "timestamp", getCurrentTimestamp() ); + + // Write test cases + for( auto const& child : groupNode.children ) + writeTestCase( *child ); + + 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() ) { + className = fileNameTag(stats.testInfo.tags); + if ( className.empty() ) + className = "global"; } - AssertionPrinter printer( stream, _assertionStats, printInfoMessages ); - printer.print(); + if ( !m_config->name().empty() ) + className = m_config->name() + "." + className; - stream << std::endl; - return true; + writeSection( className, "", rootSection ); } - virtual void sectionEnded(SectionStats const& _sectionStats) CATCH_OVERRIDE { - if (m_config->showDurations() == ShowDurations::Always) { - stream << getFormattedDuration(_sectionStats.durationInSeconds) << " s: " << _sectionStats.sectionInfo.name << std::endl; + void writeSection( std::string const& className, + std::string const& rootName, + SectionNode const& sectionNode ) { + std::string name = trim( sectionNode.stats.sectionInfo.name ); + if( !rootName.empty() ) + name = rootName + '/' + name; + + if( !sectionNode.assertions.empty() || + !sectionNode.stdOut.empty() || + !sectionNode.stdErr.empty() ) { + XmlWriter::ScopedElement e = xml.scopedElement( "testcase" ); + if( className.empty() ) { + xml.writeAttribute( "classname", name ); + xml.writeAttribute( "name", "root" ); + } + else { + xml.writeAttribute( "classname", className ); + xml.writeAttribute( "name", name ); + } + xml.writeAttribute( "time", ::Catch::Detail::stringify( 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( auto const& childNode : sectionNode.childSections ) + if( className.empty() ) + writeSection( name, "", *childNode ); + else + writeSection( className, name, *childNode ); } - virtual void testRunEnded( TestRunStats const& _testRunStats ) { - printTotals( _testRunStats.totals ); - stream << '\n' << std::endl; - StreamingReporterBase::testRunEnded( _testRunStats ); + void writeAssertions( SectionNode const& sectionNode ) { + for( auto const& assertion : sectionNode.assertions ) + writeAssertion( assertion ); } - - private: - class AssertionPrinter { - void operator= ( AssertionPrinter const& ); - public: - AssertionPrinter( std::ostream& _stream, AssertionStats const& _stats, bool _printInfoMessages ) - : stream( _stream ) - , stats( _stats ) - , result( _stats.assertionResult ) - , messages( _stats.infoMessages ) - , itMessage( _stats.infoMessages.begin() ) - , printInfoMessages( _printInfoMessages ) - {} - - void print() { - printSourceInfo(); - - itMessage = messages.begin(); - + void writeAssertion( AssertionStats const& stats ) { + AssertionResult const& result = stats.assertionResult; + if( !result.isOk() ) { + std::string elementName; switch( result.getResultType() ) { - case ResultWas::Ok: - printResultType( Colour::ResultSuccess, passedString() ); - printOriginalExpression(); - printReconstructedExpression(); - if ( ! result.hasExpression() ) - printRemainingMessages( Colour::None ); - else - printRemainingMessages(); - break; - case ResultWas::ExpressionFailed: - if( result.isOk() ) - printResultType( Colour::ResultSuccess, failedString() + std::string( " - but was ok" ) ); - else - printResultType( Colour::Error, failedString() ); - printOriginalExpression(); - printReconstructedExpression(); - printRemainingMessages(); - break; case ResultWas::ThrewException: - printResultType( Colour::Error, failedString() ); - printIssue( "unexpected exception with message:" ); - printMessage(); - printExpressionWas(); - printRemainingMessages(); - break; case ResultWas::FatalErrorCondition: - printResultType( Colour::Error, failedString() ); - printIssue( "fatal error condition with message:" ); - printMessage(); - printExpressionWas(); - printRemainingMessages(); - break; - case ResultWas::DidntThrowException: - printResultType( Colour::Error, failedString() ); - printIssue( "expected exception, got none" ); - printExpressionWas(); - printRemainingMessages(); - break; - case ResultWas::Info: - printResultType( Colour::None, "info" ); - printMessage(); - printRemainingMessages(); - break; - case ResultWas::Warning: - printResultType( Colour::None, "warning" ); - printMessage(); - printRemainingMessages(); + elementName = "error"; break; case ResultWas::ExplicitFailure: - printResultType( Colour::Error, failedString() ); - printIssue( "explicitly" ); - printRemainingMessages( Colour::None ); + elementName = "failure"; break; - // These cases are here to prevent compiler warnings + 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: - printResultType( Colour::Error, "** internal error **" ); + elementName = "internalError"; break; } - } - private: - // Colour::LightGrey + XmlWriter::ScopedElement e = xml.scopedElement( elementName ); - static Colour::Code dimColour() { return Colour::FileName; } + xml.writeAttribute( "message", result.getExpandedExpression() ); + xml.writeAttribute( "type", result.getTestMacroName() ); -#ifdef CATCH_PLATFORM_MAC - static const char* failedString() { return "FAILED"; } - static const char* passedString() { return "PASSED"; } -#else - static const char* failedString() { return "failed"; } - static const char* passedString() { return "passed"; } -#endif + std::ostringstream oss; + if( !result.getMessage().empty() ) + oss << result.getMessage() << '\n'; + for( auto const& msg : stats.infoMessages ) + if( msg.type == ResultWas::Info ) + oss << msg.message << '\n'; - void printSourceInfo() const { - Colour colourGuard( Colour::FileName ); - stream << result.getSourceInfo() << ':'; - } - - void printResultType( Colour::Code colour, std::string const& passOrFail ) const { - if( !passOrFail.empty() ) { - { - Colour colourGuard( colour ); - stream << ' ' << passOrFail; - } - stream << ':'; - } - } - - void printIssue( std::string const& 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"; - } - } - } - } - - 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 ? std::string() : 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 ) : std::string(); - 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" ) << '.'; + oss << "at " << result.getSourceInfo(); + xml.writeText( oss.str(), false ); } } + + XmlWriter xml; + Timer suiteTimer; + std::ostringstream stdOutForSuite; + std::ostringstream stdErrForSuite; + unsigned int unexpectedExceptions = 0; + bool m_okToFail = false; }; - INTERNAL_CATCH_REGISTER_REPORTER( "compact", CompactReporter ) + JunitReporter::~JunitReporter() {} + CATCH_REGISTER_REPORTER( "junit", JunitReporter ) + +} // end namespace Catch +// end catch_reporter_junit.cpp +// start catch_reporter_multi.cpp + +namespace Catch { + + void MultipleReporters::add( IStreamingReporterPtr&& reporter ) { + m_reporters.push_back( std::move( reporter ) ); + } + + ReporterPreferences MultipleReporters::getPreferences() const { + return m_reporters[0]->getPreferences(); + } + + std::set MultipleReporters::getSupportedVerbosities() { + return std::set{ }; + } + + void MultipleReporters::noMatchingTestCases( std::string const& spec ) { + for( auto const& reporter : m_reporters ) + reporter->noMatchingTestCases( spec ); + } + + void MultipleReporters::benchmarkStarting( BenchmarkInfo const& benchmarkInfo ) { + for( auto const& reporter : m_reporters ) + reporter->benchmarkStarting( benchmarkInfo ); + } + void MultipleReporters::benchmarkEnded( BenchmarkStats const& benchmarkStats ) { + for( auto const& reporter : m_reporters ) + reporter->benchmarkEnded( benchmarkStats ); + } + + void MultipleReporters::testRunStarting( TestRunInfo const& testRunInfo ) { + for( auto const& reporter : m_reporters ) + reporter->testRunStarting( testRunInfo ); + } + + void MultipleReporters::testGroupStarting( GroupInfo const& groupInfo ) { + for( auto const& reporter : m_reporters ) + reporter->testGroupStarting( groupInfo ); + } + + void MultipleReporters::testCaseStarting( TestCaseInfo const& testInfo ) { + for( auto const& reporter : m_reporters ) + reporter->testCaseStarting( testInfo ); + } + + void MultipleReporters::sectionStarting( SectionInfo const& sectionInfo ) { + for( auto const& reporter : m_reporters ) + reporter->sectionStarting( sectionInfo ); + } + + void MultipleReporters::assertionStarting( AssertionInfo const& assertionInfo ) { + for( auto const& reporter : m_reporters ) + reporter->assertionStarting( assertionInfo ); + } + + // The return value indicates if the messages buffer should be cleared: + bool MultipleReporters::assertionEnded( AssertionStats const& assertionStats ) { + bool clearBuffer = false; + for( auto const& reporter : m_reporters ) + clearBuffer |= reporter->assertionEnded( assertionStats ); + return clearBuffer; + } + + void MultipleReporters::sectionEnded( SectionStats const& sectionStats ) { + for( auto const& reporter : m_reporters ) + reporter->sectionEnded( sectionStats ); + } + + void MultipleReporters::testCaseEnded( TestCaseStats const& testCaseStats ) { + for( auto const& reporter : m_reporters ) + reporter->testCaseEnded( testCaseStats ); + } + + void MultipleReporters::testGroupEnded( TestGroupStats const& testGroupStats ) { + for( auto const& reporter : m_reporters ) + reporter->testGroupEnded( testGroupStats ); + } + + void MultipleReporters::testRunEnded( TestRunStats const& testRunStats ) { + for( auto const& reporter : m_reporters ) + reporter->testRunEnded( testRunStats ); + } + + void MultipleReporters::skipTest( TestCaseInfo const& testInfo ) { + for( auto const& reporter : m_reporters ) + reporter->skipTest( testInfo ); + } + + bool MultipleReporters::isMulti() const { + return true; + } + +} // end namespace Catch +// end catch_reporter_multi.cpp +// start catch_reporter_xml.cpp + +#if defined(_MSC_VER) +#pragma warning(push) +#pragma warning(disable:4061) // Not all labels are EXPLICITLY handled in switch + // Note that 4062 (not all labels are handled + // and default is missing) is enabled +#endif + +namespace Catch { + class XmlReporter : public StreamingReporterBase { + public: + XmlReporter( ReporterConfig const& _config ) + : StreamingReporterBase( _config ), + m_xml(_config.stream()) + { + m_reporterPrefs.shouldRedirectStdOut = true; + } + + ~XmlReporter() override; + + static std::string getDescription() { + return "Reports test results as an XML document"; + } + + virtual std::string getStylesheetRef() const { + return std::string(); + } + + void writeSourceInfo( SourceLineInfo const& sourceInfo ) { + m_xml + .writeAttribute( "filename", sourceInfo.file ) + .writeAttribute( "line", sourceInfo.line ); + } + + public: // StreamingReporterBase + + void noMatchingTestCases( std::string const& s ) override { + StreamingReporterBase::noMatchingTestCases( s ); + } + + void testRunStarting( TestRunInfo const& testInfo ) override { + StreamingReporterBase::testRunStarting( testInfo ); + std::string stylesheetRef = getStylesheetRef(); + if( !stylesheetRef.empty() ) + m_xml.writeStylesheetRef( stylesheetRef ); + m_xml.startElement( "Catch" ); + if( !m_config->name().empty() ) + m_xml.writeAttribute( "name", m_config->name() ); + } + + void testGroupStarting( GroupInfo const& groupInfo ) override { + StreamingReporterBase::testGroupStarting( groupInfo ); + m_xml.startElement( "Group" ) + .writeAttribute( "name", groupInfo.name ); + } + + void testCaseStarting( TestCaseInfo const& testInfo ) override { + StreamingReporterBase::testCaseStarting(testInfo); + m_xml.startElement( "TestCase" ) + .writeAttribute( "name", trim( testInfo.name ) ) + .writeAttribute( "description", testInfo.description ) + .writeAttribute( "tags", testInfo.tagsAsString() ); + + writeSourceInfo( testInfo.lineInfo ); + + if ( m_config->showDurations() == ShowDurations::Always ) + m_testCaseTimer.start(); + m_xml.ensureTagClosed(); + } + + void sectionStarting( SectionInfo const& sectionInfo ) override { + StreamingReporterBase::sectionStarting( sectionInfo ); + if( m_sectionDepth++ > 0 ) { + m_xml.startElement( "Section" ) + .writeAttribute( "name", trim( sectionInfo.name ) ) + .writeAttribute( "description", sectionInfo.description ); + writeSourceInfo( sectionInfo.lineInfo ); + m_xml.ensureTagClosed(); + } + } + + void assertionStarting( AssertionInfo const& ) override { } + + bool assertionEnded( AssertionStats const& assertionStats ) override { + + AssertionResult const& result = assertionStats.assertionResult; + + bool includeResults = m_config->includeSuccessfulResults() || !result.isOk(); + + if( includeResults ) { + // Print any info messages in tags. + for( auto const& msg : assertionStats.infoMessages ) { + if( msg.type == ResultWas::Info ) { + m_xml.scopedElement( "Info" ) + .writeText( msg.message ); + } else if ( msg.type == ResultWas::Warning ) { + m_xml.scopedElement( "Warning" ) + .writeText( msg.message ); + } + } + } + + // Drop out if result was successful but we're not printing them. + if( !includeResults && result.getResultType() != ResultWas::Warning ) + return true; + + // Print the expression if there is one. + if( result.hasExpression() ) { + m_xml.startElement( "Expression" ) + .writeAttribute( "success", result.succeeded() ) + .writeAttribute( "type", result.getTestMacroName() ); + + writeSourceInfo( result.getSourceInfo() ); + + m_xml.scopedElement( "Original" ) + .writeText( result.getExpression() ); + m_xml.scopedElement( "Expanded" ) + .writeText( result.getExpandedExpression() ); + } + + // And... Print a result applicable to each result type. + switch( result.getResultType() ) { + case ResultWas::ThrewException: + m_xml.startElement( "Exception" ); + writeSourceInfo( result.getSourceInfo() ); + m_xml.writeText( result.getMessage() ); + m_xml.endElement(); + break; + case ResultWas::FatalErrorCondition: + m_xml.startElement( "FatalErrorCondition" ); + writeSourceInfo( result.getSourceInfo() ); + m_xml.writeText( result.getMessage() ); + m_xml.endElement(); + break; + case ResultWas::Info: + m_xml.scopedElement( "Info" ) + .writeText( result.getMessage() ); + break; + case ResultWas::Warning: + // Warning will already have been written + break; + case ResultWas::ExplicitFailure: + m_xml.startElement( "Failure" ); + writeSourceInfo( result.getSourceInfo() ); + m_xml.writeText( result.getMessage() ); + m_xml.endElement(); + break; + default: + break; + } + + if( result.hasExpression() ) + m_xml.endElement(); + + return true; + } + + void sectionEnded( SectionStats const& sectionStats ) override { + StreamingReporterBase::sectionEnded( sectionStats ); + if( --m_sectionDepth > 0 ) { + XmlWriter::ScopedElement e = m_xml.scopedElement( "OverallResults" ); + e.writeAttribute( "successes", sectionStats.assertions.passed ); + e.writeAttribute( "failures", sectionStats.assertions.failed ); + e.writeAttribute( "expectedFailures", sectionStats.assertions.failedButOk ); + + if ( m_config->showDurations() == ShowDurations::Always ) + e.writeAttribute( "durationInSeconds", sectionStats.durationInSeconds ); + + m_xml.endElement(); + } + } + + void testCaseEnded( TestCaseStats const& testCaseStats ) override { + StreamingReporterBase::testCaseEnded( testCaseStats ); + XmlWriter::ScopedElement e = m_xml.scopedElement( "OverallResult" ); + e.writeAttribute( "success", testCaseStats.totals.assertions.allOk() ); + + if ( m_config->showDurations() == ShowDurations::Always ) + e.writeAttribute( "durationInSeconds", m_testCaseTimer.getElapsedSeconds() ); + + if( !testCaseStats.stdOut.empty() ) + m_xml.scopedElement( "StdOut" ).writeText( trim( testCaseStats.stdOut ), false ); + if( !testCaseStats.stdErr.empty() ) + m_xml.scopedElement( "StdErr" ).writeText( trim( testCaseStats.stdErr ), false ); + + m_xml.endElement(); + } + + void testGroupEnded( TestGroupStats const& testGroupStats ) override { + StreamingReporterBase::testGroupEnded( testGroupStats ); + // TODO: Check testGroupStats.aborting and act accordingly. + m_xml.scopedElement( "OverallResults" ) + .writeAttribute( "successes", testGroupStats.totals.assertions.passed ) + .writeAttribute( "failures", testGroupStats.totals.assertions.failed ) + .writeAttribute( "expectedFailures", testGroupStats.totals.assertions.failedButOk ); + m_xml.endElement(); + } + + void testRunEnded( TestRunStats const& testRunStats ) override { + StreamingReporterBase::testRunEnded( testRunStats ); + m_xml.scopedElement( "OverallResults" ) + .writeAttribute( "successes", testRunStats.totals.assertions.passed ) + .writeAttribute( "failures", testRunStats.totals.assertions.failed ) + .writeAttribute( "expectedFailures", testRunStats.totals.assertions.failedButOk ); + m_xml.endElement(); + } + + private: + Timer m_testCaseTimer; + XmlWriter m_xml; + int m_sectionDepth = 0; + }; + + XmlReporter::~XmlReporter() {} + CATCH_REGISTER_REPORTER( "xml", XmlReporter ) } // end namespace Catch +#if defined(_MSC_VER) +#pragma warning(pop) +#endif +// end catch_reporter_xml.cpp + namespace Catch { - // These are all here to avoid warnings about not having any out of line - // virtual methods - NonCopyable::~NonCopyable() {} - IShared::~IShared() {} - IStream::~IStream() CATCH_NOEXCEPT {} - FileStream::~FileStream() CATCH_NOEXCEPT {} - CoutStream::~CoutStream() CATCH_NOEXCEPT {} - DebugOutStream::~DebugOutStream() CATCH_NOEXCEPT {} - StreamBufBase::~StreamBufBase() CATCH_NOEXCEPT {} - IContext::~IContext() {} - IResultCapture::~IResultCapture() {} - ITestCase::~ITestCase() {} - ITestCaseRegistry::~ITestCaseRegistry() {} - IRegistryHub::~IRegistryHub() {} - IMutableRegistryHub::~IMutableRegistryHub() {} - IExceptionTranslator::~IExceptionTranslator() {} - IExceptionTranslatorRegistry::~IExceptionTranslatorRegistry() {} - IReporter::~IReporter() {} - IReporterFactory::~IReporterFactory() {} - IReporterRegistry::~IReporterRegistry() {} - IStreamingReporter::~IStreamingReporter() {} - AssertionStats::~AssertionStats() {} - SectionStats::~SectionStats() {} - TestCaseStats::~TestCaseStats() {} - TestGroupStats::~TestGroupStats() {} - TestRunStats::~TestRunStats() {} - CumulativeReporterBase::SectionNode::~SectionNode() {} - CumulativeReporterBase::~CumulativeReporterBase() {} - - StreamingReporterBase::~StreamingReporterBase() {} - ConsoleReporter::~ConsoleReporter() {} - CompactReporter::~CompactReporter() {} - IRunner::~IRunner() {} - IMutableContext::~IMutableContext() {} - IConfig::~IConfig() {} - XmlReporter::~XmlReporter() {} - JunitReporter::~JunitReporter() {} - TestRegistry::~TestRegistry() {} - FreeFunctionTestCase::~FreeFunctionTestCase() {} - IGeneratorInfo::~IGeneratorInfo() {} - IGeneratorsForTest::~IGeneratorsForTest() {} - WildcardPattern::~WildcardPattern() {} - TestSpec::Pattern::~Pattern() {} - TestSpec::NamePattern::~NamePattern() {} - TestSpec::TagPattern::~TagPattern() {} - TestSpec::ExcludedPattern::~ExcludedPattern() {} - Matchers::Impl::MatcherUntypedBase::~MatcherUntypedBase() {} - - void Config::dummy() {} - - namespace TestCaseTracking { - ITracker::~ITracker() {} - TrackerBase::~TrackerBase() {} - SectionTracker::~SectionTracker() {} - IndexTracker::~IndexTracker() {} - } + LeakDetector leakDetector; } #ifdef __clang__ #pragma clang diagnostic pop #endif +// end catch_impl.hpp #endif #ifdef CATCH_CONFIG_MAIN -// #included from: internal/catch_default_main.hpp -#define TWOBLUECUBES_CATCH_DEFAULT_MAIN_HPP_INCLUDED +// start catch_default_main.hpp #ifndef __OBJC__ @@ -11399,8 +11713,7 @@ extern "C" int wmain (int argc, wchar_t * argv[], wchar_t * []) { int main (int argc, char * argv[]) { #endif - int result = Catch::Session().run( argc, argv ); - return ( result < 0xff ? result : 0xff ); + return Catch::Session().run( argc, argv ); } #else // __OBJC__ @@ -11412,149 +11725,122 @@ int main (int argc, char * const argv[]) { #endif Catch::registerTestMethods(); - int result = Catch::Session().run( argc, (char* const*)argv ); + int result = Catch::Session().run( argc, (char**)argv ); #if !CATCH_ARC_ENABLED [pool drain]; #endif - return ( result < 0xff ? result : 0xff ); + return result; } #endif // __OBJC__ +// end catch_default_main.hpp #endif #ifdef CLARA_CONFIG_MAIN_NOT_DEFINED # undef CLARA_CONFIG_MAIN #endif +#if !defined(CATCH_CONFIG_DISABLE) ////// - // If this config identifier is defined then all CATCH macros are prefixed with CATCH_ #ifdef CATCH_CONFIG_PREFIX_ALL -#if defined(CATCH_CONFIG_FAST_COMPILE) -#define CATCH_REQUIRE( expr ) INTERNAL_CATCH_TEST_NO_TRY( "CATCH_REQUIRE", Catch::ResultDisposition::Normal, expr ) -#define CATCH_REQUIRE_FALSE( expr ) INTERNAL_CATCH_TEST_NO_TRY( "CATCH_REQUIRE_FALSE", Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, expr ) -#else -#define CATCH_REQUIRE( expr ) INTERNAL_CATCH_TEST( "CATCH_REQUIRE", Catch::ResultDisposition::Normal, expr ) -#define CATCH_REQUIRE_FALSE( expr ) INTERNAL_CATCH_TEST( "CATCH_REQUIRE_FALSE", Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, expr ) -#endif +#define CATCH_REQUIRE( ... ) INTERNAL_CATCH_TEST( "CATCH_REQUIRE", Catch::ResultDisposition::Normal, __VA_ARGS__ ) +#define CATCH_REQUIRE_FALSE( ... ) INTERNAL_CATCH_TEST( "CATCH_REQUIRE_FALSE", Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, __VA_ARGS__ ) -#define CATCH_REQUIRE_THROWS( expr ) INTERNAL_CATCH_THROWS( "CATCH_REQUIRE_THROWS", Catch::ResultDisposition::Normal, "", expr ) +#define CATCH_REQUIRE_THROWS( ... ) INTERNAL_CATCH_THROWS( "CATCH_REQUIRE_THROWS", Catch::ResultDisposition::Normal, "", __VA_ARGS__ ) #define CATCH_REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "CATCH_REQUIRE_THROWS_AS", exceptionType, Catch::ResultDisposition::Normal, expr ) -#define CATCH_REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( "CATCH_REQUIRE_THROWS_WITH", Catch::ResultDisposition::Normal, matcher, expr ) -#define CATCH_REQUIRE_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( "CATCH_REQUIRE_NOTHROW", Catch::ResultDisposition::Normal, expr ) +#define CATCH_REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "CATCH_REQUIRE_THROWS_WITH", Catch::ResultDisposition::Normal, matcher, expr ) +#if !defined(CATCH_CONFIG_DISABLE_MATCHERS) +#define CATCH_REQUIRE_THROWS_MATCHES( expr, exceptionType, matcher ) INTERNAL_CATCH_THROWS_MATCHES( "CATCH_REQUIRE_THROWS_MATCHES", exceptionType, Catch::ResultDisposition::Normal, matcher, expr ) +#endif// CATCH_CONFIG_DISABLE_MATCHERS +#define CATCH_REQUIRE_NOTHROW( ... ) INTERNAL_CATCH_NO_THROW( "CATCH_REQUIRE_NOTHROW", Catch::ResultDisposition::Normal, __VA_ARGS__ ) -#define CATCH_CHECK( expr ) INTERNAL_CATCH_TEST( "CATCH_CHECK", Catch::ResultDisposition::ContinueOnFailure, expr ) -#define CATCH_CHECK_FALSE( expr ) INTERNAL_CATCH_TEST( "CATCH_CHECK_FALSE", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::FalseTest, expr ) -#define CATCH_CHECKED_IF( expr ) INTERNAL_CATCH_IF( "CATCH_CHECKED_IF", Catch::ResultDisposition::ContinueOnFailure, expr ) -#define CATCH_CHECKED_ELSE( expr ) INTERNAL_CATCH_ELSE( "CATCH_CHECKED_ELSE", Catch::ResultDisposition::ContinueOnFailure, expr ) -#define CATCH_CHECK_NOFAIL( expr ) INTERNAL_CATCH_TEST( "CATCH_CHECK_NOFAIL", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, expr ) +#define CATCH_CHECK( ... ) INTERNAL_CATCH_TEST( "CATCH_CHECK", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) +#define CATCH_CHECK_FALSE( ... ) INTERNAL_CATCH_TEST( "CATCH_CHECK_FALSE", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::FalseTest, __VA_ARGS__ ) +#define CATCH_CHECKED_IF( ... ) INTERNAL_CATCH_IF( "CATCH_CHECKED_IF", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) +#define CATCH_CHECKED_ELSE( ... ) INTERNAL_CATCH_ELSE( "CATCH_CHECKED_ELSE", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) +#define CATCH_CHECK_NOFAIL( ... ) INTERNAL_CATCH_TEST( "CATCH_CHECK_NOFAIL", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, __VA_ARGS__ ) -#define CATCH_CHECK_THROWS( expr ) INTERNAL_CATCH_THROWS( "CATCH_CHECK_THROWS", Catch::ResultDisposition::ContinueOnFailure, "", expr ) +#define CATCH_CHECK_THROWS( ... ) INTERNAL_CATCH_THROWS( "CATCH_CHECK_THROWS", Catch::ResultDisposition::ContinueOnFailure, "", __VA_ARGS__ ) #define CATCH_CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "CATCH_CHECK_THROWS_AS", exceptionType, Catch::ResultDisposition::ContinueOnFailure, expr ) -#define CATCH_CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( "CATCH_CHECK_THROWS_WITH", Catch::ResultDisposition::ContinueOnFailure, matcher, expr ) -#define CATCH_CHECK_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( "CATCH_CHECK_NOTHROW", Catch::ResultDisposition::ContinueOnFailure, expr ) +#define CATCH_CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "CATCH_CHECK_THROWS_WITH", Catch::ResultDisposition::ContinueOnFailure, matcher, expr ) +#if !defined(CATCH_CONFIG_DISABLE_MATCHERS) +#define CATCH_CHECK_THROWS_MATCHES( expr, exceptionType, matcher ) INTERNAL_CATCH_THROWS_MATCHES( "CATCH_CHECK_THROWS_MATCHES", exceptionType, Catch::ResultDisposition::ContinueOnFailure, matcher, expr ) +#endif // CATCH_CONFIG_DISABLE_MATCHERS +#define CATCH_CHECK_NOTHROW( ... ) INTERNAL_CATCH_NO_THROW( "CATCH_CHECK_NOTHROW", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) +#if !defined(CATCH_CONFIG_DISABLE_MATCHERS) #define CATCH_CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "CATCH_CHECK_THAT", matcher, Catch::ResultDisposition::ContinueOnFailure, arg ) -#if defined(CATCH_CONFIG_FAST_COMPILE) -#define CATCH_REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT_NO_TRY( "CATCH_REQUIRE_THAT", matcher, Catch::ResultDisposition::Normal, arg ) -#else #define CATCH_REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "CATCH_REQUIRE_THAT", matcher, Catch::ResultDisposition::Normal, arg ) -#endif +#endif // CATCH_CONFIG_DISABLE_MATCHERS #define CATCH_INFO( msg ) INTERNAL_CATCH_INFO( "CATCH_INFO", msg ) #define CATCH_WARN( msg ) INTERNAL_CATCH_MSG( "CATCH_WARN", Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, msg ) -#define CATCH_SCOPED_INFO( msg ) INTERNAL_CATCH_INFO( "CATCH_INFO", msg ) -#define CATCH_CAPTURE( msg ) INTERNAL_CATCH_INFO( "CATCH_CAPTURE", #msg " := " << Catch::toString(msg) ) -#define CATCH_SCOPED_CAPTURE( msg ) INTERNAL_CATCH_INFO( "CATCH_CAPTURE", #msg " := " << Catch::toString(msg) ) +#define CATCH_CAPTURE( msg ) INTERNAL_CATCH_INFO( "CATCH_CAPTURE", #msg " := " << ::Catch::Detail::stringify(msg) ) -#ifdef CATCH_CONFIG_VARIADIC_MACROS - #define CATCH_TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ ) - #define CATCH_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ ) - #define CATCH_METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ ) - #define CATCH_REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ ) - #define CATCH_SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ ) - #define CATCH_FAIL( ... ) INTERNAL_CATCH_MSG( "CATCH_FAIL", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, __VA_ARGS__ ) - #define CATCH_FAIL_CHECK( ... ) INTERNAL_CATCH_MSG( "CATCH_FAIL_CHECK", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) - #define CATCH_SUCCEED( ... ) INTERNAL_CATCH_MSG( "CATCH_SUCCEED", Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) -#else - #define CATCH_TEST_CASE( name, description ) INTERNAL_CATCH_TESTCASE( name, description ) - #define CATCH_TEST_CASE_METHOD( className, name, description ) INTERNAL_CATCH_TEST_CASE_METHOD( className, name, description ) - #define CATCH_METHOD_AS_TEST_CASE( method, name, description ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, name, description ) - #define CATCH_REGISTER_TEST_CASE( function, name, description ) INTERNAL_CATCH_REGISTER_TESTCASE( function, name, description ) - #define CATCH_SECTION( name, description ) INTERNAL_CATCH_SECTION( name, description ) - #define CATCH_FAIL( msg ) INTERNAL_CATCH_MSG( "CATCH_FAIL", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, msg ) - #define CATCH_FAIL_CHECK( msg ) INTERNAL_CATCH_MSG( "CATCH_FAIL_CHECK", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::ContinueOnFailure, msg ) - #define CATCH_SUCCEED( msg ) INTERNAL_CATCH_MSG( "CATCH_SUCCEED", Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, msg ) -#endif -#define CATCH_ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE( "", "" ) +#define CATCH_TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ ) +#define CATCH_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ ) +#define CATCH_METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ ) +#define CATCH_REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ ) +#define CATCH_SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ ) +#define CATCH_FAIL( ... ) INTERNAL_CATCH_MSG( "CATCH_FAIL", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, __VA_ARGS__ ) +#define CATCH_FAIL_CHECK( ... ) INTERNAL_CATCH_MSG( "CATCH_FAIL_CHECK", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) +#define CATCH_SUCCEED( ... ) INTERNAL_CATCH_MSG( "CATCH_SUCCEED", Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) -#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_ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE() // "BDD-style" convenience wrappers -#ifdef CATCH_CONFIG_VARIADIC_MACROS #define CATCH_SCENARIO( ... ) CATCH_TEST_CASE( "Scenario: " __VA_ARGS__ ) #define CATCH_SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ ) -#else -#define CATCH_SCENARIO( name, tags ) CATCH_TEST_CASE( "Scenario: " name, tags ) -#define CATCH_SCENARIO_METHOD( className, name, tags ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " name, tags ) -#endif -#define CATCH_GIVEN( desc ) CATCH_SECTION( std::string( "Given: ") + desc, "" ) -#define CATCH_WHEN( desc ) CATCH_SECTION( std::string( " When: ") + desc, "" ) -#define CATCH_AND_WHEN( desc ) CATCH_SECTION( std::string( " And: ") + desc, "" ) -#define CATCH_THEN( desc ) CATCH_SECTION( std::string( " Then: ") + desc, "" ) -#define CATCH_AND_THEN( desc ) CATCH_SECTION( std::string( " And: ") + desc, "" ) +#define CATCH_GIVEN( desc ) CATCH_SECTION( std::string( "Given: ") + desc ) +#define CATCH_WHEN( desc ) CATCH_SECTION( std::string( " When: ") + desc ) +#define CATCH_AND_WHEN( desc ) CATCH_SECTION( std::string( " And: ") + desc ) +#define CATCH_THEN( desc ) CATCH_SECTION( std::string( " Then: ") + desc ) +#define CATCH_AND_THEN( desc ) CATCH_SECTION( std::string( " And: ") + desc ) // If CATCH_CONFIG_PREFIX_ALL is not defined then the CATCH_ prefix is not required #else -#if defined(CATCH_CONFIG_FAST_COMPILE) -#define REQUIRE( expr ) INTERNAL_CATCH_TEST_NO_TRY( "REQUIRE", Catch::ResultDisposition::Normal, expr ) -#define REQUIRE_FALSE( expr ) INTERNAL_CATCH_TEST_NO_TRY( "REQUIRE_FALSE", Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, expr ) +#define REQUIRE( ... ) INTERNAL_CATCH_TEST( "REQUIRE", Catch::ResultDisposition::Normal, __VA_ARGS__ ) +#define REQUIRE_FALSE( ... ) INTERNAL_CATCH_TEST( "REQUIRE_FALSE", Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, __VA_ARGS__ ) -#else -#define REQUIRE( expr ) INTERNAL_CATCH_TEST( "REQUIRE", Catch::ResultDisposition::Normal, expr ) -#define REQUIRE_FALSE( expr ) INTERNAL_CATCH_TEST( "REQUIRE_FALSE", Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, expr ) -#endif - -#define REQUIRE_THROWS( expr ) INTERNAL_CATCH_THROWS( "REQUIRE_THROWS", Catch::ResultDisposition::Normal, "", expr ) +#define REQUIRE_THROWS( ... ) INTERNAL_CATCH_THROWS( "REQUIRE_THROWS", Catch::ResultDisposition::Normal, __VA_ARGS__ ) #define REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "REQUIRE_THROWS_AS", exceptionType, Catch::ResultDisposition::Normal, expr ) -#define REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( "REQUIRE_THROWS_WITH", Catch::ResultDisposition::Normal, matcher, expr ) -#define REQUIRE_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( "REQUIRE_NOTHROW", Catch::ResultDisposition::Normal, expr ) +#define REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "REQUIRE_THROWS_WITH", Catch::ResultDisposition::Normal, matcher, expr ) +#if !defined(CATCH_CONFIG_DISABLE_MATCHERS) +#define REQUIRE_THROWS_MATCHES( expr, exceptionType, matcher ) INTERNAL_CATCH_THROWS_MATCHES( "REQUIRE_THROWS_MATCHES", exceptionType, Catch::ResultDisposition::Normal, matcher, expr ) +#endif // CATCH_CONFIG_DISABLE_MATCHERS +#define REQUIRE_NOTHROW( ... ) INTERNAL_CATCH_NO_THROW( "REQUIRE_NOTHROW", Catch::ResultDisposition::Normal, __VA_ARGS__ ) -#define CHECK( expr ) INTERNAL_CATCH_TEST( "CHECK", Catch::ResultDisposition::ContinueOnFailure, expr ) -#define CHECK_FALSE( expr ) INTERNAL_CATCH_TEST( "CHECK_FALSE", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::FalseTest, expr ) -#define CHECKED_IF( expr ) INTERNAL_CATCH_IF( "CHECKED_IF", Catch::ResultDisposition::ContinueOnFailure, expr ) -#define CHECKED_ELSE( expr ) INTERNAL_CATCH_ELSE( "CHECKED_ELSE", Catch::ResultDisposition::ContinueOnFailure, expr ) -#define CHECK_NOFAIL( expr ) INTERNAL_CATCH_TEST( "CHECK_NOFAIL", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, expr ) +#define CHECK( ... ) INTERNAL_CATCH_TEST( "CHECK", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) +#define CHECK_FALSE( ... ) INTERNAL_CATCH_TEST( "CHECK_FALSE", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::FalseTest, __VA_ARGS__ ) +#define CHECKED_IF( ... ) INTERNAL_CATCH_IF( "CHECKED_IF", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) +#define CHECKED_ELSE( ... ) INTERNAL_CATCH_ELSE( "CHECKED_ELSE", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) +#define CHECK_NOFAIL( ... ) INTERNAL_CATCH_TEST( "CHECK_NOFAIL", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, __VA_ARGS__ ) -#define CHECK_THROWS( expr ) INTERNAL_CATCH_THROWS( "CHECK_THROWS", Catch::ResultDisposition::ContinueOnFailure, "", expr ) +#define CHECK_THROWS( ... ) INTERNAL_CATCH_THROWS( "CHECK_THROWS", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) #define CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "CHECK_THROWS_AS", exceptionType, Catch::ResultDisposition::ContinueOnFailure, expr ) -#define CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( "CHECK_THROWS_WITH", Catch::ResultDisposition::ContinueOnFailure, matcher, expr ) -#define CHECK_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( "CHECK_NOTHROW", Catch::ResultDisposition::ContinueOnFailure, expr ) +#define CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "CHECK_THROWS_WITH", Catch::ResultDisposition::ContinueOnFailure, matcher, expr ) +#if !defined(CATCH_CONFIG_DISABLE_MATCHERS) +#define CHECK_THROWS_MATCHES( expr, exceptionType, matcher ) INTERNAL_CATCH_THROWS_MATCHES( "CHECK_THROWS_MATCHES", exceptionType, Catch::ResultDisposition::ContinueOnFailure, matcher, expr ) +#endif // CATCH_CONFIG_DISABLE_MATCHERS +#define CHECK_NOTHROW( ... ) INTERNAL_CATCH_NO_THROW( "CHECK_NOTHROW", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) +#if !defined(CATCH_CONFIG_DISABLE_MATCHERS) #define CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "CHECK_THAT", matcher, Catch::ResultDisposition::ContinueOnFailure, arg ) -#if defined(CATCH_CONFIG_FAST_COMPILE) -#define REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT_NO_TRY( "REQUIRE_THAT", matcher, Catch::ResultDisposition::Normal, arg ) -#else #define REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "REQUIRE_THAT", matcher, Catch::ResultDisposition::Normal, arg ) -#endif +#endif // CATCH_CONFIG_DISABLE_MATCHERS #define INFO( msg ) INTERNAL_CATCH_INFO( "INFO", msg ) #define WARN( msg ) INTERNAL_CATCH_MSG( "WARN", Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, msg ) -#define SCOPED_INFO( msg ) INTERNAL_CATCH_INFO( "INFO", msg ) -#define CAPTURE( msg ) INTERNAL_CATCH_INFO( "CAPTURE", #msg " := " << Catch::toString(msg) ) -#define SCOPED_CAPTURE( msg ) INTERNAL_CATCH_INFO( "CAPTURE", #msg " := " << Catch::toString(msg) ) +#define CAPTURE( msg ) INTERNAL_CATCH_INFO( "CAPTURE", #msg " := " << ::Catch::Detail::stringify(msg) ) -#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__ ) @@ -11563,46 +11849,152 @@ int main (int argc, char * const argv[]) { #define FAIL( ... ) INTERNAL_CATCH_MSG( "FAIL", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, __VA_ARGS__ ) #define FAIL_CHECK( ... ) INTERNAL_CATCH_MSG( "FAIL_CHECK", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) #define SUCCEED( ... ) INTERNAL_CATCH_MSG( "SUCCEED", Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) -#else -#define TEST_CASE( name, description ) INTERNAL_CATCH_TESTCASE( name, description ) - #define TEST_CASE_METHOD( className, name, description ) INTERNAL_CATCH_TEST_CASE_METHOD( className, name, description ) - #define METHOD_AS_TEST_CASE( method, name, description ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, name, description ) - #define REGISTER_TEST_CASE( method, name, description ) INTERNAL_CATCH_REGISTER_TESTCASE( method, name, description ) - #define SECTION( name, description ) INTERNAL_CATCH_SECTION( name, description ) - #define FAIL( msg ) INTERNAL_CATCH_MSG( "FAIL", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, msg ) - #define FAIL_CHECK( msg ) INTERNAL_CATCH_MSG( "FAIL_CHECK", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::ContinueOnFailure, msg ) - #define SUCCEED( msg ) INTERNAL_CATCH_MSG( "SUCCEED", Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, msg ) -#endif -#define ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE( "", "" ) - -#define REGISTER_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType ) -#define REGISTER_LEGACY_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) - -#define GENERATE( expr) INTERNAL_CATCH_GENERATE( expr ) +#define ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE() #endif #define CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) // "BDD-style" convenience wrappers -#ifdef CATCH_CONFIG_VARIADIC_MACROS #define SCENARIO( ... ) TEST_CASE( "Scenario: " __VA_ARGS__ ) #define SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ ) -#else -#define SCENARIO( name, tags ) TEST_CASE( "Scenario: " name, tags ) -#define SCENARIO_METHOD( className, name, tags ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " name, tags ) -#endif -#define GIVEN( desc ) SECTION( std::string(" Given: ") + desc, "" ) -#define WHEN( desc ) SECTION( std::string(" When: ") + desc, "" ) -#define AND_WHEN( desc ) SECTION( std::string("And when: ") + desc, "" ) -#define THEN( desc ) SECTION( std::string(" Then: ") + desc, "" ) -#define AND_THEN( desc ) SECTION( std::string(" And: ") + desc, "" ) + +#define GIVEN( desc ) SECTION( std::string(" Given: ") + desc ) +#define WHEN( desc ) SECTION( std::string(" When: ") + desc ) +#define AND_WHEN( desc ) SECTION( std::string("And when: ") + desc ) +#define THEN( desc ) SECTION( std::string(" Then: ") + desc ) +#define AND_THEN( desc ) SECTION( std::string(" And: ") + desc ) using Catch::Detail::Approx; -// #included from: internal/catch_reenable_warnings.h +#else +////// +// If this config identifier is defined then all CATCH macros are prefixed with CATCH_ +#ifdef CATCH_CONFIG_PREFIX_ALL + +#define CATCH_REQUIRE( ... ) (void)(0) +#define CATCH_REQUIRE_FALSE( ... ) (void)(0) + +#define CATCH_REQUIRE_THROWS( ... ) (void)(0) +#define CATCH_REQUIRE_THROWS_AS( expr, exceptionType ) (void)(0) +#define CATCH_REQUIRE_THROWS_WITH( expr, matcher ) (void)(0) +#if !defined(CATCH_CONFIG_DISABLE_MATCHERS) +#define CATCH_REQUIRE_THROWS_MATCHES( expr, exceptionType, matcher ) (void)(0) +#endif// CATCH_CONFIG_DISABLE_MATCHERS +#define CATCH_REQUIRE_NOTHROW( ... ) (void)(0) + +#define CATCH_CHECK( ... ) (void)(0) +#define CATCH_CHECK_FALSE( ... ) (void)(0) +#define CATCH_CHECKED_IF( ... ) if (__VA_ARGS__) +#define CATCH_CHECKED_ELSE( ... ) if (!(__VA_ARGS__)) +#define CATCH_CHECK_NOFAIL( ... ) (void)(0) + +#define CATCH_CHECK_THROWS( ... ) (void)(0) +#define CATCH_CHECK_THROWS_AS( expr, exceptionType ) (void)(0) +#define CATCH_CHECK_THROWS_WITH( expr, matcher ) (void)(0) +#if !defined(CATCH_CONFIG_DISABLE_MATCHERS) +#define CATCH_CHECK_THROWS_MATCHES( expr, exceptionType, matcher ) (void)(0) +#endif // CATCH_CONFIG_DISABLE_MATCHERS +#define CATCH_CHECK_NOTHROW( ... ) (void)(0) + +#if !defined(CATCH_CONFIG_DISABLE_MATCHERS) +#define CATCH_CHECK_THAT( arg, matcher ) (void)(0) + +#define CATCH_REQUIRE_THAT( arg, matcher ) (void)(0) +#endif // CATCH_CONFIG_DISABLE_MATCHERS + +#define CATCH_INFO( msg ) (void)(0) +#define CATCH_WARN( msg ) (void)(0) +#define CATCH_CAPTURE( msg ) (void)(0) + +#define CATCH_TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )) +#define CATCH_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )) +#define CATCH_METHOD_AS_TEST_CASE( method, ... ) +#define CATCH_REGISTER_TEST_CASE( Function, ... ) (void)(0) +#define CATCH_SECTION( ... ) +#define CATCH_FAIL( ... ) (void)(0) +#define CATCH_FAIL_CHECK( ... ) (void)(0) +#define CATCH_SUCCEED( ... ) (void)(0) + +#define CATCH_ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )) + +// "BDD-style" convenience wrappers +#define CATCH_SCENARIO( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )) +#define CATCH_SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_METHOD_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), className ) +#define CATCH_GIVEN( desc ) +#define CATCH_WHEN( desc ) +#define CATCH_AND_WHEN( desc ) +#define CATCH_THEN( desc ) +#define CATCH_AND_THEN( desc ) + +// If CATCH_CONFIG_PREFIX_ALL is not defined then the CATCH_ prefix is not required +#else + +#define REQUIRE( ... ) (void)(0) +#define REQUIRE_FALSE( ... ) (void)(0) + +#define REQUIRE_THROWS( ... ) (void)(0) +#define REQUIRE_THROWS_AS( expr, exceptionType ) (void)(0) +#define REQUIRE_THROWS_WITH( expr, matcher ) (void)(0) +#if !defined(CATCH_CONFIG_DISABLE_MATCHERS) +#define REQUIRE_THROWS_MATCHES( expr, exceptionType, matcher ) (void)(0) +#endif // CATCH_CONFIG_DISABLE_MATCHERS +#define REQUIRE_NOTHROW( ... ) (void)(0) + +#define CHECK( ... ) (void)(0) +#define CHECK_FALSE( ... ) (void)(0) +#define CHECKED_IF( ... ) if (__VA_ARGS__) +#define CHECKED_ELSE( ... ) if (!(__VA_ARGS__)) +#define CHECK_NOFAIL( ... ) (void)(0) + +#define CHECK_THROWS( ... ) (void)(0) +#define CHECK_THROWS_AS( expr, exceptionType ) (void)(0) +#define CHECK_THROWS_WITH( expr, matcher ) (void)(0) +#if !defined(CATCH_CONFIG_DISABLE_MATCHERS) +#define CHECK_THROWS_MATCHES( expr, exceptionType, matcher ) (void)(0) +#endif // CATCH_CONFIG_DISABLE_MATCHERS +#define CHECK_NOTHROW( ... ) (void)(0) + +#if !defined(CATCH_CONFIG_DISABLE_MATCHERS) +#define CHECK_THAT( arg, matcher ) (void)(0) + +#define REQUIRE_THAT( arg, matcher ) (void)(0) +#endif // CATCH_CONFIG_DISABLE_MATCHERS + +#define INFO( msg ) (void)(0) +#define WARN( msg ) (void)(0) +#define CAPTURE( msg ) (void)(0) + +#define TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )) +#define TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )) +#define METHOD_AS_TEST_CASE( method, ... ) +#define REGISTER_TEST_CASE( Function, ... ) (void)(0) +#define SECTION( ... ) +#define FAIL( ... ) (void)(0) +#define FAIL_CHECK( ... ) (void)(0) +#define SUCCEED( ... ) (void)(0) +#define ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )) + +#endif + +#define CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION_NO_REG( INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator ), signature ) + +// "BDD-style" convenience wrappers +#define SCENARIO( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ) ) +#define SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_METHOD_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), className ) + +#define GIVEN( desc ) +#define WHEN( desc ) +#define AND_WHEN( desc ) +#define THEN( desc ) +#define AND_THEN( desc ) + +using Catch::Detail::Approx; + +#endif + +// start catch_reenable_warnings.h -#define TWOBLUECUBES_CATCH_REENABLE_WARNINGS_H_INCLUDED #ifdef __clang__ # ifdef __ICC // icpc defines the __clang__ macro @@ -11614,5 +12006,7 @@ using Catch::Detail::Approx; # pragma GCC diagnostic pop #endif +// end catch_reenable_warnings.h +// end catch.hpp #endif // TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED From fb8482db767bf46c65c56a984238ed8564e829de Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Wed, 13 Dec 2017 23:44:53 +0100 Subject: [PATCH 4/6] :ok_hand: fixed some issues from the last commit #875 --- README.md | 2 +- src/json.hpp | 15 ++++++--------- 2 files changed, 7 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 54f73a8db..7b50c8412 100644 --- a/README.md +++ b/README.md @@ -813,7 +813,7 @@ The class contains the UTF-8 Decoder from Bjoern Hoehrmann which is licensed und If you have questions regarding the library, I would like to invite you to [open an issue at Github](https://github.com/nlohmann/json/issues/new). Please describe your request, problem, or question as detailed as possible, and also mention the version of the library you are using as well as the version of your compiler and operating system. Opening an issue at Github allows other users and contributors to this library to collaborate. For instance, I have little experience with MSVC, and most issues in this regard have been solved by a growing community. If you have a look at the [closed issues](https://github.com/nlohmann/json/issues?q=is%3Aissue+is%3Aclosed), you will see that we react quite timely in most cases. -Only if your request would contain confidential information, please [send me an email](mailto:mail@nlohmann.me). For encrypted messages, please usse [this key](https://keybase.io/nlohmann/pgp_keys.asc). +Only if your request would contain confidential information, please [send me an email](mailto:mail@nlohmann.me). For encrypted messages, please use [this key](https://keybase.io/nlohmann/pgp_keys.asc). ## Thanks diff --git a/src/json.hpp b/src/json.hpp index 1f06b6dd5..0eed04f77 100644 --- a/src/json.hpp +++ b/src/json.hpp @@ -997,10 +997,9 @@ void to_json(BasicJsonType& j, const std::vector& e) } template::value or - std::is_same::value, - int> = 0> + enable_if_t::value or + std::is_same::value, + int> = 0> void to_json(BasicJsonType& j, const CompatibleArrayType& arr) { external_constructor::construct(j, arr); @@ -1611,11 +1610,9 @@ class input_adapter /// input adapter for contiguous container template::value and - std::is_base_of()))>::iterator_category>::value, - int>::type = 0> + std::enable_if::value and + std::is_base_of()))>::iterator_category>::value, + int>::type = 0> input_adapter(const ContiguousContainer& c) : input_adapter(std::begin(c), std::end(c)) {} From 9a70c60fa5edc8d4a28cc1ee57e6679cade3bef6 Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Thu, 14 Dec 2017 07:49:16 +0100 Subject: [PATCH 5/6] Revert ":arrow_up: updated to Catch 2.0.1" This reverts commit 920f64c01c126e0664b3b1905c3f60872bd518cd. --- test/src/unit-algorithms.cpp | 2 +- test/src/unit-allocator.cpp | 22 +- test/src/unit-cbor.cpp | 47 +- test/src/unit-class_const_iterator.cpp | 8 +- test/src/unit-class_iterator.cpp | 8 +- test/src/unit-class_parser.cpp | 240 +- test/src/unit-constructor1.cpp | 63 +- test/src/unit-conversions.cpp | 95 +- test/src/unit-deserialization.cpp | 62 +- test/src/unit-element_access1.cpp | 166 +- test/src/unit-element_access2.cpp | 168 +- test/src/unit-iterators1.cpp | 80 +- test/src/unit-iterators2.cpp | 232 +- test/src/unit-json_patch.cpp | 78 +- test/src/unit-json_pointer.cpp | 58 +- test/src/unit-modifiers.cpp | 70 +- test/src/unit-msgpack.cpp | 42 +- test/src/unit-readme.cpp | 1 - test/src/unit-reference_access.cpp | 84 +- test/src/unit-regression.cpp | 84 +- test/src/unit-testsuites.cpp | 8 +- test/src/unit-unicode.cpp | 26 +- test/thirdparty/catch/catch.hpp | 17832 +++++++++++------------ 23 files changed, 9539 insertions(+), 9937 deletions(-) diff --git a/test/src/unit-algorithms.cpp b/test/src/unit-algorithms.cpp index 6136fefa5..bc108dcdd 100644 --- a/test/src/unit-algorithms.cpp +++ b/test/src/unit-algorithms.cpp @@ -240,7 +240,7 @@ TEST_CASE("algorithms") SECTION("sorting an object") { json j({{"one", 1}, {"two", 2}}); - CHECK_THROWS_AS(std::sort(j.begin(), j.end()), json::invalid_iterator); + CHECK_THROWS_AS(std::sort(j.begin(), j.end()), json::invalid_iterator&); CHECK_THROWS_WITH(std::sort(j.begin(), j.end()), "[json.exception.invalid_iterator.209] cannot use offsets with object iterators"); } diff --git a/test/src/unit-allocator.cpp b/test/src/unit-allocator.cpp index 903d5950a..d2423a487 100644 --- a/test/src/unit-allocator.cpp +++ b/test/src/unit-allocator.cpp @@ -59,7 +59,7 @@ TEST_CASE("bad_alloc") bad_allocator>; // creating an object should throw - CHECK_THROWS_AS(bad_json(bad_json::value_t::object), std::bad_alloc); + CHECK_THROWS_AS(bad_json(bad_json::value_t::object), std::bad_alloc&); } } @@ -143,7 +143,7 @@ TEST_CASE("controlled bad_alloc") auto t = my_json::value_t::object; CHECK_NOTHROW(my_allocator_clean_up(my_json::json_value(t).object)); next_construct_fails = true; - CHECK_THROWS_AS(my_json::json_value(t), std::bad_alloc); + CHECK_THROWS_AS(my_json::json_value(t), std::bad_alloc&); next_construct_fails = false; } SECTION("array") @@ -152,7 +152,7 @@ TEST_CASE("controlled bad_alloc") auto t = my_json::value_t::array; CHECK_NOTHROW(my_allocator_clean_up(my_json::json_value(t).array)); next_construct_fails = true; - CHECK_THROWS_AS(my_json::json_value(t), std::bad_alloc); + CHECK_THROWS_AS(my_json::json_value(t), std::bad_alloc&); next_construct_fails = false; } SECTION("string") @@ -161,7 +161,7 @@ TEST_CASE("controlled bad_alloc") auto t = my_json::value_t::string; CHECK_NOTHROW(my_allocator_clean_up(my_json::json_value(t).string)); next_construct_fails = true; - CHECK_THROWS_AS(my_json::json_value(t), std::bad_alloc); + CHECK_THROWS_AS(my_json::json_value(t), std::bad_alloc&); next_construct_fails = false; } } @@ -172,7 +172,7 @@ TEST_CASE("controlled bad_alloc") my_json::string_t v("foo"); CHECK_NOTHROW(my_allocator_clean_up(my_json::json_value(v).string)); next_construct_fails = true; - CHECK_THROWS_AS(my_json::json_value(v), std::bad_alloc); + CHECK_THROWS_AS(my_json::json_value(v), std::bad_alloc&); next_construct_fails = false; } @@ -183,7 +183,7 @@ TEST_CASE("controlled bad_alloc") my_json::object_t v {{"foo", "bar"}}; CHECK_NOTHROW(my_json::json_value j(v)); next_construct_fails = true; - CHECK_THROWS_AS(my_json::json_value j(v), std::bad_alloc); + CHECK_THROWS_AS(my_json::json_value j(v), std::bad_alloc&); next_construct_fails = false; } */ @@ -194,7 +194,7 @@ TEST_CASE("controlled bad_alloc") my_json::array_t v = {"foo", "bar", "baz"}; CHECK_NOTHROW(my_json::json_value j(v)); next_construct_fails = true; - CHECK_THROWS_AS(my_json::json_value j(v), std::bad_alloc); + CHECK_THROWS_AS(my_json::json_value j(v), std::bad_alloc&); next_construct_fails = false; } */ @@ -208,7 +208,7 @@ TEST_CASE("controlled bad_alloc") std::map v {{"foo", "bar"}}; CHECK_NOTHROW(my_json(v)); next_construct_fails = true; - CHECK_THROWS_AS(my_json(v), std::bad_alloc); + CHECK_THROWS_AS(my_json(v), std::bad_alloc&); next_construct_fails = false; } @@ -218,7 +218,7 @@ TEST_CASE("controlled bad_alloc") std::vector v {"foo", "bar", "baz"}; CHECK_NOTHROW(my_json(v)); next_construct_fails = true; - CHECK_THROWS_AS(my_json(v), std::bad_alloc); + CHECK_THROWS_AS(my_json(v), std::bad_alloc&); next_construct_fails = false; } @@ -227,7 +227,7 @@ TEST_CASE("controlled bad_alloc") next_construct_fails = false; CHECK_NOTHROW(my_json("foo")); next_construct_fails = true; - CHECK_THROWS_AS(my_json("foo"), std::bad_alloc); + CHECK_THROWS_AS(my_json("foo"), std::bad_alloc&); next_construct_fails = false; } @@ -237,7 +237,7 @@ TEST_CASE("controlled bad_alloc") std::string s("foo"); CHECK_NOTHROW(my_json(s)); next_construct_fails = true; - CHECK_THROWS_AS(my_json(s), std::bad_alloc); + CHECK_THROWS_AS(my_json(s), std::bad_alloc&); next_construct_fails = false; } } diff --git a/test/src/unit-cbor.cpp b/test/src/unit-cbor.cpp index 330b7ca19..8d28f6867 100644 --- a/test/src/unit-cbor.cpp +++ b/test/src/unit-cbor.cpp @@ -31,7 +31,6 @@ SOFTWARE. #include "json.hpp" using nlohmann::json; -#include #include TEST_CASE("CBOR") @@ -740,13 +739,13 @@ TEST_CASE("CBOR") { SECTION("no byte follows") { - CHECK_THROWS_AS(json::from_cbor(std::vector({0xf9})), json::parse_error); + CHECK_THROWS_AS(json::from_cbor(std::vector({0xf9})), json::parse_error&); CHECK_THROWS_WITH(json::from_cbor(std::vector({0xf9})), "[json.exception.parse_error.110] parse error at 2: unexpected end of input"); } SECTION("only one byte follows") { - CHECK_THROWS_AS(json::from_cbor(std::vector({0xf9, 0x7c})), json::parse_error); + CHECK_THROWS_AS(json::from_cbor(std::vector({0xf9, 0x7c})), json::parse_error&); CHECK_THROWS_WITH(json::from_cbor(std::vector({0xf9, 0x7c})), "[json.exception.parse_error.110] parse error at 3: unexpected end of input"); } @@ -1227,28 +1226,28 @@ TEST_CASE("CBOR") { SECTION("empty byte vector") { - CHECK_THROWS_AS(json::from_cbor(std::vector()), json::parse_error); + CHECK_THROWS_AS(json::from_cbor(std::vector()), json::parse_error&); CHECK_THROWS_WITH(json::from_cbor(std::vector()), "[json.exception.parse_error.110] parse error at 1: unexpected end of input"); } SECTION("too short byte vector") { - CHECK_THROWS_AS(json::from_cbor(std::vector({0x18})), json::parse_error); - CHECK_THROWS_AS(json::from_cbor(std::vector({0x19})), json::parse_error); - CHECK_THROWS_AS(json::from_cbor(std::vector({0x19, 0x00})), json::parse_error); - CHECK_THROWS_AS(json::from_cbor(std::vector({0x1a})), json::parse_error); - CHECK_THROWS_AS(json::from_cbor(std::vector({0x1a, 0x00})), json::parse_error); - CHECK_THROWS_AS(json::from_cbor(std::vector({0x1a, 0x00, 0x00})), json::parse_error); - CHECK_THROWS_AS(json::from_cbor(std::vector({0x1a, 0x00, 0x00, 0x00})), json::parse_error); - CHECK_THROWS_AS(json::from_cbor(std::vector({0x1b})), json::parse_error); - CHECK_THROWS_AS(json::from_cbor(std::vector({0x1b, 0x00})), json::parse_error); - CHECK_THROWS_AS(json::from_cbor(std::vector({0x1b, 0x00, 0x00})), json::parse_error); - CHECK_THROWS_AS(json::from_cbor(std::vector({0x1b, 0x00, 0x00, 0x00})), json::parse_error); - CHECK_THROWS_AS(json::from_cbor(std::vector({0x1b, 0x00, 0x00, 0x00, 0x00})), json::parse_error); - CHECK_THROWS_AS(json::from_cbor(std::vector({0x1b, 0x00, 0x00, 0x00, 0x00, 0x00})), json::parse_error); - CHECK_THROWS_AS(json::from_cbor(std::vector({0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00})), json::parse_error); - CHECK_THROWS_AS(json::from_cbor(std::vector({0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00})), json::parse_error); + CHECK_THROWS_AS(json::from_cbor(std::vector({0x18})), json::parse_error&); + CHECK_THROWS_AS(json::from_cbor(std::vector({0x19})), json::parse_error&); + CHECK_THROWS_AS(json::from_cbor(std::vector({0x19, 0x00})), json::parse_error&); + CHECK_THROWS_AS(json::from_cbor(std::vector({0x1a})), json::parse_error&); + CHECK_THROWS_AS(json::from_cbor(std::vector({0x1a, 0x00})), json::parse_error&); + CHECK_THROWS_AS(json::from_cbor(std::vector({0x1a, 0x00, 0x00})), json::parse_error&); + CHECK_THROWS_AS(json::from_cbor(std::vector({0x1a, 0x00, 0x00, 0x00})), json::parse_error&); + CHECK_THROWS_AS(json::from_cbor(std::vector({0x1b})), json::parse_error&); + CHECK_THROWS_AS(json::from_cbor(std::vector({0x1b, 0x00})), json::parse_error&); + CHECK_THROWS_AS(json::from_cbor(std::vector({0x1b, 0x00, 0x00})), json::parse_error&); + CHECK_THROWS_AS(json::from_cbor(std::vector({0x1b, 0x00, 0x00, 0x00})), json::parse_error&); + CHECK_THROWS_AS(json::from_cbor(std::vector({0x1b, 0x00, 0x00, 0x00, 0x00})), json::parse_error&); + CHECK_THROWS_AS(json::from_cbor(std::vector({0x1b, 0x00, 0x00, 0x00, 0x00, 0x00})), json::parse_error&); + CHECK_THROWS_AS(json::from_cbor(std::vector({0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00})), json::parse_error&); + CHECK_THROWS_AS(json::from_cbor(std::vector({0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00})), json::parse_error&); CHECK_THROWS_WITH(json::from_cbor(std::vector({0x18})), "[json.exception.parse_error.110] parse error at 2: unexpected end of input"); @@ -1286,10 +1285,10 @@ TEST_CASE("CBOR") { SECTION("concrete examples") { - CHECK_THROWS_AS(json::from_cbor(std::vector({0x1c})), json::parse_error); + CHECK_THROWS_AS(json::from_cbor(std::vector({0x1c})), json::parse_error&); CHECK_THROWS_WITH(json::from_cbor(std::vector({0x1c})), "[json.exception.parse_error.112] parse error at 1: error reading CBOR; last byte: 0x1C"); - CHECK_THROWS_AS(json::from_cbor(std::vector({0xf8})), json::parse_error); + CHECK_THROWS_AS(json::from_cbor(std::vector({0xf8})), json::parse_error&); CHECK_THROWS_WITH(json::from_cbor(std::vector({0xf8})), "[json.exception.parse_error.112] parse error at 1: error reading CBOR; last byte: 0xF8"); } @@ -1340,14 +1339,14 @@ TEST_CASE("CBOR") 0xf8 }) { - CHECK_THROWS_AS(json::from_cbor(std::vector({static_cast(byte)})), json::parse_error); + CHECK_THROWS_AS(json::from_cbor(std::vector({static_cast(byte)})), json::parse_error&); } } } SECTION("invalid string in map") { - CHECK_THROWS_AS(json::from_cbor(std::vector({0xa1, 0xff, 0x01})), json::parse_error); + CHECK_THROWS_AS(json::from_cbor(std::vector({0xa1, 0xff, 0x01})), json::parse_error&); CHECK_THROWS_WITH(json::from_cbor(std::vector({0xa1, 0xff, 0x01})), "[json.exception.parse_error.113] parse error at 2: expected a CBOR string; last byte: 0xFF"); } @@ -1363,7 +1362,7 @@ TEST_CASE("CBOR") SECTION("strict mode") { - CHECK_THROWS_AS(json::from_cbor(vec), json::parse_error); + CHECK_THROWS_AS(json::from_cbor(vec), json::parse_error&); CHECK_THROWS_WITH(json::from_cbor(vec), "[json.exception.parse_error.110] parse error at 2: expected end of input"); } diff --git a/test/src/unit-class_const_iterator.cpp b/test/src/unit-class_const_iterator.cpp index 5356fb356..573e773bb 100644 --- a/test/src/unit-class_const_iterator.cpp +++ b/test/src/unit-class_const_iterator.cpp @@ -147,7 +147,7 @@ TEST_CASE("const_iterator class") { json j(json::value_t::null); json::const_iterator it = j.cbegin(); - CHECK_THROWS_AS(*it, json::invalid_iterator); + CHECK_THROWS_AS(*it, json::invalid_iterator&); CHECK_THROWS_WITH(*it, "[json.exception.invalid_iterator.214] cannot get value"); } @@ -157,7 +157,7 @@ TEST_CASE("const_iterator class") json::const_iterator it = j.cbegin(); CHECK(*it == json(17)); it = j.cend(); - CHECK_THROWS_AS(*it, json::invalid_iterator); + CHECK_THROWS_AS(*it, json::invalid_iterator&); CHECK_THROWS_WITH(*it, "[json.exception.invalid_iterator.214] cannot get value"); } @@ -182,7 +182,7 @@ TEST_CASE("const_iterator class") { json j(json::value_t::null); json::const_iterator it = j.cbegin(); - CHECK_THROWS_AS(std::string(it->type_name()), json::invalid_iterator); + CHECK_THROWS_AS(std::string(it->type_name()), json::invalid_iterator&); CHECK_THROWS_WITH(std::string(it->type_name()), "[json.exception.invalid_iterator.214] cannot get value"); } @@ -192,7 +192,7 @@ TEST_CASE("const_iterator class") json::const_iterator it = j.cbegin(); CHECK(std::string(it->type_name()) == "number"); it = j.cend(); - CHECK_THROWS_AS(std::string(it->type_name()), json::invalid_iterator); + CHECK_THROWS_AS(std::string(it->type_name()), json::invalid_iterator&); CHECK_THROWS_WITH(std::string(it->type_name()), "[json.exception.invalid_iterator.214] cannot get value"); } diff --git a/test/src/unit-class_iterator.cpp b/test/src/unit-class_iterator.cpp index cb7f16a53..1ef4a5389 100644 --- a/test/src/unit-class_iterator.cpp +++ b/test/src/unit-class_iterator.cpp @@ -131,7 +131,7 @@ TEST_CASE("iterator class") { json j(json::value_t::null); json::iterator it = j.begin(); - CHECK_THROWS_AS(*it, json::invalid_iterator); + CHECK_THROWS_AS(*it, json::invalid_iterator&); CHECK_THROWS_WITH(*it, "[json.exception.invalid_iterator.214] cannot get value"); } @@ -141,7 +141,7 @@ TEST_CASE("iterator class") json::iterator it = j.begin(); CHECK(*it == json(17)); it = j.end(); - CHECK_THROWS_AS(*it, json::invalid_iterator); + CHECK_THROWS_AS(*it, json::invalid_iterator&); CHECK_THROWS_WITH(*it, "[json.exception.invalid_iterator.214] cannot get value"); } @@ -166,7 +166,7 @@ TEST_CASE("iterator class") { json j(json::value_t::null); json::iterator it = j.begin(); - CHECK_THROWS_AS(std::string(it->type_name()), json::invalid_iterator); + CHECK_THROWS_AS(std::string(it->type_name()), json::invalid_iterator&); CHECK_THROWS_WITH(std::string(it->type_name()), "[json.exception.invalid_iterator.214] cannot get value"); } @@ -176,7 +176,7 @@ TEST_CASE("iterator class") json::iterator it = j.begin(); CHECK(std::string(it->type_name()) == "number"); it = j.end(); - CHECK_THROWS_AS(std::string(it->type_name()), json::invalid_iterator); + CHECK_THROWS_AS(std::string(it->type_name()), json::invalid_iterator&); CHECK_THROWS_WITH(std::string(it->type_name()), "[json.exception.invalid_iterator.214] cannot get value"); } diff --git a/test/src/unit-class_parser.cpp b/test/src/unit-class_parser.cpp index 7c4e635a4..9afa7d269 100644 --- a/test/src/unit-class_parser.cpp +++ b/test/src/unit-class_parser.cpp @@ -123,56 +123,56 @@ TEST_CASE("parser class") SECTION("errors") { // error: tab in string - CHECK_THROWS_AS(parser_helper("\"\t\""), json::parse_error); + CHECK_THROWS_AS(parser_helper("\"\t\""), json::parse_error&); CHECK_THROWS_WITH(parser_helper("\"\t\""), "[json.exception.parse_error.101] parse error at 2: syntax error - invalid string: control character must be escaped; last read: '\"'"); // error: newline in string - CHECK_THROWS_AS(parser_helper("\"\n\""), json::parse_error); - CHECK_THROWS_AS(parser_helper("\"\r\""), json::parse_error); + CHECK_THROWS_AS(parser_helper("\"\n\""), json::parse_error&); + CHECK_THROWS_AS(parser_helper("\"\r\""), json::parse_error&); CHECK_THROWS_WITH(parser_helper("\"\n\""), "[json.exception.parse_error.101] parse error at 2: syntax error - invalid string: control character must be escaped; last read: '\"'"); CHECK_THROWS_WITH(parser_helper("\"\r\""), "[json.exception.parse_error.101] parse error at 2: syntax error - invalid string: control character must be escaped; last read: '\"'"); // error: backspace in string - CHECK_THROWS_AS(parser_helper("\"\b\""), json::parse_error); + CHECK_THROWS_AS(parser_helper("\"\b\""), json::parse_error&); CHECK_THROWS_WITH(parser_helper("\"\b\""), "[json.exception.parse_error.101] parse error at 2: syntax error - invalid string: control character must be escaped; last read: '\"'"); // improve code coverage - CHECK_THROWS_AS(parser_helper("\uFF01"), json::parse_error); - CHECK_THROWS_AS(parser_helper("[-4:1,]"), json::parse_error); + CHECK_THROWS_AS(parser_helper("\uFF01"), json::parse_error&); + CHECK_THROWS_AS(parser_helper("[-4:1,]"), json::parse_error&); // unescaped control characters - CHECK_THROWS_AS(parser_helper("\"\x00\""), json::parse_error); - CHECK_THROWS_AS(parser_helper("\"\x01\""), json::parse_error); - CHECK_THROWS_AS(parser_helper("\"\x02\""), json::parse_error); - CHECK_THROWS_AS(parser_helper("\"\x03\""), json::parse_error); - CHECK_THROWS_AS(parser_helper("\"\x04\""), json::parse_error); - CHECK_THROWS_AS(parser_helper("\"\x05\""), json::parse_error); - CHECK_THROWS_AS(parser_helper("\"\x06\""), json::parse_error); - CHECK_THROWS_AS(parser_helper("\"\x07\""), json::parse_error); - CHECK_THROWS_AS(parser_helper("\"\x08\""), json::parse_error); - CHECK_THROWS_AS(parser_helper("\"\x09\""), json::parse_error); - CHECK_THROWS_AS(parser_helper("\"\x0a\""), json::parse_error); - CHECK_THROWS_AS(parser_helper("\"\x0b\""), json::parse_error); - CHECK_THROWS_AS(parser_helper("\"\x0c\""), json::parse_error); - CHECK_THROWS_AS(parser_helper("\"\x0d\""), json::parse_error); - CHECK_THROWS_AS(parser_helper("\"\x0e\""), json::parse_error); - CHECK_THROWS_AS(parser_helper("\"\x0f\""), json::parse_error); - CHECK_THROWS_AS(parser_helper("\"\x10\""), json::parse_error); - CHECK_THROWS_AS(parser_helper("\"\x11\""), json::parse_error); - CHECK_THROWS_AS(parser_helper("\"\x12\""), json::parse_error); - CHECK_THROWS_AS(parser_helper("\"\x13\""), json::parse_error); - CHECK_THROWS_AS(parser_helper("\"\x14\""), json::parse_error); - CHECK_THROWS_AS(parser_helper("\"\x15\""), json::parse_error); - CHECK_THROWS_AS(parser_helper("\"\x16\""), json::parse_error); - CHECK_THROWS_AS(parser_helper("\"\x17\""), json::parse_error); - CHECK_THROWS_AS(parser_helper("\"\x18\""), json::parse_error); - CHECK_THROWS_AS(parser_helper("\"\x19\""), json::parse_error); - CHECK_THROWS_AS(parser_helper("\"\x1a\""), json::parse_error); - CHECK_THROWS_AS(parser_helper("\"\x1b\""), json::parse_error); - CHECK_THROWS_AS(parser_helper("\"\x1c\""), json::parse_error); - CHECK_THROWS_AS(parser_helper("\"\x1d\""), json::parse_error); - CHECK_THROWS_AS(parser_helper("\"\x1e\""), json::parse_error); - CHECK_THROWS_AS(parser_helper("\"\x1f\""), json::parse_error); + CHECK_THROWS_AS(parser_helper("\"\x00\""), json::parse_error&); + CHECK_THROWS_AS(parser_helper("\"\x01\""), json::parse_error&); + CHECK_THROWS_AS(parser_helper("\"\x02\""), json::parse_error&); + CHECK_THROWS_AS(parser_helper("\"\x03\""), json::parse_error&); + CHECK_THROWS_AS(parser_helper("\"\x04\""), json::parse_error&); + CHECK_THROWS_AS(parser_helper("\"\x05\""), json::parse_error&); + CHECK_THROWS_AS(parser_helper("\"\x06\""), json::parse_error&); + CHECK_THROWS_AS(parser_helper("\"\x07\""), json::parse_error&); + CHECK_THROWS_AS(parser_helper("\"\x08\""), json::parse_error&); + CHECK_THROWS_AS(parser_helper("\"\x09\""), json::parse_error&); + CHECK_THROWS_AS(parser_helper("\"\x0a\""), json::parse_error&); + CHECK_THROWS_AS(parser_helper("\"\x0b\""), json::parse_error&); + CHECK_THROWS_AS(parser_helper("\"\x0c\""), json::parse_error&); + CHECK_THROWS_AS(parser_helper("\"\x0d\""), json::parse_error&); + CHECK_THROWS_AS(parser_helper("\"\x0e\""), json::parse_error&); + CHECK_THROWS_AS(parser_helper("\"\x0f\""), json::parse_error&); + CHECK_THROWS_AS(parser_helper("\"\x10\""), json::parse_error&); + CHECK_THROWS_AS(parser_helper("\"\x11\""), json::parse_error&); + CHECK_THROWS_AS(parser_helper("\"\x12\""), json::parse_error&); + CHECK_THROWS_AS(parser_helper("\"\x13\""), json::parse_error&); + CHECK_THROWS_AS(parser_helper("\"\x14\""), json::parse_error&); + CHECK_THROWS_AS(parser_helper("\"\x15\""), json::parse_error&); + CHECK_THROWS_AS(parser_helper("\"\x16\""), json::parse_error&); + CHECK_THROWS_AS(parser_helper("\"\x17\""), json::parse_error&); + CHECK_THROWS_AS(parser_helper("\"\x18\""), json::parse_error&); + CHECK_THROWS_AS(parser_helper("\"\x19\""), json::parse_error&); + CHECK_THROWS_AS(parser_helper("\"\x1a\""), json::parse_error&); + CHECK_THROWS_AS(parser_helper("\"\x1b\""), json::parse_error&); + CHECK_THROWS_AS(parser_helper("\"\x1c\""), json::parse_error&); + CHECK_THROWS_AS(parser_helper("\"\x1d\""), json::parse_error&); + CHECK_THROWS_AS(parser_helper("\"\x1e\""), json::parse_error&); + CHECK_THROWS_AS(parser_helper("\"\x1f\""), json::parse_error&); CHECK_THROWS_WITH(parser_helper("\"\x00\""), "[json.exception.parse_error.101] parse error at 2: syntax error - invalid string: missing closing quote; last read: '\"'"); CHECK_THROWS_WITH(parser_helper("\"\x01\""), "[json.exception.parse_error.101] parse error at 2: syntax error - invalid string: control character must be escaped; last read: '\"'"); CHECK_THROWS_WITH(parser_helper("\"\x02\""), "[json.exception.parse_error.101] parse error at 2: syntax error - invalid string: control character must be escaped; last read: '\"'"); @@ -214,7 +214,7 @@ TEST_CASE("parser class") // uses an iterator range. std::string s = "\"1\""; s[1] = '\0'; - CHECK_THROWS_AS(json::parse(s.begin(), s.end()), json::parse_error); + CHECK_THROWS_AS(json::parse(s.begin(), s.end()), json::parse_error&); CHECK_THROWS_WITH(json::parse(s.begin(), s.end()), "[json.exception.parse_error.101] parse error at 2: syntax error - invalid string: control character must be escaped; last read: '\"'"); } } @@ -386,33 +386,33 @@ TEST_CASE("parser class") SECTION("overflow") { // overflows during parsing yield an exception - CHECK_THROWS_AS(parser_helper("1.18973e+4932") == json(), json::out_of_range); + CHECK_THROWS_AS(parser_helper("1.18973e+4932") == json(), json::out_of_range&); CHECK_THROWS_WITH(parser_helper("1.18973e+4932") == json(), "[json.exception.out_of_range.406] number overflow parsing '1.18973e+4932'"); } SECTION("invalid numbers") { - CHECK_THROWS_AS(parser_helper("01"), json::parse_error); - CHECK_THROWS_AS(parser_helper("--1"), json::parse_error); - CHECK_THROWS_AS(parser_helper("1."), json::parse_error); - CHECK_THROWS_AS(parser_helper("1E"), json::parse_error); - CHECK_THROWS_AS(parser_helper("1E-"), json::parse_error); - CHECK_THROWS_AS(parser_helper("1.E1"), json::parse_error); - CHECK_THROWS_AS(parser_helper("-1E"), json::parse_error); - CHECK_THROWS_AS(parser_helper("-0E#"), json::parse_error); - CHECK_THROWS_AS(parser_helper("-0E-#"), json::parse_error); - CHECK_THROWS_AS(parser_helper("-0#"), json::parse_error); - CHECK_THROWS_AS(parser_helper("-0.0:"), json::parse_error); - CHECK_THROWS_AS(parser_helper("-0.0Z"), json::parse_error); - CHECK_THROWS_AS(parser_helper("-0E123:"), json::parse_error); - CHECK_THROWS_AS(parser_helper("-0e0-:"), json::parse_error); - CHECK_THROWS_AS(parser_helper("-0e-:"), json::parse_error); - CHECK_THROWS_AS(parser_helper("-0f"), json::parse_error); + CHECK_THROWS_AS(parser_helper("01"), json::parse_error&); + CHECK_THROWS_AS(parser_helper("--1"), json::parse_error&); + CHECK_THROWS_AS(parser_helper("1."), json::parse_error&); + CHECK_THROWS_AS(parser_helper("1E"), json::parse_error&); + CHECK_THROWS_AS(parser_helper("1E-"), json::parse_error&); + CHECK_THROWS_AS(parser_helper("1.E1"), json::parse_error&); + CHECK_THROWS_AS(parser_helper("-1E"), json::parse_error&); + CHECK_THROWS_AS(parser_helper("-0E#"), json::parse_error&); + CHECK_THROWS_AS(parser_helper("-0E-#"), json::parse_error&); + CHECK_THROWS_AS(parser_helper("-0#"), json::parse_error&); + CHECK_THROWS_AS(parser_helper("-0.0:"), json::parse_error&); + CHECK_THROWS_AS(parser_helper("-0.0Z"), json::parse_error&); + CHECK_THROWS_AS(parser_helper("-0E123:"), json::parse_error&); + CHECK_THROWS_AS(parser_helper("-0e0-:"), json::parse_error&); + CHECK_THROWS_AS(parser_helper("-0e-:"), json::parse_error&); + CHECK_THROWS_AS(parser_helper("-0f"), json::parse_error&); // numbers must not begin with "+" - CHECK_THROWS_AS(parser_helper("+1"), json::parse_error); - CHECK_THROWS_AS(parser_helper("+0"), json::parse_error); + CHECK_THROWS_AS(parser_helper("+1"), json::parse_error&); + CHECK_THROWS_AS(parser_helper("+0"), json::parse_error&); CHECK_THROWS_WITH(parser_helper("01"), "[json.exception.parse_error.101] parse error at 2: syntax error - unexpected number literal; expected end of input"); @@ -717,20 +717,20 @@ TEST_CASE("parser class") SECTION("parse errors") { // unexpected end of number - CHECK_THROWS_AS(parser_helper("0."), json::parse_error); - CHECK_THROWS_AS(parser_helper("-"), json::parse_error); - CHECK_THROWS_AS(parser_helper("--"), json::parse_error); - CHECK_THROWS_AS(parser_helper("-0."), json::parse_error); - CHECK_THROWS_AS(parser_helper("-."), json::parse_error); - CHECK_THROWS_AS(parser_helper("-:"), json::parse_error); - CHECK_THROWS_AS(parser_helper("0.:"), json::parse_error); - CHECK_THROWS_AS(parser_helper("e."), json::parse_error); - CHECK_THROWS_AS(parser_helper("1e."), json::parse_error); - CHECK_THROWS_AS(parser_helper("1e/"), json::parse_error); - CHECK_THROWS_AS(parser_helper("1e:"), json::parse_error); - CHECK_THROWS_AS(parser_helper("1E."), json::parse_error); - CHECK_THROWS_AS(parser_helper("1E/"), json::parse_error); - CHECK_THROWS_AS(parser_helper("1E:"), json::parse_error); + CHECK_THROWS_AS(parser_helper("0."), json::parse_error&); + CHECK_THROWS_AS(parser_helper("-"), json::parse_error&); + CHECK_THROWS_AS(parser_helper("--"), json::parse_error&); + CHECK_THROWS_AS(parser_helper("-0."), json::parse_error&); + CHECK_THROWS_AS(parser_helper("-."), json::parse_error&); + CHECK_THROWS_AS(parser_helper("-:"), json::parse_error&); + CHECK_THROWS_AS(parser_helper("0.:"), json::parse_error&); + CHECK_THROWS_AS(parser_helper("e."), json::parse_error&); + CHECK_THROWS_AS(parser_helper("1e."), json::parse_error&); + CHECK_THROWS_AS(parser_helper("1e/"), json::parse_error&); + CHECK_THROWS_AS(parser_helper("1e:"), json::parse_error&); + CHECK_THROWS_AS(parser_helper("1E."), json::parse_error&); + CHECK_THROWS_AS(parser_helper("1E/"), json::parse_error&); + CHECK_THROWS_AS(parser_helper("1E:"), json::parse_error&); CHECK_THROWS_WITH(parser_helper("0."), "[json.exception.parse_error.101] parse error at 3: syntax error - invalid number; expected digit after '.'; last read: '0.'"); CHECK_THROWS_WITH(parser_helper("-"), @@ -761,11 +761,11 @@ TEST_CASE("parser class") "[json.exception.parse_error.101] parse error at 3: syntax error - invalid number; expected '+', '-', or digit after exponent; last read: '1E:'"); // unexpected end of null - CHECK_THROWS_AS(parser_helper("n"), json::parse_error); - CHECK_THROWS_AS(parser_helper("nu"), json::parse_error); - CHECK_THROWS_AS(parser_helper("nul"), json::parse_error); - CHECK_THROWS_AS(parser_helper("nulk"), json::parse_error); - CHECK_THROWS_AS(parser_helper("nulm"), json::parse_error); + CHECK_THROWS_AS(parser_helper("n"), json::parse_error&); + CHECK_THROWS_AS(parser_helper("nu"), json::parse_error&); + CHECK_THROWS_AS(parser_helper("nul"), json::parse_error&); + CHECK_THROWS_AS(parser_helper("nulk"), json::parse_error&); + CHECK_THROWS_AS(parser_helper("nulm"), json::parse_error&); CHECK_THROWS_WITH(parser_helper("n"), "[json.exception.parse_error.101] parse error at 2: syntax error - invalid literal; last read: 'n'"); CHECK_THROWS_WITH(parser_helper("nu"), @@ -778,11 +778,11 @@ TEST_CASE("parser class") "[json.exception.parse_error.101] parse error at 4: syntax error - invalid literal; last read: 'nulm'"); // unexpected end of true - CHECK_THROWS_AS(parser_helper("t"), json::parse_error); - CHECK_THROWS_AS(parser_helper("tr"), json::parse_error); - CHECK_THROWS_AS(parser_helper("tru"), json::parse_error); - CHECK_THROWS_AS(parser_helper("trud"), json::parse_error); - CHECK_THROWS_AS(parser_helper("truf"), json::parse_error); + CHECK_THROWS_AS(parser_helper("t"), json::parse_error&); + CHECK_THROWS_AS(parser_helper("tr"), json::parse_error&); + CHECK_THROWS_AS(parser_helper("tru"), json::parse_error&); + CHECK_THROWS_AS(parser_helper("trud"), json::parse_error&); + CHECK_THROWS_AS(parser_helper("truf"), json::parse_error&); CHECK_THROWS_WITH(parser_helper("t"), "[json.exception.parse_error.101] parse error at 2: syntax error - invalid literal; last read: 't'"); CHECK_THROWS_WITH(parser_helper("tr"), @@ -795,12 +795,12 @@ TEST_CASE("parser class") "[json.exception.parse_error.101] parse error at 4: syntax error - invalid literal; last read: 'truf'"); // unexpected end of false - CHECK_THROWS_AS(parser_helper("f"), json::parse_error); - CHECK_THROWS_AS(parser_helper("fa"), json::parse_error); - CHECK_THROWS_AS(parser_helper("fal"), json::parse_error); - CHECK_THROWS_AS(parser_helper("fals"), json::parse_error); - CHECK_THROWS_AS(parser_helper("falsd"), json::parse_error); - CHECK_THROWS_AS(parser_helper("falsf"), json::parse_error); + CHECK_THROWS_AS(parser_helper("f"), json::parse_error&); + CHECK_THROWS_AS(parser_helper("fa"), json::parse_error&); + CHECK_THROWS_AS(parser_helper("fal"), json::parse_error&); + CHECK_THROWS_AS(parser_helper("fals"), json::parse_error&); + CHECK_THROWS_AS(parser_helper("falsd"), json::parse_error&); + CHECK_THROWS_AS(parser_helper("falsf"), json::parse_error&); CHECK_THROWS_WITH(parser_helper("f"), "[json.exception.parse_error.101] parse error at 2: syntax error - invalid literal; last read: 'f'"); CHECK_THROWS_WITH(parser_helper("fa"), @@ -815,11 +815,11 @@ TEST_CASE("parser class") "[json.exception.parse_error.101] parse error at 5: syntax error - invalid literal; last read: 'falsf'"); // missing/unexpected end of array - CHECK_THROWS_AS(parser_helper("["), json::parse_error); - CHECK_THROWS_AS(parser_helper("[1"), json::parse_error); - CHECK_THROWS_AS(parser_helper("[1,"), json::parse_error); - CHECK_THROWS_AS(parser_helper("[1,]"), json::parse_error); - CHECK_THROWS_AS(parser_helper("]"), json::parse_error); + CHECK_THROWS_AS(parser_helper("["), json::parse_error&); + CHECK_THROWS_AS(parser_helper("[1"), json::parse_error&); + CHECK_THROWS_AS(parser_helper("[1,"), json::parse_error&); + CHECK_THROWS_AS(parser_helper("[1,]"), json::parse_error&); + CHECK_THROWS_AS(parser_helper("]"), json::parse_error&); CHECK_THROWS_WITH(parser_helper("["), "[json.exception.parse_error.101] parse error at 2: syntax error - unexpected end of input; expected '[', '{', or a literal"); CHECK_THROWS_WITH(parser_helper("[1"), @@ -832,12 +832,12 @@ TEST_CASE("parser class") "[json.exception.parse_error.101] parse error at 1: syntax error - unexpected ']'; expected '[', '{', or a literal"); // missing/unexpected end of object - CHECK_THROWS_AS(parser_helper("{"), json::parse_error); - CHECK_THROWS_AS(parser_helper("{\"foo\""), json::parse_error); - CHECK_THROWS_AS(parser_helper("{\"foo\":"), json::parse_error); - CHECK_THROWS_AS(parser_helper("{\"foo\":}"), json::parse_error); - CHECK_THROWS_AS(parser_helper("{\"foo\":1,}"), json::parse_error); - CHECK_THROWS_AS(parser_helper("}"), json::parse_error); + CHECK_THROWS_AS(parser_helper("{"), json::parse_error&); + CHECK_THROWS_AS(parser_helper("{\"foo\""), json::parse_error&); + CHECK_THROWS_AS(parser_helper("{\"foo\":"), json::parse_error&); + CHECK_THROWS_AS(parser_helper("{\"foo\":}"), json::parse_error&); + CHECK_THROWS_AS(parser_helper("{\"foo\":1,}"), json::parse_error&); + CHECK_THROWS_AS(parser_helper("}"), json::parse_error&); CHECK_THROWS_WITH(parser_helper("{"), "[json.exception.parse_error.101] parse error at 2: syntax error - unexpected end of input; expected string literal"); CHECK_THROWS_WITH(parser_helper("{\"foo\""), @@ -852,16 +852,16 @@ TEST_CASE("parser class") "[json.exception.parse_error.101] parse error at 1: syntax error - unexpected '}'; expected '[', '{', or a literal"); // missing/unexpected end of string - CHECK_THROWS_AS(parser_helper("\""), json::parse_error); - CHECK_THROWS_AS(parser_helper("\"\\\""), json::parse_error); - CHECK_THROWS_AS(parser_helper("\"\\u\""), json::parse_error); - CHECK_THROWS_AS(parser_helper("\"\\u0\""), json::parse_error); - CHECK_THROWS_AS(parser_helper("\"\\u01\""), json::parse_error); - CHECK_THROWS_AS(parser_helper("\"\\u012\""), json::parse_error); - CHECK_THROWS_AS(parser_helper("\"\\u"), json::parse_error); - CHECK_THROWS_AS(parser_helper("\"\\u0"), json::parse_error); - CHECK_THROWS_AS(parser_helper("\"\\u01"), json::parse_error); - CHECK_THROWS_AS(parser_helper("\"\\u012"), json::parse_error); + CHECK_THROWS_AS(parser_helper("\""), json::parse_error&); + CHECK_THROWS_AS(parser_helper("\"\\\""), json::parse_error&); + CHECK_THROWS_AS(parser_helper("\"\\u\""), json::parse_error&); + CHECK_THROWS_AS(parser_helper("\"\\u0\""), json::parse_error&); + CHECK_THROWS_AS(parser_helper("\"\\u01\""), json::parse_error&); + CHECK_THROWS_AS(parser_helper("\"\\u012\""), json::parse_error&); + CHECK_THROWS_AS(parser_helper("\"\\u"), json::parse_error&); + CHECK_THROWS_AS(parser_helper("\"\\u0"), json::parse_error&); + CHECK_THROWS_AS(parser_helper("\"\\u01"), json::parse_error&); + CHECK_THROWS_AS(parser_helper("\"\\u012"), json::parse_error&); CHECK_THROWS_WITH(parser_helper("\""), "[json.exception.parse_error.101] parse error at 2: syntax error - invalid string: missing closing quote; last read: '\"'"); CHECK_THROWS_WITH(parser_helper("\"\\\""), @@ -913,7 +913,7 @@ TEST_CASE("parser class") // any other combination of backslash and character is invalid default: { - CHECK_THROWS_AS(parser_helper(s.c_str()), json::parse_error); + CHECK_THROWS_AS(parser_helper(s.c_str()), json::parse_error&); // only check error message if c is not a control character if (c > 0x1f) { @@ -989,7 +989,7 @@ TEST_CASE("parser class") else { CAPTURE(s1); - CHECK_THROWS_AS(parser_helper(s1.c_str()), json::parse_error); + CHECK_THROWS_AS(parser_helper(s1.c_str()), json::parse_error&); // only check error message if c is not a control character if (c > 0x1f) { @@ -998,7 +998,7 @@ TEST_CASE("parser class") } CAPTURE(s2); - CHECK_THROWS_AS(parser_helper(s2.c_str()), json::parse_error); + CHECK_THROWS_AS(parser_helper(s2.c_str()), json::parse_error&); // only check error message if c is not a control character if (c > 0x1f) { @@ -1007,7 +1007,7 @@ TEST_CASE("parser class") } CAPTURE(s3); - CHECK_THROWS_AS(parser_helper(s3.c_str()), json::parse_error); + CHECK_THROWS_AS(parser_helper(s3.c_str()), json::parse_error&); // only check error message if c is not a control character if (c > 0x1f) { @@ -1016,7 +1016,7 @@ TEST_CASE("parser class") } CAPTURE(s4); - CHECK_THROWS_AS(parser_helper(s4.c_str()), json::parse_error); + CHECK_THROWS_AS(parser_helper(s4.c_str()), json::parse_error&); // only check error message if c is not a control character if (c > 0x1f) { @@ -1028,13 +1028,13 @@ TEST_CASE("parser class") } // missing part of a surrogate pair - CHECK_THROWS_AS(json::parse("\"\\uD80C\""), json::parse_error); + CHECK_THROWS_AS(json::parse("\"\\uD80C\""), json::parse_error&); CHECK_THROWS_WITH(json::parse("\"\\uD80C\""), "[json.exception.parse_error.101] parse error at 8: syntax error - invalid string: surrogate U+DC00..U+DFFF must be followed by U+DC00..U+DFFF; last read: '\"\\uD80C\"'"); // invalid surrogate pair - CHECK_THROWS_AS(json::parse("\"\\uD80C\\uD80C\""), json::parse_error); - CHECK_THROWS_AS(json::parse("\"\\uD80C\\u0000\""), json::parse_error); - CHECK_THROWS_AS(json::parse("\"\\uD80C\\uFFFF\""), json::parse_error); + CHECK_THROWS_AS(json::parse("\"\\uD80C\\uD80C\""), json::parse_error&); + CHECK_THROWS_AS(json::parse("\"\\uD80C\\u0000\""), json::parse_error&); + CHECK_THROWS_AS(json::parse("\"\\uD80C\\uFFFF\""), json::parse_error&); CHECK_THROWS_WITH(json::parse("\"\\uD80C\\uD80C\""), "[json.exception.parse_error.101] parse error at 13: syntax error - invalid string: surrogate U+DC00..U+DFFF must be followed by U+DC00..U+DFFF; last read: '\"\\uD80C\\uD80C'"); CHECK_THROWS_WITH(json::parse("\"\\uD80C\\u0000\""), @@ -1229,11 +1229,11 @@ TEST_CASE("parser class") SECTION("tests found by mutate++") { // test case to make sure no comma preceeds the first key - CHECK_THROWS_AS(parser_helper("{,\"key\": false}"), json::parse_error); + CHECK_THROWS_AS(parser_helper("{,\"key\": false}"), json::parse_error&); CHECK_THROWS_WITH(parser_helper("{,\"key\": false}"), "[json.exception.parse_error.101] parse error at 2: syntax error - unexpected ','; expected string literal"); // test case to make sure an object is properly closed - CHECK_THROWS_AS(parser_helper("[{\"key\": false true]"), json::parse_error); + CHECK_THROWS_AS(parser_helper("[{\"key\": false true]"), json::parse_error&); CHECK_THROWS_WITH(parser_helper("[{\"key\": false true]"), "[json.exception.parse_error.101] parse error at 19: syntax error - unexpected true literal; expected '}'"); diff --git a/test/src/unit-constructor1.cpp b/test/src/unit-constructor1.cpp index 8840fe7e7..d8c9482cb 100644 --- a/test/src/unit-constructor1.cpp +++ b/test/src/unit-constructor1.cpp @@ -36,7 +36,6 @@ using nlohmann::json; #include #include #include -#include #include #include #include @@ -1050,7 +1049,7 @@ TEST_CASE("constructors") SECTION("object with error") { CHECK_THROWS_AS(json::object({ {"one", 1}, {"two", 1u}, {"three", 2.2}, {"four", false}, 13 }), - json::type_error); + json::type_error&); CHECK_THROWS_WITH(json::object({ {"one", 1}, {"two", 1u}, {"three", 2.2}, {"four", false}, 13 }), "[json.exception.type_error.301] cannot create object from initializer list"); } @@ -1264,16 +1263,16 @@ TEST_CASE("constructors") { json jobject = {{"a", "a"}, {"b", 1}, {"c", 17u}, {"d", false}, {"e", true}}; json jobject2 = {{"a", "a"}, {"b", 1}, {"c", 17u}}; - CHECK_THROWS_AS(json(jobject.begin(), jobject2.end()), json::invalid_iterator); - CHECK_THROWS_AS(json(jobject2.begin(), jobject.end()), json::invalid_iterator); + CHECK_THROWS_AS(json(jobject.begin(), jobject2.end()), json::invalid_iterator&); + CHECK_THROWS_AS(json(jobject2.begin(), jobject.end()), json::invalid_iterator&); CHECK_THROWS_WITH(json(jobject.begin(), jobject2.end()), "[json.exception.invalid_iterator.201] iterators are not compatible"); CHECK_THROWS_WITH(json(jobject2.begin(), jobject.end()), "[json.exception.invalid_iterator.201] iterators are not compatible"); } { json jobject = {{"a", "a"}, {"b", 1}, {"c", 17u}, {"d", false}, {"e", true}}; json jobject2 = {{"a", "a"}, {"b", 1}, {"c", 17u}}; - CHECK_THROWS_AS(json(jobject.cbegin(), jobject2.cend()), json::invalid_iterator); - CHECK_THROWS_AS(json(jobject2.cbegin(), jobject.cend()), json::invalid_iterator); + CHECK_THROWS_AS(json(jobject.cbegin(), jobject2.cend()), json::invalid_iterator&); + CHECK_THROWS_AS(json(jobject2.cbegin(), jobject.cend()), json::invalid_iterator&); CHECK_THROWS_WITH(json(jobject.cbegin(), jobject2.cend()), "[json.exception.invalid_iterator.201] iterators are not compatible"); CHECK_THROWS_WITH(json(jobject2.cbegin(), jobject.cend()), "[json.exception.invalid_iterator.201] iterators are not compatible"); } @@ -1329,16 +1328,16 @@ TEST_CASE("constructors") { json jarray = {1, 2, 3, 4}; json jarray2 = {2, 3, 4, 5}; - CHECK_THROWS_AS(json(jarray.begin(), jarray2.end()), json::invalid_iterator); - CHECK_THROWS_AS(json(jarray2.begin(), jarray.end()), json::invalid_iterator); + CHECK_THROWS_AS(json(jarray.begin(), jarray2.end()), json::invalid_iterator&); + CHECK_THROWS_AS(json(jarray2.begin(), jarray.end()), json::invalid_iterator&); CHECK_THROWS_WITH(json(jarray.begin(), jarray2.end()), "[json.exception.invalid_iterator.201] iterators are not compatible"); CHECK_THROWS_WITH(json(jarray2.begin(), jarray.end()), "[json.exception.invalid_iterator.201] iterators are not compatible"); } { json jarray = {1, 2, 3, 4}; json jarray2 = {2, 3, 4, 5}; - CHECK_THROWS_AS(json(jarray.cbegin(), jarray2.cend()), json::invalid_iterator); - CHECK_THROWS_AS(json(jarray2.cbegin(), jarray.cend()), json::invalid_iterator); + CHECK_THROWS_AS(json(jarray.cbegin(), jarray2.cend()), json::invalid_iterator&); + CHECK_THROWS_AS(json(jarray2.cbegin(), jarray.cend()), json::invalid_iterator&); CHECK_THROWS_WITH(json(jarray.cbegin(), jarray2.cend()), "[json.exception.invalid_iterator.201] iterators are not compatible"); CHECK_THROWS_WITH(json(jarray2.cbegin(), jarray.cend()), "[json.exception.invalid_iterator.201] iterators are not compatible"); } @@ -1353,13 +1352,13 @@ TEST_CASE("constructors") { { json j; - CHECK_THROWS_AS(json(j.begin(), j.end()), json::invalid_iterator); + CHECK_THROWS_AS(json(j.begin(), j.end()), json::invalid_iterator&); CHECK_THROWS_WITH(json(j.begin(), j.end()), "[json.exception.invalid_iterator.206] cannot construct with iterators from null"); } { json j; - CHECK_THROWS_AS(json(j.cbegin(), j.cend()), json::invalid_iterator); + CHECK_THROWS_AS(json(j.cbegin(), j.cend()), json::invalid_iterator&); CHECK_THROWS_WITH(json(j.cbegin(), j.cend()), "[json.exception.invalid_iterator.206] cannot construct with iterators from null"); } @@ -1442,15 +1441,15 @@ TEST_CASE("constructors") { { json j = "foo"; - CHECK_THROWS_AS(json(j.end(), j.end()), json::invalid_iterator); - CHECK_THROWS_AS(json(j.begin(), j.begin()), json::invalid_iterator); + CHECK_THROWS_AS(json(j.end(), j.end()), json::invalid_iterator&); + CHECK_THROWS_AS(json(j.begin(), j.begin()), json::invalid_iterator&); CHECK_THROWS_WITH(json(j.end(), j.end()), "[json.exception.invalid_iterator.204] iterators out of range"); CHECK_THROWS_WITH(json(j.begin(), j.begin()), "[json.exception.invalid_iterator.204] iterators out of range"); } { json j = "bar"; - CHECK_THROWS_AS(json(j.cend(), j.cend()), json::invalid_iterator); - CHECK_THROWS_AS(json(j.cbegin(), j.cbegin()), json::invalid_iterator); + CHECK_THROWS_AS(json(j.cend(), j.cend()), json::invalid_iterator&); + CHECK_THROWS_AS(json(j.cbegin(), j.cbegin()), json::invalid_iterator&); CHECK_THROWS_WITH(json(j.cend(), j.cend()), "[json.exception.invalid_iterator.204] iterators out of range"); CHECK_THROWS_WITH(json(j.cbegin(), j.cbegin()), "[json.exception.invalid_iterator.204] iterators out of range"); } @@ -1460,15 +1459,15 @@ TEST_CASE("constructors") { { json j = false; - CHECK_THROWS_AS(json(j.end(), j.end()), json::invalid_iterator); - CHECK_THROWS_AS(json(j.begin(), j.begin()), json::invalid_iterator); + CHECK_THROWS_AS(json(j.end(), j.end()), json::invalid_iterator&); + CHECK_THROWS_AS(json(j.begin(), j.begin()), json::invalid_iterator&); CHECK_THROWS_WITH(json(j.end(), j.end()), "[json.exception.invalid_iterator.204] iterators out of range"); CHECK_THROWS_WITH(json(j.begin(), j.begin()), "[json.exception.invalid_iterator.204] iterators out of range"); } { json j = true; - CHECK_THROWS_AS(json(j.cend(), j.cend()), json::invalid_iterator); - CHECK_THROWS_AS(json(j.cbegin(), j.cbegin()), json::invalid_iterator); + CHECK_THROWS_AS(json(j.cend(), j.cend()), json::invalid_iterator&); + CHECK_THROWS_AS(json(j.cbegin(), j.cbegin()), json::invalid_iterator&); CHECK_THROWS_WITH(json(j.cend(), j.cend()), "[json.exception.invalid_iterator.204] iterators out of range"); CHECK_THROWS_WITH(json(j.cbegin(), j.cbegin()), "[json.exception.invalid_iterator.204] iterators out of range"); } @@ -1478,15 +1477,15 @@ TEST_CASE("constructors") { { json j = 17; - CHECK_THROWS_AS(json(j.end(), j.end()), json::invalid_iterator); - CHECK_THROWS_AS(json(j.begin(), j.begin()), json::invalid_iterator); + CHECK_THROWS_AS(json(j.end(), j.end()), json::invalid_iterator&); + CHECK_THROWS_AS(json(j.begin(), j.begin()), json::invalid_iterator&); CHECK_THROWS_WITH(json(j.end(), j.end()), "[json.exception.invalid_iterator.204] iterators out of range"); CHECK_THROWS_WITH(json(j.begin(), j.begin()), "[json.exception.invalid_iterator.204] iterators out of range"); } { json j = 17; - CHECK_THROWS_AS(json(j.cend(), j.cend()), json::invalid_iterator); - CHECK_THROWS_AS(json(j.cbegin(), j.cbegin()), json::invalid_iterator); + CHECK_THROWS_AS(json(j.cend(), j.cend()), json::invalid_iterator&); + CHECK_THROWS_AS(json(j.cbegin(), j.cbegin()), json::invalid_iterator&); CHECK_THROWS_WITH(json(j.cend(), j.cend()), "[json.exception.invalid_iterator.204] iterators out of range"); CHECK_THROWS_WITH(json(j.cbegin(), j.cbegin()), "[json.exception.invalid_iterator.204] iterators out of range"); } @@ -1496,15 +1495,15 @@ TEST_CASE("constructors") { { json j = 17u; - CHECK_THROWS_AS(json(j.end(), j.end()), json::invalid_iterator); - CHECK_THROWS_AS(json(j.begin(), j.begin()), json::invalid_iterator); + CHECK_THROWS_AS(json(j.end(), j.end()), json::invalid_iterator&); + CHECK_THROWS_AS(json(j.begin(), j.begin()), json::invalid_iterator&); CHECK_THROWS_WITH(json(j.end(), j.end()), "[json.exception.invalid_iterator.204] iterators out of range"); CHECK_THROWS_WITH(json(j.begin(), j.begin()), "[json.exception.invalid_iterator.204] iterators out of range"); } { json j = 17u; - CHECK_THROWS_AS(json(j.cend(), j.cend()), json::invalid_iterator); - CHECK_THROWS_AS(json(j.cbegin(), j.cbegin()), json::invalid_iterator); + CHECK_THROWS_AS(json(j.cend(), j.cend()), json::invalid_iterator&); + CHECK_THROWS_AS(json(j.cbegin(), j.cbegin()), json::invalid_iterator&); CHECK_THROWS_WITH(json(j.cend(), j.cend()), "[json.exception.invalid_iterator.204] iterators out of range"); CHECK_THROWS_WITH(json(j.cbegin(), j.cbegin()), "[json.exception.invalid_iterator.204] iterators out of range"); } @@ -1514,15 +1513,15 @@ TEST_CASE("constructors") { { json j = 23.42; - CHECK_THROWS_AS(json(j.end(), j.end()), json::invalid_iterator); - CHECK_THROWS_AS(json(j.begin(), j.begin()), json::invalid_iterator); + CHECK_THROWS_AS(json(j.end(), j.end()), json::invalid_iterator&); + CHECK_THROWS_AS(json(j.begin(), j.begin()), json::invalid_iterator&); CHECK_THROWS_WITH(json(j.end(), j.end()), "[json.exception.invalid_iterator.204] iterators out of range"); CHECK_THROWS_WITH(json(j.begin(), j.begin()), "[json.exception.invalid_iterator.204] iterators out of range"); } { json j = 23.42; - CHECK_THROWS_AS(json(j.cend(), j.cend()), json::invalid_iterator); - CHECK_THROWS_AS(json(j.cbegin(), j.cbegin()), json::invalid_iterator); + CHECK_THROWS_AS(json(j.cend(), j.cend()), json::invalid_iterator&); + CHECK_THROWS_AS(json(j.cbegin(), j.cbegin()), json::invalid_iterator&); CHECK_THROWS_WITH(json(j.cend(), j.cend()), "[json.exception.invalid_iterator.204] iterators out of range"); CHECK_THROWS_WITH(json(j.cbegin(), j.cbegin()), "[json.exception.invalid_iterator.204] iterators out of range"); } diff --git a/test/src/unit-conversions.cpp b/test/src/unit-conversions.cpp index fdbc72890..eafac3205 100644 --- a/test/src/unit-conversions.cpp +++ b/test/src/unit-conversions.cpp @@ -35,7 +35,6 @@ using nlohmann::json; #include #include #include -#include #include #include #include @@ -80,13 +79,13 @@ TEST_CASE("value conversion") SECTION("exception in case of a non-object type") { - CHECK_THROWS_AS(json(json::value_t::null).get(), json::type_error); - CHECK_THROWS_AS(json(json::value_t::array).get(), json::type_error); - CHECK_THROWS_AS(json(json::value_t::string).get(), json::type_error); - CHECK_THROWS_AS(json(json::value_t::boolean).get(), json::type_error); - CHECK_THROWS_AS(json(json::value_t::number_integer).get(), json::type_error); - CHECK_THROWS_AS(json(json::value_t::number_unsigned).get(), json::type_error); - CHECK_THROWS_AS(json(json::value_t::number_float).get(), json::type_error); + CHECK_THROWS_AS(json(json::value_t::null).get(), json::type_error&); + CHECK_THROWS_AS(json(json::value_t::array).get(), json::type_error&); + CHECK_THROWS_AS(json(json::value_t::string).get(), json::type_error&); + CHECK_THROWS_AS(json(json::value_t::boolean).get(), json::type_error&); + CHECK_THROWS_AS(json(json::value_t::number_integer).get(), json::type_error&); + CHECK_THROWS_AS(json(json::value_t::number_unsigned).get(), json::type_error&); + CHECK_THROWS_AS(json(json::value_t::number_float).get(), json::type_error&); CHECK_THROWS_WITH(json(json::value_t::null).get(), "[json.exception.type_error.302] type must be object, but is null"); @@ -163,7 +162,7 @@ TEST_CASE("value conversion") std::forward_list a = j.get>(); CHECK(json(a) == j); - CHECK_THROWS_AS(json(json::value_t::null).get>(), json::type_error); + CHECK_THROWS_AS(json(json::value_t::null).get>(), json::type_error&); CHECK_THROWS_WITH(json(json::value_t::null).get>(), "[json.exception.type_error.302] type must be array, but is null"); } @@ -173,7 +172,7 @@ TEST_CASE("value conversion") std::vector a = j.get>(); CHECK(json(a) == j); - CHECK_THROWS_AS(json(json::value_t::null).get>(), json::type_error); + CHECK_THROWS_AS(json(json::value_t::null).get>(), json::type_error&); CHECK_THROWS_WITH(json(json::value_t::null).get>(), "[json.exception.type_error.302] type must be array, but is null"); @@ -182,7 +181,7 @@ TEST_CASE("value conversion") { // making the call to from_json throw in order to check capacity std::vector v; - CHECK_THROWS_AS(nlohmann::from_json(j, v), json::type_error); + CHECK_THROWS_AS(nlohmann::from_json(j, v), json::type_error&); CHECK(v.capacity() == j.size()); // make sure all values are properly copied @@ -214,13 +213,13 @@ TEST_CASE("value conversion") SECTION("exception in case of a non-array type") { - CHECK_THROWS_AS(json(json::value_t::null).get(), json::type_error); - CHECK_THROWS_AS(json(json::value_t::object).get(), json::type_error); - CHECK_THROWS_AS(json(json::value_t::string).get(), json::type_error); - CHECK_THROWS_AS(json(json::value_t::boolean).get(), json::type_error); - CHECK_THROWS_AS(json(json::value_t::number_integer).get(), json::type_error); - CHECK_THROWS_AS(json(json::value_t::number_unsigned).get(), json::type_error); - CHECK_THROWS_AS(json(json::value_t::number_float).get(), json::type_error); + CHECK_THROWS_AS(json(json::value_t::null).get(), json::type_error&); + CHECK_THROWS_AS(json(json::value_t::object).get(), json::type_error&); + CHECK_THROWS_AS(json(json::value_t::string).get(), json::type_error&); + CHECK_THROWS_AS(json(json::value_t::boolean).get(), json::type_error&); + CHECK_THROWS_AS(json(json::value_t::number_integer).get(), json::type_error&); + CHECK_THROWS_AS(json(json::value_t::number_unsigned).get(), json::type_error&); + CHECK_THROWS_AS(json(json::value_t::number_float).get(), json::type_error&); CHECK_THROWS_WITH(json(json::value_t::object).get>(), "[json.exception.type_error.302] type must be array, but is object"); @@ -296,13 +295,13 @@ TEST_CASE("value conversion") SECTION("exception in case of a non-string type") { - CHECK_THROWS_AS(json(json::value_t::null).get(), json::type_error); - CHECK_THROWS_AS(json(json::value_t::object).get(), json::type_error); - CHECK_THROWS_AS(json(json::value_t::array).get(), json::type_error); - CHECK_THROWS_AS(json(json::value_t::boolean).get(), json::type_error); - CHECK_THROWS_AS(json(json::value_t::number_integer).get(), json::type_error); - CHECK_THROWS_AS(json(json::value_t::number_unsigned).get(), json::type_error); - CHECK_THROWS_AS(json(json::value_t::number_float).get(), json::type_error); + CHECK_THROWS_AS(json(json::value_t::null).get(), json::type_error&); + CHECK_THROWS_AS(json(json::value_t::object).get(), json::type_error&); + CHECK_THROWS_AS(json(json::value_t::array).get(), json::type_error&); + CHECK_THROWS_AS(json(json::value_t::boolean).get(), json::type_error&); + CHECK_THROWS_AS(json(json::value_t::number_integer).get(), json::type_error&); + CHECK_THROWS_AS(json(json::value_t::number_unsigned).get(), json::type_error&); + CHECK_THROWS_AS(json(json::value_t::number_float).get(), json::type_error&); CHECK_THROWS_WITH(json(json::value_t::null).get(), "[json.exception.type_error.302] type must be string, but is null"); @@ -358,13 +357,13 @@ TEST_CASE("value conversion") SECTION("exception in case of a non-string type") { - CHECK_THROWS_AS(json(json::value_t::null).get(), json::type_error); - CHECK_THROWS_AS(json(json::value_t::object).get(), json::type_error); - CHECK_THROWS_AS(json(json::value_t::array).get(), json::type_error); - CHECK_THROWS_AS(json(json::value_t::string).get(), json::type_error); - CHECK_THROWS_AS(json(json::value_t::number_integer).get(), json::type_error); - CHECK_THROWS_AS(json(json::value_t::number_unsigned).get(), json::type_error); - CHECK_THROWS_AS(json(json::value_t::number_float).get(), json::type_error); + CHECK_THROWS_AS(json(json::value_t::null).get(), json::type_error&); + CHECK_THROWS_AS(json(json::value_t::object).get(), json::type_error&); + CHECK_THROWS_AS(json(json::value_t::array).get(), json::type_error&); + CHECK_THROWS_AS(json(json::value_t::string).get(), json::type_error&); + CHECK_THROWS_AS(json(json::value_t::number_integer).get(), json::type_error&); + CHECK_THROWS_AS(json(json::value_t::number_unsigned).get(), json::type_error&); + CHECK_THROWS_AS(json(json::value_t::number_float).get(), json::type_error&); CHECK_THROWS_WITH(json(json::value_t::null).get(), "[json.exception.type_error.302] type must be boolean, but is null"); @@ -614,11 +613,11 @@ TEST_CASE("value conversion") SECTION("exception in case of a non-number type") { - CHECK_THROWS_AS(json(json::value_t::null).get(), json::type_error); - CHECK_THROWS_AS(json(json::value_t::object).get(), json::type_error); - CHECK_THROWS_AS(json(json::value_t::array).get(), json::type_error); - CHECK_THROWS_AS(json(json::value_t::string).get(), json::type_error); - CHECK_THROWS_AS(json(json::value_t::boolean).get(), json::type_error); + CHECK_THROWS_AS(json(json::value_t::null).get(), json::type_error&); + CHECK_THROWS_AS(json(json::value_t::object).get(), json::type_error&); + CHECK_THROWS_AS(json(json::value_t::array).get(), json::type_error&); + CHECK_THROWS_AS(json(json::value_t::string).get(), json::type_error&); + CHECK_THROWS_AS(json(json::value_t::boolean).get(), json::type_error&); CHECK_THROWS_WITH(json(json::value_t::null).get(), "[json.exception.type_error.302] type must be number, but is null"); @@ -873,11 +872,11 @@ TEST_CASE("value conversion") SECTION("exception in case of a non-string type") { - CHECK_THROWS_AS(json(json::value_t::null).get(), json::type_error); - CHECK_THROWS_AS(json(json::value_t::object).get(), json::type_error); - CHECK_THROWS_AS(json(json::value_t::array).get(), json::type_error); - CHECK_THROWS_AS(json(json::value_t::string).get(), json::type_error); - CHECK_THROWS_AS(json(json::value_t::boolean).get(), json::type_error); + CHECK_THROWS_AS(json(json::value_t::null).get(), json::type_error&); + CHECK_THROWS_AS(json(json::value_t::object).get(), json::type_error&); + CHECK_THROWS_AS(json(json::value_t::array).get(), json::type_error&); + CHECK_THROWS_AS(json(json::value_t::string).get(), json::type_error&); + CHECK_THROWS_AS(json(json::value_t::boolean).get(), json::type_error&); CHECK_THROWS_WITH(json(json::value_t::null).get(), "[json.exception.type_error.302] type must be number, but is null"); @@ -979,7 +978,7 @@ TEST_CASE("value conversion") SECTION("exception in case of a non-object type") { - CHECK_THROWS_AS((json().get>()), json::type_error); + CHECK_THROWS_AS((json().get>()), json::type_error&); CHECK_THROWS_WITH((json().get>()), "[json.exception.type_error.302] type must be object, but is null"); } } @@ -1081,11 +1080,11 @@ TEST_CASE("value conversion") SECTION("exception in case of a non-object type") { - CHECK_THROWS_AS((json().get>()), json::type_error); - CHECK_THROWS_AS((json().get>()), json::type_error); - CHECK_THROWS_AS((json().get>()), json::type_error); - CHECK_THROWS_AS((json().get>()), json::type_error); - CHECK_THROWS_AS((json().get>()), json::type_error); + CHECK_THROWS_AS((json().get>()), json::type_error&); + CHECK_THROWS_AS((json().get>()), json::type_error&); + CHECK_THROWS_AS((json().get>()), json::type_error&); + CHECK_THROWS_AS((json().get>()), json::type_error&); + CHECK_THROWS_AS((json().get>()), json::type_error&); // does type really must be an array? or it rather must not be null? // that's what I thought when other test like this one broke diff --git a/test/src/unit-deserialization.cpp b/test/src/unit-deserialization.cpp index eb347b59b..2798f1020 100644 --- a/test/src/unit-deserialization.cpp +++ b/test/src/unit-deserialization.cpp @@ -97,7 +97,7 @@ TEST_CASE("deserialization") ss2 << "[\"foo\",1,2,3,false,{\"one\":1}"; ss3 << "[\"foo\",1,2,3,false,{\"one\":1}"; ss4 << "[\"foo\",1,2,3,false,{\"one\":1}"; - CHECK_THROWS_AS(json::parse(ss1), json::parse_error); + CHECK_THROWS_AS(json::parse(ss1), json::parse_error&); CHECK_THROWS_WITH(json::parse(ss2), "[json.exception.parse_error.101] parse error at 29: syntax error - unexpected end of input; expected ']'"); CHECK(not json::accept(ss3)); @@ -110,7 +110,7 @@ TEST_CASE("deserialization") SECTION("string") { json::string_t s = "[\"foo\",1,2,3,false,{\"one\":1}"; - CHECK_THROWS_AS(json::parse(s), json::parse_error); + CHECK_THROWS_AS(json::parse(s), json::parse_error&); CHECK_THROWS_WITH(json::parse(s), "[json.exception.parse_error.101] parse error at 29: syntax error - unexpected end of input; expected ']'"); CHECK(not json::accept(s)); @@ -126,7 +126,7 @@ TEST_CASE("deserialization") ss1 << "[\"foo\",1,2,3,false,{\"one\":1}"; ss2 << "[\"foo\",1,2,3,false,{\"one\":1}"; json j; - CHECK_THROWS_AS(j << ss1, json::parse_error); + CHECK_THROWS_AS(j << ss1, json::parse_error&); CHECK_THROWS_WITH(j << ss2, "[json.exception.parse_error.101] parse error at 29: syntax error - unexpected end of input; expected ']'"); } @@ -137,14 +137,14 @@ TEST_CASE("deserialization") ss1 << "[\"foo\",1,2,3,false,{\"one\":1}"; ss2 << "[\"foo\",1,2,3,false,{\"one\":1}"; json j; - CHECK_THROWS_AS(ss1 >> j, json::parse_error); + CHECK_THROWS_AS(ss1 >> j, json::parse_error&); CHECK_THROWS_WITH(ss2 >> j, "[json.exception.parse_error.101] parse error at 29: syntax error - unexpected end of input; expected ']'"); } SECTION("user-defined string literal") { - CHECK_THROWS_AS("[\"foo\",1,2,3,false,{\"one\":1}"_json, json::parse_error); + CHECK_THROWS_AS("[\"foo\",1,2,3,false,{\"one\":1}"_json, json::parse_error&); CHECK_THROWS_WITH("[\"foo\",1,2,3,false,{\"one\":1}"_json, "[json.exception.parse_error.101] parse error at 29: syntax error - unexpected end of input; expected ']'"); } @@ -205,7 +205,7 @@ TEST_CASE("deserialization") SECTION("empty container") { std::vector v; - CHECK_THROWS_AS(json::parse(v), json::parse_error); + CHECK_THROWS_AS(json::parse(v), json::parse_error&); CHECK(not json::accept(v)); } } @@ -257,7 +257,7 @@ TEST_CASE("deserialization") SECTION("with empty range") { std::vector v; - CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), json::parse_error); + CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), json::parse_error&); CHECK(not json::accept(std::begin(v), std::end(v))); } } @@ -268,7 +268,7 @@ TEST_CASE("deserialization") SECTION("case 1") { uint8_t v[] = {'\"', 'a', 'a', 'a', 'a', 'a', 'a', '\\', 'u'}; - CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), json::parse_error); + CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), json::parse_error&); CHECK(not json::accept(std::begin(v), std::end(v))); json j_error; @@ -279,7 +279,7 @@ TEST_CASE("deserialization") SECTION("case 2") { uint8_t v[] = {'\"', 'a', 'a', 'a', 'a', 'a', 'a', '\\', 'u', '1'}; - CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), json::parse_error); + CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), json::parse_error&); CHECK(not json::accept(std::begin(v), std::end(v))); json j_error; @@ -290,7 +290,7 @@ TEST_CASE("deserialization") SECTION("case 3") { uint8_t v[] = {'\"', 'a', 'a', 'a', 'a', 'a', 'a', '\\', 'u', '1', '1', '1', '1', '1', '1', '1', '1'}; - CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), json::parse_error); + CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), json::parse_error&); CHECK(not json::accept(std::begin(v), std::end(v))); json j_error; @@ -301,7 +301,7 @@ TEST_CASE("deserialization") SECTION("case 4") { uint8_t v[] = {'\"', 'a', 'a', 'a', 'a', 'a', 'a', 'u', '1', '1', '1', '1', '1', '1', '1', '1', '\\'}; - CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), json::parse_error); + CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), json::parse_error&); CHECK(not json::accept(std::begin(v), std::end(v))); json j_error; @@ -312,7 +312,7 @@ TEST_CASE("deserialization") SECTION("case 5") { uint8_t v[] = {'\"', 0x7F, 0xC1}; - CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), json::parse_error); + CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), json::parse_error&); CHECK(not json::accept(std::begin(v), std::end(v))); json j_error; @@ -323,7 +323,7 @@ TEST_CASE("deserialization") SECTION("case 6") { uint8_t v[] = {'\"', 0x7F, 0xDF, 0x7F}; - CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), json::parse_error); + CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), json::parse_error&); CHECK_THROWS_WITH(json::parse(std::begin(v), std::end(v)), "[json.exception.parse_error.101] parse error at 4: syntax error - invalid string: ill-formed UTF-8 byte; last read: '\"\x7f\xdf\x7f'"); CHECK(not json::accept(std::begin(v), std::end(v))); @@ -336,7 +336,7 @@ TEST_CASE("deserialization") SECTION("case 7") { uint8_t v[] = {'\"', 0x7F, 0xDF, 0xC0}; - CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), json::parse_error); + CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), json::parse_error&); CHECK(not json::accept(std::begin(v), std::end(v))); json j_error; @@ -347,7 +347,7 @@ TEST_CASE("deserialization") SECTION("case 8") { uint8_t v[] = {'\"', 0x7F, 0xE0, 0x9F}; - CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), json::parse_error); + CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), json::parse_error&); CHECK(not json::accept(std::begin(v), std::end(v))); json j_error; @@ -358,7 +358,7 @@ TEST_CASE("deserialization") SECTION("case 9") { uint8_t v[] = {'\"', 0x7F, 0xEF, 0xC0}; - CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), json::parse_error); + CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), json::parse_error&); CHECK(not json::accept(std::begin(v), std::end(v))); json j_error; @@ -369,7 +369,7 @@ TEST_CASE("deserialization") SECTION("case 10") { uint8_t v[] = {'\"', 0x7F, 0xED, 0x7F}; - CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), json::parse_error); + CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), json::parse_error&); CHECK(not json::accept(std::begin(v), std::end(v))); json j_error; @@ -380,7 +380,7 @@ TEST_CASE("deserialization") SECTION("case 11") { uint8_t v[] = {'\"', 0x7F, 0xF0, 0x8F}; - CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), json::parse_error); + CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), json::parse_error&); CHECK(not json::accept(std::begin(v), std::end(v))); json j_error; @@ -391,7 +391,7 @@ TEST_CASE("deserialization") SECTION("case 12") { uint8_t v[] = {'\"', 0x7F, 0xF0, 0xC0}; - CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), json::parse_error); + CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), json::parse_error&); CHECK(not json::accept(std::begin(v), std::end(v))); json j_error; @@ -402,7 +402,7 @@ TEST_CASE("deserialization") SECTION("case 13") { uint8_t v[] = {'\"', 0x7F, 0xF3, 0x7F}; - CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), json::parse_error); + CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), json::parse_error&); CHECK(not json::accept(std::begin(v), std::end(v))); json j_error; @@ -413,7 +413,7 @@ TEST_CASE("deserialization") SECTION("case 14") { uint8_t v[] = {'\"', 0x7F, 0xF3, 0xC0}; - CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), json::parse_error); + CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), json::parse_error&); CHECK(not json::accept(std::begin(v), std::end(v))); json j_error; @@ -424,7 +424,7 @@ TEST_CASE("deserialization") SECTION("case 15") { uint8_t v[] = {'\"', 0x7F, 0xF4, 0x7F}; - CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), json::parse_error); + CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), json::parse_error&); CHECK(not json::accept(std::begin(v), std::end(v))); json j_error; @@ -435,7 +435,7 @@ TEST_CASE("deserialization") SECTION("case 16") { uint8_t v[] = {'{', '\"', '\"', ':', '1', '1'}; - CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), json::parse_error); + CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), json::parse_error&); CHECK(not json::accept(std::begin(v), std::end(v))); json j_error; @@ -451,11 +451,11 @@ TEST_CASE("deserialization") SECTION("BOM only") { - CHECK_THROWS_AS(json::parse(bom), json::parse_error); + CHECK_THROWS_AS(json::parse(bom), json::parse_error&); CHECK_THROWS_WITH(json::parse(bom), "[json.exception.parse_error.101] parse error at 1: syntax error - unexpected end of input; expected '[', '{', or a literal"); - CHECK_THROWS_AS(json::parse(std::istringstream(bom)), json::parse_error); + CHECK_THROWS_AS(json::parse(std::istringstream(bom)), json::parse_error&); CHECK_THROWS_WITH(json::parse(std::istringstream(bom)), "[json.exception.parse_error.101] parse error at 1: syntax error - unexpected end of input; expected '[', '{', or a literal"); } @@ -468,22 +468,22 @@ TEST_CASE("deserialization") SECTION("2 byte of BOM") { - CHECK_THROWS_AS(json::parse(bom.substr(0, 2)), json::parse_error); + CHECK_THROWS_AS(json::parse(bom.substr(0, 2)), json::parse_error&); CHECK_THROWS_WITH(json::parse(bom), "[json.exception.parse_error.101] parse error at 1: syntax error - unexpected end of input; expected '[', '{', or a literal"); - CHECK_THROWS_AS(json::parse(std::istringstream(bom.substr(0, 2))), json::parse_error); + CHECK_THROWS_AS(json::parse(std::istringstream(bom.substr(0, 2))), json::parse_error&); CHECK_THROWS_WITH(json::parse(std::istringstream(bom)), "[json.exception.parse_error.101] parse error at 1: syntax error - unexpected end of input; expected '[', '{', or a literal"); } SECTION("1 byte of BOM") { - CHECK_THROWS_AS(json::parse(bom.substr(0, 1)), json::parse_error); + CHECK_THROWS_AS(json::parse(bom.substr(0, 1)), json::parse_error&); CHECK_THROWS_WITH(json::parse(bom), "[json.exception.parse_error.101] parse error at 1: syntax error - unexpected end of input; expected '[', '{', or a literal"); - CHECK_THROWS_AS(json::parse(std::istringstream(bom.substr(0, 1))), json::parse_error); + CHECK_THROWS_AS(json::parse(std::istringstream(bom.substr(0, 1))), json::parse_error&); CHECK_THROWS_WITH(json::parse(std::istringstream(bom)), "[json.exception.parse_error.101] parse error at 1: syntax error - unexpected end of input; expected '[', '{', or a literal"); } @@ -517,8 +517,8 @@ TEST_CASE("deserialization") else { // any variation is an error - CHECK_THROWS_AS(json::parse(s + "null"), json::parse_error); - CHECK_THROWS_AS(json::parse(std::istringstream(s + "null")), json::parse_error); + CHECK_THROWS_AS(json::parse(s + "null"), json::parse_error&); + CHECK_THROWS_AS(json::parse(std::istringstream(s + "null")), json::parse_error&); } } } diff --git a/test/src/unit-element_access1.cpp b/test/src/unit-element_access1.cpp index eb4a92cbd..630b1a5e9 100644 --- a/test/src/unit-element_access1.cpp +++ b/test/src/unit-element_access1.cpp @@ -63,8 +63,8 @@ TEST_CASE("element access 1") SECTION("access outside bounds") { - CHECK_THROWS_AS(j.at(8), json::out_of_range); - CHECK_THROWS_AS(j_const.at(8), json::out_of_range); + CHECK_THROWS_AS(j.at(8), json::out_of_range&); + CHECK_THROWS_AS(j_const.at(8), json::out_of_range&); CHECK_THROWS_WITH(j.at(8), "[json.exception.out_of_range.401] array index 8 is out of range"); @@ -78,8 +78,8 @@ TEST_CASE("element access 1") { json j_nonarray(json::value_t::null); const json j_nonarray_const(j_nonarray); - CHECK_THROWS_AS(j_nonarray.at(0), json::type_error); - CHECK_THROWS_AS(j_nonarray_const.at(0), json::type_error); + CHECK_THROWS_AS(j_nonarray.at(0), json::type_error&); + CHECK_THROWS_AS(j_nonarray_const.at(0), json::type_error&); CHECK_THROWS_WITH(j_nonarray.at(0), "[json.exception.type_error.304] cannot use at() with null"); CHECK_THROWS_WITH(j_nonarray_const.at(0), "[json.exception.type_error.304] cannot use at() with null"); @@ -89,8 +89,8 @@ TEST_CASE("element access 1") { json j_nonarray(json::value_t::boolean); const json j_nonarray_const(j_nonarray); - CHECK_THROWS_AS(j_nonarray.at(0), json::type_error); - CHECK_THROWS_AS(j_nonarray_const.at(0), json::type_error); + CHECK_THROWS_AS(j_nonarray.at(0), json::type_error&); + CHECK_THROWS_AS(j_nonarray_const.at(0), json::type_error&); CHECK_THROWS_WITH(j_nonarray.at(0), "[json.exception.type_error.304] cannot use at() with boolean"); CHECK_THROWS_WITH(j_nonarray_const.at(0), "[json.exception.type_error.304] cannot use at() with boolean"); @@ -100,8 +100,8 @@ TEST_CASE("element access 1") { json j_nonarray(json::value_t::string); const json j_nonarray_const(j_nonarray); - CHECK_THROWS_AS(j_nonarray.at(0), json::type_error); - CHECK_THROWS_AS(j_nonarray_const.at(0), json::type_error); + CHECK_THROWS_AS(j_nonarray.at(0), json::type_error&); + CHECK_THROWS_AS(j_nonarray_const.at(0), json::type_error&); CHECK_THROWS_WITH(j_nonarray.at(0), "[json.exception.type_error.304] cannot use at() with string"); CHECK_THROWS_WITH(j_nonarray_const.at(0), "[json.exception.type_error.304] cannot use at() with string"); @@ -111,8 +111,8 @@ TEST_CASE("element access 1") { json j_nonarray(json::value_t::object); const json j_nonarray_const(j_nonarray); - CHECK_THROWS_AS(j_nonarray.at(0), json::type_error); - CHECK_THROWS_AS(j_nonarray_const.at(0), json::type_error); + CHECK_THROWS_AS(j_nonarray.at(0), json::type_error&); + CHECK_THROWS_AS(j_nonarray_const.at(0), json::type_error&); CHECK_THROWS_WITH(j_nonarray.at(0), "[json.exception.type_error.304] cannot use at() with object"); CHECK_THROWS_WITH(j_nonarray_const.at(0), "[json.exception.type_error.304] cannot use at() with object"); @@ -122,8 +122,8 @@ TEST_CASE("element access 1") { json j_nonarray(json::value_t::number_integer); const json j_nonarray_const(j_nonarray); - CHECK_THROWS_AS(j_nonarray.at(0), json::type_error); - CHECK_THROWS_AS(j_nonarray_const.at(0), json::type_error); + CHECK_THROWS_AS(j_nonarray.at(0), json::type_error&); + CHECK_THROWS_AS(j_nonarray_const.at(0), json::type_error&); CHECK_THROWS_WITH(j_nonarray.at(0), "[json.exception.type_error.304] cannot use at() with number"); CHECK_THROWS_WITH(j_nonarray_const.at(0), "[json.exception.type_error.304] cannot use at() with number"); @@ -133,8 +133,8 @@ TEST_CASE("element access 1") { json j_nonarray(json::value_t::number_unsigned); const json j_nonarray_const(j_nonarray); - CHECK_THROWS_AS(j_nonarray.at(0), json::type_error); - CHECK_THROWS_AS(j_nonarray_const.at(0), json::type_error); + CHECK_THROWS_AS(j_nonarray.at(0), json::type_error&); + CHECK_THROWS_AS(j_nonarray_const.at(0), json::type_error&); CHECK_THROWS_WITH(j_nonarray.at(0), "[json.exception.type_error.304] cannot use at() with number"); CHECK_THROWS_WITH(j_nonarray_const.at(0), "[json.exception.type_error.304] cannot use at() with number"); @@ -144,8 +144,8 @@ TEST_CASE("element access 1") { json j_nonarray(json::value_t::number_float); const json j_nonarray_const(j_nonarray); - CHECK_THROWS_AS(j_nonarray.at(0), json::type_error); - CHECK_THROWS_AS(j_nonarray_const.at(0), json::type_error); + CHECK_THROWS_AS(j_nonarray.at(0), json::type_error&); + CHECK_THROWS_AS(j_nonarray_const.at(0), json::type_error&); CHECK_THROWS_WITH(j_nonarray.at(0), "[json.exception.type_error.304] cannot use at() with number"); CHECK_THROWS_WITH(j_nonarray_const.at(0), "[json.exception.type_error.304] cannot use at() with number"); @@ -193,7 +193,7 @@ TEST_CASE("element access 1") json j_nonarray(json::value_t::null); const json j_nonarray_const(j_nonarray); CHECK_NOTHROW(j_nonarray[0]); - CHECK_THROWS_AS(j_nonarray_const[0], json::type_error); + CHECK_THROWS_AS(j_nonarray_const[0], json::type_error&); CHECK_THROWS_WITH(j_nonarray_const[0], "[json.exception.type_error.305] cannot use operator[] with null"); } @@ -209,8 +209,8 @@ TEST_CASE("element access 1") { json j_nonarray(json::value_t::boolean); const json j_nonarray_const(j_nonarray); - CHECK_THROWS_AS(j_nonarray[0], json::type_error); - CHECK_THROWS_AS(j_nonarray_const[0], json::type_error); + CHECK_THROWS_AS(j_nonarray[0], json::type_error&); + CHECK_THROWS_AS(j_nonarray_const[0], json::type_error&); CHECK_THROWS_WITH(j_nonarray[0], "[json.exception.type_error.305] cannot use operator[] with boolean"); CHECK_THROWS_WITH(j_nonarray_const[0], "[json.exception.type_error.305] cannot use operator[] with boolean"); } @@ -219,8 +219,8 @@ TEST_CASE("element access 1") { json j_nonarray(json::value_t::string); const json j_nonarray_const(j_nonarray); - CHECK_THROWS_AS(j_nonarray[0], json::type_error); - CHECK_THROWS_AS(j_nonarray_const[0], json::type_error); + CHECK_THROWS_AS(j_nonarray[0], json::type_error&); + CHECK_THROWS_AS(j_nonarray_const[0], json::type_error&); CHECK_THROWS_WITH(j_nonarray[0], "[json.exception.type_error.305] cannot use operator[] with string"); CHECK_THROWS_WITH(j_nonarray_const[0], "[json.exception.type_error.305] cannot use operator[] with string"); } @@ -229,8 +229,8 @@ TEST_CASE("element access 1") { json j_nonarray(json::value_t::object); const json j_nonarray_const(j_nonarray); - CHECK_THROWS_AS(j_nonarray[0], json::type_error); - CHECK_THROWS_AS(j_nonarray_const[0], json::type_error); + CHECK_THROWS_AS(j_nonarray[0], json::type_error&); + CHECK_THROWS_AS(j_nonarray_const[0], json::type_error&); CHECK_THROWS_WITH(j_nonarray[0], "[json.exception.type_error.305] cannot use operator[] with object"); CHECK_THROWS_WITH(j_nonarray_const[0], "[json.exception.type_error.305] cannot use operator[] with object"); } @@ -239,8 +239,8 @@ TEST_CASE("element access 1") { json j_nonarray(json::value_t::number_integer); const json j_nonarray_const(j_nonarray); - CHECK_THROWS_AS(j_nonarray[0], json::type_error); - CHECK_THROWS_AS(j_nonarray_const[0], json::type_error); + CHECK_THROWS_AS(j_nonarray[0], json::type_error&); + CHECK_THROWS_AS(j_nonarray_const[0], json::type_error&); CHECK_THROWS_WITH(j_nonarray[0], "[json.exception.type_error.305] cannot use operator[] with number"); CHECK_THROWS_WITH(j_nonarray_const[0], "[json.exception.type_error.305] cannot use operator[] with number"); } @@ -249,8 +249,8 @@ TEST_CASE("element access 1") { json j_nonarray(json::value_t::number_unsigned); const json j_nonarray_const(j_nonarray); - CHECK_THROWS_AS(j_nonarray[0], json::type_error); - CHECK_THROWS_AS(j_nonarray_const[0], json::type_error); + CHECK_THROWS_AS(j_nonarray[0], json::type_error&); + CHECK_THROWS_AS(j_nonarray_const[0], json::type_error&); CHECK_THROWS_WITH(j_nonarray[0], "[json.exception.type_error.305] cannot use operator[] with number"); CHECK_THROWS_WITH(j_nonarray_const[0], "[json.exception.type_error.305] cannot use operator[] with number"); } @@ -259,8 +259,8 @@ TEST_CASE("element access 1") { json j_nonarray(json::value_t::number_float); const json j_nonarray_const(j_nonarray); - CHECK_THROWS_AS(j_nonarray[0], json::type_error); - CHECK_THROWS_AS(j_nonarray_const[0], json::type_error); + CHECK_THROWS_AS(j_nonarray[0], json::type_error&); + CHECK_THROWS_AS(j_nonarray_const[0], json::type_error&); CHECK_THROWS_WITH(j_nonarray[0], "[json.exception.type_error.305] cannot use operator[] with number"); CHECK_THROWS_WITH(j_nonarray_const[0], "[json.exception.type_error.305] cannot use operator[] with number"); } @@ -313,7 +313,7 @@ TEST_CASE("element access 1") } { json jarray = {1, 1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}}; - CHECK_THROWS_AS(jarray.erase(8), json::out_of_range); + CHECK_THROWS_AS(jarray.erase(8), json::out_of_range&); CHECK_THROWS_WITH(jarray.erase(8), "[json.exception.out_of_range.401] array index 8 is out of range"); } @@ -408,10 +408,10 @@ TEST_CASE("element access 1") { json jarray = {1, 1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}}; json jarray2 = {"foo", "bar"}; - CHECK_THROWS_AS(jarray.erase(jarray2.begin()), json::invalid_iterator); - CHECK_THROWS_AS(jarray.erase(jarray.begin(), jarray2.end()), json::invalid_iterator); - CHECK_THROWS_AS(jarray.erase(jarray2.begin(), jarray.end()), json::invalid_iterator); - CHECK_THROWS_AS(jarray.erase(jarray2.begin(), jarray2.end()), json::invalid_iterator); + CHECK_THROWS_AS(jarray.erase(jarray2.begin()), json::invalid_iterator&); + CHECK_THROWS_AS(jarray.erase(jarray.begin(), jarray2.end()), json::invalid_iterator&); + CHECK_THROWS_AS(jarray.erase(jarray2.begin(), jarray.end()), json::invalid_iterator&); + CHECK_THROWS_AS(jarray.erase(jarray2.begin(), jarray2.end()), json::invalid_iterator&); CHECK_THROWS_WITH(jarray.erase(jarray2.begin()), "[json.exception.invalid_iterator.202] iterator does not fit current value"); @@ -425,10 +425,10 @@ TEST_CASE("element access 1") { json jarray = {1, 1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}}; json jarray2 = {"foo", "bar"}; - CHECK_THROWS_AS(jarray.erase(jarray2.cbegin()), json::invalid_iterator); - CHECK_THROWS_AS(jarray.erase(jarray.cbegin(), jarray2.cend()), json::invalid_iterator); - CHECK_THROWS_AS(jarray.erase(jarray2.cbegin(), jarray.cend()), json::invalid_iterator); - CHECK_THROWS_AS(jarray.erase(jarray2.cbegin(), jarray2.cend()), json::invalid_iterator); + CHECK_THROWS_AS(jarray.erase(jarray2.cbegin()), json::invalid_iterator&); + CHECK_THROWS_AS(jarray.erase(jarray.cbegin(), jarray2.cend()), json::invalid_iterator&); + CHECK_THROWS_AS(jarray.erase(jarray2.cbegin(), jarray.cend()), json::invalid_iterator&); + CHECK_THROWS_AS(jarray.erase(jarray2.cbegin(), jarray2.cend()), json::invalid_iterator&); CHECK_THROWS_WITH(jarray.erase(jarray2.cbegin()), "[json.exception.invalid_iterator.202] iterator does not fit current value"); @@ -447,7 +447,7 @@ TEST_CASE("element access 1") SECTION("null") { json j_nonobject(json::value_t::null); - CHECK_THROWS_AS(j_nonobject.erase(0), json::type_error); + CHECK_THROWS_AS(j_nonobject.erase(0), json::type_error&); CHECK_THROWS_WITH(j_nonobject.erase(0), "[json.exception.type_error.307] cannot use erase() with null"); } @@ -455,7 +455,7 @@ TEST_CASE("element access 1") SECTION("boolean") { json j_nonobject(json::value_t::boolean); - CHECK_THROWS_AS(j_nonobject.erase(0), json::type_error); + CHECK_THROWS_AS(j_nonobject.erase(0), json::type_error&); CHECK_THROWS_WITH(j_nonobject.erase(0), "[json.exception.type_error.307] cannot use erase() with boolean"); } @@ -463,7 +463,7 @@ TEST_CASE("element access 1") SECTION("string") { json j_nonobject(json::value_t::string); - CHECK_THROWS_AS(j_nonobject.erase(0), json::type_error); + CHECK_THROWS_AS(j_nonobject.erase(0), json::type_error&); CHECK_THROWS_WITH(j_nonobject.erase(0), "[json.exception.type_error.307] cannot use erase() with string"); } @@ -471,7 +471,7 @@ TEST_CASE("element access 1") SECTION("object") { json j_nonobject(json::value_t::object); - CHECK_THROWS_AS(j_nonobject.erase(0), json::type_error); + CHECK_THROWS_AS(j_nonobject.erase(0), json::type_error&); CHECK_THROWS_WITH(j_nonobject.erase(0), "[json.exception.type_error.307] cannot use erase() with object"); } @@ -479,7 +479,7 @@ TEST_CASE("element access 1") SECTION("number (integer)") { json j_nonobject(json::value_t::number_integer); - CHECK_THROWS_AS(j_nonobject.erase(0), json::type_error); + CHECK_THROWS_AS(j_nonobject.erase(0), json::type_error&); CHECK_THROWS_WITH(j_nonobject.erase(0), "[json.exception.type_error.307] cannot use erase() with number"); } @@ -487,7 +487,7 @@ TEST_CASE("element access 1") SECTION("number (unsigned)") { json j_nonobject(json::value_t::number_unsigned); - CHECK_THROWS_AS(j_nonobject.erase(0), json::type_error); + CHECK_THROWS_AS(j_nonobject.erase(0), json::type_error&); CHECK_THROWS_WITH(j_nonobject.erase(0), "[json.exception.type_error.307] cannot use erase() with number"); } @@ -495,7 +495,7 @@ TEST_CASE("element access 1") SECTION("number (floating-point)") { json j_nonobject(json::value_t::number_float); - CHECK_THROWS_AS(j_nonobject.erase(0), json::type_error); + CHECK_THROWS_AS(j_nonobject.erase(0), json::type_error&); CHECK_THROWS_WITH(j_nonobject.erase(0), "[json.exception.type_error.307] cannot use erase() with number"); } @@ -511,15 +511,15 @@ TEST_CASE("element access 1") { { json j; - CHECK_THROWS_AS(j.front(), json::invalid_iterator); - CHECK_THROWS_AS(j.back(), json::invalid_iterator); + CHECK_THROWS_AS(j.front(), json::invalid_iterator&); + CHECK_THROWS_AS(j.back(), json::invalid_iterator&); CHECK_THROWS_WITH(j.front(), "[json.exception.invalid_iterator.214] cannot get value"); CHECK_THROWS_WITH(j.back(), "[json.exception.invalid_iterator.214] cannot get value"); } { const json j{}; - CHECK_THROWS_AS(j.front(), json::invalid_iterator); - CHECK_THROWS_AS(j.back(), json::invalid_iterator); + CHECK_THROWS_AS(j.front(), json::invalid_iterator&); + CHECK_THROWS_AS(j.back(), json::invalid_iterator&); CHECK_THROWS_WITH(j.front(), "[json.exception.invalid_iterator.214] cannot get value"); CHECK_THROWS_WITH(j.back(), "[json.exception.invalid_iterator.214] cannot get value"); } @@ -602,13 +602,13 @@ TEST_CASE("element access 1") { { json j; - CHECK_THROWS_AS(j.erase(j.begin()), json::type_error); + CHECK_THROWS_AS(j.erase(j.begin()), json::type_error&); CHECK_THROWS_WITH(j.erase(j.begin()), "[json.exception.type_error.307] cannot use erase() with null"); } { json j; - CHECK_THROWS_AS(j.erase(j.cbegin()), json::type_error); + CHECK_THROWS_AS(j.erase(j.cbegin()), json::type_error&); CHECK_THROWS_WITH(j.erase(j.begin()), "[json.exception.type_error.307] cannot use erase() with null"); } @@ -701,13 +701,13 @@ TEST_CASE("element access 1") { { json j = "foo"; - CHECK_THROWS_AS(j.erase(j.end()), json::invalid_iterator); + CHECK_THROWS_AS(j.erase(j.end()), json::invalid_iterator&); CHECK_THROWS_WITH(j.erase(j.end()), "[json.exception.invalid_iterator.205] iterator out of range"); } { json j = "bar"; - CHECK_THROWS_AS(j.erase(j.cend()), json::invalid_iterator); + CHECK_THROWS_AS(j.erase(j.cend()), json::invalid_iterator&); CHECK_THROWS_WITH(j.erase(j.cend()), "[json.exception.invalid_iterator.205] iterator out of range"); } @@ -717,13 +717,13 @@ TEST_CASE("element access 1") { { json j = false; - CHECK_THROWS_AS(j.erase(j.end()), json::invalid_iterator); + CHECK_THROWS_AS(j.erase(j.end()), json::invalid_iterator&); CHECK_THROWS_WITH(j.erase(j.end()), "[json.exception.invalid_iterator.205] iterator out of range"); } { json j = true; - CHECK_THROWS_AS(j.erase(j.cend()), json::invalid_iterator); + CHECK_THROWS_AS(j.erase(j.cend()), json::invalid_iterator&); CHECK_THROWS_WITH(j.erase(j.cend()), "[json.exception.invalid_iterator.205] iterator out of range"); } @@ -733,13 +733,13 @@ TEST_CASE("element access 1") { { json j = 17; - CHECK_THROWS_AS(j.erase(j.end()), json::invalid_iterator); + CHECK_THROWS_AS(j.erase(j.end()), json::invalid_iterator&); CHECK_THROWS_WITH(j.erase(j.end()), "[json.exception.invalid_iterator.205] iterator out of range"); } { json j = 17; - CHECK_THROWS_AS(j.erase(j.cend()), json::invalid_iterator); + CHECK_THROWS_AS(j.erase(j.cend()), json::invalid_iterator&); CHECK_THROWS_WITH(j.erase(j.cend()), "[json.exception.invalid_iterator.205] iterator out of range"); } @@ -749,13 +749,13 @@ TEST_CASE("element access 1") { { json j = 17u; - CHECK_THROWS_AS(j.erase(j.end()), json::invalid_iterator); + CHECK_THROWS_AS(j.erase(j.end()), json::invalid_iterator&); CHECK_THROWS_WITH(j.erase(j.end()), "[json.exception.invalid_iterator.205] iterator out of range"); } { json j = 17u; - CHECK_THROWS_AS(j.erase(j.cend()), json::invalid_iterator); + CHECK_THROWS_AS(j.erase(j.cend()), json::invalid_iterator&); CHECK_THROWS_WITH(j.erase(j.cend()), "[json.exception.invalid_iterator.205] iterator out of range"); } @@ -765,13 +765,13 @@ TEST_CASE("element access 1") { { json j = 23.42; - CHECK_THROWS_AS(j.erase(j.end()), json::invalid_iterator); + CHECK_THROWS_AS(j.erase(j.end()), json::invalid_iterator&); CHECK_THROWS_WITH(j.erase(j.end()), "[json.exception.invalid_iterator.205] iterator out of range"); } { json j = 23.42; - CHECK_THROWS_AS(j.erase(j.cend()), json::invalid_iterator); + CHECK_THROWS_AS(j.erase(j.cend()), json::invalid_iterator&); CHECK_THROWS_WITH(j.erase(j.cend()), "[json.exception.invalid_iterator.205] iterator out of range"); } @@ -784,13 +784,13 @@ TEST_CASE("element access 1") { { json j; - CHECK_THROWS_AS(j.erase(j.begin(), j.end()), json::type_error); + CHECK_THROWS_AS(j.erase(j.begin(), j.end()), json::type_error&); CHECK_THROWS_WITH(j.erase(j.begin(), j.end()), "[json.exception.type_error.307] cannot use erase() with null"); } { json j; - CHECK_THROWS_AS(j.erase(j.cbegin(), j.cend()), json::type_error); + CHECK_THROWS_AS(j.erase(j.cbegin(), j.cend()), json::type_error&); CHECK_THROWS_WITH(j.erase(j.cbegin(), j.cend()), "[json.exception.type_error.307] cannot use erase() with null"); } @@ -883,15 +883,15 @@ TEST_CASE("element access 1") { { json j = "foo"; - CHECK_THROWS_AS(j.erase(j.end(), j.end()), json::invalid_iterator); - CHECK_THROWS_AS(j.erase(j.begin(), j.begin()), json::invalid_iterator); + CHECK_THROWS_AS(j.erase(j.end(), j.end()), json::invalid_iterator&); + CHECK_THROWS_AS(j.erase(j.begin(), j.begin()), json::invalid_iterator&); CHECK_THROWS_WITH(j.erase(j.end(), j.end()), "[json.exception.invalid_iterator.204] iterators out of range"); CHECK_THROWS_WITH(j.erase(j.begin(), j.begin()), "[json.exception.invalid_iterator.204] iterators out of range"); } { json j = "bar"; - CHECK_THROWS_AS(j.erase(j.cend(), j.cend()), json::invalid_iterator); - CHECK_THROWS_AS(j.erase(j.cbegin(), j.cbegin()), json::invalid_iterator); + CHECK_THROWS_AS(j.erase(j.cend(), j.cend()), json::invalid_iterator&); + CHECK_THROWS_AS(j.erase(j.cbegin(), j.cbegin()), json::invalid_iterator&); CHECK_THROWS_WITH(j.erase(j.cend(), j.cend()), "[json.exception.invalid_iterator.204] iterators out of range"); CHECK_THROWS_WITH(j.erase(j.cbegin(), j.cbegin()), "[json.exception.invalid_iterator.204] iterators out of range"); } @@ -901,15 +901,15 @@ TEST_CASE("element access 1") { { json j = false; - CHECK_THROWS_AS(j.erase(j.end(), j.end()), json::invalid_iterator); - CHECK_THROWS_AS(j.erase(j.begin(), j.begin()), json::invalid_iterator); + CHECK_THROWS_AS(j.erase(j.end(), j.end()), json::invalid_iterator&); + CHECK_THROWS_AS(j.erase(j.begin(), j.begin()), json::invalid_iterator&); CHECK_THROWS_WITH(j.erase(j.end(), j.end()), "[json.exception.invalid_iterator.204] iterators out of range"); CHECK_THROWS_WITH(j.erase(j.begin(), j.begin()), "[json.exception.invalid_iterator.204] iterators out of range"); } { json j = true; - CHECK_THROWS_AS(j.erase(j.cend(), j.cend()), json::invalid_iterator); - CHECK_THROWS_AS(j.erase(j.cbegin(), j.cbegin()), json::invalid_iterator); + CHECK_THROWS_AS(j.erase(j.cend(), j.cend()), json::invalid_iterator&); + CHECK_THROWS_AS(j.erase(j.cbegin(), j.cbegin()), json::invalid_iterator&); CHECK_THROWS_WITH(j.erase(j.cend(), j.cend()), "[json.exception.invalid_iterator.204] iterators out of range"); CHECK_THROWS_WITH(j.erase(j.cbegin(), j.cbegin()), "[json.exception.invalid_iterator.204] iterators out of range"); } @@ -919,15 +919,15 @@ TEST_CASE("element access 1") { { json j = 17; - CHECK_THROWS_AS(j.erase(j.end(), j.end()), json::invalid_iterator); - CHECK_THROWS_AS(j.erase(j.begin(), j.begin()), json::invalid_iterator); + CHECK_THROWS_AS(j.erase(j.end(), j.end()), json::invalid_iterator&); + CHECK_THROWS_AS(j.erase(j.begin(), j.begin()), json::invalid_iterator&); CHECK_THROWS_WITH(j.erase(j.end(), j.end()), "[json.exception.invalid_iterator.204] iterators out of range"); CHECK_THROWS_WITH(j.erase(j.begin(), j.begin()), "[json.exception.invalid_iterator.204] iterators out of range"); } { json j = 17; - CHECK_THROWS_AS(j.erase(j.cend(), j.cend()), json::invalid_iterator); - CHECK_THROWS_AS(j.erase(j.cbegin(), j.cbegin()), json::invalid_iterator); + CHECK_THROWS_AS(j.erase(j.cend(), j.cend()), json::invalid_iterator&); + CHECK_THROWS_AS(j.erase(j.cbegin(), j.cbegin()), json::invalid_iterator&); CHECK_THROWS_WITH(j.erase(j.cend(), j.cend()), "[json.exception.invalid_iterator.204] iterators out of range"); CHECK_THROWS_WITH(j.erase(j.cbegin(), j.cbegin()), "[json.exception.invalid_iterator.204] iterators out of range"); } @@ -937,15 +937,15 @@ TEST_CASE("element access 1") { { json j = 17u; - CHECK_THROWS_AS(j.erase(j.end(), j.end()), json::invalid_iterator); - CHECK_THROWS_AS(j.erase(j.begin(), j.begin()), json::invalid_iterator); + CHECK_THROWS_AS(j.erase(j.end(), j.end()), json::invalid_iterator&); + CHECK_THROWS_AS(j.erase(j.begin(), j.begin()), json::invalid_iterator&); CHECK_THROWS_WITH(j.erase(j.end(), j.end()), "[json.exception.invalid_iterator.204] iterators out of range"); CHECK_THROWS_WITH(j.erase(j.begin(), j.begin()), "[json.exception.invalid_iterator.204] iterators out of range"); } { json j = 17u; - CHECK_THROWS_AS(j.erase(j.cend(), j.cend()), json::invalid_iterator); - CHECK_THROWS_AS(j.erase(j.cbegin(), j.cbegin()), json::invalid_iterator); + CHECK_THROWS_AS(j.erase(j.cend(), j.cend()), json::invalid_iterator&); + CHECK_THROWS_AS(j.erase(j.cbegin(), j.cbegin()), json::invalid_iterator&); CHECK_THROWS_WITH(j.erase(j.cend(), j.cend()), "[json.exception.invalid_iterator.204] iterators out of range"); CHECK_THROWS_WITH(j.erase(j.cbegin(), j.cbegin()), "[json.exception.invalid_iterator.204] iterators out of range"); } @@ -955,15 +955,15 @@ TEST_CASE("element access 1") { { json j = 23.42; - CHECK_THROWS_AS(j.erase(j.end(), j.end()), json::invalid_iterator); - CHECK_THROWS_AS(j.erase(j.begin(), j.begin()), json::invalid_iterator); + CHECK_THROWS_AS(j.erase(j.end(), j.end()), json::invalid_iterator&); + CHECK_THROWS_AS(j.erase(j.begin(), j.begin()), json::invalid_iterator&); CHECK_THROWS_WITH(j.erase(j.end(), j.end()), "[json.exception.invalid_iterator.204] iterators out of range"); CHECK_THROWS_WITH(j.erase(j.begin(), j.begin()), "[json.exception.invalid_iterator.204] iterators out of range"); } { json j = 23.42; - CHECK_THROWS_AS(j.erase(j.cend(), j.cend()), json::invalid_iterator); - CHECK_THROWS_AS(j.erase(j.cbegin(), j.cbegin()), json::invalid_iterator); + CHECK_THROWS_AS(j.erase(j.cend(), j.cend()), json::invalid_iterator&); + CHECK_THROWS_AS(j.erase(j.cbegin(), j.cbegin()), json::invalid_iterator&); CHECK_THROWS_WITH(j.erase(j.cend(), j.cend()), "[json.exception.invalid_iterator.204] iterators out of range"); CHECK_THROWS_WITH(j.erase(j.cbegin(), j.cbegin()), "[json.exception.invalid_iterator.204] iterators out of range"); } diff --git a/test/src/unit-element_access2.cpp b/test/src/unit-element_access2.cpp index ec03507e5..5950349bc 100644 --- a/test/src/unit-element_access2.cpp +++ b/test/src/unit-element_access2.cpp @@ -63,8 +63,8 @@ TEST_CASE("element access 2") SECTION("access outside bounds") { - CHECK_THROWS_AS(j.at("foo"), json::out_of_range); - CHECK_THROWS_AS(j_const.at("foo"), json::out_of_range); + CHECK_THROWS_AS(j.at("foo"), json::out_of_range&); + CHECK_THROWS_AS(j_const.at("foo"), json::out_of_range&); CHECK_THROWS_WITH(j.at("foo"), "[json.exception.out_of_range.403] key 'foo' not found"); CHECK_THROWS_WITH(j_const.at("foo"), @@ -77,8 +77,8 @@ TEST_CASE("element access 2") { json j_nonobject(json::value_t::null); const json j_nonobject_const(j_nonobject); - CHECK_THROWS_AS(j_nonobject.at("foo"), json::type_error); - CHECK_THROWS_AS(j_nonobject_const.at("foo"), json::type_error); + CHECK_THROWS_AS(j_nonobject.at("foo"), json::type_error&); + CHECK_THROWS_AS(j_nonobject_const.at("foo"), json::type_error&); CHECK_THROWS_WITH(j_nonobject.at("foo"), "[json.exception.type_error.304] cannot use at() with null"); CHECK_THROWS_WITH(j_nonobject_const.at("foo"), "[json.exception.type_error.304] cannot use at() with null"); } @@ -87,8 +87,8 @@ TEST_CASE("element access 2") { json j_nonobject(json::value_t::boolean); const json j_nonobject_const(j_nonobject); - CHECK_THROWS_AS(j_nonobject.at("foo"), json::type_error); - CHECK_THROWS_AS(j_nonobject_const.at("foo"), json::type_error); + CHECK_THROWS_AS(j_nonobject.at("foo"), json::type_error&); + CHECK_THROWS_AS(j_nonobject_const.at("foo"), json::type_error&); CHECK_THROWS_WITH(j_nonobject.at("foo"), "[json.exception.type_error.304] cannot use at() with boolean"); CHECK_THROWS_WITH(j_nonobject_const.at("foo"), "[json.exception.type_error.304] cannot use at() with boolean"); } @@ -97,8 +97,8 @@ TEST_CASE("element access 2") { json j_nonobject(json::value_t::string); const json j_nonobject_const(j_nonobject); - CHECK_THROWS_AS(j_nonobject.at("foo"), json::type_error); - CHECK_THROWS_AS(j_nonobject_const.at("foo"), json::type_error); + CHECK_THROWS_AS(j_nonobject.at("foo"), json::type_error&); + CHECK_THROWS_AS(j_nonobject_const.at("foo"), json::type_error&); CHECK_THROWS_WITH(j_nonobject.at("foo"), "[json.exception.type_error.304] cannot use at() with string"); CHECK_THROWS_WITH(j_nonobject_const.at("foo"), "[json.exception.type_error.304] cannot use at() with string"); } @@ -107,8 +107,8 @@ TEST_CASE("element access 2") { json j_nonobject(json::value_t::array); const json j_nonobject_const(j_nonobject); - CHECK_THROWS_AS(j_nonobject.at("foo"), json::type_error); - CHECK_THROWS_AS(j_nonobject_const.at("foo"), json::type_error); + CHECK_THROWS_AS(j_nonobject.at("foo"), json::type_error&); + CHECK_THROWS_AS(j_nonobject_const.at("foo"), json::type_error&); CHECK_THROWS_WITH(j_nonobject.at("foo"), "[json.exception.type_error.304] cannot use at() with array"); CHECK_THROWS_WITH(j_nonobject_const.at("foo"), "[json.exception.type_error.304] cannot use at() with array"); } @@ -117,8 +117,8 @@ TEST_CASE("element access 2") { json j_nonobject(json::value_t::number_integer); const json j_nonobject_const(j_nonobject); - CHECK_THROWS_AS(j_nonobject.at("foo"), json::type_error); - CHECK_THROWS_AS(j_nonobject_const.at("foo"), json::type_error); + CHECK_THROWS_AS(j_nonobject.at("foo"), json::type_error&); + CHECK_THROWS_AS(j_nonobject_const.at("foo"), json::type_error&); CHECK_THROWS_WITH(j_nonobject.at("foo"), "[json.exception.type_error.304] cannot use at() with number"); CHECK_THROWS_WITH(j_nonobject_const.at("foo"), "[json.exception.type_error.304] cannot use at() with number"); } @@ -127,8 +127,8 @@ TEST_CASE("element access 2") { json j_nonobject(json::value_t::number_unsigned); const json j_nonobject_const(j_nonobject); - CHECK_THROWS_AS(j_nonobject.at("foo"), json::type_error); - CHECK_THROWS_AS(j_nonobject_const.at("foo"), json::type_error); + CHECK_THROWS_AS(j_nonobject.at("foo"), json::type_error&); + CHECK_THROWS_AS(j_nonobject_const.at("foo"), json::type_error&); CHECK_THROWS_WITH(j_nonobject.at("foo"), "[json.exception.type_error.304] cannot use at() with number"); CHECK_THROWS_WITH(j_nonobject_const.at("foo"), "[json.exception.type_error.304] cannot use at() with number"); } @@ -137,8 +137,8 @@ TEST_CASE("element access 2") { json j_nonobject(json::value_t::number_float); const json j_nonobject_const(j_nonobject); - CHECK_THROWS_AS(j_nonobject.at("foo"), json::type_error); - CHECK_THROWS_AS(j_nonobject_const.at("foo"), json::type_error); + CHECK_THROWS_AS(j_nonobject.at("foo"), json::type_error&); + CHECK_THROWS_AS(j_nonobject_const.at("foo"), json::type_error&); CHECK_THROWS_WITH(j_nonobject.at("foo"), "[json.exception.type_error.304] cannot use at() with number"); CHECK_THROWS_WITH(j_nonobject_const.at("foo"), "[json.exception.type_error.304] cannot use at() with number"); } @@ -202,8 +202,8 @@ TEST_CASE("element access 2") { json j_nonobject(json::value_t::null); const json j_nonobject_const(j_nonobject); - CHECK_THROWS_AS(j_nonobject.value("foo", 1), json::type_error); - CHECK_THROWS_AS(j_nonobject_const.value("foo", 1), json::type_error); + CHECK_THROWS_AS(j_nonobject.value("foo", 1), json::type_error&); + CHECK_THROWS_AS(j_nonobject_const.value("foo", 1), json::type_error&); CHECK_THROWS_WITH(j_nonobject.value("foo", 1), "[json.exception.type_error.306] cannot use value() with null"); CHECK_THROWS_WITH(j_nonobject_const.value("foo", 1), @@ -214,8 +214,8 @@ TEST_CASE("element access 2") { json j_nonobject(json::value_t::boolean); const json j_nonobject_const(j_nonobject); - CHECK_THROWS_AS(j_nonobject.value("foo", 1), json::type_error); - CHECK_THROWS_AS(j_nonobject_const.value("foo", 1), json::type_error); + CHECK_THROWS_AS(j_nonobject.value("foo", 1), json::type_error&); + CHECK_THROWS_AS(j_nonobject_const.value("foo", 1), json::type_error&); CHECK_THROWS_WITH(j_nonobject.value("foo", 1), "[json.exception.type_error.306] cannot use value() with boolean"); CHECK_THROWS_WITH(j_nonobject_const.value("foo", 1), @@ -226,8 +226,8 @@ TEST_CASE("element access 2") { json j_nonobject(json::value_t::string); const json j_nonobject_const(j_nonobject); - CHECK_THROWS_AS(j_nonobject.value("foo", 1), json::type_error); - CHECK_THROWS_AS(j_nonobject_const.value("foo", 1), json::type_error); + CHECK_THROWS_AS(j_nonobject.value("foo", 1), json::type_error&); + CHECK_THROWS_AS(j_nonobject_const.value("foo", 1), json::type_error&); CHECK_THROWS_WITH(j_nonobject.value("foo", 1), "[json.exception.type_error.306] cannot use value() with string"); CHECK_THROWS_WITH(j_nonobject_const.value("foo", 1), @@ -238,8 +238,8 @@ TEST_CASE("element access 2") { json j_nonobject(json::value_t::array); const json j_nonobject_const(j_nonobject); - CHECK_THROWS_AS(j_nonobject.value("foo", 1), json::type_error); - CHECK_THROWS_AS(j_nonobject_const.value("foo", 1), json::type_error); + CHECK_THROWS_AS(j_nonobject.value("foo", 1), json::type_error&); + CHECK_THROWS_AS(j_nonobject_const.value("foo", 1), json::type_error&); CHECK_THROWS_WITH(j_nonobject.value("foo", 1), "[json.exception.type_error.306] cannot use value() with array"); CHECK_THROWS_WITH(j_nonobject_const.value("foo", 1), @@ -250,8 +250,8 @@ TEST_CASE("element access 2") { json j_nonobject(json::value_t::number_integer); const json j_nonobject_const(j_nonobject); - CHECK_THROWS_AS(j_nonobject.value("foo", 1), json::type_error); - CHECK_THROWS_AS(j_nonobject_const.value("foo", 1), json::type_error); + CHECK_THROWS_AS(j_nonobject.value("foo", 1), json::type_error&); + CHECK_THROWS_AS(j_nonobject_const.value("foo", 1), json::type_error&); CHECK_THROWS_WITH(j_nonobject.value("foo", 1), "[json.exception.type_error.306] cannot use value() with number"); CHECK_THROWS_WITH(j_nonobject_const.value("foo", 1), @@ -262,8 +262,8 @@ TEST_CASE("element access 2") { json j_nonobject(json::value_t::number_unsigned); const json j_nonobject_const(j_nonobject); - CHECK_THROWS_AS(j_nonobject.value("foo", 1), json::type_error); - CHECK_THROWS_AS(j_nonobject_const.value("foo", 1), json::type_error); + CHECK_THROWS_AS(j_nonobject.value("foo", 1), json::type_error&); + CHECK_THROWS_AS(j_nonobject_const.value("foo", 1), json::type_error&); CHECK_THROWS_WITH(j_nonobject.value("foo", 1), "[json.exception.type_error.306] cannot use value() with number"); CHECK_THROWS_WITH(j_nonobject_const.value("foo", 1), @@ -274,8 +274,8 @@ TEST_CASE("element access 2") { json j_nonobject(json::value_t::number_float); const json j_nonobject_const(j_nonobject); - CHECK_THROWS_AS(j_nonobject.value("foo", 1), json::type_error); - CHECK_THROWS_AS(j_nonobject_const.value("foo", 1), json::type_error); + CHECK_THROWS_AS(j_nonobject.value("foo", 1), json::type_error&); + CHECK_THROWS_AS(j_nonobject_const.value("foo", 1), json::type_error&); CHECK_THROWS_WITH(j_nonobject.value("foo", 1), "[json.exception.type_error.306] cannot use value() with number"); CHECK_THROWS_WITH(j_nonobject_const.value("foo", 1), @@ -320,8 +320,8 @@ TEST_CASE("element access 2") { json j_nonobject(json::value_t::null); const json j_nonobject_const(j_nonobject); - CHECK_THROWS_AS(j_nonobject.value("/foo"_json_pointer, 1), json::type_error); - CHECK_THROWS_AS(j_nonobject_const.value("/foo"_json_pointer, 1), json::type_error); + CHECK_THROWS_AS(j_nonobject.value("/foo"_json_pointer, 1), json::type_error&); + CHECK_THROWS_AS(j_nonobject_const.value("/foo"_json_pointer, 1), json::type_error&); CHECK_THROWS_WITH(j_nonobject.value("/foo"_json_pointer, 1), "[json.exception.type_error.306] cannot use value() with null"); CHECK_THROWS_WITH(j_nonobject_const.value("/foo"_json_pointer, 1), @@ -332,8 +332,8 @@ TEST_CASE("element access 2") { json j_nonobject(json::value_t::boolean); const json j_nonobject_const(j_nonobject); - CHECK_THROWS_AS(j_nonobject.value("/foo"_json_pointer, 1), json::type_error); - CHECK_THROWS_AS(j_nonobject_const.value("/foo"_json_pointer, 1), json::type_error); + CHECK_THROWS_AS(j_nonobject.value("/foo"_json_pointer, 1), json::type_error&); + CHECK_THROWS_AS(j_nonobject_const.value("/foo"_json_pointer, 1), json::type_error&); CHECK_THROWS_WITH(j_nonobject.value("/foo"_json_pointer, 1), "[json.exception.type_error.306] cannot use value() with boolean"); CHECK_THROWS_WITH(j_nonobject_const.value("/foo"_json_pointer, 1), @@ -344,8 +344,8 @@ TEST_CASE("element access 2") { json j_nonobject(json::value_t::string); const json j_nonobject_const(j_nonobject); - CHECK_THROWS_AS(j_nonobject.value("/foo"_json_pointer, 1), json::type_error); - CHECK_THROWS_AS(j_nonobject_const.value("/foo"_json_pointer, 1), json::type_error); + CHECK_THROWS_AS(j_nonobject.value("/foo"_json_pointer, 1), json::type_error&); + CHECK_THROWS_AS(j_nonobject_const.value("/foo"_json_pointer, 1), json::type_error&); CHECK_THROWS_WITH(j_nonobject.value("/foo"_json_pointer, 1), "[json.exception.type_error.306] cannot use value() with string"); CHECK_THROWS_WITH(j_nonobject_const.value("/foo"_json_pointer, 1), @@ -356,8 +356,8 @@ TEST_CASE("element access 2") { json j_nonobject(json::value_t::array); const json j_nonobject_const(j_nonobject); - CHECK_THROWS_AS(j_nonobject.value("/foo"_json_pointer, 1), json::type_error); - CHECK_THROWS_AS(j_nonobject_const.value("/foo"_json_pointer, 1), json::type_error); + CHECK_THROWS_AS(j_nonobject.value("/foo"_json_pointer, 1), json::type_error&); + CHECK_THROWS_AS(j_nonobject_const.value("/foo"_json_pointer, 1), json::type_error&); CHECK_THROWS_WITH(j_nonobject.value("/foo"_json_pointer, 1), "[json.exception.type_error.306] cannot use value() with array"); CHECK_THROWS_WITH(j_nonobject_const.value("/foo"_json_pointer, 1), @@ -368,8 +368,8 @@ TEST_CASE("element access 2") { json j_nonobject(json::value_t::number_integer); const json j_nonobject_const(j_nonobject); - CHECK_THROWS_AS(j_nonobject.value("/foo"_json_pointer, 1), json::type_error); - CHECK_THROWS_AS(j_nonobject_const.value("/foo"_json_pointer, 1), json::type_error); + CHECK_THROWS_AS(j_nonobject.value("/foo"_json_pointer, 1), json::type_error&); + CHECK_THROWS_AS(j_nonobject_const.value("/foo"_json_pointer, 1), json::type_error&); CHECK_THROWS_WITH(j_nonobject.value("/foo"_json_pointer, 1), "[json.exception.type_error.306] cannot use value() with number"); CHECK_THROWS_WITH(j_nonobject_const.value("/foo"_json_pointer, 1), @@ -380,8 +380,8 @@ TEST_CASE("element access 2") { json j_nonobject(json::value_t::number_unsigned); const json j_nonobject_const(j_nonobject); - CHECK_THROWS_AS(j_nonobject.value("/foo"_json_pointer, 1), json::type_error); - CHECK_THROWS_AS(j_nonobject_const.value("/foo"_json_pointer, 1), json::type_error); + CHECK_THROWS_AS(j_nonobject.value("/foo"_json_pointer, 1), json::type_error&); + CHECK_THROWS_AS(j_nonobject_const.value("/foo"_json_pointer, 1), json::type_error&); CHECK_THROWS_WITH(j_nonobject.value("/foo"_json_pointer, 1), "[json.exception.type_error.306] cannot use value() with number"); CHECK_THROWS_WITH(j_nonobject_const.value("/foo"_json_pointer, 1), @@ -392,8 +392,8 @@ TEST_CASE("element access 2") { json j_nonobject(json::value_t::number_float); const json j_nonobject_const(j_nonobject); - CHECK_THROWS_AS(j_nonobject.value("/foo"_json_pointer, 1), json::type_error); - CHECK_THROWS_AS(j_nonobject_const.value("/foo"_json_pointer, 1), json::type_error); + CHECK_THROWS_AS(j_nonobject.value("/foo"_json_pointer, 1), json::type_error&); + CHECK_THROWS_AS(j_nonobject_const.value("/foo"_json_pointer, 1), json::type_error&); CHECK_THROWS_WITH(j_nonobject.value("/foo"_json_pointer, 1), "[json.exception.type_error.306] cannot use value() with number"); CHECK_THROWS_WITH(j_nonobject_const.value("/foo"_json_pointer, 1), @@ -472,8 +472,8 @@ TEST_CASE("element access 2") const json j_const_nonobject(j_nonobject); CHECK_NOTHROW(j_nonobject["foo"]); CHECK_NOTHROW(j_nonobject2[json::object_t::key_type("foo")]); - CHECK_THROWS_AS(j_const_nonobject["foo"], json::type_error); - CHECK_THROWS_AS(j_const_nonobject[json::object_t::key_type("foo")], json::type_error); + CHECK_THROWS_AS(j_const_nonobject["foo"], json::type_error&); + CHECK_THROWS_AS(j_const_nonobject[json::object_t::key_type("foo")], json::type_error&); CHECK_THROWS_WITH(j_const_nonobject["foo"], "[json.exception.type_error.305] cannot use operator[] with null"); CHECK_THROWS_WITH(j_const_nonobject[json::object_t::key_type("foo")], "[json.exception.type_error.305] cannot use operator[] with null"); @@ -483,10 +483,10 @@ TEST_CASE("element access 2") { json j_nonobject(json::value_t::boolean); const json j_const_nonobject(j_nonobject); - CHECK_THROWS_AS(j_nonobject["foo"], json::type_error); - CHECK_THROWS_AS(j_nonobject[json::object_t::key_type("foo")], json::type_error); - CHECK_THROWS_AS(j_const_nonobject["foo"], json::type_error); - CHECK_THROWS_AS(j_const_nonobject[json::object_t::key_type("foo")], json::type_error); + CHECK_THROWS_AS(j_nonobject["foo"], json::type_error&); + CHECK_THROWS_AS(j_nonobject[json::object_t::key_type("foo")], json::type_error&); + CHECK_THROWS_AS(j_const_nonobject["foo"], json::type_error&); + CHECK_THROWS_AS(j_const_nonobject[json::object_t::key_type("foo")], json::type_error&); CHECK_THROWS_WITH(j_nonobject["foo"], "[json.exception.type_error.305] cannot use operator[] with boolean"); CHECK_THROWS_WITH(j_nonobject[json::object_t::key_type("foo")], @@ -501,10 +501,10 @@ TEST_CASE("element access 2") { json j_nonobject(json::value_t::string); const json j_const_nonobject(j_nonobject); - CHECK_THROWS_AS(j_nonobject["foo"], json::type_error); - CHECK_THROWS_AS(j_nonobject[json::object_t::key_type("foo")], json::type_error); - CHECK_THROWS_AS(j_const_nonobject["foo"], json::type_error); - CHECK_THROWS_AS(j_const_nonobject[json::object_t::key_type("foo")], json::type_error); + CHECK_THROWS_AS(j_nonobject["foo"], json::type_error&); + CHECK_THROWS_AS(j_nonobject[json::object_t::key_type("foo")], json::type_error&); + CHECK_THROWS_AS(j_const_nonobject["foo"], json::type_error&); + CHECK_THROWS_AS(j_const_nonobject[json::object_t::key_type("foo")], json::type_error&); CHECK_THROWS_WITH(j_nonobject["foo"], "[json.exception.type_error.305] cannot use operator[] with string"); CHECK_THROWS_WITH(j_nonobject[json::object_t::key_type("foo")], @@ -519,10 +519,10 @@ TEST_CASE("element access 2") { json j_nonobject(json::value_t::array); const json j_const_nonobject(j_nonobject); - CHECK_THROWS_AS(j_nonobject["foo"], json::type_error); - CHECK_THROWS_AS(j_nonobject[json::object_t::key_type("foo")], json::type_error); - CHECK_THROWS_AS(j_const_nonobject["foo"], json::type_error); - CHECK_THROWS_AS(j_const_nonobject[json::object_t::key_type("foo")], json::type_error); + CHECK_THROWS_AS(j_nonobject["foo"], json::type_error&); + CHECK_THROWS_AS(j_nonobject[json::object_t::key_type("foo")], json::type_error&); + CHECK_THROWS_AS(j_const_nonobject["foo"], json::type_error&); + CHECK_THROWS_AS(j_const_nonobject[json::object_t::key_type("foo")], json::type_error&); CHECK_THROWS_WITH(j_nonobject["foo"], "[json.exception.type_error.305] cannot use operator[] with array"); CHECK_THROWS_WITH(j_nonobject[json::object_t::key_type("foo")], "[json.exception.type_error.305] cannot use operator[] with array"); @@ -536,10 +536,10 @@ TEST_CASE("element access 2") { json j_nonobject(json::value_t::number_integer); const json j_const_nonobject(j_nonobject); - CHECK_THROWS_AS(j_nonobject["foo"], json::type_error); - CHECK_THROWS_AS(j_nonobject[json::object_t::key_type("foo")], json::type_error); - CHECK_THROWS_AS(j_const_nonobject["foo"], json::type_error); - CHECK_THROWS_AS(j_const_nonobject[json::object_t::key_type("foo")], json::type_error); + CHECK_THROWS_AS(j_nonobject["foo"], json::type_error&); + CHECK_THROWS_AS(j_nonobject[json::object_t::key_type("foo")], json::type_error&); + CHECK_THROWS_AS(j_const_nonobject["foo"], json::type_error&); + CHECK_THROWS_AS(j_const_nonobject[json::object_t::key_type("foo")], json::type_error&); CHECK_THROWS_WITH(j_nonobject["foo"], "[json.exception.type_error.305] cannot use operator[] with number"); CHECK_THROWS_WITH(j_nonobject[json::object_t::key_type("foo")], @@ -554,10 +554,10 @@ TEST_CASE("element access 2") { json j_nonobject(json::value_t::number_unsigned); const json j_const_nonobject(j_nonobject); - CHECK_THROWS_AS(j_nonobject["foo"], json::type_error); - CHECK_THROWS_AS(j_nonobject[json::object_t::key_type("foo")], json::type_error); - CHECK_THROWS_AS(j_const_nonobject["foo"], json::type_error); - CHECK_THROWS_AS(j_const_nonobject[json::object_t::key_type("foo")], json::type_error); + CHECK_THROWS_AS(j_nonobject["foo"], json::type_error&); + CHECK_THROWS_AS(j_nonobject[json::object_t::key_type("foo")], json::type_error&); + CHECK_THROWS_AS(j_const_nonobject["foo"], json::type_error&); + CHECK_THROWS_AS(j_const_nonobject[json::object_t::key_type("foo")], json::type_error&); CHECK_THROWS_WITH(j_nonobject["foo"], "[json.exception.type_error.305] cannot use operator[] with number"); CHECK_THROWS_WITH(j_nonobject[json::object_t::key_type("foo")], @@ -572,10 +572,10 @@ TEST_CASE("element access 2") { json j_nonobject(json::value_t::number_float); const json j_const_nonobject(j_nonobject); - CHECK_THROWS_AS(j_nonobject["foo"], json::type_error); - CHECK_THROWS_AS(j_nonobject[json::object_t::key_type("foo")], json::type_error); - CHECK_THROWS_AS(j_const_nonobject["foo"], json::type_error); - CHECK_THROWS_AS(j_const_nonobject[json::object_t::key_type("foo")], json::type_error); + CHECK_THROWS_AS(j_nonobject["foo"], json::type_error&); + CHECK_THROWS_AS(j_nonobject[json::object_t::key_type("foo")], json::type_error&); + CHECK_THROWS_AS(j_const_nonobject["foo"], json::type_error&); + CHECK_THROWS_AS(j_const_nonobject[json::object_t::key_type("foo")], json::type_error&); CHECK_THROWS_WITH(j_nonobject["foo"], "[json.exception.type_error.305] cannot use operator[] with number"); CHECK_THROWS_WITH(j_nonobject[json::object_t::key_type("foo")], @@ -722,10 +722,10 @@ TEST_CASE("element access 2") { json jobject = {{"a", "a"}, {"b", 1}, {"c", 17u}, {"d", false}, {"e", true}}; json jobject2 = {{"a", "a"}, {"b", 1}, {"c", 17u}}; - CHECK_THROWS_AS(jobject.erase(jobject2.begin()), json::invalid_iterator); - CHECK_THROWS_AS(jobject.erase(jobject.begin(), jobject2.end()), json::invalid_iterator); - CHECK_THROWS_AS(jobject.erase(jobject2.begin(), jobject.end()), json::invalid_iterator); - CHECK_THROWS_AS(jobject.erase(jobject2.begin(), jobject2.end()), json::invalid_iterator); + CHECK_THROWS_AS(jobject.erase(jobject2.begin()), json::invalid_iterator&); + CHECK_THROWS_AS(jobject.erase(jobject.begin(), jobject2.end()), json::invalid_iterator&); + CHECK_THROWS_AS(jobject.erase(jobject2.begin(), jobject.end()), json::invalid_iterator&); + CHECK_THROWS_AS(jobject.erase(jobject2.begin(), jobject2.end()), json::invalid_iterator&); CHECK_THROWS_WITH(jobject.erase(jobject2.begin()), "[json.exception.invalid_iterator.202] iterator does not fit current value"); CHECK_THROWS_WITH(jobject.erase(jobject.begin(), jobject2.end()), @@ -738,10 +738,10 @@ TEST_CASE("element access 2") { json jobject = {{"a", "a"}, {"b", 1}, {"c", 17u}, {"d", false}, {"e", true}}; json jobject2 = {{"a", "a"}, {"b", 1}, {"c", 17u}}; - CHECK_THROWS_AS(jobject.erase(jobject2.cbegin()), json::invalid_iterator); - CHECK_THROWS_AS(jobject.erase(jobject.cbegin(), jobject2.cend()), json::invalid_iterator); - CHECK_THROWS_AS(jobject.erase(jobject2.cbegin(), jobject.cend()), json::invalid_iterator); - CHECK_THROWS_AS(jobject.erase(jobject2.cbegin(), jobject2.cend()), json::invalid_iterator); + CHECK_THROWS_AS(jobject.erase(jobject2.cbegin()), json::invalid_iterator&); + CHECK_THROWS_AS(jobject.erase(jobject.cbegin(), jobject2.cend()), json::invalid_iterator&); + CHECK_THROWS_AS(jobject.erase(jobject2.cbegin(), jobject.cend()), json::invalid_iterator&); + CHECK_THROWS_AS(jobject.erase(jobject2.cbegin(), jobject2.cend()), json::invalid_iterator&); CHECK_THROWS_WITH(jobject.erase(jobject2.cbegin()), "[json.exception.invalid_iterator.202] iterator does not fit current value"); CHECK_THROWS_WITH(jobject.erase(jobject.cbegin(), jobject2.cend()), @@ -759,7 +759,7 @@ TEST_CASE("element access 2") SECTION("null") { json j_nonobject(json::value_t::null); - CHECK_THROWS_AS(j_nonobject.erase("foo"), json::type_error); + CHECK_THROWS_AS(j_nonobject.erase("foo"), json::type_error&); CHECK_THROWS_WITH(j_nonobject.erase("foo"), "[json.exception.type_error.307] cannot use erase() with null"); } @@ -767,7 +767,7 @@ TEST_CASE("element access 2") SECTION("boolean") { json j_nonobject(json::value_t::boolean); - CHECK_THROWS_AS(j_nonobject.erase("foo"), json::type_error); + CHECK_THROWS_AS(j_nonobject.erase("foo"), json::type_error&); CHECK_THROWS_WITH(j_nonobject.erase("foo"), "[json.exception.type_error.307] cannot use erase() with boolean"); } @@ -775,7 +775,7 @@ TEST_CASE("element access 2") SECTION("string") { json j_nonobject(json::value_t::string); - CHECK_THROWS_AS(j_nonobject.erase("foo"), json::type_error); + CHECK_THROWS_AS(j_nonobject.erase("foo"), json::type_error&); CHECK_THROWS_WITH(j_nonobject.erase("foo"), "[json.exception.type_error.307] cannot use erase() with string"); } @@ -783,7 +783,7 @@ TEST_CASE("element access 2") SECTION("array") { json j_nonobject(json::value_t::array); - CHECK_THROWS_AS(j_nonobject.erase("foo"), json::type_error); + CHECK_THROWS_AS(j_nonobject.erase("foo"), json::type_error&); CHECK_THROWS_WITH(j_nonobject.erase("foo"), "[json.exception.type_error.307] cannot use erase() with array"); } @@ -791,7 +791,7 @@ TEST_CASE("element access 2") SECTION("number (integer)") { json j_nonobject(json::value_t::number_integer); - CHECK_THROWS_AS(j_nonobject.erase("foo"), json::type_error); + CHECK_THROWS_AS(j_nonobject.erase("foo"), json::type_error&); CHECK_THROWS_WITH(j_nonobject.erase("foo"), "[json.exception.type_error.307] cannot use erase() with number"); } @@ -799,7 +799,7 @@ TEST_CASE("element access 2") SECTION("number (floating-point)") { json j_nonobject(json::value_t::number_float); - CHECK_THROWS_AS(j_nonobject.erase("foo"), json::type_error); + CHECK_THROWS_AS(j_nonobject.erase("foo"), json::type_error&); CHECK_THROWS_WITH(j_nonobject.erase("foo"), "[json.exception.type_error.307] cannot use erase() with number"); } diff --git a/test/src/unit-iterators1.cpp b/test/src/unit-iterators1.cpp index c707b2d9f..66ffed225 100644 --- a/test/src/unit-iterators1.cpp +++ b/test/src/unit-iterators1.cpp @@ -337,19 +337,19 @@ TEST_CASE("iterators 1") { auto it = j.begin(); auto cit = j_const.cbegin(); - CHECK_THROWS_AS(it.key(), json::invalid_iterator); + CHECK_THROWS_AS(it.key(), json::invalid_iterator&); CHECK_THROWS_WITH(it.key(), "[json.exception.invalid_iterator.207] cannot use key() for non-object iterators"); CHECK(it.value() == json(true)); - CHECK_THROWS_AS(cit.key(), json::invalid_iterator); + CHECK_THROWS_AS(cit.key(), json::invalid_iterator&); CHECK_THROWS_WITH(cit.key(), "[json.exception.invalid_iterator.207] cannot use key() for non-object iterators"); CHECK(cit.value() == json(true)); auto rit = j.rend(); auto crit = j.crend(); - CHECK_THROWS_AS(rit.key(), json::invalid_iterator); - CHECK_THROWS_AS(rit.value(), json::invalid_iterator); - CHECK_THROWS_AS(crit.key(), json::invalid_iterator); - CHECK_THROWS_AS(crit.value(), json::invalid_iterator); + CHECK_THROWS_AS(rit.key(), json::invalid_iterator&); + CHECK_THROWS_AS(rit.value(), json::invalid_iterator&); + CHECK_THROWS_AS(crit.key(), json::invalid_iterator&); + CHECK_THROWS_AS(crit.value(), json::invalid_iterator&); CHECK_THROWS_WITH(rit.key(), "[json.exception.invalid_iterator.207] cannot use key() for non-object iterators"); CHECK_THROWS_WITH(rit.value(), "[json.exception.invalid_iterator.214] cannot get value"); CHECK_THROWS_WITH(crit.key(), "[json.exception.invalid_iterator.207] cannot use key() for non-object iterators"); @@ -541,19 +541,19 @@ TEST_CASE("iterators 1") { auto it = j.begin(); auto cit = j_const.cbegin(); - CHECK_THROWS_AS(it.key(), json::invalid_iterator); + CHECK_THROWS_AS(it.key(), json::invalid_iterator&); CHECK_THROWS_WITH(it.key(), "[json.exception.invalid_iterator.207] cannot use key() for non-object iterators"); CHECK(it.value() == json("hello world")); - CHECK_THROWS_AS(cit.key(), json::invalid_iterator); + CHECK_THROWS_AS(cit.key(), json::invalid_iterator&); CHECK_THROWS_WITH(cit.key(), "[json.exception.invalid_iterator.207] cannot use key() for non-object iterators"); CHECK(cit.value() == json("hello world")); auto rit = j.rend(); auto crit = j.crend(); - CHECK_THROWS_AS(rit.key(), json::invalid_iterator); - CHECK_THROWS_AS(rit.value(), json::invalid_iterator); - CHECK_THROWS_AS(crit.key(), json::invalid_iterator); - CHECK_THROWS_AS(crit.value(), json::invalid_iterator); + CHECK_THROWS_AS(rit.key(), json::invalid_iterator&); + CHECK_THROWS_AS(rit.value(), json::invalid_iterator&); + CHECK_THROWS_AS(crit.key(), json::invalid_iterator&); + CHECK_THROWS_AS(crit.value(), json::invalid_iterator&); CHECK_THROWS_WITH(rit.key(), "[json.exception.invalid_iterator.207] cannot use key() for non-object iterators"); CHECK_THROWS_WITH(rit.value(), "[json.exception.invalid_iterator.214] cannot get value"); CHECK_THROWS_WITH(crit.key(), "[json.exception.invalid_iterator.207] cannot use key() for non-object iterators"); @@ -738,10 +738,10 @@ TEST_CASE("iterators 1") { auto it = j.begin(); auto cit = j_const.cbegin(); - CHECK_THROWS_AS(it.key(), json::invalid_iterator); + CHECK_THROWS_AS(it.key(), json::invalid_iterator&); CHECK_THROWS_WITH(it.key(), "[json.exception.invalid_iterator.207] cannot use key() for non-object iterators"); CHECK(it.value() == json(1)); - CHECK_THROWS_AS(cit.key(), json::invalid_iterator); + CHECK_THROWS_AS(cit.key(), json::invalid_iterator&); CHECK_THROWS_WITH(cit.key(), "[json.exception.invalid_iterator.207] cannot use key() for non-object iterators"); CHECK(cit.value() == json(1)); } @@ -1115,19 +1115,19 @@ TEST_CASE("iterators 1") { auto it = j.begin(); auto cit = j_const.cbegin(); - CHECK_THROWS_AS(it.key(), json::invalid_iterator); + CHECK_THROWS_AS(it.key(), json::invalid_iterator&); CHECK_THROWS_WITH(it.key(), "[json.exception.invalid_iterator.207] cannot use key() for non-object iterators"); CHECK(it.value() == json(23)); - CHECK_THROWS_AS(cit.key(), json::invalid_iterator); + CHECK_THROWS_AS(cit.key(), json::invalid_iterator&); CHECK_THROWS_WITH(cit.key(), "[json.exception.invalid_iterator.207] cannot use key() for non-object iterators"); CHECK(cit.value() == json(23)); auto rit = j.rend(); auto crit = j.crend(); - CHECK_THROWS_AS(rit.key(), json::invalid_iterator); - CHECK_THROWS_AS(rit.value(), json::invalid_iterator); - CHECK_THROWS_AS(crit.key(), json::invalid_iterator); - CHECK_THROWS_AS(crit.value(), json::invalid_iterator); + CHECK_THROWS_AS(rit.key(), json::invalid_iterator&); + CHECK_THROWS_AS(rit.value(), json::invalid_iterator&); + CHECK_THROWS_AS(crit.key(), json::invalid_iterator&); + CHECK_THROWS_AS(crit.value(), json::invalid_iterator&); CHECK_THROWS_WITH(rit.key(), "[json.exception.invalid_iterator.207] cannot use key() for non-object iterators"); CHECK_THROWS_WITH(rit.value(), "[json.exception.invalid_iterator.214] cannot get value"); CHECK_THROWS_WITH(crit.key(), "[json.exception.invalid_iterator.207] cannot use key() for non-object iterators"); @@ -1319,19 +1319,19 @@ TEST_CASE("iterators 1") { auto it = j.begin(); auto cit = j_const.cbegin(); - CHECK_THROWS_AS(it.key(), json::invalid_iterator); + CHECK_THROWS_AS(it.key(), json::invalid_iterator&); CHECK_THROWS_WITH(it.key(), "[json.exception.invalid_iterator.207] cannot use key() for non-object iterators"); CHECK(it.value() == json(23)); - CHECK_THROWS_AS(cit.key(), json::invalid_iterator); + CHECK_THROWS_AS(cit.key(), json::invalid_iterator&); CHECK_THROWS_WITH(cit.key(), "[json.exception.invalid_iterator.207] cannot use key() for non-object iterators"); CHECK(cit.value() == json(23)); auto rit = j.rend(); auto crit = j.crend(); - CHECK_THROWS_AS(rit.key(), json::invalid_iterator); - CHECK_THROWS_AS(rit.value(), json::invalid_iterator); - CHECK_THROWS_AS(crit.key(), json::invalid_iterator); - CHECK_THROWS_AS(crit.value(), json::invalid_iterator); + CHECK_THROWS_AS(rit.key(), json::invalid_iterator&); + CHECK_THROWS_AS(rit.value(), json::invalid_iterator&); + CHECK_THROWS_AS(crit.key(), json::invalid_iterator&); + CHECK_THROWS_AS(crit.value(), json::invalid_iterator&); CHECK_THROWS_WITH(rit.key(), "[json.exception.invalid_iterator.207] cannot use key() for non-object iterators"); CHECK_THROWS_WITH(rit.value(), "[json.exception.invalid_iterator.214] cannot get value"); CHECK_THROWS_WITH(crit.key(), "[json.exception.invalid_iterator.207] cannot use key() for non-object iterators"); @@ -1523,19 +1523,19 @@ TEST_CASE("iterators 1") { auto it = j.begin(); auto cit = j_const.cbegin(); - CHECK_THROWS_AS(it.key(), json::invalid_iterator); + CHECK_THROWS_AS(it.key(), json::invalid_iterator&); CHECK_THROWS_WITH(it.key(), "[json.exception.invalid_iterator.207] cannot use key() for non-object iterators"); CHECK(it.value() == json(23.42)); - CHECK_THROWS_AS(cit.key(), json::invalid_iterator); + CHECK_THROWS_AS(cit.key(), json::invalid_iterator&); CHECK_THROWS_WITH(cit.key(), "[json.exception.invalid_iterator.207] cannot use key() for non-object iterators"); CHECK(cit.value() == json(23.42)); auto rit = j.rend(); auto crit = j.crend(); - CHECK_THROWS_AS(rit.key(), json::invalid_iterator); - CHECK_THROWS_AS(rit.value(), json::invalid_iterator); - CHECK_THROWS_AS(crit.key(), json::invalid_iterator); - CHECK_THROWS_AS(crit.value(), json::invalid_iterator); + CHECK_THROWS_AS(rit.key(), json::invalid_iterator&); + CHECK_THROWS_AS(rit.value(), json::invalid_iterator&); + CHECK_THROWS_AS(crit.key(), json::invalid_iterator&); + CHECK_THROWS_AS(crit.value(), json::invalid_iterator&); CHECK_THROWS_WITH(rit.key(), "[json.exception.invalid_iterator.207] cannot use key() for non-object iterators"); CHECK_THROWS_WITH(rit.value(), "[json.exception.invalid_iterator.214] cannot get value"); CHECK_THROWS_WITH(crit.key(), "[json.exception.invalid_iterator.207] cannot use key() for non-object iterators"); @@ -1597,10 +1597,10 @@ TEST_CASE("iterators 1") { auto it = j.begin(); auto cit = j_const.cbegin(); - CHECK_THROWS_AS(it.key(), json::invalid_iterator); - CHECK_THROWS_AS(it.value(), json::invalid_iterator); - CHECK_THROWS_AS(cit.key(), json::invalid_iterator); - CHECK_THROWS_AS(cit.value(), json::invalid_iterator); + CHECK_THROWS_AS(it.key(), json::invalid_iterator&); + CHECK_THROWS_AS(it.value(), json::invalid_iterator&); + CHECK_THROWS_AS(cit.key(), json::invalid_iterator&); + CHECK_THROWS_AS(cit.value(), json::invalid_iterator&); CHECK_THROWS_WITH(it.key(), "[json.exception.invalid_iterator.207] cannot use key() for non-object iterators"); CHECK_THROWS_WITH(it.value(), "[json.exception.invalid_iterator.214] cannot get value"); CHECK_THROWS_WITH(cit.key(), "[json.exception.invalid_iterator.207] cannot use key() for non-object iterators"); @@ -1608,10 +1608,10 @@ TEST_CASE("iterators 1") auto rit = j.rend(); auto crit = j.crend(); - CHECK_THROWS_AS(rit.key(), json::invalid_iterator); - CHECK_THROWS_AS(rit.value(), json::invalid_iterator); - CHECK_THROWS_AS(crit.key(), json::invalid_iterator); - CHECK_THROWS_AS(crit.value(), json::invalid_iterator); + CHECK_THROWS_AS(rit.key(), json::invalid_iterator&); + CHECK_THROWS_AS(rit.value(), json::invalid_iterator&); + CHECK_THROWS_AS(crit.key(), json::invalid_iterator&); + CHECK_THROWS_AS(crit.value(), json::invalid_iterator&); CHECK_THROWS_WITH(rit.key(), "[json.exception.invalid_iterator.207] cannot use key() for non-object iterators"); CHECK_THROWS_WITH(rit.value(), "[json.exception.invalid_iterator.214] cannot get value"); CHECK_THROWS_WITH(crit.key(), "[json.exception.invalid_iterator.207] cannot use key() for non-object iterators"); diff --git a/test/src/unit-iterators2.cpp b/test/src/unit-iterators2.cpp index 29d134dac..be4e27702 100644 --- a/test/src/unit-iterators2.cpp +++ b/test/src/unit-iterators2.cpp @@ -81,14 +81,14 @@ TEST_CASE("iterators 2") { if (j.type() == json::value_t::object) { - CHECK_THROWS_AS(it1 < it1, json::invalid_iterator); - CHECK_THROWS_AS(it1 < it2, json::invalid_iterator); - CHECK_THROWS_AS(it2 < it3, json::invalid_iterator); - CHECK_THROWS_AS(it1 < it3, json::invalid_iterator); - CHECK_THROWS_AS(it1_c < it1_c, json::invalid_iterator); - CHECK_THROWS_AS(it1_c < it2_c, json::invalid_iterator); - CHECK_THROWS_AS(it2_c < it3_c, json::invalid_iterator); - CHECK_THROWS_AS(it1_c < it3_c, json::invalid_iterator); + CHECK_THROWS_AS(it1 < it1, json::invalid_iterator&); + CHECK_THROWS_AS(it1 < it2, json::invalid_iterator&); + CHECK_THROWS_AS(it2 < it3, json::invalid_iterator&); + CHECK_THROWS_AS(it1 < it3, json::invalid_iterator&); + CHECK_THROWS_AS(it1_c < it1_c, json::invalid_iterator&); + CHECK_THROWS_AS(it1_c < it2_c, json::invalid_iterator&); + CHECK_THROWS_AS(it2_c < it3_c, json::invalid_iterator&); + CHECK_THROWS_AS(it1_c < it3_c, json::invalid_iterator&); CHECK_THROWS_WITH(it1 < it1, "[json.exception.invalid_iterator.213] cannot compare order of object iterators"); CHECK_THROWS_WITH(it1 < it2, "[json.exception.invalid_iterator.213] cannot compare order of object iterators"); CHECK_THROWS_WITH(it2 < it3, "[json.exception.invalid_iterator.213] cannot compare order of object iterators"); @@ -115,14 +115,14 @@ TEST_CASE("iterators 2") { if (j.type() == json::value_t::object) { - CHECK_THROWS_AS(it1 <= it1, json::invalid_iterator); - CHECK_THROWS_AS(it1 <= it2, json::invalid_iterator); - CHECK_THROWS_AS(it2 <= it3, json::invalid_iterator); - CHECK_THROWS_AS(it1 <= it3, json::invalid_iterator); - CHECK_THROWS_AS(it1_c <= it1_c, json::invalid_iterator); - CHECK_THROWS_AS(it1_c <= it2_c, json::invalid_iterator); - CHECK_THROWS_AS(it2_c <= it3_c, json::invalid_iterator); - CHECK_THROWS_AS(it1_c <= it3_c, json::invalid_iterator); + CHECK_THROWS_AS(it1 <= it1, json::invalid_iterator&); + CHECK_THROWS_AS(it1 <= it2, json::invalid_iterator&); + CHECK_THROWS_AS(it2 <= it3, json::invalid_iterator&); + CHECK_THROWS_AS(it1 <= it3, json::invalid_iterator&); + CHECK_THROWS_AS(it1_c <= it1_c, json::invalid_iterator&); + CHECK_THROWS_AS(it1_c <= it2_c, json::invalid_iterator&); + CHECK_THROWS_AS(it2_c <= it3_c, json::invalid_iterator&); + CHECK_THROWS_AS(it1_c <= it3_c, json::invalid_iterator&); CHECK_THROWS_WITH(it1 <= it1, "[json.exception.invalid_iterator.213] cannot compare order of object iterators"); CHECK_THROWS_WITH(it1 <= it2, "[json.exception.invalid_iterator.213] cannot compare order of object iterators"); CHECK_THROWS_WITH(it2 <= it3, "[json.exception.invalid_iterator.213] cannot compare order of object iterators"); @@ -150,14 +150,14 @@ TEST_CASE("iterators 2") { if (j.type() == json::value_t::object) { - CHECK_THROWS_AS(it1 > it1, json::invalid_iterator); - CHECK_THROWS_AS(it1 > it2, json::invalid_iterator); - CHECK_THROWS_AS(it2 > it3, json::invalid_iterator); - CHECK_THROWS_AS(it1 > it3, json::invalid_iterator); - CHECK_THROWS_AS(it1_c > it1_c, json::invalid_iterator); - CHECK_THROWS_AS(it1_c > it2_c, json::invalid_iterator); - CHECK_THROWS_AS(it2_c > it3_c, json::invalid_iterator); - CHECK_THROWS_AS(it1_c > it3_c, json::invalid_iterator); + CHECK_THROWS_AS(it1 > it1, json::invalid_iterator&); + CHECK_THROWS_AS(it1 > it2, json::invalid_iterator&); + CHECK_THROWS_AS(it2 > it3, json::invalid_iterator&); + CHECK_THROWS_AS(it1 > it3, json::invalid_iterator&); + CHECK_THROWS_AS(it1_c > it1_c, json::invalid_iterator&); + CHECK_THROWS_AS(it1_c > it2_c, json::invalid_iterator&); + CHECK_THROWS_AS(it2_c > it3_c, json::invalid_iterator&); + CHECK_THROWS_AS(it1_c > it3_c, json::invalid_iterator&); CHECK_THROWS_WITH(it1 > it1, "[json.exception.invalid_iterator.213] cannot compare order of object iterators"); CHECK_THROWS_WITH(it1 > it2, "[json.exception.invalid_iterator.213] cannot compare order of object iterators"); CHECK_THROWS_WITH(it2 > it3, "[json.exception.invalid_iterator.213] cannot compare order of object iterators"); @@ -185,14 +185,14 @@ TEST_CASE("iterators 2") { if (j.type() == json::value_t::object) { - CHECK_THROWS_AS(it1 >= it1, json::invalid_iterator); - CHECK_THROWS_AS(it1 >= it2, json::invalid_iterator); - CHECK_THROWS_AS(it2 >= it3, json::invalid_iterator); - CHECK_THROWS_AS(it1 >= it3, json::invalid_iterator); - CHECK_THROWS_AS(it1_c >= it1_c, json::invalid_iterator); - CHECK_THROWS_AS(it1_c >= it2_c, json::invalid_iterator); - CHECK_THROWS_AS(it2_c >= it3_c, json::invalid_iterator); - CHECK_THROWS_AS(it1_c >= it3_c, json::invalid_iterator); + CHECK_THROWS_AS(it1 >= it1, json::invalid_iterator&); + CHECK_THROWS_AS(it1 >= it2, json::invalid_iterator&); + CHECK_THROWS_AS(it2 >= it3, json::invalid_iterator&); + CHECK_THROWS_AS(it1 >= it3, json::invalid_iterator&); + CHECK_THROWS_AS(it1_c >= it1_c, json::invalid_iterator&); + CHECK_THROWS_AS(it1_c >= it2_c, json::invalid_iterator&); + CHECK_THROWS_AS(it2_c >= it3_c, json::invalid_iterator&); + CHECK_THROWS_AS(it1_c >= it3_c, json::invalid_iterator&); CHECK_THROWS_WITH(it1 >= it1, "[json.exception.invalid_iterator.213] cannot compare order of object iterators"); CHECK_THROWS_WITH(it1 >= it2, "[json.exception.invalid_iterator.213] cannot compare order of object iterators"); CHECK_THROWS_WITH(it2 >= it3, "[json.exception.invalid_iterator.213] cannot compare order of object iterators"); @@ -224,13 +224,13 @@ TEST_CASE("iterators 2") { if (j != k) { - CHECK_THROWS_AS(j.begin() == k.begin(), json::invalid_iterator); - CHECK_THROWS_AS(j.cbegin() == k.cbegin(), json::invalid_iterator); + CHECK_THROWS_AS(j.begin() == k.begin(), json::invalid_iterator&); + CHECK_THROWS_AS(j.cbegin() == k.cbegin(), json::invalid_iterator&); CHECK_THROWS_WITH(j.begin() == k.begin(), "[json.exception.invalid_iterator.212] cannot compare iterators of different containers"); CHECK_THROWS_WITH(j.cbegin() == k.cbegin(), "[json.exception.invalid_iterator.212] cannot compare iterators of different containers"); - CHECK_THROWS_AS(j.begin() < k.begin(), json::invalid_iterator); - CHECK_THROWS_AS(j.cbegin() < k.cbegin(), json::invalid_iterator); + CHECK_THROWS_AS(j.begin() < k.begin(), json::invalid_iterator&); + CHECK_THROWS_AS(j.cbegin() < k.cbegin(), json::invalid_iterator&); CHECK_THROWS_WITH(j.begin() < k.begin(), "[json.exception.invalid_iterator.212] cannot compare iterators of different containers"); CHECK_THROWS_WITH(j.cbegin() < k.cbegin(), "[json.exception.invalid_iterator.212] cannot compare iterators of different containers"); } @@ -251,62 +251,62 @@ TEST_CASE("iterators 2") { { auto it = j_object.begin(); - CHECK_THROWS_AS(it += 1, json::invalid_iterator); + CHECK_THROWS_AS(it += 1, json::invalid_iterator&); CHECK_THROWS_WITH(it += 1, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators"); } { auto it = j_object.cbegin(); - CHECK_THROWS_AS(it += 1, json::invalid_iterator); + CHECK_THROWS_AS(it += 1, json::invalid_iterator&); CHECK_THROWS_WITH(it += 1, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators"); } { auto it = j_object.begin(); - CHECK_THROWS_AS(it + 1, json::invalid_iterator); + CHECK_THROWS_AS(it + 1, json::invalid_iterator&); CHECK_THROWS_WITH(it + 1, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators"); } { auto it = j_object.cbegin(); - CHECK_THROWS_AS(it + 1, json::invalid_iterator); + CHECK_THROWS_AS(it + 1, json::invalid_iterator&); CHECK_THROWS_WITH(it + 1, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators"); } { auto it = j_object.begin(); - CHECK_THROWS_AS(1 + it, json::invalid_iterator); + CHECK_THROWS_AS(1 + it, json::invalid_iterator&); CHECK_THROWS_WITH(1 + it, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators"); } { auto it = j_object.cbegin(); - CHECK_THROWS_AS(1 + it, json::invalid_iterator); + CHECK_THROWS_AS(1 + it, json::invalid_iterator&); CHECK_THROWS_WITH(1 + it, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators"); } { auto it = j_object.begin(); - CHECK_THROWS_AS(it -= 1, json::invalid_iterator); + CHECK_THROWS_AS(it -= 1, json::invalid_iterator&); CHECK_THROWS_WITH(it -= 1, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators"); } { auto it = j_object.cbegin(); - CHECK_THROWS_AS(it -= 1, json::invalid_iterator); + CHECK_THROWS_AS(it -= 1, json::invalid_iterator&); CHECK_THROWS_WITH(it -= 1, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators"); } { auto it = j_object.begin(); - CHECK_THROWS_AS(it - 1, json::invalid_iterator); + CHECK_THROWS_AS(it - 1, json::invalid_iterator&); CHECK_THROWS_WITH(it - 1, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators"); } { auto it = j_object.cbegin(); - CHECK_THROWS_AS(it - 1, json::invalid_iterator); + CHECK_THROWS_AS(it - 1, json::invalid_iterator&); CHECK_THROWS_WITH(it - 1, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators"); } { auto it = j_object.begin(); - CHECK_THROWS_AS(it - it, json::invalid_iterator); + CHECK_THROWS_AS(it - it, json::invalid_iterator&); CHECK_THROWS_WITH(it - it, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators"); } { auto it = j_object.cbegin(); - CHECK_THROWS_AS(it - it, json::invalid_iterator); + CHECK_THROWS_AS(it - it, json::invalid_iterator&); CHECK_THROWS_WITH(it - it, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators"); } } @@ -396,15 +396,15 @@ TEST_CASE("iterators 2") { { auto it = j_object.begin(); - CHECK_THROWS_AS(it[0], json::invalid_iterator); - CHECK_THROWS_AS(it[1], json::invalid_iterator); + CHECK_THROWS_AS(it[0], json::invalid_iterator&); + CHECK_THROWS_AS(it[1], json::invalid_iterator&); CHECK_THROWS_WITH(it[0], "[json.exception.invalid_iterator.208] cannot use operator[] for object iterators"); CHECK_THROWS_WITH(it[1], "[json.exception.invalid_iterator.208] cannot use operator[] for object iterators"); } { auto it = j_object.cbegin(); - CHECK_THROWS_AS(it[0], json::invalid_iterator); - CHECK_THROWS_AS(it[1], json::invalid_iterator); + CHECK_THROWS_AS(it[0], json::invalid_iterator&); + CHECK_THROWS_AS(it[1], json::invalid_iterator&); CHECK_THROWS_WITH(it[0], "[json.exception.invalid_iterator.208] cannot use operator[] for object iterators"); CHECK_THROWS_WITH(it[1], "[json.exception.invalid_iterator.208] cannot use operator[] for object iterators"); } @@ -436,15 +436,15 @@ TEST_CASE("iterators 2") { { auto it = j_null.begin(); - CHECK_THROWS_AS(it[0], json::invalid_iterator); - CHECK_THROWS_AS(it[1], json::invalid_iterator); + CHECK_THROWS_AS(it[0], json::invalid_iterator&); + CHECK_THROWS_AS(it[1], json::invalid_iterator&); CHECK_THROWS_WITH(it[0], "[json.exception.invalid_iterator.214] cannot get value"); CHECK_THROWS_WITH(it[1], "[json.exception.invalid_iterator.214] cannot get value"); } { auto it = j_null.cbegin(); - CHECK_THROWS_AS(it[0], json::invalid_iterator); - CHECK_THROWS_AS(it[1], json::invalid_iterator); + CHECK_THROWS_AS(it[0], json::invalid_iterator&); + CHECK_THROWS_AS(it[1], json::invalid_iterator&); CHECK_THROWS_WITH(it[0], "[json.exception.invalid_iterator.214] cannot get value"); CHECK_THROWS_WITH(it[1], "[json.exception.invalid_iterator.214] cannot get value"); } @@ -455,13 +455,13 @@ TEST_CASE("iterators 2") { auto it = j_value.begin(); CHECK(it[0] == json(42)); - CHECK_THROWS_AS(it[1], json::invalid_iterator); + CHECK_THROWS_AS(it[1], json::invalid_iterator&); CHECK_THROWS_WITH(it[1], "[json.exception.invalid_iterator.214] cannot get value"); } { auto it = j_value.cbegin(); CHECK(it[0] == json(42)); - CHECK_THROWS_AS(it[1], json::invalid_iterator); + CHECK_THROWS_AS(it[1], json::invalid_iterator&); CHECK_THROWS_WITH(it[1], "[json.exception.invalid_iterator.214] cannot get value"); } } @@ -516,14 +516,14 @@ TEST_CASE("iterators 2") { if (j.type() == json::value_t::object) { - CHECK_THROWS_AS(it1 < it1, json::invalid_iterator); - CHECK_THROWS_AS(it1 < it2, json::invalid_iterator); - CHECK_THROWS_AS(it2 < it3, json::invalid_iterator); - CHECK_THROWS_AS(it1 < it3, json::invalid_iterator); - CHECK_THROWS_AS(it1_c < it1_c, json::invalid_iterator); - CHECK_THROWS_AS(it1_c < it2_c, json::invalid_iterator); - CHECK_THROWS_AS(it2_c < it3_c, json::invalid_iterator); - CHECK_THROWS_AS(it1_c < it3_c, json::invalid_iterator); + CHECK_THROWS_AS(it1 < it1, json::invalid_iterator&); + CHECK_THROWS_AS(it1 < it2, json::invalid_iterator&); + CHECK_THROWS_AS(it2 < it3, json::invalid_iterator&); + CHECK_THROWS_AS(it1 < it3, json::invalid_iterator&); + CHECK_THROWS_AS(it1_c < it1_c, json::invalid_iterator&); + CHECK_THROWS_AS(it1_c < it2_c, json::invalid_iterator&); + CHECK_THROWS_AS(it2_c < it3_c, json::invalid_iterator&); + CHECK_THROWS_AS(it1_c < it3_c, json::invalid_iterator&); CHECK_THROWS_WITH(it1 < it1, "[json.exception.invalid_iterator.213] cannot compare order of object iterators"); CHECK_THROWS_WITH(it1 < it2, "[json.exception.invalid_iterator.213] cannot compare order of object iterators"); CHECK_THROWS_WITH(it2 < it3, "[json.exception.invalid_iterator.213] cannot compare order of object iterators"); @@ -550,14 +550,14 @@ TEST_CASE("iterators 2") { if (j.type() == json::value_t::object) { - CHECK_THROWS_AS(it1 <= it1, json::invalid_iterator); - CHECK_THROWS_AS(it1 <= it2, json::invalid_iterator); - CHECK_THROWS_AS(it2 <= it3, json::invalid_iterator); - CHECK_THROWS_AS(it1 <= it3, json::invalid_iterator); - CHECK_THROWS_AS(it1_c <= it1_c, json::invalid_iterator); - CHECK_THROWS_AS(it1_c <= it2_c, json::invalid_iterator); - CHECK_THROWS_AS(it2_c <= it3_c, json::invalid_iterator); - CHECK_THROWS_AS(it1_c <= it3_c, json::invalid_iterator); + CHECK_THROWS_AS(it1 <= it1, json::invalid_iterator&); + CHECK_THROWS_AS(it1 <= it2, json::invalid_iterator&); + CHECK_THROWS_AS(it2 <= it3, json::invalid_iterator&); + CHECK_THROWS_AS(it1 <= it3, json::invalid_iterator&); + CHECK_THROWS_AS(it1_c <= it1_c, json::invalid_iterator&); + CHECK_THROWS_AS(it1_c <= it2_c, json::invalid_iterator&); + CHECK_THROWS_AS(it2_c <= it3_c, json::invalid_iterator&); + CHECK_THROWS_AS(it1_c <= it3_c, json::invalid_iterator&); CHECK_THROWS_WITH(it1 <= it1, "[json.exception.invalid_iterator.213] cannot compare order of object iterators"); CHECK_THROWS_WITH(it1 <= it2, "[json.exception.invalid_iterator.213] cannot compare order of object iterators"); CHECK_THROWS_WITH(it2 <= it3, "[json.exception.invalid_iterator.213] cannot compare order of object iterators"); @@ -585,14 +585,14 @@ TEST_CASE("iterators 2") { if (j.type() == json::value_t::object) { - CHECK_THROWS_AS(it1 > it1, json::invalid_iterator); - CHECK_THROWS_AS(it1 > it2, json::invalid_iterator); - CHECK_THROWS_AS(it2 > it3, json::invalid_iterator); - CHECK_THROWS_AS(it1 > it3, json::invalid_iterator); - CHECK_THROWS_AS(it1_c > it1_c, json::invalid_iterator); - CHECK_THROWS_AS(it1_c > it2_c, json::invalid_iterator); - CHECK_THROWS_AS(it2_c > it3_c, json::invalid_iterator); - CHECK_THROWS_AS(it1_c > it3_c, json::invalid_iterator); + CHECK_THROWS_AS(it1 > it1, json::invalid_iterator&); + CHECK_THROWS_AS(it1 > it2, json::invalid_iterator&); + CHECK_THROWS_AS(it2 > it3, json::invalid_iterator&); + CHECK_THROWS_AS(it1 > it3, json::invalid_iterator&); + CHECK_THROWS_AS(it1_c > it1_c, json::invalid_iterator&); + CHECK_THROWS_AS(it1_c > it2_c, json::invalid_iterator&); + CHECK_THROWS_AS(it2_c > it3_c, json::invalid_iterator&); + CHECK_THROWS_AS(it1_c > it3_c, json::invalid_iterator&); CHECK_THROWS_WITH(it1 > it1, "[json.exception.invalid_iterator.213] cannot compare order of object iterators"); CHECK_THROWS_WITH(it1 > it2, "[json.exception.invalid_iterator.213] cannot compare order of object iterators"); CHECK_THROWS_WITH(it2 > it3, "[json.exception.invalid_iterator.213] cannot compare order of object iterators"); @@ -620,14 +620,14 @@ TEST_CASE("iterators 2") { if (j.type() == json::value_t::object) { - CHECK_THROWS_AS(it1 >= it1, json::invalid_iterator); - CHECK_THROWS_AS(it1 >= it2, json::invalid_iterator); - CHECK_THROWS_AS(it2 >= it3, json::invalid_iterator); - CHECK_THROWS_AS(it1 >= it3, json::invalid_iterator); - CHECK_THROWS_AS(it1_c >= it1_c, json::invalid_iterator); - CHECK_THROWS_AS(it1_c >= it2_c, json::invalid_iterator); - CHECK_THROWS_AS(it2_c >= it3_c, json::invalid_iterator); - CHECK_THROWS_AS(it1_c >= it3_c, json::invalid_iterator); + CHECK_THROWS_AS(it1 >= it1, json::invalid_iterator&); + CHECK_THROWS_AS(it1 >= it2, json::invalid_iterator&); + CHECK_THROWS_AS(it2 >= it3, json::invalid_iterator&); + CHECK_THROWS_AS(it1 >= it3, json::invalid_iterator&); + CHECK_THROWS_AS(it1_c >= it1_c, json::invalid_iterator&); + CHECK_THROWS_AS(it1_c >= it2_c, json::invalid_iterator&); + CHECK_THROWS_AS(it2_c >= it3_c, json::invalid_iterator&); + CHECK_THROWS_AS(it1_c >= it3_c, json::invalid_iterator&); CHECK_THROWS_WITH(it1 >= it1, "[json.exception.invalid_iterator.213] cannot compare order of object iterators"); CHECK_THROWS_WITH(it1 >= it2, "[json.exception.invalid_iterator.213] cannot compare order of object iterators"); CHECK_THROWS_WITH(it2 >= it3, "[json.exception.invalid_iterator.213] cannot compare order of object iterators"); @@ -659,13 +659,13 @@ TEST_CASE("iterators 2") { if (j != k) { - CHECK_THROWS_AS(j.rbegin() == k.rbegin(), json::invalid_iterator); - CHECK_THROWS_AS(j.crbegin() == k.crbegin(), json::invalid_iterator); + CHECK_THROWS_AS(j.rbegin() == k.rbegin(), json::invalid_iterator&); + CHECK_THROWS_AS(j.crbegin() == k.crbegin(), json::invalid_iterator&); CHECK_THROWS_WITH(j.rbegin() == k.rbegin(), "[json.exception.invalid_iterator.212] cannot compare iterators of different containers"); CHECK_THROWS_WITH(j.crbegin() == k.crbegin(), "[json.exception.invalid_iterator.212] cannot compare iterators of different containers"); - CHECK_THROWS_AS(j.rbegin() < k.rbegin(), json::invalid_iterator); - CHECK_THROWS_AS(j.crbegin() < k.crbegin(), json::invalid_iterator); + CHECK_THROWS_AS(j.rbegin() < k.rbegin(), json::invalid_iterator&); + CHECK_THROWS_AS(j.crbegin() < k.crbegin(), json::invalid_iterator&); CHECK_THROWS_WITH(j.rbegin() < k.rbegin(), "[json.exception.invalid_iterator.212] cannot compare iterators of different containers"); CHECK_THROWS_WITH(j.crbegin() < k.crbegin(), "[json.exception.invalid_iterator.212] cannot compare iterators of different containers"); } @@ -686,62 +686,62 @@ TEST_CASE("iterators 2") { { auto it = j_object.rbegin(); - CHECK_THROWS_AS(it += 1, json::invalid_iterator); + CHECK_THROWS_AS(it += 1, json::invalid_iterator&); CHECK_THROWS_WITH(it += 1, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators"); } { auto it = j_object.crbegin(); - CHECK_THROWS_AS(it += 1, json::invalid_iterator); + CHECK_THROWS_AS(it += 1, json::invalid_iterator&); CHECK_THROWS_WITH(it += 1, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators"); } { auto it = j_object.rbegin(); - CHECK_THROWS_AS(it + 1, json::invalid_iterator); + CHECK_THROWS_AS(it + 1, json::invalid_iterator&); CHECK_THROWS_WITH(it + 1, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators"); } { auto it = j_object.crbegin(); - CHECK_THROWS_AS(it + 1, json::invalid_iterator); + CHECK_THROWS_AS(it + 1, json::invalid_iterator&); CHECK_THROWS_WITH(it + 1, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators"); } { auto it = j_object.rbegin(); - CHECK_THROWS_AS(1 + it, json::invalid_iterator); + CHECK_THROWS_AS(1 + it, json::invalid_iterator&); CHECK_THROWS_WITH(1 + it, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators"); } { auto it = j_object.crbegin(); - CHECK_THROWS_AS(1 + it, json::invalid_iterator); + CHECK_THROWS_AS(1 + it, json::invalid_iterator&); CHECK_THROWS_WITH(1 + it, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators"); } { auto it = j_object.rbegin(); - CHECK_THROWS_AS(it -= 1, json::invalid_iterator); + CHECK_THROWS_AS(it -= 1, json::invalid_iterator&); CHECK_THROWS_WITH(it -= 1, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators"); } { auto it = j_object.crbegin(); - CHECK_THROWS_AS(it -= 1, json::invalid_iterator); + CHECK_THROWS_AS(it -= 1, json::invalid_iterator&); CHECK_THROWS_WITH(it -= 1, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators"); } { auto it = j_object.rbegin(); - CHECK_THROWS_AS(it - 1, json::invalid_iterator); + CHECK_THROWS_AS(it - 1, json::invalid_iterator&); CHECK_THROWS_WITH(it - 1, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators"); } { auto it = j_object.crbegin(); - CHECK_THROWS_AS(it - 1, json::invalid_iterator); + CHECK_THROWS_AS(it - 1, json::invalid_iterator&); CHECK_THROWS_WITH(it - 1, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators"); } { auto it = j_object.rbegin(); - CHECK_THROWS_AS(it - it, json::invalid_iterator); + CHECK_THROWS_AS(it - it, json::invalid_iterator&); CHECK_THROWS_WITH(it - it, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators"); } { auto it = j_object.crbegin(); - CHECK_THROWS_AS(it - it, json::invalid_iterator); + CHECK_THROWS_AS(it - it, json::invalid_iterator&); CHECK_THROWS_WITH(it - it, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators"); } } @@ -831,15 +831,15 @@ TEST_CASE("iterators 2") { { auto it = j_object.rbegin(); - CHECK_THROWS_AS(it[0], json::invalid_iterator); - CHECK_THROWS_AS(it[1], json::invalid_iterator); + CHECK_THROWS_AS(it[0], json::invalid_iterator&); + CHECK_THROWS_AS(it[1], json::invalid_iterator&); CHECK_THROWS_WITH(it[0], "[json.exception.invalid_iterator.209] cannot use offsets with object iterators"); CHECK_THROWS_WITH(it[1], "[json.exception.invalid_iterator.209] cannot use offsets with object iterators"); } { auto it = j_object.crbegin(); - CHECK_THROWS_AS(it[0], json::invalid_iterator); - CHECK_THROWS_AS(it[1], json::invalid_iterator); + CHECK_THROWS_AS(it[0], json::invalid_iterator&); + CHECK_THROWS_AS(it[1], json::invalid_iterator&); CHECK_THROWS_WITH(it[0], "[json.exception.invalid_iterator.209] cannot use offsets with object iterators"); CHECK_THROWS_WITH(it[1], "[json.exception.invalid_iterator.209] cannot use offsets with object iterators"); } @@ -871,15 +871,15 @@ TEST_CASE("iterators 2") { { auto it = j_null.rbegin(); - CHECK_THROWS_AS(it[0], json::invalid_iterator); - CHECK_THROWS_AS(it[1], json::invalid_iterator); + CHECK_THROWS_AS(it[0], json::invalid_iterator&); + CHECK_THROWS_AS(it[1], json::invalid_iterator&); CHECK_THROWS_WITH(it[0], "[json.exception.invalid_iterator.214] cannot get value"); CHECK_THROWS_WITH(it[1], "[json.exception.invalid_iterator.214] cannot get value"); } { auto it = j_null.crbegin(); - CHECK_THROWS_AS(it[0], json::invalid_iterator); - CHECK_THROWS_AS(it[1], json::invalid_iterator); + CHECK_THROWS_AS(it[0], json::invalid_iterator&); + CHECK_THROWS_AS(it[1], json::invalid_iterator&); CHECK_THROWS_WITH(it[0], "[json.exception.invalid_iterator.214] cannot get value"); CHECK_THROWS_WITH(it[1], "[json.exception.invalid_iterator.214] cannot get value"); } @@ -890,13 +890,13 @@ TEST_CASE("iterators 2") { auto it = j_value.rbegin(); CHECK(it[0] == json(42)); - CHECK_THROWS_AS(it[1], json::invalid_iterator); + CHECK_THROWS_AS(it[1], json::invalid_iterator&); CHECK_THROWS_WITH(it[1], "[json.exception.invalid_iterator.214] cannot get value"); } { auto it = j_value.crbegin(); CHECK(it[0] == json(42)); - CHECK_THROWS_AS(it[1], json::invalid_iterator); + CHECK_THROWS_AS(it[1], json::invalid_iterator&); CHECK_THROWS_WITH(it[1], "[json.exception.invalid_iterator.214] cannot get value"); } } diff --git a/test/src/unit-json_patch.cpp b/test/src/unit-json_patch.cpp index 9ab86ea42..636fa2bc7 100644 --- a/test/src/unit-json_patch.cpp +++ b/test/src/unit-json_patch.cpp @@ -75,7 +75,7 @@ TEST_CASE("JSON patch") json doc2 = R"({ "q": { "bar": 2 } })"_json; // because "a" does not exist. - CHECK_THROWS_AS(doc2.patch(patch), json::out_of_range); + CHECK_THROWS_AS(doc2.patch(patch), json::out_of_range&); CHECK_THROWS_WITH(doc2.patch(patch), "[json.exception.out_of_range.403] key 'a' not found"); } @@ -337,7 +337,7 @@ TEST_CASE("JSON patch") )"_json; // check that evaluation throws - CHECK_THROWS_AS(doc.patch(patch), json::other_error); + CHECK_THROWS_AS(doc.patch(patch), json::other_error&); CHECK_THROWS_WITH(doc.patch(patch), "[json.exception.other_error.501] unsuccessful: " + patch[0].dump()); } @@ -421,7 +421,7 @@ TEST_CASE("JSON patch") // references neither the root of the document, nor a member of // an existing object, nor a member of an existing array. - CHECK_THROWS_AS(doc.patch(patch), json::out_of_range); + CHECK_THROWS_AS(doc.patch(patch), json::out_of_range&); CHECK_THROWS_WITH(doc.patch(patch), "[json.exception.out_of_range.403] key 'baz' not found"); } @@ -478,7 +478,7 @@ TEST_CASE("JSON patch") )"_json; // check that evaluation throws - CHECK_THROWS_AS(doc.patch(patch), json::other_error); + CHECK_THROWS_AS(doc.patch(patch), json::other_error&); CHECK_THROWS_WITH(doc.patch(patch), "[json.exception.other_error.501] unsuccessful: " + patch[0].dump()); } @@ -668,7 +668,7 @@ TEST_CASE("JSON patch") { json j; json patch = {{"op", "add"}, {"path", ""}, {"value", 1}}; - CHECK_THROWS_AS(j.patch(patch), json::parse_error); + CHECK_THROWS_AS(j.patch(patch), json::parse_error&); CHECK_THROWS_WITH(j.patch(patch), "[json.exception.parse_error.104] parse error: JSON patch must be an array of objects"); } @@ -677,7 +677,7 @@ TEST_CASE("JSON patch") { json j; json patch = {"op", "add", "path", "", "value", 1}; - CHECK_THROWS_AS(j.patch(patch), json::parse_error); + CHECK_THROWS_AS(j.patch(patch), json::parse_error&); CHECK_THROWS_WITH(j.patch(patch), "[json.exception.parse_error.104] parse error: JSON patch must be an array of objects"); } @@ -686,7 +686,7 @@ TEST_CASE("JSON patch") { json j; json patch = {{{"foo", "bar"}}}; - CHECK_THROWS_AS(j.patch(patch), json::parse_error); + CHECK_THROWS_AS(j.patch(patch), json::parse_error&); CHECK_THROWS_WITH(j.patch(patch), "[json.exception.parse_error.105] parse error: operation must have member 'op'"); } @@ -695,7 +695,7 @@ TEST_CASE("JSON patch") { json j; json patch = {{{"op", 1}}}; - CHECK_THROWS_AS(j.patch(patch), json::parse_error); + CHECK_THROWS_AS(j.patch(patch), json::parse_error&); CHECK_THROWS_WITH(j.patch(patch), "[json.exception.parse_error.105] parse error: operation must have string member 'op'"); } @@ -704,7 +704,7 @@ TEST_CASE("JSON patch") { json j; json patch = {{{"op", "foo"}, {"path", ""}}}; - CHECK_THROWS_AS(j.patch(patch), json::parse_error); + CHECK_THROWS_AS(j.patch(patch), json::parse_error&); CHECK_THROWS_WITH(j.patch(patch), "[json.exception.parse_error.105] parse error: operation value 'foo' is invalid"); } @@ -716,7 +716,7 @@ TEST_CASE("JSON patch") { json j; json patch = {{{"op", "add"}}}; - CHECK_THROWS_AS(j.patch(patch), json::parse_error); + CHECK_THROWS_AS(j.patch(patch), json::parse_error&); CHECK_THROWS_WITH(j.patch(patch), "[json.exception.parse_error.105] parse error: operation 'add' must have member 'path'"); } @@ -725,7 +725,7 @@ TEST_CASE("JSON patch") { json j; json patch = {{{"op", "add"}, {"path", 1}}}; - CHECK_THROWS_AS(j.patch(patch), json::parse_error); + CHECK_THROWS_AS(j.patch(patch), json::parse_error&); CHECK_THROWS_WITH(j.patch(patch), "[json.exception.parse_error.105] parse error: operation 'add' must have string member 'path'"); } @@ -734,7 +734,7 @@ TEST_CASE("JSON patch") { json j; json patch = {{{"op", "add"}, {"path", ""}}}; - CHECK_THROWS_AS(j.patch(patch), json::parse_error); + CHECK_THROWS_AS(j.patch(patch), json::parse_error&); CHECK_THROWS_WITH(j.patch(patch), "[json.exception.parse_error.105] parse error: operation 'add' must have member 'value'"); } @@ -743,7 +743,7 @@ TEST_CASE("JSON patch") { json j = {1, 2}; json patch = {{{"op", "add"}, {"path", "/4"}, {"value", 4}}}; - CHECK_THROWS_AS(j.patch(patch), json::out_of_range); + CHECK_THROWS_AS(j.patch(patch), json::out_of_range&); CHECK_THROWS_WITH(j.patch(patch), "[json.exception.out_of_range.401] array index 4 is out of range"); } @@ -755,7 +755,7 @@ TEST_CASE("JSON patch") { json j; json patch = {{{"op", "remove"}}}; - CHECK_THROWS_AS(j.patch(patch), json::parse_error); + CHECK_THROWS_AS(j.patch(patch), json::parse_error&); CHECK_THROWS_WITH(j.patch(patch), "[json.exception.parse_error.105] parse error: operation 'remove' must have member 'path'"); } @@ -764,7 +764,7 @@ TEST_CASE("JSON patch") { json j; json patch = {{{"op", "remove"}, {"path", 1}}}; - CHECK_THROWS_AS(j.patch(patch), json::parse_error); + CHECK_THROWS_AS(j.patch(patch), json::parse_error&); CHECK_THROWS_WITH(j.patch(patch), "[json.exception.parse_error.105] parse error: operation 'remove' must have string member 'path'"); } @@ -773,7 +773,7 @@ TEST_CASE("JSON patch") { json j = {1, 2, 3}; json patch = {{{"op", "remove"}, {"path", "/17"}}}; - CHECK_THROWS_AS(j.patch(patch), json::out_of_range); + CHECK_THROWS_AS(j.patch(patch), json::out_of_range&); CHECK_THROWS_WITH(j.patch(patch), "[json.exception.out_of_range.401] array index 17 is out of range"); } @@ -782,7 +782,7 @@ TEST_CASE("JSON patch") { json j = {{"foo", 1}, {"bar", 2}}; json patch = {{{"op", "remove"}, {"path", "/baz"}}}; - CHECK_THROWS_AS(j.patch(patch), json::out_of_range); + CHECK_THROWS_AS(j.patch(patch), json::out_of_range&); CHECK_THROWS_WITH(j.patch(patch), "[json.exception.out_of_range.403] key 'baz' not found"); } @@ -791,7 +791,7 @@ TEST_CASE("JSON patch") { json j = "string"; json patch = {{{"op", "remove"}, {"path", ""}}}; - CHECK_THROWS_AS(j.patch(patch), json::out_of_range); + CHECK_THROWS_AS(j.patch(patch), json::out_of_range&); CHECK_THROWS_WITH(j.patch(patch), "[json.exception.out_of_range.405] JSON pointer has no parent"); } @@ -803,7 +803,7 @@ TEST_CASE("JSON patch") { json j; json patch = {{{"op", "replace"}}}; - CHECK_THROWS_AS(j.patch(patch), json::parse_error); + CHECK_THROWS_AS(j.patch(patch), json::parse_error&); CHECK_THROWS_WITH(j.patch(patch), "[json.exception.parse_error.105] parse error: operation 'replace' must have member 'path'"); } @@ -812,7 +812,7 @@ TEST_CASE("JSON patch") { json j; json patch = {{{"op", "replace"}, {"path", 1}}}; - CHECK_THROWS_AS(j.patch(patch), json::parse_error); + CHECK_THROWS_AS(j.patch(patch), json::parse_error&); CHECK_THROWS_WITH(j.patch(patch), "[json.exception.parse_error.105] parse error: operation 'replace' must have string member 'path'"); } @@ -821,7 +821,7 @@ TEST_CASE("JSON patch") { json j; json patch = {{{"op", "replace"}, {"path", ""}}}; - CHECK_THROWS_AS(j.patch(patch), json::parse_error); + CHECK_THROWS_AS(j.patch(patch), json::parse_error&); CHECK_THROWS_WITH(j.patch(patch), "[json.exception.parse_error.105] parse error: operation 'replace' must have member 'value'"); } @@ -830,7 +830,7 @@ TEST_CASE("JSON patch") { json j = {1, 2, 3}; json patch = {{{"op", "replace"}, {"path", "/17"}, {"value", 19}}}; - CHECK_THROWS_AS(j.patch(patch), json::out_of_range); + CHECK_THROWS_AS(j.patch(patch), json::out_of_range&); CHECK_THROWS_WITH(j.patch(patch), "[json.exception.out_of_range.401] array index 17 is out of range"); } @@ -839,7 +839,7 @@ TEST_CASE("JSON patch") { json j = {{"foo", 1}, {"bar", 2}}; json patch = {{{"op", "replace"}, {"path", "/baz"}, {"value", 3}}}; - CHECK_THROWS_AS(j.patch(patch), json::out_of_range); + CHECK_THROWS_AS(j.patch(patch), json::out_of_range&); CHECK_THROWS_WITH(j.patch(patch), "[json.exception.out_of_range.403] key 'baz' not found"); } @@ -851,7 +851,7 @@ TEST_CASE("JSON patch") { json j; json patch = {{{"op", "move"}}}; - CHECK_THROWS_AS(j.patch(patch), json::parse_error); + CHECK_THROWS_AS(j.patch(patch), json::parse_error&); CHECK_THROWS_WITH(j.patch(patch), "[json.exception.parse_error.105] parse error: operation 'move' must have member 'path'"); } @@ -860,7 +860,7 @@ TEST_CASE("JSON patch") { json j; json patch = {{{"op", "move"}, {"path", 1}}}; - CHECK_THROWS_AS(j.patch(patch), json::parse_error); + CHECK_THROWS_AS(j.patch(patch), json::parse_error&); CHECK_THROWS_WITH(j.patch(patch), "[json.exception.parse_error.105] parse error: operation 'move' must have string member 'path'"); } @@ -869,7 +869,7 @@ TEST_CASE("JSON patch") { json j; json patch = {{{"op", "move"}, {"path", ""}}}; - CHECK_THROWS_AS(j.patch(patch), json::parse_error); + CHECK_THROWS_AS(j.patch(patch), json::parse_error&); CHECK_THROWS_WITH(j.patch(patch), "[json.exception.parse_error.105] parse error: operation 'move' must have member 'from'"); } @@ -878,7 +878,7 @@ TEST_CASE("JSON patch") { json j; json patch = {{{"op", "move"}, {"path", ""}, {"from", 1}}}; - CHECK_THROWS_AS(j.patch(patch), json::parse_error); + CHECK_THROWS_AS(j.patch(patch), json::parse_error&); CHECK_THROWS_WITH(j.patch(patch), "[json.exception.parse_error.105] parse error: operation 'move' must have string member 'from'"); } @@ -887,7 +887,7 @@ TEST_CASE("JSON patch") { json j = {1, 2, 3}; json patch = {{{"op", "move"}, {"path", "/0"}, {"from", "/5"}}}; - CHECK_THROWS_AS(j.patch(patch), json::out_of_range); + CHECK_THROWS_AS(j.patch(patch), json::out_of_range&); CHECK_THROWS_WITH(j.patch(patch), "[json.exception.out_of_range.401] array index 5 is out of range"); } @@ -896,7 +896,7 @@ TEST_CASE("JSON patch") { json j = {{"foo", 1}, {"bar", 2}}; json patch = {{{"op", "move"}, {"path", "/baz"}, {"from", "/baz"}}}; - CHECK_THROWS_AS(j.patch(patch), json::out_of_range); + CHECK_THROWS_AS(j.patch(patch), json::out_of_range&); CHECK_THROWS_WITH(j.patch(patch), "[json.exception.out_of_range.403] key 'baz' not found"); } @@ -908,7 +908,7 @@ TEST_CASE("JSON patch") { json j; json patch = {{{"op", "copy"}}}; - CHECK_THROWS_AS(j.patch(patch), json::parse_error); + CHECK_THROWS_AS(j.patch(patch), json::parse_error&); CHECK_THROWS_WITH(j.patch(patch), "[json.exception.parse_error.105] parse error: operation 'copy' must have member 'path'"); } @@ -917,7 +917,7 @@ TEST_CASE("JSON patch") { json j; json patch = {{{"op", "copy"}, {"path", 1}}}; - CHECK_THROWS_AS(j.patch(patch), json::parse_error); + CHECK_THROWS_AS(j.patch(patch), json::parse_error&); CHECK_THROWS_WITH(j.patch(patch), "[json.exception.parse_error.105] parse error: operation 'copy' must have string member 'path'"); } @@ -926,7 +926,7 @@ TEST_CASE("JSON patch") { json j; json patch = {{{"op", "copy"}, {"path", ""}}}; - CHECK_THROWS_AS(j.patch(patch), json::parse_error); + CHECK_THROWS_AS(j.patch(patch), json::parse_error&); CHECK_THROWS_WITH(j.patch(patch), "[json.exception.parse_error.105] parse error: operation 'copy' must have member 'from'"); } @@ -935,7 +935,7 @@ TEST_CASE("JSON patch") { json j; json patch = {{{"op", "copy"}, {"path", ""}, {"from", 1}}}; - CHECK_THROWS_AS(j.patch(patch), json::parse_error); + CHECK_THROWS_AS(j.patch(patch), json::parse_error&); CHECK_THROWS_WITH(j.patch(patch), "[json.exception.parse_error.105] parse error: operation 'copy' must have string member 'from'"); } @@ -944,7 +944,7 @@ TEST_CASE("JSON patch") { json j = {1, 2, 3}; json patch = {{{"op", "copy"}, {"path", "/0"}, {"from", "/5"}}}; - CHECK_THROWS_AS(j.patch(patch), json::out_of_range); + CHECK_THROWS_AS(j.patch(patch), json::out_of_range&); CHECK_THROWS_WITH(j.patch(patch), "[json.exception.out_of_range.401] array index 5 is out of range"); } @@ -953,7 +953,7 @@ TEST_CASE("JSON patch") { json j = {{"foo", 1}, {"bar", 2}}; json patch = {{{"op", "copy"}, {"path", "/fob"}, {"from", "/baz"}}}; - CHECK_THROWS_AS(j.patch(patch), json::out_of_range); + CHECK_THROWS_AS(j.patch(patch), json::out_of_range&); CHECK_THROWS_WITH(j.patch(patch), "[json.exception.out_of_range.403] key 'baz' not found"); } @@ -965,7 +965,7 @@ TEST_CASE("JSON patch") { json j; json patch = {{{"op", "test"}}}; - CHECK_THROWS_AS(j.patch(patch), json::parse_error); + CHECK_THROWS_AS(j.patch(patch), json::parse_error&); CHECK_THROWS_WITH(j.patch(patch), "[json.exception.parse_error.105] parse error: operation 'test' must have member 'path'"); } @@ -974,7 +974,7 @@ TEST_CASE("JSON patch") { json j; json patch = {{{"op", "test"}, {"path", 1}}}; - CHECK_THROWS_AS(j.patch(patch), json::parse_error); + CHECK_THROWS_AS(j.patch(patch), json::parse_error&); CHECK_THROWS_WITH(j.patch(patch), "[json.exception.parse_error.105] parse error: operation 'test' must have string member 'path'"); } @@ -983,7 +983,7 @@ TEST_CASE("JSON patch") { json j; json patch = {{{"op", "test"}, {"path", ""}}}; - CHECK_THROWS_AS(j.patch(patch), json::parse_error); + CHECK_THROWS_AS(j.patch(patch), json::parse_error&); CHECK_THROWS_WITH(j.patch(patch), "[json.exception.parse_error.105] parse error: operation 'test' must have member 'value'"); } @@ -1177,7 +1177,7 @@ TEST_CASE("JSON patch") )"_json; // the test will fail - CHECK_THROWS_AS(doc.patch(patch), json::other_error); + CHECK_THROWS_AS(doc.patch(patch), json::other_error&); CHECK_THROWS_WITH(doc.patch(patch), "[json.exception.other_error.501] unsuccessful: " + patch[0].dump()); } } diff --git a/test/src/unit-json_pointer.cpp b/test/src/unit-json_pointer.cpp index d42800498..ee55dc58e 100644 --- a/test/src/unit-json_pointer.cpp +++ b/test/src/unit-json_pointer.cpp @@ -36,23 +36,23 @@ TEST_CASE("JSON pointers") { SECTION("errors") { - CHECK_THROWS_AS(json::json_pointer("foo"), json::parse_error); + CHECK_THROWS_AS(json::json_pointer("foo"), json::parse_error&); CHECK_THROWS_WITH(json::json_pointer("foo"), "[json.exception.parse_error.107] parse error at 1: JSON pointer must be empty or begin with '/' - was: 'foo'"); - CHECK_THROWS_AS(json::json_pointer("/~~"), json::parse_error); + CHECK_THROWS_AS(json::json_pointer("/~~"), json::parse_error&); CHECK_THROWS_WITH(json::json_pointer("/~~"), "[json.exception.parse_error.108] parse error: escape character '~' must be followed with '0' or '1'"); - CHECK_THROWS_AS(json::json_pointer("/~"), json::parse_error); + CHECK_THROWS_AS(json::json_pointer("/~"), json::parse_error&); CHECK_THROWS_WITH(json::json_pointer("/~"), "[json.exception.parse_error.108] parse error: escape character '~' must be followed with '0' or '1'"); json::json_pointer p; - CHECK_THROWS_AS(p.top(), json::out_of_range); + CHECK_THROWS_AS(p.top(), json::out_of_range&); CHECK_THROWS_WITH(p.top(), "[json.exception.out_of_range.405] JSON pointer has no parent"); - CHECK_THROWS_AS(p.pop_back(), json::out_of_range); + CHECK_THROWS_AS(p.pop_back(), json::out_of_range&); CHECK_THROWS_WITH(p.pop_back(), "[json.exception.out_of_range.405] JSON pointer has no parent"); } @@ -126,10 +126,10 @@ TEST_CASE("JSON pointers") // unresolved access json j_primitive = 1; - CHECK_THROWS_AS(j_primitive["/foo"_json_pointer], json::out_of_range); + CHECK_THROWS_AS(j_primitive["/foo"_json_pointer], json::out_of_range&); CHECK_THROWS_WITH(j_primitive["/foo"_json_pointer], "[json.exception.out_of_range.404] unresolved reference token 'foo'"); - CHECK_THROWS_AS(j_primitive.at("/foo"_json_pointer), json::out_of_range); + CHECK_THROWS_AS(j_primitive.at("/foo"_json_pointer), json::out_of_range&); CHECK_THROWS_WITH(j_primitive.at("/foo"_json_pointer), "[json.exception.out_of_range.404] unresolved reference token 'foo'"); } @@ -189,16 +189,16 @@ TEST_CASE("JSON pointers") CHECK(j[json::json_pointer("/m~0n")] == j["m~n"]); // unescaped access - CHECK_THROWS_AS(j.at(json::json_pointer("/a/b")), json::out_of_range); + CHECK_THROWS_AS(j.at(json::json_pointer("/a/b")), json::out_of_range&); CHECK_THROWS_WITH(j.at(json::json_pointer("/a/b")), "[json.exception.out_of_range.403] key 'a' not found"); // unresolved access const json j_primitive = 1; - CHECK_THROWS_AS(j_primitive["/foo"_json_pointer], json::out_of_range); + CHECK_THROWS_AS(j_primitive["/foo"_json_pointer], json::out_of_range&); CHECK_THROWS_WITH(j_primitive["/foo"_json_pointer], "[json.exception.out_of_range.404] unresolved reference token 'foo'"); - CHECK_THROWS_AS(j_primitive.at("/foo"_json_pointer), json::out_of_range); + CHECK_THROWS_AS(j_primitive.at("/foo"_json_pointer), json::out_of_range&); CHECK_THROWS_WITH(j_primitive.at("/foo"_json_pointer), "[json.exception.out_of_range.404] unresolved reference token 'foo'"); } @@ -255,35 +255,35 @@ TEST_CASE("JSON pointers") CHECK(j == json({1, 13, 3, 33, nullptr, 55})); // error with leading 0 - CHECK_THROWS_AS(j["/01"_json_pointer], json::parse_error); + CHECK_THROWS_AS(j["/01"_json_pointer], json::parse_error&); CHECK_THROWS_WITH(j["/01"_json_pointer], "[json.exception.parse_error.106] parse error: array index '01' must not begin with '0'"); - CHECK_THROWS_AS(j_const["/01"_json_pointer], json::parse_error); + CHECK_THROWS_AS(j_const["/01"_json_pointer], json::parse_error&); CHECK_THROWS_WITH(j_const["/01"_json_pointer], "[json.exception.parse_error.106] parse error: array index '01' must not begin with '0'"); - CHECK_THROWS_AS(j.at("/01"_json_pointer), json::parse_error); + CHECK_THROWS_AS(j.at("/01"_json_pointer), json::parse_error&); CHECK_THROWS_WITH(j.at("/01"_json_pointer), "[json.exception.parse_error.106] parse error: array index '01' must not begin with '0'"); - CHECK_THROWS_AS(j_const.at("/01"_json_pointer), json::parse_error); + CHECK_THROWS_AS(j_const.at("/01"_json_pointer), json::parse_error&); CHECK_THROWS_WITH(j_const.at("/01"_json_pointer), "[json.exception.parse_error.106] parse error: array index '01' must not begin with '0'"); // error with incorrect numbers - CHECK_THROWS_AS(j["/one"_json_pointer] = 1, json::parse_error); + CHECK_THROWS_AS(j["/one"_json_pointer] = 1, json::parse_error&); CHECK_THROWS_WITH(j["/one"_json_pointer] = 1, "[json.exception.parse_error.109] parse error: array index 'one' is not a number"); - CHECK_THROWS_AS(j_const["/one"_json_pointer] == 1, json::parse_error); + CHECK_THROWS_AS(j_const["/one"_json_pointer] == 1, json::parse_error&); CHECK_THROWS_WITH(j_const["/one"_json_pointer] == 1, "[json.exception.parse_error.109] parse error: array index 'one' is not a number"); - CHECK_THROWS_AS(j.at("/one"_json_pointer) = 1, json::parse_error); + CHECK_THROWS_AS(j.at("/one"_json_pointer) = 1, json::parse_error&); CHECK_THROWS_WITH(j.at("/one"_json_pointer) = 1, "[json.exception.parse_error.109] parse error: array index 'one' is not a number"); - CHECK_THROWS_AS(j_const.at("/one"_json_pointer) == 1, json::parse_error); + CHECK_THROWS_AS(j_const.at("/one"_json_pointer) == 1, json::parse_error&); CHECK_THROWS_WITH(j_const.at("/one"_json_pointer) == 1, "[json.exception.parse_error.109] parse error: array index 'one' is not a number"); - CHECK_THROWS_AS(json({{"/list/0", 1}, {"/list/1", 2}, {"/list/three", 3}}).unflatten(), json::parse_error); + CHECK_THROWS_AS(json({{"/list/0", 1}, {"/list/1", 2}, {"/list/three", 3}}).unflatten(), json::parse_error&); CHECK_THROWS_WITH(json({{"/list/0", 1}, {"/list/1", 2}, {"/list/three", 3}}).unflatten(), "[json.exception.parse_error.109] parse error: array index 'three' is not a number"); @@ -292,15 +292,15 @@ TEST_CASE("JSON pointers") CHECK(j == json({1, 13, 3, 33, nullptr, 55, 99})); // error when using "-" in const object - CHECK_THROWS_AS(j_const["/-"_json_pointer], json::out_of_range); + CHECK_THROWS_AS(j_const["/-"_json_pointer], json::out_of_range&); CHECK_THROWS_WITH(j_const["/-"_json_pointer], "[json.exception.out_of_range.402] array index '-' (3) is out of range"); // error when using "-" with at - CHECK_THROWS_AS(j.at("/-"_json_pointer), json::out_of_range); + CHECK_THROWS_AS(j.at("/-"_json_pointer), json::out_of_range&); CHECK_THROWS_WITH(j.at("/-"_json_pointer), "[json.exception.out_of_range.402] array index '-' (7) is out of range"); - CHECK_THROWS_AS(j_const.at("/-"_json_pointer), json::out_of_range); + CHECK_THROWS_AS(j_const.at("/-"_json_pointer), json::out_of_range&); CHECK_THROWS_WITH(j_const.at("/-"_json_pointer), "[json.exception.out_of_range.402] array index '-' (3) is out of range"); } @@ -315,20 +315,20 @@ TEST_CASE("JSON pointers") CHECK(j["/2"_json_pointer] == j[2]); // assign to nonexisting index - CHECK_THROWS_AS(j.at("/3"_json_pointer), json::out_of_range); + CHECK_THROWS_AS(j.at("/3"_json_pointer), json::out_of_range&); CHECK_THROWS_WITH(j.at("/3"_json_pointer), "[json.exception.out_of_range.401] array index 3 is out of range"); // assign to nonexisting index (with gap) - CHECK_THROWS_AS(j.at("/5"_json_pointer), json::out_of_range); + CHECK_THROWS_AS(j.at("/5"_json_pointer), json::out_of_range&); CHECK_THROWS_WITH(j.at("/5"_json_pointer), "[json.exception.out_of_range.401] array index 5 is out of range"); // assign to "-" - CHECK_THROWS_AS(j["/-"_json_pointer], json::out_of_range); + CHECK_THROWS_AS(j["/-"_json_pointer], json::out_of_range&); CHECK_THROWS_WITH(j["/-"_json_pointer], "[json.exception.out_of_range.402] array index '-' (3) is out of range"); - CHECK_THROWS_AS(j.at("/-"_json_pointer), json::out_of_range); + CHECK_THROWS_AS(j.at("/-"_json_pointer), json::out_of_range&); CHECK_THROWS_WITH(j.at("/-"_json_pointer), "[json.exception.out_of_range.402] array index '-' (3) is out of range"); } @@ -386,18 +386,18 @@ TEST_CASE("JSON pointers") CHECK(j_flatten.unflatten() == j); // error for nonobjects - CHECK_THROWS_AS(json(1).unflatten(), json::type_error); + CHECK_THROWS_AS(json(1).unflatten(), json::type_error&); CHECK_THROWS_WITH(json(1).unflatten(), "[json.exception.type_error.314] only objects can be unflattened"); // error for nonprimitve values - CHECK_THROWS_AS(json({{"/1", {1, 2, 3}}}).unflatten(), json::type_error); + CHECK_THROWS_AS(json({{"/1", {1, 2, 3}}}).unflatten(), json::type_error&); CHECK_THROWS_WITH(json({{"/1", {1, 2, 3}}}).unflatten(), "[json.exception.type_error.315] values in object must be primitive"); // error for conflicting values json j_error = {{"", 42}, {"/foo", 17}}; - CHECK_THROWS_AS(j_error.unflatten(), json::type_error); + CHECK_THROWS_AS(j_error.unflatten(), json::type_error&); CHECK_THROWS_WITH(j_error.unflatten(), "[json.exception.type_error.313] invalid value to unflatten"); diff --git a/test/src/unit-modifiers.cpp b/test/src/unit-modifiers.cpp index f0eb09c6f..01dfa4152 100644 --- a/test/src/unit-modifiers.cpp +++ b/test/src/unit-modifiers.cpp @@ -172,7 +172,7 @@ TEST_CASE("modifiers") SECTION("other type") { json j = 1; - CHECK_THROWS_AS(j.push_back("Hello"), json::type_error); + CHECK_THROWS_AS(j.push_back("Hello"), json::type_error&); CHECK_THROWS_WITH(j.push_back("Hello"), "[json.exception.type_error.308] cannot use push_back() with number"); } } @@ -202,7 +202,7 @@ TEST_CASE("modifiers") { json j = 1; json k("Hello"); - CHECK_THROWS_AS(j.push_back(k), json::type_error); + CHECK_THROWS_AS(j.push_back(k), json::type_error&); CHECK_THROWS_WITH(j.push_back(k), "[json.exception.type_error.308] cannot use push_back() with number"); } } @@ -235,7 +235,7 @@ TEST_CASE("modifiers") { json j = 1; json k("Hello"); - CHECK_THROWS_AS(j.push_back(json::object_t::value_type({"one", 1})), json::type_error); + CHECK_THROWS_AS(j.push_back(json::object_t::value_type({"one", 1})), json::type_error&); CHECK_THROWS_WITH(j.push_back(json::object_t::value_type({"one", 1})), "[json.exception.type_error.308] cannot use push_back() with number"); } @@ -272,11 +272,11 @@ TEST_CASE("modifiers") CHECK(j == json({{"key1", 1}, {"key2", "bar"}})); // invalid values (no string/val pair) - CHECK_THROWS_AS(j.push_back({1}), json::type_error); + CHECK_THROWS_AS(j.push_back({1}), json::type_error&); CHECK_THROWS_WITH(j.push_back({1}), "[json.exception.type_error.308] cannot use push_back() with object"); - CHECK_THROWS_AS(j.push_back({1, 2}), json::type_error); + CHECK_THROWS_AS(j.push_back({1, 2}), json::type_error&); CHECK_THROWS_WITH(j.push_back({1, 2}), "[json.exception.type_error.308] cannot use push_back() with object"); - CHECK_THROWS_AS(j.push_back({1, 2, 3, 4}), json::type_error); + CHECK_THROWS_AS(j.push_back({1, 2, 3, 4}), json::type_error&); CHECK_THROWS_WITH(j.push_back({1, 2, 3, 4}), "[json.exception.type_error.308] cannot use push_back() with object"); } } @@ -315,7 +315,7 @@ TEST_CASE("modifiers") SECTION("other type") { json j = 1; - CHECK_THROWS_AS(j.emplace_back("Hello"), json::type_error); + CHECK_THROWS_AS(j.emplace_back("Hello"), json::type_error&); CHECK_THROWS_WITH(j.emplace_back("Hello"), "[json.exception.type_error.311] cannot use emplace_back() with number"); } @@ -375,7 +375,7 @@ TEST_CASE("modifiers") SECTION("other type") { json j = 1; - CHECK_THROWS_AS(j.emplace("foo", "bar"), json::type_error); + CHECK_THROWS_AS(j.emplace("foo", "bar"), json::type_error&); CHECK_THROWS_WITH(j.emplace("foo", "bar"), "[json.exception.type_error.311] cannot use emplace() with number"); } @@ -407,7 +407,7 @@ TEST_CASE("modifiers") SECTION("other type") { json j = 1; - CHECK_THROWS_AS(j += "Hello", json::type_error); + CHECK_THROWS_AS(j += "Hello", json::type_error&); CHECK_THROWS_WITH(j += "Hello", "[json.exception.type_error.308] cannot use push_back() with number"); } } @@ -437,7 +437,7 @@ TEST_CASE("modifiers") { json j = 1; json k("Hello"); - CHECK_THROWS_AS(j += k, json::type_error); + CHECK_THROWS_AS(j += k, json::type_error&); CHECK_THROWS_WITH(j += k, "[json.exception.type_error.308] cannot use push_back() with number"); } } @@ -470,7 +470,7 @@ TEST_CASE("modifiers") { json j = 1; json k("Hello"); - CHECK_THROWS_AS(j += json::object_t::value_type({"one", 1}), json::type_error); + CHECK_THROWS_AS(j += json::object_t::value_type({"one", 1}), json::type_error&); CHECK_THROWS_WITH(j += json::object_t::value_type({"one", 1}), "[json.exception.type_error.308] cannot use push_back() with number"); } @@ -507,7 +507,7 @@ TEST_CASE("modifiers") CHECK(j == json({{"key1", 1}, {"key2", "bar"}})); json k = {{"key1", 1}}; - CHECK_THROWS_AS((k += {1, 2, 3, 4}), json::type_error); + CHECK_THROWS_AS((k += {1, 2, 3, 4}), json::type_error&); CHECK_THROWS_WITH((k += {1, 2, 3, 4}), "[json.exception.type_error.308] cannot use push_back() with object"); } } @@ -644,9 +644,9 @@ TEST_CASE("modifiers") json j_other_array2 = {"first", "second"}; CHECK_THROWS_AS(j_array.insert(j_array.end(), j_array.begin(), j_array.end()), - json::invalid_iterator); + json::invalid_iterator&); CHECK_THROWS_AS(j_array.insert(j_array.end(), j_other_array.begin(), j_other_array2.end()), - json::invalid_iterator); + json::invalid_iterator&); CHECK_THROWS_WITH(j_array.insert(j_array.end(), j_array.begin(), j_array.end()), "[json.exception.invalid_iterator.211] passed iterators may not belong to container"); @@ -676,9 +676,9 @@ TEST_CASE("modifiers") { json j_other_array2 = {"first", "second"}; - CHECK_THROWS_AS(j_array.insert(j_object2.begin(), j_object2.end()), json::type_error); - CHECK_THROWS_AS(j_object1.insert(j_object1.begin(), j_object2.end()), json::invalid_iterator); - CHECK_THROWS_AS(j_object1.insert(j_array.begin(), j_array.end()), json::invalid_iterator); + CHECK_THROWS_AS(j_array.insert(j_object2.begin(), j_object2.end()), json::type_error&); + CHECK_THROWS_AS(j_object1.insert(j_object1.begin(), j_object2.end()), json::invalid_iterator&); + CHECK_THROWS_AS(j_object1.insert(j_array.begin(), j_array.end()), json::invalid_iterator&); CHECK_THROWS_WITH(j_array.insert(j_object2.begin(), j_object2.end()), "[json.exception.type_error.309] cannot use insert() with array"); @@ -724,11 +724,11 @@ TEST_CASE("modifiers") // pass iterator to a different array json j_another_array = {1, 2}; json j_yet_another_array = {"first", "second"}; - CHECK_THROWS_AS(j_array.insert(j_another_array.end(), 10), json::invalid_iterator); - CHECK_THROWS_AS(j_array.insert(j_another_array.end(), j_value), json::invalid_iterator); - CHECK_THROWS_AS(j_array.insert(j_another_array.end(), 10, 11), json::invalid_iterator); - CHECK_THROWS_AS(j_array.insert(j_another_array.end(), j_yet_another_array.begin(), j_yet_another_array.end()), json::invalid_iterator); - CHECK_THROWS_AS(j_array.insert(j_another_array.end(), {1, 2, 3, 4}), json::invalid_iterator); + CHECK_THROWS_AS(j_array.insert(j_another_array.end(), 10), json::invalid_iterator&); + CHECK_THROWS_AS(j_array.insert(j_another_array.end(), j_value), json::invalid_iterator&); + CHECK_THROWS_AS(j_array.insert(j_another_array.end(), 10, 11), json::invalid_iterator&); + CHECK_THROWS_AS(j_array.insert(j_another_array.end(), j_yet_another_array.begin(), j_yet_another_array.end()), json::invalid_iterator&); + CHECK_THROWS_AS(j_array.insert(j_another_array.end(), {1, 2, 3, 4}), json::invalid_iterator&); CHECK_THROWS_WITH(j_array.insert(j_another_array.end(), 10), "[json.exception.invalid_iterator.202] iterator does not fit current value"); @@ -747,12 +747,12 @@ TEST_CASE("modifiers") // call insert on a non-array type json j_nonarray = 3; json j_yet_another_array = {"first", "second"}; - CHECK_THROWS_AS(j_nonarray.insert(j_nonarray.end(), 10), json::type_error); - CHECK_THROWS_AS(j_nonarray.insert(j_nonarray.end(), j_value), json::type_error); - CHECK_THROWS_AS(j_nonarray.insert(j_nonarray.end(), 10, 11), json::type_error); + CHECK_THROWS_AS(j_nonarray.insert(j_nonarray.end(), 10), json::type_error&); + CHECK_THROWS_AS(j_nonarray.insert(j_nonarray.end(), j_value), json::type_error&); + CHECK_THROWS_AS(j_nonarray.insert(j_nonarray.end(), 10, 11), json::type_error&); CHECK_THROWS_AS(j_nonarray.insert(j_nonarray.end(), j_yet_another_array.begin(), - j_yet_another_array.end()), json::type_error); - CHECK_THROWS_AS(j_nonarray.insert(j_nonarray.end(), {1, 2, 3, 4}), json::type_error); + j_yet_another_array.end()), json::type_error&); + CHECK_THROWS_AS(j_nonarray.insert(j_nonarray.end(), {1, 2, 3, 4}), json::type_error&); CHECK_THROWS_WITH(j_nonarray.insert(j_nonarray.end(), 10), "[json.exception.type_error.309] cannot use insert() with number"); CHECK_THROWS_WITH(j_nonarray.insert(j_nonarray.end(), j_value), "[json.exception.type_error.309] cannot use insert() with number"); @@ -784,10 +784,10 @@ TEST_CASE("modifiers") SECTION("wrong types") { - CHECK_THROWS_AS(j_array.update(j_object1), json::type_error); + CHECK_THROWS_AS(j_array.update(j_object1), json::type_error&); CHECK_THROWS_WITH(j_array.update(j_object1), "[json.exception.type_error.312] cannot use update() with array"); - CHECK_THROWS_AS(j_object1.update(j_array), json::type_error); + CHECK_THROWS_AS(j_object1.update(j_array), json::type_error&); CHECK_THROWS_WITH(j_object1.update(j_array), "[json.exception.type_error.312] cannot use update() with array"); } } @@ -814,9 +814,9 @@ TEST_CASE("modifiers") { json j_other_array2 = {"first", "second"}; - CHECK_THROWS_AS(j_array.update(j_object2.begin(), j_object2.end()), json::type_error); - CHECK_THROWS_AS(j_object1.update(j_object1.begin(), j_object2.end()), json::invalid_iterator); - CHECK_THROWS_AS(j_object1.update(j_array.begin(), j_array.end()), json::invalid_iterator); + CHECK_THROWS_AS(j_array.update(j_object2.begin(), j_object2.end()), json::type_error&); + CHECK_THROWS_AS(j_object1.update(j_object1.begin(), j_object2.end()), json::invalid_iterator&); + CHECK_THROWS_AS(j_object1.update(j_array.begin(), j_array.end()), json::invalid_iterator&); CHECK_THROWS_WITH(j_array.update(j_object2.begin(), j_object2.end()), "[json.exception.type_error.312] cannot use update() with array"); @@ -876,7 +876,7 @@ TEST_CASE("modifiers") json j = 17; json::array_t a = {"foo", "bar", "baz"}; - CHECK_THROWS_AS(j.swap(a), json::type_error); + CHECK_THROWS_AS(j.swap(a), json::type_error&); CHECK_THROWS_WITH(j.swap(a), "[json.exception.type_error.310] cannot use swap() with number"); } } @@ -902,7 +902,7 @@ TEST_CASE("modifiers") json j = 17; json::object_t o = {{"cow", "Kuh"}, {"chicken", "Huhn"}}; - CHECK_THROWS_AS(j.swap(o), json::type_error); + CHECK_THROWS_AS(j.swap(o), json::type_error&); CHECK_THROWS_WITH(j.swap(o), "[json.exception.type_error.310] cannot use swap() with number"); } } @@ -928,7 +928,7 @@ TEST_CASE("modifiers") json j = 17; json::string_t s = "Hallo Welt"; - CHECK_THROWS_AS(j.swap(s), json::type_error); + CHECK_THROWS_AS(j.swap(s), json::type_error&); CHECK_THROWS_WITH(j.swap(s), "[json.exception.type_error.310] cannot use swap() with number"); } } diff --git a/test/src/unit-msgpack.cpp b/test/src/unit-msgpack.cpp index c363069f0..148bb180a 100644 --- a/test/src/unit-msgpack.cpp +++ b/test/src/unit-msgpack.cpp @@ -1016,28 +1016,28 @@ TEST_CASE("MessagePack") { SECTION("empty byte vector") { - CHECK_THROWS_AS(json::from_msgpack(std::vector()), json::parse_error); + CHECK_THROWS_AS(json::from_msgpack(std::vector()), json::parse_error&); CHECK_THROWS_WITH(json::from_msgpack(std::vector()), "[json.exception.parse_error.110] parse error at 1: unexpected end of input"); } SECTION("too short byte vector") { - CHECK_THROWS_AS(json::from_msgpack(std::vector({0xcc})), json::parse_error); - CHECK_THROWS_AS(json::from_msgpack(std::vector({0xcd})), json::parse_error); - CHECK_THROWS_AS(json::from_msgpack(std::vector({0xcd, 0x00})), json::parse_error); - CHECK_THROWS_AS(json::from_msgpack(std::vector({0xce})), json::parse_error); - CHECK_THROWS_AS(json::from_msgpack(std::vector({0xce, 0x00})), json::parse_error); - CHECK_THROWS_AS(json::from_msgpack(std::vector({0xce, 0x00, 0x00})), json::parse_error); - CHECK_THROWS_AS(json::from_msgpack(std::vector({0xce, 0x00, 0x00, 0x00})), json::parse_error); - CHECK_THROWS_AS(json::from_msgpack(std::vector({0xcf})), json::parse_error); - CHECK_THROWS_AS(json::from_msgpack(std::vector({0xcf, 0x00})), json::parse_error); - CHECK_THROWS_AS(json::from_msgpack(std::vector({0xcf, 0x00, 0x00})), json::parse_error); - CHECK_THROWS_AS(json::from_msgpack(std::vector({0xcf, 0x00, 0x00, 0x00})), json::parse_error); - CHECK_THROWS_AS(json::from_msgpack(std::vector({0xcf, 0x00, 0x00, 0x00, 0x00})), json::parse_error); - CHECK_THROWS_AS(json::from_msgpack(std::vector({0xcf, 0x00, 0x00, 0x00, 0x00, 0x00})), json::parse_error); - CHECK_THROWS_AS(json::from_msgpack(std::vector({0xcf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00})), json::parse_error); - CHECK_THROWS_AS(json::from_msgpack(std::vector({0xcf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00})), json::parse_error); + CHECK_THROWS_AS(json::from_msgpack(std::vector({0xcc})), json::parse_error&); + CHECK_THROWS_AS(json::from_msgpack(std::vector({0xcd})), json::parse_error&); + CHECK_THROWS_AS(json::from_msgpack(std::vector({0xcd, 0x00})), json::parse_error&); + CHECK_THROWS_AS(json::from_msgpack(std::vector({0xce})), json::parse_error&); + CHECK_THROWS_AS(json::from_msgpack(std::vector({0xce, 0x00})), json::parse_error&); + CHECK_THROWS_AS(json::from_msgpack(std::vector({0xce, 0x00, 0x00})), json::parse_error&); + CHECK_THROWS_AS(json::from_msgpack(std::vector({0xce, 0x00, 0x00, 0x00})), json::parse_error&); + CHECK_THROWS_AS(json::from_msgpack(std::vector({0xcf})), json::parse_error&); + CHECK_THROWS_AS(json::from_msgpack(std::vector({0xcf, 0x00})), json::parse_error&); + CHECK_THROWS_AS(json::from_msgpack(std::vector({0xcf, 0x00, 0x00})), json::parse_error&); + CHECK_THROWS_AS(json::from_msgpack(std::vector({0xcf, 0x00, 0x00, 0x00})), json::parse_error&); + CHECK_THROWS_AS(json::from_msgpack(std::vector({0xcf, 0x00, 0x00, 0x00, 0x00})), json::parse_error&); + CHECK_THROWS_AS(json::from_msgpack(std::vector({0xcf, 0x00, 0x00, 0x00, 0x00, 0x00})), json::parse_error&); + CHECK_THROWS_AS(json::from_msgpack(std::vector({0xcf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00})), json::parse_error&); + CHECK_THROWS_AS(json::from_msgpack(std::vector({0xcf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00})), json::parse_error&); CHECK_THROWS_WITH(json::from_msgpack(std::vector({0xcc})), "[json.exception.parse_error.110] parse error at 2: unexpected end of input"); @@ -1075,10 +1075,10 @@ TEST_CASE("MessagePack") { SECTION("concrete examples") { - CHECK_THROWS_AS(json::from_msgpack(std::vector({0xc1})), json::parse_error); + CHECK_THROWS_AS(json::from_msgpack(std::vector({0xc1})), json::parse_error&); CHECK_THROWS_WITH(json::from_msgpack(std::vector({0xc1})), "[json.exception.parse_error.112] parse error at 1: error reading MessagePack; last byte: 0xC1"); - CHECK_THROWS_AS(json::from_msgpack(std::vector({0xc6})), json::parse_error); + CHECK_THROWS_AS(json::from_msgpack(std::vector({0xc6})), json::parse_error&); CHECK_THROWS_WITH(json::from_msgpack(std::vector({0xc6})), "[json.exception.parse_error.112] parse error at 1: error reading MessagePack; last byte: 0xC6"); } @@ -1097,14 +1097,14 @@ TEST_CASE("MessagePack") 0xd4, 0xd5, 0xd6, 0xd7, 0xd8 }) { - CHECK_THROWS_AS(json::from_msgpack(std::vector({static_cast(byte)})), json::parse_error); + CHECK_THROWS_AS(json::from_msgpack(std::vector({static_cast(byte)})), json::parse_error&); } } } SECTION("invalid string in map") { - CHECK_THROWS_AS(json::from_msgpack(std::vector({0x81, 0xff, 0x01})), json::parse_error); + CHECK_THROWS_AS(json::from_msgpack(std::vector({0x81, 0xff, 0x01})), json::parse_error&); CHECK_THROWS_WITH(json::from_msgpack(std::vector({0x81, 0xff, 0x01})), "[json.exception.parse_error.113] parse error at 2: expected a MessagePack string; last byte: 0xFF"); } @@ -1120,7 +1120,7 @@ TEST_CASE("MessagePack") SECTION("strict mode") { - CHECK_THROWS_AS(json::from_msgpack(vec), json::parse_error); + CHECK_THROWS_AS(json::from_msgpack(vec), json::parse_error&); CHECK_THROWS_WITH(json::from_msgpack(vec), "[json.exception.parse_error.110] parse error at 2: expected end of input"); } diff --git a/test/src/unit-readme.cpp b/test/src/unit-readme.cpp index 8d126824a..1ce6ee1dc 100644 --- a/test/src/unit-readme.cpp +++ b/test/src/unit-readme.cpp @@ -31,7 +31,6 @@ SOFTWARE. #include "json.hpp" using nlohmann::json; -#include #include #include #include diff --git a/test/src/unit-reference_access.cpp b/test/src/unit-reference_access.cpp index 2e1759d62..c05ae7234 100644 --- a/test/src/unit-reference_access.cpp +++ b/test/src/unit-reference_access.cpp @@ -64,22 +64,22 @@ TEST_CASE("reference access") // check if mismatching references throw correctly CHECK_NOTHROW(value.get_ref()); - CHECK_THROWS_AS(value.get_ref(), json::type_error); + CHECK_THROWS_AS(value.get_ref(), json::type_error&); CHECK_THROWS_WITH(value.get_ref(), "[json.exception.type_error.303] incompatible ReferenceType for get_ref, actual type is object"); - CHECK_THROWS_AS(value.get_ref(), json::type_error); + CHECK_THROWS_AS(value.get_ref(), json::type_error&); CHECK_THROWS_WITH(value.get_ref(), "[json.exception.type_error.303] incompatible ReferenceType for get_ref, actual type is object"); - CHECK_THROWS_AS(value.get_ref(), json::type_error); + CHECK_THROWS_AS(value.get_ref(), json::type_error&); CHECK_THROWS_WITH(value.get_ref(), "[json.exception.type_error.303] incompatible ReferenceType for get_ref, actual type is object"); - CHECK_THROWS_AS(value.get_ref(), json::type_error); + CHECK_THROWS_AS(value.get_ref(), json::type_error&); CHECK_THROWS_WITH(value.get_ref(), "[json.exception.type_error.303] incompatible ReferenceType for get_ref, actual type is object"); - CHECK_THROWS_AS(value.get_ref(), json::type_error); + CHECK_THROWS_AS(value.get_ref(), json::type_error&); CHECK_THROWS_WITH(value.get_ref(), "[json.exception.type_error.303] incompatible ReferenceType for get_ref, actual type is object"); - CHECK_THROWS_AS(value.get_ref(), json::type_error); + CHECK_THROWS_AS(value.get_ref(), json::type_error&); CHECK_THROWS_WITH(value.get_ref(), "[json.exception.type_error.303] incompatible ReferenceType for get_ref, actual type is object"); } @@ -113,23 +113,23 @@ TEST_CASE("reference access") CHECK(p2 == value.get()); // check if mismatching references throw correctly - CHECK_THROWS_AS(value.get_ref(), json::type_error); + CHECK_THROWS_AS(value.get_ref(), json::type_error&); CHECK_THROWS_WITH(value.get_ref(), "[json.exception.type_error.303] incompatible ReferenceType for get_ref, actual type is array"); CHECK_NOTHROW(value.get_ref()); - CHECK_THROWS_AS(value.get_ref(), json::type_error); + CHECK_THROWS_AS(value.get_ref(), json::type_error&); CHECK_THROWS_WITH(value.get_ref(), "[json.exception.type_error.303] incompatible ReferenceType for get_ref, actual type is array"); - CHECK_THROWS_AS(value.get_ref(), json::type_error); + CHECK_THROWS_AS(value.get_ref(), json::type_error&); CHECK_THROWS_WITH(value.get_ref(), "[json.exception.type_error.303] incompatible ReferenceType for get_ref, actual type is array"); - CHECK_THROWS_AS(value.get_ref(), json::type_error); + CHECK_THROWS_AS(value.get_ref(), json::type_error&); CHECK_THROWS_WITH(value.get_ref(), "[json.exception.type_error.303] incompatible ReferenceType for get_ref, actual type is array"); - CHECK_THROWS_AS(value.get_ref(), json::type_error); + CHECK_THROWS_AS(value.get_ref(), json::type_error&); CHECK_THROWS_WITH(value.get_ref(), "[json.exception.type_error.303] incompatible ReferenceType for get_ref, actual type is array"); - CHECK_THROWS_AS(value.get_ref(), json::type_error); + CHECK_THROWS_AS(value.get_ref(), json::type_error&); CHECK_THROWS_WITH(value.get_ref(), "[json.exception.type_error.303] incompatible ReferenceType for get_ref, actual type is array"); } @@ -149,23 +149,23 @@ TEST_CASE("reference access") CHECK(p2 == value.get()); // check if mismatching references throw correctly - CHECK_THROWS_AS(value.get_ref(), json::type_error); + CHECK_THROWS_AS(value.get_ref(), json::type_error&); CHECK_THROWS_WITH(value.get_ref(), "[json.exception.type_error.303] incompatible ReferenceType for get_ref, actual type is string"); - CHECK_THROWS_AS(value.get_ref(), json::type_error); + CHECK_THROWS_AS(value.get_ref(), json::type_error&); CHECK_THROWS_WITH(value.get_ref(), "[json.exception.type_error.303] incompatible ReferenceType for get_ref, actual type is string"); CHECK_NOTHROW(value.get_ref()); - CHECK_THROWS_AS(value.get_ref(), json::type_error); + CHECK_THROWS_AS(value.get_ref(), json::type_error&); CHECK_THROWS_WITH(value.get_ref(), "[json.exception.type_error.303] incompatible ReferenceType for get_ref, actual type is string"); - CHECK_THROWS_AS(value.get_ref(), json::type_error); + CHECK_THROWS_AS(value.get_ref(), json::type_error&); CHECK_THROWS_WITH(value.get_ref(), "[json.exception.type_error.303] incompatible ReferenceType for get_ref, actual type is string"); - CHECK_THROWS_AS(value.get_ref(), json::type_error); + CHECK_THROWS_AS(value.get_ref(), json::type_error&); CHECK_THROWS_WITH(value.get_ref(), "[json.exception.type_error.303] incompatible ReferenceType for get_ref, actual type is string"); - CHECK_THROWS_AS(value.get_ref(), json::type_error); + CHECK_THROWS_AS(value.get_ref(), json::type_error&); CHECK_THROWS_WITH(value.get_ref(), "[json.exception.type_error.303] incompatible ReferenceType for get_ref, actual type is string"); } @@ -185,23 +185,23 @@ TEST_CASE("reference access") CHECK(p2 == value.get()); // check if mismatching references throw correctly - CHECK_THROWS_AS(value.get_ref(), json::type_error); + CHECK_THROWS_AS(value.get_ref(), json::type_error&); CHECK_THROWS_WITH(value.get_ref(), "[json.exception.type_error.303] incompatible ReferenceType for get_ref, actual type is boolean"); - CHECK_THROWS_AS(value.get_ref(), json::type_error); + CHECK_THROWS_AS(value.get_ref(), json::type_error&); CHECK_THROWS_WITH(value.get_ref(), "[json.exception.type_error.303] incompatible ReferenceType for get_ref, actual type is boolean"); - CHECK_THROWS_AS(value.get_ref(), json::type_error); + CHECK_THROWS_AS(value.get_ref(), json::type_error&); CHECK_THROWS_WITH(value.get_ref(), "[json.exception.type_error.303] incompatible ReferenceType for get_ref, actual type is boolean"); CHECK_NOTHROW(value.get_ref()); - CHECK_THROWS_AS(value.get_ref(), json::type_error); + CHECK_THROWS_AS(value.get_ref(), json::type_error&); CHECK_THROWS_WITH(value.get_ref(), "[json.exception.type_error.303] incompatible ReferenceType for get_ref, actual type is boolean"); - CHECK_THROWS_AS(value.get_ref(), json::type_error); + CHECK_THROWS_AS(value.get_ref(), json::type_error&); CHECK_THROWS_WITH(value.get_ref(), "[json.exception.type_error.303] incompatible ReferenceType for get_ref, actual type is boolean"); - CHECK_THROWS_AS(value.get_ref(), json::type_error); + CHECK_THROWS_AS(value.get_ref(), json::type_error&); CHECK_THROWS_WITH(value.get_ref(), "[json.exception.type_error.303] incompatible ReferenceType for get_ref, actual type is boolean"); } @@ -221,23 +221,23 @@ TEST_CASE("reference access") CHECK(p2 == value.get()); // check if mismatching references throw correctly - CHECK_THROWS_AS(value.get_ref(), json::type_error); + CHECK_THROWS_AS(value.get_ref(), json::type_error&); CHECK_THROWS_WITH(value.get_ref(), "[json.exception.type_error.303] incompatible ReferenceType for get_ref, actual type is number"); - CHECK_THROWS_AS(value.get_ref(), json::type_error); + CHECK_THROWS_AS(value.get_ref(), json::type_error&); CHECK_THROWS_WITH(value.get_ref(), "[json.exception.type_error.303] incompatible ReferenceType for get_ref, actual type is number"); - CHECK_THROWS_AS(value.get_ref(), json::type_error); + CHECK_THROWS_AS(value.get_ref(), json::type_error&); CHECK_THROWS_WITH(value.get_ref(), "[json.exception.type_error.303] incompatible ReferenceType for get_ref, actual type is number"); - CHECK_THROWS_AS(value.get_ref(), json::type_error); + CHECK_THROWS_AS(value.get_ref(), json::type_error&); CHECK_THROWS_WITH(value.get_ref(), "[json.exception.type_error.303] incompatible ReferenceType for get_ref, actual type is number"); CHECK_NOTHROW(value.get_ref()); - CHECK_THROWS_AS(value.get_ref(), json::type_error); + CHECK_THROWS_AS(value.get_ref(), json::type_error&); CHECK_THROWS_WITH(value.get_ref(), "[json.exception.type_error.303] incompatible ReferenceType for get_ref, actual type is number"); - CHECK_THROWS_AS(value.get_ref(), json::type_error); + CHECK_THROWS_AS(value.get_ref(), json::type_error&); CHECK_THROWS_WITH(value.get_ref(), "[json.exception.type_error.303] incompatible ReferenceType for get_ref, actual type is number"); } @@ -257,23 +257,23 @@ TEST_CASE("reference access") CHECK(p2 == value.get()); // check if mismatching references throw correctly - CHECK_THROWS_AS(value.get_ref(), json::type_error); + CHECK_THROWS_AS(value.get_ref(), json::type_error&); CHECK_THROWS_WITH(value.get_ref(), "[json.exception.type_error.303] incompatible ReferenceType for get_ref, actual type is number"); - CHECK_THROWS_AS(value.get_ref(), json::type_error); + CHECK_THROWS_AS(value.get_ref(), json::type_error&); CHECK_THROWS_WITH(value.get_ref(), "[json.exception.type_error.303] incompatible ReferenceType for get_ref, actual type is number"); - CHECK_THROWS_AS(value.get_ref(), json::type_error); + CHECK_THROWS_AS(value.get_ref(), json::type_error&); CHECK_THROWS_WITH(value.get_ref(), "[json.exception.type_error.303] incompatible ReferenceType for get_ref, actual type is number"); - CHECK_THROWS_AS(value.get_ref(), json::type_error); + CHECK_THROWS_AS(value.get_ref(), json::type_error&); CHECK_THROWS_WITH(value.get_ref(), "[json.exception.type_error.303] incompatible ReferenceType for get_ref, actual type is number"); - //CHECK_THROWS_AS(value.get_ref(), json::type_error); + //CHECK_THROWS_AS(value.get_ref(), json::type_error&); //CHECK_THROWS_WITH(value.get_ref(), // "[json.exception.type_error.303] incompatible ReferenceType for get_ref, actual type is number"); CHECK_NOTHROW(value.get_ref()); - CHECK_THROWS_AS(value.get_ref(), json::type_error); + CHECK_THROWS_AS(value.get_ref(), json::type_error&); CHECK_THROWS_WITH(value.get_ref(), "[json.exception.type_error.303] incompatible ReferenceType for get_ref, actual type is number"); } @@ -293,22 +293,22 @@ TEST_CASE("reference access") CHECK(p2 == value.get()); // check if mismatching references throw correctly - CHECK_THROWS_AS(value.get_ref(), json::type_error); + CHECK_THROWS_AS(value.get_ref(), json::type_error&); CHECK_THROWS_WITH(value.get_ref(), "[json.exception.type_error.303] incompatible ReferenceType for get_ref, actual type is number"); - CHECK_THROWS_AS(value.get_ref(), json::type_error); + CHECK_THROWS_AS(value.get_ref(), json::type_error&); CHECK_THROWS_WITH(value.get_ref(), "[json.exception.type_error.303] incompatible ReferenceType for get_ref, actual type is number"); - CHECK_THROWS_AS(value.get_ref(), json::type_error); + CHECK_THROWS_AS(value.get_ref(), json::type_error&); CHECK_THROWS_WITH(value.get_ref(), "[json.exception.type_error.303] incompatible ReferenceType for get_ref, actual type is number"); - CHECK_THROWS_AS(value.get_ref(), json::type_error); + CHECK_THROWS_AS(value.get_ref(), json::type_error&); CHECK_THROWS_WITH(value.get_ref(), "[json.exception.type_error.303] incompatible ReferenceType for get_ref, actual type is number"); - CHECK_THROWS_AS(value.get_ref(), json::type_error); + CHECK_THROWS_AS(value.get_ref(), json::type_error&); CHECK_THROWS_WITH(value.get_ref(), "[json.exception.type_error.303] incompatible ReferenceType for get_ref, actual type is number"); - CHECK_THROWS_AS(value.get_ref(), json::type_error); + CHECK_THROWS_AS(value.get_ref(), json::type_error&); CHECK_THROWS_WITH(value.get_ref(), "[json.exception.type_error.303] incompatible ReferenceType for get_ref, actual type is number"); CHECK_NOTHROW(value.get_ref()); diff --git a/test/src/unit-regression.cpp b/test/src/unit-regression.cpp index 4fd3fb523..177281608 100644 --- a/test/src/unit-regression.cpp +++ b/test/src/unit-regression.cpp @@ -588,7 +588,7 @@ TEST_CASE("regression tests") SECTION("issue #329 - serialized value not always can be parsed") { - CHECK_THROWS_AS(json::parse("22e2222"), json::out_of_range); + CHECK_THROWS_AS(json::parse("22e2222"), json::out_of_range&); CHECK_THROWS_WITH(json::parse("22e2222"), "[json.exception.out_of_range.406] number overflow parsing '22e2222'"); } @@ -596,7 +596,7 @@ TEST_CASE("regression tests") SECTION("issue #366 - json::parse on failed stream gets stuck") { std::ifstream f("file_not_found.json"); - CHECK_THROWS_AS(json::parse(f), json::parse_error); + CHECK_THROWS_AS(json::parse(f), json::parse_error&); CHECK_THROWS_WITH(json::parse(f), "[json.exception.parse_error.101] parse error at 1: syntax error - unexpected end of input; expected '[', '{', or a literal"); } @@ -611,7 +611,7 @@ TEST_CASE("regression tests") // ss is not at EOF; this yielded an error before the fix // (threw basic_string::append). No, it should just throw // a parse error because of the EOF. - CHECK_THROWS_AS(ss >> j, json::parse_error); + CHECK_THROWS_AS(ss >> j, json::parse_error&); CHECK_THROWS_WITH(ss >> j, "[json.exception.parse_error.101] parse error at 1: syntax error - unexpected end of input; expected '[', '{', or a literal"); } @@ -622,7 +622,7 @@ TEST_CASE("regression tests") { std::stringstream ss; json j; - CHECK_THROWS_AS(ss >> j, json::parse_error); + CHECK_THROWS_AS(ss >> j, json::parse_error&); CHECK_THROWS_WITH(ss >> j, "[json.exception.parse_error.101] parse error at 1: syntax error - unexpected end of input; expected '[', '{', or a literal"); } @@ -632,7 +632,7 @@ TEST_CASE("regression tests") std::stringstream ss; ss << " "; json j; - CHECK_THROWS_AS(ss >> j, json::parse_error); + CHECK_THROWS_AS(ss >> j, json::parse_error&); CHECK_THROWS_WITH(ss >> j, "[json.exception.parse_error.101] parse error at 1: syntax error - unexpected end of input; expected '[', '{', or a literal"); } @@ -645,7 +645,7 @@ TEST_CASE("regression tests") CHECK_NOTHROW(ss >> j); CHECK(j == 111); - CHECK_THROWS_AS(ss >> j, json::parse_error); + CHECK_THROWS_AS(ss >> j, json::parse_error&); CHECK_THROWS_WITH(ss >> j, "[json.exception.parse_error.101] parse error at 1: syntax error - unexpected end of input; expected '[', '{', or a literal"); } @@ -658,7 +658,7 @@ TEST_CASE("regression tests") CHECK_NOTHROW(ss >> j); CHECK(j == 222); - CHECK_THROWS_AS(ss >> j, json::parse_error); + CHECK_THROWS_AS(ss >> j, json::parse_error&); CHECK_THROWS_WITH(ss >> j, "[json.exception.parse_error.101] parse error at 1: syntax error - unexpected end of input; expected '[', '{', or a literal"); } @@ -671,7 +671,7 @@ TEST_CASE("regression tests") CHECK_NOTHROW(ss >> j); CHECK(j == 333); - CHECK_THROWS_AS(ss >> j, json::parse_error); + CHECK_THROWS_AS(ss >> j, json::parse_error&); CHECK_THROWS_WITH(ss >> j, "[json.exception.parse_error.101] parse error at 1: syntax error - unexpected end of input; expected '[', '{', or a literal"); } @@ -688,7 +688,7 @@ TEST_CASE("regression tests") CHECK_NOTHROW(ss >> j); CHECK(j == 333); - CHECK_THROWS_AS(ss >> j, json::parse_error); + CHECK_THROWS_AS(ss >> j, json::parse_error&); CHECK_THROWS_WITH(ss >> j, "[json.exception.parse_error.101] parse error at 1: syntax error - unexpected end of input; expected '[', '{', or a literal"); } @@ -707,7 +707,7 @@ TEST_CASE("regression tests") CHECK_NOTHROW(ss >> j); CHECK(j == ""); - CHECK_THROWS_AS(ss >> j, json::parse_error); + CHECK_THROWS_AS(ss >> j, json::parse_error&); CHECK_THROWS_WITH(ss >> j, "[json.exception.parse_error.101] parse error at 1: syntax error - unexpected end of input; expected '[', '{', or a literal"); } @@ -722,7 +722,7 @@ TEST_CASE("regression tests") CHECK_NOTHROW(ss >> j); CHECK(j == json({{"three", 3}})); - CHECK_THROWS_AS(ss >> j, json::parse_error); + CHECK_THROWS_AS(ss >> j, json::parse_error&); CHECK_THROWS_WITH(ss >> j, "[json.exception.parse_error.101] parse error at 1: syntax error - unexpected end of input; expected '[', '{', or a literal"); } @@ -792,7 +792,7 @@ TEST_CASE("regression tests") { // original test case std::vector vec {0x65, 0xf5, 0x0a, 0x48, 0x21}; - CHECK_THROWS_AS(json::from_cbor(vec), json::parse_error); + CHECK_THROWS_AS(json::from_cbor(vec), json::parse_error&); CHECK_THROWS_WITH(json::from_cbor(vec), "[json.exception.parse_error.110] parse error at 6: unexpected end of input"); } @@ -801,31 +801,31 @@ TEST_CASE("regression tests") { // original test case: incomplete float64 std::vector vec1 {0xcb, 0x8f, 0x0a}; - CHECK_THROWS_AS(json::from_msgpack(vec1), json::parse_error); + CHECK_THROWS_AS(json::from_msgpack(vec1), json::parse_error&); CHECK_THROWS_WITH(json::from_msgpack(vec1), "[json.exception.parse_error.110] parse error at 4: unexpected end of input"); // related test case: incomplete float32 std::vector vec2 {0xca, 0x8f, 0x0a}; - CHECK_THROWS_AS(json::from_msgpack(vec2), json::parse_error); + CHECK_THROWS_AS(json::from_msgpack(vec2), json::parse_error&); CHECK_THROWS_WITH(json::from_msgpack(vec2), "[json.exception.parse_error.110] parse error at 4: unexpected end of input"); // related test case: incomplete Half-Precision Float (CBOR) std::vector vec3 {0xf9, 0x8f}; - CHECK_THROWS_AS(json::from_cbor(vec3), json::parse_error); + CHECK_THROWS_AS(json::from_cbor(vec3), json::parse_error&); CHECK_THROWS_WITH(json::from_cbor(vec3), "[json.exception.parse_error.110] parse error at 3: unexpected end of input"); // related test case: incomplete Single-Precision Float (CBOR) std::vector vec4 {0xfa, 0x8f, 0x0a}; - CHECK_THROWS_AS(json::from_cbor(vec4), json::parse_error); + CHECK_THROWS_AS(json::from_cbor(vec4), json::parse_error&); CHECK_THROWS_WITH(json::from_cbor(vec4), "[json.exception.parse_error.110] parse error at 4: unexpected end of input"); // related test case: incomplete Double-Precision Float (CBOR) std::vector vec5 {0xfb, 0x8f, 0x0a}; - CHECK_THROWS_AS(json::from_cbor(vec5), json::parse_error); + CHECK_THROWS_AS(json::from_cbor(vec5), json::parse_error&); CHECK_THROWS_WITH(json::from_cbor(vec5), "[json.exception.parse_error.110] parse error at 4: unexpected end of input"); } @@ -834,7 +834,7 @@ TEST_CASE("regression tests") { // original test case std::vector vec1 {0x87}; - CHECK_THROWS_AS(json::from_msgpack(vec1), json::parse_error); + CHECK_THROWS_AS(json::from_msgpack(vec1), json::parse_error&); CHECK_THROWS_WITH(json::from_msgpack(vec1), "[json.exception.parse_error.110] parse error at 2: unexpected end of input"); @@ -848,7 +848,7 @@ TEST_CASE("regression tests") }) { std::vector vec(1, static_cast(b)); - CHECK_THROWS_AS(json::from_msgpack(vec), json::parse_error); + CHECK_THROWS_AS(json::from_msgpack(vec), json::parse_error&); } // more test cases for CBOR @@ -863,15 +863,15 @@ TEST_CASE("regression tests") }) { std::vector vec(1, static_cast(b)); - CHECK_THROWS_AS(json::from_cbor(vec), json::parse_error); + CHECK_THROWS_AS(json::from_cbor(vec), json::parse_error&); } // special case: empty input std::vector vec2; - CHECK_THROWS_AS(json::from_cbor(vec2), json::parse_error); + CHECK_THROWS_AS(json::from_cbor(vec2), json::parse_error&); CHECK_THROWS_WITH(json::from_cbor(vec2), "[json.exception.parse_error.110] parse error at 1: unexpected end of input"); - CHECK_THROWS_AS(json::from_msgpack(vec2), json::parse_error); + CHECK_THROWS_AS(json::from_msgpack(vec2), json::parse_error&); CHECK_THROWS_WITH(json::from_msgpack(vec2), "[json.exception.parse_error.110] parse error at 1: unexpected end of input"); } @@ -880,19 +880,19 @@ TEST_CASE("regression tests") { // original test case: empty UTF-8 string (indefinite length) std::vector vec1 {0x7f}; - CHECK_THROWS_AS(json::from_cbor(vec1), json::parse_error); + CHECK_THROWS_AS(json::from_cbor(vec1), json::parse_error&); CHECK_THROWS_WITH(json::from_cbor(vec1), "[json.exception.parse_error.110] parse error at 2: unexpected end of input"); // related test case: empty array (indefinite length) std::vector vec2 {0x9f}; - CHECK_THROWS_AS(json::from_cbor(vec2), json::parse_error); + CHECK_THROWS_AS(json::from_cbor(vec2), json::parse_error&); CHECK_THROWS_WITH(json::from_cbor(vec2), "[json.exception.parse_error.110] parse error at 2: unexpected end of input"); // related test case: empty map (indefinite length) std::vector vec3 {0xbf}; - CHECK_THROWS_AS(json::from_cbor(vec3), json::parse_error); + CHECK_THROWS_AS(json::from_cbor(vec3), json::parse_error&); CHECK_THROWS_WITH(json::from_cbor(vec3), "[json.exception.parse_error.110] parse error at 2: unexpected end of input"); } @@ -920,25 +920,25 @@ TEST_CASE("regression tests") 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60 }; - CHECK_THROWS_AS(json::from_cbor(vec), json::parse_error); + CHECK_THROWS_AS(json::from_cbor(vec), json::parse_error&); CHECK_THROWS_WITH(json::from_cbor(vec), "[json.exception.parse_error.113] parse error at 2: expected a CBOR string; last byte: 0x98"); // related test case: nonempty UTF-8 string (indefinite length) std::vector vec1 {0x7f, 0x61, 0x61}; - CHECK_THROWS_AS(json::from_cbor(vec1), json::parse_error); + CHECK_THROWS_AS(json::from_cbor(vec1), json::parse_error&); CHECK_THROWS_WITH(json::from_cbor(vec1), "[json.exception.parse_error.110] parse error at 4: unexpected end of input"); // related test case: nonempty array (indefinite length) std::vector vec2 {0x9f, 0x01}; - CHECK_THROWS_AS(json::from_cbor(vec2), json::parse_error); + CHECK_THROWS_AS(json::from_cbor(vec2), json::parse_error&); CHECK_THROWS_WITH(json::from_cbor(vec2), "[json.exception.parse_error.110] parse error at 3: unexpected end of input"); // related test case: nonempty map (indefinite length) std::vector vec3 {0xbf, 0x61, 0x61, 0x01}; - CHECK_THROWS_AS(json::from_cbor(vec3), json::parse_error); + CHECK_THROWS_AS(json::from_cbor(vec3), json::parse_error&); CHECK_THROWS_WITH(json::from_cbor(vec3), "[json.exception.parse_error.110] parse error at 5: unexpected end of input"); } @@ -973,7 +973,7 @@ TEST_CASE("regression tests") 0x96, 0x96, 0xb4, 0xb4, 0xfa, 0x94, 0x94, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0xfa }; - CHECK_THROWS_AS(json::from_cbor(vec1), json::parse_error); + CHECK_THROWS_AS(json::from_cbor(vec1), json::parse_error&); CHECK_THROWS_WITH(json::from_cbor(vec1), "[json.exception.parse_error.113] parse error at 13: expected a CBOR string; last byte: 0xB4"); @@ -987,7 +987,7 @@ TEST_CASE("regression tests") 0x96, 0x96, 0xb4, 0xb4, 0xfa, 0x94, 0x94, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0xfb }; - CHECK_THROWS_AS(json::from_cbor(vec2), json::parse_error); + CHECK_THROWS_AS(json::from_cbor(vec2), json::parse_error&); CHECK_THROWS_WITH(json::from_cbor(vec2), "[json.exception.parse_error.113] parse error at 13: expected a CBOR string; last byte: 0xB4"); } @@ -995,7 +995,7 @@ TEST_CASE("regression tests") SECTION("issue #452 - Heap-buffer-overflow (OSS-Fuzz issue 585)") { std::vector vec = {'-', '0', '1', '2', '2', '7', '4'}; - CHECK_THROWS_AS(json::parse(vec), json::parse_error); + CHECK_THROWS_AS(json::parse(vec), json::parse_error&); } SECTION("issue #454 - doubles are printed as integers") @@ -1035,9 +1035,9 @@ TEST_CASE("regression tests") }; CHECK_NOTHROW(create(j_array)); - CHECK_THROWS_AS(create(j_number), json::type_error); + CHECK_THROWS_AS(create(j_number), json::type_error&); CHECK_THROWS_WITH(create(j_number), "[json.exception.type_error.302] type must be array, but is number"); - CHECK_THROWS_AS(create(j_null), json::type_error); + CHECK_THROWS_AS(create(j_null), json::type_error&); CHECK_THROWS_WITH(create(j_null), "[json.exception.type_error.302] type must be array, but is null"); } @@ -1049,9 +1049,9 @@ TEST_CASE("regression tests") }; CHECK_NOTHROW(create(j_array)); - CHECK_THROWS_AS(create(j_number), json::type_error); + CHECK_THROWS_AS(create(j_number), json::type_error&); CHECK_THROWS_WITH(create(j_number), "[json.exception.type_error.302] type must be array, but is number"); - CHECK_THROWS_AS(create(j_null), json::type_error); + CHECK_THROWS_AS(create(j_null), json::type_error&); CHECK_THROWS_WITH(create(j_null), "[json.exception.type_error.302] type must be array, but is null"); } @@ -1063,9 +1063,9 @@ TEST_CASE("regression tests") }; CHECK_NOTHROW(create(j_array)); - CHECK_THROWS_AS(create(j_number), json::type_error); + CHECK_THROWS_AS(create(j_number), json::type_error&); CHECK_THROWS_WITH(create(j_number), "[json.exception.type_error.302] type must be array, but is number"); - CHECK_THROWS_AS(create(j_null), json::type_error); + CHECK_THROWS_AS(create(j_null), json::type_error&); CHECK_THROWS_WITH(create(j_null), "[json.exception.type_error.302] type must be array, but is null"); } } @@ -1100,7 +1100,7 @@ TEST_CASE("regression tests") l.m_stream->setstate(std::ios_base::failbit); - CHECK_THROWS_AS(l.fill_line_buffer(), json::parse_error); + CHECK_THROWS_AS(l.fill_line_buffer(), json::parse_error&); CHECK_THROWS_WITH(l.fill_line_buffer(), "[json.exception.parse_error.111] parse error: bad input stream"); } @@ -1115,7 +1115,7 @@ TEST_CASE("regression tests") l.m_stream->setstate(std::ios_base::badbit); - CHECK_THROWS_AS(l.fill_line_buffer(), json::parse_error); + CHECK_THROWS_AS(l.fill_line_buffer(), json::parse_error&); CHECK_THROWS_WITH(l.fill_line_buffer(), "[json.exception.parse_error.111] parse error: bad input stream"); } } @@ -1179,7 +1179,7 @@ TEST_CASE("regression tests") SECTION("issue #575 - heap-buffer-overflow (OSS-Fuzz 1400)") { std::vector vec = {'"', '\\', '"', 'X', '"', '"'}; - CHECK_THROWS_AS(json::parse(vec), json::parse_error); + CHECK_THROWS_AS(json::parse(vec), json::parse_error&); } SECTION("issue #600 - how does one convert a map in Json back to std::map?") @@ -1244,7 +1244,7 @@ TEST_CASE("regression tests") CHECK(v[i] == j[i]); } - CHECK_THROWS_AS(json().get>(), json::type_error); + CHECK_THROWS_AS(json().get>(), json::type_error&); CHECK_THROWS_WITH(json().get>(), "[json.exception.type_error.302] type must be array, but is null"); } diff --git a/test/src/unit-testsuites.cpp b/test/src/unit-testsuites.cpp index d3dbaf4b1..d281c679f 100644 --- a/test/src/unit-testsuites.cpp +++ b/test/src/unit-testsuites.cpp @@ -78,7 +78,7 @@ TEST_CASE("compliance tests from json.org") { CAPTURE(filename); std::ifstream f(filename); - CHECK_THROWS_AS(json::parse(f), json::parse_error); + CHECK_THROWS_AS(json::parse(f), json::parse_error&); } } @@ -772,7 +772,7 @@ TEST_CASE("nst's JSONTestSuite") { CAPTURE(filename); std::ifstream f(filename); - CHECK_THROWS_AS(json::parse(f), json::parse_error); + CHECK_THROWS_AS(json::parse(f), json::parse_error&); } } @@ -848,7 +848,7 @@ TEST_CASE("nst's JSONTestSuite") CAPTURE(filename); std::ifstream f(filename); json j; - CHECK_THROWS_AS(f >> j, json::out_of_range); + CHECK_THROWS_AS(f >> j, json::out_of_range&); } } @@ -875,7 +875,7 @@ TEST_CASE("nst's JSONTestSuite") CAPTURE(filename); std::ifstream f(filename); json j; - CHECK_THROWS_AS(f >> j, json::parse_error); + CHECK_THROWS_AS(f >> j, json::parse_error&); } } } diff --git a/test/src/unit-unicode.cpp b/test/src/unit-unicode.cpp index 9d4d65ca9..b51a1579e 100644 --- a/test/src/unit-unicode.cpp +++ b/test/src/unit-unicode.cpp @@ -81,7 +81,7 @@ void check_utf8string(bool success_expected, int byte1, int byte2 = -1, int byte } else { - CHECK_THROWS_AS(json::parse(json_string), json::parse_error); + CHECK_THROWS_AS(json::parse(json_string), json::parse_error&); } } @@ -928,31 +928,31 @@ TEST_CASE("Unicode", "[hide]") { SECTION("incorrect surrogate values") { - CHECK_THROWS_AS(json::parse("\"\\uDC00\\uDC00\""), json::parse_error); + CHECK_THROWS_AS(json::parse("\"\\uDC00\\uDC00\""), json::parse_error&); CHECK_THROWS_WITH(json::parse("\"\\uDC00\\uDC00\""), "[json.exception.parse_error.101] parse error at 7: syntax error - invalid string: surrogate U+DC00..U+DFFF must follow U+D800..U+DBFF; last read: '\"\\uDC00'"); - CHECK_THROWS_AS(json::parse("\"\\uD7FF\\uDC00\""), json::parse_error); + CHECK_THROWS_AS(json::parse("\"\\uD7FF\\uDC00\""), json::parse_error&); CHECK_THROWS_WITH(json::parse("\"\\uD7FF\\uDC00\""), "[json.exception.parse_error.101] parse error at 13: syntax error - invalid string: surrogate U+DC00..U+DFFF must follow U+D800..U+DBFF; last read: '\"\\uD7FF\\uDC00'"); - CHECK_THROWS_AS(json::parse("\"\\uD800]\""), json::parse_error); + CHECK_THROWS_AS(json::parse("\"\\uD800]\""), json::parse_error&); CHECK_THROWS_WITH(json::parse("\"\\uD800]\""), "[json.exception.parse_error.101] parse error at 8: syntax error - invalid string: surrogate U+DC00..U+DFFF must be followed by U+DC00..U+DFFF; last read: '\"\\uD800]'"); - CHECK_THROWS_AS(json::parse("\"\\uD800\\v\""), json::parse_error); + CHECK_THROWS_AS(json::parse("\"\\uD800\\v\""), json::parse_error&); CHECK_THROWS_WITH(json::parse("\"\\uD800\\v\""), "[json.exception.parse_error.101] parse error at 9: syntax error - invalid string: surrogate U+DC00..U+DFFF must be followed by U+DC00..U+DFFF; last read: '\"\\uD800\\v'"); - CHECK_THROWS_AS(json::parse("\"\\uD800\\u123\""), json::parse_error); + CHECK_THROWS_AS(json::parse("\"\\uD800\\u123\""), json::parse_error&); CHECK_THROWS_WITH(json::parse("\"\\uD800\\u123\""), "[json.exception.parse_error.101] parse error at 13: syntax error - invalid string: '\\u' must be followed by 4 hex digits; last read: '\"\\uD800\\u123\"'"); - CHECK_THROWS_AS(json::parse("\"\\uD800\\uDBFF\""), json::parse_error); + CHECK_THROWS_AS(json::parse("\"\\uD800\\uDBFF\""), json::parse_error&); CHECK_THROWS_WITH(json::parse("\"\\uD800\\uDBFF\""), "[json.exception.parse_error.101] parse error at 13: syntax error - invalid string: surrogate U+DC00..U+DFFF must be followed by U+DC00..U+DFFF; last read: '\"\\uD800\\uDBFF'"); - CHECK_THROWS_AS(json::parse("\"\\uD800\\uE000\""), json::parse_error); + CHECK_THROWS_AS(json::parse("\"\\uD800\\uE000\""), json::parse_error&); CHECK_THROWS_WITH(json::parse("\"\\uD800\\uE000\""), "[json.exception.parse_error.101] parse error at 13: syntax error - invalid string: surrogate U+DC00..U+DFFF must be followed by U+DC00..U+DFFF; last read: '\"\\uD800\\uE000'"); } @@ -969,7 +969,7 @@ TEST_CASE("Unicode", "[hide]") { std::string json_text = "\"" + codepoint_to_unicode(cp) + "\""; CAPTURE(json_text); - CHECK_THROWS_AS(json::parse(json_text), json::parse_error); + CHECK_THROWS_AS(json::parse(json_text), json::parse_error&); } } @@ -988,7 +988,7 @@ TEST_CASE("Unicode", "[hide]") std::string json_text = "\"" + codepoint_to_unicode(cp1) + codepoint_to_unicode(cp2) + "\""; CAPTURE(json_text); - CHECK_THROWS_AS(json::parse(json_text), json::parse_error); + CHECK_THROWS_AS(json::parse(json_text), json::parse_error&); } } } @@ -1001,7 +1001,7 @@ TEST_CASE("Unicode", "[hide]") { std::string json_text = "\"" + codepoint_to_unicode(cp) + "\""; CAPTURE(json_text); - CHECK_THROWS_AS(json::parse(json_text), json::parse_error); + CHECK_THROWS_AS(json::parse(json_text), json::parse_error&); } } @@ -1072,7 +1072,7 @@ TEST_CASE("Unicode", "[hide]") SECTION("error for incomplete/wrong BOM") { - CHECK_THROWS_AS(json::parse("\xef\xbb"), json::parse_error); - CHECK_THROWS_AS(json::parse("\xef\xbb\xbb"), json::parse_error); + CHECK_THROWS_AS(json::parse("\xef\xbb"), json::parse_error&); + CHECK_THROWS_AS(json::parse("\xef\xbb\xbb"), json::parse_error&); } } diff --git a/test/thirdparty/catch/catch.hpp b/test/thirdparty/catch/catch.hpp index 362f8693f..7c351e931 100644 --- a/test/thirdparty/catch/catch.hpp +++ b/test/thirdparty/catch/catch.hpp @@ -1,17 +1,17 @@ /* - * Catch v2.0.1 - * Generated: 2017-11-03 11:53:39.642003 + * Catch v1.9.7 + * Generated: 2017-08-10 23:49:15.233907 * ---------------------------------------------------------- * This file has been merged from multiple headers. Please don't edit it directly - * Copyright (c) 2017 Two Blue Cubes Ltd. All rights reserved. + * Copyright (c) 2012 Two Blue Cubes Ltd. All rights reserved. * * Distributed under the Boost Software License, Version 1.0. (See accompanying * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) */ #ifndef TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED #define TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED -// start catch.hpp +#define TWOBLUECUBES_CATCH_HPP_INCLUDED #ifdef __clang__ # pragma clang system_header @@ -19,7 +19,7 @@ # pragma GCC system_header #endif -// start catch_suppress_warnings.h +// #included from: internal/catch_suppress_warnings.h #ifdef __clang__ # ifdef __ICC // icpc defines the __clang__ macro @@ -32,6 +32,8 @@ # pragma clang diagnostic ignored "-Wunused-variable" # pragma clang diagnostic push # pragma clang diagnostic ignored "-Wpadded" +# pragma clang diagnostic ignored "-Wc++98-compat" +# pragma clang diagnostic ignored "-Wc++98-compat-pedantic" # pragma clang diagnostic ignored "-Wswitch-enum" # pragma clang diagnostic ignored "-Wcovered-switch-default" # endif @@ -43,33 +45,10 @@ # pragma GCC diagnostic push # pragma GCC diagnostic ignored "-Wpadded" #endif -// end catch_suppress_warnings.h #if defined(CATCH_CONFIG_MAIN) || defined(CATCH_CONFIG_RUNNER) # define CATCH_IMPL -# define CATCH_CONFIG_EXTERNAL_INTERFACES -# if defined(CATCH_CONFIG_DISABLE_MATCHERS) -# undef CATCH_CONFIG_DISABLE_MATCHERS -# endif #endif -// start catch_platform.h - -#ifdef __APPLE__ -# include -# if TARGET_OS_MAC == 1 -# define CATCH_PLATFORM_MAC -# elif TARGET_OS_IPHONE == 1 -# define CATCH_PLATFORM_IPHONE -# endif - -#elif defined(linux) || defined(__linux) || defined(__linux__) -# define CATCH_PLATFORM_LINUX - -#elif defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) -# define CATCH_PLATFORM_WINDOWS -#endif - -// end catch_platform.h #ifdef CATCH_IMPL # ifndef CLARA_CONFIG_MAIN # define CLARA_CONFIG_MAIN_NOT_DEFINED @@ -77,15 +56,32 @@ # endif #endif -// start catch_tag_alias_autoregistrar.h +// #included from: internal/catch_notimplemented_exception.h +#define TWOBLUECUBES_CATCH_NOTIMPLEMENTED_EXCEPTION_H_INCLUDED -// start catch_common.h +// #included from: catch_common.h +#define TWOBLUECUBES_CATCH_COMMON_H_INCLUDED -// start catch_compiler_capabilities.h +// #included from: catch_compiler_capabilities.h +#define TWOBLUECUBES_CATCH_COMPILER_CAPABILITIES_HPP_INCLUDED -// Detect a number of compiler features - by compiler +// Detect a number of compiler features - mostly C++11/14 conformance - by compiler // The following features are defined: // +// CATCH_CONFIG_CPP11_NULLPTR : is nullptr supported? +// CATCH_CONFIG_CPP11_NOEXCEPT : is noexcept supported? +// CATCH_CONFIG_CPP11_GENERATED_METHODS : The delete and default keywords for compiler generated methods +// CATCH_CONFIG_CPP11_IS_ENUM : std::is_enum is supported? +// CATCH_CONFIG_CPP11_TUPLE : std::tuple is supported +// CATCH_CONFIG_CPP11_LONG_LONG : is long long supported? +// CATCH_CONFIG_CPP11_OVERRIDE : is override supported? +// CATCH_CONFIG_CPP11_UNIQUE_PTR : is unique_ptr supported (otherwise use auto_ptr) +// CATCH_CONFIG_CPP11_SHUFFLE : is std::shuffle supported? +// CATCH_CONFIG_CPP11_TYPE_TRAITS : are type_traits and enable_if supported? + +// CATCH_CONFIG_CPP11_OR_GREATER : Is C++11 supported? + +// CATCH_CONFIG_VARIADIC_MACROS : are variadic macros supported? // CATCH_CONFIG_COUNTER : is the __COUNTER__ macro supported? // CATCH_CONFIG_WINDOWS_SEH : is Windows SEH supported? // CATCH_CONFIG_POSIX_SIGNALS : are POSIX signals supported? @@ -95,12 +91,18 @@ // **************** // In general each macro has a _NO_ form -// (e.g. CATCH_CONFIG_NO_POSIX_SIGNALS) which disables the feature. +// (e.g. CATCH_CONFIG_CPP11_NO_NULLPTR) which disables the feature. // Many features, at point of detection, define an _INTERNAL_ macro, so they // can be combined, en-mass, with the _NO_ forms later. +// All the C++11 features can be disabled with CATCH_CONFIG_NO_CPP11 + #ifdef __cplusplus +# if __cplusplus >= 201103L +# define CATCH_CPP11_OR_GREATER +# endif + # if __cplusplus >= 201402L # define CATCH_CPP14_OR_GREATER # endif @@ -109,11 +111,19 @@ #ifdef __clang__ -# define CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ +# if __has_feature(cxx_nullptr) +# define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR +# endif + +# if __has_feature(cxx_noexcept) +# define CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT +# endif + +# if defined(CATCH_CPP11_OR_GREATER) +# define CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS \ _Pragma( "clang diagnostic push" ) \ - _Pragma( "clang diagnostic ignored \"-Wexit-time-destructors\"" ) \ - _Pragma( "clang diagnostic ignored \"-Wglobal-constructors\"") -# define CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS \ + _Pragma( "clang diagnostic ignored \"-Wexit-time-destructors\"" ) +# define CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS \ _Pragma( "clang diagnostic pop" ) # define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \ @@ -121,6 +131,7 @@ _Pragma( "clang diagnostic ignored \"-Wparentheses\"" ) # define CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS \ _Pragma( "clang diagnostic pop" ) +# endif #endif // __clang__ @@ -149,34 +160,167 @@ #endif // __CYGWIN__ +//////////////////////////////////////////////////////////////////////////////// +// Borland +#ifdef __BORLANDC__ + +#endif // __BORLANDC__ + +//////////////////////////////////////////////////////////////////////////////// +// EDG +#ifdef __EDG_VERSION__ + +#endif // __EDG_VERSION__ + +//////////////////////////////////////////////////////////////////////////////// +// Digital Mars +#ifdef __DMC__ + +#endif // __DMC__ + +//////////////////////////////////////////////////////////////////////////////// +// GCC +#ifdef __GNUC__ + +# if __GNUC__ == 4 && __GNUC_MINOR__ >= 6 && defined(__GXX_EXPERIMENTAL_CXX0X__) +# define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR +# endif + +// - otherwise more recent versions define __cplusplus >= 201103L +// and will get picked up below + +#endif // __GNUC__ + //////////////////////////////////////////////////////////////////////////////// // Visual C++ #ifdef _MSC_VER -// Universal Windows platform does not support SEH -// Or console colours (or console at all...) -# if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_APP) -# define CATCH_CONFIG_COLOUR_NONE -# else -# define CATCH_INTERNAL_CONFIG_WINDOWS_SEH -# endif +#define CATCH_INTERNAL_CONFIG_WINDOWS_SEH + +#if (_MSC_VER >= 1600) +# define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR +# define CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR +#endif + +#if (_MSC_VER >= 1900 ) // (VC++ 13 (VS2015)) +#define CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT +#define CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS +#define CATCH_INTERNAL_CONFIG_CPP11_SHUFFLE +#define CATCH_INTERNAL_CONFIG_CPP11_TYPE_TRAITS +#endif #endif // _MSC_VER //////////////////////////////////////////////////////////////////////////////// -// Use of __COUNTER__ is suppressed during code analysis in -// CLion/AppCode 2017.2.x and former, because __COUNTER__ is not properly -// handled by it. -// Otherwise all supported compilers support COUNTER macro, -// but user still might want to turn it off -#if ( !defined(__JETBRAINS_IDE__) || __JETBRAINS_IDE__ >= 20170300L ) - #define CATCH_INTERNAL_CONFIG_COUNTER +// Use variadic macros if the compiler supports them +#if ( defined _MSC_VER && _MSC_VER > 1400 && !defined __EDGE__) || \ + ( defined __WAVE__ && __WAVE_HAS_VARIADICS ) || \ + ( defined __GNUC__ && __GNUC__ >= 3 ) || \ + ( !defined __cplusplus && __STDC_VERSION__ >= 199901L || __cplusplus >= 201103L ) + +#define CATCH_INTERNAL_CONFIG_VARIADIC_MACROS + #endif -#if defined(CATCH_INTERNAL_CONFIG_COUNTER) && !defined(CATCH_CONFIG_NO_COUNTER) && !defined(CATCH_CONFIG_COUNTER) +// Use __COUNTER__ if the compiler supports it +#if ( defined _MSC_VER && _MSC_VER >= 1300 ) || \ + ( defined __GNUC__ && ( __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3 )) ) || \ + ( defined __clang__ && __clang_major__ >= 3 ) + +#define CATCH_INTERNAL_CONFIG_COUNTER + +#endif + +//////////////////////////////////////////////////////////////////////////////// +// C++ language feature support + +// catch all support for C++11 +#if defined(CATCH_CPP11_OR_GREATER) + +# if !defined(CATCH_INTERNAL_CONFIG_CPP11_NULLPTR) +# define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR +# endif + +# ifndef CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT +# define CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT +# endif + +# ifndef CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS +# define CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS +# endif + +# ifndef CATCH_INTERNAL_CONFIG_CPP11_IS_ENUM +# define CATCH_INTERNAL_CONFIG_CPP11_IS_ENUM +# endif + +# ifndef CATCH_INTERNAL_CONFIG_CPP11_TUPLE +# define CATCH_INTERNAL_CONFIG_CPP11_TUPLE +# endif + +# ifndef CATCH_INTERNAL_CONFIG_VARIADIC_MACROS +# define CATCH_INTERNAL_CONFIG_VARIADIC_MACROS +# endif + +# if !defined(CATCH_INTERNAL_CONFIG_CPP11_LONG_LONG) +# define CATCH_INTERNAL_CONFIG_CPP11_LONG_LONG +# endif + +# if !defined(CATCH_INTERNAL_CONFIG_CPP11_OVERRIDE) +# define CATCH_INTERNAL_CONFIG_CPP11_OVERRIDE +# endif +# if !defined(CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR) +# define CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR +# endif +# if !defined(CATCH_INTERNAL_CONFIG_CPP11_SHUFFLE) +# define CATCH_INTERNAL_CONFIG_CPP11_SHUFFLE +# endif +# if !defined(CATCH_INTERNAL_CONFIG_CPP11_TYPE_TRAITS) +# define CATCH_INTERNAL_CONFIG_CPP11_TYPE_TRAITS +# endif + +#endif // __cplusplus >= 201103L + +// Now set the actual defines based on the above + anything the user has configured +#if defined(CATCH_INTERNAL_CONFIG_CPP11_NULLPTR) && !defined(CATCH_CONFIG_CPP11_NO_NULLPTR) && !defined(CATCH_CONFIG_CPP11_NULLPTR) && !defined(CATCH_CONFIG_NO_CPP11) +# define CATCH_CONFIG_CPP11_NULLPTR +#endif +#if defined(CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT) && !defined(CATCH_CONFIG_CPP11_NO_NOEXCEPT) && !defined(CATCH_CONFIG_CPP11_NOEXCEPT) && !defined(CATCH_CONFIG_NO_CPP11) +# define CATCH_CONFIG_CPP11_NOEXCEPT +#endif +#if defined(CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS) && !defined(CATCH_CONFIG_CPP11_NO_GENERATED_METHODS) && !defined(CATCH_CONFIG_CPP11_GENERATED_METHODS) && !defined(CATCH_CONFIG_NO_CPP11) +# define CATCH_CONFIG_CPP11_GENERATED_METHODS +#endif +#if defined(CATCH_INTERNAL_CONFIG_CPP11_IS_ENUM) && !defined(CATCH_CONFIG_CPP11_NO_IS_ENUM) && !defined(CATCH_CONFIG_CPP11_IS_ENUM) && !defined(CATCH_CONFIG_NO_CPP11) +# define CATCH_CONFIG_CPP11_IS_ENUM +#endif +#if defined(CATCH_INTERNAL_CONFIG_CPP11_TUPLE) && !defined(CATCH_CONFIG_CPP11_NO_TUPLE) && !defined(CATCH_CONFIG_CPP11_TUPLE) && !defined(CATCH_CONFIG_NO_CPP11) +# define CATCH_CONFIG_CPP11_TUPLE +#endif +#if defined(CATCH_INTERNAL_CONFIG_VARIADIC_MACROS) && !defined(CATCH_CONFIG_NO_VARIADIC_MACROS) && !defined(CATCH_CONFIG_VARIADIC_MACROS) +# define CATCH_CONFIG_VARIADIC_MACROS +#endif +#if defined(CATCH_INTERNAL_CONFIG_CPP11_LONG_LONG) && !defined(CATCH_CONFIG_CPP11_NO_LONG_LONG) && !defined(CATCH_CONFIG_CPP11_LONG_LONG) && !defined(CATCH_CONFIG_NO_CPP11) +# define CATCH_CONFIG_CPP11_LONG_LONG +#endif +#if defined(CATCH_INTERNAL_CONFIG_CPP11_OVERRIDE) && !defined(CATCH_CONFIG_CPP11_NO_OVERRIDE) && !defined(CATCH_CONFIG_CPP11_OVERRIDE) && !defined(CATCH_CONFIG_NO_CPP11) +# define CATCH_CONFIG_CPP11_OVERRIDE +#endif +#if defined(CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR) && !defined(CATCH_CONFIG_CPP11_NO_UNIQUE_PTR) && !defined(CATCH_CONFIG_CPP11_UNIQUE_PTR) && !defined(CATCH_CONFIG_NO_CPP11) +# define CATCH_CONFIG_CPP11_UNIQUE_PTR +#endif +// Use of __COUNTER__ is suppressed if __JETBRAINS_IDE__ is #defined (meaning we're being parsed by a JetBrains IDE for +// analytics) because, at time of writing, __COUNTER__ is not properly handled by it. +// This does not affect compilation +#if defined(CATCH_INTERNAL_CONFIG_COUNTER) && !defined(CATCH_CONFIG_NO_COUNTER) && !defined(CATCH_CONFIG_COUNTER) && !defined(__JETBRAINS_IDE__) # define CATCH_CONFIG_COUNTER #endif +#if defined(CATCH_INTERNAL_CONFIG_CPP11_SHUFFLE) && !defined(CATCH_CONFIG_CPP11_NO_SHUFFLE) && !defined(CATCH_CONFIG_CPP11_SHUFFLE) && !defined(CATCH_CONFIG_NO_CPP11) +# define CATCH_CONFIG_CPP11_SHUFFLE +#endif +# if defined(CATCH_INTERNAL_CONFIG_CPP11_TYPE_TRAITS) && !defined(CATCH_CONFIG_CPP11_NO_TYPE_TRAITS) && !defined(CATCH_CONFIG_CPP11_TYPE_TRAITS) && !defined(CATCH_CONFIG_NO_CPP11) +# define CATCH_CONFIG_CPP11_TYPE_TRAITS +# endif #if defined(CATCH_INTERNAL_CONFIG_WINDOWS_SEH) && !defined(CATCH_CONFIG_NO_WINDOWS_SEH) && !defined(CATCH_CONFIG_WINDOWS_SEH) # define CATCH_CONFIG_WINDOWS_SEH #endif @@ -189,12 +333,41 @@ # define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS # define CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS #endif -#if !defined(CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS) -# define CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS -# define CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS +#if !defined(CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS) +# define CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS +# define CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS +#endif + +// noexcept support: +#if defined(CATCH_CONFIG_CPP11_NOEXCEPT) && !defined(CATCH_NOEXCEPT) +# define CATCH_NOEXCEPT noexcept +# define CATCH_NOEXCEPT_IS(x) noexcept(x) +#else +# define CATCH_NOEXCEPT throw() +# define CATCH_NOEXCEPT_IS(x) +#endif + +// nullptr support +#ifdef CATCH_CONFIG_CPP11_NULLPTR +# define CATCH_NULL nullptr +#else +# define CATCH_NULL NULL +#endif + +// override support +#ifdef CATCH_CONFIG_CPP11_OVERRIDE +# define CATCH_OVERRIDE override +#else +# define CATCH_OVERRIDE +#endif + +// unique_ptr support +#ifdef CATCH_CONFIG_CPP11_UNIQUE_PTR +# define CATCH_AUTO_PTR( T ) std::unique_ptr +#else +# define CATCH_AUTO_PTR( T ) std::auto_ptr #endif -// end catch_compiler_capabilities.h #define INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) name##line #define INTERNAL_CATCH_UNIQUE_NAME_LINE( name, line ) INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) #ifdef CATCH_CONFIG_COUNTER @@ -203,41 +376,95 @@ # define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __LINE__ ) #endif -#include -#include -#include +#define INTERNAL_CATCH_STRINGIFY2( expr ) #expr +#define INTERNAL_CATCH_STRINGIFY( expr ) INTERNAL_CATCH_STRINGIFY2( expr ) + +#include +#include namespace Catch { + struct IConfig; + struct CaseSensitive { enum Choice { Yes, No }; }; class NonCopyable { +#ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS NonCopyable( NonCopyable const& ) = delete; NonCopyable( NonCopyable && ) = delete; NonCopyable& operator = ( NonCopyable const& ) = delete; NonCopyable& operator = ( NonCopyable && ) = delete; +#else + NonCopyable( NonCopyable const& info ); + NonCopyable& operator = ( NonCopyable const& ); +#endif protected: - NonCopyable(); + NonCopyable() {} virtual ~NonCopyable(); }; + class SafeBool { + public: + typedef void (SafeBool::*type)() const; + + static type makeSafe( bool value ) { + return value ? &SafeBool::trueValue : 0; + } + private: + void trueValue() const {} + }; + + template + 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 + 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 startsWith( std::string const& s, char prefix ); + bool endsWith( std::string const& s, std::string const& suffix ); + bool endsWith( std::string const& s, char suffix ); + bool contains( std::string const& s, std::string const& infix ); + void toLowerInPlace( std::string& s ); + std::string toLower( std::string const& s ); + std::string trim( std::string const& str ); + bool replaceInPlace( std::string& str, std::string const& replaceThis, std::string const& withThis ); + + struct pluralise { + pluralise( std::size_t count, std::string const& label ); + + friend std::ostream& operator << ( std::ostream& os, pluralise const& pluraliser ); + + std::size_t m_count; + std::string m_label; + }; + struct SourceLineInfo { - SourceLineInfo() = delete; - SourceLineInfo( char const* _file, std::size_t _line ) noexcept; - - SourceLineInfo( SourceLineInfo const& other ) = default; + SourceLineInfo(); + SourceLineInfo( char const* _file, std::size_t _line ); +# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS + SourceLineInfo(SourceLineInfo const& other) = default; SourceLineInfo( SourceLineInfo && ) = default; SourceLineInfo& operator = ( SourceLineInfo const& ) = default; SourceLineInfo& operator = ( SourceLineInfo && ) = default; - - bool empty() const noexcept; - bool operator == ( SourceLineInfo const& other ) const noexcept; - bool operator < ( SourceLineInfo const& other ) const noexcept; +# endif + bool empty() const; + bool operator == ( SourceLineInfo const& other ) const; + bool operator < ( SourceLineInfo const& other ) const; char const* file; std::size_t line; @@ -246,16 +473,23 @@ namespace Catch { std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info ); // This is just here to avoid compiler warnings with macro constants and boolean literals - bool isTrue( bool value ); - bool alwaysTrue(); - bool alwaysFalse(); + inline bool isTrue( bool value ){ return value; } + inline bool alwaysTrue() { return true; } + inline bool alwaysFalse() { return false; } + + void throwLogicError( std::string const& message, SourceLineInfo const& locationInfo ); + + void seedRng( IConfig const& config ); + unsigned int rngSeed(); // Use this in variadic streaming macros to allow // >> +StreamEndStop // as well as // >> stuff +StreamEndStop struct StreamEndStop { - std::string operator+() const; + std::string operator+() { + return std::string(); + } }; template T const& operator + ( T const& value, StreamEndStop ) { @@ -263,39 +497,193 @@ namespace Catch { } } -#define CATCH_INTERNAL_LINEINFO \ - ::Catch::SourceLineInfo( __FILE__, static_cast( __LINE__ ) ) +#define CATCH_INTERNAL_LINEINFO ::Catch::SourceLineInfo( __FILE__, static_cast( __LINE__ ) ) +#define CATCH_INTERNAL_ERROR( msg ) ::Catch::throwLogicError( msg, CATCH_INTERNAL_LINEINFO ); -// end catch_common.h namespace Catch { - struct RegistrarForTagAliases { - RegistrarForTagAliases( char const* alias, char const* tag, SourceLineInfo const& lineInfo ); + class NotImplementedException : public std::exception + { + public: + NotImplementedException( SourceLineInfo const& lineInfo ); + + virtual ~NotImplementedException() CATCH_NOEXCEPT {} + + virtual const char* what() const CATCH_NOEXCEPT; + + private: + std::string m_what; + SourceLineInfo m_lineInfo; }; } // end namespace Catch -#define CATCH_REGISTER_TAG_ALIAS( alias, spec ) namespace{ Catch::RegistrarForTagAliases INTERNAL_CATCH_UNIQUE_NAME( AutoRegisterTagAlias )( alias, spec, CATCH_INTERNAL_LINEINFO ); } +/////////////////////////////////////////////////////////////////////////////// +#define CATCH_NOT_IMPLEMENTED throw Catch::NotImplementedException( CATCH_INTERNAL_LINEINFO ) -// end catch_tag_alias_autoregistrar.h -// start catch_test_registry.h +// #included from: internal/catch_context.h +#define TWOBLUECUBES_CATCH_CONTEXT_H_INCLUDED -// start catch_interfaces_testcase.h +// #included from: catch_interfaces_generators.h +#define TWOBLUECUBES_CATCH_INTERFACES_GENERATORS_H_INCLUDED + +#include + +namespace Catch { + + struct IGeneratorInfo { + virtual ~IGeneratorInfo(); + virtual bool moveNext() = 0; + virtual std::size_t getCurrentIndex() const = 0; + }; + + struct IGeneratorsForTest { + virtual ~IGeneratorsForTest(); + + virtual IGeneratorInfo& getGeneratorInfo( std::string const& fileInfo, std::size_t size ) = 0; + virtual bool moveNext() = 0; + }; + + IGeneratorsForTest* createGeneratorsForTest(); + +} // end namespace Catch + +// #included from: catch_ptr.hpp +#define TWOBLUECUBES_CATCH_PTR_HPP_INCLUDED + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wpadded" +#endif + +namespace Catch { + + // An intrusive reference counting smart pointer. + // T must implement addRef() and release() methods + // typically implementing the IShared interface + template + class Ptr { + public: + Ptr() : m_p( CATCH_NULL ){} + Ptr( T* p ) : m_p( p ){ + if( m_p ) + m_p->addRef(); + } + Ptr( Ptr const& other ) : m_p( other.m_p ){ + if( m_p ) + m_p->addRef(); + } + ~Ptr(){ + if( m_p ) + m_p->release(); + } + void reset() { + if( m_p ) + m_p->release(); + m_p = CATCH_NULL; + } + Ptr& operator = ( T* p ){ + Ptr temp( p ); + swap( temp ); + return *this; + } + Ptr& operator = ( Ptr const& other ){ + Ptr temp( other ); + swap( temp ); + return *this; + } + void swap( Ptr& other ) { std::swap( m_p, other.m_p ); } + T* get() const{ return m_p; } + T& operator*() const { return *m_p; } + T* operator->() const { return m_p; } + bool operator !() const { return m_p == CATCH_NULL; } + operator SafeBool::type() const { return SafeBool::makeSafe( m_p != CATCH_NULL ); } + + private: + T* m_p; + }; + + struct IShared : NonCopyable { + virtual ~IShared(); + virtual void addRef() const = 0; + virtual void release() const = 0; + }; + + template + struct SharedImpl : T { + + SharedImpl() : m_rc( 0 ){} + + virtual void addRef() const { + ++m_rc; + } + virtual void release() const { + if( --m_rc == 0 ) + delete this; + } + + mutable unsigned int m_rc; + }; + +} // end namespace Catch + +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + +namespace Catch { + + class TestCase; + class Stream; + struct IResultCapture; + struct IRunner; + struct IGeneratorsForTest; + struct IConfig; + + struct IContext + { + virtual ~IContext(); + + virtual IResultCapture* getResultCapture() = 0; + virtual IRunner* getRunner() = 0; + virtual size_t getGeneratorIndex( std::string const& fileInfo, size_t totalSize ) = 0; + virtual bool advanceGeneratorsForCurrentTest() = 0; + virtual Ptr 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; + }; + + IContext& getCurrentContext(); + IMutableContext& getCurrentMutableContext(); + void cleanUpContext(); + Stream createStream( std::string const& streamName ); + +} + +// #included from: internal/catch_test_registry.hpp +#define TWOBLUECUBES_CATCH_TEST_REGISTRY_HPP_INCLUDED + +// #included from: catch_interfaces_testcase.h +#define TWOBLUECUBES_CATCH_INTERFACES_TESTCASE_H_INCLUDED #include -#include namespace Catch { class TestSpec; - struct ITestInvoker { + struct ITestCase : IShared { virtual void invoke () const = 0; - virtual ~ITestInvoker(); + protected: + virtual ~ITestCase(); }; - using ITestCasePtr = std::shared_ptr; - class TestCase; struct IConfig; @@ -311,180 +699,814 @@ namespace Catch { } -// end catch_interfaces_testcase.h -// start catch_stringref.h - -#include -#include -#include - -namespace Catch { - - class StringData; - - /// A non-owning string class (similar to the forthcoming std::string_view) - /// Note that, because a StringRef may be a substring of another string, - /// it may not be null terminated. c_str() must return a null terminated - /// string, however, and so the StringRef will internally take ownership - /// (taking a copy), if necessary. In theory this ownership is not externally - /// visible - but it does mean (substring) StringRefs should not be shared between - /// threads. - class StringRef { - friend struct StringRefTestAccess; - - using size_type = std::size_t; - - char const* m_start; - size_type m_size; - - char* m_data = nullptr; - - void takeOwnership(); - - public: // construction/ assignment - StringRef() noexcept; - StringRef( StringRef const& other ) noexcept; - StringRef( StringRef&& other ) noexcept; - StringRef( char const* rawChars ) noexcept; - StringRef( char const* rawChars, size_type size ) noexcept; - StringRef( std::string const& stdString ) noexcept; - ~StringRef() noexcept; - - auto operator = ( StringRef other ) noexcept -> StringRef&; - operator std::string() const; - - void swap( StringRef& other ) noexcept; - - public: // operators - auto operator == ( StringRef const& other ) const noexcept -> bool; - auto operator != ( StringRef const& other ) const noexcept -> bool; - - auto operator[] ( size_type index ) const noexcept -> char; - - public: // named queries - auto empty() const noexcept -> bool; - auto size() const noexcept -> size_type; - auto numberOfCharacters() const noexcept -> size_type; - auto c_str() const -> char const*; - - public: // substrings and searches - auto substr( size_type start, size_type size ) const noexcept -> StringRef; - - private: // ownership queries - may not be consistent between calls - auto isOwned() const noexcept -> bool; - auto isSubstring() const noexcept -> bool; - auto data() const noexcept -> char const*; - }; - - auto operator + ( StringRef const& lhs, StringRef const& rhs ) -> std::string; - auto operator + ( StringRef const& lhs, char const* rhs ) -> std::string; - auto operator + ( char const* lhs, StringRef const& rhs ) -> std::string; - - auto operator << ( std::ostream& os, StringRef const& sr ) -> std::ostream&; - -} // namespace Catch - -// end catch_stringref.h namespace Catch { template -class TestInvokerAsMethod : public ITestInvoker { - void (C::*m_testAsMethod)(); +class MethodTestCase : public SharedImpl { + public: - TestInvokerAsMethod( void (C::*testAsMethod)() ) noexcept : m_testAsMethod( testAsMethod ) {} + MethodTestCase( void (C::*method)() ) : m_method( method ) {} - void invoke() const override { + virtual void invoke() const { C obj; - (obj.*m_testAsMethod)(); + (obj.*m_method)(); } + +private: + virtual ~MethodTestCase() {} + + void (C::*m_method)(); }; -auto makeTestInvoker( void(*testAsFunction)() ) noexcept -> ITestInvoker*; +typedef void(*TestFunction)(); -template -auto makeTestInvoker( void (C::*testAsMethod)() ) noexcept -> ITestInvoker* { - return new(std::nothrow) TestInvokerAsMethod( testAsMethod ); -} +struct NameAndDesc { + NameAndDesc( const char* _name = "", const char* _description= "" ) + : name( _name ), description( _description ) + {} -struct NameAndTags { - NameAndTags( StringRef name_ = "", StringRef tags_ = "" ) noexcept; - StringRef name; - StringRef tags; + const char* name; + const char* description; }; -struct AutoReg : NonCopyable { - AutoReg( ITestInvoker* invoker, SourceLineInfo const& lineInfo, StringRef classOrMethod, NameAndTags const& nameAndTags ) noexcept; +void registerTestCase + ( ITestCase* testCase, + char const* className, + NameAndDesc const& nameAndDesc, + SourceLineInfo const& lineInfo ); + +struct AutoReg { + + AutoReg + ( TestFunction function, + SourceLineInfo const& lineInfo, + NameAndDesc const& nameAndDesc ); + + template + AutoReg + ( void (C::*method)(), + char const* className, + NameAndDesc const& nameAndDesc, + SourceLineInfo const& lineInfo ) { + + registerTestCase + ( new MethodTestCase( method ), + className, + nameAndDesc, + lineInfo ); + } + ~AutoReg(); + +private: + AutoReg( AutoReg const& ); + void operator= ( AutoReg const& ); }; +void registerTestCaseFunction + ( TestFunction function, + SourceLineInfo const& lineInfo, + NameAndDesc const& nameAndDesc ); + } // end namespace Catch -#if defined(CATCH_CONFIG_DISABLE) - #define INTERNAL_CATCH_TESTCASE_NO_REGISTRATION( TestName, ... ) \ - static void TestName() - #define INTERNAL_CATCH_TESTCASE_METHOD_NO_REGISTRATION( TestName, ClassName, ... ) \ - namespace{ \ - struct TestName : ClassName { \ - void test(); \ - }; \ - } \ - void TestName::test() - -#endif - +#ifdef CATCH_CONFIG_VARIADIC_MACROS /////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CATCH_TESTCASE2( TestName, ... ) \ static void TestName(); \ - CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ - namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( Catch::makeTestInvoker( &TestName ), CATCH_INTERNAL_LINEINFO, "", Catch::NameAndTags{ __VA_ARGS__ } ); } /* NOLINT */ \ - CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS \ + CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS \ + namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &TestName, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( __VA_ARGS__ ) ); } /* NOLINT */ \ + CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS \ static void TestName() #define INTERNAL_CATCH_TESTCASE( ... ) \ INTERNAL_CATCH_TESTCASE2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), __VA_ARGS__ ) /////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, ... ) \ - CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ - namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( Catch::makeTestInvoker( &QualifiedMethod ), CATCH_INTERNAL_LINEINFO, "&" #QualifiedMethod, Catch::NameAndTags{ __VA_ARGS__ } ); } /* NOLINT */ \ - CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS + CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS \ + namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &QualifiedMethod, "&" #QualifiedMethod, Catch::NameAndDesc( __VA_ARGS__ ), CATCH_INTERNAL_LINEINFO ); } /* NOLINT */ \ + CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS /////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CATCH_TEST_CASE_METHOD2( TestName, ClassName, ... )\ - CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ + CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS \ namespace{ \ struct TestName : ClassName{ \ void test(); \ }; \ - Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( Catch::makeTestInvoker( &TestName::test ), CATCH_INTERNAL_LINEINFO, #ClassName, Catch::NameAndTags{ __VA_ARGS__ } ); /* NOLINT */ \ + Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( &TestName::test, #ClassName, Catch::NameAndDesc( __VA_ARGS__ ), CATCH_INTERNAL_LINEINFO ); /* NOLINT */ \ } \ - CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS \ + CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS \ void TestName::test() #define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, ... ) \ INTERNAL_CATCH_TEST_CASE_METHOD2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), ClassName, __VA_ARGS__ ) /////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CATCH_REGISTER_TESTCASE( Function, ... ) \ - CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ - Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( Catch::makeTestInvoker( Function ), CATCH_INTERNAL_LINEINFO, "", Catch::NameAndTags{ __VA_ARGS__ } ); /* NOLINT */ \ - CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS + CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS \ + Catch::AutoReg( Function, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( __VA_ARGS__ ) ); /* NOLINT */ \ + CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS -// end catch_test_registry.h -// start catch_capture.hpp +#else + /////////////////////////////////////////////////////////////////////////////// + #define INTERNAL_CATCH_TESTCASE2( TestName, Name, Desc ) \ + static void TestName(); \ + CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS \ + namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &TestName, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( Name, Desc ) ); } /* NOLINT */ \ + CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS \ + static void TestName() + #define INTERNAL_CATCH_TESTCASE( Name, Desc ) \ + INTERNAL_CATCH_TESTCASE2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), Name, Desc ) -// start catch_assertionhandler.h + /////////////////////////////////////////////////////////////////////////////// + #define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, Name, Desc ) \ + CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS \ + namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &QualifiedMethod, "&" #QualifiedMethod, Catch::NameAndDesc( Name, Desc ), CATCH_INTERNAL_LINEINFO ); } /* NOLINT */ \ + CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS -// start catch_decomposer.h + /////////////////////////////////////////////////////////////////////////////// + #define INTERNAL_CATCH_TEST_CASE_METHOD2( TestCaseName, ClassName, TestName, Desc )\ + CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS \ + namespace{ \ + struct TestCaseName : ClassName{ \ + void test(); \ + }; \ + Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( &TestCaseName::test, #ClassName, Catch::NameAndDesc( TestName, Desc ), CATCH_INTERNAL_LINEINFO ); /* NOLINT */ \ + } \ + CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS \ + void TestCaseName::test() + #define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, TestName, Desc )\ + INTERNAL_CATCH_TEST_CASE_METHOD2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), ClassName, TestName, Desc ) -// start catch_tostring.h + /////////////////////////////////////////////////////////////////////////////// + #define INTERNAL_CATCH_REGISTER_TESTCASE( Function, Name, Desc ) \ + CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS \ + Catch::AutoReg( Function, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( Name, Desc ) ); /* NOLINT */ \ + CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS + +#endif + +// #included from: internal/catch_capture.hpp +#define TWOBLUECUBES_CATCH_CAPTURE_HPP_INCLUDED + +// #included from: catch_result_builder.h +#define TWOBLUECUBES_CATCH_RESULT_BUILDER_H_INCLUDED + +// #included from: catch_result_type.h +#define TWOBLUECUBES_CATCH_RESULT_TYPE_H_INCLUDED + +namespace Catch { + + // ResultWas::OfType enum + struct ResultWas { enum OfType { + Unknown = -1, + Ok = 0, + Info = 1, + Warning = 2, + + FailureBit = 0x10, + + ExpressionFailed = FailureBit | 1, + ExplicitFailure = FailureBit | 2, + + Exception = 0x100 | FailureBit, + + ThrewException = Exception | 1, + DidntThrowException = Exception | 2, + + FatalErrorCondition = 0x200 | FailureBit + + }; }; + + inline bool isOk( ResultWas::OfType resultType ) { + return ( resultType & ResultWas::FailureBit ) == 0; + } + inline bool isJustInfo( int flags ) { + return flags == ResultWas::Info; + } + + // ResultDisposition::Flags enum + struct ResultDisposition { enum Flags { + Normal = 0x01, + + ContinueOnFailure = 0x02, // Failures fail test, but execution continues + FalseTest = 0x04, // Prefix expression with ! + SuppressFail = 0x08 // Failures are reported but do not fail the test + }; }; + + inline ResultDisposition::Flags operator | ( ResultDisposition::Flags lhs, ResultDisposition::Flags rhs ) { + return static_cast( 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; } + +} // end namespace Catch + +// #included from: catch_assertionresult.h +#define TWOBLUECUBES_CATCH_ASSERTIONRESULT_H_INCLUDED -#include -#include -#include -#include #include +namespace Catch { + + struct STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison; + + struct DecomposedExpression + { + virtual ~DecomposedExpression() {} + virtual bool isBinaryExpression() const { + return false; + } + virtual void reconstructExpression( std::string& dest ) const = 0; + + // Only simple binary comparisons can be decomposed. + // If more complex check is required then wrap sub-expressions in parentheses. + template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator + ( T const& ); + template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator - ( T const& ); + template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator * ( T const& ); + template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator / ( T const& ); + template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator % ( T const& ); + template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator && ( T const& ); + template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator || ( T const& ); + + private: + DecomposedExpression& operator = (DecomposedExpression const&); + }; + + struct AssertionInfo + { + AssertionInfo(); + AssertionInfo( char const * _macroName, + SourceLineInfo const& _lineInfo, + char const * _capturedExpression, + ResultDisposition::Flags _resultDisposition, + char const * _secondArg = ""); + + char const * macroName; + SourceLineInfo lineInfo; + char const * capturedExpression; + ResultDisposition::Flags resultDisposition; + char const * secondArg; + }; + + struct AssertionResultData + { + AssertionResultData() : decomposedExpression( CATCH_NULL ) + , resultType( ResultWas::Unknown ) + , negated( false ) + , parenthesized( false ) {} + + void negate( bool parenthesize ) { + negated = !negated; + parenthesized = parenthesize; + if( resultType == ResultWas::Ok ) + resultType = ResultWas::ExpressionFailed; + else if( resultType == ResultWas::ExpressionFailed ) + resultType = ResultWas::Ok; + } + + std::string const& reconstructExpression() const { + if( decomposedExpression != CATCH_NULL ) { + decomposedExpression->reconstructExpression( reconstructedExpression ); + if( parenthesized ) { + reconstructedExpression.insert( 0, 1, '(' ); + reconstructedExpression.append( 1, ')' ); + } + if( negated ) { + reconstructedExpression.insert( 0, 1, '!' ); + } + decomposedExpression = CATCH_NULL; + } + return reconstructedExpression; + } + + mutable DecomposedExpression const* decomposedExpression; + mutable std::string reconstructedExpression; + std::string message; + ResultWas::OfType resultType; + bool negated; + bool parenthesized; + }; + + class AssertionResult { + public: + AssertionResult(); + AssertionResult( AssertionInfo const& info, AssertionResultData const& data ); + ~AssertionResult(); +# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS + AssertionResult( AssertionResult const& ) = default; + AssertionResult( AssertionResult && ) = default; + AssertionResult& operator = ( AssertionResult const& ) = default; + AssertionResult& operator = ( AssertionResult && ) = default; +# endif + + bool isOk() const; + bool succeeded() const; + ResultWas::OfType getResultType() const; + bool hasExpression() const; + bool hasMessage() const; + std::string getExpression() const; + std::string getExpressionInMacro() const; + bool hasExpandedExpression() const; + std::string getExpandedExpression() const; + std::string getMessage() const; + SourceLineInfo getSourceInfo() const; + std::string getTestMacroName() const; + void discardDecomposedExpression() const; + void expandDecomposedExpression() const; + + protected: + AssertionInfo m_info; + AssertionResultData m_resultData; + }; + +} // end namespace Catch + +// #included from: catch_matchers.hpp +#define TWOBLUECUBES_CATCH_MATCHERS_HPP_INCLUDED + +namespace Catch { +namespace Matchers { + namespace Impl { + + template struct MatchAllOf; + template struct MatchAnyOf; + template struct MatchNotOf; + + class MatcherUntypedBase { + public: + std::string toString() const { + if( m_cachedToString.empty() ) + m_cachedToString = describe(); + return m_cachedToString; + } + + protected: + virtual ~MatcherUntypedBase(); + virtual std::string describe() const = 0; + mutable std::string m_cachedToString; + private: + MatcherUntypedBase& operator = ( MatcherUntypedBase const& ); + }; + + template + struct MatcherMethod { + virtual bool match( ObjectT const& arg ) const = 0; + }; + template + struct MatcherMethod { + virtual bool match( PtrT* arg ) const = 0; + }; + + template + struct MatcherBase : MatcherUntypedBase, MatcherMethod { + + MatchAllOf operator && ( MatcherBase const& other ) const; + MatchAnyOf operator || ( MatcherBase const& other ) const; + MatchNotOf operator ! () const; + }; + + template + struct MatchAllOf : MatcherBase { + virtual bool match( ArgT const& arg ) const CATCH_OVERRIDE { + for( std::size_t i = 0; i < m_matchers.size(); ++i ) { + if (!m_matchers[i]->match(arg)) + return false; + } + return true; + } + virtual std::string describe() const CATCH_OVERRIDE { + std::string description; + description.reserve( 4 + m_matchers.size()*32 ); + description += "( "; + for( std::size_t i = 0; i < m_matchers.size(); ++i ) { + if( i != 0 ) + description += " and "; + description += m_matchers[i]->toString(); + } + description += " )"; + return description; + } + + MatchAllOf& operator && ( MatcherBase const& other ) { + m_matchers.push_back( &other ); + return *this; + } + + std::vector const*> m_matchers; + }; + template + struct MatchAnyOf : MatcherBase { + + virtual bool match( ArgT const& arg ) const CATCH_OVERRIDE { + for( std::size_t i = 0; i < m_matchers.size(); ++i ) { + if (m_matchers[i]->match(arg)) + return true; + } + return false; + } + virtual std::string describe() const CATCH_OVERRIDE { + std::string description; + description.reserve( 4 + m_matchers.size()*32 ); + description += "( "; + for( std::size_t i = 0; i < m_matchers.size(); ++i ) { + if( i != 0 ) + description += " or "; + description += m_matchers[i]->toString(); + } + description += " )"; + return description; + } + + MatchAnyOf& operator || ( MatcherBase const& other ) { + m_matchers.push_back( &other ); + return *this; + } + + std::vector const*> m_matchers; + }; + + template + struct MatchNotOf : MatcherBase { + + MatchNotOf( MatcherBase const& underlyingMatcher ) : m_underlyingMatcher( underlyingMatcher ) {} + + virtual bool match( ArgT const& arg ) const CATCH_OVERRIDE { + return !m_underlyingMatcher.match( arg ); + } + + virtual std::string describe() const CATCH_OVERRIDE { + return "not " + m_underlyingMatcher.toString(); + } + MatcherBase const& m_underlyingMatcher; + }; + + template + MatchAllOf MatcherBase::operator && ( MatcherBase const& other ) const { + return MatchAllOf() && *this && other; + } + template + MatchAnyOf MatcherBase::operator || ( MatcherBase const& other ) const { + return MatchAnyOf() || *this || other; + } + template + MatchNotOf MatcherBase::operator ! () const { + return MatchNotOf( *this ); + } + + } // namespace Impl + + // The following functions create the actual matcher objects. + // This allows the types to be inferred + // - deprecated: prefer ||, && and ! + template + Impl::MatchNotOf Not( Impl::MatcherBase const& underlyingMatcher ) { + return Impl::MatchNotOf( underlyingMatcher ); + } + template + Impl::MatchAllOf AllOf( Impl::MatcherBase const& m1, Impl::MatcherBase const& m2 ) { + return Impl::MatchAllOf() && m1 && m2; + } + template + Impl::MatchAllOf AllOf( Impl::MatcherBase const& m1, Impl::MatcherBase const& m2, Impl::MatcherBase const& m3 ) { + return Impl::MatchAllOf() && m1 && m2 && m3; + } + template + Impl::MatchAnyOf AnyOf( Impl::MatcherBase const& m1, Impl::MatcherBase const& m2 ) { + return Impl::MatchAnyOf() || m1 || m2; + } + template + Impl::MatchAnyOf AnyOf( Impl::MatcherBase const& m1, Impl::MatcherBase const& m2, Impl::MatcherBase const& m3 ) { + return Impl::MatchAnyOf() || m1 || m2 || m3; + } + +} // namespace Matchers + +using namespace Matchers; +using Matchers::Impl::MatcherBase; + +} // namespace Catch + +namespace Catch { + + struct TestFailureException{}; + + template class ExpressionLhs; + + struct CopyableStream { + CopyableStream() {} + CopyableStream( CopyableStream const& other ) { + oss << other.oss.str(); + } + CopyableStream& operator=( CopyableStream const& other ) { + oss.str(std::string()); + oss << other.oss.str(); + return *this; + } + std::ostringstream oss; + }; + + class ResultBuilder : public DecomposedExpression { + public: + ResultBuilder( char const* macroName, + SourceLineInfo const& lineInfo, + char const* capturedExpression, + ResultDisposition::Flags resultDisposition, + char const* secondArg = "" ); + ~ResultBuilder(); + + template + ExpressionLhs operator <= ( T const& operand ); + ExpressionLhs operator <= ( bool value ); + + template + ResultBuilder& operator << ( T const& value ) { + stream().oss << value; + return *this; + } + + ResultBuilder& setResultType( ResultWas::OfType result ); + ResultBuilder& setResultType( bool result ); + + void endExpression( DecomposedExpression const& expr ); + + virtual void reconstructExpression( std::string& dest ) const CATCH_OVERRIDE; + + AssertionResult build() const; + AssertionResult build( DecomposedExpression const& expr ) const; + + void useActiveException( ResultDisposition::Flags resultDisposition = ResultDisposition::Normal ); + void captureResult( ResultWas::OfType resultType ); + void captureExpression(); + void captureExpectedException( std::string const& expectedMessage ); + void captureExpectedException( Matchers::Impl::MatcherBase const& matcher ); + void handleResult( AssertionResult const& result ); + void react(); + bool shouldDebugBreak() const; + bool allowThrows() const; + + template + void captureMatch( ArgT const& arg, MatcherT const& matcher, char const* matcherString ); + + void setExceptionGuard(); + void unsetExceptionGuard(); + + private: + AssertionInfo m_assertionInfo; + AssertionResultData m_data; + + CopyableStream &stream() + { + if(!m_usedStream) + { + m_usedStream = true; + m_stream().oss.str(""); + } + return m_stream(); + } + + static CopyableStream &m_stream() + { + static CopyableStream s; + return s; + } + + bool m_shouldDebugBreak; + bool m_shouldThrow; + bool m_guardException; + bool m_usedStream; + }; + +} // namespace Catch + +// Include after due to circular dependency: +// #included from: catch_expression_lhs.hpp +#define TWOBLUECUBES_CATCH_EXPRESSION_LHS_HPP_INCLUDED + +// #included from: catch_evaluate.hpp +#define TWOBLUECUBES_CATCH_EVALUATE_HPP_INCLUDED + +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable:4389) // '==' : signed/unsigned mismatch +#pragma warning(disable:4312) // Converting int to T* using reinterpret_cast (issue on x64 platform) +#endif + +#include + +namespace Catch { +namespace Internal { + + 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 + 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; } +#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 + struct Evaluator{}; + + template + struct Evaluator { + static bool evaluate( T1 const& lhs, T2 const& rhs) { + return bool( opCast( lhs ) == opCast( rhs ) ); + } + }; + template + struct Evaluator { + static bool evaluate( T1 const& lhs, T2 const& rhs ) { + return bool( opCast( lhs ) != opCast( rhs ) ); + } + }; + template + struct Evaluator { + static bool evaluate( T1 const& lhs, T2 const& rhs ) { + return bool( opCast( lhs ) < opCast( rhs ) ); + } + }; + template + struct Evaluator { + static bool evaluate( T1 const& lhs, T2 const& rhs ) { + return bool( opCast( lhs ) > opCast( rhs ) ); + } + }; + template + struct Evaluator { + static bool evaluate( T1 const& lhs, T2 const& rhs ) { + return bool( opCast( lhs ) >= opCast( rhs ) ); + } + }; + template + struct Evaluator { + static bool evaluate( T1 const& lhs, T2 const& rhs ) { + return bool( opCast( lhs ) <= opCast( rhs ) ); + } + }; + + template + bool applyEvaluator( T1 const& lhs, T2 const& rhs ) { + return Evaluator::evaluate( lhs, 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 ); + } + + // 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 ) ); + } + +#ifdef CATCH_CONFIG_CPP11_LONG_LONG + // long long to unsigned X + template bool compare( long long lhs, unsigned int rhs ) { + return applyEvaluator( static_cast( lhs ), rhs ); + } + template bool compare( long long lhs, unsigned long rhs ) { + return applyEvaluator( static_cast( lhs ), rhs ); + } + template bool compare( long long lhs, unsigned long long rhs ) { + return applyEvaluator( static_cast( lhs ), rhs ); + } + template bool compare( long long lhs, unsigned char rhs ) { + return applyEvaluator( static_cast( lhs ), rhs ); + } + + // unsigned long long to X + template bool compare( unsigned long long lhs, int rhs ) { + return applyEvaluator( static_cast( lhs ), rhs ); + } + template bool compare( unsigned long long lhs, long rhs ) { + return applyEvaluator( static_cast( lhs ), rhs ); + } + template bool compare( unsigned long long lhs, long long rhs ) { + return applyEvaluator( static_cast( lhs ), rhs ); + } + template bool compare( unsigned long long lhs, char rhs ) { + return applyEvaluator( static_cast( lhs ), rhs ); + } + + // pointer to long long (when comparing against NULL) + template bool compare( long long lhs, T* rhs ) { + return Evaluator::evaluate( reinterpret_cast( lhs ), rhs ); + } + template bool compare( T* lhs, long long rhs ) { + return Evaluator::evaluate( lhs, reinterpret_cast( rhs ) ); + } +#endif // CATCH_CONFIG_CPP11_LONG_LONG + +#ifdef CATCH_CONFIG_CPP11_NULLPTR + // pointer to nullptr_t (when comparing against nullptr) + template bool compare( std::nullptr_t, T* rhs ) { + return Evaluator::evaluate( nullptr, rhs ); + } + template bool compare( T* lhs, std::nullptr_t ) { + return Evaluator::evaluate( lhs, nullptr ); + } +#endif // CATCH_CONFIG_CPP11_NULLPTR + +} // end of namespace Internal +} // end of namespace Catch + +#ifdef _MSC_VER +#pragma warning(pop) +#endif + +// #included from: catch_tostring.h +#define TWOBLUECUBES_CATCH_TOSTRING_H_INCLUDED + +#include +#include +#include +#include +#include + #ifdef __OBJC__ -// start catch_objc_arc.hpp +// #included from: catch_objc_arc.hpp +#define TWOBLUECUBES_CATCH_OBJC_ARC_HPP_INCLUDED #import @@ -526,735 +1548,451 @@ inline id performOptionalSelector( id obj, SEL sel ) { #define CATCH_ARC_STRONG __strong #endif -// end catch_objc_arc.hpp #endif -#ifdef _MSC_VER -#pragma warning(push) -#pragma warning(disable:4180) // We attempt to stream a function (address) by const&, which MSVC complains about but is harmless +#ifdef CATCH_CONFIG_CPP11_TUPLE +#include #endif -// We need a dummy global operator<< so we can bring it into Catch namespace later -struct Catch_global_namespace_dummy; -std::ostream& operator<<(std::ostream&, Catch_global_namespace_dummy); +#ifdef CATCH_CONFIG_CPP11_IS_ENUM +#include +#endif namespace Catch { - // Bring in operator<< from global namespace into Catch namespace - using ::operator<<; - namespace Detail { +// Why we're here. +template +std::string toString( T const& value ); - extern const std::string unprintableString; +// Built in overloads - std::string rawMemoryToString( const void *object, std::size_t size ); +std::string toString( std::string const& value ); +std::string toString( std::wstring const& value ); +std::string toString( const char* const value ); +std::string toString( char* const value ); +std::string toString( const wchar_t* const value ); +std::string toString( wchar_t* const value ); +std::string toString( int value ); +std::string toString( unsigned long value ); +std::string toString( unsigned int value ); +std::string toString( const double value ); +std::string toString( const float value ); +std::string toString( bool value ); +std::string toString( char value ); +std::string toString( signed char value ); +std::string toString( unsigned char value ); - template - std::string rawMemoryToString( const T& object ) { - return rawMemoryToString( &object, sizeof(object) ); - } +#ifdef CATCH_CONFIG_CPP11_LONG_LONG +std::string toString( long long value ); +std::string toString( unsigned long long value ); +#endif - template - class IsStreamInsertable { - template - static auto test(int) - -> decltype(std::declval() << std::declval(), std::true_type()); - - template - static auto test(...)->std::false_type; - - public: - static const bool value = decltype(test(0))::value; - }; - - } // namespace Detail - - // If we decide for C++14, change these to enable_if_ts - template - struct StringMaker { - template - static - typename std::enable_if<::Catch::Detail::IsStreamInsertable::value, std::string>::type - convert(const Fake& t) { - std::ostringstream sstr; - sstr << t; - return sstr.str(); - } - - template - static - typename std::enable_if::value, std::string>::type - convert(const Fake&) { - return Detail::unprintableString; - } - }; - - namespace Detail { - - // This function dispatches all stringification requests inside of Catch. - // Should be preferably called fully qualified, like ::Catch::Detail::stringify - template - std::string stringify(const T& e) { - return ::Catch::StringMaker::type>::type>::convert(e); - } - - } // namespace Detail - - // Some predefined specializations - - template<> - struct StringMaker { - static std::string convert(const std::string& str); - }; - template<> - struct StringMaker { - static std::string convert(const std::wstring& wstr); - }; - - template<> - struct StringMaker { - static std::string convert(char const * str); - }; - template<> - struct StringMaker { - static std::string convert(char * str); - }; - template<> - struct StringMaker { - static std::string convert(wchar_t const * str); - }; - template<> - struct StringMaker { - static std::string convert(wchar_t * str); - }; - - template - struct StringMaker { - static std::string convert(const char* str) { - return ::Catch::Detail::stringify(std::string{ str }); - } - }; - template - struct StringMaker { - static std::string convert(const char* str) { - return ::Catch::Detail::stringify(std::string{ str }); - } - }; - template - struct StringMaker { - static std::string convert(const char* str) { - return ::Catch::Detail::stringify(std::string{ str }); - } - }; - - template<> - struct StringMaker { - static std::string convert(int value); - }; - template<> - struct StringMaker { - static std::string convert(long value); - }; - template<> - struct StringMaker { - static std::string convert(long long value); - }; - template<> - struct StringMaker { - static std::string convert(unsigned int value); - }; - template<> - struct StringMaker { - static std::string convert(unsigned long value); - }; - template<> - struct StringMaker { - static std::string convert(unsigned long long value); - }; - - template<> - struct StringMaker { - static std::string convert(bool b); - }; - - template<> - struct StringMaker { - static std::string convert(char c); - }; - template<> - struct StringMaker { - static std::string convert(signed char c); - }; - template<> - struct StringMaker { - static std::string convert(unsigned char c); - }; - - template<> - struct StringMaker { - static std::string convert(std::nullptr_t); - }; - - template<> - struct StringMaker { - static std::string convert(float value); - }; - template<> - struct StringMaker { - static std::string convert(double value); - }; - - template - struct StringMaker { - template - static std::string convert(U* p) { - if (p) { - return ::Catch::Detail::rawMemoryToString(p); - } else { - return "nullptr"; - } - } - }; - - template - struct StringMaker { - static std::string convert(R C::* p) { - if (p) { - return ::Catch::Detail::rawMemoryToString(p); - } else { - return "nullptr"; - } - } - }; - - namespace Detail { - template - std::string rangeToString(InputIterator first, InputIterator last) { - std::ostringstream oss; - oss << "{ "; - if (first != last) { - oss << ::Catch::Detail::stringify(*first); - for (++first; first != last; ++first) - oss << ", " << ::Catch::Detail::stringify(*first); - } - oss << " }"; - return oss.str(); - } - } - - template - struct StringMaker > { - static std::string convert( std::vector const& v ) { - return ::Catch::Detail::rangeToString( v.begin(), v.end() ); - } - }; - - template - struct EnumStringMaker { - static std::string convert(const T& t) { - return ::Catch::Detail::stringify(static_cast::type>(t)); - } - }; +#ifdef CATCH_CONFIG_CPP11_NULLPTR +std::string toString( std::nullptr_t ); +#endif #ifdef __OBJC__ - template<> - struct StringMaker { - static std::string convert(NSString * nsstring) { - if (!nsstring) - return "nil"; - return std::string("@") + [nsstring UTF8String]; - } - }; - template<> - struct StringMaker { - static std::string convert(NSObject* nsObject) { - return ::Catch::Detail::stringify([nsObject description]); - } - - }; - namespace Detail { - inline std::string stringify( NSString* nsstring ) { - return StringMaker::convert( nsstring ); - } - - } // namespace Detail -#endif // __OBJC__ - -} // namespace Catch - -////////////////////////////////////////////////////// -// Separate std-lib types stringification, so it can be selectively enabled -// This means that we do not bring in - -#if defined(CATCH_CONFIG_ENABLE_ALL_STRINGMAKERS) -# define CATCH_CONFIG_ENABLE_PAIR_STRINGMAKER -# define CATCH_CONFIG_ENABLE_TUPLE_STRINGMAKER -# define CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER + std::string toString( NSString const * const& nsstring ); + std::string toString( NSString * CATCH_ARC_STRONG & nsstring ); + std::string toString( NSObject* const& nsObject ); #endif -// Separate std::pair specialization -#if defined(CATCH_CONFIG_ENABLE_PAIR_STRINGMAKER) -#include -namespace Catch { - template - struct StringMaker > { - static std::string convert(const std::pair& pair) { - std::ostringstream oss; - oss << "{ " - << ::Catch::Detail::stringify(pair.first) - << ", " - << ::Catch::Detail::stringify(pair.second) - << " }"; - return oss.str(); - } - }; -} -#endif // CATCH_CONFIG_ENABLE_PAIR_STRINGMAKER +namespace Detail { -// Separate std::tuple specialization -#if defined(CATCH_CONFIG_ENABLE_TUPLE_STRINGMAKER) -#include -namespace Catch { - namespace Detail { - template< - typename Tuple, - std::size_t N = 0, - bool = (N < std::tuple_size::value) - > - struct TupleElementPrinter { - static void print(const Tuple& tuple, std::ostream& os) { - os << (N ? ", " : " ") - << ::Catch::Detail::stringify(std::get(tuple)); - TupleElementPrinter::print(tuple, os); - } - }; + extern const std::string unprintableString; - template< - typename Tuple, - std::size_t N - > - struct TupleElementPrinter { - static void print(const Tuple&, std::ostream&) {} - }; - - } - - template - struct StringMaker> { - static std::string convert(const std::tuple& tuple) { - std::ostringstream os; - os << '{'; - Detail::TupleElementPrinter>::print(tuple, os); - os << " }"; - return os.str(); - } - }; -} -#endif // CATCH_CONFIG_ENABLE_TUPLE_STRINGMAKER - -// Separate std::chrono::duration specialization -#if defined(CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER) -#include -#include -#include - -template -struct ratio_string { - static std::string symbol(); -}; - -template -std::string ratio_string::symbol() { - std::ostringstream oss; - oss << '[' << Ratio::num << '/' - << Ratio::den << ']'; - return oss.str(); -} -template <> -struct ratio_string { - static std::string symbol() { return "a"; } -}; -template <> -struct ratio_string { - static std::string symbol() { return "f"; } -}; -template <> -struct ratio_string { - static std::string symbol() { return "p"; } -}; -template <> -struct ratio_string { - static std::string symbol() { return "n"; } -}; -template <> -struct ratio_string { - static std::string symbol() { return "u"; } -}; -template <> -struct ratio_string { - static std::string symbol() { return "m"; } -}; - -namespace Catch { - //////////// - // std::chrono::duration specializations - template - struct StringMaker> { - static std::string convert(std::chrono::duration const& duration) { - std::ostringstream oss; - oss << duration.count() << ' ' << ratio_string::symbol() << 's'; - return oss.str(); - } - }; - template - struct StringMaker>> { - static std::string convert(std::chrono::duration> const& duration) { - std::ostringstream oss; - oss << duration.count() << " s"; - return oss.str(); - } - }; - template - struct StringMaker>> { - static std::string convert(std::chrono::duration> const& duration) { - std::ostringstream oss; - oss << duration.count() << " m"; - return oss.str(); - } - }; - template - struct StringMaker>> { - static std::string convert(std::chrono::duration> const& duration) { - std::ostringstream oss; - oss << duration.count() << " h"; - return oss.str(); - } + #if !defined(CATCH_CONFIG_CPP11_STREAM_INSERTABLE_CHECK) + struct BorgType { + template BorgType( T const& ); }; - //////////// - // std::chrono::time_point specialization - // Generic time_point cannot be specialized, only std::chrono::time_point - template - struct StringMaker> { - static std::string convert(std::chrono::time_point const& time_point) { - return ::Catch::Detail::stringify(time_point.time_since_epoch()) + " since epoch"; - } - }; - // std::chrono::time_point specialization - template - struct StringMaker> { - static std::string convert(std::chrono::time_point const& time_point) { - auto converted = std::chrono::system_clock::to_time_t(time_point); + struct TrueType { char sizer[1]; }; + struct FalseType { char sizer[2]; }; -#ifdef _MSC_VER - std::tm timeInfo = {}; - gmtime_s(&timeInfo, &converted); + TrueType& testStreamable( std::ostream& ); + FalseType testStreamable( FalseType ); + + 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 ) }; + }; #else - std::tm* timeInfo = std::gmtime(&converted); -#endif + template + class IsStreamInsertable { + template + static auto test(int) + -> decltype( std::declval() << std::declval(), std::true_type() ); - auto const timeStampSize = sizeof("2017-01-16T17:06:45Z"); - char timeStamp[timeStampSize]; - const char * const fmt = "%Y-%m-%dT%H:%M:%SZ"; - -#ifdef _MSC_VER - std::strftime(timeStamp, timeStampSize, fmt, &timeInfo); -#else - std::strftime(timeStamp, timeStampSize, fmt, timeInfo); -#endif - return std::string(timeStamp); - } - }; -} -#endif // CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER - -#ifdef _MSC_VER -#pragma warning(pop) -#endif - -// end catch_tostring.h -#include - -#ifdef _MSC_VER -#pragma warning(push) -#pragma warning(disable:4389) // '==' : signed/unsigned mismatch -#pragma warning(disable:4018) // more "signed/unsigned mismatch" -#pragma warning(disable:4312) // Converting int to T* using reinterpret_cast (issue on x64 platform) -#pragma warning(disable:4180) // qualifier applied to function type has no meaning -#endif - -namespace Catch { - - struct ITransientExpression { - virtual auto isBinaryExpression() const -> bool = 0; - virtual auto getResult() const -> bool = 0; - virtual void streamReconstructedExpression( std::ostream &os ) const = 0; - - // We don't actually need a virtual destructore, but many static analysers - // complain if it's not here :-( - virtual ~ITransientExpression(); - }; - - void formatReconstructedExpression( std::ostream &os, std::string const& lhs, StringRef op, std::string const& rhs ); - - template - class BinaryExpr : public ITransientExpression { - bool m_result; - LhsT m_lhs; - StringRef m_op; - RhsT m_rhs; - - auto isBinaryExpression() const -> bool override { return true; } - auto getResult() const -> bool override { return m_result; } - - void streamReconstructedExpression( std::ostream &os ) const override { - formatReconstructedExpression - ( os, Catch::Detail::stringify( m_lhs ), m_op, Catch::Detail::stringify( m_rhs ) ); - } + template + static auto test(...) -> std::false_type; public: - BinaryExpr( bool comparisonResult, LhsT lhs, StringRef op, RhsT rhs ) - : m_result( comparisonResult ), - m_lhs( lhs ), - m_op( op ), - m_rhs( rhs ) - {} + static const bool value = decltype(test(0))::value; }; - - template - class UnaryExpr : public ITransientExpression { - LhsT m_lhs; - - auto isBinaryExpression() const -> bool override { return false; } - auto getResult() const -> bool override { return m_lhs ? true : false; } - - void streamReconstructedExpression( std::ostream &os ) const override { - os << Catch::Detail::stringify( m_lhs ); - } - - public: - UnaryExpr( LhsT lhs ) : m_lhs( lhs ) {} - }; - - // Specialised comparison functions to handle equality comparisons between ints and pointers (NULL deduces as an int) - template - auto compareEqual( LhsT const& lhs, RhsT const& rhs ) -> bool { return lhs == rhs; }; - template - auto compareEqual( T* const& lhs, int rhs ) -> bool { return lhs == reinterpret_cast( rhs ); } - template - auto compareEqual( T* const& lhs, long rhs ) -> bool { return lhs == reinterpret_cast( rhs ); } - template - auto compareEqual( int lhs, T* const& rhs ) -> bool { return reinterpret_cast( lhs ) == rhs; } - template - auto compareEqual( long lhs, T* const& rhs ) -> bool { return reinterpret_cast( lhs ) == rhs; } - - template - auto compareNotEqual( LhsT const& lhs, RhsT&& rhs ) -> bool { return lhs != rhs; }; - template - auto compareNotEqual( T* const& lhs, int rhs ) -> bool { return lhs != reinterpret_cast( rhs ); } - template - auto compareNotEqual( T* const& lhs, long rhs ) -> bool { return lhs != reinterpret_cast( rhs ); } - template - auto compareNotEqual( int lhs, T* const& rhs ) -> bool { return reinterpret_cast( lhs ) != rhs; } - template - auto compareNotEqual( long lhs, T* const& rhs ) -> bool { return reinterpret_cast( lhs ) != rhs; } - - template - class ExprLhs { - LhsT m_lhs; - public: - ExprLhs( LhsT lhs ) : m_lhs( lhs ) {} - - template - auto operator == ( RhsT const& rhs ) -> BinaryExpr const { - return BinaryExpr( compareEqual( m_lhs, rhs ), m_lhs, "==", rhs ); - } - auto operator == ( bool rhs ) -> BinaryExpr const { - return BinaryExpr( m_lhs == rhs, m_lhs, "==", rhs ); - } - - template - auto operator != ( RhsT const& rhs ) -> BinaryExpr const { - return BinaryExpr( compareNotEqual( m_lhs, rhs ), m_lhs, "!=", rhs ); - } - auto operator != ( bool rhs ) -> BinaryExpr const { - return BinaryExpr( m_lhs != rhs, m_lhs, "!=", rhs ); - } - - template - auto operator > ( RhsT const& rhs ) -> BinaryExpr const { - return BinaryExpr( m_lhs > rhs, m_lhs, ">", rhs ); - } - template - auto operator < ( RhsT const& rhs ) -> BinaryExpr const { - return BinaryExpr( m_lhs < rhs, m_lhs, "<", rhs ); - } - template - auto operator >= ( RhsT const& rhs ) -> BinaryExpr const { - return BinaryExpr( m_lhs >= rhs, m_lhs, ">=", rhs ); - } - template - auto operator <= ( RhsT const& rhs ) -> BinaryExpr const { - return BinaryExpr( m_lhs <= rhs, m_lhs, "<=", rhs ); - } - - auto makeUnaryExpr() const -> UnaryExpr { - return UnaryExpr( m_lhs ); - } - }; - - void handleExpression( ITransientExpression const& expr ); - - template - void handleExpression( ExprLhs const& expr ) { - handleExpression( expr.makeUnaryExpr() ); - } - - struct Decomposer { - template - auto operator <= ( T const& lhs ) -> ExprLhs { - return ExprLhs( lhs ); - } - auto operator <=( bool value ) -> ExprLhs { - return ExprLhs( value ); - } - }; - -} // end namespace Catch - -#ifdef _MSC_VER -#pragma warning(pop) #endif -// end catch_decomposer.h -// start catch_assertioninfo.h - -// start catch_result_type.h - -namespace Catch { - - // ResultWas::OfType enum - struct ResultWas { enum OfType { - Unknown = -1, - Ok = 0, - Info = 1, - Warning = 2, - - FailureBit = 0x10, - - ExpressionFailed = FailureBit | 1, - ExplicitFailure = FailureBit | 2, - - Exception = 0x100 | FailureBit, - - ThrewException = Exception | 1, - DidntThrowException = Exception | 2, - - FatalErrorCondition = 0x200 | FailureBit - - }; }; - - bool isOk( ResultWas::OfType resultType ); - bool isJustInfo( int flags ); - - // ResultDisposition::Flags enum - struct ResultDisposition { enum Flags { - Normal = 0x01, - - ContinueOnFailure = 0x02, // Failures fail test, but execution continues - FalseTest = 0x04, // Prefix expression with ! - SuppressFail = 0x08 // Failures are reported but do not fail the test - }; }; - - ResultDisposition::Flags operator | ( ResultDisposition::Flags lhs, ResultDisposition::Flags rhs ); - - bool shouldContinueOnFailure( int flags ); - bool isFalseTest( int flags ); - bool shouldSuppressFailure( int flags ); - -} // end namespace Catch - -// end catch_result_type.h -namespace Catch { - - struct AssertionInfo +#if defined(CATCH_CONFIG_CPP11_IS_ENUM) + template::value + > + struct EnumStringMaker { - StringRef macroName; - SourceLineInfo lineInfo; - StringRef capturedExpression; - ResultDisposition::Flags resultDisposition; - - // We want to delete this constructor but a compiler bug in 4.8 means - // the struct is then treated as non-aggregate - //AssertionInfo() = delete; + static std::string convert( T const& ) { return unprintableString; } }; + template + struct EnumStringMaker + { + static std::string convert( T const& v ) + { + return ::Catch::toString( + static_cast::type>(v) + ); + } + }; +#endif + template + struct StringMakerBase { +#if defined(CATCH_CONFIG_CPP11_IS_ENUM) + template + static std::string convert( T const& v ) + { + return EnumStringMaker::convert( v ); + } +#else + template + static std::string convert( T const& ) { return unprintableString; } +#endif + }; + + 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 + std::string rawMemoryToString( const T& object ) { + return rawMemoryToString( &object, sizeof(object) ); + } + +} // end namespace Detail + +template +struct StringMaker : + Detail::StringMakerBase::value> {}; + +template +struct StringMaker { + template + static std::string convert( U* p ) { + if( !p ) + return "NULL"; + else + return Detail::rawMemoryToString( p ); + } +}; + +template +struct StringMaker { + static std::string convert( R C::* p ) { + if( !p ) + return "NULL"; + else + return Detail::rawMemoryToString( p ); + } +}; + +namespace Detail { + template + std::string rangeToString( InputIterator first, InputIterator last ); +} + +//template +//struct StringMaker > { +// static std::string convert( std::vector const& v ) { +// return Detail::rangeToString( v.begin(), v.end() ); +// } +//}; + +template +std::string toString( std::vector const& v ) { + return Detail::rangeToString( v.begin(), v.end() ); +} + +#ifdef CATCH_CONFIG_CPP11_TUPLE + +// toString for tuples +namespace TupleDetail { + template< + typename Tuple, + std::size_t N = 0, + bool = (N < std::tuple_size::value) + > + struct ElementPrinter { + static void print( const Tuple& tuple, std::ostream& os ) + { + os << ( N ? ", " : " " ) + << Catch::toString(std::get(tuple)); + ElementPrinter::print(tuple,os); + } + }; + + template< + typename Tuple, + std::size_t N + > + struct ElementPrinter { + static void print( const Tuple&, std::ostream& ) {} + }; + +} + +template +struct StringMaker> { + + static std::string convert( const std::tuple& tuple ) + { + std::ostringstream os; + os << '{'; + TupleDetail::ElementPrinter>::print( tuple, os ); + os << " }"; + return os.str(); + } +}; +#endif // CATCH_CONFIG_CPP11_TUPLE + +namespace Detail { + template + std::string makeString( T const& value ) { + return StringMaker::convert( value ); + } +} // end namespace Detail + +/// \brief converts any type to a string +/// +/// The default template forwards on to ostringstream - except when an +/// ostringstream overload does not exist - in which case it attempts to detect +/// that and writes {?}. +/// Overload (not specialise) this template for custom typs that you don't want +/// to provide an ostream overload for. +template +std::string toString( T const& value ) { + return StringMaker::convert( value ); +} + + namespace Detail { + template + std::string rangeToString( InputIterator first, InputIterator last ) { + std::ostringstream oss; + oss << "{ "; + if( first != last ) { + oss << Catch::toString( *first ); + for( ++first ; first != last ; ++first ) + oss << ", " << Catch::toString( *first ); + } + oss << " }"; + return oss.str(); + } +} + } // end namespace Catch -// end catch_assertioninfo.h namespace Catch { - struct TestFailureException{}; - struct AssertionResultData; +template +class BinaryExpression; - class LazyExpression { - friend class AssertionHandler; - friend struct AssertionStats; +template +class MatchExpression; - ITransientExpression const* m_transientExpression = nullptr; - bool m_isNegated; - public: - LazyExpression( bool isNegated ); - LazyExpression( LazyExpression const& other ); - LazyExpression& operator = ( LazyExpression const& ) = delete; +// Wraps the LHS of an expression and overloads comparison operators +// for also capturing those and RHS (if any) +template +class ExpressionLhs : public DecomposedExpression { +public: + ExpressionLhs( ResultBuilder& rb, T lhs ) : m_rb( rb ), m_lhs( lhs ), m_truthy(false) {} - explicit operator bool() const; + ExpressionLhs& operator = ( const ExpressionLhs& ); - friend auto operator << ( std::ostream& os, LazyExpression const& lazyExpr ) -> std::ostream&; - }; + template + BinaryExpression + operator == ( RhsT const& rhs ) { + return captureExpression( rhs ); + } - class AssertionHandler { - AssertionInfo m_assertionInfo; - bool m_shouldDebugBreak = false; - bool m_shouldThrow = false; - bool m_inExceptionGuard = false; + template + BinaryExpression + operator != ( RhsT const& rhs ) { + return captureExpression( rhs ); + } - public: - AssertionHandler - ( StringRef macroName, - SourceLineInfo const& lineInfo, - StringRef capturedExpression, - ResultDisposition::Flags resultDisposition ); - ~AssertionHandler(); + template + BinaryExpression + operator < ( RhsT const& rhs ) { + return captureExpression( rhs ); + } - void handle( ITransientExpression const& expr ); + template + BinaryExpression + operator > ( RhsT const& rhs ) { + return captureExpression( rhs ); + } - template - void handle( ExprLhs const& expr ) { - handle( expr.makeUnaryExpr() ); - } - void handle( ResultWas::OfType resultType ); - void handle( ResultWas::OfType resultType, StringRef const& message ); - void handle( ResultWas::OfType resultType, ITransientExpression const* expr, bool negated ); - void handle( AssertionResultData const& resultData, ITransientExpression const* expr ); + template + BinaryExpression + operator <= ( RhsT const& rhs ) { + return captureExpression( rhs ); + } - auto shouldDebugBreak() const -> bool; - auto allowThrows() const -> bool; - void reactWithDebugBreak() const; - void reactWithoutDebugBreak() const; - void useActiveException(); - void setExceptionGuard(); - void unsetExceptionGuard(); - }; + template + BinaryExpression + operator >= ( RhsT const& rhs ) { + return captureExpression( rhs ); + } - void handleExceptionMatchExpr( AssertionHandler& handler, std::string const& str, StringRef matcherString ); + BinaryExpression operator == ( bool rhs ) { + return captureExpression( rhs ); + } + + BinaryExpression operator != ( bool rhs ) { + return captureExpression( rhs ); + } + + void endExpression() { + m_truthy = m_lhs ? true : false; + m_rb + .setResultType( m_truthy ) + .endExpression( *this ); + } + + virtual void reconstructExpression( std::string& dest ) const CATCH_OVERRIDE { + dest = Catch::toString( m_lhs ); + } + +private: + template + BinaryExpression captureExpression( RhsT& rhs ) const { + return BinaryExpression( m_rb, m_lhs, rhs ); + } + + template + BinaryExpression captureExpression( bool rhs ) const { + return BinaryExpression( m_rb, m_lhs, rhs ); + } + +private: + ResultBuilder& m_rb; + T m_lhs; + bool m_truthy; +}; + +template +class BinaryExpression : public DecomposedExpression { +public: + BinaryExpression( ResultBuilder& rb, LhsT lhs, RhsT rhs ) + : m_rb( rb ), m_lhs( lhs ), m_rhs( rhs ) {} + + BinaryExpression& operator = ( BinaryExpression& ); + + void endExpression() const { + m_rb + .setResultType( Internal::compare( m_lhs, m_rhs ) ) + .endExpression( *this ); + } + + virtual bool isBinaryExpression() const CATCH_OVERRIDE { + return true; + } + + virtual void reconstructExpression( std::string& dest ) const CATCH_OVERRIDE { + std::string lhs = Catch::toString( m_lhs ); + std::string rhs = Catch::toString( m_rhs ); + char delim = lhs.size() + rhs.size() < 40 && + lhs.find('\n') == std::string::npos && + rhs.find('\n') == std::string::npos ? ' ' : '\n'; + dest.reserve( 7 + lhs.size() + rhs.size() ); + // 2 for spaces around operator + // 2 for operator + // 2 for parentheses (conditionally added later) + // 1 for negation (conditionally added later) + dest = lhs; + dest += delim; + dest += Internal::OperatorTraits::getName(); + dest += delim; + dest += rhs; + } + +private: + ResultBuilder& m_rb; + LhsT m_lhs; + RhsT m_rhs; +}; + +template +class MatchExpression : public DecomposedExpression { +public: + MatchExpression( ArgT arg, MatcherT matcher, char const* matcherString ) + : m_arg( arg ), m_matcher( matcher ), m_matcherString( matcherString ) {} + + virtual bool isBinaryExpression() const CATCH_OVERRIDE { + return true; + } + + virtual void reconstructExpression( std::string& dest ) const CATCH_OVERRIDE { + std::string matcherAsString = m_matcher.toString(); + dest = Catch::toString( m_arg ); + dest += ' '; + if( matcherAsString == Detail::unprintableString ) + dest += m_matcherString; + else + dest += matcherAsString; + } + +private: + ArgT m_arg; + MatcherT m_matcher; + char const* m_matcherString; +}; + +} // end namespace Catch + + +namespace Catch { + + template + ExpressionLhs ResultBuilder::operator <= ( T const& operand ) { + return ExpressionLhs( *this, operand ); + } + + inline ExpressionLhs ResultBuilder::operator <= ( bool value ) { + return ExpressionLhs( *this, value ); + } + + template + void ResultBuilder::captureMatch( ArgT const& arg, MatcherT const& matcher, + char const* matcherString ) { + MatchExpression expr( arg, matcher, matcherString ); + setResultType( matcher.match( arg ) ); + endExpression( expr ); + } } // namespace Catch -// end catch_assertionhandler.h -// start catch_message.h +// #included from: catch_message.h +#define TWOBLUECUBES_CATCH_MESSAGE_H_INCLUDED #include -#include namespace Catch { @@ -1264,33 +2002,27 @@ namespace Catch { ResultWas::OfType _type ); std::string macroName; - std::string message; SourceLineInfo lineInfo; ResultWas::OfType type; + std::string message; unsigned int sequence; - bool operator == ( MessageInfo const& other ) const; - bool operator < ( MessageInfo const& other ) const; + 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 MessageStream { - - template - MessageStream& operator << ( T const& value ) { - m_stream << value; - return *this; - } - - // !TBD reuse a global/ thread-local stream - std::ostringstream m_stream; - }; - - struct MessageBuilder : MessageStream { + struct MessageBuilder { MessageBuilder( std::string const& macroName, SourceLineInfo const& lineInfo, - ResultWas::OfType type ); + ResultWas::OfType type ) + : m_info( macroName, lineInfo, type ) + {} template MessageBuilder& operator << ( T const& value ) { @@ -1299,11 +2031,13 @@ namespace Catch { } MessageInfo m_info; + std::ostringstream m_stream; }; class ScopedMessage { public: ScopedMessage( MessageBuilder const& builder ); + ScopedMessage( ScopedMessage const& other ); ~ScopedMessage(); MessageInfo m_info; @@ -1311,36 +2045,31 @@ namespace Catch { } // end namespace Catch -// end catch_message.h -// start catch_interfaces_capture.h +// #included from: catch_interfaces_capture.h +#define TWOBLUECUBES_CATCH_INTERFACES_CAPTURE_H_INCLUDED #include namespace Catch { + class TestCase; class AssertionResult; struct AssertionInfo; struct SectionInfo; struct SectionEndInfo; struct MessageInfo; + class ScopedMessageBuilder; struct Counts; - struct BenchmarkInfo; - struct BenchmarkStats; struct IResultCapture { virtual ~IResultCapture(); - virtual void assertionStarting( AssertionInfo const& info ) = 0; virtual void assertionEnded( AssertionResult const& result ) = 0; virtual bool sectionStarted( SectionInfo const& sectionInfo, Counts& assertions ) = 0; virtual void sectionEnded( SectionEndInfo const& endInfo ) = 0; virtual void sectionEndedEarly( SectionEndInfo const& endInfo ) = 0; - - virtual void benchmarkStarting( BenchmarkInfo const& info ) = 0; - virtual void benchmarkEnded( BenchmarkStats const& stats ) = 0; - virtual void pushScopedMessage( MessageInfo const& message ) = 0; virtual void popScopedMessage( MessageInfo const& message ) = 0; @@ -1349,7 +2078,7 @@ namespace Catch { virtual void exceptionEarlyReported() = 0; - virtual void handleFatalErrorCondition( StringRef message ) = 0; + virtual void handleFatalErrorCondition( std::string const& message ) = 0; virtual bool lastAssertionPassed() = 0; virtual void assertionPassed() = 0; @@ -1359,16 +2088,47 @@ namespace Catch { IResultCapture& getResultCapture(); } -// end catch_interfaces_capture.h -// start catch_debugger.h +// #included from: catch_debugger.h +#define TWOBLUECUBES_CATCH_DEBUGGER_H_INCLUDED + +// #included from: catch_platform.h +#define TWOBLUECUBES_CATCH_PLATFORM_H_INCLUDED + +#if defined(__MAC_OS_X_VERSION_MIN_REQUIRED) +# define CATCH_PLATFORM_MAC +#elif defined(__IPHONE_OS_VERSION_MIN_REQUIRED) +# define CATCH_PLATFORM_IPHONE +#elif defined(linux) || defined(__linux) || defined(__linux__) +# define CATCH_PLATFORM_LINUX +#elif defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) +# define CATCH_PLATFORM_WINDOWS +# if !defined(NOMINMAX) && !defined(CATCH_CONFIG_NO_NOMINMAX) +# define CATCH_DEFINES_NOMINMAX +# endif +# if !defined(WIN32_LEAN_AND_MEAN) && !defined(CATCH_CONFIG_NO_WIN32_LEAN_AND_MEAN) +# define CATCH_DEFINES_WIN32_LEAN_AND_MEAN +# endif +#endif + +#include + +namespace Catch{ -namespace Catch { bool isDebuggerActive(); + void writeToDebugConsole( std::string const& text ); } #ifdef CATCH_PLATFORM_MAC - #define CATCH_TRAP() __asm__("int $3\n" : : ) /* NOLINT */ + // The following code snippet based on: + // http://cocoawithlove.com/2008/03/break-into-debugger.html + #if defined(__ppc64__) || defined(__ppc__) + #define CATCH_TRAP() \ + __asm__("li r0, 20\nsc\nnop\nli r0, 37\nli r4, 2\nsc\nnop\n" \ + : : : "memory","r0","r3","r4" ) /* NOLINT */ + #else + #define CATCH_TRAP() __asm__("int $3\n" : : /* NOLINT */ ) + #endif #elif defined(CATCH_PLATFORM_LINUX) // If we can use inline assembler, do it because this allows us to break @@ -1394,190 +2154,251 @@ namespace Catch { #define CATCH_BREAK_INTO_DEBUGGER() Catch::alwaysTrue(); #endif -// end catch_debugger.h -#if !defined(CATCH_CONFIG_DISABLE) +// #included from: catch_interfaces_runner.h +#define TWOBLUECUBES_CATCH_INTERFACES_RUNNER_H_INCLUDED -#if !defined(CATCH_CONFIG_DISABLE_STRINGIFICATION) - #define CATCH_INTERNAL_STRINGIFY(...) #__VA_ARGS__ -#else - #define CATCH_INTERNAL_STRINGIFY(...) "Disabled by CATCH_CONFIG_DISABLE_STRINGIFICATION" -#endif +namespace Catch { + class TestCase; + + struct IRunner { + virtual ~IRunner(); + virtual bool aborting() const = 0; + }; +} #if defined(CATCH_CONFIG_FAST_COMPILE) /////////////////////////////////////////////////////////////////////////////// // We can speedup compilation significantly by breaking into debugger lower in // the callstack, because then we don't have to expand CATCH_BREAK_INTO_DEBUGGER // macro in each assertion -#define INTERNAL_CATCH_REACT( handler ) \ - handler.reactWithDebugBreak(); +#define INTERNAL_CATCH_REACT( resultBuilder ) \ + resultBuilder.react(); /////////////////////////////////////////////////////////////////////////////// // Another way to speed-up compilation is to omit local try-catch for REQUIRE* // macros. // This can potentially cause false negative, if the test code catches // the exception before it propagates back up to the runner. -#define INTERNAL_CATCH_TRY( capturer ) capturer.setExceptionGuard(); -#define INTERNAL_CATCH_CATCH( capturer ) capturer.unsetExceptionGuard(); +#define INTERNAL_CATCH_TEST_NO_TRY( macroName, resultDisposition, expr ) \ + do { \ + Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \ + __catchResult.setExceptionGuard(); \ + CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \ + ( __catchResult <= expr ).endExpression(); \ + CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS \ + __catchResult.unsetExceptionGuard(); \ + INTERNAL_CATCH_REACT( __catchResult ) \ + } while( Catch::isTrue( false && static_cast( !!(expr) ) ) ) // expr here is never evaluated at runtime but it forces the compiler to give it a look +// The double negation silences MSVC's C4800 warning, the static_cast forces short-circuit evaluation if the type has overloaded &&. -#else // CATCH_CONFIG_FAST_COMPILE +#define INTERNAL_CHECK_THAT_NO_TRY( macroName, matcher, resultDisposition, arg ) \ + do { \ + Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #arg ", " #matcher, resultDisposition ); \ + __catchResult.setExceptionGuard(); \ + __catchResult.captureMatch( arg, matcher, #matcher ); \ + __catchResult.unsetExceptionGuard(); \ + INTERNAL_CATCH_REACT( __catchResult ) \ + } while( Catch::alwaysFalse() ) +#else /////////////////////////////////////////////////////////////////////////////// // In the event of a failure works out if the debugger needs to be invoked // and/or an exception thrown and takes appropriate action. // This needs to be done as a macro so the debugger will stop in the user // source code rather than in Catch library code -#define INTERNAL_CATCH_REACT( handler ) \ - if( handler.shouldDebugBreak() ) CATCH_BREAK_INTO_DEBUGGER(); \ - handler.reactWithoutDebugBreak(); - -#define INTERNAL_CATCH_TRY( capturer ) try -#define INTERNAL_CATCH_CATCH( capturer ) catch(...) { capturer.useActiveException(); } - +#define INTERNAL_CATCH_REACT( resultBuilder ) \ + if( resultBuilder.shouldDebugBreak() ) CATCH_BREAK_INTO_DEBUGGER(); \ + resultBuilder.react(); #endif /////////////////////////////////////////////////////////////////////////////// -#define INTERNAL_CATCH_TEST( macroName, resultDisposition, ... ) \ +#define INTERNAL_CATCH_TEST( macroName, resultDisposition, expr ) \ do { \ - Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__), resultDisposition ); \ - INTERNAL_CATCH_TRY( catchAssertionHandler ) { \ + Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \ + try { \ CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \ - catchAssertionHandler.handle( Catch::Decomposer() <= __VA_ARGS__ ); \ + ( __catchResult <= expr ).endExpression(); \ CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS \ - } INTERNAL_CATCH_CATCH( catchAssertionHandler ) \ - INTERNAL_CATCH_REACT( catchAssertionHandler ) \ - } while( Catch::isTrue( false && static_cast( !!(__VA_ARGS__) ) ) ) // the expression here is never evaluated at runtime but it forces the compiler to give it a look + } \ + catch( ... ) { \ + __catchResult.useActiveException( resultDisposition ); \ + } \ + INTERNAL_CATCH_REACT( __catchResult ) \ + } while( Catch::isTrue( false && static_cast( !!(expr) ) ) ) // expr here is never evaluated at runtime but it forces the compiler to give it a look // The double negation silences MSVC's C4800 warning, the static_cast forces short-circuit evaluation if the type has overloaded &&. /////////////////////////////////////////////////////////////////////////////// -#define INTERNAL_CATCH_IF( macroName, resultDisposition, ... ) \ - INTERNAL_CATCH_TEST( macroName, resultDisposition, __VA_ARGS__ ); \ +#define INTERNAL_CATCH_IF( macroName, resultDisposition, expr ) \ + INTERNAL_CATCH_TEST( macroName, resultDisposition, expr ); \ if( Catch::getResultCapture().lastAssertionPassed() ) /////////////////////////////////////////////////////////////////////////////// -#define INTERNAL_CATCH_ELSE( macroName, resultDisposition, ... ) \ - INTERNAL_CATCH_TEST( macroName, resultDisposition, __VA_ARGS__ ); \ +#define INTERNAL_CATCH_ELSE( macroName, resultDisposition, expr ) \ + INTERNAL_CATCH_TEST( macroName, resultDisposition, expr ); \ if( !Catch::getResultCapture().lastAssertionPassed() ) /////////////////////////////////////////////////////////////////////////////// -#define INTERNAL_CATCH_NO_THROW( macroName, resultDisposition, ... ) \ +#define INTERNAL_CATCH_NO_THROW( macroName, resultDisposition, expr ) \ do { \ - Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__), resultDisposition ); \ + Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \ try { \ - static_cast(__VA_ARGS__); \ - catchAssertionHandler.handle( Catch::ResultWas::Ok ); \ + static_cast(expr); \ + __catchResult.captureResult( Catch::ResultWas::Ok ); \ } \ catch( ... ) { \ - catchAssertionHandler.useActiveException(); \ + __catchResult.useActiveException( resultDisposition ); \ } \ - INTERNAL_CATCH_REACT( catchAssertionHandler ) \ + INTERNAL_CATCH_REACT( __catchResult ) \ } while( Catch::alwaysFalse() ) /////////////////////////////////////////////////////////////////////////////// -#define INTERNAL_CATCH_THROWS( macroName, resultDisposition, ... ) \ +#define INTERNAL_CATCH_THROWS( macroName, resultDisposition, matcher, expr ) \ do { \ - Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__), resultDisposition); \ - if( catchAssertionHandler.allowThrows() ) \ + Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition, #matcher ); \ + if( __catchResult.allowThrows() ) \ try { \ - static_cast(__VA_ARGS__); \ - catchAssertionHandler.handle( Catch::ResultWas::DidntThrowException ); \ + static_cast(expr); \ + __catchResult.captureResult( Catch::ResultWas::DidntThrowException ); \ } \ catch( ... ) { \ - catchAssertionHandler.handle( Catch::ResultWas::Ok ); \ + __catchResult.captureExpectedException( matcher ); \ } \ else \ - catchAssertionHandler.handle( Catch::ResultWas::Ok ); \ - INTERNAL_CATCH_REACT( catchAssertionHandler ) \ + __catchResult.captureResult( Catch::ResultWas::Ok ); \ + INTERNAL_CATCH_REACT( __catchResult ) \ } while( Catch::alwaysFalse() ) /////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CATCH_THROWS_AS( macroName, exceptionType, resultDisposition, expr ) \ do { \ - Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(expr) ", " CATCH_INTERNAL_STRINGIFY(exceptionType), resultDisposition ); \ - if( catchAssertionHandler.allowThrows() ) \ + Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr ", " #exceptionType, resultDisposition ); \ + if( __catchResult.allowThrows() ) \ try { \ static_cast(expr); \ - catchAssertionHandler.handle( Catch::ResultWas::DidntThrowException ); \ + __catchResult.captureResult( Catch::ResultWas::DidntThrowException ); \ } \ - catch( exceptionType const& ) { \ - catchAssertionHandler.handle( Catch::ResultWas::Ok ); \ + catch( exceptionType ) { \ + __catchResult.captureResult( Catch::ResultWas::Ok ); \ } \ catch( ... ) { \ - catchAssertionHandler.useActiveException(); \ + __catchResult.useActiveException( resultDisposition ); \ } \ else \ - catchAssertionHandler.handle( Catch::ResultWas::Ok ); \ - INTERNAL_CATCH_REACT( catchAssertionHandler ) \ + __catchResult.captureResult( Catch::ResultWas::Ok ); \ + INTERNAL_CATCH_REACT( __catchResult ) \ } while( Catch::alwaysFalse() ) /////////////////////////////////////////////////////////////////////////////// -#define INTERNAL_CATCH_MSG( macroName, messageType, resultDisposition, ... ) \ - do { \ - Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, "", resultDisposition ); \ - catchAssertionHandler.handle( messageType, ( Catch::MessageStream() << __VA_ARGS__ + ::Catch::StreamEndStop() ).m_stream.str() ); \ - INTERNAL_CATCH_REACT( catchAssertionHandler ) \ - } while( Catch::alwaysFalse() ) +#ifdef CATCH_CONFIG_VARIADIC_MACROS + #define INTERNAL_CATCH_MSG( macroName, messageType, resultDisposition, ... ) \ + 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( macroName, messageType, resultDisposition, log ) \ + do { \ + Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, "", resultDisposition ); \ + __catchResult << log + ::Catch::StreamEndStop(); \ + __catchResult.captureResult( messageType ); \ + INTERNAL_CATCH_REACT( __catchResult ) \ + } while( Catch::alwaysFalse() ) +#endif /////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CATCH_INFO( macroName, log ) \ Catch::ScopedMessage INTERNAL_CATCH_UNIQUE_NAME( scopedMessage ) = Catch::MessageBuilder( macroName, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info ) << log; /////////////////////////////////////////////////////////////////////////////// -// Although this is matcher-based, it can be used with just a string -#define INTERNAL_CATCH_THROWS_STR_MATCHES( macroName, resultDisposition, matcher, ... ) \ +#define INTERNAL_CHECK_THAT( macroName, matcher, resultDisposition, arg ) \ do { \ - Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__) ", " CATCH_INTERNAL_STRINGIFY(matcher), resultDisposition ); \ - if( catchAssertionHandler.allowThrows() ) \ - try { \ - static_cast(__VA_ARGS__); \ - catchAssertionHandler.handle( Catch::ResultWas::DidntThrowException ); \ - } \ - catch( ... ) { \ - handleExceptionMatchExpr( catchAssertionHandler, matcher, #matcher ); \ - } \ - else \ - catchAssertionHandler.handle( Catch::ResultWas::Ok ); \ - INTERNAL_CATCH_REACT( catchAssertionHandler ) \ + Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #arg ", " #matcher, resultDisposition ); \ + try { \ + __catchResult.captureMatch( arg, matcher, #matcher ); \ + } catch( ... ) { \ + __catchResult.useActiveException( resultDisposition | Catch::ResultDisposition::ContinueOnFailure ); \ + } \ + INTERNAL_CATCH_REACT( __catchResult ) \ } while( Catch::alwaysFalse() ) -#endif // CATCH_CONFIG_DISABLE +// #included from: internal/catch_section.h +#define TWOBLUECUBES_CATCH_SECTION_H_INCLUDED -// end catch_capture.hpp -// start catch_section.h +// #included from: catch_section_info.h +#define TWOBLUECUBES_CATCH_SECTION_INFO_H_INCLUDED -// start catch_section_info.h - -// start catch_totals.h +// #included from: catch_totals.hpp +#define TWOBLUECUBES_CATCH_TOTALS_HPP_INCLUDED #include namespace Catch { struct Counts { - Counts operator - ( Counts const& other ) const; - Counts& operator += ( Counts const& other ); + Counts() : passed( 0 ), failed( 0 ), failedButOk( 0 ) {} - std::size_t total() const; - bool allPassed() const; - bool allOk() const; + 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 passed = 0; - std::size_t failed = 0; - std::size_t failedButOk = 0; + std::size_t total() const { + return passed + failed + failedButOk; + } + bool allPassed() const { + return failed == 0 && failedButOk == 0; + } + bool allOk() const { + return failed == 0; + } + + std::size_t passed; + std::size_t failed; + std::size_t failedButOk; }; struct Totals { - Totals operator - ( Totals const& other ) const; - Totals& operator += ( Totals const& other ); + 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 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; }; } -// end catch_totals.h #include namespace Catch { @@ -1594,7 +2415,9 @@ namespace Catch { }; struct SectionEndInfo { - SectionEndInfo( SectionInfo const& _sectionInfo, Counts const& _prevAssertions, double _durationInSeconds ); + SectionEndInfo( SectionInfo const& _sectionInfo, Counts const& _prevAssertions, double _durationInSeconds ) + : sectionInfo( _sectionInfo ), prevAssertions( _prevAssertions ), durationInSeconds( _durationInSeconds ) + {} SectionInfo sectionInfo; Counts prevAssertions; @@ -1603,29 +2426,36 @@ namespace Catch { } // end namespace Catch -// end catch_section_info.h -// start catch_timer.h +// #included from: catch_timer.h +#define TWOBLUECUBES_CATCH_TIMER_H_INCLUDED -#include +#ifdef _MSC_VER namespace Catch { + typedef unsigned long long UInt64; +} +#else +#include +namespace Catch { + typedef uint64_t UInt64; +} +#endif - auto getCurrentNanosecondsSinceEpoch() -> uint64_t; - auto getEstimatedClockResolution() -> uint64_t; - +namespace Catch { class Timer { - uint64_t m_nanoseconds = 0; public: + Timer() : m_ticks( 0 ) {} void start(); - auto getElapsedNanoseconds() const -> unsigned int; - auto getElapsedMicroseconds() const -> unsigned int; - auto getElapsedMilliseconds() const -> unsigned int; - auto getElapsedSeconds() const -> double; + unsigned int getElapsedMicroseconds() const; + unsigned int getElapsedMilliseconds() const; + double getElapsedSeconds() const; + + private: + UInt64 m_ticks; }; } // namespace Catch -// end catch_timer.h #include namespace Catch { @@ -1636,7 +2466,7 @@ namespace Catch { ~Section(); // This indicates whether the section should be executed or not - explicit operator bool() const; + operator bool() const; private: SectionInfo m_info; @@ -1649,62 +2479,203 @@ namespace Catch { } // end namespace Catch +#ifdef CATCH_CONFIG_VARIADIC_MACROS #define INTERNAL_CATCH_SECTION( ... ) \ if( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::SectionInfo( CATCH_INTERNAL_LINEINFO, __VA_ARGS__ ) ) +#else + #define INTERNAL_CATCH_SECTION( name, desc ) \ + if( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::SectionInfo( CATCH_INTERNAL_LINEINFO, name, desc ) ) +#endif -// end catch_section.h -// start catch_benchmark.h +// #included from: internal/catch_generators.hpp +#define TWOBLUECUBES_CATCH_GENERATORS_HPP_INCLUDED -#include +#include #include +#include namespace Catch { - class BenchmarkLooper { +template +struct IGenerator { + virtual ~IGenerator() {} + virtual T getValue( std::size_t index ) const = 0; + virtual std::size_t size () const = 0; +}; - std::string m_name; - std::size_t m_count = 0; - std::size_t m_iterationsToRun = 1; - uint64_t m_resolution; - Timer m_timer; +template +class BetweenGenerator : public IGenerator { +public: + BetweenGenerator( T from, T to ) : m_from( from ), m_to( to ){} - static auto getResolution() -> uint64_t; - public: - // Keep most of this inline as it's on the code path that is being timed - BenchmarkLooper( StringRef name ) - : m_name( name ), - m_resolution( getResolution() ) + 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 ); + } + +private: + + T m_from; + T m_to; +}; + +template +class ValuesGenerator : public IGenerator { +public: + ValuesGenerator(){} + + void add( T value ) { + m_values.push_back( value ); + } + + virtual T getValue( std::size_t index ) const { + return m_values[index]; + } + + virtual std::size_t size() const { + return m_values.size(); + } + +private: + std::vector m_values; +}; + +template +class CompositeGenerator { +public: + CompositeGenerator() : m_totalSize( 0 ) {} + + // *** Move semantics, similar to auto_ptr *** + CompositeGenerator( CompositeGenerator& other ) + : m_fileInfo( other.m_fileInfo ), + m_totalSize( 0 ) + { + move( other ); + } + + CompositeGenerator& setFileInfo( const char* fileInfo ) { + m_fileInfo = fileInfo; + return *this; + } + + ~CompositeGenerator() { + deleteAll( m_composed ); + } + + operator T () const { + size_t overallIndex = getCurrentContext().getGeneratorIndex( m_fileInfo, m_totalSize ); + + typename std::vector*>::const_iterator it = m_composed.begin(); + typename std::vector*>::const_iterator itEnd = m_composed.end(); + for( size_t index = 0; it != itEnd; ++it ) { - reportStart(); - m_timer.start(); + const IGenerator* generator = *it; + if( overallIndex >= index && overallIndex < index + generator->size() ) + { + return generator->getValue( overallIndex-index ); + } + index += generator->size(); } + CATCH_INTERNAL_ERROR( "Indexed past end of generated range" ); + return T(); // Suppress spurious "not all control paths return a value" warning in Visual Studio - if you know how to fix this please do so + } - explicit operator bool() { - if( m_count < m_iterationsToRun ) - return true; - return needsMoreIterations(); - } + void add( const IGenerator* generator ) { + m_totalSize += generator->size(); + m_composed.push_back( generator ); + } - void increment() { - ++m_count; - } + CompositeGenerator& then( CompositeGenerator& other ) { + move( other ); + return *this; + } - void reportStart(); - auto needsMoreIterations() -> bool; - }; + CompositeGenerator& then( T value ) { + ValuesGenerator* valuesGen = new ValuesGenerator(); + valuesGen->add( value ); + add( valuesGen ); + return *this; + } + +private: + + void move( CompositeGenerator& other ) { + m_composed.insert( m_composed.end(), other.m_composed.begin(), other.m_composed.end() ); + m_totalSize += other.m_totalSize; + other.m_composed.clear(); + } + + std::vector*> m_composed; + std::string m_fileInfo; + size_t m_totalSize; +}; + +namespace 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, 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; + } + +} // end namespace Generators + +using namespace Generators; } // end namespace Catch -#define BENCHMARK( name ) \ - for( Catch::BenchmarkLooper looper( name ); looper; looper.increment() ) +#define INTERNAL_CATCH_LINESTR2( line ) #line +#define INTERNAL_CATCH_LINESTR( line ) INTERNAL_CATCH_LINESTR2( line ) -// end catch_benchmark.h -// start catch_interfaces_exception.h +#define INTERNAL_CATCH_GENERATE( expr ) expr.setFileInfo( __FILE__ "(" INTERNAL_CATCH_LINESTR( __LINE__ ) ")" ) -// start catch_interfaces_registry_hub.h +// #included from: internal/catch_interfaces_exception.h +#define TWOBLUECUBES_CATCH_INTERFACES_EXCEPTION_H_INCLUDED + +#include +#include + +// #included from: catch_interfaces_registry_hub.h +#define TWOBLUECUBES_CATCH_INTERFACES_REGISTRY_HUB_H_INCLUDED #include -#include namespace Catch { @@ -1715,9 +2686,6 @@ namespace Catch { struct IReporterRegistry; struct IReporterFactory; struct ITagAliasRegistry; - class StartupExceptionRegistry; - - using IReporterFactoryPtr = std::shared_ptr; struct IRegistryHub { virtual ~IRegistryHub(); @@ -1727,18 +2695,15 @@ namespace Catch { virtual ITagAliasRegistry const& getTagAliasRegistry() const = 0; virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() = 0; - - virtual StartupExceptionRegistry const& getStartupExceptionRegistry() const = 0; }; struct IMutableRegistryHub { virtual ~IMutableRegistryHub(); - virtual void registerReporter( std::string const& name, IReporterFactoryPtr const& factory ) = 0; - virtual void registerListener( IReporterFactoryPtr const& factory ) = 0; + virtual void registerReporter( std::string const& name, Ptr const& factory ) = 0; + virtual void registerListener( Ptr const& factory ) = 0; virtual void registerTest( TestCase const& testInfo ) = 0; virtual void registerTranslator( const IExceptionTranslator* translator ) = 0; virtual void registerTagAlias( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo ) = 0; - virtual void registerStartupException() noexcept = 0; }; IRegistryHub& getRegistryHub(); @@ -1748,21 +2713,12 @@ namespace Catch { } -// end catch_interfaces_registry_hub.h -#if defined(CATCH_CONFIG_DISABLE) - #define INTERNAL_CATCH_TRANSLATE_EXCEPTION_NO_REG( translatorName, signature) \ - static std::string translatorName( signature ) -#endif - -#include -#include -#include - namespace Catch { - using exceptionTranslateFunction = std::string(*)(); + + typedef std::string(*exceptionTranslateFunction)(); struct IExceptionTranslator; - using ExceptionTranslators = std::vector>; + typedef std::vector ExceptionTranslators; struct IExceptionTranslator { virtual ~IExceptionTranslator(); @@ -1784,10 +2740,10 @@ namespace Catch { : m_translateFunction( translateFunction ) {} - std::string translate( ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd ) const override { + virtual std::string translate( ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd ) const CATCH_OVERRIDE { try { if( it == itEnd ) - std::rethrow_exception(std::current_exception()); + throw; else return (*it)->translate( it+1, itEnd ); } @@ -1817,40 +2773,36 @@ namespace Catch { #define INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION2( INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator ), signature ) -// end catch_interfaces_exception.h -// start catch_approx.h +// #included from: internal/catch_approx.hpp +#define TWOBLUECUBES_CATCH_APPROX_HPP_INCLUDED -// start catch_enforce.h +#include +#include -#include -#include - -#define CATCH_PREPARE_EXCEPTION( type, msg ) \ - type( static_cast( std::ostringstream() << msg ).str() ) -#define CATCH_INTERNAL_ERROR( msg ) \ - throw CATCH_PREPARE_EXCEPTION( std::logic_error, CATCH_INTERNAL_LINEINFO << ": Internal Catch error: " << msg); -#define CATCH_ERROR( msg ) \ - throw CATCH_PREPARE_EXCEPTION( std::domain_error, msg ) -#define CATCH_ENFORCE( condition, msg ) \ - do{ if( !(condition) ) CATCH_ERROR( msg ); } while(false) - -// end catch_enforce.h +#if defined(CATCH_CONFIG_CPP11_TYPE_TRAITS) #include +#endif namespace Catch { namespace Detail { class Approx { - private: - bool equalityComparisonImpl(double other) const; - public: - explicit Approx ( double value ); + explicit Approx ( double value ) + : m_epsilon( std::numeric_limits::epsilon()*100 ), + m_margin( 0.0 ), + m_scale( 1.0 ), + m_value( value ) + {} - static Approx custom(); + static Approx custom() { + return Approx( 0 ); + } + +#if defined(CATCH_CONFIG_CPP11_TYPE_TRAITS) template ::value>::type> - Approx operator()( T const& value ) { + Approx operator()( T value ) { Approx approx( static_cast(value) ); approx.epsilon( m_epsilon ); approx.margin( m_margin ); @@ -1859,13 +2811,18 @@ namespace Detail { } template ::value>::type> - explicit Approx( T const& value ): Approx(static_cast(value)) + explicit Approx( T value ): Approx(static_cast(value)) {} template ::value>::type> friend bool operator == ( const T& lhs, Approx const& rhs ) { - auto lhs_v = static_cast(lhs); - return rhs.equalityComparisonImpl(lhs_v); + // Thanks to Richard Harris for his help refining this formula + auto lhs_v = double(lhs); + bool relativeOK = std::fabs(lhs_v - rhs.m_value) < rhs.m_epsilon * (rhs.m_scale + (std::max)(std::fabs(lhs_v), std::fabs(rhs.m_value))); + if (relativeOK) { + return true; + } + return std::fabs(lhs_v - rhs.m_value) < rhs.m_margin; } template ::value>::type> @@ -1874,62 +2831,121 @@ namespace Detail { } template ::value>::type> - friend bool operator != ( T const& lhs, Approx const& rhs ) { + friend bool operator != ( T lhs, Approx const& rhs ) { return !operator==( lhs, rhs ); } template ::value>::type> - friend bool operator != ( Approx const& lhs, T const& rhs ) { + friend bool operator != ( Approx const& lhs, T rhs ) { return !operator==( rhs, lhs ); } template ::value>::type> - friend bool operator <= ( T const& lhs, Approx const& rhs ) { - return static_cast(lhs) < rhs.m_value || lhs == rhs; + friend bool operator <= ( T lhs, Approx const& rhs ) { + return double(lhs) < rhs.m_value || lhs == rhs; } template ::value>::type> - friend bool operator <= ( Approx const& lhs, T const& rhs ) { - return lhs.m_value < static_cast(rhs) || lhs == rhs; + friend bool operator <= ( Approx const& lhs, T rhs ) { + return lhs.m_value < double(rhs) || lhs == rhs; } template ::value>::type> - friend bool operator >= ( T const& lhs, Approx const& rhs ) { - return static_cast(lhs) > rhs.m_value || lhs == rhs; + friend bool operator >= ( T lhs, Approx const& rhs ) { + return double(lhs) > rhs.m_value || lhs == rhs; } template ::value>::type> - friend bool operator >= ( Approx const& lhs, T const& rhs ) { - return lhs.m_value > static_cast(rhs) || lhs == rhs; + friend bool operator >= ( Approx const& lhs, T rhs ) { + return lhs.m_value > double(rhs) || lhs == rhs; } template ::value>::type> - Approx& epsilon( T const& newEpsilon ) { - double epsilonAsDouble = static_cast(newEpsilon); - CATCH_ENFORCE(epsilonAsDouble >= 0 && epsilonAsDouble <= 1.0, - "Invalid Approx::epsilon: " << epsilonAsDouble - << ", Approx::epsilon has to be between 0 and 1"); - m_epsilon = epsilonAsDouble; + Approx& epsilon( T newEpsilon ) { + m_epsilon = double(newEpsilon); return *this; } template ::value>::type> - Approx& margin( T const& newMargin ) { - double marginAsDouble = static_cast(newMargin); - CATCH_ENFORCE(marginAsDouble >= 0, - "Invalid Approx::margin: " << marginAsDouble - << ", Approx::Margin has to be non-negative."); - m_margin = marginAsDouble; + Approx& margin( T newMargin ) { + m_margin = double(newMargin); return *this; } template ::value>::type> - Approx& scale( T const& newScale ) { - m_scale = static_cast(newScale); + Approx& scale( T newScale ) { + m_scale = double(newScale); return *this; } - std::string toString() const; +#else + + Approx operator()( double value ) { + Approx approx( value ); + approx.epsilon( m_epsilon ); + approx.margin( m_margin ); + approx.scale( m_scale ); + return approx; + } + + friend bool operator == ( double lhs, Approx const& rhs ) { + // Thanks to Richard Harris for his help refining this formula + bool relativeOK = std::fabs( lhs - rhs.m_value ) < rhs.m_epsilon * (rhs.m_scale + (std::max)( std::fabs(lhs), std::fabs(rhs.m_value) ) ); + if (relativeOK) { + return true; + } + return std::fabs(lhs - rhs.m_value) < rhs.m_margin; + } + + friend bool operator == ( Approx const& lhs, double rhs ) { + return operator==( rhs, lhs ); + } + + friend bool operator != ( double lhs, Approx const& rhs ) { + return !operator==( lhs, rhs ); + } + + friend bool operator != ( Approx const& lhs, double rhs ) { + return !operator==( rhs, lhs ); + } + + friend bool operator <= ( double lhs, Approx const& rhs ) { + return lhs < rhs.m_value || lhs == rhs; + } + + friend bool operator <= ( Approx const& lhs, double rhs ) { + return lhs.m_value < rhs || lhs == rhs; + } + + friend bool operator >= ( double lhs, Approx const& rhs ) { + return lhs > rhs.m_value || lhs == rhs; + } + + friend bool operator >= ( Approx const& lhs, double rhs ) { + return lhs.m_value > rhs || lhs == rhs; + } + + Approx& epsilon( double newEpsilon ) { + m_epsilon = newEpsilon; + return *this; + } + + Approx& margin( double newMargin ) { + m_margin = newMargin; + return *this; + } + + Approx& scale( double newScale ) { + m_scale = newScale; + return *this; + } +#endif + + std::string toString() const { + std::ostringstream oss; + oss << "Approx( " << Catch::toString( m_value ) << " )"; + return oss.str(); + } private: double m_epsilon; @@ -1940,194 +2956,14 @@ namespace Detail { } template<> -struct StringMaker { - static std::string convert(Catch::Detail::Approx const& value); -}; +inline std::string toString( Detail::Approx const& value ) { + return value.toString(); +} } // end namespace Catch -// end catch_approx.h -// start catch_string_manip.h - -#include -#include - -namespace Catch { - - bool startsWith( std::string const& s, std::string const& prefix ); - bool startsWith( std::string const& s, char prefix ); - bool endsWith( std::string const& s, std::string const& suffix ); - bool endsWith( std::string const& s, char suffix ); - bool contains( std::string const& s, std::string const& infix ); - void toLowerInPlace( std::string& s ); - std::string toLower( std::string const& s ); - std::string trim( std::string const& str ); - bool replaceInPlace( std::string& str, std::string const& replaceThis, std::string const& withThis ); - - struct pluralise { - pluralise( std::size_t count, std::string const& label ); - - friend std::ostream& operator << ( std::ostream& os, pluralise const& pluraliser ); - - std::size_t m_count; - std::string m_label; - }; -} - -// end catch_string_manip.h -#ifndef CATCH_CONFIG_DISABLE_MATCHERS -// start catch_capture_matchers.h - -// start catch_matchers.h - -#include -#include - -namespace Catch { -namespace Matchers { - namespace Impl { - - template struct MatchAllOf; - template struct MatchAnyOf; - template struct MatchNotOf; - - class MatcherUntypedBase { - public: - MatcherUntypedBase() = default; - MatcherUntypedBase ( MatcherUntypedBase const& ) = default; - MatcherUntypedBase& operator = ( MatcherUntypedBase const& ) = delete; - std::string toString() const; - - protected: - virtual ~MatcherUntypedBase(); - virtual std::string describe() const = 0; - mutable std::string m_cachedToString; - }; - - template - struct MatcherMethod { - virtual bool match( ObjectT const& arg ) const = 0; - }; - template - struct MatcherMethod { - virtual bool match( PtrT* arg ) const = 0; - }; - - template - struct MatcherBase : MatcherUntypedBase, MatcherMethod { - - MatchAllOf operator && ( MatcherBase const& other ) const; - MatchAnyOf operator || ( MatcherBase const& other ) const; - MatchNotOf operator ! () const; - }; - - template - struct MatchAllOf : MatcherBase { - bool match( ArgT const& arg ) const override { - for( auto matcher : m_matchers ) { - if (!matcher->match(arg)) - return false; - } - return true; - } - std::string describe() const override { - std::string description; - description.reserve( 4 + m_matchers.size()*32 ); - description += "( "; - bool first = true; - for( auto matcher : m_matchers ) { - if( first ) - first = false; - else - description += " and "; - description += matcher->toString(); - } - description += " )"; - return description; - } - - MatchAllOf& operator && ( MatcherBase const& other ) { - m_matchers.push_back( &other ); - return *this; - } - - std::vector const*> m_matchers; - }; - template - struct MatchAnyOf : MatcherBase { - - bool match( ArgT const& arg ) const override { - for( auto matcher : m_matchers ) { - if (matcher->match(arg)) - return true; - } - return false; - } - std::string describe() const override { - std::string description; - description.reserve( 4 + m_matchers.size()*32 ); - description += "( "; - bool first = true; - for( auto matcher : m_matchers ) { - if( first ) - first = false; - else - description += " or "; - description += matcher->toString(); - } - description += " )"; - return description; - } - - MatchAnyOf& operator || ( MatcherBase const& other ) { - m_matchers.push_back( &other ); - return *this; - } - - std::vector const*> m_matchers; - }; - - template - struct MatchNotOf : MatcherBase { - - MatchNotOf( MatcherBase const& underlyingMatcher ) : m_underlyingMatcher( underlyingMatcher ) {} - - bool match( ArgT const& arg ) const override { - return !m_underlyingMatcher.match( arg ); - } - - std::string describe() const override { - return "not " + m_underlyingMatcher.toString(); - } - MatcherBase const& m_underlyingMatcher; - }; - - template - MatchAllOf MatcherBase::operator && ( MatcherBase const& other ) const { - return MatchAllOf() && *this && other; - } - template - MatchAnyOf MatcherBase::operator || ( MatcherBase const& other ) const { - return MatchAnyOf() || *this || other; - } - template - MatchNotOf MatcherBase::operator ! () const { - return MatchNotOf( *this ); - } - - } // namespace Impl - -} // namespace Matchers - -using namespace Matchers; -using Matchers::Impl::MatcherBase; - -} // namespace Catch - -// end catch_matchers.h -// start catch_matchers_string.h - -#include +// #included from: internal/catch_matchers_string.h +#define TWOBLUECUBES_CATCH_MATCHERS_STRING_H_INCLUDED namespace Catch { namespace Matchers { @@ -2146,7 +2982,7 @@ namespace Matchers { struct StringMatcherBase : MatcherBase { StringMatcherBase( std::string const& operation, CasedString const& comparator ); - std::string describe() const override; + virtual std::string describe() const CATCH_OVERRIDE; CasedString m_comparator; std::string m_operation; @@ -2154,19 +2990,19 @@ namespace Matchers { struct EqualsMatcher : StringMatcherBase { EqualsMatcher( CasedString const& comparator ); - bool match( std::string const& source ) const override; + virtual bool match( std::string const& source ) const CATCH_OVERRIDE; }; struct ContainsMatcher : StringMatcherBase { ContainsMatcher( CasedString const& comparator ); - bool match( std::string const& source ) const override; + virtual bool match( std::string const& source ) const CATCH_OVERRIDE; }; struct StartsWithMatcher : StringMatcherBase { StartsWithMatcher( CasedString const& comparator ); - bool match( std::string const& source ) const override; + virtual bool match( std::string const& source ) const CATCH_OVERRIDE; }; struct EndsWithMatcher : StringMatcherBase { EndsWithMatcher( CasedString const& comparator ); - bool match( std::string const& source ) const override; + virtual bool match( std::string const& source ) const CATCH_OVERRIDE; }; } // namespace StdString @@ -2182,8 +3018,8 @@ namespace Matchers { } // namespace Matchers } // namespace Catch -// end catch_matchers_string.h -// start catch_matchers_vector.h +// #included from: internal/catch_matchers_vector.h +#define TWOBLUECUBES_CATCH_MATCHERS_VECTOR_H_INCLUDED namespace Catch { namespace Matchers { @@ -2195,17 +3031,12 @@ namespace Matchers { ContainsElementMatcher(T const &comparator) : m_comparator( comparator) {} - bool match(std::vector const &v) const override { - for (auto const& el : v) { - if (el == m_comparator) { - return true; - } - } - return false; + bool match(std::vector const &v) const CATCH_OVERRIDE { + return std::find(v.begin(), v.end(), m_comparator) != v.end(); } - std::string describe() const override { - return "Contains: " + ::Catch::Detail::stringify( m_comparator ); + virtual std::string describe() const CATCH_OVERRIDE { + return "Contains: " + Catch::toString( m_comparator ); } T const& m_comparator; @@ -2216,26 +3047,17 @@ namespace Matchers { ContainsMatcher(std::vector const &comparator) : m_comparator( comparator ) {} - bool match(std::vector const &v) const override { + bool match(std::vector const &v) const CATCH_OVERRIDE { // !TBD: see note in EqualsMatcher if (m_comparator.size() > v.size()) return false; - for (auto const& comparator : m_comparator) { - auto present = false; - for (const auto& el : v) { - if (el == comparator) { - present = true; - break; - } - } - if (!present) { + for (size_t i = 0; i < m_comparator.size(); ++i) + if (std::find(v.begin(), v.end(), m_comparator[i]) == v.end()) return false; - } - } return true; } - std::string describe() const override { - return "Contains: " + ::Catch::Detail::stringify( m_comparator ); + virtual std::string describe() const CATCH_OVERRIDE { + return "Contains: " + Catch::toString( m_comparator ); } std::vector const& m_comparator; @@ -2246,20 +3068,20 @@ namespace Matchers { EqualsMatcher(std::vector const &comparator) : m_comparator( comparator ) {} - bool match(std::vector const &v) const override { + bool match(std::vector const &v) const CATCH_OVERRIDE { // !TBD: This currently works if all elements can be compared using != // - a more general approach would be via a compare template that defaults // to using !=. but could be specialised for, e.g. std::vector etc // - then just call that directly if (m_comparator.size() != v.size()) return false; - for (std::size_t i = 0; i < v.size(); ++i) + for (size_t i = 0; i < v.size(); ++i) if (m_comparator[i] != v[i]) return false; return true; } - std::string describe() const override { - return "Equals: " + ::Catch::Detail::stringify( m_comparator ); + virtual std::string describe() const CATCH_OVERRIDE { + return "Equals: " + Catch::toString( m_comparator ); } std::vector const& m_comparator; }; @@ -2287,87 +3109,124 @@ namespace Matchers { } // namespace Matchers } // namespace Catch -// end catch_matchers_vector.h +// #included from: internal/catch_interfaces_tag_alias_registry.h +#define TWOBLUECUBES_CATCH_INTERFACES_TAG_ALIAS_REGISTRY_H_INCLUDED + +// #included from: catch_tag_alias.h +#define TWOBLUECUBES_CATCH_TAG_ALIAS_H_INCLUDED + +#include + namespace Catch { - template - class MatchExpr : public ITransientExpression { - ArgT const& m_arg; - MatcherT m_matcher; - StringRef m_matcherString; - bool m_result; - public: - MatchExpr( ArgT const& arg, MatcherT const& matcher, StringRef matcherString ) - : m_arg( arg ), - m_matcher( matcher ), - m_matcherString( matcherString ), - m_result( matcher.match( arg ) ) - {} + struct TagAlias { + TagAlias( std::string const& _tag, SourceLineInfo _lineInfo ) : tag( _tag ), lineInfo( _lineInfo ) {} - auto isBinaryExpression() const -> bool override { return true; } - auto getResult() const -> bool override { return m_result; } - - void streamReconstructedExpression( std::ostream &os ) const override { - auto matcherAsString = m_matcher.toString(); - os << Catch::Detail::stringify( m_arg ) << ' '; - if( matcherAsString == Detail::unprintableString ) - os << m_matcherString; - else - os << matcherAsString; - } + std::string tag; + SourceLineInfo lineInfo; }; - using StringMatcher = Matchers::Impl::MatcherBase; + struct RegistrarForTagAliases { + RegistrarForTagAliases( char const* alias, char const* tag, SourceLineInfo const& lineInfo ); + }; - void handleExceptionMatchExpr( AssertionHandler& handler, StringMatcher const& matcher, StringRef matcherString ); +} // end namespace Catch - template - auto makeMatchExpr( ArgT const& arg, MatcherT const& matcher, StringRef matcherString ) -> MatchExpr { - return MatchExpr( arg, matcher, matcherString ); - } +#define CATCH_REGISTER_TAG_ALIAS( alias, spec ) namespace{ Catch::RegistrarForTagAliases INTERNAL_CATCH_UNIQUE_NAME( AutoRegisterTagAlias )( alias, spec, CATCH_INTERNAL_LINEINFO ); } +// #included from: catch_option.hpp +#define TWOBLUECUBES_CATCH_OPTION_HPP_INCLUDED -} // namespace Catch +namespace Catch { -/////////////////////////////////////////////////////////////////////////////// -#define INTERNAL_CHECK_THAT( macroName, matcher, resultDisposition, arg ) \ - do { \ - Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(arg) ", " CATCH_INTERNAL_STRINGIFY(matcher), resultDisposition ); \ - INTERNAL_CATCH_TRY( catchAssertionHandler ) { \ - catchAssertionHandler.handle( Catch::makeMatchExpr( arg, matcher, #matcher ) ); \ - } INTERNAL_CATCH_CATCH( catchAssertionHandler ) \ - INTERNAL_CATCH_REACT( catchAssertionHandler ) \ - } while( Catch::alwaysFalse() ) + // An optional type + template + class Option { + public: + Option() : nullableValue( CATCH_NULL ) {} + Option( T const& _value ) + : nullableValue( new( storage ) T( _value ) ) + {} + Option( Option const& _other ) + : nullableValue( _other ? new( storage ) T( *_other ) : CATCH_NULL ) + {} -/////////////////////////////////////////////////////////////////////////////// -#define INTERNAL_CATCH_THROWS_MATCHES( macroName, exceptionType, resultDisposition, matcher, ... ) \ - do { \ - Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__) ", " CATCH_INTERNAL_STRINGIFY(exceptionType) ", " CATCH_INTERNAL_STRINGIFY(matcher), resultDisposition ); \ - if( catchAssertionHandler.allowThrows() ) \ - try { \ - static_cast(__VA_ARGS__ ); \ - catchAssertionHandler.handle( Catch::ResultWas::DidntThrowException ); \ - } \ - catch( exceptionType const& ex ) { \ - catchAssertionHandler.handle( Catch::makeMatchExpr( ex, matcher, #matcher ) ); \ - } \ - catch( ... ) { \ - catchAssertionHandler.useActiveException(); \ - } \ - else \ - catchAssertionHandler.handle( Catch::ResultWas::Ok ); \ - INTERNAL_CATCH_REACT( catchAssertionHandler ) \ - } while( Catch::alwaysFalse() ) + ~Option() { + reset(); + } -// end catch_capture_matchers.h + Option& operator= ( Option const& _other ) { + if( &_other != this ) { + reset(); + if( _other ) + nullableValue = new( storage ) T( *_other ); + } + return *this; + } + Option& operator = ( T const& _value ) { + reset(); + nullableValue = new( storage ) T( _value ); + return *this; + } + + void reset() { + if( nullableValue ) + nullableValue->~T(); + nullableValue = CATCH_NULL; + } + + T& operator*() { return *nullableValue; } + T const& operator*() const { return *nullableValue; } + T* operator->() { return nullableValue; } + const T* operator->() const { return nullableValue; } + + T valueOr( T const& defaultValue ) const { + return nullableValue ? *nullableValue : defaultValue; + } + + bool some() const { return nullableValue != CATCH_NULL; } + bool none() const { return nullableValue == CATCH_NULL; } + + bool operator !() const { return nullableValue == CATCH_NULL; } + operator SafeBool::type() const { + return SafeBool::makeSafe( some() ); + } + + private: + T *nullableValue; + union { + char storage[sizeof(T)]; + + // These are here to force alignment for the storage + long double dummy1; + void (*dummy2)(); + long double dummy3; +#ifdef CATCH_CONFIG_CPP11_LONG_LONG + long long dummy4; #endif + }; + }; + +} // end 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; + + static ITagAliasRegistry const& get(); + }; + +} // end namespace Catch // These files are included here so the single_include script doesn't put them // in the conditionally compiled sections -// start catch_test_case_info.h +// #included from: internal/catch_test_case_info.h +#define TWOBLUECUBES_CATCH_TEST_CASE_INFO_H_INCLUDED #include -#include -#include +#include #ifdef __clang__ #pragma clang diagnostic push @@ -2376,7 +3235,7 @@ namespace Catch { namespace Catch { - struct ITestInvoker; + struct ITestCase; struct TestCaseInfo { enum SpecialProperties{ @@ -2385,30 +3244,30 @@ namespace Catch { ShouldFail = 1 << 2, MayFail = 1 << 3, Throws = 1 << 4, - NonPortable = 1 << 5, - Benchmark = 1 << 6 + NonPortable = 1 << 5 }; TestCaseInfo( std::string const& _name, std::string const& _className, std::string const& _description, - std::vector const& _tags, + std::set const& _tags, SourceLineInfo const& _lineInfo ); - friend void setTags( TestCaseInfo& testCaseInfo, std::vector tags ); + TestCaseInfo( TestCaseInfo const& other ); + + friend void setTags( TestCaseInfo& testCaseInfo, std::set const& tags ); bool isHidden() const; bool throws() const; bool okToFail() const; bool expectedToFail() const; - std::string tagsAsString() const; - std::string name; std::string className; std::string description; - std::vector tags; - std::vector lcaseTags; + std::set tags; + std::set lcaseTags; + std::string tagsAsString; SourceLineInfo lineInfo; SpecialProperties properties; }; @@ -2416,7 +3275,8 @@ namespace Catch { class TestCase : public TestCaseInfo { public: - TestCase( ITestInvoker* testCase, TestCaseInfo const& info ); + TestCase( ITestCase* testCase, TestCaseInfo const& info ); + TestCase( TestCase const& other ); TestCase withName( std::string const& _newName ) const; @@ -2424,14 +3284,16 @@ namespace Catch { 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: - std::shared_ptr test; + Ptr test; }; - TestCase makeTestCase( ITestInvoker* testCase, + TestCase makeTestCase( ITestCase* testCase, std::string const& className, std::string const& name, std::string const& description, @@ -2442,21 +3304,10 @@ namespace Catch { #pragma clang diagnostic pop #endif -// end catch_test_case_info.h -// start catch_interfaces_runner.h - -namespace Catch { - - struct IRunner { - virtual ~IRunner(); - virtual bool aborting() const = 0; - }; -} - -// end catch_interfaces_runner.h #ifdef __OBJC__ -// start catch_objc.hpp +// #included from: internal/catch_objc.hpp +#define TWOBLUECUBES_CATCH_OBJC_HPP_INCLUDED #import @@ -2480,7 +3331,7 @@ namespace Catch { namespace Catch { - class OcMethod : public ITestInvoker { + class OcMethod : public SharedImpl { public: OcMethod( Class cls, SEL sel ) : m_cls( cls ), m_sel( sel ) {} @@ -2516,9 +3367,9 @@ namespace Catch { } } - inline std::size_t registerTestMethods() { - std::size_t noTestMethods = 0; - int noClasses = objc_getClassList( nullptr, 0 ); + inline size_t registerTestMethods() { + size_t noTestMethods = 0; + int noClasses = objc_getClassList( CATCH_NULL, 0 ); Class* classes = (CATCH_UNSAFE_UNRETAINED Class *)malloc( sizeof(Class) * noClasses); objc_getClassList( classes, noClasses ); @@ -2537,7 +3388,7 @@ namespace Catch { 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("",0) ) ); + getMutableRegistryHub().registerTest( makeTestCase( new OcMethod( cls, selector ), className, name.c_str(), desc.c_str(), SourceLineInfo() ) ); noTestMethods++; } } @@ -2547,8 +3398,6 @@ namespace Catch { return noTestMethods; } -#if !defined(CATCH_CONFIG_DISABLE_MATCHERS) - namespace Matchers { namespace Impl { namespace NSStringMatchers { @@ -2560,61 +3409,61 @@ namespace Catch { arcSafeRelease( m_substr ); } - bool match( NSString* arg ) const override { + virtual bool match( NSString* arg ) const CATCH_OVERRIDE { return false; } - NSString* CATCH_ARC_STRONG m_substr; + NSString* m_substr; }; struct Equals : StringHolder { Equals( NSString* substr ) : StringHolder( substr ){} - bool match( NSString* str ) const override { + virtual bool match( NSString* str ) const CATCH_OVERRIDE { return (str != nil || m_substr == nil ) && [str isEqualToString:m_substr]; } - std::string describe() const override { - return "equals string: " + Catch::Detail::stringify( m_substr ); + virtual std::string describe() const CATCH_OVERRIDE { + return "equals string: " + Catch::toString( m_substr ); } }; struct Contains : StringHolder { Contains( NSString* substr ) : StringHolder( substr ){} - bool match( NSString* str ) const { + virtual bool match( NSString* str ) const { return (str != nil || m_substr == nil ) && [str rangeOfString:m_substr].location != NSNotFound; } - std::string describe() const override { - return "contains string: " + Catch::Detail::stringify( m_substr ); + virtual std::string describe() const CATCH_OVERRIDE { + return "contains string: " + Catch::toString( m_substr ); } }; struct StartsWith : StringHolder { StartsWith( NSString* substr ) : StringHolder( substr ){} - bool match( NSString* str ) const override { + virtual bool match( NSString* str ) const { return (str != nil || m_substr == nil ) && [str rangeOfString:m_substr].location == 0; } - std::string describe() const override { - return "starts with: " + Catch::Detail::stringify( m_substr ); + virtual std::string describe() const CATCH_OVERRIDE { + return "starts with: " + Catch::toString( m_substr ); } }; struct EndsWith : StringHolder { EndsWith( NSString* substr ) : StringHolder( substr ){} - bool match( NSString* str ) const override { + virtual bool match( NSString* str ) const { return (str != nil || m_substr == nil ) && [str rangeOfString:m_substr].location == [str length] - [m_substr length]; } - std::string describe() const override { - return "ends with: " + Catch::Detail::stringify( m_substr ); + virtual std::string describe() const CATCH_OVERRIDE { + return "ends with: " + Catch::toString( m_substr ); } }; @@ -2637,52 +3486,86 @@ namespace Catch { using namespace Matchers; -#endif // CATCH_CONFIG_DISABLE_MATCHERS - } // namespace Catch /////////////////////////////////////////////////////////////////////////////// -#define OC_MAKE_UNIQUE_NAME( root, uniqueSuffix ) root##uniqueSuffix -#define OC_TEST_CASE2( name, desc, uniqueSuffix ) \ -+(NSString*) OC_MAKE_UNIQUE_NAME( Catch_Name_test_, uniqueSuffix ) \ -{ \ +#define OC_TEST_CASE( name, desc )\ ++(NSString*) INTERNAL_CATCH_UNIQUE_NAME( Catch_Name_test ) \ +{\ return @ name; \ -} \ -+(NSString*) OC_MAKE_UNIQUE_NAME( Catch_Description_test_, uniqueSuffix ) \ +}\ ++(NSString*) INTERNAL_CATCH_UNIQUE_NAME( Catch_Description_test ) \ { \ return @ desc; \ } \ --(void) OC_MAKE_UNIQUE_NAME( Catch_TestCase_test_, uniqueSuffix ) +-(void) INTERNAL_CATCH_UNIQUE_NAME( Catch_TestCase_test ) -#define OC_TEST_CASE( name, desc ) OC_TEST_CASE2( name, desc, __LINE__ ) - -// end catch_objc.hpp #endif -#ifdef CATCH_CONFIG_EXTERNAL_INTERFACES -// start catch_external_interfaces.h +#ifdef CATCH_IMPL -// start catch_reporter_bases.hpp +// !TBD: Move the leak detector code into a separate header +#ifdef CATCH_CONFIG_WINDOWS_CRTDBG +#include +class LeakDetector { +public: + LeakDetector() { + int flag = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG); + flag |= _CRTDBG_LEAK_CHECK_DF; + flag |= _CRTDBG_ALLOC_MEM_DF; + _CrtSetDbgFlag(flag); + _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG); + _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR); + // Change this to leaking allocation's number to break there + _CrtSetBreakAlloc(-1); + } +}; +#else +class LeakDetector {}; +#endif -// start catch_interfaces_reporter.h +LeakDetector leakDetector; -// start catch_config.hpp +// #included from: internal/catch_impl.hpp +#define TWOBLUECUBES_CATCH_IMPL_HPP_INCLUDED -// start catch_test_spec_parser.h +// Collect all the implementation files together here +// These are the equivalent of what would usually be cpp files + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wweak-vtables" +#endif + +// #included from: ../catch_session.hpp +#define TWOBLUECUBES_CATCH_RUNNER_HPP_INCLUDED + +// #included from: internal/catch_commandline.hpp +#define TWOBLUECUBES_CATCH_COMMANDLINE_HPP_INCLUDED + +// #included from: catch_config.hpp +#define TWOBLUECUBES_CATCH_CONFIG_HPP_INCLUDED + +// #included from: catch_test_spec_parser.hpp +#define TWOBLUECUBES_CATCH_TEST_SPEC_PARSER_HPP_INCLUDED #ifdef __clang__ #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wpadded" #endif -// start catch_test_spec.h +// #included from: catch_test_spec.hpp +#define TWOBLUECUBES_CATCH_TEST_SPEC_HPP_INCLUDED #ifdef __clang__ #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wpadded" #endif -// start catch_wildcard_pattern.h +// #included from: catch_wildcard_pattern.hpp +#define TWOBLUECUBES_CATCH_WILDCARD_PATTERN_HPP_INCLUDED + +#include namespace Catch { @@ -2696,68 +3579,119 @@ namespace Catch public: - WildcardPattern( std::string const& pattern, CaseSensitive::Choice caseSensitivity ); - virtual ~WildcardPattern() = default; - virtual bool matches( std::string const& str ) const; + WildcardPattern( std::string const& pattern, CaseSensitive::Choice caseSensitivity ) + : m_caseSensitivity( caseSensitivity ), + m_wildcard( NoWildcard ), + m_pattern( adjustCase( pattern ) ) + { + if( startsWith( m_pattern, '*' ) ) { + m_pattern = m_pattern.substr( 1 ); + m_wildcard = WildcardAtStart; + } + if( endsWith( m_pattern, '*' ) ) { + m_pattern = m_pattern.substr( 0, m_pattern.size()-1 ); + m_wildcard = static_cast( m_wildcard | WildcardAtEnd ); + } + } + virtual ~WildcardPattern(); + virtual bool matches( std::string const& str ) const { + switch( m_wildcard ) { + case NoWildcard: + return m_pattern == adjustCase( str ); + case WildcardAtStart: + return endsWith( adjustCase( str ), m_pattern ); + case WildcardAtEnd: + return startsWith( adjustCase( str ), m_pattern ); + case WildcardAtBothEnds: + return contains( adjustCase( str ), m_pattern ); + } +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunreachable-code" +#endif + throw std::logic_error( "Unknown enum" ); +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + } private: - std::string adjustCase( std::string const& str ) const; + std::string adjustCase( std::string const& str ) const { + return m_caseSensitivity == CaseSensitive::No ? toLower( str ) : str; + } CaseSensitive::Choice m_caseSensitivity; - WildcardPosition m_wildcard = NoWildcard; + WildcardPosition m_wildcard; std::string m_pattern; }; } -// end catch_wildcard_pattern.h #include #include -#include namespace Catch { class TestSpec { - struct Pattern { + struct Pattern : SharedImpl<> { virtual ~Pattern(); virtual bool matches( TestCaseInfo const& testCase ) const = 0; }; - using PatternPtr = std::shared_ptr; - class NamePattern : public Pattern { public: - NamePattern( std::string const& name ); + NamePattern( std::string const& name ) + : m_wildcardPattern( toLower( name ), CaseSensitive::No ) + {} virtual ~NamePattern(); - virtual bool matches( TestCaseInfo const& testCase ) const override; + virtual bool matches( TestCaseInfo const& testCase ) const { + return m_wildcardPattern.matches( toLower( testCase.name ) ); + } private: WildcardPattern m_wildcardPattern; }; class TagPattern : public Pattern { public: - TagPattern( std::string const& tag ); + TagPattern( std::string const& tag ) : m_tag( toLower( tag ) ) {} virtual ~TagPattern(); - virtual bool matches( TestCaseInfo const& testCase ) const override; + 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( PatternPtr const& underlyingPattern ); + ExcludedPattern( Ptr const& underlyingPattern ) : m_underlyingPattern( underlyingPattern ) {} virtual ~ExcludedPattern(); - virtual bool matches( TestCaseInfo const& testCase ) const override; + virtual bool matches( TestCaseInfo const& testCase ) const { return !m_underlyingPattern->matches( testCase ); } private: - PatternPtr m_underlyingPattern; + Ptr m_underlyingPattern; }; struct Filter { - std::vector m_patterns; + std::vector > m_patterns; - bool matches( TestCaseInfo const& testCase ) const; + 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; - bool matches( TestCaseInfo const& testCase ) const; + 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; @@ -2770,56 +3704,87 @@ namespace Catch { #pragma clang diagnostic pop #endif -// end catch_test_spec.h -// start catch_interfaces_tag_alias_registry.h - -#include - -namespace Catch { - - struct TagAlias; - - struct ITagAliasRegistry { - virtual ~ITagAliasRegistry(); - // Nullptr if not present - virtual TagAlias const* find( std::string const& alias ) const = 0; - virtual std::string expandAliases( std::string const& unexpandedTestSpec ) const = 0; - - static ITagAliasRegistry const& get(); - }; - -} // end namespace Catch - -// end catch_interfaces_tag_alias_registry.h namespace Catch { class TestSpecParser { enum Mode{ None, Name, QuotedName, Tag, EscapedName }; - Mode m_mode = None; - bool m_exclusion = false; - std::size_t m_start = std::string::npos, m_pos = 0; + Mode m_mode; + bool m_exclusion; + std::size_t m_start, m_pos; std::string m_arg; std::vector m_escapeChars; TestSpec::Filter m_currentFilter; TestSpec m_testSpec; - ITagAliasRegistry const* m_tagAliases = nullptr; + ITagAliasRegistry const* m_tagAliases; public: - TestSpecParser( ITagAliasRegistry const& tagAliases ); - - TestSpecParser& parse( std::string const& arg ); - TestSpec testSpec(); + TestSpecParser( ITagAliasRegistry const& tagAliases ) :m_mode(None), m_exclusion(false), m_start(0), m_pos(0), 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 ); + m_escapeChars.clear(); + 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 ); - void startNewMode( Mode mode, std::size_t start ); - void escape(); - std::string subString() const; - + 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 ); + case '\\': return escape(); + default: startNewMode( Name, m_pos ); break; + } + } + if( m_mode == Name ) { + if( c == ',' ) { + addPattern(); + addFilter(); + } + else if( c == '[' ) { + if( subString() == "exclude:" ) + m_exclusion = true; + else + addPattern(); + startNewMode( Tag, ++m_pos ); + } + else if( c == '\\' ) + escape(); + } + else if( m_mode == EscapedName ) + m_mode = Name; + 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; + } + void escape() { + if( m_mode == None ) + m_start = m_pos; + m_mode = EscapedName; + m_escapeChars.push_back( m_pos ); + } + std::string subString() const { return m_arg.substr( m_start, m_pos - m_start ); } template void addPattern() { std::string token = subString(); - for( std::size_t i = 0; i < m_escapeChars.size(); ++i ) + for( size_t i = 0; i < m_escapeChars.size(); ++i ) token = token.substr( 0, m_escapeChars[i]-m_start-i ) + token.substr( m_escapeChars[i]-m_start-i+1 ); m_escapeChars.clear(); if( startsWith( token, "exclude:" ) ) { @@ -2827,18 +3792,24 @@ namespace Catch { token = token.substr( 8 ); } if( !token.empty() ) { - TestSpec::PatternPtr pattern = std::make_shared( token ); + Ptr pattern = new T( token ); if( m_exclusion ) - pattern = std::make_shared( pattern ); + pattern = new TestSpec::ExcludedPattern( pattern ); m_currentFilter.m_patterns.push_back( pattern ); } m_exclusion = false; m_mode = None; } - - void addFilter(); + void addFilter() { + if( !m_currentFilter.m_patterns.empty() ) { + m_testSpec.m_filters.push_back( m_currentFilter ); + m_currentFilter = TestSpec::Filter(); + } + } }; - TestSpec parseTestSpec( std::string const& arg ); + inline TestSpec parseTestSpec( std::string const& arg ) { + return TestSpecParser( ITagAliasRegistry::get() ).parse( arg ).testSpec(); + } } // namespace Catch @@ -2846,21 +3817,20 @@ namespace Catch { #pragma clang diagnostic pop #endif -// end catch_test_spec_parser.h -// start catch_interfaces_config.h +// #included from: catch_interfaces_config.h +#define TWOBLUECUBES_CATCH_INTERFACES_CONFIG_H_INCLUDED #include #include #include -#include namespace Catch { - enum class Verbosity { - Quiet = 0, - Normal, - High - }; + struct Verbosity { enum Level { + NoOutput = 0, + Quiet, + Normal + }; }; struct WarnAbout { enum What { Nothing = 0x00, @@ -2882,16 +3852,10 @@ namespace Catch { Yes, No }; }; - struct WaitForKeypress { enum When { - Never, - BeforeStart = 1, - BeforeExit = 2, - BeforeStartAndExit = BeforeStart | BeforeExit - }; }; class TestSpec; - struct IConfig : NonCopyable { + struct IConfig : IShared { virtual ~IConfig(); @@ -2907,20 +3871,17 @@ namespace Catch { virtual TestSpec const& testSpec() const = 0; virtual RunTests::InWhatOrder runOrder() const = 0; virtual unsigned int rngSeed() const = 0; - virtual int benchmarkResolutionMultiple() const = 0; virtual UseColour::YesOrNo useColour() const = 0; virtual std::vector const& getSectionsToRun() const = 0; - virtual Verbosity verbosity() const = 0; - }; - using IConfigPtr = std::shared_ptr; + }; } -// end catch_interfaces_config.h -// Libstdc++ doesn't like incomplete classes for unique_ptr -// start catch_stream.h +// #included from: catch_stream.h +#define TWOBLUECUBES_CATCH_STREAM_H_INCLUDED -// start catch_streambuf.h +// #included from: catch_streambuf.h +#define TWOBLUECUBES_CATCH_STREAMBUF_H_INCLUDED #include @@ -2928,11 +3889,10 @@ namespace Catch { class StreamBufBase : public std::streambuf { public: - virtual ~StreamBufBase(); + virtual ~StreamBufBase() CATCH_NOEXCEPT; }; } -// end catch_streambuf.h #include #include #include @@ -2945,7 +3905,7 @@ namespace Catch { std::ostream& clog(); struct IStream { - virtual ~IStream(); + virtual ~IStream() CATCH_NOEXCEPT; virtual std::ostream& stream() const = 0; }; @@ -2953,38 +3913,37 @@ namespace Catch { mutable std::ofstream m_ofs; public: FileStream( std::string const& filename ); - ~FileStream() override = default; + virtual ~FileStream() CATCH_NOEXCEPT; public: // IStream - std::ostream& stream() const override; + virtual std::ostream& stream() const CATCH_OVERRIDE; }; class CoutStream : public IStream { mutable std::ostream m_os; public: CoutStream(); - ~CoutStream() override = default; + virtual ~CoutStream() CATCH_NOEXCEPT; public: // IStream - std::ostream& stream() const override; + virtual std::ostream& stream() const CATCH_OVERRIDE; }; class DebugOutStream : public IStream { - std::unique_ptr m_streamBuf; + CATCH_AUTO_PTR( StreamBufBase ) m_streamBuf; mutable std::ostream m_os; public: DebugOutStream(); - ~DebugOutStream() override = default; + virtual ~DebugOutStream() CATCH_NOEXCEPT; public: // IStream - std::ostream& stream() const override; + virtual std::ostream& stream() const CATCH_OVERRIDE; }; } -// end catch_stream.h - #include #include #include +#include #ifndef CATCH_CONFIG_CONSOLE_WIDTH #define CATCH_CONFIG_CONSOLE_WIDTH 80 @@ -2992,32 +3951,50 @@ namespace Catch { namespace Catch { - struct IStream; - struct ConfigData { - bool listTests = false; - bool listTags = false; - bool listReporters = false; - bool listTestNamesOnly = false; - bool showSuccessfulTests = false; - bool shouldDebugBreak = false; - bool noThrow = false; - bool showHelp = false; - bool showInvisibles = false; - bool filenamesAsTags = false; - bool libIdentify = false; + ConfigData() + : listTests( false ), + listTags( false ), + listReporters( false ), + listTestNamesOnly( false ), + listExtraInfo( false ), + showSuccessfulTests( false ), + shouldDebugBreak( false ), + noThrow( false ), + showHelp( false ), + showInvisibles( false ), + filenamesAsTags( false ), + abortAfter( -1 ), + rngSeed( 0 ), + verbosity( Verbosity::Normal ), + warnings( WarnAbout::Nothing ), + showDurations( ShowDurations::DefaultForReporter ), + runOrder( RunTests::InDeclarationOrder ), + useColour( UseColour::Auto ) + {} - int abortAfter = -1; - unsigned int rngSeed = 0; - int benchmarkResolutionMultiple = 100; + bool listTests; + bool listTags; + bool listReporters; + bool listTestNamesOnly; + bool listExtraInfo; - Verbosity verbosity = Verbosity::Normal; - WarnAbout::What warnings = WarnAbout::Nothing; - ShowDurations::OrNot showDurations = ShowDurations::DefaultForReporter; - RunTests::InWhatOrder runOrder = RunTests::InDeclarationOrder; - UseColour::YesOrNo useColour = UseColour::Auto; - WaitForKeypress::When waitForKeypress = WaitForKeypress::Never; + bool showSuccessfulTests; + bool shouldDebugBreak; + bool noThrow; + bool showHelp; + bool showInvisibles; + bool filenamesAsTags; + + int abortAfter; + unsigned int rngSeed; + + Verbosity::Level verbosity; + WarnAbout::What warnings; + ShowDurations::OrNot showDurations; + RunTests::InWhatOrder runOrder; + UseColour::YesOrNo useColour; std::string outputFilename; std::string name; @@ -3028,638 +4005,1505 @@ namespace Catch { std::vector sectionsToRun; }; - class Config : public IConfig { + class Config : public SharedImpl { + private: + Config( Config const& other ); + Config& operator = ( Config const& other ); + virtual void dummy(); public: - Config() = default; - Config( ConfigData const& data ); - virtual ~Config() = default; + Config() + {} - std::string const& getFilename() const; + Config( ConfigData const& data ) + : m_data( data ), + m_stream( openStream() ) + { + if( !data.testsOrTags.empty() ) { + TestSpecParser parser( ITagAliasRegistry::get() ); + for( std::size_t i = 0; i < data.testsOrTags.size(); ++i ) + parser.parse( data.testsOrTags[i] ); + m_testSpec = parser.testSpec(); + } + } - bool listTests() const; - bool listTestNamesOnly() const; - bool listTags() const; - bool listReporters() const; + virtual ~Config() {} - std::string getProcessName() const; + std::string const& getFilename() const { + return m_data.outputFilename ; + } - std::vector const& getReporterNames() const; - std::vector const& getSectionsToRun() const override; + 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 listExtraInfo() const { return m_data.listExtraInfo; } - virtual TestSpec const& testSpec() const override; + std::string getProcessName() const { return m_data.processName; } - bool showHelp() const; + std::vector const& getReporterNames() const { return m_data.reporterNames; } + std::vector const& getSectionsToRun() const CATCH_OVERRIDE { return m_data.sectionsToRun; } + + virtual TestSpec const& testSpec() const CATCH_OVERRIDE { return m_testSpec; } + + bool showHelp() const { return m_data.showHelp; } // IConfig interface - bool allowThrows() const override; - std::ostream& stream() const override; - std::string name() const override; - bool includeSuccessfulResults() const override; - bool warnAboutMissingAssertions() const override; - ShowDurations::OrNot showDurations() const override; - RunTests::InWhatOrder runOrder() const override; - unsigned int rngSeed() const override; - int benchmarkResolutionMultiple() const override; - UseColour::YesOrNo useColour() const override; - bool shouldDebugBreak() const override; - int abortAfter() const override; - bool showInvisibles() const override; - Verbosity verbosity() const override; + virtual bool allowThrows() const CATCH_OVERRIDE { return !m_data.noThrow; } + virtual std::ostream& stream() const CATCH_OVERRIDE { return m_stream->stream(); } + virtual std::string name() const CATCH_OVERRIDE { return m_data.name.empty() ? m_data.processName : m_data.name; } + virtual bool includeSuccessfulResults() const CATCH_OVERRIDE { return m_data.showSuccessfulTests; } + virtual bool warnAboutMissingAssertions() const CATCH_OVERRIDE { return m_data.warnings & WarnAbout::NoAssertions; } + virtual ShowDurations::OrNot showDurations() const CATCH_OVERRIDE { return m_data.showDurations; } + virtual RunTests::InWhatOrder runOrder() const CATCH_OVERRIDE { return m_data.runOrder; } + virtual unsigned int rngSeed() const CATCH_OVERRIDE { return m_data.rngSeed; } + virtual UseColour::YesOrNo useColour() const CATCH_OVERRIDE { return m_data.useColour; } + virtual bool shouldDebugBreak() const CATCH_OVERRIDE { return m_data.shouldDebugBreak; } + virtual int abortAfter() const CATCH_OVERRIDE { return m_data.abortAfter; } + virtual bool showInvisibles() const CATCH_OVERRIDE { return m_data.showInvisibles; } private: - IStream const* openStream(); + IStream const* openStream() { + if( m_data.outputFilename.empty() ) + return new CoutStream(); + else if( m_data.outputFilename[0] == '%' ) { + if( m_data.outputFilename == "%debug" ) + return new DebugOutStream(); + else + throw std::domain_error( "Unrecognised stream: " + m_data.outputFilename ); + } + else + return new FileStream( m_data.outputFilename ); + } ConfigData m_data; - std::unique_ptr m_stream; + CATCH_AUTO_PTR( IStream const ) m_stream; TestSpec m_testSpec; }; } // end namespace Catch -// end catch_config.hpp -// start catch_assertionresult.h +// #included from: catch_clara.h +#define TWOBLUECUBES_CATCH_CLARA_H_INCLUDED + +// Use Catch's value for console width (store Clara's off to the side, if present) +#ifdef CLARA_CONFIG_CONSOLE_WIDTH +#define CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH CLARA_CONFIG_CONSOLE_WIDTH +#undef CLARA_CONFIG_CONSOLE_WIDTH +#endif +#define CLARA_CONFIG_CONSOLE_WIDTH CATCH_CONFIG_CONSOLE_WIDTH + +// Declare Clara inside the Catch namespace +#define STITCH_CLARA_OPEN_NAMESPACE namespace Catch { +// #included from: ../external/clara.h + +// Version 0.0.2.4 + +// Only use header guard if we are not using an outer namespace +#if !defined(TWOBLUECUBES_CLARA_H_INCLUDED) || defined(STITCH_CLARA_OPEN_NAMESPACE) + +#ifndef STITCH_CLARA_OPEN_NAMESPACE +#define TWOBLUECUBES_CLARA_H_INCLUDED +#define STITCH_CLARA_OPEN_NAMESPACE +#define STITCH_CLARA_CLOSE_NAMESPACE +#else +#define STITCH_CLARA_CLOSE_NAMESPACE } +#endif + +#define STITCH_TBC_TEXT_FORMAT_OPEN_NAMESPACE STITCH_CLARA_OPEN_NAMESPACE + +// ----------- #included from tbc_text_format.h ----------- + +// Only use header guard if we are not using an outer namespace +#if !defined(TBC_TEXT_FORMAT_H_INCLUDED) || defined(STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE) +#ifndef STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE +#define TBC_TEXT_FORMAT_H_INCLUDED +#endif #include - -namespace Catch { - - struct AssertionResultData - { - AssertionResultData() = delete; - - AssertionResultData( ResultWas::OfType _resultType, LazyExpression const& _lazyExpression ); - - std::string message; - mutable std::string reconstructedExpression; - LazyExpression lazyExpression; - ResultWas::OfType resultType; - - std::string reconstructExpression() const; - }; - - class AssertionResult { - public: - AssertionResult() = delete; - AssertionResult( AssertionInfo const& info, AssertionResultData const& data ); - - bool isOk() const; - bool succeeded() const; - ResultWas::OfType getResultType() const; - bool hasExpression() const; - bool hasMessage() const; - std::string getExpression() const; - std::string getExpressionInMacro() const; - bool hasExpandedExpression() const; - std::string getExpandedExpression() const; - std::string getMessage() const; - SourceLineInfo getSourceInfo() const; - std::string getTestMacroName() const; - - //protected: - AssertionInfo m_info; - AssertionResultData m_resultData; - }; - -} // end namespace Catch - -// end catch_assertionresult.h -// start catch_option.hpp - -namespace Catch { - - // An optional type - template - class Option { - public: - Option() : nullableValue( nullptr ) {} - Option( T const& _value ) - : nullableValue( new( storage ) T( _value ) ) - {} - Option( Option const& _other ) - : nullableValue( _other ? new( storage ) T( *_other ) : nullptr ) - {} - - ~Option() { - reset(); - } - - Option& operator= ( Option const& _other ) { - if( &_other != this ) { - reset(); - if( _other ) - nullableValue = new( storage ) T( *_other ); - } - return *this; - } - Option& operator = ( T const& _value ) { - reset(); - nullableValue = new( storage ) T( _value ); - return *this; - } - - void reset() { - if( nullableValue ) - nullableValue->~T(); - nullableValue = nullptr; - } - - T& operator*() { return *nullableValue; } - T const& operator*() const { return *nullableValue; } - T* operator->() { return nullableValue; } - const T* operator->() const { return nullableValue; } - - T valueOr( T const& defaultValue ) const { - return nullableValue ? *nullableValue : defaultValue; - } - - bool some() const { return nullableValue != nullptr; } - bool none() const { return nullableValue == nullptr; } - - bool operator !() const { return nullableValue == nullptr; } - explicit operator bool() const { - return some(); - } - - private: - T *nullableValue; - alignas(alignof(T)) char storage[sizeof(T)]; - }; - -} // end namespace Catch - -// end catch_option.hpp -#include -#include -#include -#include -#include - -namespace Catch { - - struct ReporterConfig { - explicit ReporterConfig( IConfigPtr const& _fullConfig ); - - ReporterConfig( IConfigPtr const& _fullConfig, std::ostream& _stream ); - - std::ostream& stream() const; - IConfigPtr fullConfig() const; - - private: - std::ostream* m_stream; - IConfigPtr m_fullConfig; - }; - - struct ReporterPreferences { - bool shouldRedirectStdOut = false; - }; - - template - struct LazyStat : Option { - LazyStat& operator=( T const& _value ) { - Option::operator=( _value ); - used = false; - return *this; - } - void reset() { - Option::reset(); - used = false; - } - bool used = false; - }; - - struct TestRunInfo { - TestRunInfo( std::string const& _name ); - std::string name; - }; - struct GroupInfo { - GroupInfo( std::string const& _name, - std::size_t _groupIndex, - std::size_t _groupsCount ); - - std::string name; - std::size_t groupIndex; - std::size_t groupsCounts; - }; - - struct AssertionStats { - AssertionStats( AssertionResult const& _assertionResult, - std::vector const& _infoMessages, - Totals const& _totals ); - - AssertionStats( AssertionStats const& ) = default; - AssertionStats( AssertionStats && ) = default; - AssertionStats& operator = ( AssertionStats const& ) = default; - AssertionStats& operator = ( AssertionStats && ) = default; - virtual ~AssertionStats(); - - AssertionResult assertionResult; - std::vector infoMessages; - Totals totals; - }; - - struct SectionStats { - SectionStats( SectionInfo const& _sectionInfo, - Counts const& _assertions, - double _durationInSeconds, - bool _missingAssertions ); - SectionStats( SectionStats const& ) = default; - SectionStats( SectionStats && ) = default; - SectionStats& operator = ( SectionStats const& ) = default; - SectionStats& operator = ( SectionStats && ) = default; - virtual ~SectionStats(); - - 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 ); - - TestCaseStats( TestCaseStats const& ) = default; - TestCaseStats( TestCaseStats && ) = default; - TestCaseStats& operator = ( TestCaseStats const& ) = default; - TestCaseStats& operator = ( TestCaseStats && ) = default; - virtual ~TestCaseStats(); - - TestCaseInfo testInfo; - Totals totals; - std::string stdOut; - std::string stdErr; - bool aborting; - }; - - struct TestGroupStats { - TestGroupStats( GroupInfo const& _groupInfo, - Totals const& _totals, - bool _aborting ); - TestGroupStats( GroupInfo const& _groupInfo ); - - TestGroupStats( TestGroupStats const& ) = default; - TestGroupStats( TestGroupStats && ) = default; - TestGroupStats& operator = ( TestGroupStats const& ) = default; - TestGroupStats& operator = ( TestGroupStats && ) = default; - virtual ~TestGroupStats(); - - GroupInfo groupInfo; - Totals totals; - bool aborting; - }; - - struct TestRunStats { - TestRunStats( TestRunInfo const& _runInfo, - Totals const& _totals, - bool _aborting ); - - TestRunStats( TestRunStats const& ) = default; - TestRunStats( TestRunStats && ) = default; - TestRunStats& operator = ( TestRunStats const& ) = default; - TestRunStats& operator = ( TestRunStats && ) = default; - virtual ~TestRunStats(); - - TestRunInfo runInfo; - Totals totals; - bool aborting; - }; - - struct BenchmarkInfo { - std::string name; - }; - struct BenchmarkStats { - BenchmarkInfo info; - std::size_t iterations; - uint64_t elapsedTimeInNanoseconds; - }; - - struct IStreamingReporter { - virtual ~IStreamingReporter() = default; - - // Implementing class must also provide the following static methods: - // static std::string getDescription(); - // static std::set getSupportedVerbosities() - - virtual ReporterPreferences getPreferences() const = 0; - - virtual void noMatchingTestCases( std::string const& spec ) = 0; - - virtual void testRunStarting( TestRunInfo const& testRunInfo ) = 0; - virtual void testGroupStarting( GroupInfo const& groupInfo ) = 0; - - virtual void testCaseStarting( TestCaseInfo const& testInfo ) = 0; - virtual void sectionStarting( SectionInfo const& sectionInfo ) = 0; - - // *** experimental *** - virtual void benchmarkStarting( BenchmarkInfo const& ) {} - - virtual void assertionStarting( AssertionInfo const& assertionInfo ) = 0; - - // The return value indicates if the messages buffer should be cleared: - virtual bool assertionEnded( AssertionStats const& assertionStats ) = 0; - - // *** experimental *** - virtual void benchmarkEnded( BenchmarkStats const& ) {} - - virtual void sectionEnded( SectionStats const& sectionStats ) = 0; - virtual void testCaseEnded( TestCaseStats const& testCaseStats ) = 0; - virtual void testGroupEnded( TestGroupStats const& testGroupStats ) = 0; - virtual void testRunEnded( TestRunStats const& testRunStats ) = 0; - - virtual void skipTest( TestCaseInfo const& testInfo ) = 0; - - // Default empty implementation provided - virtual void fatalErrorEncountered( StringRef name ); - - virtual bool isMulti() const; - }; - using IStreamingReporterPtr = std::unique_ptr; - - struct IReporterFactory { - virtual ~IReporterFactory(); - virtual IStreamingReporterPtr create( ReporterConfig const& config ) const = 0; - virtual std::string getDescription() const = 0; - }; - using IReporterFactoryPtr = std::shared_ptr; - - struct IReporterRegistry { - using FactoryMap = std::map; - using Listeners = std::vector; - - virtual ~IReporterRegistry(); - virtual IStreamingReporterPtr create( std::string const& name, IConfigPtr const& config ) const = 0; - virtual FactoryMap const& getFactories() const = 0; - virtual Listeners const& getListeners() const = 0; - }; - - void addReporter( IStreamingReporterPtr& existingReporter, IStreamingReporterPtr&& additionalReporter ); - -} // end namespace Catch - -// end catch_interfaces_reporter.h +#include +#include #include -#include -#include -#include -#include +#include + +// Use optional outer namespace +#ifdef STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE +namespace STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE { +#endif + +namespace Tbc { + +#ifdef TBC_TEXT_FORMAT_CONSOLE_WIDTH + const unsigned int consoleWidth = TBC_TEXT_FORMAT_CONSOLE_WIDTH; +#else + const unsigned int consoleWidth = 80; +#endif + + struct TextAttributes { + TextAttributes() + : initialIndent( std::string::npos ), + indent( 0 ), + width( consoleWidth-1 ), + tabChar( '\t' ) + {} + + TextAttributes& setInitialIndent( std::size_t _value ) { initialIndent = _value; return *this; } + TextAttributes& setIndent( std::size_t _value ) { indent = _value; return *this; } + TextAttributes& setWidth( std::size_t _value ) { width = _value; return *this; } + TextAttributes& setTabChar( char _value ) { tabChar = _value; return *this; } + + std::size_t initialIndent; // indent of first line, or npos + std::size_t indent; // indent of subsequent lines, or all if initialIndent is npos + std::size_t width; // maximum width of text, including indent. Longer text will wrap + char tabChar; // If this char is seen the indent is changed to current pos + }; + + class Text { + public: + Text( std::string const& _str, TextAttributes const& _attr = TextAttributes() ) + : attr( _attr ) + { + std::string wrappableChars = " [({.,/|\\-"; + std::size_t indent = _attr.initialIndent != std::string::npos + ? _attr.initialIndent + : _attr.indent; + std::string remainder = _str; + + while( !remainder.empty() ) { + if( lines.size() >= 1000 ) { + lines.push_back( "... message truncated due to excessive size" ); + return; + } + std::size_t tabPos = std::string::npos; + std::size_t width = (std::min)( remainder.size(), _attr.width - indent ); + std::size_t pos = remainder.find_first_of( '\n' ); + if( pos <= width ) { + width = pos; + } + pos = remainder.find_last_of( _attr.tabChar, width ); + if( pos != std::string::npos ) { + tabPos = pos; + if( remainder[width] == '\n' ) + width--; + remainder = remainder.substr( 0, tabPos ) + remainder.substr( tabPos+1 ); + } + + if( width == remainder.size() ) { + spliceLine( indent, remainder, width ); + } + else if( remainder[width] == '\n' ) { + spliceLine( indent, remainder, width ); + if( width <= 1 || remainder.size() != 1 ) + remainder = remainder.substr( 1 ); + indent = _attr.indent; + } + else { + pos = remainder.find_last_of( wrappableChars, width ); + if( pos != std::string::npos && pos > 0 ) { + spliceLine( indent, remainder, pos ); + if( remainder[0] == ' ' ) + remainder = remainder.substr( 1 ); + } + else { + spliceLine( indent, remainder, width-1 ); + lines.back() += "-"; + } + if( lines.size() == 1 ) + indent = _attr.indent; + if( tabPos != std::string::npos ) + indent += tabPos; + } + } + } + + void spliceLine( std::size_t _indent, std::string& _remainder, std::size_t _pos ) { + lines.push_back( std::string( _indent, ' ' ) + _remainder.substr( 0, _pos ) ); + _remainder = _remainder.substr( _pos ); + } + + typedef std::vector::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(); + } + + 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 + +#ifdef STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE +} // end outer namespace +#endif + +#endif // TBC_TEXT_FORMAT_H_INCLUDED + +// ----------- end of #include from tbc_text_format.h ----------- +// ........... back in clara.h + +#undef STITCH_TBC_TEXT_FORMAT_OPEN_NAMESPACE + +// ----------- #included from clara_compilers.h ----------- + +#ifndef TWOBLUECUBES_CLARA_COMPILERS_H_INCLUDED +#define TWOBLUECUBES_CLARA_COMPILERS_H_INCLUDED + +// Detect a number of compiler features - mostly C++11/14 conformance - by compiler +// The following features are defined: +// +// CLARA_CONFIG_CPP11_NULLPTR : is nullptr supported? +// CLARA_CONFIG_CPP11_NOEXCEPT : is noexcept supported? +// CLARA_CONFIG_CPP11_GENERATED_METHODS : The delete and default keywords for compiler generated methods +// CLARA_CONFIG_CPP11_OVERRIDE : is override supported? +// CLARA_CONFIG_CPP11_UNIQUE_PTR : is unique_ptr supported (otherwise use auto_ptr) + +// CLARA_CONFIG_CPP11_OR_GREATER : Is C++11 supported? + +// CLARA_CONFIG_VARIADIC_MACROS : are variadic macros supported? + +// In general each macro has a _NO_ form +// (e.g. CLARA_CONFIG_CPP11_NO_NULLPTR) which disables the feature. +// Many features, at point of detection, define an _INTERNAL_ macro, so they +// can be combined, en-mass, with the _NO_ forms later. + +// All the C++11 features can be disabled with CLARA_CONFIG_NO_CPP11 + +#ifdef __clang__ + +#if __has_feature(cxx_nullptr) +#define CLARA_INTERNAL_CONFIG_CPP11_NULLPTR +#endif + +#if __has_feature(cxx_noexcept) +#define CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT +#endif + +#endif // __clang__ + +//////////////////////////////////////////////////////////////////////////////// +// GCC +#ifdef __GNUC__ + +#if __GNUC__ == 4 && __GNUC_MINOR__ >= 6 && defined(__GXX_EXPERIMENTAL_CXX0X__) +#define CLARA_INTERNAL_CONFIG_CPP11_NULLPTR +#endif + +// - otherwise more recent versions define __cplusplus >= 201103L +// and will get picked up below + +#endif // __GNUC__ + +//////////////////////////////////////////////////////////////////////////////// +// Visual C++ +#ifdef _MSC_VER + +#if (_MSC_VER >= 1600) +#define CLARA_INTERNAL_CONFIG_CPP11_NULLPTR +#define CLARA_INTERNAL_CONFIG_CPP11_UNIQUE_PTR +#endif + +#if (_MSC_VER >= 1900 ) // (VC++ 13 (VS2015)) +#define CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT +#define CLARA_INTERNAL_CONFIG_CPP11_GENERATED_METHODS +#endif + +#endif // _MSC_VER + +//////////////////////////////////////////////////////////////////////////////// +// C++ language feature support + +// catch all support for C++11 +#if defined(__cplusplus) && __cplusplus >= 201103L + +#define CLARA_CPP11_OR_GREATER + +#if !defined(CLARA_INTERNAL_CONFIG_CPP11_NULLPTR) +#define CLARA_INTERNAL_CONFIG_CPP11_NULLPTR +#endif + +#ifndef CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT +#define CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT +#endif + +#ifndef CLARA_INTERNAL_CONFIG_CPP11_GENERATED_METHODS +#define CLARA_INTERNAL_CONFIG_CPP11_GENERATED_METHODS +#endif + +#if !defined(CLARA_INTERNAL_CONFIG_CPP11_OVERRIDE) +#define CLARA_INTERNAL_CONFIG_CPP11_OVERRIDE +#endif +#if !defined(CLARA_INTERNAL_CONFIG_CPP11_UNIQUE_PTR) +#define CLARA_INTERNAL_CONFIG_CPP11_UNIQUE_PTR +#endif + +#endif // __cplusplus >= 201103L + +// Now set the actual defines based on the above + anything the user has configured +#if defined(CLARA_INTERNAL_CONFIG_CPP11_NULLPTR) && !defined(CLARA_CONFIG_CPP11_NO_NULLPTR) && !defined(CLARA_CONFIG_CPP11_NULLPTR) && !defined(CLARA_CONFIG_NO_CPP11) +#define CLARA_CONFIG_CPP11_NULLPTR +#endif +#if defined(CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT) && !defined(CLARA_CONFIG_CPP11_NO_NOEXCEPT) && !defined(CLARA_CONFIG_CPP11_NOEXCEPT) && !defined(CLARA_CONFIG_NO_CPP11) +#define CLARA_CONFIG_CPP11_NOEXCEPT +#endif +#if defined(CLARA_INTERNAL_CONFIG_CPP11_GENERATED_METHODS) && !defined(CLARA_CONFIG_CPP11_NO_GENERATED_METHODS) && !defined(CLARA_CONFIG_CPP11_GENERATED_METHODS) && !defined(CLARA_CONFIG_NO_CPP11) +#define CLARA_CONFIG_CPP11_GENERATED_METHODS +#endif +#if defined(CLARA_INTERNAL_CONFIG_CPP11_OVERRIDE) && !defined(CLARA_CONFIG_NO_OVERRIDE) && !defined(CLARA_CONFIG_CPP11_OVERRIDE) && !defined(CLARA_CONFIG_NO_CPP11) +#define CLARA_CONFIG_CPP11_OVERRIDE +#endif +#if defined(CLARA_INTERNAL_CONFIG_CPP11_UNIQUE_PTR) && !defined(CLARA_CONFIG_NO_UNIQUE_PTR) && !defined(CLARA_CONFIG_CPP11_UNIQUE_PTR) && !defined(CLARA_CONFIG_NO_CPP11) +#define CLARA_CONFIG_CPP11_UNIQUE_PTR +#endif + +// noexcept support: +#if defined(CLARA_CONFIG_CPP11_NOEXCEPT) && !defined(CLARA_NOEXCEPT) +#define CLARA_NOEXCEPT noexcept +# define CLARA_NOEXCEPT_IS(x) noexcept(x) +#else +#define CLARA_NOEXCEPT throw() +# define CLARA_NOEXCEPT_IS(x) +#endif + +// nullptr support +#ifdef CLARA_CONFIG_CPP11_NULLPTR +#define CLARA_NULL nullptr +#else +#define CLARA_NULL NULL +#endif + +// override support +#ifdef CLARA_CONFIG_CPP11_OVERRIDE +#define CLARA_OVERRIDE override +#else +#define CLARA_OVERRIDE +#endif + +// unique_ptr support +#ifdef CLARA_CONFIG_CPP11_UNIQUE_PTR +# define CLARA_AUTO_PTR( T ) std::unique_ptr +#else +# define CLARA_AUTO_PTR( T ) std::auto_ptr +#endif + +#endif // TWOBLUECUBES_CLARA_COMPILERS_H_INCLUDED + +// ----------- end of #include from clara_compilers.h ----------- +// ........... back in clara.h + +#include +#include #include -namespace Catch { - void prepareExpandedExpression(AssertionResult& result); +#if defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) +#define CLARA_PLATFORM_WINDOWS +#endif - // Returns double formatted as %.3f (format expected on output) - std::string getFormattedDuration( double duration ); +// Use optional outer namespace +#ifdef STITCH_CLARA_OPEN_NAMESPACE +STITCH_CLARA_OPEN_NAMESPACE +#endif - template - struct StreamingReporterBase : IStreamingReporter { +namespace Clara { - StreamingReporterBase( ReporterConfig const& _config ) - : m_config( _config.fullConfig() ), - stream( _config.stream() ) - { - m_reporterPrefs.shouldRedirectStdOut = false; - CATCH_ENFORCE( DerivedT::getSupportedVerbosities().count( m_config->verbosity() ), "Verbosity level not supported by this reporter" ); + struct UnpositionalTag {}; + + extern UnpositionalTag _; + +#ifdef CLARA_CONFIG_MAIN + UnpositionalTag _; +#endif + + namespace Detail { + +#ifdef CLARA_CONSOLE_WIDTH + const unsigned int consoleWidth = CLARA_CONFIG_CONSOLE_WIDTH; +#else + const unsigned int consoleWidth = 80; +#endif + + 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; } - ReporterPreferences getPreferences() const override { - return m_reporterPrefs; + 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 + 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; + } + char toLowerCh(char c) { + return static_cast( std::tolower( c ) ); + } + inline void convertInto( std::string const& _source, bool& _dest ) { + std::string sourceLC = _source; + std::transform( sourceLC.begin(), sourceLC.end(), sourceLC.begin(), toLowerCh ); + 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 + "'" ); } - static std::set getSupportedVerbosities() { - return { Verbosity::Normal }; - } - - ~StreamingReporterBase() override = default; - - void noMatchingTestCases(std::string const&) override {} - - void testRunStarting(TestRunInfo const& _testRunInfo) override { - currentTestRunInfo = _testRunInfo; - } - void testGroupStarting(GroupInfo const& _groupInfo) override { - currentGroupInfo = _groupInfo; - } - - void testCaseStarting(TestCaseInfo const& _testInfo) override { - currentTestCaseInfo = _testInfo; - } - void sectionStarting(SectionInfo const& _sectionInfo) override { - m_sectionStack.push_back(_sectionInfo); - } - - void sectionEnded(SectionStats const& /* _sectionStats */) override { - m_sectionStack.pop_back(); - } - void testCaseEnded(TestCaseStats const& /* _testCaseStats */) override { - currentTestCaseInfo.reset(); - } - void testGroupEnded(TestGroupStats const& /* _testGroupStats */) override { - currentGroupInfo.reset(); - } - void testRunEnded(TestRunStats const& /* _testRunStats */) override { - currentTestCaseInfo.reset(); - currentGroupInfo.reset(); - currentTestRunInfo.reset(); - } - - void skipTest(TestCaseInfo const&) override { - // Don't do anything with this by default. - // It can optionally be overridden in the derived class. - } - - IConfigPtr m_config; - std::ostream& stream; - - LazyStat currentTestRunInfo; - LazyStat currentGroupInfo; - LazyStat currentTestCaseInfo; - - std::vector m_sectionStack; - ReporterPreferences m_reporterPrefs; - }; - - template - struct CumulativeReporterBase : IStreamingReporter { - template - struct Node { - explicit Node( T const& _value ) : value( _value ) {} - virtual ~Node() {} - - using ChildNodes = std::vector>; - T value; - ChildNodes children; - }; - struct SectionNode { - explicit SectionNode(SectionStats const& _stats) : stats(_stats) {} - virtual ~SectionNode() = default; - - bool operator == (SectionNode const& other) const { - return stats.sectionInfo.lineInfo == other.stats.sectionInfo.lineInfo; - } - bool operator == (std::shared_ptr const& other) const { - return operator==(*other); - } - - SectionStats stats; - using ChildSections = std::vector>; - using Assertions = std::vector; - ChildSections childSections; - Assertions assertions; - std::string stdOut; - std::string stdErr; + template + struct IArgFunction { + virtual ~IArgFunction() {} +#ifdef CLARA_CONFIG_CPP11_GENERATED_METHODS + IArgFunction() = default; + IArgFunction( IArgFunction const& ) = default; +#endif + virtual void set( ConfigT& config, std::string const& value ) const = 0; + virtual bool takesArg() const = 0; + virtual IArgFunction* clone() const = 0; }; - struct BySectionInfo { - BySectionInfo( SectionInfo const& other ) : m_other( other ) {} - BySectionInfo( BySectionInfo const& other ) : m_other( other.m_other ) {} - bool operator() (std::shared_ptr const& node) const { - return ((node->stats.sectionInfo.name == m_other.name) && - (node->stats.sectionInfo.lineInfo == m_other.lineInfo)); + template + class BoundArgFunction { + public: + BoundArgFunction() : functionObj( CLARA_NULL ) {} + BoundArgFunction( IArgFunction* _functionObj ) : functionObj( _functionObj ) {} + BoundArgFunction( BoundArgFunction const& other ) : functionObj( other.functionObj ? other.functionObj->clone() : CLARA_NULL ) {} + BoundArgFunction& operator = ( BoundArgFunction const& other ) { + IArgFunction* newFunctionObj = other.functionObj ? other.functionObj->clone() : CLARA_NULL; + delete functionObj; + functionObj = newFunctionObj; + return *this; } - void operator=(BySectionInfo const&) = delete; + ~BoundArgFunction() { delete functionObj; } + void set( ConfigT& config, std::string const& value ) const { + functionObj->set( config, value ); + } + bool takesArg() const { return functionObj->takesArg(); } + + bool isSet() const { + return functionObj != CLARA_NULL; + } private: - SectionInfo const& m_other; + IArgFunction* functionObj; }; - using TestCaseNode = Node; - using TestGroupNode = Node; - using TestRunNode = Node; + template + struct NullBinder : IArgFunction{ + virtual void set( C&, std::string const& ) const {} + virtual bool takesArg() const { return true; } + virtual IArgFunction* clone() const { return new NullBinder( *this ); } + }; - CumulativeReporterBase( ReporterConfig const& _config ) - : m_config( _config.fullConfig() ), - stream( _config.stream() ) - { - m_reporterPrefs.shouldRedirectStdOut = false; - CATCH_ENFORCE( DerivedT::getSupportedVerbosities().count( m_config->verbosity() ), "Verbosity level not supported by this reporter" ); - } - ~CumulativeReporterBase() override = default; - - ReporterPreferences getPreferences() const override { - return m_reporterPrefs; - } - - static std::set getSupportedVerbosities() { - return { Verbosity::Normal }; - } - - void testRunStarting( TestRunInfo const& ) override {} - void testGroupStarting( GroupInfo const& ) override {} - - void testCaseStarting( TestCaseInfo const& ) override {} - - void sectionStarting( SectionInfo const& sectionInfo ) override { - SectionStats incompleteStats( sectionInfo, Counts(), 0, false ); - std::shared_ptr node; - if( m_sectionStack.empty() ) { - if( !m_rootSection ) - m_rootSection = std::make_shared( incompleteStats ); - node = m_rootSection; + template + struct BoundDataMember : IArgFunction{ + BoundDataMember( M C::* _member ) : member( _member ) {} + virtual void set( C& p, std::string const& stringValue ) const { + convertInto( stringValue, p.*member ); } - else { - SectionNode& parentNode = *m_sectionStack.back(); - auto it = - std::find_if( parentNode.childSections.begin(), - parentNode.childSections.end(), - BySectionInfo( sectionInfo ) ); - if( it == parentNode.childSections.end() ) { - node = std::make_shared( incompleteStats ); - parentNode.childSections.push_back( node ); - } - else - node = *it; + 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 ); } - m_sectionStack.push_back( node ); - m_deepestSection = std::move(node); - } + 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 bool takesArg() const { return false; } + virtual IArgFunction* clone() const { return new BoundNullaryMethod( *this ); } + void (C::*member)(); + }; - void assertionStarting(AssertionInfo const&) override {} + 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 bool takesArg() const { return false; } + virtual IArgFunction* clone() const { return new BoundUnaryFunction( *this ); } + void (*function)( C& ); + }; - bool assertionEnded(AssertionStats const& assertionStats) override { - assert(!m_sectionStack.empty()); - // AssertionResult holds a pointer to a temporary DecomposedExpression, - // which getExpandedExpression() calls to build the expression string. - // Our section stack copy of the assertionResult will likely outlive the - // temporary, so it must be expanded or discarded now to avoid calling - // a destroyed object later. - prepareExpandedExpression(const_cast( assertionStats.assertionResult ) ); - SectionNode& sectionNode = *m_sectionStack.back(); - sectionNode.assertions.push_back(assertionStats); - return true; - } - void sectionEnded(SectionStats const& sectionStats) override { - assert(!m_sectionStack.empty()); - SectionNode& node = *m_sectionStack.back(); - node.stats = sectionStats; - m_sectionStack.pop_back(); - } - void testCaseEnded(TestCaseStats const& testCaseStats) override { - auto node = std::make_shared(testCaseStats); - assert(m_sectionStack.size() == 0); - node->children.push_back(m_rootSection); - m_testCases.push_back(node); - m_rootSection.reset(); + 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 bool takesArg() const { return !IsBool::value; } + virtual IArgFunction* clone() const { return new BoundBinaryFunction( *this ); } + void (*function)( C&, T ); + }; - assert(m_deepestSection); - m_deepestSection->stdOut = testCaseStats.stdOut; - m_deepestSection->stdErr = testCaseStats.stdErr; - } - void testGroupEnded(TestGroupStats const& testGroupStats) override { - auto node = std::make_shared(testGroupStats); - node->children.swap(m_testCases); - m_testGroups.push_back(node); - } - void testRunEnded(TestRunStats const& testRunStats) override { - auto node = std::make_shared(testRunStats); - node->children.swap(m_testGroups); - m_testRuns.push_back(node); - testRunEndedCumulative(); - } - virtual void testRunEndedCumulative() = 0; + } // namespace Detail - void skipTest(TestCaseInfo const&) override {} + inline std::vector argsToVector( int argc, char const* const* const argv ) { + std::vector args( static_cast( argc ) ); + for( std::size_t i = 0; i < static_cast( argc ); ++i ) + args[i] = argv[i]; - IConfigPtr m_config; - std::ostream& stream; - std::vector m_assertions; - std::vector>> m_sections; - std::vector> m_testCases; - std::vector> m_testGroups; - - std::vector> m_testRuns; - - std::shared_ptr m_rootSection; - std::shared_ptr m_deepestSection; - std::vector> m_sectionStack; - ReporterPreferences m_reporterPrefs; - }; - - template - char const* getLineOfChars() { - static char line[CATCH_CONFIG_CONSOLE_WIDTH] = {0}; - if( !*line ) { - std::memset( line, C, CATCH_CONFIG_CONSOLE_WIDTH-1 ); - line[CATCH_CONFIG_CONSOLE_WIDTH-1] = 0; - } - return line; + return args; } - struct TestEventListenerBase : StreamingReporterBase { - TestEventListenerBase( ReporterConfig const& _config ); + class Parser { + enum Mode { None, MaybeShortOpt, SlashOpt, ShortOpt, LongOpt, Positional }; + Mode mode; + std::size_t from; + bool inQuotes; + public: - void assertionStarting(AssertionInfo const&) override; - bool assertionEnded(AssertionStats const&) override; + struct Token { + enum Type { Positional, ShortOpt, LongOpt }; + Token( Type _type, std::string const& _data ) : type( _type ), data( _data ) {} + Type type; + std::string data; + }; + + Parser() : mode( None ), from( 0 ), inQuotes( false ){} + + void parseIntoTokens( std::vector const& args, std::vector& tokens ) { + const std::string doubleDash = "--"; + for( std::size_t i = 1; i < args.size() && args[i] != doubleDash; ++i ) + parseIntoTokens( args[i], tokens); + } + + void parseIntoTokens( std::string const& arg, std::vector& tokens ) { + for( std::size_t i = 0; i < arg.size(); ++i ) { + char c = arg[i]; + if( c == '"' ) + inQuotes = !inQuotes; + mode = handleMode( i, c, arg, tokens ); + } + mode = handleMode( arg.size(), '\0', arg, tokens ); + } + Mode handleMode( std::size_t i, char c, std::string const& arg, std::vector& tokens ) { + switch( mode ) { + case None: return handleNone( i, c ); + case MaybeShortOpt: return handleMaybeShortOpt( i, c ); + case ShortOpt: + case LongOpt: + case SlashOpt: return handleOpt( i, c, arg, tokens ); + case Positional: return handlePositional( i, c, arg, tokens ); + default: throw std::logic_error( "Unknown mode" ); + } + } + + Mode handleNone( std::size_t i, char c ) { + if( inQuotes ) { + from = i; + return Positional; + } + switch( c ) { + case '-': return MaybeShortOpt; +#ifdef CLARA_PLATFORM_WINDOWS + case '/': from = i+1; return SlashOpt; +#endif + default: from = i; return Positional; + } + } + Mode handleMaybeShortOpt( std::size_t i, char c ) { + switch( c ) { + case '-': from = i+1; return LongOpt; + default: from = i; return ShortOpt; + } + } + + Mode handleOpt( std::size_t i, char c, std::string const& arg, std::vector& tokens ) { + if( std::string( ":=\0", 3 ).find( c ) == std::string::npos ) + return mode; + + std::string optName = arg.substr( from, i-from ); + if( mode == ShortOpt ) + for( std::size_t j = 0; j < optName.size(); ++j ) + tokens.push_back( Token( Token::ShortOpt, optName.substr( j, 1 ) ) ); + else if( mode == SlashOpt && optName.size() == 1 ) + tokens.push_back( Token( Token::ShortOpt, optName ) ); + else + tokens.push_back( Token( Token::LongOpt, optName ) ); + return None; + } + Mode handlePositional( std::size_t i, char c, std::string const& arg, std::vector& tokens ) { + if( inQuotes || std::string( "\0", 1 ).find( c ) == std::string::npos ) + return mode; + + std::string data = arg.substr( from, i-from ); + tokens.push_back( Token( Token::Positional, data ) ); + return None; + } }; + 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 + + bool takesArg() const { + return !placeholder.empty(); + } + void validate() const { + if( !boundField.isSet() ) + throw std::logic_error( "option not bound" ); + } + }; + 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"; + } + 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(); + } + }; + + typedef CLARA_AUTO_PTR( Arg ) ArgAutoPtr; + + friend void addOptName( Arg& arg, std::string const& optName ) + { + if( optName.empty() ) + return; + if( Detail::startsWith( optName, "--" ) ) { + if( !arg.longName.empty() ) + throw std::logic_error( "Only one long opt may be specified. '" + + arg.longName + + "' already specified, now attempting to add '" + + optName + "'" ); + arg.longName = optName.substr( 2 ); + } + else if( Detail::startsWith( optName, "-" ) ) + arg.shortNames.push_back( optName.substr( 1 ) ); + else + throw std::logic_error( "option must begin with - or --. Option was: '" + optName + "'" ); + } + friend void setPositionalArg( Arg& arg, int position ) + { + arg.position = position; + } + + class ArgBuilder { + public: + ArgBuilder( Arg* arg ) : m_arg( arg ) {} + + // Bind a non-boolean data member (requires placeholder string) + template + 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 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 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 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 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 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; + } + + ArgBuilder& describe( std::string const& description ) { + m_arg->description = description; + return *this; + } + ArgBuilder& detail( std::string const& detail ) { + m_arg->detail = detail; + return *this; + } + + protected: + Arg* m_arg; + }; + + class OptBuilder : public ArgBuilder { + public: + OptBuilder( Arg* arg ) : ArgBuilder( arg ) {} + OptBuilder( OptBuilder& other ) : ArgBuilder( other ) {} + + OptBuilder& operator[]( std::string const& optName ) { + addOptName( *ArgBuilder::m_arg, optName ); + return *this; + } + }; + + public: + + CommandLine() + : m_boundProcessName( new Detail::NullBinder() ), + m_highestSpecifiedArgPosition( 0 ), + m_throwOnUnrecognisedTokens( false ) + {} + CommandLine( CommandLine const& other ) + : m_boundProcessName( other.m_boundProcessName ), + m_options ( other.m_options ), + m_positionalArgs( other.m_positionalArgs ), + m_highestSpecifiedArgPosition( other.m_highestSpecifiedArgPosition ), + m_throwOnUnrecognisedTokens( other.m_throwOnUnrecognisedTokens ) + { + if( other.m_floatingArg.get() ) + m_floatingArg.reset( new Arg( *other.m_floatingArg ) ); + } + + CommandLine& setThrowOnUnrecognisedTokens( bool shouldThrow = true ) { + m_throwOnUnrecognisedTokens = shouldThrow; + return *this; + } + + OptBuilder operator[]( std::string const& optName ) { + m_options.push_back( Arg() ); + addOptName( m_options.back(), optName ); + OptBuilder builder( &m_options.back() ); + return builder; + } + + ArgBuilder operator[]( int position ) { + m_positionalArgs.insert( std::make_pair( position, Arg() ) ); + if( position > m_highestSpecifiedArgPosition ) + m_highestSpecifiedArgPosition = position; + setPositionalArg( m_positionalArgs[position], position ); + ArgBuilder builder( &m_positionalArgs[position] ); + return builder; + } + + // Invoke this with the _ instance + ArgBuilder operator[]( UnpositionalTag ) { + if( m_floatingArg.get() ) + throw std::logic_error( "Only one unpositional argument can be added" ); + m_floatingArg.reset( new Arg() ); + ArgBuilder builder( m_floatingArg.get() ); + return builder; + } + + template + 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(); + } + + 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" ); + } + // !TBD No indication of mandatory args + if( m_floatingArg.get() ) { + if( m_highestSpecifiedArgPosition > 1 ) + os << " "; + os << "[<" << m_floatingArg->placeholder << "> ...]"; + } + } + std::string argSynopsis() const { + std::ostringstream oss; + argSynopsis( oss ); + return oss.str(); + } + + void usage( std::ostream& os, std::string const& procName ) const { + validate(); + os << "usage:\n " << procName << " "; + argSynopsis( os ); + if( !m_options.empty() ) { + os << " [options]\n\nwhere options are: \n"; + optUsage( os, 2 ); + } + os << "\n"; + } + std::string usage( std::string const& procName ) const { + std::ostringstream oss; + usage( oss, procName ); + return oss.str(); + } + + ConfigT parse( std::vector const& args ) const { + ConfigT config; + parseInto( args, config ); + return config; + } + + std::vector parseInto( std::vector const& args, ConfigT& config ) const { + std::string processName = args.empty() ? std::string() : args[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( args, 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 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, "true" ); + } + break; + } + } + catch( std::exception& ex ) { + errors.push_back( std::string( ex.what() ) + "\n- while parsing: (" + arg.commands() + ")" ); + } + } + if( it == itEnd ) { + if( token.type == Parser::Token::Positional || !m_throwOnUnrecognisedTokens ) + unusedTokens.push_back( token ); + else if( errors.empty() && m_throwOnUnrecognisedTokens ) + errors.push_back( "unrecognised option: " + token.data ); + } + } + if( !errors.empty() ) { + std::ostringstream oss; + for( std::vector::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 ); + 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" ); + + 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 + +STITCH_CLARA_CLOSE_NAMESPACE +#undef STITCH_CLARA_OPEN_NAMESPACE +#undef STITCH_CLARA_CLOSE_NAMESPACE + +#endif // TWOBLUECUBES_CLARA_H_INCLUDED +#undef STITCH_CLARA_OPEN_NAMESPACE + +// Restore Clara's value for console width, if present +#ifdef CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH +#define CLARA_CONFIG_CONSOLE_WIDTH CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH +#undef CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH +#endif + +#include +#include + +namespace Catch { + + inline void abortAfterFirst( ConfigData& config ) { config.abortAfter = 1; } + inline void abortAfterX( ConfigData& config, int x ) { + if( x < 1 ) + throw std::runtime_error( "Value after -x or --abortAfter must be greater than zero" ); + config.abortAfter = x; + } + inline void addTestOrTags( ConfigData& config, std::string const& _testSpec ) { config.testsOrTags.push_back( _testSpec ); } + inline void addSectionToRun( ConfigData& config, std::string const& sectionName ) { config.sectionsToRun.push_back( sectionName ); } + inline void addReporterName( ConfigData& config, std::string const& _reporterName ) { config.reporterNames.push_back( _reporterName ); } + + inline void addWarning( ConfigData& config, std::string const& _warning ) { + if( _warning == "NoAssertions" ) + config.warnings = static_cast( config.warnings | WarnAbout::NoAssertions ); + else + throw std::runtime_error( "Unrecognised warning: '" + _warning + '\'' ); + } + inline void setOrder( ConfigData& config, std::string const& order ) { + if( startsWith( "declared", order ) ) + config.runOrder = RunTests::InDeclarationOrder; + else if( startsWith( "lexical", order ) ) + config.runOrder = RunTests::InLexicographicalOrder; + else if( startsWith( "random", order ) ) + config.runOrder = RunTests::InRandomOrder; + else + throw std::runtime_error( "Unrecognised ordering: '" + order + '\'' ); + } + inline void setRngSeed( ConfigData& config, std::string const& seed ) { + if( seed == "time" ) { + config.rngSeed = static_cast( std::time(0) ); + } + else { + std::stringstream ss; + ss << seed; + ss >> config.rngSeed; + if( ss.fail() ) + throw std::runtime_error( "Argument to --rng-seed should be the word 'time' or a number" ); + } + } + inline void setVerbosity( ConfigData& config, int level ) { + // !TBD: accept strings? + config.verbosity = static_cast( level ); + } + inline void setShowDurations( ConfigData& config, bool _showDurations ) { + config.showDurations = _showDurations + ? ShowDurations::Always + : ShowDurations::Never; + } + inline void setUseColour( ConfigData& config, std::string const& value ) { + std::string mode = toLower( value ); + + if( mode == "yes" ) + config.useColour = UseColour::Yes; + else if( mode == "no" ) + config.useColour = UseColour::No; + else if( mode == "auto" ) + config.useColour = UseColour::Auto; + else + throw std::runtime_error( "colour mode must be one of: auto, yes or no" ); + } + inline void forceColour( ConfigData& config ) { + config.useColour = UseColour::Yes; + } + inline void loadTestNamesFromFile( ConfigData& config, std::string const& _filename ) { + std::ifstream f( _filename.c_str() ); + if( !f.is_open() ) + throw std::domain_error( "Unable to load input file: " + _filename ); + + std::string line; + while( std::getline( f, line ) ) { + line = trim(line); + if( !line.empty() && !startsWith( line, '#' ) ) { + if( !startsWith( line, '"' ) ) + line = '"' + line + '"'; + addTestOrTags( config, line + ',' ); + } + } + } + + inline Clara::CommandLine makeCommandLineParser() { + + using namespace Clara; + CommandLine cli; + + cli.bindProcessName( &ConfigData::processName ); + + cli["-?"]["-h"]["--help"] + .describe( "display usage information" ) + .bind( &ConfigData::showHelp ); + + cli["-l"]["--list-tests"] + .describe( "list all/matching test cases" ) + .bind( &ConfigData::listTests ); + + cli["-t"]["--list-tags"] + .describe( "list all/matching tags" ) + .bind( &ConfigData::listTags ); + + cli["-s"]["--success"] + .describe( "include successful tests in output" ) + .bind( &ConfigData::showSuccessfulTests ); + + cli["-b"]["--break"] + .describe( "break into debugger on failure" ) + .bind( &ConfigData::shouldDebugBreak ); + + cli["-e"]["--nothrow"] + .describe( "skip exception tests" ) + .bind( &ConfigData::noThrow ); + + cli["-i"]["--invisibles"] + .describe( "show invisibles (tabs, newlines)" ) + .bind( &ConfigData::showInvisibles ); + + cli["-o"]["--out"] + .describe( "output filename" ) + .bind( &ConfigData::outputFilename, "filename" ); + + cli["-r"]["--reporter"] +// .placeholder( "name[:filename]" ) + .describe( "reporter to use (defaults to console)" ) + .bind( &addReporterName, "name" ); + + cli["-n"]["--name"] + .describe( "suite name" ) + .bind( &ConfigData::name, "name" ); + + cli["-a"]["--abort"] + .describe( "abort at first failure" ) + .bind( &abortAfterFirst ); + + cli["-x"]["--abortx"] + .describe( "abort after x failures" ) + .bind( &abortAfterX, "no. failures" ); + + cli["-w"]["--warn"] + .describe( "enable warnings" ) + .bind( &addWarning, "warning name" ); + +// - needs updating if reinstated +// cli.into( &setVerbosity ) +// .describe( "level of verbosity (0=no output)" ) +// .shortOpt( "v") +// .longOpt( "verbosity" ) +// .placeholder( "level" ); + + cli[_] + .describe( "which test or tests to use" ) + .bind( &addTestOrTags, "test name, pattern or tags" ); + + cli["-d"]["--durations"] + .describe( "show test durations" ) + .bind( &setShowDurations, "yes|no" ); + + cli["-f"]["--input-file"] + .describe( "load test names to run from a file" ) + .bind( &loadTestNamesFromFile, "filename" ); + + cli["-#"]["--filenames-as-tags"] + .describe( "adds a tag for the filename" ) + .bind( &ConfigData::filenamesAsTags ); + + cli["-c"]["--section"] + .describe( "specify section to run" ) + .bind( &addSectionToRun, "section name" ); + + // 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-extra-info"] + .describe( "list all/matching test cases with more info" ) + .bind( &ConfigData::listExtraInfo ); + + cli["--list-reporters"] + .describe( "list all reporters" ) + .bind( &ConfigData::listReporters ); + + cli["--order"] + .describe( "test case order (defaults to decl)" ) + .bind( &setOrder, "decl|lex|rand" ); + + cli["--rng-seed"] + .describe( "set a specific seed for random numbers" ) + .bind( &setRngSeed, "'time'|number" ); + + cli["--force-colour"] + .describe( "force colourised output (deprecated)" ) + .bind( &forceColour ); + + cli["--use-colour"] + .describe( "should output be colourised" ) + .bind( &setUseColour, "yes|no" ); + + return cli; + } + } // end namespace Catch -// end catch_reporter_bases.hpp -// start catch_console_colour.h +// #included from: internal/catch_list.hpp +#define TWOBLUECUBES_CATCH_LIST_HPP_INCLUDED + +// #included from: catch_text.h +#define TWOBLUECUBES_CATCH_TEXT_H_INCLUDED + +#define TBC_TEXT_FORMAT_CONSOLE_WIDTH CATCH_CONFIG_CONSOLE_WIDTH + +#define CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE Catch +// #included from: ../external/tbc_text_format.h +// Only use header guard if we are not using an outer namespace +#ifndef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE +# ifdef TWOBLUECUBES_TEXT_FORMAT_H_INCLUDED +# ifndef TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED +# define TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED +# endif +# else +# define TWOBLUECUBES_TEXT_FORMAT_H_INCLUDED +# endif +#endif +#ifndef TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED +#include +#include +#include + +// Use optional outer namespace +#ifdef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE +namespace CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE { +#endif + +namespace Tbc { + +#ifdef TBC_TEXT_FORMAT_CONSOLE_WIDTH + const unsigned int consoleWidth = TBC_TEXT_FORMAT_CONSOLE_WIDTH; +#else + const unsigned int consoleWidth = 80; +#endif + + struct TextAttributes { + TextAttributes() + : initialIndent( std::string::npos ), + indent( 0 ), + width( consoleWidth-1 ) + {} + + 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; } + + 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 + }; + + class Text { + public: + Text( std::string const& _str, TextAttributes const& _attr = TextAttributes() ) + : attr( _attr ) + { + const std::string wrappableBeforeChars = "[({<\t"; + const std::string wrappableAfterChars = "])}>-,./|\\"; + const std::string wrappableInsteadOfChars = " \n\r"; + std::string indent = _attr.initialIndent != std::string::npos + ? std::string( _attr.initialIndent, ' ' ) + : std::string( _attr.indent, ' ' ); + + typedef std::string::const_iterator iterator; + iterator it = _str.begin(); + const iterator strEnd = _str.end(); + + while( it != strEnd ) { + + if( lines.size() >= 1000 ) { + lines.push_back( "... message truncated due to excessive size" ); + return; + } + + std::string suffix; + std::size_t width = (std::min)( static_cast( strEnd-it ), _attr.width-static_cast( indent.size() ) ); + iterator itEnd = it+width; + iterator itNext = _str.end(); + + iterator itNewLine = std::find( it, itEnd, '\n' ); + if( itNewLine != itEnd ) + itEnd = itNewLine; + + if( itEnd != strEnd ) { + bool foundWrapPoint = false; + iterator findIt = itEnd; + do { + if( wrappableAfterChars.find( *findIt ) != std::string::npos && findIt != itEnd ) { + itEnd = findIt+1; + itNext = findIt+1; + foundWrapPoint = true; + } + else if( findIt > it && wrappableBeforeChars.find( *findIt ) != std::string::npos ) { + itEnd = findIt; + itNext = findIt; + foundWrapPoint = true; + } + else if( wrappableInsteadOfChars.find( *findIt ) != std::string::npos ) { + itNext = findIt+1; + itEnd = findIt; + foundWrapPoint = true; + } + if( findIt == it ) + break; + else + --findIt; + } + while( !foundWrapPoint ); + + if( !foundWrapPoint ) { + // No good wrap char, so we'll break mid word and add a hyphen + --itEnd; + itNext = itEnd; + suffix = "-"; + } + else { + while( itEnd > it && wrappableInsteadOfChars.find( *(itEnd-1) ) != std::string::npos ) + --itEnd; + } + } + lines.push_back( indent + std::string( it, itEnd ) + suffix ); + + if( indent.size() != _attr.indent ) + indent = std::string( _attr.indent, ' ' ); + it = itNext; + } + } + + 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 + +#ifdef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE +} // end outer namespace +#endif + +#endif // TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED +#undef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE + +namespace Catch { + using Tbc::Text; + using Tbc::TextAttributes; +} + +// #included from: catch_console_colour.hpp +#define TWOBLUECUBES_CATCH_CONSOLE_COLOUR_HPP_INCLUDED namespace Catch { @@ -3701,105 +5545,462 @@ namespace Catch { // Use constructed object for RAII guard Colour( Code _colourCode ); - Colour( Colour&& other ) noexcept; - Colour& operator=( Colour&& other ) noexcept; + Colour( Colour const& other ); ~Colour(); // Use static method for one-shot changes static void use( Code _colourCode ); private: - bool m_moved = false; + bool m_moved; }; - std::ostream& operator << ( std::ostream& os, Colour const& ); + inline std::ostream& operator << ( std::ostream& os, Colour const& ) { return os; } } // end namespace Catch -// end catch_console_colour.h -// start catch_reporter_registrars.hpp +// #included from: catch_interfaces_reporter.h +#define TWOBLUECUBES_CATCH_INTERFACES_REPORTER_H_INCLUDED +#include +#include +#include + +namespace Catch +{ + struct ReporterConfig { + explicit ReporterConfig( Ptr const& _fullConfig ) + : m_stream( &_fullConfig->stream() ), m_fullConfig( _fullConfig ) {} + + 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; } + + private: + std::ostream* m_stream; + Ptr m_fullConfig; + }; + + struct ReporterPreferences { + ReporterPreferences() + : shouldRedirectStdOut( false ) + {} + + 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; + }; + + struct TestRunInfo { + TestRunInfo( std::string const& _name ) : name( _name ) {} + std::string name; + }; + struct GroupInfo { + GroupInfo( std::string const& _name, + std::size_t _groupIndex, + std::size_t _groupsCount ) + : name( _name ), + groupIndex( _groupIndex ), + groupsCounts( _groupsCount ) + {} + + std::string name; + std::size_t groupIndex; + std::size_t groupsCounts; + }; + + struct AssertionStats { + AssertionStats( AssertionResult const& _assertionResult, + std::vector const& _infoMessages, + Totals const& _totals ) + : assertionResult( _assertionResult ), + infoMessages( _infoMessages ), + totals( _totals ) + { + if( assertionResult.hasMessage() ) { + // Copy message into messages list. + // !TBD This should have been done earlier, somewhere + MessageBuilder builder( assertionResult.getTestMacroName(), assertionResult.getSourceInfo(), assertionResult.getResultType() ); + builder << assertionResult.getMessage(); + builder.m_info.message = builder.m_stream.str(); + + infoMessages.push_back( builder.m_info ); + } + } + virtual ~AssertionStats(); + +# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS + AssertionStats( AssertionStats const& ) = default; + AssertionStats( AssertionStats && ) = default; + AssertionStats& operator = ( AssertionStats const& ) = default; + AssertionStats& operator = ( AssertionStats && ) = default; +# endif + + AssertionResult assertionResult; + std::vector infoMessages; + Totals totals; + }; + + struct SectionStats { + SectionStats( SectionInfo const& _sectionInfo, + Counts const& _assertions, + double _durationInSeconds, + bool _missingAssertions ) + : sectionInfo( _sectionInfo ), + assertions( _assertions ), + durationInSeconds( _durationInSeconds ), + missingAssertions( _missingAssertions ) + {} + virtual ~SectionStats(); +# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS + SectionStats( SectionStats const& ) = default; + SectionStats( SectionStats && ) = default; + SectionStats& operator = ( SectionStats const& ) = default; + SectionStats& operator = ( SectionStats && ) = default; +# endif + + SectionInfo sectionInfo; + Counts assertions; + double durationInSeconds; + bool missingAssertions; + }; + + struct TestCaseStats { + TestCaseStats( TestCaseInfo const& _testInfo, + Totals const& _totals, + std::string const& _stdOut, + std::string const& _stdErr, + bool _aborting ) + : testInfo( _testInfo ), + totals( _totals ), + stdOut( _stdOut ), + stdErr( _stdErr ), + aborting( _aborting ) + {} + virtual ~TestCaseStats(); + +# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS + TestCaseStats( TestCaseStats const& ) = default; + TestCaseStats( TestCaseStats && ) = default; + TestCaseStats& operator = ( TestCaseStats const& ) = default; + TestCaseStats& operator = ( TestCaseStats && ) = default; +# endif + + TestCaseInfo testInfo; + Totals totals; + std::string stdOut; + std::string stdErr; + bool aborting; + }; + + struct TestGroupStats { + TestGroupStats( GroupInfo const& _groupInfo, + Totals const& _totals, + bool _aborting ) + : groupInfo( _groupInfo ), + totals( _totals ), + aborting( _aborting ) + {} + TestGroupStats( GroupInfo const& _groupInfo ) + : groupInfo( _groupInfo ), + aborting( false ) + {} + virtual ~TestGroupStats(); + +# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS + TestGroupStats( TestGroupStats const& ) = default; + TestGroupStats( TestGroupStats && ) = default; + TestGroupStats& operator = ( TestGroupStats const& ) = default; + TestGroupStats& operator = ( TestGroupStats && ) = default; +# endif + + GroupInfo groupInfo; + Totals totals; + bool aborting; + }; + + struct TestRunStats { + TestRunStats( TestRunInfo const& _runInfo, + Totals const& _totals, + bool _aborting ) + : runInfo( _runInfo ), + totals( _totals ), + aborting( _aborting ) + {} + virtual ~TestRunStats(); + +# ifndef CATCH_CONFIG_CPP11_GENERATED_METHODS + TestRunStats( TestRunStats const& _other ) + : runInfo( _other.runInfo ), + totals( _other.totals ), + aborting( _other.aborting ) + {} +# else + TestRunStats( TestRunStats const& ) = default; + TestRunStats( TestRunStats && ) = default; + TestRunStats& operator = ( TestRunStats const& ) = default; + TestRunStats& operator = ( TestRunStats && ) = default; +# endif + + TestRunInfo runInfo; + Totals totals; + bool aborting; + }; + + class MultipleReporters; + + struct IStreamingReporter : IShared { + virtual ~IStreamingReporter(); + + // Implementing class must also provide the following static method: + // static std::string getDescription(); + + virtual ReporterPreferences getPreferences() const = 0; + + virtual void noMatchingTestCases( std::string const& spec ) = 0; + + virtual void testRunStarting( TestRunInfo const& testRunInfo ) = 0; + virtual void testGroupStarting( GroupInfo const& groupInfo ) = 0; + + virtual void testCaseStarting( TestCaseInfo const& testInfo ) = 0; + virtual void sectionStarting( SectionInfo const& sectionInfo ) = 0; + + virtual void assertionStarting( AssertionInfo const& assertionInfo ) = 0; + + // The return value indicates if the messages buffer should be cleared: + virtual bool assertionEnded( AssertionStats const& assertionStats ) = 0; + + virtual void sectionEnded( SectionStats const& sectionStats ) = 0; + virtual void testCaseEnded( TestCaseStats const& testCaseStats ) = 0; + virtual void testGroupEnded( TestGroupStats const& testGroupStats ) = 0; + virtual void testRunEnded( TestRunStats const& testRunStats ) = 0; + + virtual void skipTest( TestCaseInfo const& testInfo ) = 0; + + virtual MultipleReporters* tryAsMulti() { return CATCH_NULL; } + }; + + struct IReporterFactory : IShared { + virtual ~IReporterFactory(); + virtual IStreamingReporter* create( ReporterConfig const& config ) const = 0; + virtual std::string getDescription() const = 0; + }; + + struct IReporterRegistry { + typedef std::map > FactoryMap; + typedef std::vector > Listeners; + + virtual ~IReporterRegistry(); + virtual IStreamingReporter* create( std::string const& name, Ptr const& config ) const = 0; + virtual FactoryMap const& getFactories() const = 0; + virtual Listeners const& getListeners() const = 0; + }; + + Ptr addReporter( Ptr const& existingReporter, Ptr const& additionalReporter ); + +} + +#include +#include namespace Catch { - template - class ReporterRegistrar { + inline std::size_t listTests( Config const& config ) { - class ReporterFactory : public IReporterFactory { - - virtual IStreamingReporterPtr create( ReporterConfig const& config ) const override { - return std::unique_ptr( new T( config ) ); - } - - virtual std::string getDescription() const override { - return T::getDescription(); - } - }; - - public: - - ReporterRegistrar( std::string const& name ) { - getMutableRegistryHub().registerReporter( name, std::make_shared() ); + TestSpec testSpec = config.testSpec(); + if( config.testSpec().hasFilters() ) + Catch::cout() << "Matching test cases:\n"; + else { + Catch::cout() << "All available test cases:\n"; + testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "*" ).testSpec(); } + + std::size_t matchedTests = 0; + TextAttributes nameAttr, descAttr, tagsAttr; + nameAttr.setInitialIndent( 2 ).setIndent( 4 ); + descAttr.setIndent( 4 ); + tagsAttr.setIndent( 6 ); + + std::vector matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config ); + 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 ); + + Catch::cout() << Text( testCaseInfo.name, nameAttr ) << std::endl; + if( config.listExtraInfo() ) { + Catch::cout() << " " << testCaseInfo.lineInfo << std::endl; + std::string description = testCaseInfo.description; + if( description.empty() ) + description = "(NO DESCRIPTION)"; + Catch::cout() << Text( description, descAttr ) << std::endl; + } + if( !testCaseInfo.tags.empty() ) + Catch::cout() << Text( testCaseInfo.tagsAsString, tagsAttr ) << std::endl; + } + + if( !config.testSpec().hasFilters() ) + Catch::cout() << pluralise( matchedTests, "test case" ) << '\n' << std::endl; + else + Catch::cout() << pluralise( matchedTests, "matching test case" ) << '\n' << std::endl; + return matchedTests; + } + + inline std::size_t listTestsNamesOnly( Config const& config ) { + TestSpec testSpec = config.testSpec(); + if( !config.testSpec().hasFilters() ) + testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "*" ).testSpec(); + std::size_t matchedTests = 0; + std::vector matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config ); + for( std::vector::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end(); + it != itEnd; + ++it ) { + matchedTests++; + TestCaseInfo const& testCaseInfo = it->getTestCaseInfo(); + if( startsWith( testCaseInfo.name, '#' ) ) + Catch::cout() << '"' << testCaseInfo.name << '"'; + else + Catch::cout() << testCaseInfo.name; + if ( config.listExtraInfo() ) + Catch::cout() << "\t@" << testCaseInfo.lineInfo; + Catch::cout() << 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(); + it != itEnd; + ++it ) + out += "[" + *it + "]"; + return out; + } + std::set spellings; + std::size_t count; }; - template - class ListenerRegistrar { - - class ListenerFactory : public IReporterFactory { - - virtual IStreamingReporterPtr create( ReporterConfig const& config ) const override { - return std::unique_ptr( new T( config ) ); - } - virtual std::string getDescription() const override { - return std::string(); - } - }; - - public: - - ListenerRegistrar() { - getMutableRegistryHub().registerListener( std::make_shared() ); + inline std::size_t listTags( Config const& config ) { + TestSpec testSpec = config.testSpec(); + if( config.testSpec().hasFilters() ) + Catch::cout() << "Tags for matching test cases:\n"; + else { + Catch::cout() << "All available tags:\n"; + testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "*" ).testSpec(); } - }; -} -#if !defined(CATCH_CONFIG_DISABLE) + std::map tagCounts; -#define CATCH_REGISTER_REPORTER( name, reporterType ) \ - CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ - namespace{ Catch::ReporterRegistrar catch_internal_RegistrarFor##reporterType( name ); } \ - CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS + std::vector matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config ); + 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 ); + } + } -#define CATCH_REGISTER_LISTENER( listenerType ) \ - CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ - namespace{ Catch::ListenerRegistrar catch_internal_RegistrarFor##listenerType; } \ - CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS -#else // CATCH_CONFIG_DISABLE + 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 ) ); + Catch::cout() << oss.str() << wrapper << '\n'; + } + Catch::cout() << pluralise( tagCounts.size(), "tag" ) << '\n' << std::endl; + return tagCounts.size(); + } -#define CATCH_REGISTER_REPORTER(name, reporterType) -#define CATCH_REGISTER_LISTENER(listenerType) + inline std::size_t listReporters( Config const& /*config*/ ) { + Catch::cout() << "Available reporters:\n"; + IReporterRegistry::FactoryMap const& factories = getRegistryHub().getReporterRegistry().getFactories(); + IReporterRegistry::FactoryMap::const_iterator itBegin = factories.begin(), itEnd = factories.end(), it; + std::size_t maxNameLen = 0; + for(it = itBegin; it != itEnd; ++it ) + maxNameLen = (std::max)( maxNameLen, it->first.size() ); -#endif // CATCH_CONFIG_DISABLE + for(it = itBegin; it != itEnd; ++it ) { + Text wrapper( it->second->getDescription(), TextAttributes() + .setInitialIndent( 0 ) + .setIndent( 7+maxNameLen ) + .setWidth( CATCH_CONFIG_CONSOLE_WIDTH - maxNameLen-8 ) ); + Catch::cout() << " " + << it->first + << ':' + << std::string( maxNameLen - it->first.size() + 2, ' ' ) + << wrapper << '\n'; + } + Catch::cout() << std::endl; + return factories.size(); + } -// end catch_reporter_registrars.hpp -// end catch_external_interfaces.h -#endif + inline Option list( Config const& config ) { + Option listedCount; + if( config.listTests() || ( config.listExtraInfo() && !config.listTestNamesOnly() ) ) + 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; + } -#ifdef CATCH_IMPL -// start catch_impl.hpp +} // end namespace Catch -#ifdef __clang__ -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wweak-vtables" -#endif +// #included from: internal/catch_run_context.hpp +#define TWOBLUECUBES_CATCH_RUNNER_IMPL_HPP_INCLUDED -// Keep these here for external reporters -// start catch_test_case_tracker.h +// #included from: catch_test_case_tracker.hpp +#define TWOBLUECUBES_CATCH_TEST_CASE_TRACKER_HPP_INCLUDED +#include #include +#include #include -#include +#include + +CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS namespace Catch { namespace TestCaseTracking { @@ -3808,14 +6009,13 @@ namespace TestCaseTracking { std::string name; SourceLineInfo location; - NameAndLocation( std::string const& _name, SourceLineInfo const& _location ); + NameAndLocation( std::string const& _name, SourceLineInfo const& _location ) + : name( _name ), + location( _location ) + {} }; - struct ITracker; - - using ITrackerPtr = std::shared_ptr; - - struct ITracker { + struct ITracker : SharedImpl<> { virtual ~ITracker(); // static queries @@ -3834,8 +6034,8 @@ namespace TestCaseTracking { virtual void fail() = 0; virtual void markAsNeedingAnotherRun() = 0; - virtual void addChild( ITrackerPtr const& child ) = 0; - virtual ITrackerPtr findChild( NameAndLocation const& nameAndLocation ) = 0; + virtual void addChild( Ptr const& child ) = 0; + virtual ITracker* findChild( NameAndLocation const& nameAndLocation ) = 0; virtual void openChild() = 0; // Debug/ checking @@ -3843,7 +6043,7 @@ namespace TestCaseTracking { virtual bool isIndexTracker() const = 0; }; - class TrackerContext { + class TrackerContext { enum RunState { NotStarted, @@ -3851,23 +6051,47 @@ namespace TestCaseTracking { CompletedCycle }; - ITrackerPtr m_rootTracker; - ITracker* m_currentTracker = nullptr; - RunState m_runState = NotStarted; + Ptr m_rootTracker; + ITracker* m_currentTracker; + RunState m_runState; public: - static TrackerContext& instance(); + static TrackerContext& instance() { + static TrackerContext s_instance; + return s_instance; + } + + TrackerContext() + : m_currentTracker( CATCH_NULL ), + m_runState( NotStarted ) + {} ITracker& startRun(); - void endRun(); - void startCycle(); - void completeCycle(); + void endRun() { + m_rootTracker.reset(); + m_currentTracker = CATCH_NULL; + m_runState = NotStarted; + } - bool completedCycle() const; - ITracker& currentTracker(); - void setCurrentTracker( ITracker* tracker ); + void startCycle() { + m_currentTracker = m_rootTracker.get(); + m_runState = Executing; + } + void completeCycle() { + m_runState = CompletedCycle; + } + + bool completedCycle() const { + return m_runState == CompletedCycle; + } + ITracker& currentTracker() { + return *m_currentTracker; + } + void setCurrentTracker( ITracker* tracker ) { + m_currentTracker = tracker; + } }; class TrackerBase : public ITracker { @@ -3880,82 +6104,240 @@ namespace TestCaseTracking { CompletedSuccessfully, Failed }; - class TrackerHasName { NameAndLocation m_nameAndLocation; public: - TrackerHasName( NameAndLocation const& nameAndLocation ); - bool operator ()( ITrackerPtr const& tracker ) const; + TrackerHasName( NameAndLocation const& nameAndLocation ) : m_nameAndLocation( nameAndLocation ) {} + bool operator ()( Ptr const& tracker ) { + return + tracker->nameAndLocation().name == m_nameAndLocation.name && + tracker->nameAndLocation().location == m_nameAndLocation.location; + } }; - - using Children = std::vector; + typedef std::vector > Children; NameAndLocation m_nameAndLocation; TrackerContext& m_ctx; ITracker* m_parent; Children m_children; - CycleState m_runState = NotStarted; - + CycleState m_runState; public: - TrackerBase( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent ); + TrackerBase( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent ) + : m_nameAndLocation( nameAndLocation ), + m_ctx( ctx ), + m_parent( parent ), + m_runState( NotStarted ) + {} + virtual ~TrackerBase(); - NameAndLocation const& nameAndLocation() const override; - bool isComplete() const override; - bool isSuccessfullyCompleted() const override; - bool isOpen() const override; - bool hasChildren() const override; + virtual NameAndLocation const& nameAndLocation() const CATCH_OVERRIDE { + return m_nameAndLocation; + } + virtual bool isComplete() const CATCH_OVERRIDE { + return m_runState == CompletedSuccessfully || m_runState == Failed; + } + virtual bool isSuccessfullyCompleted() const CATCH_OVERRIDE { + return m_runState == CompletedSuccessfully; + } + virtual bool isOpen() const CATCH_OVERRIDE { + return m_runState != NotStarted && !isComplete(); + } + virtual bool hasChildren() const CATCH_OVERRIDE { + return !m_children.empty(); + } - void addChild( ITrackerPtr const& child ) override; + virtual void addChild( Ptr const& child ) CATCH_OVERRIDE { + m_children.push_back( child ); + } - ITrackerPtr findChild( NameAndLocation const& nameAndLocation ) override; - ITracker& parent() override; + virtual ITracker* findChild( NameAndLocation const& nameAndLocation ) CATCH_OVERRIDE { + Children::const_iterator it = std::find_if( m_children.begin(), m_children.end(), TrackerHasName( nameAndLocation ) ); + return( it != m_children.end() ) + ? it->get() + : CATCH_NULL; + } + virtual ITracker& parent() CATCH_OVERRIDE { + assert( m_parent ); // Should always be non-null except for root + return *m_parent; + } - void openChild() override; + virtual void openChild() CATCH_OVERRIDE { + if( m_runState != ExecutingChildren ) { + m_runState = ExecutingChildren; + if( m_parent ) + m_parent->openChild(); + } + } - bool isSectionTracker() const override; - bool isIndexTracker() const override; + virtual bool isSectionTracker() const CATCH_OVERRIDE { return false; } + virtual bool isIndexTracker() const CATCH_OVERRIDE { return false; } - void open(); + void open() { + m_runState = Executing; + moveToThis(); + if( m_parent ) + m_parent->openChild(); + } - void close() override; - void fail() override; - void markAsNeedingAnotherRun() override; + virtual void close() CATCH_OVERRIDE { + // Close any still open children (e.g. generators) + while( &m_ctx.currentTracker() != this ) + m_ctx.currentTracker().close(); + + switch( m_runState ) { + case NotStarted: + case CompletedSuccessfully: + case Failed: + throw std::logic_error( "Illogical state" ); + + case NeedsAnotherRun: + break;; + + case Executing: + m_runState = CompletedSuccessfully; + break; + case ExecutingChildren: + if( m_children.empty() || m_children.back()->isComplete() ) + m_runState = CompletedSuccessfully; + break; + + default: + throw std::logic_error( "Unexpected state" ); + } + moveToParent(); + m_ctx.completeCycle(); + } + virtual void fail() CATCH_OVERRIDE { + m_runState = Failed; + if( m_parent ) + m_parent->markAsNeedingAnotherRun(); + moveToParent(); + m_ctx.completeCycle(); + } + virtual void markAsNeedingAnotherRun() CATCH_OVERRIDE { + m_runState = NeedsAnotherRun; + } private: - void moveToParent(); - void moveToThis(); + void moveToParent() { + assert( m_parent ); + m_ctx.setCurrentTracker( m_parent ); + } + void moveToThis() { + m_ctx.setCurrentTracker( this ); + } }; class SectionTracker : public TrackerBase { std::vector m_filters; public: - SectionTracker( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent ); + SectionTracker( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent ) + : TrackerBase( nameAndLocation, ctx, parent ) + { + if( parent ) { + while( !parent->isSectionTracker() ) + parent = &parent->parent(); - bool isSectionTracker() const override; + SectionTracker& parentSection = static_cast( *parent ); + addNextFilters( parentSection.m_filters ); + } + } + virtual ~SectionTracker(); - static SectionTracker& acquire( TrackerContext& ctx, NameAndLocation const& nameAndLocation ); + virtual bool isSectionTracker() const CATCH_OVERRIDE { return true; } - void tryOpen(); + static SectionTracker& acquire( TrackerContext& ctx, NameAndLocation const& nameAndLocation ) { + SectionTracker* section = CATCH_NULL; - void addInitialFilters( std::vector const& filters ); - void addNextFilters( std::vector const& filters ); + ITracker& currentTracker = ctx.currentTracker(); + if( ITracker* childTracker = currentTracker.findChild( nameAndLocation ) ) { + assert( childTracker ); + assert( childTracker->isSectionTracker() ); + section = static_cast( childTracker ); + } + else { + section = new SectionTracker( nameAndLocation, ctx, ¤tTracker ); + currentTracker.addChild( section ); + } + if( !ctx.completedCycle() ) + section->tryOpen(); + return *section; + } + + void tryOpen() { + if( !isComplete() && (m_filters.empty() || m_filters[0].empty() || m_filters[0] == m_nameAndLocation.name ) ) + open(); + } + + void addInitialFilters( std::vector const& filters ) { + if( !filters.empty() ) { + m_filters.push_back(""); // Root - should never be consulted + m_filters.push_back(""); // Test Case - not a section filter + m_filters.insert( m_filters.end(), filters.begin(), filters.end() ); + } + } + void addNextFilters( std::vector const& filters ) { + if( filters.size() > 1 ) + m_filters.insert( m_filters.end(), ++filters.begin(), filters.end() ); + } }; class IndexTracker : public TrackerBase { int m_size; - int m_index = -1; + int m_index; public: - IndexTracker( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent, int size ); + IndexTracker( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent, int size ) + : TrackerBase( nameAndLocation, ctx, parent ), + m_size( size ), + m_index( -1 ) + {} + virtual ~IndexTracker(); - bool isIndexTracker() const override; - void close() override; + virtual bool isIndexTracker() const CATCH_OVERRIDE { return true; } - static IndexTracker& acquire( TrackerContext& ctx, NameAndLocation const& nameAndLocation, int size ); + static IndexTracker& acquire( TrackerContext& ctx, NameAndLocation const& nameAndLocation, int size ) { + IndexTracker* tracker = CATCH_NULL; - int index() const; + ITracker& currentTracker = ctx.currentTracker(); + if( ITracker* childTracker = currentTracker.findChild( nameAndLocation ) ) { + assert( childTracker ); + assert( childTracker->isIndexTracker() ); + tracker = static_cast( childTracker ); + } + else { + tracker = new IndexTracker( nameAndLocation, ctx, ¤tTracker, size ); + currentTracker.addChild( tracker ); + } - void moveNext(); + if( !ctx.completedCycle() && !tracker->isComplete() ) { + if( tracker->m_runState != ExecutingChildren && tracker->m_runState != NeedsAnotherRun ) + tracker->moveNext(); + tracker->open(); + } + + return *tracker; + } + + int index() const { return m_index; } + + void moveNext() { + m_index++; + m_children.clear(); + } + + virtual void close() CATCH_OVERRIDE { + TrackerBase::close(); + if( m_runState == CompletedSuccessfully && m_index < m_size-1 ) + m_runState = Executing; + } }; + inline ITracker& TrackerContext::startRun() { + m_rootTracker = new SectionTracker( NameAndLocation( "{root}", CATCH_INTERNAL_LINEINFO ), *this, CATCH_NULL ); + m_currentTracker = CATCH_NULL; + m_runState = Executing; + return *m_rootTracker; + } + } // namespace TestCaseTracking using TestCaseTracking::ITracker; @@ -3965,1941 +6347,31 @@ using TestCaseTracking::IndexTracker; } // namespace Catch -// end catch_test_case_tracker.h +CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS -// start catch_leak_detector.h +// #included from: catch_fatal_condition.hpp +#define TWOBLUECUBES_CATCH_FATAL_CONDITION_H_INCLUDED namespace Catch { - struct LeakDetector { - LeakDetector(); - }; - -} -// end catch_leak_detector.h -// Cpp files will be included in the single-header file here -// start catch_approx.cpp - -#include -#include - -namespace { - -// Performs equivalent check of std::fabs(lhs - rhs) <= margin -// But without the subtraction to allow for INFINITY in comparison -bool marginComparison(double lhs, double rhs, double margin) { - return (lhs + margin >= rhs) && (rhs + margin >= lhs); -} - -} - -namespace Catch { -namespace Detail { - - Approx::Approx ( double value ) - : m_epsilon( std::numeric_limits::epsilon()*100 ), - m_margin( 0.0 ), - m_scale( 0.0 ), - m_value( value ) - {} - - Approx Approx::custom() { - return Approx( 0 ); - } - - std::string Approx::toString() const { - std::ostringstream oss; - oss << "Approx( " << ::Catch::Detail::stringify( m_value ) << " )"; - return oss.str(); - } - - bool Approx::equalityComparisonImpl(const double other) const { - // First try with fixed margin, then compute margin based on epsilon, scale and Approx's value - // Thanks to Richard Harris for his help refining the scaled margin value - return marginComparison(m_value, other, m_margin) || marginComparison(m_value, other, m_epsilon * (m_scale + std::fabs(m_value))); - } - -} // end namespace Detail - -std::string StringMaker::convert(Catch::Detail::Approx const& value) { - return value.toString(); -} - -} // end namespace Catch -// end catch_approx.cpp -// start catch_assertionhandler.cpp - -// start catch_context.h - -#include - -namespace Catch { - - struct IResultCapture; - struct IRunner; - struct IConfig; - - using IConfigPtr = std::shared_ptr; - - struct IContext - { - virtual ~IContext(); - - virtual IResultCapture* getResultCapture() = 0; - virtual IRunner* getRunner() = 0; - virtual IConfigPtr getConfig() const = 0; - }; - - struct IMutableContext : IContext - { - virtual ~IMutableContext(); - virtual void setResultCapture( IResultCapture* resultCapture ) = 0; - virtual void setRunner( IRunner* runner ) = 0; - virtual void setConfig( IConfigPtr const& config ) = 0; - }; - - IContext& getCurrentContext(); - IMutableContext& getCurrentMutableContext(); - void cleanUpContext(); -} - -// end catch_context.h -#include - -namespace Catch { - - auto operator <<( std::ostream& os, ITransientExpression const& expr ) -> std::ostream& { - expr.streamReconstructedExpression( os ); - return os; - } - - LazyExpression::LazyExpression( bool isNegated ) - : m_isNegated( isNegated ) - {} - - LazyExpression::LazyExpression( LazyExpression const& other ) : m_isNegated( other.m_isNegated ) {} - - LazyExpression::operator bool() const { - return m_transientExpression != nullptr; - } - - auto operator << ( std::ostream& os, LazyExpression const& lazyExpr ) -> std::ostream& { - if( lazyExpr.m_isNegated ) - os << "!"; - - if( lazyExpr ) { - if( lazyExpr.m_isNegated && lazyExpr.m_transientExpression->isBinaryExpression() ) - os << "(" << *lazyExpr.m_transientExpression << ")"; - else - os << *lazyExpr.m_transientExpression; - } - else { - os << "{** error - unchecked empty expression requested **}"; - } - return os; - } - - AssertionHandler::AssertionHandler - ( StringRef macroName, - SourceLineInfo const& lineInfo, - StringRef capturedExpression, - ResultDisposition::Flags resultDisposition ) - : m_assertionInfo{ macroName, lineInfo, capturedExpression, resultDisposition } - { - getCurrentContext().getResultCapture()->assertionStarting( m_assertionInfo ); - } - AssertionHandler::~AssertionHandler() { - if ( m_inExceptionGuard ) { - handle( ResultWas::ThrewException, "Exception translation was disabled by CATCH_CONFIG_FAST_COMPILE" ); - getCurrentContext().getResultCapture()->exceptionEarlyReported(); - } - } - - void AssertionHandler::handle( ITransientExpression const& expr ) { - - bool negated = isFalseTest( m_assertionInfo.resultDisposition ); - bool result = expr.getResult() != negated; - - handle( result ? ResultWas::Ok : ResultWas::ExpressionFailed, &expr, negated ); - } - void AssertionHandler::handle( ResultWas::OfType resultType ) { - handle( resultType, nullptr, false ); - } - void AssertionHandler::handle( ResultWas::OfType resultType, StringRef const& message ) { - AssertionResultData data( resultType, LazyExpression( false ) ); - data.message = message; - handle( data, nullptr ); - } - void AssertionHandler::handle( ResultWas::OfType resultType, ITransientExpression const* expr, bool negated ) { - AssertionResultData data( resultType, LazyExpression( negated ) ); - handle( data, expr ); - } - void AssertionHandler::handle( AssertionResultData const& resultData, ITransientExpression const* expr ) { - - getResultCapture().assertionRun(); - - AssertionResult assertionResult{ m_assertionInfo, resultData }; - assertionResult.m_resultData.lazyExpression.m_transientExpression = expr; - - getResultCapture().assertionEnded( assertionResult ); - - if( !assertionResult.isOk() ) { - m_shouldDebugBreak = getCurrentContext().getConfig()->shouldDebugBreak(); - m_shouldThrow = - getCurrentContext().getRunner()->aborting() || - (m_assertionInfo.resultDisposition & ResultDisposition::Normal); - } - } - - auto AssertionHandler::allowThrows() const -> bool { - return getCurrentContext().getConfig()->allowThrows(); - } - - auto AssertionHandler::shouldDebugBreak() const -> bool { - return m_shouldDebugBreak; - } - void AssertionHandler::reactWithDebugBreak() const { - if (m_shouldDebugBreak) { - /////////////////////////////////////////////////////////////////// - // To inspect the state during test, you need to go one level up the callstack - // To go back to the test and change execution, jump over the reactWithoutDebugBreak() call - /////////////////////////////////////////////////////////////////// - CATCH_BREAK_INTO_DEBUGGER(); - } - reactWithoutDebugBreak(); - } - void AssertionHandler::reactWithoutDebugBreak() const { - if( m_shouldThrow ) - throw Catch::TestFailureException(); - } - - void AssertionHandler::useActiveException() { - handle( ResultWas::ThrewException, Catch::translateActiveException() ); - } - - void AssertionHandler::setExceptionGuard() { - assert( m_inExceptionGuard == false ); - m_inExceptionGuard = true; - } - void AssertionHandler::unsetExceptionGuard() { - assert( m_inExceptionGuard == true ); - m_inExceptionGuard = false; - } - - // This is the overload that takes a string and infers the Equals matcher from it - // The more general overload, that takes any string matcher, is in catch_capture_matchers.cpp - void handleExceptionMatchExpr( AssertionHandler& handler, std::string const& str, StringRef matcherString ) { - handleExceptionMatchExpr( handler, Matchers::Equals( str ), matcherString ); + // Report the error condition + inline void reportFatal( std::string const& message ) { + IContext& context = Catch::getCurrentContext(); + IResultCapture* resultCapture = context.getResultCapture(); + resultCapture->handleFatalErrorCondition( message ); } } // namespace Catch -// end catch_assertionhandler.cpp -// start catch_assertionresult.cpp -namespace Catch { - AssertionResultData::AssertionResultData(ResultWas::OfType _resultType, LazyExpression const & _lazyExpression): - lazyExpression(_lazyExpression), - resultType(_resultType) {} +#if defined ( CATCH_PLATFORM_WINDOWS ) ///////////////////////////////////////// +// #included from: catch_windows_h_proxy.h - std::string AssertionResultData::reconstructExpression() const { +#define TWOBLUECUBES_CATCH_WINDOWS_H_PROXY_H_INCLUDED - if( reconstructedExpression.empty() ) { - if( lazyExpression ) { - // !TBD Use stringstream for now, but rework above to pass stream in - std::ostringstream oss; - oss << lazyExpression; - reconstructedExpression = oss.str(); - } - } - return reconstructedExpression; - } - - AssertionResult::AssertionResult( AssertionInfo const& info, AssertionResultData const& data ) - : m_info( info ), - m_resultData( data ) - {} - - // 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[0] != 0; - } - - bool AssertionResult::hasMessage() const { - return !m_resultData.message.empty(); - } - - std::string AssertionResult::getExpression() const { - if( isFalseTest( m_info.resultDisposition ) ) - return "!(" + std::string(m_info.capturedExpression) + ")"; - else - return m_info.capturedExpression; - } - - std::string AssertionResult::getExpressionInMacro() const { - std::string expr; - if( m_info.macroName[0] == 0 ) - expr = m_info.capturedExpression; - else { - expr.reserve( m_info.macroName.size() + m_info.capturedExpression.size() + 4 ); - expr += m_info.macroName; - expr += "( "; - expr += m_info.capturedExpression; - expr += " )"; - } - return expr; - } - - bool AssertionResult::hasExpandedExpression() const { - return hasExpression() && getExpandedExpression() != getExpression(); - } - - std::string AssertionResult::getExpandedExpression() const { - std::string expr = m_resultData.reconstructExpression(); - return expr.empty() - ? getExpression() - : expr; - } - - 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 -// end catch_assertionresult.cpp -// start catch_benchmark.cpp - -namespace Catch { - - auto BenchmarkLooper::getResolution() -> uint64_t { - return getEstimatedClockResolution() * getCurrentContext().getConfig()->benchmarkResolutionMultiple(); - } - - void BenchmarkLooper::reportStart() { - getResultCapture().benchmarkStarting( { m_name } ); - } - auto BenchmarkLooper::needsMoreIterations() -> bool { - auto elapsed = m_timer.getElapsedNanoseconds(); - - // Exponentially increasing iterations until we're confident in our timer resolution - if( elapsed < m_resolution ) { - m_iterationsToRun *= 10; - return true; - } - - getResultCapture().benchmarkEnded( { { m_name }, m_count, elapsed } ); - return false; - } - -} // end namespace Catch -// end catch_benchmark.cpp -// start catch_capture_matchers.cpp - -namespace Catch { - - using StringMatcher = Matchers::Impl::MatcherBase; - - // This is the general overload that takes a any string matcher - // There is another overload, in catch_assertinhandler.h/.cpp, that only takes a string and infers - // the Equals matcher (so the header does not mention matchers) - void handleExceptionMatchExpr( AssertionHandler& handler, StringMatcher const& matcher, StringRef matcherString ) { - std::string exceptionMessage = Catch::translateActiveException(); - MatchExpr expr( exceptionMessage, matcher, matcherString ); - handler.handle( expr ); - } - -} // namespace Catch -// end catch_capture_matchers.cpp -// start catch_commandline.cpp - -// start catch_commandline.h - -// start catch_clara.h - -// 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 CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH -#undef CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH -#endif -#define CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH CATCH_CONFIG_CONSOLE_WIDTH-1 - -#ifdef __clang__ -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wweak-vtables" -#pragma clang diagnostic ignored "-Wexit-time-destructors" -#pragma clang diagnostic ignored "-Wshadow" -#endif - -// start clara.hpp -// v1.0-develop.2 -// See https://github.com/philsquared/Clara - - -#ifndef CATCH_CLARA_CONFIG_CONSOLE_WIDTH -#define CATCH_CLARA_CONFIG_CONSOLE_WIDTH 80 -#endif - -#ifndef CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH -#define CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH CATCH_CLARA_CONFIG_CONSOLE_WIDTH -#endif - -// ----------- #included from clara_textflow.hpp ----------- - -// TextFlowCpp -// -// A single-header library for wrapping and laying out basic text, by Phil Nash -// -// This work is licensed under the BSD 2-Clause license. -// See the accompanying LICENSE file, or the one at https://opensource.org/licenses/BSD-2-Clause -// -// This project is hosted at https://github.com/philsquared/textflowcpp - - -#include -#include -#include -#include - -#ifndef CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH -#define CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH 80 -#endif - -namespace Catch { namespace clara { namespace TextFlow { - - inline auto isWhitespace( char c ) -> bool { - static std::string chars = " \t\n\r"; - return chars.find( c ) != std::string::npos; - } - inline auto isBreakableBefore( char c ) -> bool { - static std::string chars = "[({<|"; - return chars.find( c ) != std::string::npos; - } - inline auto isBreakableAfter( char c ) -> bool { - static std::string chars = "])}>.,:;*+-=&/\\"; - return chars.find( c ) != std::string::npos; - } - - class Columns; - - class Column { - std::vector m_strings; - size_t m_width = CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH; - size_t m_indent = 0; - size_t m_initialIndent = std::string::npos; - - public: - class iterator { - friend Column; - - Column const& m_column; - size_t m_stringIndex = 0; - size_t m_pos = 0; - - size_t m_len = 0; - size_t m_end = 0; - bool m_suffix = false; - - iterator( Column const& column, size_t stringIndex ) - : m_column( column ), - m_stringIndex( stringIndex ) - {} - - auto line() const -> std::string const& { return m_column.m_strings[m_stringIndex]; } - - auto isBoundary( size_t at ) const -> bool { - assert( at > 0 ); - assert( at <= line().size() ); - - return at == line().size() || - ( isWhitespace( line()[at] ) && !isWhitespace( line()[at-1] ) ) || - isBreakableBefore( line()[at] ) || - isBreakableAfter( line()[at-1] ); - } - - void calcLength() { - assert( m_stringIndex < m_column.m_strings.size() ); - - m_suffix = false; - auto width = m_column.m_width-indent(); - m_end = m_pos; - while( m_end < line().size() && line()[m_end] != '\n' ) - ++m_end; - - if( m_end < m_pos + width ) { - m_len = m_end - m_pos; - } - else { - size_t len = width; - while (len > 0 && !isBoundary(m_pos + len)) - --len; - while (len > 0 && isWhitespace( line()[m_pos + len - 1] )) - --len; - - if (len > 0) { - m_len = len; - } else { - m_suffix = true; - m_len = width - 1; - } - } - } - - auto indent() const -> size_t { - auto initial = m_pos == 0 && m_stringIndex == 0 ? m_column.m_initialIndent : std::string::npos; - return initial == std::string::npos ? m_column.m_indent : initial; - } - - auto addIndentAndSuffix(std::string const &plain) const -> std::string { - return std::string( indent(), ' ' ) + (m_suffix ? plain + "-" : plain); - } - - public: - explicit iterator( Column const& column ) : m_column( column ) { - assert( m_column.m_width > m_column.m_indent ); - assert( m_column.m_initialIndent == std::string::npos || m_column.m_width > m_column.m_initialIndent ); - calcLength(); - if( m_len == 0 ) - m_stringIndex++; // Empty string - } - - auto operator *() const -> std::string { - assert( m_stringIndex < m_column.m_strings.size() ); - assert( m_pos <= m_end ); - if( m_pos + m_column.m_width < m_end ) - return addIndentAndSuffix(line().substr(m_pos, m_len)); - else - return addIndentAndSuffix(line().substr(m_pos, m_end - m_pos)); - } - - auto operator ++() -> iterator& { - m_pos += m_len; - if( m_pos < line().size() && line()[m_pos] == '\n' ) - m_pos += 1; - else - while( m_pos < line().size() && isWhitespace( line()[m_pos] ) ) - ++m_pos; - - if( m_pos == line().size() ) { - m_pos = 0; - ++m_stringIndex; - } - if( m_stringIndex < m_column.m_strings.size() ) - calcLength(); - return *this; - } - auto operator ++(int) -> iterator { - iterator prev( *this ); - operator++(); - return prev; - } - - auto operator ==( iterator const& other ) const -> bool { - return - m_pos == other.m_pos && - m_stringIndex == other.m_stringIndex && - &m_column == &other.m_column; - } - auto operator !=( iterator const& other ) const -> bool { - return !operator==( other ); - } - }; - using const_iterator = iterator; - - explicit Column( std::string const& text ) { m_strings.push_back( text ); } - - auto width( size_t newWidth ) -> Column& { - assert( newWidth > 0 ); - m_width = newWidth; - return *this; - } - auto indent( size_t newIndent ) -> Column& { - m_indent = newIndent; - return *this; - } - auto initialIndent( size_t newIndent ) -> Column& { - m_initialIndent = newIndent; - return *this; - } - - auto width() const -> size_t { return m_width; } - auto begin() const -> iterator { return iterator( *this ); } - auto end() const -> iterator { return { *this, m_strings.size() }; } - - inline friend std::ostream& operator << ( std::ostream& os, Column const& col ) { - bool first = true; - for( auto line : col ) { - if( first ) - first = false; - else - os << "\n"; - os << line; - } - return os; - } - - auto operator + ( Column const& other ) -> Columns; - - auto toString() const -> std::string { - std::ostringstream oss; - oss << *this; - return oss.str(); - } - }; - - class Spacer : public Column { - - public: - explicit Spacer( size_t spaceWidth ) : Column( "" ) { - width( spaceWidth ); - } - }; - - class Columns { - std::vector m_columns; - - public: - - class iterator { - friend Columns; - struct EndTag {}; - - std::vector const& m_columns; - std::vector m_iterators; - size_t m_activeIterators; - - iterator( Columns const& columns, EndTag ) - : m_columns( columns.m_columns ), - m_activeIterators( 0 ) - { - m_iterators.reserve( m_columns.size() ); - - for( auto const& col : m_columns ) - m_iterators.push_back( col.end() ); - } - - public: - explicit iterator( Columns const& columns ) - : m_columns( columns.m_columns ), - m_activeIterators( m_columns.size() ) - { - m_iterators.reserve( m_columns.size() ); - - for( auto const& col : m_columns ) - m_iterators.push_back( col.begin() ); - } - - auto operator ==( iterator const& other ) const -> bool { - return m_iterators == other.m_iterators; - } - auto operator !=( iterator const& other ) const -> bool { - return m_iterators != other.m_iterators; - } - auto operator *() const -> std::string { - std::string row, padding; - - for( size_t i = 0; i < m_columns.size(); ++i ) { - auto width = m_columns[i].width(); - if( m_iterators[i] != m_columns[i].end() ) { - std::string col = *m_iterators[i]; - row += padding + col; - if( col.size() < width ) - padding = std::string( width - col.size(), ' ' ); - else - padding = ""; - } - else { - padding += std::string( width, ' ' ); - } - } - return row; - } - auto operator ++() -> iterator& { - for( size_t i = 0; i < m_columns.size(); ++i ) { - if (m_iterators[i] != m_columns[i].end()) - ++m_iterators[i]; - } - return *this; - } - auto operator ++(int) -> iterator { - iterator prev( *this ); - operator++(); - return prev; - } - }; - using const_iterator = iterator; - - auto begin() const -> iterator { return iterator( *this ); } - auto end() const -> iterator { return { *this, iterator::EndTag() }; } - - auto operator += ( Column const& col ) -> Columns& { - m_columns.push_back( col ); - return *this; - } - auto operator + ( Column const& col ) -> Columns { - Columns combined = *this; - combined += col; - return combined; - } - - inline friend std::ostream& operator << ( std::ostream& os, Columns const& cols ) { - - bool first = true; - for( auto line : cols ) { - if( first ) - first = false; - else - os << "\n"; - os << line; - } - return os; - } - - auto toString() const -> std::string { - std::ostringstream oss; - oss << *this; - return oss.str(); - } - }; - - inline auto Column::operator + ( Column const& other ) -> Columns { - Columns cols; - cols += *this; - cols += other; - return cols; - } -}}} // namespace Catch::clara::TextFlow - -// ----------- end of #include from clara_textflow.hpp ----------- -// ........... back in clara.hpp - -#include -#include -#include - -#if !defined(CATCH_PLATFORM_WINDOWS) && ( defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) ) -#define CATCH_PLATFORM_WINDOWS -#endif - -namespace Catch { namespace clara { -namespace detail { - - // Traits for extracting arg and return type of lambdas (for single argument lambdas) - template - struct UnaryLambdaTraits : UnaryLambdaTraits {}; - - template - struct UnaryLambdaTraits { - static const bool isValid = false; - }; - - template - struct UnaryLambdaTraits { - static const bool isValid = true; - using ArgType = typename std::remove_const::type>::type;; - using ReturnType = ReturnT; - }; - - class TokenStream; - - // Transport for raw args (copied from main args, or supplied via init list for testing) - class Args { - friend TokenStream; - std::string m_exeName; - std::vector m_args; - - public: - Args( int argc, char *argv[] ) { - m_exeName = argv[0]; - for( int i = 1; i < argc; ++i ) - m_args.push_back( argv[i] ); - } - - Args( std::initializer_list args ) - : m_exeName( *args.begin() ), - m_args( args.begin()+1, args.end() ) - {} - - auto exeName() const -> std::string { - return m_exeName; - } - }; - - // Wraps a token coming from a token stream. These may not directly correspond to strings as a single string - // may encode an option + its argument if the : or = form is used - enum class TokenType { - Option, Argument - }; - struct Token { - TokenType type; - std::string token; - }; - - inline auto isOptPrefix( char c ) -> bool { - return c == '-' -#ifdef CATCH_PLATFORM_WINDOWS - || c == '/' -#endif - ; - } - - // Abstracts iterators into args as a stream of tokens, with option arguments uniformly handled - class TokenStream { - using Iterator = std::vector::const_iterator; - Iterator it; - Iterator itEnd; - std::vector m_tokenBuffer; - - void loadBuffer() { - m_tokenBuffer.resize( 0 ); - - // Skip any empty strings - while( it != itEnd && it->empty() ) - ++it; - - if( it != itEnd ) { - auto const &next = *it; - if( isOptPrefix( next[0] ) ) { - auto delimiterPos = next.find_first_of( " :=" ); - if( delimiterPos != std::string::npos ) { - m_tokenBuffer.push_back( { TokenType::Option, next.substr( 0, delimiterPos ) } ); - m_tokenBuffer.push_back( { TokenType::Argument, next.substr( delimiterPos + 1 ) } ); - } else { - if( next[1] != '-' && next.size() > 2 ) { - std::string opt = "- "; - for( size_t i = 1; i < next.size(); ++i ) { - opt[1] = next[i]; - m_tokenBuffer.push_back( { TokenType::Option, opt } ); - } - } else { - m_tokenBuffer.push_back( { TokenType::Option, next } ); - } - } - } else { - m_tokenBuffer.push_back( { TokenType::Argument, next } ); - } - } - } - - public: - explicit TokenStream( Args const &args ) : TokenStream( args.m_args.begin(), args.m_args.end() ) {} - - TokenStream( Iterator it, Iterator itEnd ) : it( it ), itEnd( itEnd ) { - loadBuffer(); - } - - explicit operator bool() const { - return !m_tokenBuffer.empty() || it != itEnd; - } - - auto count() const -> size_t { return m_tokenBuffer.size() + (itEnd - it); } - - auto operator*() const -> Token { - assert( !m_tokenBuffer.empty() ); - return m_tokenBuffer.front(); - } - - auto operator->() const -> Token const * { - assert( !m_tokenBuffer.empty() ); - return &m_tokenBuffer.front(); - } - - auto operator++() -> TokenStream & { - if( m_tokenBuffer.size() >= 2 ) { - m_tokenBuffer.erase( m_tokenBuffer.begin() ); - } else { - if( it != itEnd ) - ++it; - loadBuffer(); - } - return *this; - } - }; - - class ResultBase { - public: - enum Type { - Ok, LogicError, RuntimeError - }; - - protected: - ResultBase( Type type ) : m_type( type ) {} - virtual ~ResultBase() = default; - - virtual void enforceOk() const = 0; - - Type m_type; - }; - - template - class ResultValueBase : public ResultBase { - public: - auto value() const -> T const & { - enforceOk(); - return m_value; - } - - protected: - ResultValueBase( Type type ) : ResultBase( type ) {} - - ResultValueBase( ResultValueBase const &other ) : ResultBase( other ) { - if( m_type == ResultBase::Ok ) - new( &m_value ) T( other.m_value ); - } - - ResultValueBase( Type, T const &value ) : ResultBase( Ok ) { - new( &m_value ) T( value ); - } - - auto operator=( ResultValueBase const &other ) -> ResultValueBase & { - if( m_type == ResultBase::Ok ) - m_value.~T(); - ResultBase::operator=(other); - if( m_type == ResultBase::Ok ) - new( &m_value ) T( other.m_value ); - return *this; - } - - ~ResultValueBase() { - if( m_type == Ok ) - m_value.~T(); - } - - union { - T m_value; - }; - }; - - template<> - class ResultValueBase : public ResultBase { - protected: - using ResultBase::ResultBase; - }; - - template - class BasicResult : public ResultValueBase { - public: - template - explicit BasicResult( BasicResult const &other ) - : ResultValueBase( other.type() ), - m_errorMessage( other.errorMessage() ) - { - assert( type() != ResultBase::Ok ); - } - - template - static auto ok( U const &value ) -> BasicResult { return { ResultBase::Ok, value }; } - static auto ok() -> BasicResult { return { ResultBase::Ok }; } - static auto logicError( std::string const &message ) -> BasicResult { return { ResultBase::LogicError, message }; } - static auto runtimeError( std::string const &message ) -> BasicResult { return { ResultBase::RuntimeError, message }; } - - explicit operator bool() const { return m_type == ResultBase::Ok; } - auto type() const -> ResultBase::Type { return m_type; } - auto errorMessage() const -> std::string { return m_errorMessage; } - - protected: - virtual void enforceOk() const { - // !TBD: If no exceptions, std::terminate here or something - switch( m_type ) { - case ResultBase::LogicError: - throw std::logic_error( m_errorMessage ); - case ResultBase::RuntimeError: - throw std::runtime_error( m_errorMessage ); - case ResultBase::Ok: - break; - } - } - - std::string m_errorMessage; // Only populated if resultType is an error - - BasicResult( ResultBase::Type type, std::string const &message ) - : ResultValueBase(type), - m_errorMessage(message) - { - assert( m_type != ResultBase::Ok ); - } - - using ResultValueBase::ResultValueBase; - using ResultBase::m_type; - }; - - enum class ParseResultType { - Matched, NoMatch, ShortCircuitAll, ShortCircuitSame - }; - - class ParseState { - public: - - ParseState( ParseResultType type, TokenStream const &remainingTokens ) - : m_type(type), - m_remainingTokens( remainingTokens ) - {} - - auto type() const -> ParseResultType { return m_type; } - auto remainingTokens() const -> TokenStream { return m_remainingTokens; } - - private: - ParseResultType m_type; - TokenStream m_remainingTokens; - }; - - using Result = BasicResult; - using ParserResult = BasicResult; - using InternalParseResult = BasicResult; - - struct HelpColumns { - std::string left; - std::string right; - }; - - template - inline auto convertInto( std::string const &source, T& target ) -> ParserResult { - std::stringstream ss; - ss << source; - ss >> target; - if( ss.fail() ) - return ParserResult::runtimeError( "Unable to convert '" + source + "' to destination type" ); - else - return ParserResult::ok( ParseResultType::Matched ); - } - inline auto convertInto( std::string const &source, std::string& target ) -> ParserResult { - target = source; - return ParserResult::ok( ParseResultType::Matched ); - } - inline auto convertInto( std::string const &source, bool &target ) -> ParserResult { - std::string srcLC = source; - std::transform( srcLC.begin(), srcLC.end(), srcLC.begin(), []( char c ) { return static_cast( ::tolower(c) ); } ); - if (srcLC == "y" || srcLC == "1" || srcLC == "true" || srcLC == "yes" || srcLC == "on") - target = true; - else if (srcLC == "n" || srcLC == "0" || srcLC == "false" || srcLC == "no" || srcLC == "off") - target = false; - else - return ParserResult::runtimeError( "Expected a boolean value but did not recognise: '" + source + "'" ); - return ParserResult::ok( ParseResultType::Matched ); - } - - struct BoundRefBase { - BoundRefBase() = default; - BoundRefBase( BoundRefBase const & ) = delete; - BoundRefBase( BoundRefBase && ) = delete; - BoundRefBase &operator=( BoundRefBase const & ) = delete; - BoundRefBase &operator=( BoundRefBase && ) = delete; - - virtual ~BoundRefBase() = default; - - virtual auto isFlag() const -> bool = 0; - virtual auto isContainer() const -> bool { return false; } - virtual auto setValue( std::string const &arg ) -> ParserResult = 0; - virtual auto setFlag( bool flag ) -> ParserResult = 0; - }; - - struct BoundValueRefBase : BoundRefBase { - auto isFlag() const -> bool override { return false; } - - auto setFlag( bool ) -> ParserResult override { - return ParserResult::logicError( "Flags can only be set on boolean fields" ); - } - }; - - struct BoundFlagRefBase : BoundRefBase { - auto isFlag() const -> bool override { return true; } - - auto setValue( std::string const &arg ) -> ParserResult override { - bool flag; - auto result = convertInto( arg, flag ); - if( result ) - setFlag( flag ); - return result; - } - }; - - template - struct BoundRef : BoundValueRefBase { - T &m_ref; - - explicit BoundRef( T &ref ) : m_ref( ref ) {} - - auto setValue( std::string const &arg ) -> ParserResult override { - return convertInto( arg, m_ref ); - } - }; - - template - struct BoundRef> : BoundValueRefBase { - std::vector &m_ref; - - explicit BoundRef( std::vector &ref ) : m_ref( ref ) {} - - auto isContainer() const -> bool override { return true; } - - auto setValue( std::string const &arg ) -> ParserResult override { - T temp; - auto result = convertInto( arg, temp ); - if( result ) - m_ref.push_back( temp ); - return result; - } - }; - - struct BoundFlagRef : BoundFlagRefBase { - bool &m_ref; - - explicit BoundFlagRef( bool &ref ) : m_ref( ref ) {} - - auto setFlag( bool flag ) -> ParserResult override { - m_ref = flag; - return ParserResult::ok( ParseResultType::Matched ); - } - }; - - template - struct LambdaInvoker { - static_assert( std::is_same::value, "Lambda must return void or clara::ParserResult" ); - - template - static auto invoke( L const &lambda, ArgType const &arg ) -> ParserResult { - return lambda( arg ); - } - }; - - template<> - struct LambdaInvoker { - template - static auto invoke( L const &lambda, ArgType const &arg ) -> ParserResult { - lambda( arg ); - return ParserResult::ok( ParseResultType::Matched ); - } - }; - - template - inline auto invokeLambda( L const &lambda, std::string const &arg ) -> ParserResult { - ArgType temp; - auto result = convertInto( arg, temp ); - return !result - ? result - : LambdaInvoker::ReturnType>::invoke( lambda, temp ); - }; - - template - struct BoundLambda : BoundValueRefBase { - L m_lambda; - - static_assert( UnaryLambdaTraits::isValid, "Supplied lambda must take exactly one argument" ); - explicit BoundLambda( L const &lambda ) : m_lambda( lambda ) {} - - auto setValue( std::string const &arg ) -> ParserResult override { - return invokeLambda::ArgType>( m_lambda, arg ); - } - }; - - template - struct BoundFlagLambda : BoundFlagRefBase { - L m_lambda; - - static_assert( UnaryLambdaTraits::isValid, "Supplied lambda must take exactly one argument" ); - static_assert( std::is_same::ArgType, bool>::value, "flags must be boolean" ); - - explicit BoundFlagLambda( L const &lambda ) : m_lambda( lambda ) {} - - auto setFlag( bool flag ) -> ParserResult override { - return LambdaInvoker::ReturnType>::invoke( m_lambda, flag ); - } - }; - - enum class Optionality { Optional, Required }; - - struct Parser; - - class ParserBase { - public: - virtual ~ParserBase() = default; - virtual auto validate() const -> Result { return Result::ok(); } - virtual auto parse( std::string const& exeName, TokenStream const &tokens) const -> InternalParseResult = 0; - virtual auto cardinality() const -> size_t { return 1; } - - auto parse( Args const &args ) const -> InternalParseResult { - return parse( args.exeName(), TokenStream( args ) ); - } - }; - - template - class ComposableParserImpl : public ParserBase { - public: - template - auto operator|( T const &other ) const -> Parser; - }; - - // Common code and state for Args and Opts - template - class ParserRefImpl : public ComposableParserImpl { - protected: - Optionality m_optionality = Optionality::Optional; - std::shared_ptr m_ref; - std::string m_hint; - std::string m_description; - - explicit ParserRefImpl( std::shared_ptr const &ref ) : m_ref( ref ) {} - - public: - template - ParserRefImpl( T &ref, std::string const &hint ) - : m_ref( std::make_shared>( ref ) ), - m_hint( hint ) - {} - - template - ParserRefImpl( LambdaT const &ref, std::string const &hint ) - : m_ref( std::make_shared>( ref ) ), - m_hint(hint) - {} - - auto operator()( std::string const &description ) -> DerivedT & { - m_description = description; - return static_cast( *this ); - } - - auto optional() -> DerivedT & { - m_optionality = Optionality::Optional; - return static_cast( *this ); - }; - - auto required() -> DerivedT & { - m_optionality = Optionality::Required; - return static_cast( *this ); - }; - - auto isOptional() const -> bool { - return m_optionality == Optionality::Optional; - } - - auto cardinality() const -> size_t override { - if( m_ref->isContainer() ) - return 0; - else - return 1; - } - - auto hint() const -> std::string { return m_hint; } - }; - - class ExeName : public ComposableParserImpl { - std::shared_ptr m_name; - std::shared_ptr m_ref; - - template - static auto makeRef(LambdaT const &lambda) -> std::shared_ptr { - return std::make_shared>( lambda) ; - } - - public: - ExeName() : m_name( std::make_shared( "" ) ) {} - - explicit ExeName( std::string &ref ) : ExeName() { - m_ref = std::make_shared>( ref ); - } - - template - explicit ExeName( LambdaT const& lambda ) : ExeName() { - m_ref = std::make_shared>( lambda ); - } - - // The exe name is not parsed out of the normal tokens, but is handled specially - auto parse( std::string const&, TokenStream const &tokens ) const -> InternalParseResult override { - return InternalParseResult::ok( ParseState( ParseResultType::NoMatch, tokens ) ); - } - - auto name() const -> std::string { return *m_name; } - auto set( std::string const& newName ) -> ParserResult { - - auto lastSlash = newName.find_last_of( "\\/" ); - auto filename = ( lastSlash == std::string::npos ) - ? newName - : newName.substr( lastSlash+1 ); - - *m_name = filename; - if( m_ref ) - return m_ref->setValue( filename ); - else - return ParserResult::ok( ParseResultType::Matched ); - } - }; - - class Arg : public ParserRefImpl { - public: - using ParserRefImpl::ParserRefImpl; - - auto parse( std::string const &, TokenStream const &tokens ) const -> InternalParseResult override { - auto validationResult = validate(); - if( !validationResult ) - return InternalParseResult( validationResult ); - - auto remainingTokens = tokens; - auto const &token = *remainingTokens; - if( token.type != TokenType::Argument ) - return InternalParseResult::ok( ParseState( ParseResultType::NoMatch, remainingTokens ) ); - - auto result = m_ref->setValue( remainingTokens->token ); - if( !result ) - return InternalParseResult( result ); - else - return InternalParseResult::ok( ParseState( ParseResultType::Matched, ++remainingTokens ) ); - } - }; - - inline auto normaliseOpt( std::string const &optName ) -> std::string { -#ifdef CATCH_PLATFORM_WINDOWS - if( optName[0] == '/' ) - return "-" + optName.substr( 1 ); - else -#endif - return optName; - } - - class Opt : public ParserRefImpl { - protected: - std::vector m_optNames; - - public: - template - explicit Opt( LambdaT const &ref ) : ParserRefImpl( std::make_shared>( ref ) ) {} - - explicit Opt( bool &ref ) : ParserRefImpl( std::make_shared( ref ) ) {} - - template - Opt( LambdaT const &ref, std::string const &hint ) : ParserRefImpl( ref, hint ) {} - - template - Opt( T &ref, std::string const &hint ) : ParserRefImpl( ref, hint ) {} - - auto operator[]( std::string const &optName ) -> Opt & { - m_optNames.push_back( optName ); - return *this; - } - - auto getHelpColumns() const -> std::vector { - std::ostringstream oss; - bool first = true; - for( auto const &opt : m_optNames ) { - if (first) - first = false; - else - oss << ", "; - oss << opt; - } - if( !m_hint.empty() ) - oss << " <" << m_hint << ">"; - return { { oss.str(), m_description } }; - } - - auto isMatch( std::string const &optToken ) const -> bool { - auto normalisedToken = normaliseOpt( optToken ); - for( auto const &name : m_optNames ) { - if( normaliseOpt( name ) == normalisedToken ) - return true; - } - return false; - } - - using ParserBase::parse; - - auto parse( std::string const&, TokenStream const &tokens ) const -> InternalParseResult override { - auto validationResult = validate(); - if( !validationResult ) - return InternalParseResult( validationResult ); - - auto remainingTokens = tokens; - if( remainingTokens && remainingTokens->type == TokenType::Option ) { - auto const &token = *remainingTokens; - if( isMatch(token.token ) ) { - if( m_ref->isFlag() ) { - auto result = m_ref->setFlag( true ); - if( !result ) - return InternalParseResult( result ); - if( result.value() == ParseResultType::ShortCircuitAll ) - return InternalParseResult::ok( ParseState( result.value(), remainingTokens ) ); - } else { - ++remainingTokens; - if( !remainingTokens ) - return InternalParseResult::runtimeError( "Expected argument following " + token.token ); - auto const &argToken = *remainingTokens; - if( argToken.type != TokenType::Argument ) - return InternalParseResult::runtimeError( "Expected argument following " + token.token ); - auto result = m_ref->setValue( argToken.token ); - if( !result ) - return InternalParseResult( result ); - if( result.value() == ParseResultType::ShortCircuitAll ) - return InternalParseResult::ok( ParseState( result.value(), remainingTokens ) ); - } - return InternalParseResult::ok( ParseState( ParseResultType::Matched, ++remainingTokens ) ); - } - } - return InternalParseResult::ok( ParseState( ParseResultType::NoMatch, remainingTokens ) ); - } - - auto validate() const -> Result override { - if( m_optNames.empty() ) - return Result::logicError( "No options supplied to Opt" ); - for( auto const &name : m_optNames ) { - if( name.empty() ) - return Result::logicError( "Option name cannot be empty" ); -#ifdef CATCH_PLATFORM_WINDOWS - if( name[0] != '-' && name[0] != '/' ) - return Result::logicError( "Option name must begin with '-' or '/'" ); -#else - if( name[0] != '-' ) - return Result::logicError( "Option name must begin with '-'" ); -#endif - } - return ParserRefImpl::validate(); - } - }; - - struct Help : Opt { - Help( bool &showHelpFlag ) - : Opt([&]( bool flag ) { - showHelpFlag = flag; - return ParserResult::ok( ParseResultType::ShortCircuitAll ); - }) - { - static_cast( *this ) - ("display usage information") - ["-?"]["-h"]["--help"] - .optional(); - } - }; - - struct Parser : ParserBase { - - mutable ExeName m_exeName; - std::vector m_options; - std::vector m_args; - - auto operator|=( ExeName const &exeName ) -> Parser & { - m_exeName = exeName; - return *this; - } - - auto operator|=( Arg const &arg ) -> Parser & { - m_args.push_back(arg); - return *this; - } - - auto operator|=( Opt const &opt ) -> Parser & { - m_options.push_back(opt); - return *this; - } - - auto operator|=( Parser const &other ) -> Parser & { - m_options.insert(m_options.end(), other.m_options.begin(), other.m_options.end()); - m_args.insert(m_args.end(), other.m_args.begin(), other.m_args.end()); - return *this; - } - - template - auto operator|( T const &other ) const -> Parser { - return Parser( *this ) |= other; - } - - auto getHelpColumns() const -> std::vector { - std::vector cols; - for (auto const &o : m_options) { - auto childCols = o.getHelpColumns(); - cols.insert( cols.end(), childCols.begin(), childCols.end() ); - } - return cols; - } - - void writeToStream( std::ostream &os ) const { - if (!m_exeName.name().empty()) { - os << "usage:\n" << " " << m_exeName.name() << " "; - bool required = true, first = true; - for( auto const &arg : m_args ) { - if (first) - first = false; - else - os << " "; - if( arg.isOptional() && required ) { - os << "["; - required = false; - } - os << "<" << arg.hint() << ">"; - if( arg.cardinality() == 0 ) - os << " ... "; - } - if( !required ) - os << "]"; - if( !m_options.empty() ) - os << " options"; - os << "\n\nwhere options are:" << std::endl; - } - - auto rows = getHelpColumns(); - size_t consoleWidth = CATCH_CLARA_CONFIG_CONSOLE_WIDTH; - size_t optWidth = 0; - for( auto const &cols : rows ) - optWidth = (std::max)(optWidth, cols.left.size() + 2); - - for( auto const &cols : rows ) { - auto row = - TextFlow::Column( cols.left ).width( optWidth ).indent( 2 ) + - TextFlow::Spacer(4) + - TextFlow::Column( cols.right ).width( consoleWidth - 7 - optWidth ); - os << row << std::endl; - } - } - - friend auto operator<<( std::ostream &os, Parser const &parser ) -> std::ostream& { - parser.writeToStream( os ); - return os; - } - - auto validate() const -> Result override { - for( auto const &opt : m_options ) { - auto result = opt.validate(); - if( !result ) - return result; - } - for( auto const &arg : m_args ) { - auto result = arg.validate(); - if( !result ) - return result; - } - return Result::ok(); - } - - using ParserBase::parse; - - auto parse( std::string const& exeName, TokenStream const &tokens ) const -> InternalParseResult override { - - struct ParserInfo { - ParserBase const* parser = nullptr; - size_t count = 0; - }; - const size_t totalParsers = m_options.size() + m_args.size(); - assert( totalParsers < 512 ); - // ParserInfo parseInfos[totalParsers]; // <-- this is what we really want to do - ParserInfo parseInfos[512]; - - { - size_t i = 0; - for (auto const &opt : m_options) parseInfos[i++].parser = &opt; - for (auto const &arg : m_args) parseInfos[i++].parser = &arg; - } - - m_exeName.set( exeName ); - - auto result = InternalParseResult::ok( ParseState( ParseResultType::NoMatch, tokens ) ); - while( result.value().remainingTokens() ) { - bool tokenParsed = false; - - for( size_t i = 0; i < totalParsers; ++i ) { - auto& parseInfo = parseInfos[i]; - if( parseInfo.parser->cardinality() == 0 || parseInfo.count < parseInfo.parser->cardinality() ) { - result = parseInfo.parser->parse(exeName, result.value().remainingTokens()); - if (!result) - return result; - if (result.value().type() != ParseResultType::NoMatch) { - tokenParsed = true; - ++parseInfo.count; - break; - } - } - } - - if( result.value().type() == ParseResultType::ShortCircuitAll ) - return result; - if( !tokenParsed ) - return InternalParseResult::runtimeError( "Unrecognised token: " + result.value().remainingTokens()->token ); - } - // !TBD Check missing required options - return result; - } - }; - - template - template - auto ComposableParserImpl::operator|( T const &other ) const -> Parser { - return Parser() | static_cast( *this ) | other; - } -} // namespace detail - -// A Combined parser -using detail::Parser; - -// A parser for options -using detail::Opt; - -// A parser for arguments -using detail::Arg; - -// Wrapper for argc, argv from main() -using detail::Args; - -// Specifies the name of the executable -using detail::ExeName; - -// Convenience wrapper for option parser that specifies the help option -using detail::Help; - -// enum of result types from a parse -using detail::ParseResultType; - -// Result type for parser operation -using detail::ParserResult; - -}} // namespace Catch::clara - -// end clara.hpp -#ifdef __clang__ -#pragma clang diagnostic pop -#endif - -// Restore Clara's value for console width, if present -#ifdef CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH -#define CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH -#undef CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH -#endif - -// end catch_clara.h -namespace Catch { - - clara::Parser makeCommandLineParser( ConfigData& config ); - -} // end namespace Catch - -// end catch_commandline.h -#include -#include - -namespace Catch { - - clara::Parser makeCommandLineParser( ConfigData& config ) { - - using namespace clara; - - auto const setWarning = [&]( std::string const& warning ) { - if( warning != "NoAssertions" ) - return ParserResult::runtimeError( "Unrecognised warning: '" + warning + "'" ); - config.warnings = static_cast( config.warnings | WarnAbout::NoAssertions ); - return ParserResult::ok( ParseResultType::Matched ); - }; - auto const loadTestNamesFromFile = [&]( std::string const& filename ) { - std::ifstream f( filename.c_str() ); - if( !f.is_open() ) - return ParserResult::runtimeError( "Unable to load input file: '" + filename + "'" ); - - std::string line; - while( std::getline( f, line ) ) { - line = trim(line); - if( !line.empty() && !startsWith( line, '#' ) ) { - if( !startsWith( line, '"' ) ) - line = '"' + line + '"'; - config.testsOrTags.push_back( line + ',' ); - } - } - return ParserResult::ok( ParseResultType::Matched ); - }; - auto const setTestOrder = [&]( std::string const& order ) { - if( startsWith( "declared", order ) ) - config.runOrder = RunTests::InDeclarationOrder; - else if( startsWith( "lexical", order ) ) - config.runOrder = RunTests::InLexicographicalOrder; - else if( startsWith( "random", order ) ) - config.runOrder = RunTests::InRandomOrder; - else - return clara::ParserResult::runtimeError( "Unrecognised ordering: '" + order + "'" ); - return ParserResult::ok( ParseResultType::Matched ); - }; - auto const setRngSeed = [&]( std::string const& seed ) { - if( seed != "time" ) - return clara::detail::convertInto( seed, config.rngSeed ); - config.rngSeed = static_cast( std::time(nullptr) ); - return ParserResult::ok( ParseResultType::Matched ); - }; - auto const setColourUsage = [&]( std::string const& useColour ) { - auto mode = toLower( useColour ); - - if( mode == "yes" ) - config.useColour = UseColour::Yes; - else if( mode == "no" ) - config.useColour = UseColour::No; - else if( mode == "auto" ) - config.useColour = UseColour::Auto; - else - return ParserResult::runtimeError( "colour mode must be one of: auto, yes or no. '" + useColour + "' not recognised" ); - return ParserResult::ok( ParseResultType::Matched ); - }; - auto const setWaitForKeypress = [&]( std::string const& keypress ) { - auto keypressLc = toLower( keypress ); - if( keypressLc == "start" ) - config.waitForKeypress = WaitForKeypress::BeforeStart; - else if( keypressLc == "exit" ) - config.waitForKeypress = WaitForKeypress::BeforeExit; - else if( keypressLc == "both" ) - config.waitForKeypress = WaitForKeypress::BeforeStartAndExit; - else - return ParserResult::runtimeError( "keypress argument must be one of: start, exit or both. '" + keypress + "' not recognised" ); - return ParserResult::ok( ParseResultType::Matched ); - }; - auto const setVerbosity = [&]( std::string const& verbosity ) { - auto lcVerbosity = toLower( verbosity ); - if( lcVerbosity == "quiet" ) - config.verbosity = Verbosity::Quiet; - else if( lcVerbosity == "normal" ) - config.verbosity = Verbosity::Normal; - else if( lcVerbosity == "high" ) - config.verbosity = Verbosity::High; - else - return ParserResult::runtimeError( "Unrecognised verbosity, '" + verbosity + "'" ); - return ParserResult::ok( ParseResultType::Matched ); - }; - - auto cli - = ExeName( config.processName ) - | Help( config.showHelp ) - | Opt( config.listTests ) - ["-l"]["--list-tests"] - ( "list all/matching test cases" ) - | Opt( config.listTags ) - ["-t"]["--list-tags"] - ( "list all/matching tags" ) - | Opt( config.showSuccessfulTests ) - ["-s"]["--success"] - ( "include successful tests in output" ) - | Opt( config.shouldDebugBreak ) - ["-b"]["--break"] - ( "break into debugger on failure" ) - | Opt( config.noThrow ) - ["-e"]["--nothrow"] - ( "skip exception tests" ) - | Opt( config.showInvisibles ) - ["-i"]["--invisibles"] - ( "show invisibles (tabs, newlines)" ) - | Opt( config.outputFilename, "filename" ) - ["-o"]["--out"] - ( "output filename" ) - | Opt( config.reporterNames, "name" ) - ["-r"]["--reporter"] - ( "reporter to use (defaults to console)" ) - | Opt( config.name, "name" ) - ["-n"]["--name"] - ( "suite name" ) - | Opt( [&]( bool ){ config.abortAfter = 1; } ) - ["-a"]["--abort"] - ( "abort at first failure" ) - | Opt( [&]( int x ){ config.abortAfter = x; }, "no. failures" ) - ["-x"]["--abortx"] - ( "abort after x failures" ) - | Opt( setWarning, "warning name" ) - ["-w"]["--warn"] - ( "enable warnings" ) - | Opt( [&]( bool flag ) { config.showDurations = flag ? ShowDurations::Always : ShowDurations::Never; }, "yes|no" ) - ["-d"]["--durations"] - ( "show test durations" ) - | Opt( loadTestNamesFromFile, "filename" ) - ["-f"]["--input-file"] - ( "load test names to run from a file" ) - | Opt( config.filenamesAsTags ) - ["-#"]["--filenames-as-tags"] - ( "adds a tag for the filename" ) - | Opt( config.sectionsToRun, "section name" ) - ["-c"]["--section"] - ( "specify section to run" ) - | Opt( setVerbosity, "quiet|normal|high" ) - ["-v"]["--verbosity"] - ( "set output verbosity" ) - | Opt( config.listTestNamesOnly ) - ["--list-test-names-only"] - ( "list all/matching test cases names only" ) - | Opt( config.listReporters ) - ["--list-reporters"] - ( "list all reporters" ) - | Opt( setTestOrder, "decl|lex|rand" ) - ["--order"] - ( "test case order (defaults to decl)" ) - | Opt( setRngSeed, "'time'|number" ) - ["--rng-seed"] - ( "set a specific seed for random numbers" ) - | Opt( setColourUsage, "yes|no" ) - ["--use-colour"] - ( "should output be colourised" ) - | Opt( config.libIdentify ) - ["--libidentify"] - ( "report name and version according to libidentify standard" ) - | Opt( setWaitForKeypress, "start|exit|both" ) - ["--wait-for-keypress"] - ( "waits for a keypress before exiting" ) - | Opt( config.benchmarkResolutionMultiple, "multiplier" ) - ["--benchmark-resolution-multiple"] - ( "multiple of clock resolution to run benchmarks" ) - - | Arg( config.testsOrTags, "test name|pattern|tags" ) - ( "which test or tests to use" ); - - return cli; - } - -} // end namespace Catch -// end catch_commandline.cpp -// start catch_common.cpp - -#include -#include - -namespace Catch { - - SourceLineInfo::SourceLineInfo( char const* _file, std::size_t _line ) noexcept - : file( _file ), - line( _line ) - {} - bool SourceLineInfo::empty() const noexcept { - return file[0] == '\0'; - } - bool SourceLineInfo::operator == ( SourceLineInfo const& other ) const noexcept { - return line == other.line && (file == other.file || std::strcmp(file, other.file) == 0); - } - bool SourceLineInfo::operator < ( SourceLineInfo const& other ) const noexcept { - return line < other.line || ( line == other.line && (std::strcmp(file, other.file) < 0)); - } - - 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; - } - - bool isTrue( bool value ){ return value; } - bool alwaysTrue() { return true; } - bool alwaysFalse() { return false; } - - std::string StreamEndStop::operator+() const { - return std::string(); - } - - NonCopyable::NonCopyable() = default; - NonCopyable::~NonCopyable() = default; - -} -// end catch_common.cpp -// start catch_config.cpp - -namespace Catch { - - Config::Config( ConfigData const& data ) - : m_data( data ), - m_stream( openStream() ) - { - if( !data.testsOrTags.empty() ) { - TestSpecParser parser( ITagAliasRegistry::get() ); - for( auto const& testOrTags : data.testsOrTags ) - parser.parse( testOrTags ); - m_testSpec = parser.testSpec(); - } - } - - std::string const& Config::getFilename() const { - return m_data.outputFilename ; - } - - bool Config::listTests() const { return m_data.listTests; } - bool Config::listTestNamesOnly() const { return m_data.listTestNamesOnly; } - bool Config::listTags() const { return m_data.listTags; } - bool Config::listReporters() const { return m_data.listReporters; } - - std::string Config::getProcessName() const { return m_data.processName; } - - std::vector const& Config::getReporterNames() const { return m_data.reporterNames; } - std::vector const& Config::getSectionsToRun() const { return m_data.sectionsToRun; } - - TestSpec const& Config::testSpec() const { return m_testSpec; } - - bool Config::showHelp() const { return m_data.showHelp; } - - // IConfig interface - bool Config::allowThrows() const { return !m_data.noThrow; } - std::ostream& Config::stream() const { return m_stream->stream(); } - std::string Config::name() const { return m_data.name.empty() ? m_data.processName : m_data.name; } - bool Config::includeSuccessfulResults() const { return m_data.showSuccessfulTests; } - bool Config::warnAboutMissingAssertions() const { return m_data.warnings & WarnAbout::NoAssertions; } - ShowDurations::OrNot Config::showDurations() const { return m_data.showDurations; } - RunTests::InWhatOrder Config::runOrder() const { return m_data.runOrder; } - unsigned int Config::rngSeed() const { return m_data.rngSeed; } - int Config::benchmarkResolutionMultiple() const { return m_data.benchmarkResolutionMultiple; } - UseColour::YesOrNo Config::useColour() const { return m_data.useColour; } - bool Config::shouldDebugBreak() const { return m_data.shouldDebugBreak; } - int Config::abortAfter() const { return m_data.abortAfter; } - bool Config::showInvisibles() const { return m_data.showInvisibles; } - Verbosity Config::verbosity() const { return m_data.verbosity; } - - IStream const* Config::openStream() { - if( m_data.outputFilename.empty() ) - return new CoutStream(); - else if( m_data.outputFilename[0] == '%' ) { - if( m_data.outputFilename == "%debug" ) - return new DebugOutStream(); - else - CATCH_ERROR( "Unrecognised stream: '" << m_data.outputFilename << "'" ); - } - else - return new FileStream( m_data.outputFilename ); - } - -} // end namespace Catch -// end catch_config.cpp -// start catch_console_colour.cpp - -#if defined(__clang__) -# pragma clang diagnostic push -# pragma clang diagnostic ignored "-Wexit-time-destructors" -#endif - -// start catch_errno_guard.h - -namespace Catch { - - class ErrnoGuard { - public: - ErrnoGuard(); - ~ErrnoGuard(); - private: - int m_oldErrno; - }; - -} - -// end catch_errno_guard.h -// start catch_windows_h_proxy.h - - -#if defined(CATCH_PLATFORM_WINDOWS) - -#if !defined(NOMINMAX) && !defined(CATCH_CONFIG_NO_NOMINMAX) -# define CATCH_DEFINED_NOMINMAX +#ifdef CATCH_DEFINES_NOMINMAX # define NOMINMAX #endif -#if !defined(WIN32_LEAN_AND_MEAN) && !defined(CATCH_CONFIG_NO_WIN32_LEAN_AND_MEAN) -# define CATCH_DEFINED_WIN32_LEAN_AND_MEAN +#ifdef CATCH_DEFINES_WIN32_LEAN_AND_MEAN # define WIN32_LEAN_AND_MEAN #endif @@ -5909,21 +6381,1471 @@ namespace Catch { #include #endif -#ifdef CATCH_DEFINED_NOMINMAX +#ifdef CATCH_DEFINES_NOMINMAX # undef NOMINMAX #endif -#ifdef CATCH_DEFINED_WIN32_LEAN_AND_MEAN +#ifdef CATCH_DEFINES_WIN32_LEAN_AND_MEAN # undef WIN32_LEAN_AND_MEAN #endif -#endif // defined(CATCH_PLATFORM_WINDOWS) -// end catch_windows_h_proxy.h +# if !defined ( CATCH_CONFIG_WINDOWS_SEH ) + +namespace Catch { + struct FatalConditionHandler { + void reset() {} + }; +} + +# else // CATCH_CONFIG_WINDOWS_SEH is defined + +namespace Catch { + + struct SignalDefs { DWORD id; const char* name; }; + extern SignalDefs signalDefs[]; + // There is no 1-1 mapping between signals and windows exceptions. + // Windows can easily distinguish between SO and SigSegV, + // but SigInt, SigTerm, etc are handled differently. + SignalDefs signalDefs[] = { + { EXCEPTION_ILLEGAL_INSTRUCTION, "SIGILL - Illegal instruction signal" }, + { EXCEPTION_STACK_OVERFLOW, "SIGSEGV - Stack overflow" }, + { EXCEPTION_ACCESS_VIOLATION, "SIGSEGV - Segmentation violation signal" }, + { EXCEPTION_INT_DIVIDE_BY_ZERO, "Divide by zero error" }, + }; + + struct FatalConditionHandler { + + static LONG CALLBACK handleVectoredException(PEXCEPTION_POINTERS ExceptionInfo) { + for (int i = 0; i < sizeof(signalDefs) / sizeof(SignalDefs); ++i) { + if (ExceptionInfo->ExceptionRecord->ExceptionCode == signalDefs[i].id) { + reportFatal(signalDefs[i].name); + } + } + // If its not an exception we care about, pass it along. + // This stops us from eating debugger breaks etc. + return EXCEPTION_CONTINUE_SEARCH; + } + + FatalConditionHandler() { + isSet = true; + // 32k seems enough for Catch to handle stack overflow, + // but the value was found experimentally, so there is no strong guarantee + guaranteeSize = 32 * 1024; + exceptionHandlerHandle = CATCH_NULL; + // Register as first handler in current chain + exceptionHandlerHandle = AddVectoredExceptionHandler(1, handleVectoredException); + // Pass in guarantee size to be filled + SetThreadStackGuarantee(&guaranteeSize); + } + + static void reset() { + if (isSet) { + // Unregister handler and restore the old guarantee + RemoveVectoredExceptionHandler(exceptionHandlerHandle); + SetThreadStackGuarantee(&guaranteeSize); + exceptionHandlerHandle = CATCH_NULL; + isSet = false; + } + } + + ~FatalConditionHandler() { + reset(); + } + private: + static bool isSet; + static ULONG guaranteeSize; + static PVOID exceptionHandlerHandle; + }; + + bool FatalConditionHandler::isSet = false; + ULONG FatalConditionHandler::guaranteeSize = 0; + PVOID FatalConditionHandler::exceptionHandlerHandle = CATCH_NULL; + +} // namespace Catch + +# endif // CATCH_CONFIG_WINDOWS_SEH + +#else // Not Windows - assumed to be POSIX compatible ////////////////////////// + +# if !defined(CATCH_CONFIG_POSIX_SIGNALS) + +namespace Catch { + struct FatalConditionHandler { + void reset() {} + }; +} + +# else // CATCH_CONFIG_POSIX_SIGNALS is defined + +#include + +namespace Catch { + + struct SignalDefs { + int id; + const char* name; + }; + extern SignalDefs signalDefs[]; + SignalDefs signalDefs[] = { + { SIGINT, "SIGINT - Terminal interrupt signal" }, + { SIGILL, "SIGILL - Illegal instruction signal" }, + { SIGFPE, "SIGFPE - Floating point error signal" }, + { SIGSEGV, "SIGSEGV - Segmentation violation signal" }, + { SIGTERM, "SIGTERM - Termination request signal" }, + { SIGABRT, "SIGABRT - Abort (abnormal termination) signal" } + }; + + struct FatalConditionHandler { + + static bool isSet; + static struct sigaction oldSigActions [sizeof(signalDefs)/sizeof(SignalDefs)]; + static stack_t oldSigStack; + static char altStackMem[SIGSTKSZ]; + + static void handleSignal( int sig ) { + std::string name = ""; + for (std::size_t i = 0; i < sizeof(signalDefs) / sizeof(SignalDefs); ++i) { + SignalDefs &def = signalDefs[i]; + if (sig == def.id) { + name = def.name; + break; + } + } + reset(); + reportFatal(name); + raise( sig ); + } + + FatalConditionHandler() { + isSet = true; + stack_t sigStack; + sigStack.ss_sp = altStackMem; + sigStack.ss_size = SIGSTKSZ; + sigStack.ss_flags = 0; + sigaltstack(&sigStack, &oldSigStack); + struct sigaction sa = { 0 }; + + sa.sa_handler = handleSignal; + sa.sa_flags = SA_ONSTACK; + for (std::size_t i = 0; i < sizeof(signalDefs)/sizeof(SignalDefs); ++i) { + sigaction(signalDefs[i].id, &sa, &oldSigActions[i]); + } + } + + ~FatalConditionHandler() { + reset(); + } + static void reset() { + if( isSet ) { + // Set signals back to previous values -- hopefully nobody overwrote them in the meantime + for( std::size_t i = 0; i < sizeof(signalDefs)/sizeof(SignalDefs); ++i ) { + sigaction(signalDefs[i].id, &oldSigActions[i], CATCH_NULL); + } + // Return the old stack + sigaltstack(&oldSigStack, CATCH_NULL); + isSet = false; + } + } + }; + + bool FatalConditionHandler::isSet = false; + struct sigaction FatalConditionHandler::oldSigActions[sizeof(signalDefs)/sizeof(SignalDefs)] = {}; + stack_t FatalConditionHandler::oldSigStack = {}; + char FatalConditionHandler::altStackMem[SIGSTKSZ] = {}; + +} // namespace Catch + +# endif // CATCH_CONFIG_POSIX_SIGNALS + +#endif // not Windows + +#include +#include + +namespace Catch { + + class StreamRedirect { + + public: + StreamRedirect( std::ostream& stream, std::string& targetString ) + : m_stream( stream ), + m_prevBuf( stream.rdbuf() ), + m_targetString( targetString ) + { + stream.rdbuf( m_oss.rdbuf() ); + } + + ~StreamRedirect() { + m_targetString += m_oss.str(); + m_stream.rdbuf( m_prevBuf ); + } + + private: + std::ostream& m_stream; + std::streambuf* m_prevBuf; + std::ostringstream m_oss; + std::string& m_targetString; + }; + + // StdErr has two constituent streams in C++, std::cerr and std::clog + // This means that we need to redirect 2 streams into 1 to keep proper + // order of writes and cannot use StreamRedirect on its own + class StdErrRedirect { + public: + StdErrRedirect(std::string& targetString) + :m_cerrBuf( cerr().rdbuf() ), m_clogBuf(clog().rdbuf()), + m_targetString(targetString){ + cerr().rdbuf(m_oss.rdbuf()); + clog().rdbuf(m_oss.rdbuf()); + } + ~StdErrRedirect() { + m_targetString += m_oss.str(); + cerr().rdbuf(m_cerrBuf); + clog().rdbuf(m_clogBuf); + } + private: + std::streambuf* m_cerrBuf; + std::streambuf* m_clogBuf; + std::ostringstream m_oss; + std::string& m_targetString; + }; + + /////////////////////////////////////////////////////////////////////////// + + class RunContext : public IResultCapture, public IRunner { + + RunContext( RunContext const& ); + void operator =( RunContext const& ); + + public: + + explicit RunContext( Ptr const& _config, Ptr const& reporter ) + : m_runInfo( _config->name() ), + m_context( getCurrentMutableContext() ), + m_activeTestCase( CATCH_NULL ), + m_config( _config ), + m_reporter( reporter ), + m_shouldReportUnexpected ( true ) + { + m_context.setRunner( this ); + m_context.setConfig( m_config ); + m_context.setResultCapture( this ); + m_reporter->testRunStarting( m_runInfo ); + } + + virtual ~RunContext() { + m_reporter->testRunEnded( TestRunStats( m_runInfo, m_totals, aborting() ) ); + } + + void testGroupStarting( std::string const& testSpec, std::size_t groupIndex, std::size_t groupsCount ) { + m_reporter->testGroupStarting( GroupInfo( testSpec, groupIndex, groupsCount ) ); + } + void testGroupEnded( std::string const& testSpec, Totals const& totals, std::size_t groupIndex, std::size_t groupsCount ) { + m_reporter->testGroupEnded( TestGroupStats( GroupInfo( testSpec, groupIndex, groupsCount ), totals, aborting() ) ); + } + + Totals runTest( TestCase const& testCase ) { + Totals prevTotals = m_totals; + + std::string redirectedCout; + std::string redirectedCerr; + + TestCaseInfo testInfo = testCase.getTestCaseInfo(); + + m_reporter->testCaseStarting( testInfo ); + + m_activeTestCase = &testCase; + + do { + ITracker& rootTracker = m_trackerContext.startRun(); + assert( rootTracker.isSectionTracker() ); + static_cast( rootTracker ).addInitialFilters( m_config->getSectionsToRun() ); + do { + m_trackerContext.startCycle(); + m_testCaseTracker = &SectionTracker::acquire( m_trackerContext, TestCaseTracking::NameAndLocation( testInfo.name, testInfo.lineInfo ) ); + runCurrentTest( redirectedCout, redirectedCerr ); + } + while( !m_testCaseTracker->isSuccessfullyCompleted() && !aborting() ); + } + // !TBD: deprecated - this will be replaced by indexed trackers + while( getCurrentContext().advanceGeneratorsForCurrentTest() && !aborting() ); + + Totals deltaTotals = m_totals.delta( prevTotals ); + if( testInfo.expectedToFail() && deltaTotals.testCases.passed > 0 ) { + deltaTotals.assertions.failed++; + deltaTotals.testCases.passed--; + deltaTotals.testCases.failed++; + } + m_totals.testCases += deltaTotals.testCases; + m_reporter->testCaseEnded( TestCaseStats( testInfo, + deltaTotals, + redirectedCout, + redirectedCerr, + aborting() ) ); + + m_activeTestCase = CATCH_NULL; + m_testCaseTracker = CATCH_NULL; + + return deltaTotals; + } + + Ptr config() const { + return m_config; + } + + private: // IResultCapture + + virtual void assertionEnded( AssertionResult const& result ) { + if( result.getResultType() == ResultWas::Ok ) { + m_totals.assertions.passed++; + } + else if( !result.isOk() ) { + m_totals.assertions.failed++; + } + + // We have no use for the return value (whether messages should be cleared), because messages were made scoped + // and should be let to clear themselves out. + static_cast(m_reporter->assertionEnded(AssertionStats(result, m_messages, m_totals))); + + // Reset working state + m_lastAssertionInfo = AssertionInfo( "", m_lastAssertionInfo.lineInfo, "{Unknown expression after the reported line}" , m_lastAssertionInfo.resultDisposition ); + m_lastResult = result; + } + + virtual bool lastAssertionPassed() + { + return m_totals.assertions.passed == (m_prevPassed + 1); + } + + virtual void assertionPassed() + { + m_totals.assertions.passed++; + m_lastAssertionInfo.capturedExpression = "{Unknown expression after the reported line}"; + m_lastAssertionInfo.macroName = ""; + } + + virtual void assertionRun() + { + m_prevPassed = m_totals.assertions.passed; + } + + virtual bool sectionStarted ( + SectionInfo const& sectionInfo, + Counts& assertions + ) + { + ITracker& sectionTracker = SectionTracker::acquire( m_trackerContext, TestCaseTracking::NameAndLocation( sectionInfo.name, sectionInfo.lineInfo ) ); + if( !sectionTracker.isOpen() ) + return false; + m_activeSections.push_back( §ionTracker ); + + m_lastAssertionInfo.lineInfo = sectionInfo.lineInfo; + + m_reporter->sectionStarting( sectionInfo ); + + assertions = m_totals.assertions; + + return true; + } + bool testForMissingAssertions( Counts& assertions ) { + if( assertions.total() != 0 ) + return false; + if( !m_config->warnAboutMissingAssertions() ) + return false; + if( m_trackerContext.currentTracker().hasChildren() ) + return false; + m_totals.assertions.failed++; + assertions.failed++; + return true; + } + + virtual void sectionEnded( SectionEndInfo const& endInfo ) { + Counts assertions = m_totals.assertions - endInfo.prevAssertions; + bool missingAssertions = testForMissingAssertions( assertions ); + + if( !m_activeSections.empty() ) { + m_activeSections.back()->close(); + m_activeSections.pop_back(); + } + + m_reporter->sectionEnded( SectionStats( endInfo.sectionInfo, assertions, endInfo.durationInSeconds, missingAssertions ) ); + m_messages.clear(); + } + + virtual void sectionEndedEarly( SectionEndInfo const& endInfo ) { + if( m_unfinishedSections.empty() ) + m_activeSections.back()->fail(); + else + m_activeSections.back()->close(); + m_activeSections.pop_back(); + + m_unfinishedSections.push_back( endInfo ); + } + + virtual void pushScopedMessage( MessageInfo const& message ) { + m_messages.push_back( message ); + } + + virtual void popScopedMessage( MessageInfo const& message ) { + m_messages.erase( std::remove( m_messages.begin(), m_messages.end(), message ), m_messages.end() ); + } + + virtual std::string getCurrentTestName() const { + return m_activeTestCase + ? m_activeTestCase->getTestCaseInfo().name + : std::string(); + } + + virtual const AssertionResult* getLastResult() const { + return &m_lastResult; + } + + virtual void exceptionEarlyReported() { + m_shouldReportUnexpected = false; + } + + virtual void handleFatalErrorCondition( std::string const& message ) { + // Don't rebuild the result -- the stringification itself can cause more fatal errors + // Instead, fake a result data. + AssertionResultData tempResult; + tempResult.resultType = ResultWas::FatalErrorCondition; + tempResult.message = message; + AssertionResult result(m_lastAssertionInfo, tempResult); + + getResultCapture().assertionEnded(result); + + handleUnfinishedSections(); + + // Recreate section for test case (as we will lose the one that was in scope) + TestCaseInfo const& testCaseInfo = m_activeTestCase->getTestCaseInfo(); + SectionInfo testCaseSection( testCaseInfo.lineInfo, testCaseInfo.name, testCaseInfo.description ); + + Counts assertions; + assertions.failed = 1; + SectionStats testCaseSectionStats( testCaseSection, assertions, 0, false ); + m_reporter->sectionEnded( testCaseSectionStats ); + + TestCaseInfo testInfo = m_activeTestCase->getTestCaseInfo(); + + Totals deltaTotals; + deltaTotals.testCases.failed = 1; + deltaTotals.assertions.failed = 1; + m_reporter->testCaseEnded( TestCaseStats( testInfo, + deltaTotals, + std::string(), + std::string(), + false ) ); + m_totals.testCases.failed++; + testGroupEnded( std::string(), m_totals, 1, 1 ); + m_reporter->testRunEnded( TestRunStats( m_runInfo, m_totals, false ) ); + } + + public: + // !TBD We need to do this another way! + bool aborting() const { + return m_totals.assertions.failed == static_cast( 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; + m_shouldReportUnexpected = true; + try { + m_lastAssertionInfo = AssertionInfo( "TEST_CASE", testCaseInfo.lineInfo, "", ResultDisposition::Normal ); + + seedRng( *m_config ); + + Timer timer; + timer.start(); + if( m_reporter->getPreferences().shouldRedirectStdOut ) { + StreamRedirect coutRedir( Catch::cout(), redirectedCout ); + StdErrRedirect errRedir( redirectedCerr ); + invokeActiveTestCase(); + } + else { + invokeActiveTestCase(); + } + duration = timer.getElapsedSeconds(); + } + catch( TestFailureException& ) { + // This just means the test was aborted due to failure + } + catch(...) { + // Under CATCH_CONFIG_FAST_COMPILE, unexpected exceptions under REQUIRE assertions + // are reported without translation at the point of origin. + if (m_shouldReportUnexpected) { + makeUnexpectedResultBuilder().useActiveException(); + } + } + m_testCaseTracker->close(); + handleUnfinishedSections(); + m_messages.clear(); + + Counts assertions = m_totals.assertions - prevAssertions; + bool missingAssertions = testForMissingAssertions( assertions ); + + if( testCaseInfo.okToFail() ) { + std::swap( assertions.failedButOk, assertions.failed ); + m_totals.assertions.failed -= assertions.failedButOk; + m_totals.assertions.failedButOk += assertions.failedButOk; + } + + SectionStats testCaseSectionStats( testCaseSection, assertions, duration, missingAssertions ); + m_reporter->sectionEnded( testCaseSectionStats ); + } + + void invokeActiveTestCase() { + FatalConditionHandler fatalConditionHandler; // Handle signals + m_activeTestCase->invoke(); + fatalConditionHandler.reset(); + } + + private: + + ResultBuilder makeUnexpectedResultBuilder() const { + return ResultBuilder( m_lastAssertionInfo.macroName, + m_lastAssertionInfo.lineInfo, + m_lastAssertionInfo.capturedExpression, + m_lastAssertionInfo.resultDisposition ); + } + + void handleUnfinishedSections() { + // If sections ended prematurely due to an exception we stored their + // infos here so we can tear them down outside the unwind process. + for( std::vector::const_reverse_iterator it = m_unfinishedSections.rbegin(), + itEnd = m_unfinishedSections.rend(); + it != itEnd; + ++it ) + sectionEnded( *it ); + m_unfinishedSections.clear(); + } + + TestRunInfo m_runInfo; + IMutableContext& m_context; + TestCase const* m_activeTestCase; + ITracker* m_testCaseTracker; + ITracker* m_currentSectionTracker; + AssertionResult m_lastResult; + + Ptr m_config; + Totals m_totals; + Ptr m_reporter; + std::vector m_messages; + AssertionInfo m_lastAssertionInfo; + std::vector m_unfinishedSections; + std::vector m_activeSections; + TrackerContext m_trackerContext; + size_t m_prevPassed; + bool m_shouldReportUnexpected; + }; + + IResultCapture& getResultCapture() { + if( IResultCapture* capture = getCurrentContext().getResultCapture() ) + return *capture; + else + throw std::logic_error( "No result capture instance" ); + } + +} // end namespace Catch + +// #included from: internal/catch_version.h +#define TWOBLUECUBES_CATCH_VERSION_H_INCLUDED + +namespace Catch { + + // Versioning information + struct Version { + Version( unsigned int _majorVersion, + unsigned int _minorVersion, + unsigned int _patchNumber, + char const * const _branchName, + unsigned int _buildNumber ); + + unsigned int const majorVersion; + unsigned int const minorVersion; + unsigned int const patchNumber; + + // buildNumber is only used if branchName is not null + char const * const branchName; + unsigned int const buildNumber; + + friend std::ostream& operator << ( std::ostream& os, Version const& version ); + + private: + void operator=( Version const& ); + }; + + inline Version libraryVersion(); +} + +#include +#include +#include + +namespace Catch { + + Ptr createReporter( std::string const& reporterName, Ptr const& config ) { + Ptr reporter = getRegistryHub().getReporterRegistry().create( reporterName, config.get() ); + if( !reporter ) { + std::ostringstream oss; + oss << "No reporter registered with name: '" << reporterName << "'"; + throw std::domain_error( oss.str() ); + } + return reporter; + } + +#if !defined(CATCH_CONFIG_DEFAULT_REPORTER) +#define CATCH_CONFIG_DEFAULT_REPORTER "console" +#endif + + Ptr makeReporter( Ptr const& config ) { + std::vector reporters = config->getReporterNames(); + if( reporters.empty() ) + reporters.push_back( CATCH_CONFIG_DEFAULT_REPORTER ); + + Ptr reporter; + for( std::vector::const_iterator it = reporters.begin(), itEnd = reporters.end(); + it != itEnd; + ++it ) + reporter = addReporter( reporter, createReporter( *it, config ) ); + return reporter; + } + Ptr addListeners( Ptr const& config, Ptr reporters ) { + IReporterRegistry::Listeners listeners = getRegistryHub().getReporterRegistry().getListeners(); + for( IReporterRegistry::Listeners::const_iterator it = listeners.begin(), itEnd = listeners.end(); + it != itEnd; + ++it ) + reporters = addReporter(reporters, (*it)->create( ReporterConfig( config ) ) ); + return reporters; + } + + Totals runTests( Ptr const& config ) { + + Ptr iconfig = config.get(); + + Ptr reporter = makeReporter( config ); + reporter = addListeners( iconfig, reporter ); + + RunContext context( iconfig, reporter ); + + Totals totals; + + context.testGroupStarting( config->name(), 1, 1 ); + + TestSpec testSpec = config->testSpec(); + if( !testSpec.hasFilters() ) + testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "~[.]" ).testSpec(); // All not hidden tests + + std::vector const& allTestCases = getAllTestCasesSorted( *iconfig ); + for( std::vector::const_iterator it = allTestCases.begin(), itEnd = allTestCases.end(); + it != itEnd; + ++it ) { + if( !context.aborting() && matchTest( *it, testSpec, *iconfig ) ) + totals += context.runTest( *it ); + else + reporter->skipTest( *it ); + } + + context.testGroupEnded( iconfig->name(), totals, 1, 1 ); + return totals; + } + + void applyFilenamesAsTags( IConfig const& config ) { + std::vector const& tests = getAllTestCasesSorted( config ); + for(std::size_t i = 0; i < tests.size(); ++i ) { + TestCase& test = const_cast( tests[i] ); + std::set tags = test.tags; + + std::string filename = test.lineInfo.file; + std::string::size_type lastSlash = filename.find_last_of( "\\/" ); + if( lastSlash != std::string::npos ) + filename = filename.substr( lastSlash+1 ); + + std::string::size_type lastDot = filename.find_last_of( '.' ); + if( lastDot != std::string::npos ) + filename = filename.substr( 0, lastDot ); + + tags.insert( '#' + filename ); + setTags( test, tags ); + } + } + + class Session : NonCopyable { + static bool alreadyInstantiated; + + public: + + struct OnUnusedOptions { enum DoWhat { Ignore, Fail }; }; + + Session() + : m_cli( makeCommandLineParser() ) { + if( alreadyInstantiated ) { + std::string msg = "Only one instance of Catch::Session can ever be used"; + Catch::cerr() << msg << std::endl; + throw std::logic_error( msg ); + } + alreadyInstantiated = true; + } + ~Session() { + Catch::cleanUp(); + } + + void showHelp( std::string const& processName ) { + Catch::cout() << "\nCatch v" << libraryVersion() << "\n"; + + m_cli.usage( Catch::cout(), processName ); + Catch::cout() << "For more detail usage please see the project docs\n" << std::endl; + } + + int applyCommandLine( int argc, char const* const* const argv, OnUnusedOptions::DoWhat unusedOptionBehaviour = OnUnusedOptions::Fail ) { + try { + m_cli.setThrowOnUnrecognisedTokens( unusedOptionBehaviour == OnUnusedOptions::Fail ); + m_unusedTokens = m_cli.parseInto( Clara::argsToVector( argc, argv ), m_configData ); + if( m_configData.showHelp ) + showHelp( m_configData.processName ); + m_config.reset(); + } + catch( std::exception& ex ) { + { + Colour colourGuard( Colour::Red ); + Catch::cerr() + << "\nError(s) in input:\n" + << Text( ex.what(), TextAttributes().setIndent(2) ) + << "\n\n"; + } + m_cli.usage( Catch::cout(), m_configData.processName ); + return (std::numeric_limits::max)(); + } + return 0; + } + + void useConfigData( ConfigData const& _configData ) { + m_configData = _configData; + m_config.reset(); + } + + int run( int argc, char const* const* const argv ) { + + int returnCode = applyCommandLine( argc, argv ); + if( returnCode == 0 ) + returnCode = run(); + return returnCode; + } + + #if defined(WIN32) && defined(UNICODE) + int run( int argc, wchar_t const* const* const argv ) { + + char **utf8Argv = new char *[ argc ]; + + for ( int i = 0; i < argc; ++i ) { + int bufSize = WideCharToMultiByte( CP_UTF8, 0, argv[i], -1, NULL, 0, NULL, NULL ); + + utf8Argv[ i ] = new char[ bufSize ]; + + WideCharToMultiByte( CP_UTF8, 0, argv[i], -1, utf8Argv[i], bufSize, NULL, NULL ); + } + + int returnCode = applyCommandLine( argc, utf8Argv ); + if( returnCode == 0 ) + returnCode = run(); + + for ( int i = 0; i < argc; ++i ) + delete [] utf8Argv[ i ]; + + delete [] utf8Argv; + + return returnCode; + } + #endif + + int run() { + if( m_configData.showHelp ) + return 0; + + try + { + config(); // Force config to be constructed + + seedRng( *m_config ); + + if( m_configData.filenamesAsTags ) + applyFilenamesAsTags( *m_config ); + + // Handle list request + if( Option listed = list( config() ) ) + return static_cast( *listed ); + + return static_cast( runTests( m_config ).assertions.failed ); + } + catch( std::exception& ex ) { + Catch::cerr() << ex.what() << std::endl; + return (std::numeric_limits::max)(); + } + } + + 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 ); + return *m_config; + } + private: + Clara::CommandLine m_cli; + std::vector m_unusedTokens; + ConfigData m_configData; + Ptr m_config; + }; + + bool Session::alreadyInstantiated = false; + +} // end namespace Catch + +// #included from: catch_registry_hub.hpp +#define TWOBLUECUBES_CATCH_REGISTRY_HUB_HPP_INCLUDED + +// #included from: catch_test_case_registry_impl.hpp +#define TWOBLUECUBES_CATCH_TEST_CASE_REGISTRY_IMPL_HPP_INCLUDED + +#include +#include +#include +#include + +namespace Catch { + + struct RandomNumberGenerator { + typedef std::ptrdiff_t result_type; + + result_type operator()( result_type n ) const { return std::rand() % n; } + +#ifdef CATCH_CONFIG_CPP11_SHUFFLE + static constexpr result_type min() { return 0; } + static constexpr result_type max() { return 1000000; } + result_type operator()() const { return std::rand() % max(); } +#endif + template + static void shuffle( V& vector ) { + RandomNumberGenerator rng; +#ifdef CATCH_CONFIG_CPP11_SHUFFLE + std::shuffle( vector.begin(), vector.end(), rng ); +#else + std::random_shuffle( vector.begin(), vector.end(), rng ); +#endif + } + }; + + inline std::vector sortTests( IConfig const& config, std::vector const& unsortedTestCases ) { + + std::vector sorted = unsortedTestCases; + + switch( config.runOrder() ) { + case RunTests::InLexicographicalOrder: + std::sort( sorted.begin(), sorted.end() ); + break; + case RunTests::InRandomOrder: + { + seedRng( config ); + RandomNumberGenerator::shuffle( sorted ); + } + break; + case RunTests::InDeclarationOrder: + // already in declaration order + break; + } + return sorted; + } + bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config ) { + return testSpec.matches( testCase ) && ( config.allowThrows() || !testCase.throws() ); + } + + void enforceNoDuplicateTestCases( std::vector const& functions ) { + std::set seenFunctions; + for( std::vector::const_iterator it = functions.begin(), itEnd = functions.end(); + it != itEnd; + ++it ) { + std::pair::const_iterator, bool> prev = seenFunctions.insert( *it ); + if( !prev.second ) { + std::ostringstream ss; + + ss << Colour( Colour::Red ) + << "error: TEST_CASE( \"" << it->name << "\" ) already defined.\n" + << "\tFirst seen at " << prev.first->getTestCaseInfo().lineInfo << '\n' + << "\tRedefined at " << it->getTestCaseInfo().lineInfo << std::endl; + + throw std::runtime_error(ss.str()); + } + } + } + + std::vector filterTests( std::vector const& testCases, TestSpec const& testSpec, IConfig const& config ) { + std::vector filtered; + filtered.reserve( testCases.size() ); + for( std::vector::const_iterator it = testCases.begin(), itEnd = testCases.end(); + it != itEnd; + ++it ) + if( matchTest( *it, testSpec, config ) ) + filtered.push_back( *it ); + return filtered; + } + std::vector const& getAllTestCasesSorted( IConfig const& config ) { + return getRegistryHub().getTestCaseRegistry().getAllTestsSorted( config ); + } + + class TestRegistry : public ITestCaseRegistry { + public: + TestRegistry() + : m_currentSortOrder( RunTests::InDeclarationOrder ), + m_unnamedCount( 0 ) + {} + virtual ~TestRegistry(); + + virtual void registerTest( TestCase const& testCase ) { + std::string name = testCase.getTestCaseInfo().name; + if( name.empty() ) { + std::ostringstream oss; + oss << "Anonymous test case " << ++m_unnamedCount; + return registerTest( testCase.withName( oss.str() ) ); + } + m_functions.push_back( testCase ); + } + + virtual std::vector const& getAllTests() const { + return m_functions; + } + virtual std::vector const& getAllTestsSorted( IConfig const& config ) const { + if( m_sortedFunctions.empty() ) + enforceNoDuplicateTestCases( m_functions ); + + if( m_currentSortOrder != config.runOrder() || m_sortedFunctions.empty() ) { + m_sortedFunctions = sortTests( config, m_functions ); + m_currentSortOrder = config.runOrder(); + } + return m_sortedFunctions; + } + + private: + std::vector m_functions; + mutable RunTests::InWhatOrder m_currentSortOrder; + mutable std::vector m_sortedFunctions; + size_t m_unnamedCount; + std::ios_base::Init m_ostreamInit; // Forces cout/ cerr to be initialised + }; + + /////////////////////////////////////////////////////////////////////////// + + class FreeFunctionTestCase : public SharedImpl { + public: + + FreeFunctionTestCase( TestFunction fun ) : m_fun( fun ) {} + + virtual void invoke() const { + m_fun(); + } + + private: + virtual ~FreeFunctionTestCase(); + + TestFunction m_fun; + }; + + inline std::string extractClassName( std::string const& classOrQualifiedMethodName ) { + std::string className = classOrQualifiedMethodName; + if( startsWith( className, '&' ) ) + { + std::size_t lastColons = className.rfind( "::" ); + std::size_t penultimateColons = className.rfind( "::", lastColons-1 ); + if( penultimateColons == std::string::npos ) + penultimateColons = 1; + className = className.substr( penultimateColons, lastColons-penultimateColons ); + } + return className; + } + + void registerTestCase + ( ITestCase* testCase, + char const* classOrQualifiedMethodName, + NameAndDesc const& nameAndDesc, + SourceLineInfo const& lineInfo ) { + + getMutableRegistryHub().registerTest + ( makeTestCase + ( testCase, + extractClassName( classOrQualifiedMethodName ), + nameAndDesc.name, + nameAndDesc.description, + lineInfo ) ); + } + void registerTestCaseFunction + ( TestFunction function, + SourceLineInfo const& lineInfo, + NameAndDesc const& nameAndDesc ) { + registerTestCase( new FreeFunctionTestCase( function ), "", nameAndDesc, lineInfo ); + } + + /////////////////////////////////////////////////////////////////////////// + + AutoReg::AutoReg + ( TestFunction function, + SourceLineInfo const& lineInfo, + NameAndDesc const& nameAndDesc ) { + registerTestCaseFunction( function, lineInfo, nameAndDesc ); + } + + AutoReg::~AutoReg() {} + +} // end namespace Catch + +// #included from: catch_reporter_registry.hpp +#define TWOBLUECUBES_CATCH_REPORTER_REGISTRY_HPP_INCLUDED + +#include + +namespace Catch { + + class ReporterRegistry : public IReporterRegistry { + + public: + + virtual ~ReporterRegistry() CATCH_OVERRIDE {} + + virtual IStreamingReporter* create( std::string const& name, Ptr const& config ) const CATCH_OVERRIDE { + FactoryMap::const_iterator it = m_factories.find( name ); + if( it == m_factories.end() ) + return CATCH_NULL; + return it->second->create( ReporterConfig( config ) ); + } + + void registerReporter( std::string const& name, Ptr const& factory ) { + m_factories.insert( std::make_pair( name, factory ) ); + } + void registerListener( Ptr const& factory ) { + m_listeners.push_back( factory ); + } + + virtual FactoryMap const& getFactories() const CATCH_OVERRIDE { + return m_factories; + } + virtual Listeners const& getListeners() const CATCH_OVERRIDE { + return m_listeners; + } + + private: + FactoryMap m_factories; + Listeners m_listeners; + }; +} + +// #included from: catch_exception_translator_registry.hpp +#define TWOBLUECUBES_CATCH_EXCEPTION_TRANSLATOR_REGISTRY_HPP_INCLUDED + +#ifdef __OBJC__ +#import "Foundation/Foundation.h" +#endif + +namespace Catch { + + class ExceptionTranslatorRegistry : public IExceptionTranslatorRegistry { + public: + ~ExceptionTranslatorRegistry() { + deleteAll( m_translators ); + } + + virtual void registerTranslator( const IExceptionTranslator* translator ) { + m_translators.push_back( translator ); + } + + virtual std::string translateActiveException() const { + try { +#ifdef __OBJC__ + // In Objective-C try objective-c exceptions first + @try { + return tryTranslators(); + } + @catch (NSException *exception) { + return Catch::toString( [exception description] ); + } +#else + return tryTranslators(); +#endif + } + catch( TestFailureException& ) { + throw; + } + catch( std::exception& ex ) { + return ex.what(); + } + catch( std::string& msg ) { + return msg; + } + catch( const char* msg ) { + return msg; + } + catch(...) { + return "Unknown exception"; + } + } + + std::string tryTranslators() const { + if( m_translators.empty() ) + throw; + else + return m_translators[0]->translate( m_translators.begin()+1, m_translators.end() ); + } + + private: + std::vector m_translators; + }; +} + +// #included from: catch_tag_alias_registry.h +#define TWOBLUECUBES_CATCH_TAG_ALIAS_REGISTRY_H_INCLUDED + +#include + +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( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo ); + + private: + std::map m_registry; + }; + +} // end namespace Catch + +namespace Catch { + + namespace { + + class RegistryHub : public IRegistryHub, public IMutableRegistryHub { + + RegistryHub( RegistryHub const& ); + void operator=( RegistryHub const& ); + + public: // IRegistryHub + RegistryHub() { + } + virtual IReporterRegistry const& getReporterRegistry() const CATCH_OVERRIDE { + return m_reporterRegistry; + } + virtual ITestCaseRegistry const& getTestCaseRegistry() const CATCH_OVERRIDE { + return m_testCaseRegistry; + } + virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() CATCH_OVERRIDE { + return m_exceptionTranslatorRegistry; + } + virtual ITagAliasRegistry const& getTagAliasRegistry() const CATCH_OVERRIDE { + return m_tagAliasRegistry; + } + + public: // IMutableRegistryHub + virtual void registerReporter( std::string const& name, Ptr const& factory ) CATCH_OVERRIDE { + m_reporterRegistry.registerReporter( name, factory ); + } + virtual void registerListener( Ptr const& factory ) CATCH_OVERRIDE { + m_reporterRegistry.registerListener( factory ); + } + virtual void registerTest( TestCase const& testInfo ) CATCH_OVERRIDE { + m_testCaseRegistry.registerTest( testInfo ); + } + virtual void registerTranslator( const IExceptionTranslator* translator ) CATCH_OVERRIDE { + m_exceptionTranslatorRegistry.registerTranslator( translator ); + } + virtual void registerTagAlias( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo ) CATCH_OVERRIDE { + m_tagAliasRegistry.add( alias, tag, lineInfo ); + } + + private: + TestRegistry m_testCaseRegistry; + ReporterRegistry m_reporterRegistry; + ExceptionTranslatorRegistry m_exceptionTranslatorRegistry; + TagAliasRegistry m_tagAliasRegistry; + }; + + // Single, global, instance + inline RegistryHub*& getTheRegistryHub() { + static RegistryHub* theRegistryHub = CATCH_NULL; + if( !theRegistryHub ) + theRegistryHub = new RegistryHub(); + return theRegistryHub; + } + } + + IRegistryHub& getRegistryHub() { + return *getTheRegistryHub(); + } + IMutableRegistryHub& getMutableRegistryHub() { + return *getTheRegistryHub(); + } + void cleanUp() { + delete getTheRegistryHub(); + getTheRegistryHub() = CATCH_NULL; + cleanUpContext(); + } + std::string translateActiveException() { + return getRegistryHub().getExceptionTranslatorRegistry().translateActiveException(); + } + +} // end namespace Catch + +// #included from: catch_notimplemented_exception.hpp +#define TWOBLUECUBES_CATCH_NOTIMPLEMENTED_EXCEPTION_HPP_INCLUDED + +#include + +namespace Catch { + + NotImplementedException::NotImplementedException( SourceLineInfo const& lineInfo ) + : m_lineInfo( lineInfo ) { + std::ostringstream oss; + oss << lineInfo << ": function "; + oss << "not implemented"; + m_what = oss.str(); + } + + const char* NotImplementedException::what() const CATCH_NOEXCEPT { + return m_what.c_str(); + } + +} // end namespace Catch + +// #included from: catch_context_impl.hpp +#define TWOBLUECUBES_CATCH_CONTEXT_IMPL_HPP_INCLUDED + +// #included from: catch_stream.hpp +#define TWOBLUECUBES_CATCH_STREAM_HPP_INCLUDED + +#include +#include +#include + +namespace Catch { + + 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 ) ); + } + return 0; + } + + int sync() { + if( pbase() != pptr() ) { + m_writer( std::string( pbase(), static_cast( pptr() - pbase() ) ) ); + setp( pbase(), epptr() ); + } + return 0; + } + }; + + /////////////////////////////////////////////////////////////////////////// + + FileStream::FileStream( std::string const& filename ) { + m_ofs.open( filename.c_str() ); + if( m_ofs.fail() ) { + std::ostringstream oss; + oss << "Unable to open file: '" << filename << '\''; + throw std::domain_error( oss.str() ); + } + } + + std::ostream& FileStream::stream() const { + return m_ofs; + } + + struct OutputDebugWriter { + + void operator()( std::string const&str ) { + writeToDebugConsole( str ); + } + }; + + DebugOutStream::DebugOutStream() + : m_streamBuf( new StreamBufImpl() ), + m_os( m_streamBuf.get() ) + {} + + std::ostream& DebugOutStream::stream() const { + return m_os; + } + + // Store the streambuf from cout up-front because + // cout may get redirected when running tests + CoutStream::CoutStream() + : m_os( Catch::cout().rdbuf() ) + {} + + std::ostream& CoutStream::stream() const { + return m_os; + } + +#ifndef CATCH_CONFIG_NOSTDOUT // If you #define this you must implement these functions + std::ostream& cout() { + return std::cout; + } + std::ostream& cerr() { + return std::cerr; + } + std::ostream& clog() { + return std::clog; + } +#endif +} + +namespace Catch { + + class Context : public IMutableContext { + + Context() : m_config( CATCH_NULL ), m_runner( CATCH_NULL ), m_resultCapture( CATCH_NULL ) {} + Context( Context const& ); + void operator=( Context const& ); + + public: + virtual ~Context() { + deleteAllValues( m_generatorsByTestName ); + } + + 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 + : CATCH_NULL; + } + + IGeneratorsForTest& getGeneratorsForCurrentTest() { + IGeneratorsForTest* generators = findGeneratorsForCurrentTest(); + if( !generators ) { + std::string testName = getResultCapture()->getCurrentTestName(); + generators = createGeneratorsForTest(); + m_generatorsByTestName.insert( std::make_pair( testName, generators ) ); + } + return *generators; + } + + private: + Ptr m_config; + IRunner* m_runner; + IResultCapture* m_resultCapture; + std::map m_generatorsByTestName; + }; + + namespace { + Context* currentContext = CATCH_NULL; + } + IMutableContext& getCurrentMutableContext() { + if( !currentContext ) + currentContext = new Context(); + return *currentContext; + } + IContext& getCurrentContext() { + return getCurrentMutableContext(); + } + + void cleanUpContext() { + delete currentContext; + currentContext = CATCH_NULL; + } +} + +// #included from: catch_console_colour_impl.hpp +#define TWOBLUECUBES_CATCH_CONSOLE_COLOUR_IMPL_HPP_INCLUDED + +// #included from: catch_errno_guard.hpp +#define TWOBLUECUBES_CATCH_ERRNO_GUARD_HPP_INCLUDED + +#include + +namespace Catch { + + class ErrnoGuard { + public: + ErrnoGuard():m_oldErrno(errno){} + ~ErrnoGuard() { errno = m_oldErrno; } + private: + int m_oldErrno; + }; + +} + namespace Catch { namespace { struct IColourImpl { - virtual ~IColourImpl() = default; + virtual ~IColourImpl() {} virtual void use( Colour::Code _colourCode ) = 0; }; @@ -5962,7 +7884,7 @@ namespace { originalBackgroundAttributes = csbiInfo.wAttributes & ~( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY ); } - virtual void use( Colour::Code _colourCode ) override { + virtual void use( Colour::Code _colourCode ) { switch( _colourCode ) { case Colour::None: return setTextAttribute( originalForegroundAttributes ); case Colour::White: return setTextAttribute( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE ); @@ -5978,7 +7900,7 @@ namespace { 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: CATCH_INTERNAL_ERROR( "not a colour" ); + case Colour::Bright: throw std::logic_error( "not a colour" ); } } @@ -5994,12 +7916,14 @@ namespace { IColourImpl* platformColourInstance() { static Win32ColourImpl s_instance; - IConfigPtr config = getCurrentContext().getConfig(); + Ptr config = getCurrentContext().getConfig(); UseColour::YesOrNo colourMode = config ? config->useColour() : UseColour::Auto; if( colourMode == UseColour::Auto ) - colourMode = UseColour::Yes; + colourMode = !isDebuggerActive() + ? UseColour::Yes + : UseColour::No; return colourMode == UseColour::Yes ? &s_instance : NoColourImpl::instance(); @@ -6021,7 +7945,7 @@ namespace { // https://github.com/philsquared/Catch/pull/131 class PosixColourImpl : public IColourImpl { public: - virtual void use( Colour::Code _colourCode ) override { + virtual void use( Colour::Code _colourCode ) { switch( _colourCode ) { case Colour::None: case Colour::White: return setColour( "[0m" ); @@ -6037,7 +7961,7 @@ namespace { case Colour::BrightGreen: return setColour( "[1;32m" ); case Colour::BrightWhite: return setColour( "[1;37m" ); - case Colour::Bright: CATCH_INTERNAL_ERROR( "not a colour" ); + case Colour::Bright: throw std::logic_error( "not a colour" ); } } static IColourImpl* instance() { @@ -6051,21 +7975,14 @@ namespace { } }; - bool useColourOnPlatform() { - return -#ifdef CATCH_PLATFORM_MAC - !isDebuggerActive() && -#endif - isatty(STDOUT_FILENO); - } IColourImpl* platformColourInstance() { ErrnoGuard guard; - IConfigPtr config = getCurrentContext().getConfig(); + Ptr config = getCurrentContext().getConfig(); UseColour::YesOrNo colourMode = config ? config->useColour() : UseColour::Auto; if( colourMode == UseColour::Auto ) - colourMode = useColourOnPlatform() + colourMode = (!isDebuggerActive() && isatty(STDOUT_FILENO) ) ? UseColour::Yes : UseColour::No; return colourMode == UseColour::Yes @@ -6088,17 +8005,8 @@ namespace Catch { namespace Catch { - Colour::Colour( Code _colourCode ) { use( _colourCode ); } - Colour::Colour( Colour&& rhs ) noexcept { - m_moved = rhs.m_moved; - rhs.m_moved = true; - } - Colour& Colour::operator=( Colour&& rhs ) noexcept { - m_moved = rhs.m_moved; - rhs.m_moved = true; - return *this; - } - + 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 ) { @@ -6106,105 +8014,776 @@ namespace Catch { impl->use( _colourCode ); } - std::ostream& operator << ( std::ostream& os, Colour const& ) { - return os; +} // end namespace Catch + +// #included from: catch_generators_impl.hpp +#define TWOBLUECUBES_CATCH_GENERATORS_IMPL_HPP_INCLUDED + +#include +#include +#include + +namespace Catch { + + struct GeneratorInfo : IGeneratorInfo { + + GeneratorInfo( std::size_t size ) + : m_size( size ), + m_currentIndex( 0 ) + {} + + bool moveNext() { + if( ++m_currentIndex == m_size ) { + m_currentIndex = 0; + return false; + } + return true; + } + + std::size_t getCurrentIndex() const { + return m_currentIndex; + } + + std::size_t m_size; + std::size_t m_currentIndex; + }; + + /////////////////////////////////////////////////////////////////////////// + + class GeneratorsForTest : public IGeneratorsForTest { + + public: + ~GeneratorsForTest() { + deleteAll( m_generatorsInOrder ); + } + + IGeneratorInfo& getGeneratorInfo( std::string const& fileInfo, std::size_t size ) { + std::map::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 -#if defined(__clang__) -# pragma clang diagnostic pop -#endif - -// end catch_console_colour.cpp -// start catch_context.cpp +// #included from: catch_assertionresult.hpp +#define TWOBLUECUBES_CATCH_ASSERTIONRESULT_HPP_INCLUDED namespace Catch { - class Context : public IMutableContext, NonCopyable { + AssertionInfo::AssertionInfo():macroName(""), capturedExpression(""), resultDisposition(ResultDisposition::Normal), secondArg(""){} - public: // IContext - virtual IResultCapture* getResultCapture() override { - return m_resultCapture; + AssertionInfo::AssertionInfo( char const * _macroName, + SourceLineInfo const& _lineInfo, + char const * _capturedExpression, + ResultDisposition::Flags _resultDisposition, + char const * _secondArg) + : macroName( _macroName ), + lineInfo( _lineInfo ), + capturedExpression( _capturedExpression ), + resultDisposition( _resultDisposition ), + secondArg( _secondArg ) + {} + + AssertionResult::AssertionResult() {} + + AssertionResult::AssertionResult( AssertionInfo const& info, AssertionResultData const& data ) + : m_info( info ), + m_resultData( data ) + {} + + AssertionResult::~AssertionResult() {} + + // Result was a success + bool AssertionResult::succeeded() const { + return Catch::isOk( m_resultData.resultType ); + } + + // Result was a success, or failure is suppressed + bool AssertionResult::isOk() const { + return Catch::isOk( m_resultData.resultType ) || shouldSuppressFailure( m_info.resultDisposition ); + } + + ResultWas::OfType AssertionResult::getResultType() const { + return m_resultData.resultType; + } + + bool AssertionResult::hasExpression() const { + return m_info.capturedExpression[0] != 0; + } + + bool AssertionResult::hasMessage() const { + return !m_resultData.message.empty(); + } + + std::string capturedExpressionWithSecondArgument( char const * capturedExpression, char const * secondArg ) { + return (secondArg[0] == 0 || secondArg[0] == '"' && secondArg[1] == '"') + ? capturedExpression + : std::string(capturedExpression) + ", " + secondArg; + } + + std::string AssertionResult::getExpression() const { + if( isFalseTest( m_info.resultDisposition ) ) + return '!' + capturedExpressionWithSecondArgument(m_info.capturedExpression, m_info.secondArg); + else + return capturedExpressionWithSecondArgument(m_info.capturedExpression, m_info.secondArg); + } + std::string AssertionResult::getExpressionInMacro() const { + if( m_info.macroName[0] == 0 ) + return capturedExpressionWithSecondArgument(m_info.capturedExpression, m_info.secondArg); + else + return std::string(m_info.macroName) + "( " + capturedExpressionWithSecondArgument(m_info.capturedExpression, m_info.secondArg) + " )"; + } + + bool AssertionResult::hasExpandedExpression() const { + return hasExpression() && getExpandedExpression() != getExpression(); + } + + std::string AssertionResult::getExpandedExpression() const { + return m_resultData.reconstructExpression(); + } + + 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; + } + + void AssertionResult::discardDecomposedExpression() const { + m_resultData.decomposedExpression = CATCH_NULL; + } + + void AssertionResult::expandDecomposedExpression() const { + m_resultData.reconstructExpression(); + } + +} // end namespace Catch + +// #included from: catch_test_case_info.hpp +#define TWOBLUECUBES_CATCH_TEST_CASE_INFO_HPP_INCLUDED + +#include + +namespace Catch { + + inline TestCaseInfo::SpecialProperties parseSpecialTag( std::string const& tag ) { + if( startsWith( tag, '.' ) || + tag == "hide" || + tag == "!hide" ) + return TestCaseInfo::IsHidden; + else if( tag == "!throws" ) + return TestCaseInfo::Throws; + else if( tag == "!shouldfail" ) + return TestCaseInfo::ShouldFail; + else if( tag == "!mayfail" ) + return TestCaseInfo::MayFail; + else if( tag == "!nonportable" ) + return TestCaseInfo::NonPortable; + else + return TestCaseInfo::None; + } + inline bool isReservedTag( std::string const& tag ) { + return parseSpecialTag( tag ) == TestCaseInfo::None && tag.size() > 0 && !std::isalnum( tag[0] ); + } + inline void enforceNotReservedTag( std::string const& tag, SourceLineInfo const& _lineInfo ) { + if( isReservedTag( tag ) ) { + std::ostringstream ss; + ss << Colour(Colour::Red) + << "Tag name [" << tag << "] not allowed.\n" + << "Tag names starting with non alpha-numeric characters are reserved\n" + << Colour(Colour::FileName) + << _lineInfo << '\n'; + throw std::runtime_error(ss.str()); } - virtual IRunner* getRunner() override { - return m_runner; + } + + 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 ) { + char c = _descOrTags[i]; + if( !inTag ) { + if( c == '[' ) + inTag = true; + else + desc += c; + } + else { + if( c == ']' ) { + TestCaseInfo::SpecialProperties prop = parseSpecialTag( tag ); + if( prop == TestCaseInfo::IsHidden ) + isHidden = true; + else if( prop == TestCaseInfo::None ) + enforceNotReservedTag( tag, _lineInfo ); + + tags.insert( tag ); + tag.clear(); + inTag = false; + } + else + tag += c; + } + } + if( isHidden ) { + tags.insert( "hide" ); + tags.insert( "." ); } - virtual IConfigPtr getConfig() const override { - return m_config; - } + TestCaseInfo info( _name, _className, desc, tags, _lineInfo ); + return TestCase( _testCase, info ); + } - virtual ~Context() override; + void setTags( TestCaseInfo& testCaseInfo, std::set const& tags ) + { + testCaseInfo.tags = tags; + testCaseInfo.lcaseTags.clear(); - public: // IMutableContext - virtual void setResultCapture( IResultCapture* resultCapture ) override { - m_resultCapture = resultCapture; - } - virtual void setRunner( IRunner* runner ) override { - m_runner = runner; - } - virtual void setConfig( IConfigPtr const& config ) override { - m_config = config; + std::ostringstream oss; + for( std::set::const_iterator it = tags.begin(), itEnd = tags.end(); it != itEnd; ++it ) { + oss << '[' << *it << ']'; + std::string lcaseTag = toLower( *it ); + testCaseInfo.properties = static_cast( testCaseInfo.properties | parseSpecialTag( lcaseTag ) ); + testCaseInfo.lcaseTags.insert( lcaseTag ); } + testCaseInfo.tagsAsString = oss.str(); + } - friend IMutableContext& getCurrentMutableContext(); + 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 ), + lineInfo( _lineInfo ), + properties( None ) + { + setTags( *this, _tags ); + } - private: - IConfigPtr m_config; - IRunner* m_runner = nullptr; - IResultCapture* m_resultCapture = nullptr; + TestCaseInfo::TestCaseInfo( TestCaseInfo const& other ) + : name( other.name ), + className( other.className ), + description( other.description ), + tags( other.tags ), + lcaseTags( other.lcaseTags ), + tagsAsString( other.tagsAsString ), + lineInfo( other.lineInfo ), + properties( other.properties ) + {} + + bool TestCaseInfo::isHidden() const { + return ( properties & IsHidden ) != 0; + } + bool TestCaseInfo::throws() const { + return ( properties & Throws ) != 0; + } + bool TestCaseInfo::okToFail() const { + return ( properties & (ShouldFail | MayFail ) ) != 0; + } + bool TestCaseInfo::expectedToFail() const { + return ( properties & (ShouldFail ) ) != 0; + } + + TestCase::TestCase( ITestCase* testCase, TestCaseInfo const& info ) : TestCaseInfo( info ), test( testCase ) {} + + TestCase::TestCase( TestCase const& other ) + : TestCaseInfo( other ), + test( other.test ) + {} + + TestCase TestCase::withName( std::string const& _newName ) const { + TestCase other( *this ); + other.name = _newName; + return other; + } + + void TestCase::swap( TestCase& other ) { + test.swap( other.test ); + name.swap( other.name ); + className.swap( other.className ); + description.swap( other.description ); + tags.swap( other.tags ); + lcaseTags.swap( other.lcaseTags ); + tagsAsString.swap( other.tagsAsString ); + std::swap( TestCaseInfo::properties, static_cast( other ).properties ); + std::swap( lineInfo, other.lineInfo ); + } + + void TestCase::invoke() const { + test->invoke(); + } + + bool TestCase::operator == ( TestCase const& other ) const { + return test.get() == other.test.get() && + name == other.name && + className == other.className; + } + + bool TestCase::operator < ( TestCase const& other ) const { + return name < other.name; + } + TestCase& TestCase::operator = ( TestCase const& other ) { + TestCase temp( other ); + swap( temp ); + return *this; + } + + TestCaseInfo const& TestCase::getTestCaseInfo() const + { + return *this; + } + +} // end namespace Catch + +// #included from: catch_version.hpp +#define TWOBLUECUBES_CATCH_VERSION_HPP_INCLUDED + +namespace Catch { + + Version::Version + ( unsigned int _majorVersion, + unsigned int _minorVersion, + unsigned int _patchNumber, + char const * const _branchName, + unsigned int _buildNumber ) + : majorVersion( _majorVersion ), + minorVersion( _minorVersion ), + patchNumber( _patchNumber ), + branchName( _branchName ), + buildNumber( _buildNumber ) + {} + + std::ostream& operator << ( std::ostream& os, Version const& version ) { + os << version.majorVersion << '.' + << version.minorVersion << '.' + << version.patchNumber; + // branchName is never null -> 0th char is \0 if it is empty + if (version.branchName[0]) { + os << '-' << version.branchName + << '.' << version.buildNumber; + } + return os; + } + + inline Version libraryVersion() { + static Version version( 1, 9, 7, "", 0 ); + return version; + } + +} + +// #included from: catch_message.hpp +#define TWOBLUECUBES_CATCH_MESSAGE_HPP_INCLUDED + +namespace Catch { + + MessageInfo::MessageInfo( std::string const& _macroName, + SourceLineInfo const& _lineInfo, + ResultWas::OfType _type ) + : macroName( _macroName ), + lineInfo( _lineInfo ), + type( _type ), + sequence( ++globalCount ) + {} + + // This may need protecting if threading support is added + unsigned int MessageInfo::globalCount = 0; + + //////////////////////////////////////////////////////////////////////////// + + ScopedMessage::ScopedMessage( MessageBuilder const& builder ) + : m_info( builder.m_info ) + { + m_info.message = builder.m_stream.str(); + getResultCapture().pushScopedMessage( m_info ); + } + ScopedMessage::ScopedMessage( ScopedMessage const& other ) + : m_info( other.m_info ) + {} + + ScopedMessage::~ScopedMessage() { + if ( !std::uncaught_exception() ){ + getResultCapture().popScopedMessage(m_info); + } + } + +} // end namespace Catch + +// #included from: catch_legacy_reporter_adapter.hpp +#define TWOBLUECUBES_CATCH_LEGACY_REPORTER_ADAPTER_HPP_INCLUDED + +// #included from: catch_legacy_reporter_adapter.h +#define TWOBLUECUBES_CATCH_LEGACY_REPORTER_ADAPTER_H_INCLUDED + +namespace Catch +{ + // Deprecated + struct IReporter : IShared { + virtual ~IReporter(); + + virtual bool shouldRedirectStdout() const = 0; + + virtual void StartTesting() = 0; + virtual void EndTesting( Totals const& totals ) = 0; + virtual void StartGroup( std::string const& groupName ) = 0; + virtual void EndGroup( std::string const& groupName, Totals const& totals ) = 0; + virtual void StartTestCase( TestCaseInfo const& testInfo ) = 0; + virtual void EndTestCase( TestCaseInfo const& testInfo, Totals const& totals, std::string const& stdOut, std::string const& stdErr ) = 0; + virtual void StartSection( std::string const& sectionName, std::string const& description ) = 0; + virtual void EndSection( std::string const& sectionName, Counts const& assertions ) = 0; + virtual void NoAssertionsInSection( std::string const& sectionName ) = 0; + virtual void NoAssertionsInTestCase( std::string const& testName ) = 0; + virtual void Aborted() = 0; + virtual void Result( AssertionResult const& result ) = 0; }; - namespace { - Context* currentContext = nullptr; - } - IMutableContext& getCurrentMutableContext() { - if( !currentContext ) - currentContext = new Context(); - return *currentContext; - } - IContext& getCurrentContext() { - return getCurrentMutableContext(); - } + class LegacyReporterAdapter : public SharedImpl + { + public: + LegacyReporterAdapter( Ptr const& legacyReporter ); + virtual ~LegacyReporterAdapter(); - void cleanUpContext() { - delete currentContext; - currentContext = nullptr; - } - IContext::~IContext() = default; - IMutableContext::~IMutableContext() = default; - Context::~Context() = default; -} -// end catch_context.cpp -// start catch_debug_console.cpp + virtual ReporterPreferences getPreferences() const; + virtual void noMatchingTestCases( std::string const& ); + virtual void testRunStarting( TestRunInfo const& ); + virtual void testGroupStarting( GroupInfo const& groupInfo ); + virtual void testCaseStarting( TestCaseInfo const& testInfo ); + virtual void sectionStarting( SectionInfo const& sectionInfo ); + virtual void assertionStarting( AssertionInfo const& ); + virtual bool assertionEnded( AssertionStats const& assertionStats ); + virtual void sectionEnded( SectionStats const& sectionStats ); + virtual void testCaseEnded( TestCaseStats const& testCaseStats ); + virtual void testGroupEnded( TestGroupStats const& testGroupStats ); + virtual void testRunEnded( TestRunStats const& testRunStats ); + virtual void skipTest( TestCaseInfo const& ); -// start catch_debug_console.h - -#include - -namespace Catch { - void writeToDebugConsole( std::string const& text ); + private: + Ptr m_legacyReporter; + }; } -// end catch_debug_console.h +namespace Catch +{ + LegacyReporterAdapter::LegacyReporterAdapter( Ptr const& legacyReporter ) + : m_legacyReporter( legacyReporter ) + {} + LegacyReporterAdapter::~LegacyReporterAdapter() {} + + ReporterPreferences LegacyReporterAdapter::getPreferences() const { + ReporterPreferences prefs; + prefs.shouldRedirectStdOut = m_legacyReporter->shouldRedirectStdout(); + return prefs; + } + + void LegacyReporterAdapter::noMatchingTestCases( std::string const& ) {} + void LegacyReporterAdapter::testRunStarting( TestRunInfo const& ) { + m_legacyReporter->StartTesting(); + } + void LegacyReporterAdapter::testGroupStarting( GroupInfo const& groupInfo ) { + m_legacyReporter->StartGroup( groupInfo.name ); + } + void LegacyReporterAdapter::testCaseStarting( TestCaseInfo const& testInfo ) { + m_legacyReporter->StartTestCase( testInfo ); + } + void LegacyReporterAdapter::sectionStarting( SectionInfo const& sectionInfo ) { + m_legacyReporter->StartSection( sectionInfo.name, sectionInfo.description ); + } + void LegacyReporterAdapter::assertionStarting( AssertionInfo const& ) { + // Not on legacy interface + } + + bool LegacyReporterAdapter::assertionEnded( AssertionStats const& assertionStats ) { + if( assertionStats.assertionResult.getResultType() != ResultWas::Ok ) { + for( std::vector::const_iterator it = assertionStats.infoMessages.begin(), itEnd = assertionStats.infoMessages.end(); + it != itEnd; + ++it ) { + if( it->type == ResultWas::Info ) { + ResultBuilder rb( it->macroName.c_str(), it->lineInfo, "", ResultDisposition::Normal ); + rb << it->message; + rb.setResultType( ResultWas::Info ); + AssertionResult result = rb.build(); + m_legacyReporter->Result( result ); + } + } + } + m_legacyReporter->Result( assertionStats.assertionResult ); + return true; + } + void LegacyReporterAdapter::sectionEnded( SectionStats const& sectionStats ) { + if( sectionStats.missingAssertions ) + m_legacyReporter->NoAssertionsInSection( sectionStats.sectionInfo.name ); + m_legacyReporter->EndSection( sectionStats.sectionInfo.name, sectionStats.assertions ); + } + void LegacyReporterAdapter::testCaseEnded( TestCaseStats const& testCaseStats ) { + m_legacyReporter->EndTestCase + ( testCaseStats.testInfo, + testCaseStats.totals, + testCaseStats.stdOut, + testCaseStats.stdErr ); + } + void LegacyReporterAdapter::testGroupEnded( TestGroupStats const& testGroupStats ) { + if( testGroupStats.aborting ) + m_legacyReporter->Aborted(); + m_legacyReporter->EndGroup( testGroupStats.groupInfo.name, testGroupStats.totals ); + } + void LegacyReporterAdapter::testRunEnded( TestRunStats const& testRunStats ) { + m_legacyReporter->EndTesting( testRunStats.totals ); + } + void LegacyReporterAdapter::skipTest( TestCaseInfo const& ) { + } +} + +// #included from: catch_timer.hpp + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wc++11-long-long" +#endif + #ifdef CATCH_PLATFORM_WINDOWS - namespace Catch { - void writeToDebugConsole( std::string const& text ) { - ::OutputDebugStringA( text.c_str() ); - } - } #else - namespace Catch { - void writeToDebugConsole( std::string const& text ) { - // !TBD: Need a version for Mac/ XCode and other IDEs - Catch::cout() << text; + +#include + +#endif + +namespace Catch { + + namespace { +#ifdef CATCH_PLATFORM_WINDOWS + UInt64 getCurrentTicks() { + static UInt64 hz=0, hzo=0; + if (!hz) { + QueryPerformanceFrequency( reinterpret_cast( &hz ) ); + QueryPerformanceCounter( reinterpret_cast( &hzo ) ); + } + UInt64 t; + QueryPerformanceCounter( reinterpret_cast( &t ) ); + return ((t-hzo)*1000000)/hz; + } +#else + UInt64 getCurrentTicks() { + timeval t; + gettimeofday(&t,CATCH_NULL); + return static_cast( t.tv_sec ) * 1000000ull + static_cast( t.tv_usec ); + } +#endif + } + + void Timer::start() { + m_ticks = getCurrentTicks(); + } + unsigned int Timer::getElapsedMicroseconds() const { + return static_cast(getCurrentTicks() - m_ticks); + } + unsigned int Timer::getElapsedMilliseconds() const { + return static_cast(getElapsedMicroseconds()/1000); + } + double Timer::getElapsedSeconds() const { + return getElapsedMicroseconds()/1000000.0; + } + +} // namespace Catch + +#ifdef __clang__ +#pragma clang diagnostic pop +#endif +// #included from: catch_common.hpp +#define TWOBLUECUBES_CATCH_COMMON_HPP_INCLUDED + +#include +#include + +namespace Catch { + + bool startsWith( std::string const& s, std::string const& prefix ) { + return s.size() >= prefix.size() && std::equal(prefix.begin(), prefix.end(), s.begin()); + } + bool startsWith( std::string const& s, char prefix ) { + return !s.empty() && s[0] == prefix; + } + bool endsWith( std::string const& s, std::string const& suffix ) { + return s.size() >= suffix.size() && std::equal(suffix.rbegin(), suffix.rend(), s.rbegin()); + } + bool endsWith( std::string const& s, char suffix ) { + return !s.empty() && s[s.size()-1] == suffix; + } + bool contains( std::string const& s, std::string const& infix ) { + return s.find( infix ) != std::string::npos; + } + char toLowerCh(char c) { + return static_cast( std::tolower( c ) ); + } + void toLowerInPlace( std::string& s ) { + std::transform( s.begin(), s.end(), s.begin(), toLowerCh ); + } + 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 ) : std::string(); + } + + bool replaceInPlace( std::string& str, std::string const& replaceThis, std::string const& withThis ) { + bool replaced = false; + std::size_t i = str.find( replaceThis ); + while( i != std::string::npos ) { + replaced = true; + str = str.substr( 0, i ) + withThis + str.substr( i+replaceThis.size() ); + if( i < str.size()-withThis.size() ) + i = str.find( replaceThis, i+withThis.size() ); + else + i = std::string::npos; + } + return replaced; + } + + pluralise::pluralise( std::size_t count, std::string const& label ) + : m_count( count ), + m_label( label ) + {} + + std::ostream& operator << ( std::ostream& os, pluralise const& pluraliser ) { + os << pluraliser.m_count << ' ' << pluraliser.m_label; + if( pluraliser.m_count != 1 ) + os << 's'; + return os; + } + + SourceLineInfo::SourceLineInfo() : file(""), line( 0 ){} + SourceLineInfo::SourceLineInfo( char const* _file, std::size_t _line ) + : file( _file ), + line( _line ) + {} + bool SourceLineInfo::empty() const { + return file[0] == '\0'; + } + bool SourceLineInfo::operator == ( SourceLineInfo const& other ) const { + return line == other.line && (file == other.file || std::strcmp(file, other.file) == 0); + } + bool SourceLineInfo::operator < ( SourceLineInfo const& other ) const { + return line < other.line || ( line == other.line && (std::strcmp(file, other.file) < 0)); + } + + void seedRng( IConfig const& config ) { + if( config.rngSeed() != 0 ) + std::srand( config.rngSeed() ); + } + unsigned int rngSeed() { + return getCurrentContext().getConfig()->rngSeed(); + } + + std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info ) { +#ifndef __GNUG__ + os << info.file << '(' << info.line << ')'; +#else + os << info.file << ':' << info.line; +#endif + return os; + } + + void throwLogicError( std::string const& message, SourceLineInfo const& locationInfo ) { + std::ostringstream oss; + oss << locationInfo << ": Internal Catch error: '" << message << '\''; + if( alwaysTrue() ) + throw std::logic_error( oss.str() ); + } +} + +// #included from: catch_section.hpp +#define TWOBLUECUBES_CATCH_SECTION_HPP_INCLUDED + +namespace Catch { + + SectionInfo::SectionInfo + ( SourceLineInfo const& _lineInfo, + std::string const& _name, + std::string const& _description ) + : name( _name ), + description( _description ), + lineInfo( _lineInfo ) + {} + + Section::Section( SectionInfo const& info ) + : m_info( info ), + m_sectionIncluded( getResultCapture().sectionStarted( m_info, m_assertions ) ) + { + m_timer.start(); + } + +#if defined(_MSC_VER) +#pragma warning(push) +#pragma warning(disable:4996) // std::uncaught_exception is deprecated in C++17 +#endif + Section::~Section() { + if( m_sectionIncluded ) { + SectionEndInfo endInfo( m_info, m_assertions, m_timer.getElapsedSeconds() ); + if( std::uncaught_exception() ) + getResultCapture().sectionEndedEarly( endInfo ); + else + getResultCapture().sectionEnded( endInfo ); } } -#endif // Platform -// end catch_debug_console.cpp -// start catch_debugger.cpp +#if defined(_MSC_VER) +#pragma warning(pop) +#endif + + // This indicates whether the section should be executed or not + Section::operator bool() const { + return m_sectionIncluded; + } + +} // end namespace Catch + +// #included from: catch_debugger.hpp +#define TWOBLUECUBES_CATCH_DEBUGGER_HPP_INCLUDED #ifdef CATCH_PLATFORM_MAC @@ -6214,7 +8793,7 @@ namespace Catch { #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 @@ -6225,7 +8804,7 @@ namespace Catch { int mib[4]; struct kinfo_proc info; - std::size_t size; + size_t size; // Initialize the flags so that, if sysctl fails for some bizarre // reason, we get a predictable result. @@ -6243,7 +8822,7 @@ namespace Catch { // Call sysctl. size = sizeof(info); - if( sysctl(mib, sizeof(mib) / sizeof(*mib), &info, &size, nullptr, 0) != 0 ) { + if( sysctl(mib, sizeof(mib) / sizeof(*mib), &info, &size, CATCH_NULL, 0) != 0 ) { Catch::cerr() << "\n** Call to sysctl failed - unable to determine if debugger is active **\n" << std::endl; return false; } @@ -6300,778 +8879,449 @@ namespace Catch { } #else namespace Catch { - bool isDebuggerActive() { return false; } + inline bool isDebuggerActive() { return false; } } #endif // Platform -// end catch_debugger.cpp -// start catch_decomposer.cpp -namespace Catch { +#ifdef CATCH_PLATFORM_WINDOWS - ITransientExpression::~ITransientExpression() = default; - - void formatReconstructedExpression( std::ostream &os, std::string const& lhs, StringRef op, std::string const& rhs ) { - if( lhs.size() + rhs.size() < 40 && - lhs.find('\n') == std::string::npos && - rhs.find('\n') == std::string::npos ) - os << lhs << " " << op << " " << rhs; - else - os << lhs << "\n" << op << "\n" << rhs; + namespace Catch { + void writeToDebugConsole( std::string const& text ) { + ::OutputDebugStringA( text.c_str() ); + } } -} -// end catch_decomposer.cpp -// start catch_errno_guard.cpp - -#include - -namespace Catch { - ErrnoGuard::ErrnoGuard():m_oldErrno(errno){} - ErrnoGuard::~ErrnoGuard() { errno = m_oldErrno; } -} -// end catch_errno_guard.cpp -// start catch_exception_translator_registry.cpp - -// start catch_exception_translator_registry.h - -#include -#include -#include - -namespace Catch { - - class ExceptionTranslatorRegistry : public IExceptionTranslatorRegistry { - public: - ~ExceptionTranslatorRegistry(); - virtual void registerTranslator( const IExceptionTranslator* translator ); - virtual std::string translateActiveException() const override; - std::string tryTranslators() const; - - private: - std::vector> m_translators; - }; -} - -// end catch_exception_translator_registry.h -#ifdef __OBJC__ -#import "Foundation/Foundation.h" -#endif - -namespace Catch { - - ExceptionTranslatorRegistry::~ExceptionTranslatorRegistry() { - } - - void ExceptionTranslatorRegistry::registerTranslator( const IExceptionTranslator* translator ) { - m_translators.push_back( std::unique_ptr( translator ) ); - } - - std::string ExceptionTranslatorRegistry::translateActiveException() const { - try { -#ifdef __OBJC__ - // In Objective-C try objective-c exceptions first - @try { - return tryTranslators(); - } - @catch (NSException *exception) { - return Catch::Detail::stringify( [exception description] ); - } #else - return tryTranslators(); -#endif - } - catch( TestFailureException& ) { - std::rethrow_exception(std::current_exception()); - } - catch( std::exception& ex ) { - return ex.what(); - } - catch( std::string& msg ) { - return msg; - } - catch( const char* msg ) { - return msg; - } - catch(...) { - return "Unknown exception"; + namespace Catch { + void writeToDebugConsole( std::string const& text ) { + // !TBD: Need a version for Mac/ XCode and other IDEs + Catch::cout() << text; } } +#endif // Platform - std::string ExceptionTranslatorRegistry::tryTranslators() const { - if( m_translators.empty() ) - std::rethrow_exception(std::current_exception()); - else - return m_translators[0]->translate( m_translators.begin()+1, m_translators.end() ); - } -} -// end catch_exception_translator_registry.cpp -// start catch_fatal_condition.cpp - -// start catch_fatal_condition.h - -#include - -#if defined ( CATCH_PLATFORM_WINDOWS ) ///////////////////////////////////////// - -# if !defined ( CATCH_CONFIG_WINDOWS_SEH ) - -namespace Catch { - struct FatalConditionHandler { - void reset(); - }; -} - -# else // CATCH_CONFIG_WINDOWS_SEH is defined +// #included from: catch_tostring.hpp +#define TWOBLUECUBES_CATCH_TOSTRING_HPP_INCLUDED namespace Catch { - struct FatalConditionHandler { +namespace Detail { - static LONG CALLBACK handleVectoredException(PEXCEPTION_POINTERS ExceptionInfo); - FatalConditionHandler(); - static void reset(); - ~FatalConditionHandler(); + const std::string unprintableString = "{?}"; - private: - static bool isSet; - static ULONG guaranteeSize; - static PVOID exceptionHandlerHandle; - }; + namespace { + const int hexThreshold = 255; -} // namespace Catch + struct Endianness { + enum Arch { Big, Little }; -# endif // CATCH_CONFIG_WINDOWS_SEH + static Arch which() { + union _{ + int asInt; + char asChar[sizeof (int)]; + } u; -#else // Not Windows - assumed to be POSIX compatible ////////////////////////// - -# if !defined(CATCH_CONFIG_POSIX_SIGNALS) - -namespace Catch { - struct FatalConditionHandler { - void reset(); - }; -} - -# else // CATCH_CONFIG_POSIX_SIGNALS is defined - -#include - -namespace Catch { - - struct FatalConditionHandler { - - static bool isSet; - static struct sigaction oldSigActions[];// [sizeof(signalDefs) / sizeof(SignalDefs)]; - static stack_t oldSigStack; - static char altStackMem[]; - - static void handleSignal( int sig ); - - FatalConditionHandler(); - ~FatalConditionHandler(); - static void reset(); - }; - -} // namespace Catch - -# endif // CATCH_CONFIG_POSIX_SIGNALS - -#endif // not Windows - -// end catch_fatal_condition.h -namespace { - // Report the error condition - void reportFatal( char const * const message ) { - Catch::getCurrentContext().getResultCapture()->handleFatalErrorCondition( message ); - } -} - -#if defined ( CATCH_PLATFORM_WINDOWS ) ///////////////////////////////////////// - -# if !defined ( CATCH_CONFIG_WINDOWS_SEH ) - -namespace Catch { - void FatalConditionHandler::reset() {} -} - -# else // CATCH_CONFIG_WINDOWS_SEH is defined - -namespace Catch { - struct SignalDefs { DWORD id; const char* name; }; - - // There is no 1-1 mapping between signals and windows exceptions. - // Windows can easily distinguish between SO and SigSegV, - // but SigInt, SigTerm, etc are handled differently. - static SignalDefs signalDefs[] = { - { EXCEPTION_ILLEGAL_INSTRUCTION, "SIGILL - Illegal instruction signal" }, - { EXCEPTION_STACK_OVERFLOW, "SIGSEGV - Stack overflow" }, - { EXCEPTION_ACCESS_VIOLATION, "SIGSEGV - Segmentation violation signal" }, - { EXCEPTION_INT_DIVIDE_BY_ZERO, "Divide by zero error" }, - }; - - LONG CALLBACK FatalConditionHandler::handleVectoredException(PEXCEPTION_POINTERS ExceptionInfo) { - for (auto const& def : signalDefs) { - if (ExceptionInfo->ExceptionRecord->ExceptionCode == def.id) { - reportFatal(def.name); + u.asInt = 1; + return ( u.asChar[sizeof(int)-1] == 1 ) ? Big : Little; } - } - // If its not an exception we care about, pass it along. - // This stops us from eating debugger breaks etc. - return EXCEPTION_CONTINUE_SEARCH; + }; } - FatalConditionHandler::FatalConditionHandler() { - isSet = true; - // 32k seems enough for Catch to handle stack overflow, - // but the value was found experimentally, so there is no strong guarantee - guaranteeSize = 32 * 1024; - exceptionHandlerHandle = nullptr; - // Register as first handler in current chain - exceptionHandlerHandle = AddVectoredExceptionHandler(1, handleVectoredException); - // Pass in guarantee size to be filled - SetThreadStackGuarantee(&guaranteeSize); - } - - void FatalConditionHandler::reset() { - if (isSet) { - // Unregister handler and restore the old guarantee - RemoveVectoredExceptionHandler(exceptionHandlerHandle); - SetThreadStackGuarantee(&guaranteeSize); - exceptionHandlerHandle = nullptr; - isSet = false; - } - } - - FatalConditionHandler::~FatalConditionHandler() { - reset(); - } - -bool FatalConditionHandler::isSet = false; -ULONG FatalConditionHandler::guaranteeSize = 0; -PVOID FatalConditionHandler::exceptionHandlerHandle = nullptr; - -} // namespace Catch - -# endif // CATCH_CONFIG_WINDOWS_SEH - -#else // Not Windows - assumed to be POSIX compatible ////////////////////////// - -# if !defined(CATCH_CONFIG_POSIX_SIGNALS) - -namespace Catch { - void FatalConditionHandler::reset() {} -} - -# else // CATCH_CONFIG_POSIX_SIGNALS is defined - -#include - -namespace Catch { - - struct SignalDefs { - int id; - const char* name; - }; - static SignalDefs signalDefs[] = { - { SIGINT, "SIGINT - Terminal interrupt signal" }, - { SIGILL, "SIGILL - Illegal instruction signal" }, - { SIGFPE, "SIGFPE - Floating point error signal" }, - { SIGSEGV, "SIGSEGV - Segmentation violation signal" }, - { SIGTERM, "SIGTERM - Termination request signal" }, - { SIGABRT, "SIGABRT - Abort (abnormal termination) signal" } - }; - - void FatalConditionHandler::handleSignal( int sig ) { - char const * name = ""; - for (auto const& def : signalDefs) { - if (sig == def.id) { - name = def.name; - break; - } - } - reset(); - reportFatal(name); - raise( sig ); - } - - FatalConditionHandler::FatalConditionHandler() { - isSet = true; - stack_t sigStack; - sigStack.ss_sp = altStackMem; - sigStack.ss_size = SIGSTKSZ; - sigStack.ss_flags = 0; - sigaltstack(&sigStack, &oldSigStack); - struct sigaction sa = { }; - - sa.sa_handler = handleSignal; - sa.sa_flags = SA_ONSTACK; - for (std::size_t i = 0; i < sizeof(signalDefs)/sizeof(SignalDefs); ++i) { - sigaction(signalDefs[i].id, &sa, &oldSigActions[i]); - } - } - - FatalConditionHandler::~FatalConditionHandler() { - reset(); - } - - void FatalConditionHandler::reset() { - if( isSet ) { - // Set signals back to previous values -- hopefully nobody overwrote them in the meantime - for( std::size_t i = 0; i < sizeof(signalDefs)/sizeof(SignalDefs); ++i ) { - sigaction(signalDefs[i].id, &oldSigActions[i], nullptr); - } - // Return the old stack - sigaltstack(&oldSigStack, nullptr); - isSet = false; - } - } - - bool FatalConditionHandler::isSet = false; - struct sigaction FatalConditionHandler::oldSigActions[sizeof(signalDefs)/sizeof(SignalDefs)] = {}; - stack_t FatalConditionHandler::oldSigStack = {}; - char FatalConditionHandler::altStackMem[SIGSTKSZ] = {}; - -} // namespace Catch - -# endif // CATCH_CONFIG_POSIX_SIGNALS - -#endif // not Windows -// end catch_fatal_condition.cpp -// start catch_interfaces_capture.cpp - -namespace Catch { - IResultCapture::~IResultCapture() = default; -} -// end catch_interfaces_capture.cpp -// start catch_interfaces_config.cpp - -namespace Catch { - IConfig::~IConfig() = default; -} -// end catch_interfaces_config.cpp -// start catch_interfaces_exception.cpp - -namespace Catch { - IExceptionTranslator::~IExceptionTranslator() = default; - IExceptionTranslatorRegistry::~IExceptionTranslatorRegistry() = default; -} -// end catch_interfaces_exception.cpp -// start catch_interfaces_registry_hub.cpp - -namespace Catch { - IRegistryHub::~IRegistryHub() = default; - IMutableRegistryHub::~IMutableRegistryHub() = default; -} -// end catch_interfaces_registry_hub.cpp -// start catch_interfaces_reporter.cpp - -// start catch_reporter_multi.h - -namespace Catch { - - class MultipleReporters : public IStreamingReporter { - using Reporters = std::vector; - Reporters m_reporters; - - public: - void add( IStreamingReporterPtr&& reporter ); - - public: // IStreamingReporter - - ReporterPreferences getPreferences() const override; - - void noMatchingTestCases( std::string const& spec ) override; - - static std::set getSupportedVerbosities(); - - void benchmarkStarting( BenchmarkInfo const& benchmarkInfo ) override; - void benchmarkEnded( BenchmarkStats const& benchmarkStats ) override; - - void testRunStarting( TestRunInfo const& testRunInfo ) override; - void testGroupStarting( GroupInfo const& groupInfo ) override; - void testCaseStarting( TestCaseInfo const& testInfo ) override; - void sectionStarting( SectionInfo const& sectionInfo ) override; - void assertionStarting( AssertionInfo const& assertionInfo ) override; - - // The return value indicates if the messages buffer should be cleared: - bool assertionEnded( AssertionStats const& assertionStats ) override; - void sectionEnded( SectionStats const& sectionStats ) override; - void testCaseEnded( TestCaseStats const& testCaseStats ) override; - void testGroupEnded( TestGroupStats const& testGroupStats ) override; - void testRunEnded( TestRunStats const& testRunStats ) override; - - void skipTest( TestCaseInfo const& testInfo ) override; - bool isMulti() const override; - - }; - -} // end namespace Catch - -// end catch_reporter_multi.h -namespace Catch { - - ReporterConfig::ReporterConfig( IConfigPtr const& _fullConfig ) - : m_stream( &_fullConfig->stream() ), m_fullConfig( _fullConfig ) {} - - ReporterConfig::ReporterConfig( IConfigPtr const& _fullConfig, std::ostream& _stream ) - : m_stream( &_stream ), m_fullConfig( _fullConfig ) {} - - std::ostream& ReporterConfig::stream() const { return *m_stream; } - IConfigPtr ReporterConfig::fullConfig() const { return m_fullConfig; } - - TestRunInfo::TestRunInfo( std::string const& _name ) : name( _name ) {} - - GroupInfo::GroupInfo( std::string const& _name, - std::size_t _groupIndex, - std::size_t _groupsCount ) - : name( _name ), - groupIndex( _groupIndex ), - groupsCounts( _groupsCount ) - {} - - AssertionStats::AssertionStats( AssertionResult const& _assertionResult, - std::vector const& _infoMessages, - Totals const& _totals ) - : assertionResult( _assertionResult ), - infoMessages( _infoMessages ), - totals( _totals ) + std::string rawMemoryToString( const void *object, std::size_t size ) { - assertionResult.m_resultData.lazyExpression.m_transientExpression = _assertionResult.m_resultData.lazyExpression.m_transientExpression; + // 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; + } - 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(); + 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(); + } +} - infoMessages.push_back( builder.m_info ); +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 ) { - AssertionStats::~AssertionStats() = default; + std::string s; + s.reserve( value.size() ); + for(size_t i = 0; i < value.size(); ++i ) + s += value[i] <= 0xff ? static_cast( value[i] ) : '?'; + return Catch::toString( s ); +} - SectionStats::SectionStats( SectionInfo const& _sectionInfo, - Counts const& _assertions, - double _durationInSeconds, - bool _missingAssertions ) - : sectionInfo( _sectionInfo ), - assertions( _assertions ), - durationInSeconds( _durationInSeconds ), - missingAssertions( _missingAssertions ) - {} +std::string toString( const char* const value ) { + return value ? Catch::toString( std::string( value ) ) : std::string( "{null string}" ); +} - SectionStats::~SectionStats() = default; +std::string toString( char* const value ) { + return Catch::toString( static_cast( value ) ); +} - 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 ) - {} +std::string toString( const wchar_t* const value ) +{ + return value ? Catch::toString( std::wstring(value) ) : std::string( "{null string}" ); +} - TestCaseStats::~TestCaseStats() = default; +std::string toString( wchar_t* const value ) +{ + return Catch::toString( static_cast( value ) ); +} - TestGroupStats::TestGroupStats( GroupInfo const& _groupInfo, - Totals const& _totals, - bool _aborting ) - : groupInfo( _groupInfo ), - totals( _totals ), - aborting( _aborting ) - {} +std::string toString( int value ) { + std::ostringstream oss; + oss << value; + if( value > Detail::hexThreshold ) + oss << " (0x" << std::hex << value << ')'; + return oss.str(); +} - TestGroupStats::TestGroupStats( GroupInfo const& _groupInfo ) - : groupInfo( _groupInfo ), - aborting( false ) - {} +std::string toString( unsigned long value ) { + std::ostringstream oss; + oss << value; + if( value > Detail::hexThreshold ) + oss << " (0x" << std::hex << value << ')'; + return oss.str(); +} - TestGroupStats::~TestGroupStats() = default; +std::string toString( unsigned int value ) { + return Catch::toString( static_cast( value ) ); +} - TestRunStats::TestRunStats( TestRunInfo const& _runInfo, - Totals const& _totals, - bool _aborting ) - : runInfo( _runInfo ), - totals( _totals ), - aborting( _aborting ) - {} - - TestRunStats::~TestRunStats() = default; - - void IStreamingReporter::fatalErrorEncountered( StringRef ) {} - bool IStreamingReporter::isMulti() const { return false; } - - IReporterFactory::~IReporterFactory() = default; - IReporterRegistry::~IReporterRegistry() = default; - - void addReporter( IStreamingReporterPtr& existingReporter, IStreamingReporterPtr&& additionalReporter ) { - - if( !existingReporter ) { - existingReporter = std::move( additionalReporter ); - return; - } - - MultipleReporters* multi = nullptr; - - if( existingReporter->isMulti() ) { - multi = static_cast( existingReporter.get() ); - } - else { - auto newMulti = std::unique_ptr( new MultipleReporters ); - newMulti->add( std::move( existingReporter ) ); - multi = newMulti.get(); - existingReporter = std::move( newMulti ); - } - multi->add( std::move( additionalReporter ) ); +template +std::string fpToString( T value, int precision ) { + std::ostringstream oss; + oss << std::setprecision( precision ) + << std::fixed + << value; + std::string d = oss.str(); + std::size_t i = d.find_last_not_of( '0' ); + if( i != std::string::npos && i != d.size()-1 ) { + if( d[i] == '.' ) + i++; + d = d.substr( 0, i+1 ); } - -} // end namespace Catch -// end catch_interfaces_reporter.cpp -// start catch_interfaces_runner.cpp - -namespace Catch { - IRunner::~IRunner() = default; + return d; } -// end catch_interfaces_runner.cpp -// start catch_interfaces_testcase.cpp -namespace Catch { - ITestInvoker::~ITestInvoker() = default; - ITestCaseRegistry::~ITestCaseRegistry() = default; +std::string toString( const double value ) { + return fpToString( value, 10 ); +} +std::string toString( const float value ) { + return fpToString( value, 5 ) + 'f'; } -// end catch_interfaces_testcase.cpp -// start catch_leak_detector.cpp -namespace Catch { +std::string toString( bool value ) { + return value ? "true" : "false"; +} -#ifdef CATCH_CONFIG_WINDOWS_CRTDBG -#include +std::string toString( char value ) { + if ( value == '\r' ) + return "'\\r'"; + if ( value == '\f' ) + return "'\\f'"; + if ( value == '\n' ) + return "'\\n'"; + if ( value == '\t' ) + return "'\\t'"; + if ( '\0' <= value && value < ' ' ) + return toString( static_cast( value ) ); + char chstr[] = "' '"; + chstr[1] = value; + return chstr; +} - LeakDetector::LeakDetector() { - int flag = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG); - flag |= _CRTDBG_LEAK_CHECK_DF; - flag |= _CRTDBG_ALLOC_MEM_DF; - _CrtSetDbgFlag(flag); - _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG); - _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR); - // Change this to leaking allocation's number to break there - _CrtSetBreakAlloc(-1); - } +std::string toString( signed char value ) { + return toString( static_cast( value ) ); +} -#else - - LeakDetector::LeakDetector(){} +std::string toString( unsigned char value ) { + return toString( static_cast( value ) ); +} +#ifdef CATCH_CONFIG_CPP11_LONG_LONG +std::string toString( long long value ) { + std::ostringstream oss; + oss << value; + if( value > Detail::hexThreshold ) + oss << " (0x" << std::hex << value << ')'; + return oss.str(); +} +std::string toString( unsigned long long value ) { + std::ostringstream oss; + oss << value; + if( value > Detail::hexThreshold ) + oss << " (0x" << std::hex << value << ')'; + return oss.str(); +} #endif +#ifdef CATCH_CONFIG_CPP11_NULLPTR +std::string toString( std::nullptr_t ) { + return "nullptr"; } -// end catch_leak_detector.cpp -// start catch_list.cpp +#endif -// start catch_list.h - -#include - -namespace Catch { - - std::size_t listTests( Config const& config ); - - std::size_t listTestsNamesOnly( Config const& config ); - - struct TagInfo { - void add( std::string const& spelling ); - std::string all() const; - - std::set spellings; - std::size_t count = 0; - }; - - std::size_t listTags( Config const& config ); - - std::size_t listReporters( Config const& /*config*/ ); - - Option list( Config const& config ); +#ifdef __OBJC__ + std::string toString( NSString const * const& nsstring ) { + if( !nsstring ) + return "nil"; + return "@" + toString([nsstring UTF8String]); + } + std::string toString( NSString * CATCH_ARC_STRONG & nsstring ) { + if( !nsstring ) + return "nil"; + return "@" + toString([nsstring UTF8String]); + } + std::string toString( NSObject* const& nsObject ) { + return toString( [nsObject description] ); + } +#endif } // end namespace Catch -// end catch_list.h -// start catch_text.h - -namespace Catch { - using namespace clara::TextFlow; -} - -// end catch_text.h -#include -#include -#include +// #included from: catch_result_builder.hpp +#define TWOBLUECUBES_CATCH_RESULT_BUILDER_HPP_INCLUDED namespace Catch { - std::size_t listTests( Config const& config ) { - TestSpec testSpec = config.testSpec(); - if( config.testSpec().hasFilters() ) - Catch::cout() << "Matching test cases:\n"; - else { - Catch::cout() << "All available test cases:\n"; - testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "*" ).testSpec(); + ResultBuilder::ResultBuilder( char const* macroName, + SourceLineInfo const& lineInfo, + char const* capturedExpression, + ResultDisposition::Flags resultDisposition, + char const* secondArg ) + : m_assertionInfo( macroName, lineInfo, capturedExpression, resultDisposition, secondArg ), + m_shouldDebugBreak( false ), + m_shouldThrow( false ), + m_guardException( false ), + m_usedStream( false ) + {} + + ResultBuilder::~ResultBuilder() { +#if defined(CATCH_CONFIG_FAST_COMPILE) + if ( m_guardException ) { + stream().oss << "Exception translation was disabled by CATCH_CONFIG_FAST_COMPILE"; + captureResult( ResultWas::ThrewException ); + getCurrentContext().getResultCapture()->exceptionEarlyReported(); + } +#endif + } + + 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; + } + + void ResultBuilder::endExpression( DecomposedExpression const& expr ) { + // Flip bool results if FalseTest flag is set + if( isFalseTest( m_assertionInfo.resultDisposition ) ) { + m_data.negate( expr.isBinaryExpression() ); } - auto matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config ); - for( auto const& testCaseInfo : matchedTestCases ) { - Colour::Code colour = testCaseInfo.isHidden() - ? Colour::SecondaryText - : Colour::None; - Colour colourGuard( colour ); + getResultCapture().assertionRun(); - Catch::cout() << Column( testCaseInfo.name ).initialIndent( 2 ).indent( 4 ) << "\n"; - if( config.verbosity() >= Verbosity::High ) { - Catch::cout() << Column( Catch::Detail::stringify( testCaseInfo.lineInfo ) ).indent(4) << std::endl; - std::string description = testCaseInfo.description; - if( description.empty() ) - description = "(NO DESCRIPTION)"; - Catch::cout() << Column( description ).indent(4) << std::endl; - } - if( !testCaseInfo.tags.empty() ) - Catch::cout() << Column( testCaseInfo.tagsAsString() ).indent( 6 ) << "\n"; + if(getCurrentContext().getConfig()->includeSuccessfulResults() || m_data.resultType != ResultWas::Ok) + { + AssertionResult result = build( expr ); + handleResult( result ); } - - if( !config.testSpec().hasFilters() ) - Catch::cout() << pluralise( matchedTestCases.size(), "test case" ) << '\n' << std::endl; else - Catch::cout() << pluralise( matchedTestCases.size(), "matching test case" ) << '\n' << std::endl; - return matchedTestCases.size(); + getResultCapture().assertionPassed(); } - 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 = filterTests( getAllTestCasesSorted( config ), testSpec, config ); - for( auto const& testCaseInfo : matchedTestCases ) { - matchedTests++; - if( startsWith( testCaseInfo.name, '#' ) ) - Catch::cout() << '"' << testCaseInfo.name << '"'; - else - Catch::cout() << testCaseInfo.name; - if ( config.verbosity() >= Verbosity::High ) - Catch::cout() << "\t@" << testCaseInfo.lineInfo; - Catch::cout() << std::endl; + void ResultBuilder::useActiveException( ResultDisposition::Flags resultDisposition ) { + m_assertionInfo.resultDisposition = resultDisposition; + stream().oss << Catch::translateActiveException(); + captureResult( ResultWas::ThrewException ); + } + + void ResultBuilder::captureResult( ResultWas::OfType resultType ) { + setResultType( resultType ); + captureExpression(); + } + + void ResultBuilder::captureExpectedException( std::string const& expectedMessage ) { + if( expectedMessage.empty() ) + captureExpectedException( Matchers::Impl::MatchAllOf() ); + else + captureExpectedException( Matchers::Equals( expectedMessage ) ); + } + + void ResultBuilder::captureExpectedException( Matchers::Impl::MatcherBase const& matcher ) { + + assert( !isFalseTest( m_assertionInfo.resultDisposition ) ); + AssertionResultData data = m_data; + data.resultType = ResultWas::Ok; + data.reconstructedExpression = capturedExpressionWithSecondArgument(m_assertionInfo.capturedExpression, m_assertionInfo.secondArg); + + std::string actualMessage = Catch::translateActiveException(); + if( !matcher.match( actualMessage ) ) { + data.resultType = ResultWas::ExpressionFailed; + data.reconstructedExpression = actualMessage; } - return matchedTests; + AssertionResult result( m_assertionInfo, data ); + handleResult( result ); } - void TagInfo::add( std::string const& spelling ) { - ++count; - spellings.insert( spelling ); + void ResultBuilder::captureExpression() { + AssertionResult result = build(); + handleResult( result ); } - std::string TagInfo::all() const { - std::string out; - for( auto const& spelling : spellings ) - out += "[" + spelling + "]"; - return out; - } + void ResultBuilder::handleResult( AssertionResult const& result ) + { + getResultCapture().assertionEnded( result ); - std::size_t listTags( Config const& config ) { - TestSpec testSpec = config.testSpec(); - if( config.testSpec().hasFilters() ) - Catch::cout() << "Tags for matching test cases:\n"; - else { - Catch::cout() << "All available tags:\n"; - testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "*" ).testSpec(); + if( !result.isOk() ) { + if( getCurrentContext().getConfig()->shouldDebugBreak() ) + m_shouldDebugBreak = true; + if( getCurrentContext().getRunner()->aborting() || (m_assertionInfo.resultDisposition & ResultDisposition::Normal) ) + m_shouldThrow = true; } - - std::map tagCounts; - - std::vector matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config ); - for( auto const& testCase : matchedTestCases ) { - for( auto const& tagName : testCase.getTestCaseInfo().tags ) { - std::string lcaseTagName = toLower( tagName ); - auto countIt = tagCounts.find( lcaseTagName ); - if( countIt == tagCounts.end() ) - countIt = tagCounts.insert( std::make_pair( lcaseTagName, TagInfo() ) ).first; - countIt->second.add( tagName ); - } - } - - for( auto const& tagCount : tagCounts ) { - std::ostringstream oss; - oss << " " << std::setw(2) << tagCount.second.count << " "; - auto wrapper = Column( tagCount.second.all() ) - .initialIndent( 0 ) - .indent( oss.str().size() ) - .width( CATCH_CONFIG_CONSOLE_WIDTH-10 ); - Catch::cout() << oss.str() << wrapper << '\n'; - } - Catch::cout() << pluralise( tagCounts.size(), "tag" ) << '\n' << std::endl; - return tagCounts.size(); } - std::size_t listReporters( Config const& /*config*/ ) { - Catch::cout() << "Available reporters:\n"; - IReporterRegistry::FactoryMap const& factories = getRegistryHub().getReporterRegistry().getFactories(); - std::size_t maxNameLen = 0; - for( auto const& factoryKvp : factories ) - maxNameLen = (std::max)( maxNameLen, factoryKvp.first.size() ); - - for( auto const& factoryKvp : factories ) { - Catch::cout() - << Column( factoryKvp.first + ":" ) - .indent(2) - .width( 5+maxNameLen ) - + Column( factoryKvp.second->getDescription() ) - .initialIndent(0) - .indent(2) - .width( CATCH_CONFIG_CONSOLE_WIDTH - maxNameLen-8 ) - << "\n"; + void ResultBuilder::react() { +#if defined(CATCH_CONFIG_FAST_COMPILE) + if (m_shouldDebugBreak) { + /////////////////////////////////////////////////////////////////// + // To inspect the state during test, you need to go one level up the callstack + // To go back to the test and change execution, jump over the throw statement + /////////////////////////////////////////////////////////////////// + CATCH_BREAK_INTO_DEBUGGER(); } - Catch::cout() << std::endl; - return factories.size(); +#endif + if( m_shouldThrow ) + throw Catch::TestFailureException(); } - 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; + bool ResultBuilder::shouldDebugBreak() const { return m_shouldDebugBreak; } + bool ResultBuilder::allowThrows() const { return getCurrentContext().getConfig()->allowThrows(); } + + AssertionResult ResultBuilder::build() const + { + return build( *this ); + } + + // CAVEAT: The returned AssertionResult stores a pointer to the argument expr, + // a temporary DecomposedExpression, which in turn holds references to + // operands, possibly temporary as well. + // It should immediately be passed to handleResult; if the expression + // needs to be reported, its string expansion must be composed before + // the temporaries are destroyed. + AssertionResult ResultBuilder::build( DecomposedExpression const& expr ) const + { + assert( m_data.resultType != ResultWas::Unknown ); + AssertionResultData data = m_data; + + if(m_usedStream) + data.message = m_stream().oss.str(); + data.decomposedExpression = &expr; // for lazy reconstruction + return AssertionResult( m_assertionInfo, data ); + } + + void ResultBuilder::reconstructExpression( std::string& dest ) const { + dest = capturedExpressionWithSecondArgument(m_assertionInfo.capturedExpression, m_assertionInfo.secondArg); + } + + void ResultBuilder::setExceptionGuard() { + m_guardException = true; + } + void ResultBuilder::unsetExceptionGuard() { + m_guardException = false; } } // end namespace Catch -// end catch_list.cpp -// start catch_matchers.cpp + +// #included from: catch_tag_alias_registry.hpp +#define TWOBLUECUBES_CATCH_TAG_ALIAS_REGISTRY_HPP_INCLUDED namespace Catch { -namespace Matchers { - namespace Impl { - std::string MatcherUntypedBase::toString() const { - if( m_cachedToString.empty() ) - m_cachedToString = describe(); - return m_cachedToString; + 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; + 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() ); + } } + return expandedTestSpec; + } - MatcherUntypedBase::~MatcherUntypedBase() = default; + void TagAliasRegistry::add( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo ) { - } // namespace Impl -} // namespace Matchers + if( !startsWith( alias, "[@" ) || !endsWith( alias, ']' ) ) { + std::ostringstream oss; + oss << Colour( Colour::Red ) + << "error: tag alias, \"" << alias << "\" is not of the form [@alias name].\n" + << Colour( Colour::FileName ) + << lineInfo << '\n'; + throw std::domain_error( oss.str().c_str() ); + } + if( !m_registry.insert( std::make_pair( alias, TagAlias( tag, lineInfo ) ) ).second ) { + std::ostringstream oss; + oss << Colour( Colour::Red ) + << "error: tag alias, \"" << alias << "\" already registered.\n" + << "\tFirst seen at " + << Colour( Colour::Red ) << find(alias)->lineInfo << '\n' + << Colour( Colour::Red ) << "\tRedefined at " + << Colour( Colour::FileName) << lineInfo << '\n'; + throw std::domain_error( oss.str().c_str() ); + } + } -using namespace Matchers; -using Matchers::Impl::MatcherBase; + ITagAliasRegistry::~ITagAliasRegistry() {} -} // namespace Catch -// end catch_matchers.cpp -// start catch_matchers_string.cpp + ITagAliasRegistry const& ITagAliasRegistry::get() { + return getRegistryHub().getTagAliasRegistry(); + } + + RegistrarForTagAliases::RegistrarForTagAliases( char const* alias, char const* tag, SourceLineInfo const& lineInfo ) { + getMutableRegistryHub().registerTagAlias( alias, tag, lineInfo ); + } + +} // end namespace Catch + +// #included from: catch_matchers_string.hpp namespace Catch { namespace Matchers { @@ -7151,2732 +9401,517 @@ namespace Matchers { } // namespace Matchers } // namespace Catch -// end catch_matchers_string.cpp -// start catch_message.cpp +// #included from: ../reporters/catch_reporter_multi.hpp +#define TWOBLUECUBES_CATCH_REPORTER_MULTI_HPP_INCLUDED namespace Catch { - MessageInfo::MessageInfo( std::string const& _macroName, - SourceLineInfo const& _lineInfo, - ResultWas::OfType _type ) - : macroName( _macroName ), - lineInfo( _lineInfo ), - type( _type ), - sequence( ++globalCount ) - {} +class MultipleReporters : public SharedImpl { + typedef std::vector > Reporters; + Reporters m_reporters; - bool MessageInfo::operator==( MessageInfo const& other ) const { - return sequence == other.sequence; +public: + void add( Ptr const& reporter ) { + m_reporters.push_back( reporter ); } - bool MessageInfo::operator<( MessageInfo const& other ) const { - return sequence < other.sequence; +public: // IStreamingReporter + + virtual ReporterPreferences getPreferences() const CATCH_OVERRIDE { + return m_reporters[0]->getPreferences(); } - // This may need protecting if threading support is added - unsigned int MessageInfo::globalCount = 0; - - //////////////////////////////////////////////////////////////////////////// - - Catch::MessageBuilder::MessageBuilder( std::string const& macroName, - SourceLineInfo const& lineInfo, - ResultWas::OfType type ) - :m_info(macroName, lineInfo, type) {} - - //////////////////////////////////////////////////////////////////////////// - - ScopedMessage::ScopedMessage( MessageBuilder const& builder ) - : m_info( builder.m_info ) - { - m_info.message = builder.m_stream.str(); - getResultCapture().pushScopedMessage( m_info ); + virtual void noMatchingTestCases( std::string const& spec ) CATCH_OVERRIDE { + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + (*it)->noMatchingTestCases( spec ); } - ScopedMessage::~ScopedMessage() { - if ( !std::uncaught_exception() ){ - getResultCapture().popScopedMessage(m_info); + virtual void testRunStarting( TestRunInfo const& testRunInfo ) CATCH_OVERRIDE { + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + (*it)->testRunStarting( testRunInfo ); + } + + virtual void testGroupStarting( GroupInfo const& groupInfo ) CATCH_OVERRIDE { + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + (*it)->testGroupStarting( groupInfo ); + } + + virtual void testCaseStarting( TestCaseInfo const& testInfo ) CATCH_OVERRIDE { + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + (*it)->testCaseStarting( testInfo ); + } + + virtual void sectionStarting( SectionInfo const& sectionInfo ) CATCH_OVERRIDE { + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + (*it)->sectionStarting( sectionInfo ); + } + + virtual void assertionStarting( AssertionInfo const& assertionInfo ) CATCH_OVERRIDE { + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + (*it)->assertionStarting( assertionInfo ); + } + + // The return value indicates if the messages buffer should be cleared: + virtual bool assertionEnded( AssertionStats const& assertionStats ) CATCH_OVERRIDE { + bool clearBuffer = false; + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + clearBuffer |= (*it)->assertionEnded( assertionStats ); + return clearBuffer; + } + + virtual void sectionEnded( SectionStats const& sectionStats ) CATCH_OVERRIDE { + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + (*it)->sectionEnded( sectionStats ); + } + + virtual void testCaseEnded( TestCaseStats const& testCaseStats ) CATCH_OVERRIDE { + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + (*it)->testCaseEnded( testCaseStats ); + } + + virtual void testGroupEnded( TestGroupStats const& testGroupStats ) CATCH_OVERRIDE { + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + (*it)->testGroupEnded( testGroupStats ); + } + + virtual void testRunEnded( TestRunStats const& testRunStats ) CATCH_OVERRIDE { + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + (*it)->testRunEnded( testRunStats ); + } + + virtual void skipTest( TestCaseInfo const& testInfo ) CATCH_OVERRIDE { + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + (*it)->skipTest( testInfo ); + } + + virtual MultipleReporters* tryAsMulti() CATCH_OVERRIDE { + return this; + } + +}; + +Ptr addReporter( Ptr const& existingReporter, Ptr const& additionalReporter ) { + Ptr resultingReporter; + + if( existingReporter ) { + MultipleReporters* multi = existingReporter->tryAsMulti(); + if( !multi ) { + multi = new MultipleReporters; + resultingReporter = Ptr( multi ); + if( existingReporter ) + multi->add( existingReporter ); } + else + resultingReporter = existingReporter; + multi->add( additionalReporter ); } + else + resultingReporter = additionalReporter; -} // end namespace Catch -// end catch_message.cpp -// start catch_random_number_generator.cpp - -// start catch_random_number_generator.h - -#include - -namespace Catch { - - struct IConfig; - - void seedRng( IConfig const& config ); - - unsigned int rngSeed(); - - struct RandomNumberGenerator { - using result_type = unsigned int; - - static constexpr result_type (min)() { return 0; } - static constexpr result_type (max)() { return 1000000; } - - result_type operator()( result_type n ) const; - result_type operator()() const; - - template - static void shuffle( V& vector ) { - RandomNumberGenerator rng; - std::shuffle( vector.begin(), vector.end(), rng ); - } - }; - + return resultingReporter; } -// end catch_random_number_generator.h -#include - -namespace Catch { - - void seedRng( IConfig const& config ) { - if( config.rngSeed() != 0 ) - std::srand( config.rngSeed() ); - } - unsigned int rngSeed() { - return getCurrentContext().getConfig()->rngSeed(); - } - - RandomNumberGenerator::result_type RandomNumberGenerator::operator()( result_type n ) const { - return std::rand() % n; - } - RandomNumberGenerator::result_type RandomNumberGenerator::operator()() const { - return std::rand() % (max)(); - } - -} -// end catch_random_number_generator.cpp -// start catch_registry_hub.cpp - -// start catch_test_case_registry_impl.h - -#include -#include -#include -#include - -namespace Catch { - - class TestCase; - struct IConfig; - - std::vector sortTests( IConfig const& config, std::vector const& unsortedTestCases ); - bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config ); - - void enforceNoDuplicateTestCases( std::vector const& functions ); - - std::vector filterTests( std::vector const& testCases, TestSpec const& testSpec, IConfig const& config ); - std::vector const& getAllTestCasesSorted( IConfig const& config ); - - class TestRegistry : public ITestCaseRegistry { - public: - virtual ~TestRegistry() = default; - - virtual void registerTest( TestCase const& testCase ); - - std::vector const& getAllTests() const override; - std::vector const& getAllTestsSorted( IConfig const& config ) const override; - - private: - std::vector m_functions; - mutable RunTests::InWhatOrder m_currentSortOrder = RunTests::InDeclarationOrder; - mutable std::vector m_sortedFunctions; - std::size_t m_unnamedCount = 0; - std::ios_base::Init m_ostreamInit; // Forces cout/ cerr to be initialised - }; - - /////////////////////////////////////////////////////////////////////////// - - class TestInvokerAsFunction : public ITestInvoker { - void(*m_testAsFunction)(); - public: - TestInvokerAsFunction( void(*testAsFunction)() ) noexcept; - - void invoke() const override; - }; - - std::string extractClassName( std::string const& classOrQualifiedMethodName ); - - /////////////////////////////////////////////////////////////////////////// - } // end namespace Catch -// end catch_test_case_registry_impl.h -// start catch_reporter_registry.h +// #included from: ../reporters/catch_reporter_xml.hpp +#define TWOBLUECUBES_CATCH_REPORTER_XML_HPP_INCLUDED -#include +// #included from: catch_reporter_bases.hpp +#define TWOBLUECUBES_CATCH_REPORTER_BASES_HPP_INCLUDED -namespace Catch { +#include +#include +#include +#include - class ReporterRegistry : public IReporterRegistry { - - public: - - ~ReporterRegistry() override; - - IStreamingReporterPtr create( std::string const& name, IConfigPtr const& config ) const override; - - void registerReporter( std::string const& name, IReporterFactoryPtr const& factory ); - void registerListener( IReporterFactoryPtr const& factory ); - - FactoryMap const& getFactories() const override; - Listeners const& getListeners() const override; - - private: - FactoryMap m_factories; - Listeners m_listeners; - }; -} - -// end catch_reporter_registry.h -// start catch_tag_alias_registry.h - -// start catch_tag_alias.h - -#include - -namespace Catch { - - struct TagAlias { - TagAlias(std::string const& _tag, SourceLineInfo _lineInfo); - - std::string tag; - SourceLineInfo lineInfo; - }; - -} // end namespace Catch - -// end catch_tag_alias.h -#include - -namespace Catch { - - class TagAliasRegistry : public ITagAliasRegistry { - public: - ~TagAliasRegistry() override; - TagAlias const* find( std::string const& alias ) const override; - std::string expandAliases( std::string const& unexpandedTestSpec ) const override; - void add( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo ); - - private: - std::map m_registry; - }; - -} // end namespace Catch - -// end catch_tag_alias_registry.h -// start catch_startup_exception_registry.h - -#include -#include - -namespace Catch { - - class StartupExceptionRegistry { - public: - void add(std::exception_ptr const& exception) noexcept; - std::vector const& getExceptions() const noexcept; - private: - std::vector m_exceptions; - }; - -} // end namespace Catch - -// end catch_startup_exception_registry.h namespace Catch { namespace { + // Because formatting using c++ streams is stateful, drop down to C is required + // Alternatively we could use stringstream, but its performance is... not good. + std::string getFormattedDuration( double duration ) { + // Max exponent + 1 is required to represent the whole part + // + 1 for decimal point + // + 3 for the 3 decimal places + // + 1 for null terminator + const size_t maxDoubleSize = DBL_MAX_10_EXP + 1 + 1 + 3 + 1; + char buffer[maxDoubleSize]; - class RegistryHub : public IRegistryHub, public IMutableRegistryHub, - private NonCopyable { + // Save previous errno, to prevent sprintf from overwriting it + ErrnoGuard guard; +#ifdef _MSC_VER + sprintf_s(buffer, "%.3f", duration); +#else + sprintf(buffer, "%.3f", duration); +#endif + return std::string(buffer); + } + } - public: // IRegistryHub - RegistryHub() = default; - IReporterRegistry const& getReporterRegistry() const override { - return m_reporterRegistry; + struct StreamingReporterBase : SharedImpl { + + StreamingReporterBase( ReporterConfig const& _config ) + : m_config( _config.fullConfig() ), + stream( _config.stream() ) + { + m_reporterPrefs.shouldRedirectStdOut = false; + } + + virtual ReporterPreferences getPreferences() const CATCH_OVERRIDE { + return m_reporterPrefs; + } + + virtual ~StreamingReporterBase() CATCH_OVERRIDE; + + virtual void noMatchingTestCases( std::string const& ) CATCH_OVERRIDE {} + + virtual void testRunStarting( TestRunInfo const& _testRunInfo ) CATCH_OVERRIDE { + currentTestRunInfo = _testRunInfo; + } + virtual void testGroupStarting( GroupInfo const& _groupInfo ) CATCH_OVERRIDE { + currentGroupInfo = _groupInfo; + } + + virtual void testCaseStarting( TestCaseInfo const& _testInfo ) CATCH_OVERRIDE { + currentTestCaseInfo = _testInfo; + } + virtual void sectionStarting( SectionInfo const& _sectionInfo ) CATCH_OVERRIDE { + m_sectionStack.push_back( _sectionInfo ); + } + + virtual void sectionEnded( SectionStats const& /* _sectionStats */ ) CATCH_OVERRIDE { + m_sectionStack.pop_back(); + } + virtual void testCaseEnded( TestCaseStats const& /* _testCaseStats */ ) CATCH_OVERRIDE { + currentTestCaseInfo.reset(); + } + virtual void testGroupEnded( TestGroupStats const& /* _testGroupStats */ ) CATCH_OVERRIDE { + currentGroupInfo.reset(); + } + virtual void testRunEnded( TestRunStats const& /* _testRunStats */ ) CATCH_OVERRIDE { + currentTestCaseInfo.reset(); + currentGroupInfo.reset(); + currentTestRunInfo.reset(); + } + + virtual void skipTest( TestCaseInfo const& ) CATCH_OVERRIDE { + // Don't do anything with this by default. + // It can optionally be overridden in the derived class. + } + + Ptr m_config; + std::ostream& stream; + + LazyStat currentTestRunInfo; + LazyStat currentGroupInfo; + LazyStat currentTestCaseInfo; + + std::vector m_sectionStack; + ReporterPreferences m_reporterPrefs; + }; + + 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; } - ITestCaseRegistry const& getTestCaseRegistry() const override { - return m_testCaseRegistry; - } - IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() override { - return m_exceptionTranslatorRegistry; - } - ITagAliasRegistry const& getTagAliasRegistry() const override { - return m_tagAliasRegistry; - } - StartupExceptionRegistry const& getStartupExceptionRegistry() const override { - return m_exceptionRegistry; + bool operator == ( Ptr const& other ) const { + return operator==( *other ); } - public: // IMutableRegistryHub - void registerReporter( std::string const& name, IReporterFactoryPtr const& factory ) override { - m_reporterRegistry.registerReporter( name, factory ); - } - void registerListener( IReporterFactoryPtr const& factory ) override { - m_reporterRegistry.registerListener( factory ); - } - void registerTest( TestCase const& testInfo ) override { - m_testCaseRegistry.registerTest( testInfo ); - } - void registerTranslator( const IExceptionTranslator* translator ) override { - m_exceptionTranslatorRegistry.registerTranslator( translator ); - } - void registerTagAlias( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo ) override { - m_tagAliasRegistry.add( alias, tag, lineInfo ); - } - void registerStartupException() noexcept override { - m_exceptionRegistry.add(std::current_exception()); - } - - private: - TestRegistry m_testCaseRegistry; - ReporterRegistry m_reporterRegistry; - ExceptionTranslatorRegistry m_exceptionTranslatorRegistry; - TagAliasRegistry m_tagAliasRegistry; - StartupExceptionRegistry m_exceptionRegistry; + SectionStats stats; + typedef std::vector > ChildSections; + typedef std::vector Assertions; + ChildSections childSections; + Assertions assertions; + std::string stdOut; + std::string stdErr; }; - // Single, global, instance - RegistryHub*& getTheRegistryHub() { - static RegistryHub* theRegistryHub = nullptr; - if( !theRegistryHub ) - theRegistryHub = new RegistryHub(); - return theRegistryHub; - } - } - - IRegistryHub& getRegistryHub() { - return *getTheRegistryHub(); - } - IMutableRegistryHub& getMutableRegistryHub() { - return *getTheRegistryHub(); - } - void cleanUp() { - delete getTheRegistryHub(); - getTheRegistryHub() = nullptr; - cleanUpContext(); - } - std::string translateActiveException() { - return getRegistryHub().getExceptionTranslatorRegistry().translateActiveException(); - } - -} // end namespace Catch -// end catch_registry_hub.cpp -// start catch_reporter_registry.cpp - -namespace Catch { - - ReporterRegistry::~ReporterRegistry() = default; - - IStreamingReporterPtr ReporterRegistry::create( std::string const& name, IConfigPtr const& config ) const { - auto it = m_factories.find( name ); - if( it == m_factories.end() ) - return nullptr; - return it->second->create( ReporterConfig( config ) ); - } - - void ReporterRegistry::registerReporter( std::string const& name, IReporterFactoryPtr const& factory ) { - m_factories.emplace(name, factory); - } - void ReporterRegistry::registerListener( IReporterFactoryPtr const& factory ) { - m_listeners.push_back( factory ); - } - - IReporterRegistry::FactoryMap const& ReporterRegistry::getFactories() const { - return m_factories; - } - IReporterRegistry::Listeners const& ReporterRegistry::getListeners() const { - return m_listeners; - } - -} -// end catch_reporter_registry.cpp -// start catch_result_type.cpp - -namespace Catch { - - bool isOk( ResultWas::OfType resultType ) { - return ( resultType & ResultWas::FailureBit ) == 0; - } - bool isJustInfo( int flags ) { - return flags == ResultWas::Info; - } - - ResultDisposition::Flags operator | ( ResultDisposition::Flags lhs, ResultDisposition::Flags rhs ) { - return static_cast( static_cast( lhs ) | static_cast( rhs ) ); - } - - bool shouldContinueOnFailure( int flags ) { return ( flags & ResultDisposition::ContinueOnFailure ) != 0; } - bool isFalseTest( int flags ) { return ( flags & ResultDisposition::FalseTest ) != 0; } - bool shouldSuppressFailure( int flags ) { return ( flags & ResultDisposition::SuppressFail ) != 0; } - -} // end namespace Catch -// end catch_result_type.cpp -// start catch_run_context.cpp -// start catch_run_context.h - -#include - -namespace Catch { - - struct IMutableContext; - - class StreamRedirect { - - public: - StreamRedirect(std::ostream& stream, std::string& targetString); - - ~StreamRedirect(); - - private: - std::ostream& m_stream; - std::streambuf* m_prevBuf; - std::ostringstream m_oss; - std::string& m_targetString; - }; - - // StdErr has two constituent streams in C++, std::cerr and std::clog - // This means that we need to redirect 2 streams into 1 to keep proper - // order of writes and cannot use StreamRedirect on its own - class StdErrRedirect { - public: - StdErrRedirect(std::string& targetString); - ~StdErrRedirect(); - private: - std::streambuf* m_cerrBuf; - std::streambuf* m_clogBuf; - std::ostringstream m_oss; - std::string& m_targetString; - }; - - /////////////////////////////////////////////////////////////////////////// - - class RunContext : public IResultCapture, public IRunner { - - public: - RunContext( RunContext const& ) = delete; - RunContext& operator =( RunContext const& ) = delete; - - explicit RunContext(IConfigPtr const& _config, IStreamingReporterPtr&& reporter); - - virtual ~RunContext(); - - void testGroupStarting(std::string const& testSpec, std::size_t groupIndex, std::size_t groupsCount); - void testGroupEnded(std::string const& testSpec, Totals const& totals, std::size_t groupIndex, std::size_t groupsCount); - - Totals runTest(TestCase const& testCase); - - IConfigPtr config() const; - IStreamingReporter& reporter() const; - - private: // IResultCapture - - void assertionStarting(AssertionInfo const& info) override; - void assertionEnded(AssertionResult const& result) override; - - bool sectionStarted( SectionInfo const& sectionInfo, Counts& assertions ) override; - bool testForMissingAssertions(Counts& assertions); - - void sectionEnded(SectionEndInfo const& endInfo) override; - void sectionEndedEarly(SectionEndInfo const& endInfo) override; - - void benchmarkStarting( BenchmarkInfo const& info ) override; - void benchmarkEnded( BenchmarkStats const& stats ) override; - - void pushScopedMessage(MessageInfo const& message) override; - void popScopedMessage(MessageInfo const& message) override; - - std::string getCurrentTestName() const override; - - const AssertionResult* getLastResult() const override; - - void exceptionEarlyReported() override; - - void handleFatalErrorCondition( StringRef message ) override; - - bool lastAssertionPassed() override; - - void assertionPassed() override; - - void assertionRun() override; - - public: - // !TBD We need to do this another way! - bool aborting() const override; - - private: - - void runCurrentTest(std::string& redirectedCout, std::string& redirectedCerr); - void invokeActiveTestCase(); - - private: - - void handleUnfinishedSections(); - - TestRunInfo m_runInfo; - IMutableContext& m_context; - TestCase const* m_activeTestCase = nullptr; - ITracker* m_testCaseTracker; - Option m_lastResult; - - IConfigPtr m_config; - Totals m_totals; - IStreamingReporterPtr m_reporter; - std::vector m_messages; - AssertionInfo m_lastAssertionInfo; - std::vector m_unfinishedSections; - std::vector m_activeSections; - TrackerContext m_trackerContext; - std::size_t m_prevPassed = 0; - bool m_shouldReportUnexpected = true; - }; - - IResultCapture& getResultCapture(); - -} // end namespace Catch - -// end catch_run_context.h - -#include -#include - -namespace Catch { - - StreamRedirect::StreamRedirect(std::ostream& stream, std::string& targetString) - : m_stream(stream), - m_prevBuf(stream.rdbuf()), - m_targetString(targetString) { - stream.rdbuf(m_oss.rdbuf()); - } - - StreamRedirect::~StreamRedirect() { - m_targetString += m_oss.str(); - m_stream.rdbuf(m_prevBuf); - } - - StdErrRedirect::StdErrRedirect(std::string & targetString) - :m_cerrBuf(cerr().rdbuf()), m_clogBuf(clog().rdbuf()), - m_targetString(targetString) { - cerr().rdbuf(m_oss.rdbuf()); - clog().rdbuf(m_oss.rdbuf()); - } - - StdErrRedirect::~StdErrRedirect() { - m_targetString += m_oss.str(); - cerr().rdbuf(m_cerrBuf); - clog().rdbuf(m_clogBuf); - } - - RunContext::RunContext(IConfigPtr const& _config, IStreamingReporterPtr&& reporter) - : m_runInfo(_config->name()), - m_context(getCurrentMutableContext()), - m_config(_config), - m_reporter(std::move(reporter)), - m_lastAssertionInfo{ "", SourceLineInfo("",0), "", ResultDisposition::Normal } - { - m_context.setRunner(this); - m_context.setConfig(m_config); - m_context.setResultCapture(this); - m_reporter->testRunStarting(m_runInfo); - } - - RunContext::~RunContext() { - m_reporter->testRunEnded(TestRunStats(m_runInfo, m_totals, aborting())); - } - - void RunContext::testGroupStarting(std::string const& testSpec, std::size_t groupIndex, std::size_t groupsCount) { - m_reporter->testGroupStarting(GroupInfo(testSpec, groupIndex, groupsCount)); - } - - void RunContext::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 RunContext::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; - - ITracker& rootTracker = m_trackerContext.startRun(); - assert(rootTracker.isSectionTracker()); - static_cast(rootTracker).addInitialFilters(m_config->getSectionsToRun()); - do { - m_trackerContext.startCycle(); - m_testCaseTracker = &SectionTracker::acquire(m_trackerContext, TestCaseTracking::NameAndLocation(testInfo.name, testInfo.lineInfo)); - runCurrentTest(redirectedCout, redirectedCerr); - } while (!m_testCaseTracker->isSuccessfullyCompleted() && !aborting()); - - Totals deltaTotals = m_totals.delta(prevTotals); - if (testInfo.expectedToFail() && deltaTotals.testCases.passed > 0) { - deltaTotals.assertions.failed++; - deltaTotals.testCases.passed--; - deltaTotals.testCases.failed++; - } - m_totals.testCases += deltaTotals.testCases; - m_reporter->testCaseEnded(TestCaseStats(testInfo, - deltaTotals, - redirectedCout, - redirectedCerr, - aborting())); - - m_activeTestCase = nullptr; - m_testCaseTracker = nullptr; - - return deltaTotals; - } - - IConfigPtr RunContext::config() const { - return m_config; - } - - IStreamingReporter& RunContext::reporter() const { - return *m_reporter; - } - - void RunContext::assertionStarting(AssertionInfo const& info) { - m_reporter->assertionStarting( info ); - } - void RunContext::assertionEnded(AssertionResult const & result) { - if (result.getResultType() == ResultWas::Ok) { - m_totals.assertions.passed++; - } else if (!result.isOk()) { - if( m_activeTestCase->getTestCaseInfo().okToFail() ) - m_totals.assertions.failedButOk++; - else - m_totals.assertions.failed++; - } - - // We have no use for the return value (whether messages should be cleared), because messages were made scoped - // and should be let to clear themselves out. - static_cast(m_reporter->assertionEnded(AssertionStats(result, m_messages, m_totals))); - - // Reset working state - m_lastAssertionInfo = { "", m_lastAssertionInfo.lineInfo, "{Unknown expression after the reported line}", m_lastAssertionInfo.resultDisposition }; - m_lastResult = result; - } - - bool RunContext::sectionStarted(SectionInfo const & sectionInfo, Counts & assertions) { - ITracker& sectionTracker = SectionTracker::acquire(m_trackerContext, TestCaseTracking::NameAndLocation(sectionInfo.name, sectionInfo.lineInfo)); - if (!sectionTracker.isOpen()) - return false; - m_activeSections.push_back(§ionTracker); - - m_lastAssertionInfo.lineInfo = sectionInfo.lineInfo; - - m_reporter->sectionStarting(sectionInfo); - - assertions = m_totals.assertions; - - return true; - } - - bool RunContext::testForMissingAssertions(Counts& assertions) { - if (assertions.total() != 0) - return false; - if (!m_config->warnAboutMissingAssertions()) - return false; - if (m_trackerContext.currentTracker().hasChildren()) - return false; - m_totals.assertions.failed++; - assertions.failed++; - return true; - } - - void RunContext::sectionEnded(SectionEndInfo const & endInfo) { - Counts assertions = m_totals.assertions - endInfo.prevAssertions; - bool missingAssertions = testForMissingAssertions(assertions); - - if (!m_activeSections.empty()) { - m_activeSections.back()->close(); - m_activeSections.pop_back(); - } - - m_reporter->sectionEnded(SectionStats(endInfo.sectionInfo, assertions, endInfo.durationInSeconds, missingAssertions)); - m_messages.clear(); - } - - void RunContext::sectionEndedEarly(SectionEndInfo const & endInfo) { - if (m_unfinishedSections.empty()) - m_activeSections.back()->fail(); - else - m_activeSections.back()->close(); - m_activeSections.pop_back(); - - m_unfinishedSections.push_back(endInfo); - } - void RunContext::benchmarkStarting( BenchmarkInfo const& info ) { - m_reporter->benchmarkStarting( info ); - } - void RunContext::benchmarkEnded( BenchmarkStats const& stats ) { - m_reporter->benchmarkEnded( stats ); - } - - void RunContext::pushScopedMessage(MessageInfo const & message) { - m_messages.push_back(message); - } - - void RunContext::popScopedMessage(MessageInfo const & message) { - m_messages.erase(std::remove(m_messages.begin(), m_messages.end(), message), m_messages.end()); - } - - std::string RunContext::getCurrentTestName() const { - return m_activeTestCase - ? m_activeTestCase->getTestCaseInfo().name - : std::string(); - } - - const AssertionResult * RunContext::getLastResult() const { - return &(*m_lastResult); - } - - void RunContext::exceptionEarlyReported() { - m_shouldReportUnexpected = false; - } - - void RunContext::handleFatalErrorCondition( StringRef message ) { - // First notify reporter that bad things happened - m_reporter->fatalErrorEncountered(message); - - // Don't rebuild the result -- the stringification itself can cause more fatal errors - // Instead, fake a result data. - AssertionResultData tempResult( ResultWas::FatalErrorCondition, { false } ); - tempResult.message = message; - AssertionResult result(m_lastAssertionInfo, tempResult); - - getResultCapture().assertionEnded(result); - - handleUnfinishedSections(); - - // Recreate section for test case (as we will lose the one that was in scope) - auto const& testCaseInfo = m_activeTestCase->getTestCaseInfo(); - SectionInfo testCaseSection(testCaseInfo.lineInfo, testCaseInfo.name, testCaseInfo.description); - - Counts assertions; - assertions.failed = 1; - SectionStats testCaseSectionStats(testCaseSection, assertions, 0, false); - m_reporter->sectionEnded(testCaseSectionStats); - - auto const& testInfo = m_activeTestCase->getTestCaseInfo(); - - Totals deltaTotals; - deltaTotals.testCases.failed = 1; - deltaTotals.assertions.failed = 1; - m_reporter->testCaseEnded(TestCaseStats(testInfo, - deltaTotals, - std::string(), - std::string(), - false)); - m_totals.testCases.failed++; - testGroupEnded(std::string(), m_totals, 1, 1); - m_reporter->testRunEnded(TestRunStats(m_runInfo, m_totals, false)); - } - - bool RunContext::lastAssertionPassed() { - return m_totals.assertions.passed == (m_prevPassed + 1); - } - - void RunContext::assertionPassed() { - ++m_totals.assertions.passed; - m_lastAssertionInfo.capturedExpression = "{Unknown expression after the reported line}"; - m_lastAssertionInfo.macroName = ""; - } - - void RunContext::assertionRun() { - m_prevPassed = m_totals.assertions.passed; - } - - bool RunContext::aborting() const { - return m_totals.assertions.failed == static_cast(m_config->abortAfter()); - } - - void RunContext::runCurrentTest(std::string & redirectedCout, std::string & redirectedCerr) { - auto 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; - m_shouldReportUnexpected = true; - try { - m_lastAssertionInfo = { "TEST_CASE", testCaseInfo.lineInfo, "", ResultDisposition::Normal }; - - seedRng(*m_config); - - Timer timer; - timer.start(); - if (m_reporter->getPreferences().shouldRedirectStdOut) { - StreamRedirect coutRedir(cout(), redirectedCout); - StdErrRedirect errRedir(redirectedCerr); - invokeActiveTestCase(); - } else { - invokeActiveTestCase(); + 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.name == m_other.name) && + (node->stats.sectionInfo.lineInfo == m_other.lineInfo)); } - duration = timer.getElapsedSeconds(); - } catch (TestFailureException&) { - // This just means the test was aborted due to failure - } catch (...) { - // Under CATCH_CONFIG_FAST_COMPILE, unexpected exceptions under REQUIRE assertions - // are reported without translation at the point of origin. - if (m_shouldReportUnexpected) { - AssertionHandler - ( m_lastAssertionInfo.macroName, - m_lastAssertionInfo.lineInfo, - m_lastAssertionInfo.capturedExpression, - m_lastAssertionInfo.resultDisposition ).useActiveException(); - } - } - m_testCaseTracker->close(); - handleUnfinishedSections(); - m_messages.clear(); - - Counts assertions = m_totals.assertions - prevAssertions; - bool missingAssertions = testForMissingAssertions(assertions); - SectionStats testCaseSectionStats(testCaseSection, assertions, duration, missingAssertions); - m_reporter->sectionEnded(testCaseSectionStats); - } - - void RunContext::invokeActiveTestCase() { - FatalConditionHandler fatalConditionHandler; // Handle signals - m_activeTestCase->invoke(); - fatalConditionHandler.reset(); - } - - void RunContext::handleUnfinishedSections() { - // If sections ended prematurely due to an exception we stored their - // infos here so we can tear them down outside the unwind process. - for (auto it = m_unfinishedSections.rbegin(), - itEnd = m_unfinishedSections.rend(); - it != itEnd; - ++it) - sectionEnded(*it); - m_unfinishedSections.clear(); - } - - IResultCapture& getResultCapture() { - if (auto* capture = getCurrentContext().getResultCapture()) - return *capture; - else - CATCH_INTERNAL_ERROR("No result capture instance"); - } -} -// end catch_run_context.cpp -// start catch_section.cpp - -namespace Catch { - - Section::Section( SectionInfo const& info ) - : m_info( info ), - m_sectionIncluded( getResultCapture().sectionStarted( m_info, m_assertions ) ) - { - m_timer.start(); - } - -#if defined(_MSC_VER) -#pragma warning(push) -#pragma warning(disable:4996) // std::uncaught_exception is deprecated in C++17 -#endif - Section::~Section() { - if( m_sectionIncluded ) { - SectionEndInfo endInfo( m_info, m_assertions, m_timer.getElapsedSeconds() ); - if( std::uncaught_exception() ) - getResultCapture().sectionEndedEarly( endInfo ); - else - getResultCapture().sectionEnded( endInfo ); - } - } -#if defined(_MSC_VER) -#pragma warning(pop) -#endif - - // This indicates whether the section should be executed or not - Section::operator bool() const { - return m_sectionIncluded; - } - -} // end namespace Catch -// end catch_section.cpp -// start catch_section_info.cpp - -namespace Catch { - - SectionInfo::SectionInfo - ( SourceLineInfo const& _lineInfo, - std::string const& _name, - std::string const& _description ) - : name( _name ), - description( _description ), - lineInfo( _lineInfo ) - {} - - SectionEndInfo::SectionEndInfo( SectionInfo const& _sectionInfo, Counts const& _prevAssertions, double _durationInSeconds ) - : sectionInfo( _sectionInfo ), prevAssertions( _prevAssertions ), durationInSeconds( _durationInSeconds ) - {} - -} // end namespace Catch -// end catch_section_info.cpp -// start catch_session.cpp - -// start catch_session.h - -#include - -namespace Catch { - - class Session : NonCopyable { - public: - - Session(); - ~Session() override; - - void showHelp() const; - void libIdentify(); - - int applyCommandLine( int argc, char* argv[] ); - - void useConfigData( ConfigData const& configData ); - - int run( int argc, char* argv[] ); - #if defined(WIN32) && defined(UNICODE) - int run( int argc, wchar_t* const argv[] ); - #endif - int run(); - - clara::Parser const& cli() const; - void cli( clara::Parser const& newParser ); - ConfigData& configData(); - Config& config(); - private: - int runInternal(); - - clara::Parser m_cli; - ConfigData m_configData; - std::shared_ptr m_config; - bool m_startupExceptions = false; - }; - -} // end namespace Catch - -// end catch_session.h -// start catch_version.h - -#include - -namespace Catch { - - // Versioning information - struct Version { - Version( Version const& ) = delete; - Version& operator=( Version const& ) = delete; - Version( unsigned int _majorVersion, - unsigned int _minorVersion, - unsigned int _patchNumber, - char const * const _branchName, - unsigned int _buildNumber ); - - unsigned int const majorVersion; - unsigned int const minorVersion; - unsigned int const patchNumber; - - // buildNumber is only used if branchName is not null - char const * const branchName; - unsigned int const buildNumber; - - friend std::ostream& operator << ( std::ostream& os, Version const& version ); - }; - - Version const& libraryVersion(); -} - -// end catch_version.h -#include -#include - -namespace { - const int MaxExitCode = 255; - using Catch::IStreamingReporterPtr; - using Catch::IConfigPtr; - using Catch::Config; - - IStreamingReporterPtr createReporter(std::string const& reporterName, IConfigPtr const& config) { - auto reporter = Catch::getRegistryHub().getReporterRegistry().create(reporterName, config); - CATCH_ENFORCE(reporter, "No reporter registered with name: '" << reporterName << "'"); - - return reporter; - } - -#ifndef CATCH_CONFIG_DEFAULT_REPORTER -#define CATCH_CONFIG_DEFAULT_REPORTER "console" -#endif - - IStreamingReporterPtr makeReporter(std::shared_ptr const& config) { - auto const& reporterNames = config->getReporterNames(); - if (reporterNames.empty()) - return createReporter(CATCH_CONFIG_DEFAULT_REPORTER, config); - - IStreamingReporterPtr reporter; - for (auto const& name : reporterNames) - addReporter(reporter, createReporter(name, config)); - return reporter; - } - -#undef CATCH_CONFIG_DEFAULT_REPORTER - - void addListeners(IStreamingReporterPtr& reporters, IConfigPtr const& config) { - auto const& listeners = Catch::getRegistryHub().getReporterRegistry().getListeners(); - for (auto const& listener : listeners) - addReporter(reporters, listener->create(Catch::ReporterConfig(config))); - } - - Catch::Totals runTests(std::shared_ptr const& config) { - using namespace Catch; - IStreamingReporterPtr reporter = makeReporter(config); - addListeners(reporter, config); - - RunContext context(config, std::move(reporter)); - - Totals totals; - - context.testGroupStarting(config->name(), 1, 1); - - TestSpec testSpec = config->testSpec(); - if (!testSpec.hasFilters()) - testSpec = TestSpecParser(ITagAliasRegistry::get()).parse("~[.]").testSpec(); // All not hidden tests - - auto const& allTestCases = getAllTestCasesSorted(*config); - for (auto const& testCase : allTestCases) { - if (!context.aborting() && matchTest(testCase, testSpec, *config)) - totals += context.runTest(testCase); - else - context.reporter().skipTest(testCase); - } - - context.testGroupEnded(config->name(), totals, 1, 1); - return totals; - } - - void applyFilenamesAsTags(Catch::IConfig const& config) { - using namespace Catch; - auto& tests = const_cast&>(getAllTestCasesSorted(config)); - for (auto& testCase : tests) { - auto tags = testCase.tags; - - std::string filename = testCase.lineInfo.file; - auto lastSlash = filename.find_last_of("\\/"); - if (lastSlash != std::string::npos) { - filename.erase(0, lastSlash); - filename[0] = '#'; - } - - auto lastDot = filename.find_last_of('.'); - if (lastDot != std::string::npos) { - filename.erase(lastDot); - } - - tags.push_back(std::move(filename)); - setTags(testCase, tags); - } - } - -} - -namespace Catch { - - Session::Session() { - static bool alreadyInstantiated = false; - if( alreadyInstantiated ) { - try { CATCH_INTERNAL_ERROR( "Only one instance of Catch::Session can ever be used" ); } - catch(...) { getMutableRegistryHub().registerStartupException(); } - } - - const auto& exceptions = getRegistryHub().getStartupExceptionRegistry().getExceptions(); - if ( !exceptions.empty() ) { - m_startupExceptions = true; - Colour colourGuard( Colour::Red ); - Catch::cerr() << "Errors occured during startup!" << '\n'; - // iterate over all exceptions and notify user - for ( const auto& ex_ptr : exceptions ) { - try { - std::rethrow_exception(ex_ptr); - } catch ( std::exception const& ex ) { - Catch::cerr() << Column( ex.what() ).indent(2) << '\n'; - } - } - } - - alreadyInstantiated = true; - m_cli = makeCommandLineParser( m_configData ); - } - Session::~Session() { - Catch::cleanUp(); - } - - void Session::showHelp() const { - Catch::cout() - << "\nCatch v" << libraryVersion() << "\n" - << m_cli << std::endl - << "For more detailed usage please see the project docs\n" << std::endl; - } - void Session::libIdentify() { - Catch::cout() - << std::left << std::setw(16) << "description: " << "A Catch test executable\n" - << std::left << std::setw(16) << "category: " << "testframework\n" - << std::left << std::setw(16) << "framework: " << "Catch Test\n" - << std::left << std::setw(16) << "version: " << libraryVersion() << std::endl; - } - - int Session::applyCommandLine( int argc, char* argv[] ) { - if( m_startupExceptions ) - return 1; - - auto result = m_cli.parse( clara::Args( argc, argv ) ); - if( !result ) { - Catch::cerr() - << Colour( Colour::Red ) - << "\nError(s) in input:\n" - << Column( result.errorMessage() ).indent( 2 ) - << "\n\n"; - Catch::cerr() << "Run with -? for usage\n" << std::endl; - return MaxExitCode; - } - - if( m_configData.showHelp ) - showHelp(); - if( m_configData.libIdentify ) - libIdentify(); - m_config.reset(); - return 0; - } - - void Session::useConfigData( ConfigData const& configData ) { - m_configData = configData; - m_config.reset(); - } - - int Session::run( int argc, char* argv[] ) { - if( m_startupExceptions ) - return 1; - int returnCode = applyCommandLine( argc, argv ); - if( returnCode == 0 ) - returnCode = run(); - return returnCode; - } - -#if defined(WIN32) && defined(UNICODE) - int Session::run( int argc, wchar_t* const argv[] ) { - - char **utf8Argv = new char *[ argc ]; - - for ( int i = 0; i < argc; ++i ) { - int bufSize = WideCharToMultiByte( CP_UTF8, 0, argv[i], -1, NULL, 0, NULL, NULL ); - - utf8Argv[ i ] = new char[ bufSize ]; - - WideCharToMultiByte( CP_UTF8, 0, argv[i], -1, utf8Argv[i], bufSize, NULL, NULL ); - } - - int returnCode = run( argc, utf8Argv ); - - for ( int i = 0; i < argc; ++i ) - delete [] utf8Argv[ i ]; - - delete [] utf8Argv; - - return returnCode; - } -#endif - int Session::run() { - if( ( m_configData.waitForKeypress & WaitForKeypress::BeforeStart ) != 0 ) { - Catch::cout() << "...waiting for enter/ return before starting" << std::endl; - static_cast(std::getchar()); - } - int exitCode = runInternal(); - if( ( m_configData.waitForKeypress & WaitForKeypress::BeforeExit ) != 0 ) { - Catch::cout() << "...waiting for enter/ return before exiting, with code: " << exitCode << std::endl; - static_cast(std::getchar()); - } - return exitCode; - } - - clara::Parser const& Session::cli() const { - return m_cli; - } - void Session::cli( clara::Parser const& newParser ) { - m_cli = newParser; - } - ConfigData& Session::configData() { - return m_configData; - } - Config& Session::config() { - if( !m_config ) - m_config = std::make_shared( m_configData ); - return *m_config; - } - - int Session::runInternal() { - if( m_startupExceptions ) - return 1; - - if( m_configData.showHelp || m_configData.libIdentify ) - return 0; - - try + 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() ) { - config(); // Force config to be constructed - - seedRng( *m_config ); - - if( m_configData.filenamesAsTags ) - applyFilenamesAsTags( *m_config ); - - // Handle list request - if( Option listed = list( config() ) ) - return static_cast( *listed ); - - return (std::min)( MaxExitCode, static_cast( runTests( m_config ).assertions.failed ) ); + m_reporterPrefs.shouldRedirectStdOut = false; } - catch( std::exception& ex ) { - Catch::cerr() << ex.what() << std::endl; - return MaxExitCode; - } - } + ~CumulativeReporterBase(); -} // end namespace Catch -// end catch_session.cpp -// start catch_startup_exception_registry.cpp - -namespace Catch { - void StartupExceptionRegistry::add( std::exception_ptr const& exception ) noexcept { - try { - m_exceptions.push_back(exception); - } - catch(...) { - // If we run out of memory during start-up there's really not a lot more we can do about it - std::terminate(); - } - } - - std::vector const& StartupExceptionRegistry::getExceptions() const noexcept { - return m_exceptions; - } - -} // end namespace Catch -// end catch_startup_exception_registry.cpp -// start catch_stream.cpp - -#include -#include -#include - -namespace Catch { - - template - class StreamBufImpl : public StreamBufBase { - char data[bufferSize]; - WriterF m_writer; - - public: - StreamBufImpl() { - setp( data, data + sizeof(data) ); + virtual ReporterPreferences getPreferences() const CATCH_OVERRIDE { + return m_reporterPrefs; } - ~StreamBufImpl() noexcept { - StreamBufImpl::sync(); - } + virtual void testRunStarting( TestRunInfo const& ) CATCH_OVERRIDE {} + virtual void testGroupStarting( GroupInfo const& ) CATCH_OVERRIDE {} - private: - int overflow( int c ) override { - sync(); + virtual void testCaseStarting( TestCaseInfo const& ) CATCH_OVERRIDE {} - if( c != EOF ) { - if( pbase() == epptr() ) - m_writer( std::string( 1, static_cast( c ) ) ); - else - sputc( static_cast( c ) ); - } - return 0; - } - - int sync() override { - if( pbase() != pptr() ) { - m_writer( std::string( pbase(), static_cast( pptr() - pbase() ) ) ); - setp( pbase(), epptr() ); - } - return 0; - } - }; - - /////////////////////////////////////////////////////////////////////////// - - Catch::IStream::~IStream() = default; - - FileStream::FileStream( std::string const& filename ) { - m_ofs.open( filename.c_str() ); - CATCH_ENFORCE( !m_ofs.fail(), "Unable to open file: '" << filename << "'" ); - } - - std::ostream& FileStream::stream() const { - return m_ofs; - } - - struct OutputDebugWriter { - - void operator()( std::string const&str ) { - writeToDebugConsole( str ); - } - }; - - DebugOutStream::DebugOutStream() - : m_streamBuf( new StreamBufImpl() ), - m_os( m_streamBuf.get() ) - {} - - std::ostream& DebugOutStream::stream() const { - return m_os; - } - - // Store the streambuf from cout up-front because - // cout may get redirected when running tests - CoutStream::CoutStream() - : m_os( Catch::cout().rdbuf() ) - {} - - std::ostream& CoutStream::stream() const { - return m_os; - } - -#ifndef CATCH_CONFIG_NOSTDOUT // If you #define this you must implement these functions - std::ostream& cout() { - return std::cout; - } - std::ostream& cerr() { - return std::cerr; - } - std::ostream& clog() { - return std::clog; - } -#endif -} -// end catch_stream.cpp -// start catch_streambuf.cpp - -namespace Catch { - StreamBufBase::~StreamBufBase() = default; -} -// end catch_streambuf.cpp -// start catch_string_manip.cpp - -#include -#include -#include -#include - -namespace Catch { - - bool startsWith( std::string const& s, std::string const& prefix ) { - return s.size() >= prefix.size() && std::equal(prefix.begin(), prefix.end(), s.begin()); - } - bool startsWith( std::string const& s, char prefix ) { - return !s.empty() && s[0] == prefix; - } - bool endsWith( std::string const& s, std::string const& suffix ) { - return s.size() >= suffix.size() && std::equal(suffix.rbegin(), suffix.rend(), s.rbegin()); - } - bool endsWith( std::string const& s, char suffix ) { - return !s.empty() && s[s.size()-1] == suffix; - } - bool contains( std::string const& s, std::string const& infix ) { - return s.find( infix ) != std::string::npos; - } - char toLowerCh(char c) { - return static_cast( std::tolower( c ) ); - } - void toLowerInPlace( std::string& s ) { - std::transform( s.begin(), s.end(), s.begin(), toLowerCh ); - } - 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 ) : std::string(); - } - - bool replaceInPlace( std::string& str, std::string const& replaceThis, std::string const& withThis ) { - bool replaced = false; - std::size_t i = str.find( replaceThis ); - while( i != std::string::npos ) { - replaced = true; - str = str.substr( 0, i ) + withThis + str.substr( i+replaceThis.size() ); - if( i < str.size()-withThis.size() ) - i = str.find( replaceThis, i+withThis.size() ); - else - i = std::string::npos; - } - return replaced; - } - - pluralise::pluralise( std::size_t count, std::string const& label ) - : m_count( count ), - m_label( label ) - {} - - std::ostream& operator << ( std::ostream& os, pluralise const& pluraliser ) { - os << pluraliser.m_count << ' ' << pluraliser.m_label; - if( pluraliser.m_count != 1 ) - os << 's'; - return os; - } - -} -// end catch_string_manip.cpp -// start catch_stringref.cpp - -#if defined(__clang__) -# pragma clang diagnostic push -# pragma clang diagnostic ignored "-Wexit-time-destructors" -#endif - -#include -#include -#include - -namespace Catch { - - auto getEmptyStringRef() -> StringRef { - static StringRef s_emptyStringRef(""); - return s_emptyStringRef; - } - - StringRef::StringRef() noexcept - : StringRef( getEmptyStringRef() ) - {} - - StringRef::StringRef( StringRef const& other ) noexcept - : m_start( other.m_start ), - m_size( other.m_size ) - {} - - StringRef::StringRef( StringRef&& other ) noexcept - : m_start( other.m_start ), - m_size( other.m_size ), - m_data( other.m_data ) - { - other.m_data = nullptr; - } - - StringRef::StringRef( char const* rawChars ) noexcept - : m_start( rawChars ), - m_size( static_cast( std::strlen( rawChars ) ) ) - { - assert( rawChars != nullptr ); - } - - StringRef::StringRef( char const* rawChars, size_type size ) noexcept - : m_start( rawChars ), - m_size( size ) - { - size_type rawSize = rawChars == nullptr ? 0 : static_cast( std::strlen( rawChars ) ); - if( rawSize < size ) - m_size = rawSize; - } - - StringRef::StringRef( std::string const& stdString ) noexcept - : m_start( stdString.c_str() ), - m_size( stdString.size() ) - {} - - StringRef::~StringRef() noexcept { - delete[] m_data; - } - - auto StringRef::operator = ( StringRef other ) noexcept -> StringRef& { - swap( other ); - return *this; - } - StringRef::operator std::string() const { - return std::string( m_start, m_size ); - } - - void StringRef::swap( StringRef& other ) noexcept { - std::swap( m_start, other.m_start ); - std::swap( m_size, other.m_size ); - std::swap( m_data, other.m_data ); - } - - auto StringRef::c_str() const -> char const* { - if( isSubstring() ) - const_cast( this )->takeOwnership(); - return m_start; - } - auto StringRef::data() const noexcept -> char const* { - return m_start; - } - - auto StringRef::isOwned() const noexcept -> bool { - return m_data != nullptr; - } - auto StringRef::isSubstring() const noexcept -> bool { - return m_start[m_size] != '\0'; - } - - void StringRef::takeOwnership() { - if( !isOwned() ) { - m_data = new char[m_size+1]; - memcpy( m_data, m_start, m_size ); - m_data[m_size] = '\0'; - m_start = m_data; - } - } - auto StringRef::substr( size_type start, size_type size ) const noexcept -> StringRef { - if( start < m_size ) - return StringRef( m_start+start, size ); - else - return StringRef(); - } - auto StringRef::operator == ( StringRef const& other ) const noexcept -> bool { - return - size() == other.size() && - (std::strncmp( m_start, other.m_start, size() ) == 0); - } - auto StringRef::operator != ( StringRef const& other ) const noexcept -> bool { - return !operator==( other ); - } - - auto StringRef::operator[](size_type index) const noexcept -> char { - return m_start[index]; - } - - auto StringRef::empty() const noexcept -> bool { - return m_size == 0; - } - - auto StringRef::size() const noexcept -> size_type { - return m_size; - } - auto StringRef::numberOfCharacters() const noexcept -> size_type { - size_type noChars = m_size; - // Make adjustments for uft encodings - for( size_type i=0; i < m_size; ++i ) { - char c = m_start[i]; - if( ( c & 0b11000000 ) == 0b11000000 ) { - if( ( c & 0b11100000 ) == 0b11000000 ) - noChars--; - else if( ( c & 0b11110000 ) == 0b11100000 ) - noChars-=2; - else if( ( c & 0b11111000 ) == 0b11110000 ) - noChars-=3; - } - } - return noChars; - } - - auto operator + ( StringRef const& lhs, StringRef const& rhs ) -> std::string { - std::string str; - str.reserve( lhs.size() + rhs.size() ); - str += lhs; - str += rhs; - return str; - } - auto operator + ( StringRef const& lhs, const char* rhs ) -> std::string { - return std::string( lhs ) + std::string( rhs ); - } - auto operator + ( char const* lhs, StringRef const& rhs ) -> std::string { - return std::string( lhs ) + std::string( rhs ); - } - - auto operator << ( std::ostream& os, StringRef const& str ) -> std::ostream& { - return os << str.c_str(); - } - -} // namespace Catch - -#if defined(__clang__) -# pragma clang diagnostic pop -#endif -// end catch_stringref.cpp -// start catch_tag_alias.cpp - -namespace Catch { - TagAlias::TagAlias(std::string const & _tag, SourceLineInfo _lineInfo): tag(_tag), lineInfo(_lineInfo) {} -} -// end catch_tag_alias.cpp -// start catch_tag_alias_autoregistrar.cpp - -namespace Catch { - - RegistrarForTagAliases::RegistrarForTagAliases(char const* alias, char const* tag, SourceLineInfo const& lineInfo) { - try { - getMutableRegistryHub().registerTagAlias(alias, tag, lineInfo); - } catch (...) { - // Do not throw when constructing global objects, instead register the exception to be processed later - getMutableRegistryHub().registerStartupException(); - } - } - -} -// end catch_tag_alias_autoregistrar.cpp -// start catch_tag_alias_registry.cpp - -namespace Catch { - - TagAliasRegistry::~TagAliasRegistry() {} - - TagAlias const* TagAliasRegistry::find( std::string const& alias ) const { - auto it = m_registry.find( alias ); - if( it != m_registry.end() ) - return &(it->second); - else - return nullptr; - } - - std::string TagAliasRegistry::expandAliases( std::string const& unexpandedTestSpec ) const { - std::string expandedTestSpec = unexpandedTestSpec; - for( auto const& registryKvp : m_registry ) { - std::size_t pos = expandedTestSpec.find( registryKvp.first ); - if( pos != std::string::npos ) { - expandedTestSpec = expandedTestSpec.substr( 0, pos ) + - registryKvp.second.tag + - expandedTestSpec.substr( pos + registryKvp.first.size() ); - } - } - return expandedTestSpec; - } - - void TagAliasRegistry::add( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo ) { - CATCH_ENFORCE( startsWith(alias, "[@") && endsWith(alias, ']'), - "error: tag alias, '" << alias << "' is not of the form [@alias name].\n" << lineInfo ); - - CATCH_ENFORCE( m_registry.insert(std::make_pair(alias, TagAlias(tag, lineInfo))).second, - "error: tag alias, '" << alias << "' already registered.\n" - << "\tFirst seen at: " << find(alias)->lineInfo << "\n" - << "\tRedefined at: " << lineInfo ); - } - - ITagAliasRegistry::~ITagAliasRegistry() {} - - ITagAliasRegistry const& ITagAliasRegistry::get() { - return getRegistryHub().getTagAliasRegistry(); - } - -} // end namespace Catch -// end catch_tag_alias_registry.cpp -// start catch_test_case_info.cpp - -#include -#include -#include - -namespace Catch { - - TestCaseInfo::SpecialProperties parseSpecialTag( std::string const& tag ) { - if( startsWith( tag, '.' ) || - tag == "!hide" ) - return TestCaseInfo::IsHidden; - else if( tag == "!throws" ) - return TestCaseInfo::Throws; - else if( tag == "!shouldfail" ) - return TestCaseInfo::ShouldFail; - else if( tag == "!mayfail" ) - return TestCaseInfo::MayFail; - else if( tag == "!nonportable" ) - return TestCaseInfo::NonPortable; - else if( tag == "!benchmark" ) - return static_cast( TestCaseInfo::Benchmark | TestCaseInfo::IsHidden ); - else - return TestCaseInfo::None; - } - bool isReservedTag( std::string const& tag ) { - return parseSpecialTag( tag ) == TestCaseInfo::None && tag.size() > 0 && !std::isalnum( tag[0] ); - } - void enforceNotReservedTag( std::string const& tag, SourceLineInfo const& _lineInfo ) { - CATCH_ENFORCE( !isReservedTag(tag), - "Tag name: [" << tag << "] is not allowed.\n" - << "Tag names starting with non alpha-numeric characters are reserved\n" - << _lineInfo ); - } - - TestCase makeTestCase( ITestInvoker* _testCase, - std::string const& _className, - std::string const& _name, - std::string const& _descOrTags, - SourceLineInfo const& _lineInfo ) - { - bool isHidden = false; - - // Parse out tags - std::vector tags; - std::string desc, tag; - bool inTag = false; - for (char c : _descOrTags) { - if( !inTag ) { - if( c == '[' ) - inTag = true; - else - desc += c; + virtual void sectionStarting( SectionInfo const& sectionInfo ) CATCH_OVERRIDE { + SectionStats incompleteStats( sectionInfo, Counts(), 0, false ); + Ptr node; + if( m_sectionStack.empty() ) { + if( !m_rootSection ) + m_rootSection = new SectionNode( incompleteStats ); + node = m_rootSection; } else { - if( c == ']' ) { - TestCaseInfo::SpecialProperties prop = parseSpecialTag( tag ); - if( ( prop & TestCaseInfo::IsHidden ) != 0 ) - isHidden = true; - else if( prop == TestCaseInfo::None ) - enforceNotReservedTag( tag, _lineInfo ); - - tags.push_back( tag ); - tag.clear(); - inTag = false; + 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 - tag += c; + node = *it; } - } - if( isHidden ) { - tags.push_back( "." ); + m_sectionStack.push_back( node ); + m_deepestSection = node; } - TestCaseInfo info( _name, _className, desc, tags, _lineInfo ); - return TestCase( _testCase, info ); - } + virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE {} - void setTags( TestCaseInfo& testCaseInfo, std::vector tags ) { - std::sort(begin(tags), end(tags)); - tags.erase(std::unique(begin(tags), end(tags)), end(tags)); - testCaseInfo.lcaseTags.clear(); - - for( auto const& tag : tags ) { - std::string lcaseTag = toLower( tag ); - testCaseInfo.properties = static_cast( testCaseInfo.properties | parseSpecialTag( lcaseTag ) ); - testCaseInfo.lcaseTags.push_back( lcaseTag ); + virtual bool assertionEnded( AssertionStats const& assertionStats ) CATCH_OVERRIDE { + assert( !m_sectionStack.empty() ); + SectionNode& sectionNode = *m_sectionStack.back(); + sectionNode.assertions.push_back( assertionStats ); + // AssertionResult holds a pointer to a temporary DecomposedExpression, + // which getExpandedExpression() calls to build the expression string. + // Our section stack copy of the assertionResult will likely outlive the + // temporary, so it must be expanded or discarded now to avoid calling + // a destroyed object later. + prepareExpandedExpression( sectionNode.assertions.back().assertionResult ); + return true; } - testCaseInfo.tags = std::move(tags); - } - - TestCaseInfo::TestCaseInfo( std::string const& _name, - std::string const& _className, - std::string const& _description, - std::vector const& _tags, - SourceLineInfo const& _lineInfo ) - : name( _name ), - className( _className ), - description( _description ), - lineInfo( _lineInfo ), - properties( None ) - { - setTags( *this, _tags ); - } - - 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; - } - - std::string TestCaseInfo::tagsAsString() const { - std::string ret; - // '[' and ']' per tag - std::size_t full_size = 2 * tags.size(); - for (const auto& tag : tags) { - full_size += tag.size(); + virtual void sectionEnded( SectionStats const& sectionStats ) CATCH_OVERRIDE { + assert( !m_sectionStack.empty() ); + SectionNode& node = *m_sectionStack.back(); + node.stats = sectionStats; + m_sectionStack.pop_back(); } - ret.reserve(full_size); - for (const auto& tag : tags) { - ret.push_back('['); - ret.append(tag); - ret.push_back(']'); + virtual void testCaseEnded( TestCaseStats const& testCaseStats ) CATCH_OVERRIDE { + Ptr node = new TestCaseNode( testCaseStats ); + assert( m_sectionStack.size() == 0 ); + node->children.push_back( m_rootSection ); + m_testCases.push_back( node ); + m_rootSection.reset(); + + assert( m_deepestSection ); + m_deepestSection->stdOut = testCaseStats.stdOut; + m_deepestSection->stdErr = testCaseStats.stdErr; + } + virtual void testGroupEnded( TestGroupStats const& testGroupStats ) CATCH_OVERRIDE { + Ptr node = new TestGroupNode( testGroupStats ); + node->children.swap( m_testCases ); + m_testGroups.push_back( node ); + } + virtual void testRunEnded( TestRunStats const& testRunStats ) CATCH_OVERRIDE { + Ptr node = new TestRunNode( testRunStats ); + node->children.swap( m_testGroups ); + m_testRuns.push_back( node ); + testRunEndedCumulative(); + } + virtual void testRunEndedCumulative() = 0; + + virtual void skipTest( TestCaseInfo const& ) CATCH_OVERRIDE {} + + virtual void prepareExpandedExpression( AssertionResult& result ) const { + if( result.isOk() ) + result.discardDecomposedExpression(); + else + result.expandDecomposedExpression(); } - return ret; + Ptr m_config; + std::ostream& stream; + std::vector m_assertions; + std::vector > > m_sections; + std::vector > m_testCases; + std::vector > m_testGroups; + + std::vector > m_testRuns; + + Ptr m_rootSection; + Ptr m_deepestSection; + std::vector > m_sectionStack; + ReporterPreferences m_reporterPrefs; + + }; + + template + char const* getLineOfChars() { + static char line[CATCH_CONFIG_CONSOLE_WIDTH] = {0}; + if( !*line ) { + std::memset( line, C, CATCH_CONFIG_CONSOLE_WIDTH-1 ); + line[CATCH_CONFIG_CONSOLE_WIDTH-1] = 0; + } + return line; } - TestCase::TestCase( ITestInvoker* testCase, TestCaseInfo const& info ) : TestCaseInfo( info ), test( testCase ) {} + struct TestEventListenerBase : StreamingReporterBase { + TestEventListenerBase( ReporterConfig const& _config ) + : StreamingReporterBase( _config ) + {} - TestCase TestCase::withName( std::string const& _newName ) const { - TestCase other( *this ); - other.name = _newName; - return other; - } - - void TestCase::invoke() const { - test->invoke(); - } - - bool TestCase::operator == ( TestCase const& other ) const { - return test.get() == other.test.get() && - name == other.name && - className == other.className; - } - - bool TestCase::operator < ( TestCase const& other ) const { - return name < other.name; - } - - TestCaseInfo const& TestCase::getTestCaseInfo() const - { - return *this; - } + virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE {} + virtual bool assertionEnded( AssertionStats const& ) CATCH_OVERRIDE { + return false; + } + }; } // end namespace Catch -// end catch_test_case_info.cpp -// start catch_test_case_registry_impl.cpp -#include +// #included from: ../internal/catch_reporter_registrars.hpp +#define TWOBLUECUBES_CATCH_REPORTER_REGISTRARS_HPP_INCLUDED namespace Catch { - std::vector sortTests( IConfig const& config, std::vector const& unsortedTestCases ) { + template + class LegacyReporterRegistrar { - std::vector sorted = unsortedTestCases; - - switch( config.runOrder() ) { - case RunTests::InLexicographicalOrder: - std::sort( sorted.begin(), sorted.end() ); - break; - case RunTests::InRandomOrder: - seedRng( config ); - RandomNumberGenerator::shuffle( sorted ); - break; - case RunTests::InDeclarationOrder: - // already in declaration order - break; - } - return sorted; - } - bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config ) { - return testSpec.matches( testCase ) && ( config.allowThrows() || !testCase.throws() ); - } - - void enforceNoDuplicateTestCases( std::vector const& functions ) { - std::set seenFunctions; - for( auto const& function : functions ) { - auto prev = seenFunctions.insert( function ); - CATCH_ENFORCE( prev.second, - "error: TEST_CASE( \"" << function.name << "\" ) already defined.\n" - << "\tFirst seen at " << prev.first->getTestCaseInfo().lineInfo << "\n" - << "\tRedefined at " << function.getTestCaseInfo().lineInfo ); - } - } - - std::vector filterTests( std::vector const& testCases, TestSpec const& testSpec, IConfig const& config ) { - std::vector filtered; - filtered.reserve( testCases.size() ); - for( auto const& testCase : testCases ) - if( matchTest( testCase, testSpec, config ) ) - filtered.push_back( testCase ); - return filtered; - } - std::vector const& getAllTestCasesSorted( IConfig const& config ) { - return getRegistryHub().getTestCaseRegistry().getAllTestsSorted( config ); - } - - void TestRegistry::registerTest( TestCase const& testCase ) { - std::string name = testCase.getTestCaseInfo().name; - if( name.empty() ) { - std::ostringstream oss; - oss << "Anonymous test case " << ++m_unnamedCount; - return registerTest( testCase.withName( oss.str() ) ); - } - m_functions.push_back( testCase ); - } - - std::vector const& TestRegistry::getAllTests() const { - return m_functions; - } - std::vector const& TestRegistry::getAllTestsSorted( IConfig const& config ) const { - if( m_sortedFunctions.empty() ) - enforceNoDuplicateTestCases( m_functions ); - - if( m_currentSortOrder != config.runOrder() || m_sortedFunctions.empty() ) { - m_sortedFunctions = sortTests( config, m_functions ); - m_currentSortOrder = config.runOrder(); - } - return m_sortedFunctions; - } - - /////////////////////////////////////////////////////////////////////////// - TestInvokerAsFunction::TestInvokerAsFunction( void(*testAsFunction)() ) noexcept : m_testAsFunction( testAsFunction ) {} - - void TestInvokerAsFunction::invoke() const { - m_testAsFunction(); - } - - 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; - } - -} // end namespace Catch -// end catch_test_case_registry_impl.cpp -// start catch_test_case_tracker.cpp - -#include -#include -#include -#include - -#if defined(__clang__) -# pragma clang diagnostic push -# pragma clang diagnostic ignored "-Wexit-time-destructors" -#endif - -namespace Catch { -namespace TestCaseTracking { - - NameAndLocation::NameAndLocation( std::string const& _name, SourceLineInfo const& _location ) - : name( _name ), - location( _location ) - {} - - ITracker::~ITracker() = default; - - TrackerContext& TrackerContext::instance() { - static TrackerContext s_instance; - return s_instance; - } - - ITracker& TrackerContext::startRun() { - m_rootTracker = std::make_shared( NameAndLocation( "{root}", CATCH_INTERNAL_LINEINFO ), *this, nullptr ); - m_currentTracker = nullptr; - m_runState = Executing; - return *m_rootTracker; - } - - void TrackerContext::endRun() { - m_rootTracker.reset(); - m_currentTracker = nullptr; - m_runState = NotStarted; - } - - void TrackerContext::startCycle() { - m_currentTracker = m_rootTracker.get(); - m_runState = Executing; - } - void TrackerContext::completeCycle() { - m_runState = CompletedCycle; - } - - bool TrackerContext::completedCycle() const { - return m_runState == CompletedCycle; - } - ITracker& TrackerContext::currentTracker() { - return *m_currentTracker; - } - void TrackerContext::setCurrentTracker( ITracker* tracker ) { - m_currentTracker = tracker; - } - - TrackerBase::TrackerHasName::TrackerHasName( NameAndLocation const& nameAndLocation ) : m_nameAndLocation( nameAndLocation ) {} - bool TrackerBase::TrackerHasName::operator ()( ITrackerPtr const& tracker ) const { - return - tracker->nameAndLocation().name == m_nameAndLocation.name && - tracker->nameAndLocation().location == m_nameAndLocation.location; - } - - TrackerBase::TrackerBase( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent ) - : m_nameAndLocation( nameAndLocation ), - m_ctx( ctx ), - m_parent( parent ) - {} - - NameAndLocation const& TrackerBase::nameAndLocation() const { - return m_nameAndLocation; - } - bool TrackerBase::isComplete() const { - return m_runState == CompletedSuccessfully || m_runState == Failed; - } - bool TrackerBase::isSuccessfullyCompleted() const { - return m_runState == CompletedSuccessfully; - } - bool TrackerBase::isOpen() const { - return m_runState != NotStarted && !isComplete(); - } - bool TrackerBase::hasChildren() const { - return !m_children.empty(); - } - - void TrackerBase::addChild( ITrackerPtr const& child ) { - m_children.push_back( child ); - } - - ITrackerPtr TrackerBase::findChild( NameAndLocation const& nameAndLocation ) { - auto it = std::find_if( m_children.begin(), m_children.end(), TrackerHasName( nameAndLocation ) ); - return( it != m_children.end() ) - ? *it - : nullptr; - } - ITracker& TrackerBase::parent() { - assert( m_parent ); // Should always be non-null except for root - return *m_parent; - } - - void TrackerBase::openChild() { - if( m_runState != ExecutingChildren ) { - m_runState = ExecutingChildren; - if( m_parent ) - m_parent->openChild(); - } - } - - bool TrackerBase::isSectionTracker() const { return false; } - bool TrackerBase::isIndexTracker() const { return false; } - - void TrackerBase::open() { - m_runState = Executing; - moveToThis(); - if( m_parent ) - m_parent->openChild(); - } - - void TrackerBase::close() { - - // Close any still open children (e.g. generators) - while( &m_ctx.currentTracker() != this ) - m_ctx.currentTracker().close(); - - switch( m_runState ) { - case NeedsAnotherRun: - break; - - case Executing: - m_runState = CompletedSuccessfully; - break; - case ExecutingChildren: - if( m_children.empty() || m_children.back()->isComplete() ) - m_runState = CompletedSuccessfully; - break; - - case NotStarted: - case CompletedSuccessfully: - case Failed: - CATCH_INTERNAL_ERROR( "Illogical state: " << m_runState ); - - default: - CATCH_INTERNAL_ERROR( "Unknown state: " << m_runState ); - } - moveToParent(); - m_ctx.completeCycle(); - } - void TrackerBase::fail() { - m_runState = Failed; - if( m_parent ) - m_parent->markAsNeedingAnotherRun(); - moveToParent(); - m_ctx.completeCycle(); - } - void TrackerBase::markAsNeedingAnotherRun() { - m_runState = NeedsAnotherRun; - } - - void TrackerBase::moveToParent() { - assert( m_parent ); - m_ctx.setCurrentTracker( m_parent ); - } - void TrackerBase::moveToThis() { - m_ctx.setCurrentTracker( this ); - } - - SectionTracker::SectionTracker( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent ) - : TrackerBase( nameAndLocation, ctx, parent ) - { - if( parent ) { - while( !parent->isSectionTracker() ) - parent = &parent->parent(); - - SectionTracker& parentSection = static_cast( *parent ); - addNextFilters( parentSection.m_filters ); - } - } - - bool SectionTracker::isSectionTracker() const { return true; } - - SectionTracker& SectionTracker::acquire( TrackerContext& ctx, NameAndLocation const& nameAndLocation ) { - std::shared_ptr section; - - ITracker& currentTracker = ctx.currentTracker(); - if( ITrackerPtr childTracker = currentTracker.findChild( nameAndLocation ) ) { - assert( childTracker ); - assert( childTracker->isSectionTracker() ); - section = std::static_pointer_cast( childTracker ); - } - else { - section = std::make_shared( nameAndLocation, ctx, ¤tTracker ); - currentTracker.addChild( section ); - } - if( !ctx.completedCycle() ) - section->tryOpen(); - return *section; - } - - void SectionTracker::tryOpen() { - if( !isComplete() && (m_filters.empty() || m_filters[0].empty() || m_filters[0] == m_nameAndLocation.name ) ) - open(); - } - - void SectionTracker::addInitialFilters( std::vector const& filters ) { - if( !filters.empty() ) { - m_filters.push_back(""); // Root - should never be consulted - m_filters.push_back(""); // Test Case - not a section filter - m_filters.insert( m_filters.end(), filters.begin(), filters.end() ); - } - } - void SectionTracker::addNextFilters( std::vector const& filters ) { - if( filters.size() > 1 ) - m_filters.insert( m_filters.end(), ++filters.begin(), filters.end() ); - } - - IndexTracker::IndexTracker( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent, int size ) - : TrackerBase( nameAndLocation, ctx, parent ), - m_size( size ) - {} - - bool IndexTracker::isIndexTracker() const { return true; } - - IndexTracker& IndexTracker::acquire( TrackerContext& ctx, NameAndLocation const& nameAndLocation, int size ) { - std::shared_ptr tracker; - - ITracker& currentTracker = ctx.currentTracker(); - if( ITrackerPtr childTracker = currentTracker.findChild( nameAndLocation ) ) { - assert( childTracker ); - assert( childTracker->isIndexTracker() ); - tracker = std::static_pointer_cast( childTracker ); - } - else { - tracker = std::make_shared( nameAndLocation, ctx, ¤tTracker, size ); - currentTracker.addChild( tracker ); - } - - if( !ctx.completedCycle() && !tracker->isComplete() ) { - if( tracker->m_runState != ExecutingChildren && tracker->m_runState != NeedsAnotherRun ) - tracker->moveNext(); - tracker->open(); - } - - return *tracker; - } - - int IndexTracker::index() const { return m_index; } - - void IndexTracker::moveNext() { - m_index++; - m_children.clear(); - } - - void IndexTracker::close() { - TrackerBase::close(); - if( m_runState == CompletedSuccessfully && m_index < m_size-1 ) - m_runState = Executing; - } - -} // namespace TestCaseTracking - -using TestCaseTracking::ITracker; -using TestCaseTracking::TrackerContext; -using TestCaseTracking::SectionTracker; -using TestCaseTracking::IndexTracker; - -} // namespace Catch - -#if defined(__clang__) -# pragma clang diagnostic pop -#endif -// end catch_test_case_tracker.cpp -// start catch_test_registry.cpp - -namespace Catch { - - auto makeTestInvoker( void(*testAsFunction)() ) noexcept -> ITestInvoker* { - return new(std::nothrow) TestInvokerAsFunction( testAsFunction ); - } - - NameAndTags::NameAndTags( StringRef name_ , StringRef tags_ ) noexcept : name( name_ ), tags( tags_ ) {} - - AutoReg::AutoReg( ITestInvoker* invoker, SourceLineInfo const& lineInfo, StringRef classOrMethod, NameAndTags const& nameAndTags ) noexcept { - try { - getMutableRegistryHub() - .registerTest( - makeTestCase( - invoker, - extractClassName( classOrMethod ), - nameAndTags.name, - nameAndTags.tags, - lineInfo)); - } catch (...) { - // Do not throw when constructing global objects, instead register the exception to be processed later - getMutableRegistryHub().registerStartupException(); - } - } - - AutoReg::~AutoReg() = default; -} -// end catch_test_registry.cpp -// start catch_test_spec.cpp - -#include -#include -#include -#include - -namespace Catch { - - TestSpec::Pattern::~Pattern() = default; - TestSpec::NamePattern::~NamePattern() = default; - TestSpec::TagPattern::~TagPattern() = default; - TestSpec::ExcludedPattern::~ExcludedPattern() = default; - - TestSpec::NamePattern::NamePattern( std::string const& name ) - : m_wildcardPattern( toLower( name ), CaseSensitive::No ) - {} - bool TestSpec::NamePattern::matches( TestCaseInfo const& testCase ) const { - return m_wildcardPattern.matches( toLower( testCase.name ) ); - } - - TestSpec::TagPattern::TagPattern( std::string const& tag ) : m_tag( toLower( tag ) ) {} - bool TestSpec::TagPattern::matches( TestCaseInfo const& testCase ) const { - return std::find(begin(testCase.lcaseTags), - end(testCase.lcaseTags), - m_tag) != end(testCase.lcaseTags); - } - - TestSpec::ExcludedPattern::ExcludedPattern( PatternPtr const& underlyingPattern ) : m_underlyingPattern( underlyingPattern ) {} - bool TestSpec::ExcludedPattern::matches( TestCaseInfo const& testCase ) const { return !m_underlyingPattern->matches( testCase ); } - - bool TestSpec::Filter::matches( TestCaseInfo const& testCase ) const { - // All patterns in a filter must match for the filter to be a match - for( auto const& pattern : m_patterns ) { - if( !pattern->matches( testCase ) ) - return false; - } - return true; - } - - bool TestSpec::hasFilters() const { - return !m_filters.empty(); - } - bool TestSpec::matches( TestCaseInfo const& testCase ) const { - // A TestSpec matches if any filter matches - for( auto const& filter : m_filters ) - if( filter.matches( testCase ) ) - return true; - return false; - } -} -// end catch_test_spec.cpp -// start catch_test_spec_parser.cpp - -namespace Catch { - - TestSpecParser::TestSpecParser( ITagAliasRegistry const& tagAliases ) : m_tagAliases( &tagAliases ) {} - - TestSpecParser& TestSpecParser::parse( std::string const& arg ) { - m_mode = None; - m_exclusion = false; - m_start = std::string::npos; - m_arg = m_tagAliases->expandAliases( arg ); - m_escapeChars.clear(); - for( m_pos = 0; m_pos < m_arg.size(); ++m_pos ) - visitChar( m_arg[m_pos] ); - if( m_mode == Name ) - addPattern(); - return *this; - } - TestSpec TestSpecParser::testSpec() { - addFilter(); - return m_testSpec; - } - - void TestSpecParser::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 ); - case '\\': return escape(); - default: startNewMode( Name, m_pos ); break; + class ReporterFactory : public IReporterFactory { + virtual IStreamingReporter* create( ReporterConfig const& config ) const { + return new LegacyReporterAdapter( new T( config ) ); } - } - if( m_mode == Name ) { - if( c == ',' ) { - addPattern(); - addFilter(); - } - else if( c == '[' ) { - if( subString() == "exclude:" ) - m_exclusion = true; - else - addPattern(); - startNewMode( Tag, ++m_pos ); - } - else if( c == '\\' ) - escape(); - } - else if( m_mode == EscapedName ) - m_mode = Name; - else if( m_mode == QuotedName && c == '"' ) - addPattern(); - else if( m_mode == Tag && c == ']' ) - addPattern(); - } - void TestSpecParser::startNewMode( Mode mode, std::size_t start ) { - m_mode = mode; - m_start = start; - } - void TestSpecParser::escape() { - if( m_mode == None ) - m_start = m_pos; - m_mode = EscapedName; - m_escapeChars.push_back( m_pos ); - } - std::string TestSpecParser::subString() const { return m_arg.substr( m_start, m_pos - m_start ); } - void TestSpecParser::addFilter() { - if( !m_currentFilter.m_patterns.empty() ) { - m_testSpec.m_filters.push_back( m_currentFilter ); - m_currentFilter = TestSpec::Filter(); - } - } - - TestSpec parseTestSpec( std::string const& arg ) { - return TestSpecParser( ITagAliasRegistry::get() ).parse( arg ).testSpec(); - } - -} // namespace Catch -// end catch_test_spec_parser.cpp -// start catch_timer.cpp - -#include - -namespace Catch { - - auto getCurrentNanosecondsSinceEpoch() -> uint64_t { - return std::chrono::duration_cast( std::chrono::high_resolution_clock::now().time_since_epoch() ).count(); - } - - auto estimateClockResolution() -> uint64_t { - uint64_t sum = 0; - static const uint64_t iterations = 1000000; - - for( std::size_t i = 0; i < iterations; ++i ) { - - uint64_t ticks; - uint64_t baseTicks = getCurrentNanosecondsSinceEpoch(); - do { - ticks = getCurrentNanosecondsSinceEpoch(); - } - while( ticks == baseTicks ); - - auto delta = ticks - baseTicks; - sum += delta; - } - - // We're just taking the mean, here. To do better we could take the std. dev and exclude outliers - // - and potentially do more iterations if there's a high variance. - return sum/iterations; - } - auto getEstimatedClockResolution() -> uint64_t { - static auto s_resolution = estimateClockResolution(); - return s_resolution; - } - - void Timer::start() { - m_nanoseconds = getCurrentNanosecondsSinceEpoch(); - } - auto Timer::getElapsedNanoseconds() const -> unsigned int { - return static_cast(getCurrentNanosecondsSinceEpoch() - m_nanoseconds); - } - auto Timer::getElapsedMicroseconds() const -> unsigned int { - return static_cast(getElapsedNanoseconds()/1000); - } - auto Timer::getElapsedMilliseconds() const -> unsigned int { - return static_cast(getElapsedMicroseconds()/1000); - } - auto Timer::getElapsedSeconds() const -> double { - return getElapsedMicroseconds()/1000000.0; - } - -} // namespace Catch -// end catch_timer.cpp -// start catch_tostring.cpp - -#if defined(__clang__) -# pragma clang diagnostic push -# pragma clang diagnostic ignored "-Wexit-time-destructors" -# pragma clang diagnostic ignored "-Wglobal-constructors" -#endif - -#include - -namespace Catch { - -namespace Detail { - - const std::string unprintableString = "{?}"; - - namespace { - const int hexThreshold = 255; - - struct Endianness { - enum Arch { Big, Little }; - - static Arch which() { - union _{ - int asInt; - char asChar[sizeof (int)]; - } u; - - u.asInt = 1; - return ( u.asChar[sizeof(int)-1] == 1 ) ? Big : Little; + virtual std::string getDescription() const { + return T::getDescription(); } }; - } - 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; + public: + + LegacyReporterRegistrar( std::string const& name ) { + getMutableRegistryHub().registerReporter( name, new ReporterFactory() ); } + }; - 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(); - } -} + template + class ReporterRegistrar { -template -std::string fpToString( T value, int precision ) { - std::ostringstream oss; - oss << std::setprecision( precision ) - << std::fixed - << value; - std::string d = oss.str(); - std::size_t i = d.find_last_not_of( '0' ); - if( i != std::string::npos && i != d.size()-1 ) { - if( d[i] == '.' ) - i++; - d = d.substr( 0, i+1 ); - } - return d; -} + class ReporterFactory : public SharedImpl { -//// ======================================================= //// -// -// Out-of-line defs for full specialization of StringMaker -// -//// ======================================================= //// + // *** 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 ); + } -std::string StringMaker::convert(const std::string& str) { - if (!getCurrentContext().getConfig()->showInvisibles()) { - return '"' + str + '"'; - } + virtual std::string getDescription() const { + return T::getDescription(); + } + }; - std::string s("\""); - for (char c : str) { - switch (c) { - case '\n': - s.append("\\n"); - break; - case '\t': - s.append("\\t"); - break; - default: - s.push_back(c); - break; + public: + + ReporterRegistrar( std::string const& name ) { + getMutableRegistryHub().registerReporter( name, new ReporterFactory() ); } - } - s.append("\""); - return s; -} + }; -std::string StringMaker::convert(const std::wstring& wstr) { - std::string s; - s.reserve(wstr.size()); - for (auto c : wstr) { - s += (c <= 0xff) ? static_cast(c) : '?'; - } - return ::Catch::Detail::stringify(s); -} + template + class ListenerRegistrar { -std::string StringMaker::convert(char const* str) { - if (str) { - return ::Catch::Detail::stringify(std::string{ str }); - } else { - return{ "{null string}" }; - } -} -std::string StringMaker::convert(char* str) { - if (str) { - return ::Catch::Detail::stringify(std::string{ str }); - } else { - return{ "{null string}" }; - } -} -std::string StringMaker::convert(wchar_t const * str) { - if (str) { - return ::Catch::Detail::stringify(std::wstring{ str }); - } else { - return{ "{null string}" }; - } -} -std::string StringMaker::convert(wchar_t * str) { - if (str) { - return ::Catch::Detail::stringify(std::wstring{ str }); - } else { - return{ "{null string}" }; - } -} + class ListenerFactory : public SharedImpl { -std::string StringMaker::convert(int value) { - return ::Catch::Detail::stringify(static_cast(value)); -} -std::string StringMaker::convert(long value) { - return ::Catch::Detail::stringify(static_cast(value)); -} -std::string StringMaker::convert(long long value) { - std::ostringstream oss; - oss << value; - if (value > Detail::hexThreshold) { - oss << " (0x" << std::hex << value << ')'; - } - return oss.str(); -} + virtual IStreamingReporter* create( ReporterConfig const& config ) const { + return new T( config ); + } + virtual std::string getDescription() const { + return std::string(); + } + }; -std::string StringMaker::convert(unsigned int value) { - return ::Catch::Detail::stringify(static_cast(value)); -} -std::string StringMaker::convert(unsigned long value) { - return ::Catch::Detail::stringify(static_cast(value)); -} -std::string StringMaker::convert(unsigned long long value) { - std::ostringstream oss; - oss << value; - if (value > Detail::hexThreshold) { - oss << " (0x" << std::hex << value << ')'; - } - return oss.str(); -} + public: -std::string StringMaker::convert(bool b) { - return b ? "true" : "false"; -} - -std::string StringMaker::convert(char value) { - if (value == '\r') { - return "'\\r'"; - } else if (value == '\f') { - return "'\\f'"; - } else if (value == '\n') { - return "'\\n'"; - } else if (value == '\t') { - return "'\\t'"; - } else if ('\0' <= value && value < ' ') { - return ::Catch::Detail::stringify(static_cast(value)); - } else { - char chstr[] = "' '"; - chstr[1] = value; - return chstr; - } -} -std::string StringMaker::convert(signed char c) { - return ::Catch::Detail::stringify(static_cast(c)); -} -std::string StringMaker::convert(unsigned char c) { - return ::Catch::Detail::stringify(static_cast(c)); -} - -std::string StringMaker::convert(std::nullptr_t) { - return "nullptr"; -} - -std::string StringMaker::convert(float value) { - return fpToString(value, 5) + 'f'; -} -std::string StringMaker::convert(double value) { - return fpToString(value, 10); -} - -} // end namespace Catch - -#if defined(__clang__) -# pragma clang diagnostic pop -#endif - -// end catch_tostring.cpp -// start catch_totals.cpp - -namespace Catch { - - Counts 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& Counts::operator += ( Counts const& other ) { - passed += other.passed; - failed += other.failed; - failedButOk += other.failedButOk; - return *this; - } - - std::size_t Counts::total() const { - return passed + failed + failedButOk; - } - bool Counts::allPassed() const { - return failed == 0 && failedButOk == 0; - } - bool Counts::allOk() const { - return failed == 0; - } - - Totals Totals::operator - ( Totals const& other ) const { - Totals diff; - diff.assertions = assertions - other.assertions; - diff.testCases = testCases - other.testCases; - return diff; - } - - Totals& Totals::operator += ( Totals const& other ) { - assertions += other.assertions; - testCases += other.testCases; - return *this; - } - - Totals 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; - } - -} -// end catch_totals.cpp -// start catch_version.cpp - -#include - -namespace Catch { - - Version::Version - ( unsigned int _majorVersion, - unsigned int _minorVersion, - unsigned int _patchNumber, - char const * const _branchName, - unsigned int _buildNumber ) - : majorVersion( _majorVersion ), - minorVersion( _minorVersion ), - patchNumber( _patchNumber ), - branchName( _branchName ), - buildNumber( _buildNumber ) - {} - - std::ostream& operator << ( std::ostream& os, Version const& version ) { - os << version.majorVersion << '.' - << version.minorVersion << '.' - << version.patchNumber; - // branchName is never null -> 0th char is \0 if it is empty - if (version.branchName[0]) { - os << '-' << version.branchName - << '.' << version.buildNumber; + ListenerRegistrar() { + getMutableRegistryHub().registerListener( new ListenerFactory() ); } - return os; - } - - Version const& libraryVersion() { - static Version version( 2, 0, 1, "", 0 ); - return version; - } - + }; } -// end catch_version.cpp -// start catch_wildcard_pattern.cpp -namespace Catch { +#define INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) \ + namespace{ Catch::LegacyReporterRegistrar catch_internal_RegistrarFor##reporterType( name ); } - WildcardPattern::WildcardPattern( std::string const& pattern, - CaseSensitive::Choice caseSensitivity ) - : m_caseSensitivity( caseSensitivity ), - m_pattern( adjustCase( pattern ) ) - { - if( startsWith( m_pattern, '*' ) ) { - m_pattern = m_pattern.substr( 1 ); - m_wildcard = WildcardAtStart; - } - if( endsWith( m_pattern, '*' ) ) { - m_pattern = m_pattern.substr( 0, m_pattern.size()-1 ); - m_wildcard = static_cast( m_wildcard | WildcardAtEnd ); - } - } +#define INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType ) \ + namespace{ Catch::ReporterRegistrar catch_internal_RegistrarFor##reporterType( name ); } - bool WildcardPattern::matches( std::string const& str ) const { - switch( m_wildcard ) { - case NoWildcard: - return m_pattern == adjustCase( str ); - case WildcardAtStart: - return endsWith( adjustCase( str ), m_pattern ); - case WildcardAtEnd: - return startsWith( adjustCase( str ), m_pattern ); - case WildcardAtBothEnds: - return contains( adjustCase( str ), m_pattern ); - default: - CATCH_INTERNAL_ERROR( "Unknown enum" ); - } - } +// Deprecated - use the form without INTERNAL_ +#define INTERNAL_CATCH_REGISTER_LISTENER( listenerType ) \ + namespace{ Catch::ListenerRegistrar catch_internal_RegistrarFor##listenerType; } - std::string WildcardPattern::adjustCase( std::string const& str ) const { - return m_caseSensitivity == CaseSensitive::No ? toLower( str ) : str; - } -} -// end catch_wildcard_pattern.cpp -// start catch_xmlwriter.cpp +#define CATCH_REGISTER_LISTENER( listenerType ) \ + namespace{ Catch::ListenerRegistrar catch_internal_RegistrarFor##listenerType; } -// start catch_xmlwriter.h +// #included from: ../internal/catch_xmlwriter.hpp +#define TWOBLUECUBES_CATCH_XMLWRITER_HPP_INCLUDED #include +#include #include +#include namespace Catch { @@ -9884,11 +9919,55 @@ namespace Catch { public: enum ForWhat { ForTextNodes, ForAttributes }; - XmlEncode( std::string const& str, ForWhat forWhat = ForTextNodes ); + XmlEncode( std::string const& str, ForWhat forWhat = ForTextNodes ) + : m_str( str ), + m_forWhat( forWhat ) + {} - void encodeTo( std::ostream& os ) const; + void encodeTo( std::ostream& os ) const { - friend std::ostream& operator << ( std::ostream& os, XmlEncode const& xmlEncode ); + // Apostrophe escaping not necessary if we always use " to write attributes + // (see: http://www.w3.org/TR/xml/#syntax) + + for( std::size_t i = 0; i < m_str.size(); ++ i ) { + char c = m_str[i]; + switch( c ) { + case '<': os << "<"; break; + case '&': os << "&"; break; + + case '>': + // See: http://www.w3.org/TR/xml/#syntax + if( i > 2 && m_str[i-1] == ']' && m_str[i-2] == ']' ) + os << ">"; + else + os << c; + break; + + case '\"': + if( m_forWhat == ForAttributes ) + os << """; + else + os << c; + break; + + default: + // Escape control chars - based on contribution by @espenalb in PR #465 and + // by @mrpi PR #588 + if ( ( c >= 0 && c < '\x09' ) || ( c > '\x0D' && c < '\x20') || c=='\x7F' ) { + // see http://stackoverflow.com/questions/404107/why-are-control-characters-illegal-in-xml-1-0 + os << "\\x" << std::uppercase << std::hex << std::setfill('0') << std::setw(2) + << static_cast( c ); + } + else + os << c; + } + } + } + + friend std::ostream& operator << ( std::ostream& os, XmlEncode const& xmlEncode ) { + xmlEncode.encodeTo( os ); + return os; + } private: std::string m_str; @@ -9900,14 +9979,24 @@ namespace Catch { class ScopedElement { public: - ScopedElement( XmlWriter* writer ); + ScopedElement( XmlWriter* writer ) + : m_writer( writer ) + {} - ScopedElement( ScopedElement&& other ) noexcept; - ScopedElement& operator=( ScopedElement&& other ) noexcept; + ScopedElement( ScopedElement const& other ) + : m_writer( other.m_writer ){ + other.m_writer = CATCH_NULL; + } - ~ScopedElement(); + ~ScopedElement() { + if( m_writer ) + m_writer->endElement(); + } - ScopedElement& writeText( std::string const& text, bool indent = true ); + 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 ) { @@ -9916,790 +10005,622 @@ namespace Catch { } private: - mutable XmlWriter* m_writer = nullptr; + mutable XmlWriter* m_writer; }; - XmlWriter( std::ostream& os = Catch::cout() ); - ~XmlWriter(); + XmlWriter() + : m_tagIsOpen( false ), + m_needsNewline( false ), + m_os( Catch::cout() ) + { + writeDeclaration(); + } - XmlWriter( XmlWriter const& ) = delete; - XmlWriter& operator=( XmlWriter const& ) = delete; + XmlWriter( std::ostream& os ) + : m_tagIsOpen( false ), + m_needsNewline( false ), + m_os( os ) + { + writeDeclaration(); + } - XmlWriter& startElement( std::string const& name ); + ~XmlWriter() { + while( !m_tags.empty() ) + endElement(); + } - ScopedElement scopedElement( std::string const& name ); + XmlWriter& startElement( std::string const& name ) { + ensureTagClosed(); + newlineIfNecessary(); + m_os << m_indent << '<' << name; + m_tags.push_back( name ); + m_indent += " "; + m_tagIsOpen = true; + return *this; + } - XmlWriter& endElement(); + ScopedElement scopedElement( std::string const& name ) { + ScopedElement scoped( this ); + startElement( name ); + return scoped; + } - XmlWriter& writeAttribute( std::string const& name, std::string const& attribute ); + XmlWriter& endElement() { + newlineIfNecessary(); + m_indent = m_indent.substr( 0, m_indent.size()-2 ); + if( m_tagIsOpen ) { + m_os << "/>"; + m_tagIsOpen = false; + } + else { + m_os << m_indent << ""; + } + m_os << std::endl; + m_tags.pop_back(); + return *this; + } - XmlWriter& writeAttribute( std::string const& name, bool attribute ); + XmlWriter& writeAttribute( std::string const& name, std::string const& attribute ) { + if( !name.empty() && !attribute.empty() ) + m_os << ' ' << name << "=\"" << XmlEncode( attribute, XmlEncode::ForAttributes ) << '"'; + return *this; + } + + XmlWriter& writeAttribute( std::string const& name, bool attribute ) { + m_os << ' ' << name << "=\"" << ( attribute ? "true" : "false" ) << '"'; + return *this; + } template XmlWriter& writeAttribute( std::string const& name, T const& attribute ) { - m_oss.clear(); - m_oss.str(std::string()); - m_oss << attribute; - return writeAttribute( name, m_oss.str() ); + std::ostringstream oss; + oss << attribute; + return writeAttribute( name, oss.str() ); } - XmlWriter& writeText( std::string const& text, bool indent = true ); + XmlWriter& writeText( std::string const& text, bool indent = true ) { + if( !text.empty() ){ + bool tagWasOpen = m_tagIsOpen; + ensureTagClosed(); + if( tagWasOpen && indent ) + m_os << m_indent; + m_os << XmlEncode( text ); + m_needsNewline = true; + } + return *this; + } - XmlWriter& writeComment( std::string const& text ); + XmlWriter& writeComment( std::string const& text ) { + ensureTagClosed(); + m_os << m_indent << ""; + m_needsNewline = true; + return *this; + } - void writeStylesheetRef( std::string const& url ); + void writeStylesheetRef( std::string const& url ) { + m_os << "\n"; + } - XmlWriter& writeBlankLine(); + XmlWriter& writeBlankLine() { + ensureTagClosed(); + m_os << '\n'; + return *this; + } - void ensureTagClosed(); + void ensureTagClosed() { + if( m_tagIsOpen ) { + m_os << ">" << std::endl; + m_tagIsOpen = false; + } + } private: + XmlWriter( XmlWriter const& ); + void operator=( XmlWriter const& ); - void writeDeclaration(); + void writeDeclaration() { + m_os << "\n"; + } - void newlineIfNecessary(); + void newlineIfNecessary() { + if( m_needsNewline ) { + m_os << std::endl; + m_needsNewline = false; + } + } - bool m_tagIsOpen = false; - bool m_needsNewline = false; + bool m_tagIsOpen; + bool m_needsNewline; std::vector m_tags; std::string m_indent; std::ostream& m_os; - std::ostringstream m_oss; }; } -// end catch_xmlwriter.h -#include - namespace Catch { - - XmlEncode::XmlEncode( std::string const& str, ForWhat forWhat ) - : m_str( str ), - m_forWhat( forWhat ) - {} - - void XmlEncode::encodeTo( std::ostream& os ) const { - - // Apostrophe escaping not necessary if we always use " to write attributes - // (see: http://www.w3.org/TR/xml/#syntax) - - for( std::size_t i = 0; i < m_str.size(); ++ i ) { - char c = m_str[i]; - switch( c ) { - case '<': os << "<"; break; - case '&': os << "&"; break; - - case '>': - // See: http://www.w3.org/TR/xml/#syntax - if( i > 2 && m_str[i-1] == ']' && m_str[i-2] == ']' ) - os << ">"; - else - os << c; - break; - - case '\"': - if( m_forWhat == ForAttributes ) - os << """; - else - os << c; - break; - - default: - // Escape control chars - based on contribution by @espenalb in PR #465 and - // by @mrpi PR #588 - if ( ( c >= 0 && c < '\x09' ) || ( c > '\x0D' && c < '\x20') || c=='\x7F' ) { - // see http://stackoverflow.com/questions/404107/why-are-control-characters-illegal-in-xml-1-0 - os << "\\x" << std::uppercase << std::hex << std::setfill('0') << std::setw(2) - << static_cast( c ); - } - else - os << c; - } + class XmlReporter : public StreamingReporterBase { + public: + XmlReporter( ReporterConfig const& _config ) + : StreamingReporterBase( _config ), + m_xml(_config.stream()), + m_sectionDepth( 0 ) + { + m_reporterPrefs.shouldRedirectStdOut = true; } - } - std::ostream& operator << ( std::ostream& os, XmlEncode const& xmlEncode ) { - xmlEncode.encodeTo( os ); - return os; - } - - XmlWriter::ScopedElement::ScopedElement( XmlWriter* writer ) - : m_writer( writer ) - {} - - XmlWriter::ScopedElement::ScopedElement( ScopedElement&& other ) noexcept - : m_writer( other.m_writer ){ - other.m_writer = nullptr; - } - XmlWriter::ScopedElement& XmlWriter::ScopedElement::operator=( ScopedElement&& other ) noexcept { - if ( m_writer ) { - m_writer->endElement(); - } - m_writer = other.m_writer; - other.m_writer = nullptr; - return *this; - } - - XmlWriter::ScopedElement::~ScopedElement() { - if( m_writer ) - m_writer->endElement(); - } - - XmlWriter::ScopedElement& XmlWriter::ScopedElement::writeText( std::string const& text, bool indent ) { - m_writer->writeText( text, indent ); - return *this; - } - - XmlWriter::XmlWriter( std::ostream& os ) : m_os( os ) - { - writeDeclaration(); - } - - XmlWriter::~XmlWriter() { - while( !m_tags.empty() ) - endElement(); - } - - XmlWriter& XmlWriter::startElement( std::string const& name ) { - ensureTagClosed(); - newlineIfNecessary(); - m_os << m_indent << '<' << name; - m_tags.push_back( name ); - m_indent += " "; - m_tagIsOpen = true; - return *this; - } - - XmlWriter::ScopedElement XmlWriter::scopedElement( std::string const& name ) { - ScopedElement scoped( this ); - startElement( name ); - return scoped; - } - - XmlWriter& XmlWriter::endElement() { - newlineIfNecessary(); - m_indent = m_indent.substr( 0, m_indent.size()-2 ); - if( m_tagIsOpen ) { - m_os << "/>"; - m_tagIsOpen = false; - } - else { - m_os << m_indent << ""; - } - m_os << std::endl; - m_tags.pop_back(); - return *this; - } - - XmlWriter& XmlWriter::writeAttribute( std::string const& name, std::string const& attribute ) { - if( !name.empty() && !attribute.empty() ) - m_os << ' ' << name << "=\"" << XmlEncode( attribute, XmlEncode::ForAttributes ) << '"'; - return *this; - } - - XmlWriter& XmlWriter::writeAttribute( std::string const& name, bool attribute ) { - m_os << ' ' << name << "=\"" << ( attribute ? "true" : "false" ) << '"'; - return *this; - } - - XmlWriter& XmlWriter::writeText( std::string const& text, bool indent ) { - if( !text.empty() ){ - bool tagWasOpen = m_tagIsOpen; - ensureTagClosed(); - if( tagWasOpen && indent ) - m_os << m_indent; - m_os << XmlEncode( text ); - m_needsNewline = true; - } - return *this; - } - - XmlWriter& XmlWriter::writeComment( std::string const& text ) { - ensureTagClosed(); - m_os << m_indent << ""; - m_needsNewline = true; - return *this; - } - - void XmlWriter::writeStylesheetRef( std::string const& url ) { - m_os << "\n"; - } - - XmlWriter& XmlWriter::writeBlankLine() { - ensureTagClosed(); - m_os << '\n'; - return *this; - } - - void XmlWriter::ensureTagClosed() { - if( m_tagIsOpen ) { - m_os << ">" << std::endl; - m_tagIsOpen = false; - } - } - - void XmlWriter::writeDeclaration() { - m_os << "\n"; - } - - void XmlWriter::newlineIfNecessary() { - if( m_needsNewline ) { - m_os << std::endl; - m_needsNewline = false; - } - } -} -// end catch_xmlwriter.cpp -// start catch_reporter_bases.cpp - -#include -#include -#include -#include -#include - -namespace Catch { - void prepareExpandedExpression(AssertionResult& result) { - result.getExpandedExpression(); - } - - // Because formatting using c++ streams is stateful, drop down to C is required - // Alternatively we could use stringstream, but its performance is... not good. - std::string getFormattedDuration( double duration ) { - // Max exponent + 1 is required to represent the whole part - // + 1 for decimal point - // + 3 for the 3 decimal places - // + 1 for null terminator - const std::size_t maxDoubleSize = DBL_MAX_10_EXP + 1 + 1 + 3 + 1; - char buffer[maxDoubleSize]; - - // Save previous errno, to prevent sprintf from overwriting it - ErrnoGuard guard; -#ifdef _MSC_VER - sprintf_s(buffer, "%.3f", duration); -#else - sprintf(buffer, "%.3f", duration); -#endif - return std::string(buffer); - } - - TestEventListenerBase::TestEventListenerBase(ReporterConfig const & _config) - :StreamingReporterBase(_config) {} - - void TestEventListenerBase::assertionStarting(AssertionInfo const &) {} - - bool TestEventListenerBase::assertionEnded(AssertionStats const &) { - return false; - } - -} // end namespace Catch -// end catch_reporter_bases.cpp -// start catch_reporter_compact.cpp - -namespace { - -#ifdef CATCH_PLATFORM_MAC - const char* failedString() { return "FAILED"; } - const char* passedString() { return "PASSED"; } -#else - const char* failedString() { return "failed"; } - const char* passedString() { return "passed"; } -#endif - - // Colour::LightGrey - Catch::Colour::Code dimColour() { return Catch::Colour::FileName; } - - std::string bothOrAll( std::size_t count ) { - return count == 1 ? std::string() : - count == 2 ? "both " : "all " ; - } -} - -namespace Catch { - - struct CompactReporter : StreamingReporterBase { - - using StreamingReporterBase::StreamingReporterBase; - - ~CompactReporter() override; + virtual ~XmlReporter() CATCH_OVERRIDE; static std::string getDescription() { - return "Reports test results on a single line, suitable for IDEs"; + return "Reports test results as an XML document"; } - ReporterPreferences getPreferences() const override { - ReporterPreferences prefs; - prefs.shouldRedirectStdOut = false; - return prefs; + virtual std::string getStylesheetRef() const { + return std::string(); } - void noMatchingTestCases( std::string const& spec ) override { - stream << "No test cases matched '" << spec << '\'' << std::endl; + void writeSourceInfo( SourceLineInfo const& sourceInfo ) { + m_xml + .writeAttribute( "filename", sourceInfo.file ) + .writeAttribute( "line", sourceInfo.line ); } - void assertionStarting( AssertionInfo const& ) override {} + public: // StreamingReporterBase - bool assertionEnded( AssertionStats const& _assertionStats ) override { - AssertionResult const& result = _assertionStats.assertionResult; + virtual void noMatchingTestCases( std::string const& s ) CATCH_OVERRIDE { + StreamingReporterBase::noMatchingTestCases( s ); + } - bool printInfoMessages = true; + virtual void testRunStarting( TestRunInfo const& testInfo ) CATCH_OVERRIDE { + StreamingReporterBase::testRunStarting( testInfo ); + std::string stylesheetRef = getStylesheetRef(); + if( !stylesheetRef.empty() ) + m_xml.writeStylesheetRef( stylesheetRef ); + m_xml.startElement( "Catch" ); + if( !m_config->name().empty() ) + m_xml.writeAttribute( "name", m_config->name() ); + } - // 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 testGroupStarting( GroupInfo const& groupInfo ) CATCH_OVERRIDE { + StreamingReporterBase::testGroupStarting( groupInfo ); + m_xml.startElement( "Group" ) + .writeAttribute( "name", groupInfo.name ); + } + + virtual void testCaseStarting( TestCaseInfo const& testInfo ) CATCH_OVERRIDE { + StreamingReporterBase::testCaseStarting(testInfo); + m_xml.startElement( "TestCase" ) + .writeAttribute( "name", trim( testInfo.name ) ) + .writeAttribute( "description", testInfo.description ) + .writeAttribute( "tags", testInfo.tagsAsString ); + + writeSourceInfo( testInfo.lineInfo ); + + if ( m_config->showDurations() == ShowDurations::Always ) + m_testCaseTimer.start(); + m_xml.ensureTagClosed(); + } + + virtual void sectionStarting( SectionInfo const& sectionInfo ) CATCH_OVERRIDE { + StreamingReporterBase::sectionStarting( sectionInfo ); + if( m_sectionDepth++ > 0 ) { + m_xml.startElement( "Section" ) + .writeAttribute( "name", trim( sectionInfo.name ) ) + .writeAttribute( "description", sectionInfo.description ); + writeSourceInfo( sectionInfo.lineInfo ); + m_xml.ensureTagClosed(); + } + } + + virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE { } + + virtual bool assertionEnded( AssertionStats const& assertionStats ) CATCH_OVERRIDE { + + AssertionResult const& result = assertionStats.assertionResult; + + bool includeResults = m_config->includeSuccessfulResults() || !result.isOk(); + + if( includeResults ) { + // Print any info messages in tags. + for( std::vector::const_iterator it = assertionStats.infoMessages.begin(), itEnd = assertionStats.infoMessages.end(); + it != itEnd; + ++it ) { + if( it->type == ResultWas::Info ) { + m_xml.scopedElement( "Info" ) + .writeText( it->message ); + } else if ( it->type == ResultWas::Warning ) { + m_xml.scopedElement( "Warning" ) + .writeText( it->message ); + } + } } - AssertionPrinter printer( stream, _assertionStats, printInfoMessages ); - printer.print(); + // Drop out if result was successful but we're not printing them. + if( !includeResults && result.getResultType() != ResultWas::Warning ) + return true; + + // Print the expression if there is one. + if( result.hasExpression() ) { + m_xml.startElement( "Expression" ) + .writeAttribute( "success", result.succeeded() ) + .writeAttribute( "type", result.getTestMacroName() ); + + writeSourceInfo( result.getSourceInfo() ); + + m_xml.scopedElement( "Original" ) + .writeText( result.getExpression() ); + m_xml.scopedElement( "Expanded" ) + .writeText( result.getExpandedExpression() ); + } + + // And... Print a result applicable to each result type. + switch( result.getResultType() ) { + case ResultWas::ThrewException: + m_xml.startElement( "Exception" ); + writeSourceInfo( result.getSourceInfo() ); + m_xml.writeText( result.getMessage() ); + m_xml.endElement(); + break; + case ResultWas::FatalErrorCondition: + m_xml.startElement( "FatalErrorCondition" ); + writeSourceInfo( result.getSourceInfo() ); + m_xml.writeText( result.getMessage() ); + m_xml.endElement(); + break; + case ResultWas::Info: + m_xml.scopedElement( "Info" ) + .writeText( result.getMessage() ); + break; + case ResultWas::Warning: + // Warning will already have been written + break; + case ResultWas::ExplicitFailure: + m_xml.startElement( "Failure" ); + writeSourceInfo( result.getSourceInfo() ); + m_xml.writeText( result.getMessage() ); + m_xml.endElement(); + break; + default: + break; + } + + if( result.hasExpression() ) + m_xml.endElement(); - stream << std::endl; return true; } - void sectionEnded(SectionStats const& _sectionStats) override { - if (m_config->showDurations() == ShowDurations::Always) { - stream << getFormattedDuration(_sectionStats.durationInSeconds) << " s: " << _sectionStats.sectionInfo.name << std::endl; + virtual void sectionEnded( SectionStats const& sectionStats ) CATCH_OVERRIDE { + StreamingReporterBase::sectionEnded( sectionStats ); + if( --m_sectionDepth > 0 ) { + XmlWriter::ScopedElement e = m_xml.scopedElement( "OverallResults" ); + e.writeAttribute( "successes", sectionStats.assertions.passed ); + e.writeAttribute( "failures", sectionStats.assertions.failed ); + e.writeAttribute( "expectedFailures", sectionStats.assertions.failedButOk ); + + if ( m_config->showDurations() == ShowDurations::Always ) + e.writeAttribute( "durationInSeconds", sectionStats.durationInSeconds ); + + m_xml.endElement(); } } - void testRunEnded( TestRunStats const& _testRunStats ) override { - printTotals( _testRunStats.totals ); - stream << '\n' << std::endl; - StreamingReporterBase::testRunEnded( _testRunStats ); + virtual void testCaseEnded( TestCaseStats const& testCaseStats ) CATCH_OVERRIDE { + StreamingReporterBase::testCaseEnded( testCaseStats ); + XmlWriter::ScopedElement e = m_xml.scopedElement( "OverallResult" ); + e.writeAttribute( "success", testCaseStats.totals.assertions.allOk() ); + + if ( m_config->showDurations() == ShowDurations::Always ) + e.writeAttribute( "durationInSeconds", m_testCaseTimer.getElapsedSeconds() ); + + if( !testCaseStats.stdOut.empty() ) + m_xml.scopedElement( "StdOut" ).writeText( trim( testCaseStats.stdOut ), false ); + if( !testCaseStats.stdErr.empty() ) + m_xml.scopedElement( "StdErr" ).writeText( trim( testCaseStats.stdErr ), false ); + + m_xml.endElement(); + } + + virtual void testGroupEnded( TestGroupStats const& testGroupStats ) CATCH_OVERRIDE { + StreamingReporterBase::testGroupEnded( testGroupStats ); + // TODO: Check testGroupStats.aborting and act accordingly. + m_xml.scopedElement( "OverallResults" ) + .writeAttribute( "successes", testGroupStats.totals.assertions.passed ) + .writeAttribute( "failures", testGroupStats.totals.assertions.failed ) + .writeAttribute( "expectedFailures", testGroupStats.totals.assertions.failedButOk ); + m_xml.endElement(); + } + + virtual void testRunEnded( TestRunStats const& testRunStats ) CATCH_OVERRIDE { + StreamingReporterBase::testRunEnded( testRunStats ); + m_xml.scopedElement( "OverallResults" ) + .writeAttribute( "successes", testRunStats.totals.assertions.passed ) + .writeAttribute( "failures", testRunStats.totals.assertions.failed ) + .writeAttribute( "expectedFailures", testRunStats.totals.assertions.failedButOk ); + m_xml.endElement(); } private: - class AssertionPrinter { - public: - AssertionPrinter& operator= ( AssertionPrinter const& ) = delete; - AssertionPrinter( AssertionPrinter const& ) = delete; - AssertionPrinter( std::ostream& _stream, AssertionStats const& _stats, bool _printInfoMessages ) - : stream( _stream ) - , result( _stats.assertionResult ) - , messages( _stats.infoMessages ) - , itMessage( _stats.infoMessages.begin() ) - , printInfoMessages( _printInfoMessages ) - {} - - void print() { - printSourceInfo(); - - itMessage = messages.begin(); - - switch( result.getResultType() ) { - case ResultWas::Ok: - printResultType( Colour::ResultSuccess, passedString() ); - printOriginalExpression(); - printReconstructedExpression(); - if ( ! result.hasExpression() ) - printRemainingMessages( Colour::None ); - else - printRemainingMessages(); - break; - case ResultWas::ExpressionFailed: - if( result.isOk() ) - printResultType( Colour::ResultSuccess, failedString() + std::string( " - but was ok" ) ); - else - printResultType( Colour::Error, failedString() ); - printOriginalExpression(); - printReconstructedExpression(); - printRemainingMessages(); - break; - case ResultWas::ThrewException: - printResultType( Colour::Error, failedString() ); - printIssue( "unexpected exception with message:" ); - printMessage(); - printExpressionWas(); - printRemainingMessages(); - break; - case ResultWas::FatalErrorCondition: - printResultType( Colour::Error, failedString() ); - printIssue( "fatal error condition with message:" ); - printMessage(); - printExpressionWas(); - printRemainingMessages(); - break; - case ResultWas::DidntThrowException: - printResultType( Colour::Error, failedString() ); - printIssue( "expected exception, got none" ); - printExpressionWas(); - printRemainingMessages(); - break; - case ResultWas::Info: - printResultType( Colour::None, "info" ); - printMessage(); - printRemainingMessages(); - break; - case ResultWas::Warning: - printResultType( Colour::None, "warning" ); - printMessage(); - printRemainingMessages(); - break; - case ResultWas::ExplicitFailure: - printResultType( Colour::Error, failedString() ); - printIssue( "explicitly" ); - printRemainingMessages( Colour::None ); - break; - // These cases are here to prevent compiler warnings - case ResultWas::Unknown: - case ResultWas::FailureBit: - case ResultWas::Exception: - printResultType( Colour::Error, "** internal error **" ); - break; - } - } - - private: - void printSourceInfo() const { - Colour colourGuard( Colour::FileName ); - stream << result.getSourceInfo() << ':'; - } - - void printResultType( Colour::Code colour, std::string const& passOrFail ) const { - if( !passOrFail.empty() ) { - { - Colour colourGuard( colour ); - stream << ' ' << passOrFail; - } - stream << ':'; - } - } - - void printIssue( std::string const& 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 (or auto) 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"; - } - } - } - } - - private: - std::ostream& stream; - 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. - - 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 ) : std::string(); - 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" ) << '.'; - } - } + Timer m_testCaseTimer; + XmlWriter m_xml; + int m_sectionDepth; }; - CompactReporter::~CompactReporter() {} - - CATCH_REGISTER_REPORTER( "compact", CompactReporter ) + INTERNAL_CATCH_REGISTER_REPORTER( "xml", XmlReporter ) } // end namespace Catch -// end catch_reporter_compact.cpp -// start catch_reporter_console.cpp -#include -#include +// #included from: ../reporters/catch_reporter_junit.hpp +#define TWOBLUECUBES_CATCH_REPORTER_JUNIT_HPP_INCLUDED -#if defined(_MSC_VER) -#pragma warning(push) -#pragma warning(disable:4061) // Not all labels are EXPLICITLY handled in switch - // Note that 4062 (not all labels are handled - // and default is missing) is enabled -#endif +#include namespace Catch { namespace { - 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; + std::string getCurrentTimestamp() { + // Beware, this is not reentrant because of backward compatibility issues + // Also, UTC only, again because of backward compatibility (%z is C++11) + time_t rawtime; + std::time(&rawtime); + const size_t timeStampSize = sizeof("2017-01-16T17:06:45Z"); + +#ifdef _MSC_VER + std::tm timeInfo = {}; + gmtime_s(&timeInfo, &rawtime); +#else + std::tm* timeInfo; + timeInfo = std::gmtime(&rawtime); +#endif + + char timeStamp[timeStampSize]; + const char * const fmt = "%Y-%m-%dT%H:%M:%SZ"; + +#ifdef _MSC_VER + std::strftime(timeStamp, timeStampSize, fmt, &timeInfo); +#else + std::strftime(timeStamp, timeStampSize, fmt, timeInfo); +#endif + return std::string(timeStamp); } - 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; + } + + class JunitReporter : public CumulativeReporterBase { + public: + JunitReporter( ReporterConfig const& _config ) + : CumulativeReporterBase( _config ), + xml( _config.stream() ), + unexpectedExceptions( 0 ), + m_okToFail( false ) + { + m_reporterPrefs.shouldRedirectStdOut = true; + } + + virtual ~JunitReporter() CATCH_OVERRIDE; + + static std::string getDescription() { + return "Reports test results in an XML format that looks like Ant's junitreport target"; + } + + virtual void noMatchingTestCases( std::string const& /*spec*/ ) CATCH_OVERRIDE {} + + virtual void testRunStarting( TestRunInfo const& runInfo ) CATCH_OVERRIDE { + CumulativeReporterBase::testRunStarting( runInfo ); + xml.startElement( "testsuites" ); + } + + virtual void testGroupStarting( GroupInfo const& groupInfo ) CATCH_OVERRIDE { + suiteTimer.start(); + stdOutForSuite.str(""); + stdErrForSuite.str(""); + unexpectedExceptions = 0; + CumulativeReporterBase::testGroupStarting( groupInfo ); + } + + virtual void testCaseStarting( TestCaseInfo const& testCaseInfo ) CATCH_OVERRIDE { + m_okToFail = testCaseInfo.okToFail(); + } + virtual bool assertionEnded( AssertionStats const& assertionStats ) CATCH_OVERRIDE { + if( assertionStats.assertionResult.getResultType() == ResultWas::ThrewException && !m_okToFail ) + unexpectedExceptions++; + return CumulativeReporterBase::assertionEnded( assertionStats ); + } + + virtual void testCaseEnded( TestCaseStats const& testCaseStats ) CATCH_OVERRIDE { + stdOutForSuite << testCaseStats.stdOut; + stdErrForSuite << testCaseStats.stdErr; + CumulativeReporterBase::testCaseEnded( testCaseStats ); + } + + virtual void testGroupEnded( TestGroupStats const& testGroupStats ) CATCH_OVERRIDE { + double suiteTime = suiteTimer.getElapsedSeconds(); + CumulativeReporterBase::testGroupEnded( testGroupStats ); + writeGroup( *m_testGroups.back(), suiteTime ); + } + + virtual void testRunEndedCumulative() CATCH_OVERRIDE { + xml.endElement(); + } + + void writeGroup( TestGroupNode const& groupNode, double suiteTime ) { + XmlWriter::ScopedElement e = xml.scopedElement( "testsuite" ); + TestGroupStats const& stats = groupNode.value; + xml.writeAttribute( "name", stats.groupInfo.name ); + xml.writeAttribute( "errors", unexpectedExceptions ); + xml.writeAttribute( "failures", stats.totals.assertions.failed-unexpectedExceptions ); + xml.writeAttribute( "tests", stats.totals.assertions.total() ); + xml.writeAttribute( "hostname", "tbd" ); // !TBD + if( m_config->showDurations() == ShowDurations::Never ) + xml.writeAttribute( "time", "" ); else - return k; + xml.writeAttribute( "time", suiteTime ); + xml.writeAttribute( "timestamp", getCurrentTimestamp() ); + + // Write test cases + for( TestGroupNode::ChildNodes::const_iterator + it = groupNode.children.begin(), itEnd = groupNode.children.end(); + it != itEnd; + ++it ) + writeTestCase( **it ); + + xml.scopedElement( "system-out" ).writeText( trim( stdOutForSuite.str() ), false ); + xml.scopedElement( "system-err" ).writeText( trim( stdErrForSuite.str() ), false ); } - struct ColumnInfo { - enum Justification { Left, Right }; - std::string name; - int width; - Justification justification; - }; - struct ColumnBreak {}; - struct RowBreak {}; + void writeTestCase( TestCaseNode const& testCaseNode ) { + TestCaseStats const& stats = testCaseNode.value; - class TablePrinter { - std::ostream& m_os; - std::vector m_columnInfos; - std::ostringstream m_oss; - int m_currentColumn = -1; - bool m_isOpen = false; + // 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(); - public: - TablePrinter( std::ostream& os, std::vector const& columnInfos ) - : m_os( os ), - m_columnInfos( columnInfos ) - {} + std::string className = stats.testInfo.className; - auto columnInfos() const -> std::vector const& { - return m_columnInfos; + if( className.empty() ) { + if( rootSection.childSections.empty() ) + className = "global"; } + writeSection( className, "", rootSection ); + } - void open() { - if( !m_isOpen ) { - m_isOpen = true; - *this << RowBreak(); - for( auto const& info : m_columnInfos ) - *this << info.name << ColumnBreak(); - *this << RowBreak(); - m_os << Catch::getLineOfChars<'-'>() << "\n"; + 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" ); } - } - void close() { - if( m_isOpen ) { - *this << RowBreak(); - m_os << std::endl; - m_isOpen = false; + else { + xml.writeAttribute( "classname", className ); + xml.writeAttribute( "name", name ); } + xml.writeAttribute( "time", Catch::toString( sectionNode.stats.durationInSeconds ) ); + + writeAssertions( sectionNode ); + + if( !sectionNode.stdOut.empty() ) + xml.scopedElement( "system-out" ).writeText( trim( sectionNode.stdOut ), false ); + if( !sectionNode.stdErr.empty() ) + xml.scopedElement( "system-err" ).writeText( trim( sectionNode.stdErr ), false ); } - - template - friend TablePrinter& operator << ( TablePrinter& tp, T const& value ) { - tp.m_oss << value; - return tp; - } - - friend TablePrinter& operator << ( TablePrinter& tp, ColumnBreak ) { - auto colStr = tp.m_oss.str(); - // This takes account of utf8 encodings - auto strSize = Catch::StringRef( colStr ).numberOfCharacters(); - tp.m_oss.str(""); - tp.open(); - if( tp.m_currentColumn == static_cast(tp.m_columnInfos.size()-1) ) { - tp.m_currentColumn = -1; - tp.m_os << "\n"; - } - tp.m_currentColumn++; - - auto colInfo = tp.m_columnInfos[tp.m_currentColumn]; - auto padding = ( strSize+2 < static_cast( colInfo.width ) ) - ? std::string( colInfo.width-(strSize+2), ' ' ) - : std::string(); - if( colInfo.justification == ColumnInfo::Left ) - tp.m_os << colStr << padding << " "; + for( SectionNode::ChildSections::const_iterator + it = sectionNode.childSections.begin(), + itEnd = sectionNode.childSections.end(); + it != itEnd; + ++it ) + if( className.empty() ) + writeSection( name, "", **it ); else - tp.m_os << padding << colStr << " "; - return tp; - } + writeSection( className, name, **it ); + } - friend TablePrinter& operator << ( TablePrinter& tp, RowBreak ) { - if( tp.m_currentColumn > 0 ) { - tp.m_os << "\n"; - tp.m_currentColumn = -1; - } - return tp; - } - }; + void writeAssertions( SectionNode const& sectionNode ) { + for( SectionNode::Assertions::const_iterator + it = sectionNode.assertions.begin(), itEnd = sectionNode.assertions.end(); + it != itEnd; + ++it ) + writeAssertion( *it ); + } + void writeAssertion( AssertionStats const& stats ) { + AssertionResult const& result = stats.assertionResult; + if( !result.isOk() ) { + std::string elementName; + switch( result.getResultType() ) { + case ResultWas::ThrewException: + case ResultWas::FatalErrorCondition: + elementName = "error"; + break; + case ResultWas::ExplicitFailure: + elementName = "failure"; + break; + case ResultWas::ExpressionFailed: + elementName = "failure"; + break; + case ResultWas::DidntThrowException: + elementName = "failure"; + break; - class Duration { - enum class Unit { - Auto, - Nanoseconds, - Microseconds, - Milliseconds, - Seconds, - Minutes - }; - static const uint64_t s_nanosecondsInAMicrosecond = 1000; - static const uint64_t s_nanosecondsInAMillisecond = 1000*s_nanosecondsInAMicrosecond; - static const uint64_t s_nanosecondsInASecond = 1000*s_nanosecondsInAMillisecond; - static const uint64_t s_nanosecondsInAMinute = 60*s_nanosecondsInASecond; - - uint64_t m_inNanoseconds; - Unit m_units; - - public: - Duration( uint64_t inNanoseconds, Unit units = Unit::Auto ) - : m_inNanoseconds( inNanoseconds ), - m_units( units ) - { - if( m_units == Unit::Auto ) { - if( m_inNanoseconds < s_nanosecondsInAMicrosecond ) - m_units = Unit::Nanoseconds; - else if( m_inNanoseconds < s_nanosecondsInAMillisecond ) - m_units = Unit::Microseconds; - else if( m_inNanoseconds < s_nanosecondsInASecond ) - m_units = Unit::Milliseconds; - else if( m_inNanoseconds < s_nanosecondsInAMinute ) - m_units = Unit::Seconds; - else - m_units = Unit::Minutes; + // 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 ); - auto value() const -> double { - switch( m_units ) { - case Unit::Microseconds: - return m_inNanoseconds / static_cast( s_nanosecondsInAMicrosecond ); - case Unit::Milliseconds: - return m_inNanoseconds / static_cast( s_nanosecondsInAMillisecond ); - case Unit::Seconds: - return m_inNanoseconds / static_cast( s_nanosecondsInASecond ); - case Unit::Minutes: - return m_inNanoseconds / static_cast( s_nanosecondsInAMinute ); - default: - return static_cast( m_inNanoseconds ); - } - } - auto unitsAsString() const -> std::string { - switch( m_units ) { - case Unit::Nanoseconds: - return "ns"; - case Unit::Microseconds: - return "µs"; - case Unit::Milliseconds: - return "ms"; - case Unit::Seconds: - return "s"; - case Unit::Minutes: - return "m"; - default: - return "** internal error **"; - } + xml.writeAttribute( "message", result.getExpandedExpression() ); + xml.writeAttribute( "type", result.getTestMacroName() ); - } - friend auto operator << ( std::ostream& os, Duration const& duration ) -> std::ostream& { - return os << duration.value() << " " << duration.unitsAsString(); - } - }; - } // end anon namespace + 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'; - struct ConsoleReporter : StreamingReporterBase { - TablePrinter m_tablePrinter; + oss << "at " << result.getSourceInfo(); + xml.writeText( oss.str(), false ); + } + } - ConsoleReporter( ReporterConfig const& config ) - : StreamingReporterBase( config ), - m_tablePrinter( config.stream(), - { - { "benchmark name", CATCH_CONFIG_CONSOLE_WIDTH-32, ColumnInfo::Left }, - { "iters", 8, ColumnInfo::Right }, - { "elapsed ns", 14, ColumnInfo::Right }, - { "average", 14, ColumnInfo::Right } - } ) + XmlWriter xml; + Timer suiteTimer; + std::ostringstream stdOutForSuite; + std::ostringstream stdErrForSuite; + unsigned int unexpectedExceptions; + bool m_okToFail; + }; + + INTERNAL_CATCH_REGISTER_REPORTER( "junit", JunitReporter ) + +} // end namespace Catch + +// #included from: ../reporters/catch_reporter_console.hpp +#define TWOBLUECUBES_CATCH_REPORTER_CONSOLE_HPP_INCLUDED + +#include +#include + +namespace Catch { + + struct ConsoleReporter : StreamingReporterBase { + ConsoleReporter( ReporterConfig const& _config ) + : StreamingReporterBase( _config ), + m_headerPrinted( false ) {} - ~ConsoleReporter() override; + + virtual ~ConsoleReporter() CATCH_OVERRIDE; static std::string getDescription() { return "Reports test results as plain lines of text"; } - void noMatchingTestCases( std::string const& spec ) override { + virtual void noMatchingTestCases( std::string const& spec ) CATCH_OVERRIDE { stream << "No test cases matched '" << spec << '\'' << std::endl; } - void assertionStarting( AssertionInfo const& ) override { + virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE { } - bool assertionEnded( AssertionStats const& _assertionStats ) override { + virtual bool assertionEnded( AssertionStats const& _assertionStats ) CATCH_OVERRIDE { AssertionResult const& result = _assertionStats.assertionResult; bool includeResults = m_config->includeSuccessfulResults() || !result.isOk(); @@ -10716,12 +10637,11 @@ namespace Catch { return true; } - void sectionStarting( SectionInfo const& _sectionInfo ) override { + virtual void sectionStarting( SectionInfo const& _sectionInfo ) CATCH_OVERRIDE { m_headerPrinted = false; StreamingReporterBase::sectionStarting( _sectionInfo ); } - void sectionEnded( SectionStats const& _sectionStats ) override { - m_tablePrinter.close(); + virtual void sectionEnded( SectionStats const& _sectionStats ) CATCH_OVERRIDE { if( _sectionStats.missingAssertions ) { lazyPrint(); Colour colour( Colour::ResultError ); @@ -10740,35 +10660,11 @@ namespace Catch { StreamingReporterBase::sectionEnded( _sectionStats ); } - void benchmarkStarting( BenchmarkInfo const& info ) override { - lazyPrintWithoutClosingBenchmarkTable(); - - auto nameCol = Column( info.name ).width( m_tablePrinter.columnInfos()[0].width-2 ); - - bool firstLine = true; - for( auto line : nameCol ) { - if( !firstLine ) - m_tablePrinter << ColumnBreak() << ColumnBreak() << ColumnBreak(); - else - firstLine = false; - - m_tablePrinter << line << ColumnBreak(); - } - } - void benchmarkEnded( BenchmarkStats const& stats ) override { - Duration average( stats.elapsedTimeInNanoseconds/stats.iterations ); - m_tablePrinter - << stats.iterations << ColumnBreak() - << stats.elapsedTimeInNanoseconds << ColumnBreak() - << average << ColumnBreak(); - } - - void testCaseEnded( TestCaseStats const& _testCaseStats ) override { - m_tablePrinter.close(); + virtual void testCaseEnded( TestCaseStats const& _testCaseStats ) CATCH_OVERRIDE { StreamingReporterBase::testCaseEnded( _testCaseStats ); m_headerPrinted = false; } - void testGroupEnded( TestGroupStats const& _testGroupStats ) override { + virtual void testGroupEnded( TestGroupStats const& _testGroupStats ) CATCH_OVERRIDE { if( currentGroupInfo.used ) { printSummaryDivider(); stream << "Summary for group '" << _testGroupStats.groupInfo.name << "':\n"; @@ -10777,7 +10673,7 @@ namespace Catch { } StreamingReporterBase::testGroupEnded( _testGroupStats ); } - void testRunEnded( TestRunStats const& _testRunStats ) override { + virtual void testRunEnded( TestRunStats const& _testRunStats ) CATCH_OVERRIDE { printTotalsDivider( _testRunStats.totals ); printTotals( _testRunStats.totals ); stream << std::endl; @@ -10787,9 +10683,8 @@ namespace Catch { private: class AssertionPrinter { + void operator= ( AssertionPrinter const& ); public: - AssertionPrinter& operator= ( AssertionPrinter const& ) = delete; - AssertionPrinter( AssertionPrinter const& ) = delete; AssertionPrinter( std::ostream& _stream, AssertionStats const& _stats, bool _printInfoMessages ) : stream( _stream ), stats( _stats ), @@ -10900,16 +10795,18 @@ namespace Catch { if( result.hasExpandedExpression() ) { stream << "with expansion:\n"; Colour colourGuard( Colour::ReconstructedExpression ); - stream << Column( result.getExpandedExpression() ).indent(2) << '\n'; + stream << Text( result.getExpandedExpression(), TextAttributes().setIndent(2) ) << '\n'; } } void printMessage() const { if( !messageLabel.empty() ) stream << messageLabel << ':' << '\n'; - for( auto const& msg : messages ) { + 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 || msg.type != ResultWas::Info ) - stream << Column( msg.message ).indent(2) << '\n'; + if( printInfoMessages || it->type != ResultWas::Info ) + stream << Text( it->message, TextAttributes().setIndent(2) ) << '\n'; } } void printSourceInfo() const { @@ -10930,12 +10827,6 @@ namespace Catch { void lazyPrint() { - m_tablePrinter.close(); - lazyPrintWithoutClosingBenchmarkTable(); - } - - void lazyPrintWithoutClosingBenchmarkTable() { - if( !currentTestRunInfo.used ) lazyPrintRunInfo(); if( !currentGroupInfo.used ) @@ -10971,7 +10862,7 @@ namespace Catch { if( m_sectionStack.size() > 1 ) { Colour colourGuard( Colour::Headers ); - auto + std::vector::const_iterator it = m_sectionStack.begin()+1, // Skip first section (test case) itEnd = m_sectionStack.end(); for( ; it != itEnd; ++it ) @@ -11008,7 +10899,9 @@ namespace Catch { i+=2; else i = 0; - stream << Column( _string ).indent( indent+i ).initialIndent( indent ) << '\n'; + stream << Text( _string, TextAttributes() + .setIndent( indent+i) + .setInitialIndent( indent ) ) << '\n'; } struct SummaryColumn { @@ -11021,10 +10914,10 @@ namespace Catch { std::ostringstream oss; oss << count; std::string row = oss.str(); - for( auto& oldRow : rows ) { - while( oldRow.size() < row.size() ) - oldRow = ' ' + oldRow; - while( oldRow.size() > row.size() ) + 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; } rows.push_back( row ); @@ -11069,9 +10962,9 @@ namespace Catch { } } void printSummaryRow( std::string const& label, std::vector const& cols, std::size_t row ) { - for( auto col : cols ) { - std::string value = col.rows[row]; - if( col.label.empty() ) { + 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; @@ -11080,13 +10973,26 @@ namespace Catch { } else if( value != "0" ) { stream << Colour( Colour::LightGrey ) << " | "; - stream << Colour( col.colour ) - << value << ' ' << col.label; + 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() ); @@ -11114,594 +11020,374 @@ namespace Catch { } private: - bool m_headerPrinted = false; + bool m_headerPrinted; }; - CATCH_REGISTER_REPORTER( "console", ConsoleReporter ) - - ConsoleReporter::~ConsoleReporter() {} + INTERNAL_CATCH_REGISTER_REPORTER( "console", ConsoleReporter ) } // end namespace Catch -#if defined(_MSC_VER) -#pragma warning(pop) -#endif -// end catch_reporter_console.cpp -// start catch_reporter_junit.cpp - -#include - -#include -#include +// #included from: ../reporters/catch_reporter_compact.hpp +#define TWOBLUECUBES_CATCH_REPORTER_COMPACT_HPP_INCLUDED namespace Catch { - namespace { - std::string getCurrentTimestamp() { - // Beware, this is not reentrant because of backward compatibility issues - // Also, UTC only, again because of backward compatibility (%z is C++11) - time_t rawtime; - std::time(&rawtime); - auto const timeStampSize = sizeof("2017-01-16T17:06:45Z"); + struct CompactReporter : StreamingReporterBase { -#ifdef _MSC_VER - std::tm timeInfo = {}; - gmtime_s(&timeInfo, &rawtime); -#else - std::tm* timeInfo; - timeInfo = std::gmtime(&rawtime); -#endif + CompactReporter( ReporterConfig const& _config ) + : StreamingReporterBase( _config ) + {} - char timeStamp[timeStampSize]; - const char * const fmt = "%Y-%m-%dT%H:%M:%SZ"; - -#ifdef _MSC_VER - std::strftime(timeStamp, timeStampSize, fmt, &timeInfo); -#else - std::strftime(timeStamp, timeStampSize, fmt, timeInfo); -#endif - return std::string(timeStamp); - } - - std::string fileNameTag(const std::vector &tags) { - auto it = std::find_if(begin(tags), - end(tags), - [] (std::string const& tag) {return tag.front() == '#'; }); - if (it != tags.end()) - return it->substr(1); - return std::string(); - } - } - - class JunitReporter : public CumulativeReporterBase { - public: - JunitReporter( ReporterConfig const& _config ) - : CumulativeReporterBase( _config ), - xml( _config.stream() ) - { - m_reporterPrefs.shouldRedirectStdOut = true; - } - - ~JunitReporter() override; + virtual ~CompactReporter(); static std::string getDescription() { - return "Reports test results in an XML format that looks like Ant's junitreport target"; + return "Reports test results on a single line, suitable for IDEs"; } - void noMatchingTestCases( std::string const& /*spec*/ ) override {} - - void testRunStarting( TestRunInfo const& runInfo ) override { - CumulativeReporterBase::testRunStarting( runInfo ); - xml.startElement( "testsuites" ); + virtual ReporterPreferences getPreferences() const { + ReporterPreferences prefs; + prefs.shouldRedirectStdOut = false; + return prefs; } - void testGroupStarting( GroupInfo const& groupInfo ) override { - suiteTimer.start(); - stdOutForSuite.str(""); - stdErrForSuite.str(""); - unexpectedExceptions = 0; - CumulativeReporterBase::testGroupStarting( groupInfo ); + virtual void noMatchingTestCases( std::string const& spec ) { + stream << "No test cases matched '" << spec << '\'' << std::endl; } - void testCaseStarting( TestCaseInfo const& testCaseInfo ) override { - m_okToFail = testCaseInfo.okToFail(); - } - bool assertionEnded( AssertionStats const& assertionStats ) override { - if( assertionStats.assertionResult.getResultType() == ResultWas::ThrewException && !m_okToFail ) - unexpectedExceptions++; - return CumulativeReporterBase::assertionEnded( assertionStats ); - } + virtual void assertionStarting( AssertionInfo const& ) {} - void testCaseEnded( TestCaseStats const& testCaseStats ) override { - stdOutForSuite << testCaseStats.stdOut; - stdErrForSuite << testCaseStats.stdErr; - CumulativeReporterBase::testCaseEnded( testCaseStats ); - } + virtual bool assertionEnded( AssertionStats const& _assertionStats ) { + AssertionResult const& result = _assertionStats.assertionResult; - void testGroupEnded( TestGroupStats const& testGroupStats ) override { - double suiteTime = suiteTimer.getElapsedSeconds(); - CumulativeReporterBase::testGroupEnded( testGroupStats ); - writeGroup( *m_testGroups.back(), suiteTime ); - } + bool printInfoMessages = true; - void testRunEndedCumulative() override { - xml.endElement(); - } - - void writeGroup( TestGroupNode const& groupNode, double suiteTime ) { - XmlWriter::ScopedElement e = xml.scopedElement( "testsuite" ); - TestGroupStats const& stats = groupNode.value; - xml.writeAttribute( "name", stats.groupInfo.name ); - xml.writeAttribute( "errors", unexpectedExceptions ); - xml.writeAttribute( "failures", stats.totals.assertions.failed-unexpectedExceptions ); - xml.writeAttribute( "tests", stats.totals.assertions.total() ); - xml.writeAttribute( "hostname", "tbd" ); // !TBD - if( m_config->showDurations() == ShowDurations::Never ) - xml.writeAttribute( "time", "" ); - else - xml.writeAttribute( "time", suiteTime ); - xml.writeAttribute( "timestamp", getCurrentTimestamp() ); - - // Write test cases - for( auto const& child : groupNode.children ) - writeTestCase( *child ); - - 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() ) { - className = fileNameTag(stats.testInfo.tags); - if ( className.empty() ) - className = "global"; + // 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; } - if ( !m_config->name().empty() ) - className = m_config->name() + "." + className; + AssertionPrinter printer( stream, _assertionStats, printInfoMessages ); + printer.print(); - writeSection( className, "", rootSection ); + stream << std::endl; + return true; } - void writeSection( std::string const& className, - std::string const& rootName, - SectionNode const& sectionNode ) { - std::string name = trim( sectionNode.stats.sectionInfo.name ); - if( !rootName.empty() ) - name = rootName + '/' + name; - - if( !sectionNode.assertions.empty() || - !sectionNode.stdOut.empty() || - !sectionNode.stdErr.empty() ) { - XmlWriter::ScopedElement e = xml.scopedElement( "testcase" ); - if( className.empty() ) { - xml.writeAttribute( "classname", name ); - xml.writeAttribute( "name", "root" ); - } - else { - xml.writeAttribute( "classname", className ); - xml.writeAttribute( "name", name ); - } - xml.writeAttribute( "time", ::Catch::Detail::stringify( 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 ); + virtual void sectionEnded(SectionStats const& _sectionStats) CATCH_OVERRIDE { + if (m_config->showDurations() == ShowDurations::Always) { + stream << getFormattedDuration(_sectionStats.durationInSeconds) << " s: " << _sectionStats.sectionInfo.name << std::endl; } - for( auto const& childNode : sectionNode.childSections ) - if( className.empty() ) - writeSection( name, "", *childNode ); - else - writeSection( className, name, *childNode ); } - void writeAssertions( SectionNode const& sectionNode ) { - for( auto const& assertion : sectionNode.assertions ) - writeAssertion( assertion ); + virtual void testRunEnded( TestRunStats const& _testRunStats ) { + printTotals( _testRunStats.totals ); + stream << '\n' << std::endl; + StreamingReporterBase::testRunEnded( _testRunStats ); } - void writeAssertion( AssertionStats const& stats ) { - AssertionResult const& result = stats.assertionResult; - if( !result.isOk() ) { - std::string elementName; + + private: + class AssertionPrinter { + void operator= ( AssertionPrinter const& ); + public: + AssertionPrinter( std::ostream& _stream, AssertionStats const& _stats, bool _printInfoMessages ) + : stream( _stream ) + , stats( _stats ) + , result( _stats.assertionResult ) + , messages( _stats.infoMessages ) + , itMessage( _stats.infoMessages.begin() ) + , printInfoMessages( _printInfoMessages ) + {} + + void print() { + printSourceInfo(); + + itMessage = messages.begin(); + switch( result.getResultType() ) { - case ResultWas::ThrewException: - case ResultWas::FatalErrorCondition: - elementName = "error"; - break; - case ResultWas::ExplicitFailure: - elementName = "failure"; + case ResultWas::Ok: + printResultType( Colour::ResultSuccess, passedString() ); + printOriginalExpression(); + printReconstructedExpression(); + if ( ! result.hasExpression() ) + printRemainingMessages( Colour::None ); + else + printRemainingMessages(); break; case ResultWas::ExpressionFailed: - elementName = "failure"; + if( result.isOk() ) + printResultType( Colour::ResultSuccess, failedString() + std::string( " - but was ok" ) ); + else + printResultType( Colour::Error, failedString() ); + printOriginalExpression(); + printReconstructedExpression(); + printRemainingMessages(); + break; + case ResultWas::ThrewException: + printResultType( Colour::Error, failedString() ); + printIssue( "unexpected exception with message:" ); + printMessage(); + printExpressionWas(); + printRemainingMessages(); + break; + case ResultWas::FatalErrorCondition: + printResultType( Colour::Error, failedString() ); + printIssue( "fatal error condition with message:" ); + printMessage(); + printExpressionWas(); + printRemainingMessages(); break; case ResultWas::DidntThrowException: - elementName = "failure"; + printResultType( Colour::Error, failedString() ); + printIssue( "expected exception, got none" ); + printExpressionWas(); + printRemainingMessages(); break; - - // We should never see these here: case ResultWas::Info: + printResultType( Colour::None, "info" ); + printMessage(); + printRemainingMessages(); + break; case ResultWas::Warning: - case ResultWas::Ok: + 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: - elementName = "internalError"; + printResultType( Colour::Error, "** internal error **" ); 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( auto const& msg : stats.infoMessages ) - if( msg.type == ResultWas::Info ) - oss << msg.message << '\n'; - - oss << "at " << result.getSourceInfo(); - xml.writeText( oss.str(), false ); } - } - XmlWriter xml; - Timer suiteTimer; - std::ostringstream stdOutForSuite; - std::ostringstream stdErrForSuite; - unsigned int unexpectedExceptions = 0; - bool m_okToFail = false; - }; + private: + // Colour::LightGrey - JunitReporter::~JunitReporter() {} - CATCH_REGISTER_REPORTER( "junit", JunitReporter ) + static Colour::Code dimColour() { return Colour::FileName; } -} // end namespace Catch -// end catch_reporter_junit.cpp -// start catch_reporter_multi.cpp - -namespace Catch { - - void MultipleReporters::add( IStreamingReporterPtr&& reporter ) { - m_reporters.push_back( std::move( reporter ) ); - } - - ReporterPreferences MultipleReporters::getPreferences() const { - return m_reporters[0]->getPreferences(); - } - - std::set MultipleReporters::getSupportedVerbosities() { - return std::set{ }; - } - - void MultipleReporters::noMatchingTestCases( std::string const& spec ) { - for( auto const& reporter : m_reporters ) - reporter->noMatchingTestCases( spec ); - } - - void MultipleReporters::benchmarkStarting( BenchmarkInfo const& benchmarkInfo ) { - for( auto const& reporter : m_reporters ) - reporter->benchmarkStarting( benchmarkInfo ); - } - void MultipleReporters::benchmarkEnded( BenchmarkStats const& benchmarkStats ) { - for( auto const& reporter : m_reporters ) - reporter->benchmarkEnded( benchmarkStats ); - } - - void MultipleReporters::testRunStarting( TestRunInfo const& testRunInfo ) { - for( auto const& reporter : m_reporters ) - reporter->testRunStarting( testRunInfo ); - } - - void MultipleReporters::testGroupStarting( GroupInfo const& groupInfo ) { - for( auto const& reporter : m_reporters ) - reporter->testGroupStarting( groupInfo ); - } - - void MultipleReporters::testCaseStarting( TestCaseInfo const& testInfo ) { - for( auto const& reporter : m_reporters ) - reporter->testCaseStarting( testInfo ); - } - - void MultipleReporters::sectionStarting( SectionInfo const& sectionInfo ) { - for( auto const& reporter : m_reporters ) - reporter->sectionStarting( sectionInfo ); - } - - void MultipleReporters::assertionStarting( AssertionInfo const& assertionInfo ) { - for( auto const& reporter : m_reporters ) - reporter->assertionStarting( assertionInfo ); - } - - // The return value indicates if the messages buffer should be cleared: - bool MultipleReporters::assertionEnded( AssertionStats const& assertionStats ) { - bool clearBuffer = false; - for( auto const& reporter : m_reporters ) - clearBuffer |= reporter->assertionEnded( assertionStats ); - return clearBuffer; - } - - void MultipleReporters::sectionEnded( SectionStats const& sectionStats ) { - for( auto const& reporter : m_reporters ) - reporter->sectionEnded( sectionStats ); - } - - void MultipleReporters::testCaseEnded( TestCaseStats const& testCaseStats ) { - for( auto const& reporter : m_reporters ) - reporter->testCaseEnded( testCaseStats ); - } - - void MultipleReporters::testGroupEnded( TestGroupStats const& testGroupStats ) { - for( auto const& reporter : m_reporters ) - reporter->testGroupEnded( testGroupStats ); - } - - void MultipleReporters::testRunEnded( TestRunStats const& testRunStats ) { - for( auto const& reporter : m_reporters ) - reporter->testRunEnded( testRunStats ); - } - - void MultipleReporters::skipTest( TestCaseInfo const& testInfo ) { - for( auto const& reporter : m_reporters ) - reporter->skipTest( testInfo ); - } - - bool MultipleReporters::isMulti() const { - return true; - } - -} // end namespace Catch -// end catch_reporter_multi.cpp -// start catch_reporter_xml.cpp - -#if defined(_MSC_VER) -#pragma warning(push) -#pragma warning(disable:4061) // Not all labels are EXPLICITLY handled in switch - // Note that 4062 (not all labels are handled - // and default is missing) is enabled +#ifdef CATCH_PLATFORM_MAC + static const char* failedString() { return "FAILED"; } + static const char* passedString() { return "PASSED"; } +#else + static const char* failedString() { return "failed"; } + static const char* passedString() { return "passed"; } #endif -namespace Catch { - class XmlReporter : public StreamingReporterBase { - public: - XmlReporter( ReporterConfig const& _config ) - : StreamingReporterBase( _config ), - m_xml(_config.stream()) - { - m_reporterPrefs.shouldRedirectStdOut = true; - } - - ~XmlReporter() override; - - static std::string getDescription() { - return "Reports test results as an XML document"; - } - - virtual std::string getStylesheetRef() const { - return std::string(); - } - - void writeSourceInfo( SourceLineInfo const& sourceInfo ) { - m_xml - .writeAttribute( "filename", sourceInfo.file ) - .writeAttribute( "line", sourceInfo.line ); - } - - public: // StreamingReporterBase - - void noMatchingTestCases( std::string const& s ) override { - StreamingReporterBase::noMatchingTestCases( s ); - } - - void testRunStarting( TestRunInfo const& testInfo ) override { - StreamingReporterBase::testRunStarting( testInfo ); - std::string stylesheetRef = getStylesheetRef(); - if( !stylesheetRef.empty() ) - m_xml.writeStylesheetRef( stylesheetRef ); - m_xml.startElement( "Catch" ); - if( !m_config->name().empty() ) - m_xml.writeAttribute( "name", m_config->name() ); - } - - void testGroupStarting( GroupInfo const& groupInfo ) override { - StreamingReporterBase::testGroupStarting( groupInfo ); - m_xml.startElement( "Group" ) - .writeAttribute( "name", groupInfo.name ); - } - - void testCaseStarting( TestCaseInfo const& testInfo ) override { - StreamingReporterBase::testCaseStarting(testInfo); - m_xml.startElement( "TestCase" ) - .writeAttribute( "name", trim( testInfo.name ) ) - .writeAttribute( "description", testInfo.description ) - .writeAttribute( "tags", testInfo.tagsAsString() ); - - writeSourceInfo( testInfo.lineInfo ); - - if ( m_config->showDurations() == ShowDurations::Always ) - m_testCaseTimer.start(); - m_xml.ensureTagClosed(); - } - - void sectionStarting( SectionInfo const& sectionInfo ) override { - StreamingReporterBase::sectionStarting( sectionInfo ); - if( m_sectionDepth++ > 0 ) { - m_xml.startElement( "Section" ) - .writeAttribute( "name", trim( sectionInfo.name ) ) - .writeAttribute( "description", sectionInfo.description ); - writeSourceInfo( sectionInfo.lineInfo ); - m_xml.ensureTagClosed(); + void printSourceInfo() const { + Colour colourGuard( Colour::FileName ); + stream << result.getSourceInfo() << ':'; } - } - void assertionStarting( AssertionInfo const& ) override { } + void printResultType( Colour::Code colour, std::string const& passOrFail ) const { + if( !passOrFail.empty() ) { + { + Colour colourGuard( colour ); + stream << ' ' << passOrFail; + } + stream << ':'; + } + } - bool assertionEnded( AssertionStats const& assertionStats ) override { + void printIssue( std::string const& issue ) const { + stream << ' ' << issue; + } - AssertionResult const& result = assertionStats.assertionResult; + void printExpressionWas() { + if( result.hasExpression() ) { + stream << ';'; + { + Colour colour( dimColour() ); + stream << " expression was:"; + } + printOriginalExpression(); + } + } - bool includeResults = m_config->includeSuccessfulResults() || !result.isOk(); + void printOriginalExpression() const { + if( result.hasExpression() ) { + stream << ' ' << result.getExpression(); + } + } - if( includeResults ) { - // Print any info messages in tags. - for( auto const& msg : assertionStats.infoMessages ) { - if( msg.type == ResultWas::Info ) { - m_xml.scopedElement( "Info" ) - .writeText( msg.message ); - } else if ( msg.type == ResultWas::Warning ) { - m_xml.scopedElement( "Warning" ) - .writeText( msg.message ); + 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"; + } } } } - // Drop out if result was successful but we're not printing them. - if( !includeResults && result.getResultType() != ResultWas::Warning ) - return true; + private: + std::ostream& stream; + AssertionStats const& stats; + AssertionResult const& result; + std::vector messages; + std::vector::const_iterator itMessage; + bool printInfoMessages; + }; - // Print the expression if there is one. - if( result.hasExpression() ) { - m_xml.startElement( "Expression" ) - .writeAttribute( "success", result.succeeded() ) - .writeAttribute( "type", result.getTestMacroName() ); + // 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. - writeSourceInfo( result.getSourceInfo() ); - - m_xml.scopedElement( "Original" ) - .writeText( result.getExpression() ); - m_xml.scopedElement( "Expanded" ) - .writeText( result.getExpandedExpression() ); - } - - // And... Print a result applicable to each result type. - switch( result.getResultType() ) { - case ResultWas::ThrewException: - m_xml.startElement( "Exception" ); - writeSourceInfo( result.getSourceInfo() ); - m_xml.writeText( result.getMessage() ); - m_xml.endElement(); - break; - case ResultWas::FatalErrorCondition: - m_xml.startElement( "FatalErrorCondition" ); - writeSourceInfo( result.getSourceInfo() ); - m_xml.writeText( result.getMessage() ); - m_xml.endElement(); - break; - case ResultWas::Info: - m_xml.scopedElement( "Info" ) - .writeText( result.getMessage() ); - break; - case ResultWas::Warning: - // Warning will already have been written - break; - case ResultWas::ExplicitFailure: - m_xml.startElement( "Failure" ); - writeSourceInfo( result.getSourceInfo() ); - m_xml.writeText( result.getMessage() ); - m_xml.endElement(); - break; - default: - break; - } - - if( result.hasExpression() ) - m_xml.endElement(); - - return true; + std::string bothOrAll( std::size_t count ) const { + return count == 1 ? std::string() : count == 2 ? "both " : "all " ; } - void sectionEnded( SectionStats const& sectionStats ) override { - StreamingReporterBase::sectionEnded( sectionStats ); - if( --m_sectionDepth > 0 ) { - XmlWriter::ScopedElement e = m_xml.scopedElement( "OverallResults" ); - e.writeAttribute( "successes", sectionStats.assertions.passed ); - e.writeAttribute( "failures", sectionStats.assertions.failed ); - e.writeAttribute( "expectedFailures", sectionStats.assertions.failedButOk ); - - if ( m_config->showDurations() == ShowDurations::Always ) - e.writeAttribute( "durationInSeconds", sectionStats.durationInSeconds ); - - m_xml.endElement(); + 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 ) : std::string(); + 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" ) << '.'; } } - - void testCaseEnded( TestCaseStats const& testCaseStats ) override { - StreamingReporterBase::testCaseEnded( testCaseStats ); - XmlWriter::ScopedElement e = m_xml.scopedElement( "OverallResult" ); - e.writeAttribute( "success", testCaseStats.totals.assertions.allOk() ); - - if ( m_config->showDurations() == ShowDurations::Always ) - e.writeAttribute( "durationInSeconds", m_testCaseTimer.getElapsedSeconds() ); - - if( !testCaseStats.stdOut.empty() ) - m_xml.scopedElement( "StdOut" ).writeText( trim( testCaseStats.stdOut ), false ); - if( !testCaseStats.stdErr.empty() ) - m_xml.scopedElement( "StdErr" ).writeText( trim( testCaseStats.stdErr ), false ); - - m_xml.endElement(); - } - - void testGroupEnded( TestGroupStats const& testGroupStats ) override { - StreamingReporterBase::testGroupEnded( testGroupStats ); - // TODO: Check testGroupStats.aborting and act accordingly. - m_xml.scopedElement( "OverallResults" ) - .writeAttribute( "successes", testGroupStats.totals.assertions.passed ) - .writeAttribute( "failures", testGroupStats.totals.assertions.failed ) - .writeAttribute( "expectedFailures", testGroupStats.totals.assertions.failedButOk ); - m_xml.endElement(); - } - - void testRunEnded( TestRunStats const& testRunStats ) override { - StreamingReporterBase::testRunEnded( testRunStats ); - m_xml.scopedElement( "OverallResults" ) - .writeAttribute( "successes", testRunStats.totals.assertions.passed ) - .writeAttribute( "failures", testRunStats.totals.assertions.failed ) - .writeAttribute( "expectedFailures", testRunStats.totals.assertions.failedButOk ); - m_xml.endElement(); - } - - private: - Timer m_testCaseTimer; - XmlWriter m_xml; - int m_sectionDepth = 0; }; - XmlReporter::~XmlReporter() {} - CATCH_REGISTER_REPORTER( "xml", XmlReporter ) + INTERNAL_CATCH_REGISTER_REPORTER( "compact", CompactReporter ) } // end namespace Catch -#if defined(_MSC_VER) -#pragma warning(pop) -#endif -// end catch_reporter_xml.cpp - namespace Catch { - LeakDetector leakDetector; + // These are all here to avoid warnings about not having any out of line + // virtual methods + NonCopyable::~NonCopyable() {} + IShared::~IShared() {} + IStream::~IStream() CATCH_NOEXCEPT {} + FileStream::~FileStream() CATCH_NOEXCEPT {} + CoutStream::~CoutStream() CATCH_NOEXCEPT {} + DebugOutStream::~DebugOutStream() CATCH_NOEXCEPT {} + StreamBufBase::~StreamBufBase() CATCH_NOEXCEPT {} + IContext::~IContext() {} + IResultCapture::~IResultCapture() {} + ITestCase::~ITestCase() {} + ITestCaseRegistry::~ITestCaseRegistry() {} + IRegistryHub::~IRegistryHub() {} + IMutableRegistryHub::~IMutableRegistryHub() {} + IExceptionTranslator::~IExceptionTranslator() {} + IExceptionTranslatorRegistry::~IExceptionTranslatorRegistry() {} + IReporter::~IReporter() {} + IReporterFactory::~IReporterFactory() {} + IReporterRegistry::~IReporterRegistry() {} + IStreamingReporter::~IStreamingReporter() {} + AssertionStats::~AssertionStats() {} + SectionStats::~SectionStats() {} + TestCaseStats::~TestCaseStats() {} + TestGroupStats::~TestGroupStats() {} + TestRunStats::~TestRunStats() {} + CumulativeReporterBase::SectionNode::~SectionNode() {} + CumulativeReporterBase::~CumulativeReporterBase() {} + + StreamingReporterBase::~StreamingReporterBase() {} + ConsoleReporter::~ConsoleReporter() {} + CompactReporter::~CompactReporter() {} + IRunner::~IRunner() {} + IMutableContext::~IMutableContext() {} + IConfig::~IConfig() {} + XmlReporter::~XmlReporter() {} + JunitReporter::~JunitReporter() {} + TestRegistry::~TestRegistry() {} + FreeFunctionTestCase::~FreeFunctionTestCase() {} + IGeneratorInfo::~IGeneratorInfo() {} + IGeneratorsForTest::~IGeneratorsForTest() {} + WildcardPattern::~WildcardPattern() {} + TestSpec::Pattern::~Pattern() {} + TestSpec::NamePattern::~NamePattern() {} + TestSpec::TagPattern::~TagPattern() {} + TestSpec::ExcludedPattern::~ExcludedPattern() {} + Matchers::Impl::MatcherUntypedBase::~MatcherUntypedBase() {} + + void Config::dummy() {} + + namespace TestCaseTracking { + ITracker::~ITracker() {} + TrackerBase::~TrackerBase() {} + SectionTracker::~SectionTracker() {} + IndexTracker::~IndexTracker() {} + } } #ifdef __clang__ #pragma clang diagnostic pop #endif -// end catch_impl.hpp #endif #ifdef CATCH_CONFIG_MAIN -// start catch_default_main.hpp +// #included from: internal/catch_default_main.hpp +#define TWOBLUECUBES_CATCH_DEFAULT_MAIN_HPP_INCLUDED #ifndef __OBJC__ @@ -11713,7 +11399,8 @@ extern "C" int wmain (int argc, wchar_t * argv[], wchar_t * []) { int main (int argc, char * argv[]) { #endif - return Catch::Session().run( argc, argv ); + int result = Catch::Session().run( argc, argv ); + return ( result < 0xff ? result : 0xff ); } #else // __OBJC__ @@ -11725,122 +11412,149 @@ int main (int argc, char * const argv[]) { #endif Catch::registerTestMethods(); - int result = Catch::Session().run( argc, (char**)argv ); + int result = Catch::Session().run( argc, (char* const*)argv ); #if !CATCH_ARC_ENABLED [pool drain]; #endif - return result; + return ( result < 0xff ? result : 0xff ); } #endif // __OBJC__ -// end catch_default_main.hpp #endif #ifdef CLARA_CONFIG_MAIN_NOT_DEFINED # undef CLARA_CONFIG_MAIN #endif -#if !defined(CATCH_CONFIG_DISABLE) ////// + // If this config identifier is defined then all CATCH macros are prefixed with CATCH_ #ifdef CATCH_CONFIG_PREFIX_ALL -#define CATCH_REQUIRE( ... ) INTERNAL_CATCH_TEST( "CATCH_REQUIRE", Catch::ResultDisposition::Normal, __VA_ARGS__ ) -#define CATCH_REQUIRE_FALSE( ... ) INTERNAL_CATCH_TEST( "CATCH_REQUIRE_FALSE", Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, __VA_ARGS__ ) +#if defined(CATCH_CONFIG_FAST_COMPILE) +#define CATCH_REQUIRE( expr ) INTERNAL_CATCH_TEST_NO_TRY( "CATCH_REQUIRE", Catch::ResultDisposition::Normal, expr ) +#define CATCH_REQUIRE_FALSE( expr ) INTERNAL_CATCH_TEST_NO_TRY( "CATCH_REQUIRE_FALSE", Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, expr ) +#else +#define CATCH_REQUIRE( expr ) INTERNAL_CATCH_TEST( "CATCH_REQUIRE", Catch::ResultDisposition::Normal, expr ) +#define CATCH_REQUIRE_FALSE( expr ) INTERNAL_CATCH_TEST( "CATCH_REQUIRE_FALSE", Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, expr ) +#endif -#define CATCH_REQUIRE_THROWS( ... ) INTERNAL_CATCH_THROWS( "CATCH_REQUIRE_THROWS", Catch::ResultDisposition::Normal, "", __VA_ARGS__ ) +#define CATCH_REQUIRE_THROWS( expr ) INTERNAL_CATCH_THROWS( "CATCH_REQUIRE_THROWS", Catch::ResultDisposition::Normal, "", expr ) #define CATCH_REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "CATCH_REQUIRE_THROWS_AS", exceptionType, Catch::ResultDisposition::Normal, expr ) -#define CATCH_REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "CATCH_REQUIRE_THROWS_WITH", Catch::ResultDisposition::Normal, matcher, expr ) -#if !defined(CATCH_CONFIG_DISABLE_MATCHERS) -#define CATCH_REQUIRE_THROWS_MATCHES( expr, exceptionType, matcher ) INTERNAL_CATCH_THROWS_MATCHES( "CATCH_REQUIRE_THROWS_MATCHES", exceptionType, Catch::ResultDisposition::Normal, matcher, expr ) -#endif// CATCH_CONFIG_DISABLE_MATCHERS -#define CATCH_REQUIRE_NOTHROW( ... ) INTERNAL_CATCH_NO_THROW( "CATCH_REQUIRE_NOTHROW", Catch::ResultDisposition::Normal, __VA_ARGS__ ) +#define CATCH_REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( "CATCH_REQUIRE_THROWS_WITH", Catch::ResultDisposition::Normal, matcher, expr ) +#define CATCH_REQUIRE_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( "CATCH_REQUIRE_NOTHROW", Catch::ResultDisposition::Normal, expr ) -#define CATCH_CHECK( ... ) INTERNAL_CATCH_TEST( "CATCH_CHECK", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) -#define CATCH_CHECK_FALSE( ... ) INTERNAL_CATCH_TEST( "CATCH_CHECK_FALSE", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::FalseTest, __VA_ARGS__ ) -#define CATCH_CHECKED_IF( ... ) INTERNAL_CATCH_IF( "CATCH_CHECKED_IF", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) -#define CATCH_CHECKED_ELSE( ... ) INTERNAL_CATCH_ELSE( "CATCH_CHECKED_ELSE", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) -#define CATCH_CHECK_NOFAIL( ... ) INTERNAL_CATCH_TEST( "CATCH_CHECK_NOFAIL", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, __VA_ARGS__ ) +#define CATCH_CHECK( expr ) INTERNAL_CATCH_TEST( "CATCH_CHECK", Catch::ResultDisposition::ContinueOnFailure, expr ) +#define CATCH_CHECK_FALSE( expr ) INTERNAL_CATCH_TEST( "CATCH_CHECK_FALSE", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::FalseTest, expr ) +#define CATCH_CHECKED_IF( expr ) INTERNAL_CATCH_IF( "CATCH_CHECKED_IF", Catch::ResultDisposition::ContinueOnFailure, expr ) +#define CATCH_CHECKED_ELSE( expr ) INTERNAL_CATCH_ELSE( "CATCH_CHECKED_ELSE", Catch::ResultDisposition::ContinueOnFailure, expr ) +#define CATCH_CHECK_NOFAIL( expr ) INTERNAL_CATCH_TEST( "CATCH_CHECK_NOFAIL", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, expr ) -#define CATCH_CHECK_THROWS( ... ) INTERNAL_CATCH_THROWS( "CATCH_CHECK_THROWS", Catch::ResultDisposition::ContinueOnFailure, "", __VA_ARGS__ ) +#define CATCH_CHECK_THROWS( expr ) INTERNAL_CATCH_THROWS( "CATCH_CHECK_THROWS", Catch::ResultDisposition::ContinueOnFailure, "", expr ) #define CATCH_CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "CATCH_CHECK_THROWS_AS", exceptionType, Catch::ResultDisposition::ContinueOnFailure, expr ) -#define CATCH_CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "CATCH_CHECK_THROWS_WITH", Catch::ResultDisposition::ContinueOnFailure, matcher, expr ) -#if !defined(CATCH_CONFIG_DISABLE_MATCHERS) -#define CATCH_CHECK_THROWS_MATCHES( expr, exceptionType, matcher ) INTERNAL_CATCH_THROWS_MATCHES( "CATCH_CHECK_THROWS_MATCHES", exceptionType, Catch::ResultDisposition::ContinueOnFailure, matcher, expr ) -#endif // CATCH_CONFIG_DISABLE_MATCHERS -#define CATCH_CHECK_NOTHROW( ... ) INTERNAL_CATCH_NO_THROW( "CATCH_CHECK_NOTHROW", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) +#define CATCH_CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( "CATCH_CHECK_THROWS_WITH", Catch::ResultDisposition::ContinueOnFailure, matcher, expr ) +#define CATCH_CHECK_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( "CATCH_CHECK_NOTHROW", Catch::ResultDisposition::ContinueOnFailure, expr ) -#if !defined(CATCH_CONFIG_DISABLE_MATCHERS) #define CATCH_CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "CATCH_CHECK_THAT", matcher, Catch::ResultDisposition::ContinueOnFailure, arg ) +#if defined(CATCH_CONFIG_FAST_COMPILE) +#define CATCH_REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT_NO_TRY( "CATCH_REQUIRE_THAT", matcher, Catch::ResultDisposition::Normal, arg ) +#else #define CATCH_REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "CATCH_REQUIRE_THAT", matcher, Catch::ResultDisposition::Normal, arg ) -#endif // CATCH_CONFIG_DISABLE_MATCHERS +#endif #define CATCH_INFO( msg ) INTERNAL_CATCH_INFO( "CATCH_INFO", msg ) #define CATCH_WARN( msg ) INTERNAL_CATCH_MSG( "CATCH_WARN", Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, msg ) -#define CATCH_CAPTURE( msg ) INTERNAL_CATCH_INFO( "CATCH_CAPTURE", #msg " := " << ::Catch::Detail::stringify(msg) ) +#define CATCH_SCOPED_INFO( msg ) INTERNAL_CATCH_INFO( "CATCH_INFO", msg ) +#define CATCH_CAPTURE( msg ) INTERNAL_CATCH_INFO( "CATCH_CAPTURE", #msg " := " << Catch::toString(msg) ) +#define CATCH_SCOPED_CAPTURE( msg ) INTERNAL_CATCH_INFO( "CATCH_CAPTURE", #msg " := " << Catch::toString(msg) ) -#define CATCH_TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ ) -#define CATCH_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ ) -#define CATCH_METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ ) -#define CATCH_REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ ) -#define CATCH_SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ ) -#define CATCH_FAIL( ... ) INTERNAL_CATCH_MSG( "CATCH_FAIL", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, __VA_ARGS__ ) -#define CATCH_FAIL_CHECK( ... ) INTERNAL_CATCH_MSG( "CATCH_FAIL_CHECK", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) -#define CATCH_SUCCEED( ... ) INTERNAL_CATCH_MSG( "CATCH_SUCCEED", Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) +#ifdef CATCH_CONFIG_VARIADIC_MACROS + #define CATCH_TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ ) + #define CATCH_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ ) + #define CATCH_METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ ) + #define CATCH_REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ ) + #define CATCH_SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ ) + #define CATCH_FAIL( ... ) INTERNAL_CATCH_MSG( "CATCH_FAIL", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, __VA_ARGS__ ) + #define CATCH_FAIL_CHECK( ... ) INTERNAL_CATCH_MSG( "CATCH_FAIL_CHECK", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) + #define CATCH_SUCCEED( ... ) INTERNAL_CATCH_MSG( "CATCH_SUCCEED", Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) +#else + #define CATCH_TEST_CASE( name, description ) INTERNAL_CATCH_TESTCASE( name, description ) + #define CATCH_TEST_CASE_METHOD( className, name, description ) INTERNAL_CATCH_TEST_CASE_METHOD( className, name, description ) + #define CATCH_METHOD_AS_TEST_CASE( method, name, description ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, name, description ) + #define CATCH_REGISTER_TEST_CASE( function, name, description ) INTERNAL_CATCH_REGISTER_TESTCASE( function, name, description ) + #define CATCH_SECTION( name, description ) INTERNAL_CATCH_SECTION( name, description ) + #define CATCH_FAIL( msg ) INTERNAL_CATCH_MSG( "CATCH_FAIL", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, msg ) + #define CATCH_FAIL_CHECK( msg ) INTERNAL_CATCH_MSG( "CATCH_FAIL_CHECK", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::ContinueOnFailure, msg ) + #define CATCH_SUCCEED( msg ) INTERNAL_CATCH_MSG( "CATCH_SUCCEED", Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, msg ) +#endif +#define CATCH_ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE( "", "" ) -#define CATCH_ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE() +#define CATCH_REGISTER_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType ) +#define CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) + +#define CATCH_GENERATE( expr) INTERNAL_CATCH_GENERATE( expr ) // "BDD-style" convenience wrappers +#ifdef CATCH_CONFIG_VARIADIC_MACROS #define CATCH_SCENARIO( ... ) CATCH_TEST_CASE( "Scenario: " __VA_ARGS__ ) #define CATCH_SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ ) -#define CATCH_GIVEN( desc ) CATCH_SECTION( std::string( "Given: ") + desc ) -#define CATCH_WHEN( desc ) CATCH_SECTION( std::string( " When: ") + desc ) -#define CATCH_AND_WHEN( desc ) CATCH_SECTION( std::string( " And: ") + desc ) -#define CATCH_THEN( desc ) CATCH_SECTION( std::string( " Then: ") + desc ) -#define CATCH_AND_THEN( desc ) CATCH_SECTION( std::string( " And: ") + desc ) +#else +#define CATCH_SCENARIO( name, tags ) CATCH_TEST_CASE( "Scenario: " name, tags ) +#define CATCH_SCENARIO_METHOD( className, name, tags ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " name, tags ) +#endif +#define CATCH_GIVEN( desc ) CATCH_SECTION( std::string( "Given: ") + desc, "" ) +#define CATCH_WHEN( desc ) CATCH_SECTION( std::string( " When: ") + desc, "" ) +#define CATCH_AND_WHEN( desc ) CATCH_SECTION( std::string( " And: ") + desc, "" ) +#define CATCH_THEN( desc ) CATCH_SECTION( std::string( " Then: ") + desc, "" ) +#define CATCH_AND_THEN( desc ) CATCH_SECTION( std::string( " And: ") + desc, "" ) // If CATCH_CONFIG_PREFIX_ALL is not defined then the CATCH_ prefix is not required #else -#define REQUIRE( ... ) INTERNAL_CATCH_TEST( "REQUIRE", Catch::ResultDisposition::Normal, __VA_ARGS__ ) -#define REQUIRE_FALSE( ... ) INTERNAL_CATCH_TEST( "REQUIRE_FALSE", Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, __VA_ARGS__ ) +#if defined(CATCH_CONFIG_FAST_COMPILE) +#define REQUIRE( expr ) INTERNAL_CATCH_TEST_NO_TRY( "REQUIRE", Catch::ResultDisposition::Normal, expr ) +#define REQUIRE_FALSE( expr ) INTERNAL_CATCH_TEST_NO_TRY( "REQUIRE_FALSE", Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, expr ) -#define REQUIRE_THROWS( ... ) INTERNAL_CATCH_THROWS( "REQUIRE_THROWS", Catch::ResultDisposition::Normal, __VA_ARGS__ ) +#else +#define REQUIRE( expr ) INTERNAL_CATCH_TEST( "REQUIRE", Catch::ResultDisposition::Normal, expr ) +#define REQUIRE_FALSE( expr ) INTERNAL_CATCH_TEST( "REQUIRE_FALSE", Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, expr ) +#endif + +#define REQUIRE_THROWS( expr ) INTERNAL_CATCH_THROWS( "REQUIRE_THROWS", Catch::ResultDisposition::Normal, "", expr ) #define REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "REQUIRE_THROWS_AS", exceptionType, Catch::ResultDisposition::Normal, expr ) -#define REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "REQUIRE_THROWS_WITH", Catch::ResultDisposition::Normal, matcher, expr ) -#if !defined(CATCH_CONFIG_DISABLE_MATCHERS) -#define REQUIRE_THROWS_MATCHES( expr, exceptionType, matcher ) INTERNAL_CATCH_THROWS_MATCHES( "REQUIRE_THROWS_MATCHES", exceptionType, Catch::ResultDisposition::Normal, matcher, expr ) -#endif // CATCH_CONFIG_DISABLE_MATCHERS -#define REQUIRE_NOTHROW( ... ) INTERNAL_CATCH_NO_THROW( "REQUIRE_NOTHROW", Catch::ResultDisposition::Normal, __VA_ARGS__ ) +#define REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( "REQUIRE_THROWS_WITH", Catch::ResultDisposition::Normal, matcher, expr ) +#define REQUIRE_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( "REQUIRE_NOTHROW", Catch::ResultDisposition::Normal, expr ) -#define CHECK( ... ) INTERNAL_CATCH_TEST( "CHECK", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) -#define CHECK_FALSE( ... ) INTERNAL_CATCH_TEST( "CHECK_FALSE", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::FalseTest, __VA_ARGS__ ) -#define CHECKED_IF( ... ) INTERNAL_CATCH_IF( "CHECKED_IF", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) -#define CHECKED_ELSE( ... ) INTERNAL_CATCH_ELSE( "CHECKED_ELSE", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) -#define CHECK_NOFAIL( ... ) INTERNAL_CATCH_TEST( "CHECK_NOFAIL", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, __VA_ARGS__ ) +#define CHECK( expr ) INTERNAL_CATCH_TEST( "CHECK", Catch::ResultDisposition::ContinueOnFailure, expr ) +#define CHECK_FALSE( expr ) INTERNAL_CATCH_TEST( "CHECK_FALSE", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::FalseTest, expr ) +#define CHECKED_IF( expr ) INTERNAL_CATCH_IF( "CHECKED_IF", Catch::ResultDisposition::ContinueOnFailure, expr ) +#define CHECKED_ELSE( expr ) INTERNAL_CATCH_ELSE( "CHECKED_ELSE", Catch::ResultDisposition::ContinueOnFailure, expr ) +#define CHECK_NOFAIL( expr ) INTERNAL_CATCH_TEST( "CHECK_NOFAIL", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, expr ) -#define CHECK_THROWS( ... ) INTERNAL_CATCH_THROWS( "CHECK_THROWS", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) +#define CHECK_THROWS( expr ) INTERNAL_CATCH_THROWS( "CHECK_THROWS", Catch::ResultDisposition::ContinueOnFailure, "", expr ) #define CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "CHECK_THROWS_AS", exceptionType, Catch::ResultDisposition::ContinueOnFailure, expr ) -#define CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "CHECK_THROWS_WITH", Catch::ResultDisposition::ContinueOnFailure, matcher, expr ) -#if !defined(CATCH_CONFIG_DISABLE_MATCHERS) -#define CHECK_THROWS_MATCHES( expr, exceptionType, matcher ) INTERNAL_CATCH_THROWS_MATCHES( "CHECK_THROWS_MATCHES", exceptionType, Catch::ResultDisposition::ContinueOnFailure, matcher, expr ) -#endif // CATCH_CONFIG_DISABLE_MATCHERS -#define CHECK_NOTHROW( ... ) INTERNAL_CATCH_NO_THROW( "CHECK_NOTHROW", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) +#define CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( "CHECK_THROWS_WITH", Catch::ResultDisposition::ContinueOnFailure, matcher, expr ) +#define CHECK_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( "CHECK_NOTHROW", Catch::ResultDisposition::ContinueOnFailure, expr ) -#if !defined(CATCH_CONFIG_DISABLE_MATCHERS) #define CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "CHECK_THAT", matcher, Catch::ResultDisposition::ContinueOnFailure, arg ) +#if defined(CATCH_CONFIG_FAST_COMPILE) +#define REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT_NO_TRY( "REQUIRE_THAT", matcher, Catch::ResultDisposition::Normal, arg ) +#else #define REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "REQUIRE_THAT", matcher, Catch::ResultDisposition::Normal, arg ) -#endif // CATCH_CONFIG_DISABLE_MATCHERS +#endif #define INFO( msg ) INTERNAL_CATCH_INFO( "INFO", msg ) #define WARN( msg ) INTERNAL_CATCH_MSG( "WARN", Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, msg ) -#define CAPTURE( msg ) INTERNAL_CATCH_INFO( "CAPTURE", #msg " := " << ::Catch::Detail::stringify(msg) ) +#define SCOPED_INFO( msg ) INTERNAL_CATCH_INFO( "INFO", msg ) +#define CAPTURE( msg ) INTERNAL_CATCH_INFO( "CAPTURE", #msg " := " << Catch::toString(msg) ) +#define SCOPED_CAPTURE( msg ) INTERNAL_CATCH_INFO( "CAPTURE", #msg " := " << Catch::toString(msg) ) +#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__ ) @@ -11849,152 +11563,46 @@ int main (int argc, char * const argv[]) { #define FAIL( ... ) INTERNAL_CATCH_MSG( "FAIL", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, __VA_ARGS__ ) #define FAIL_CHECK( ... ) INTERNAL_CATCH_MSG( "FAIL_CHECK", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) #define SUCCEED( ... ) INTERNAL_CATCH_MSG( "SUCCEED", Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) -#define ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE() +#else +#define TEST_CASE( name, description ) INTERNAL_CATCH_TESTCASE( name, description ) + #define TEST_CASE_METHOD( className, name, description ) INTERNAL_CATCH_TEST_CASE_METHOD( className, name, description ) + #define METHOD_AS_TEST_CASE( method, name, description ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, name, description ) + #define REGISTER_TEST_CASE( method, name, description ) INTERNAL_CATCH_REGISTER_TESTCASE( method, name, description ) + #define SECTION( name, description ) INTERNAL_CATCH_SECTION( name, description ) + #define FAIL( msg ) INTERNAL_CATCH_MSG( "FAIL", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, msg ) + #define FAIL_CHECK( msg ) INTERNAL_CATCH_MSG( "FAIL_CHECK", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::ContinueOnFailure, msg ) + #define SUCCEED( msg ) INTERNAL_CATCH_MSG( "SUCCEED", Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, msg ) +#endif +#define ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE( "", "" ) + +#define REGISTER_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType ) +#define REGISTER_LEGACY_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) + +#define GENERATE( expr) INTERNAL_CATCH_GENERATE( expr ) #endif #define CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) // "BDD-style" convenience wrappers +#ifdef CATCH_CONFIG_VARIADIC_MACROS #define SCENARIO( ... ) TEST_CASE( "Scenario: " __VA_ARGS__ ) #define SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ ) - -#define GIVEN( desc ) SECTION( std::string(" Given: ") + desc ) -#define WHEN( desc ) SECTION( std::string(" When: ") + desc ) -#define AND_WHEN( desc ) SECTION( std::string("And when: ") + desc ) -#define THEN( desc ) SECTION( std::string(" Then: ") + desc ) -#define AND_THEN( desc ) SECTION( std::string(" And: ") + desc ) +#else +#define SCENARIO( name, tags ) TEST_CASE( "Scenario: " name, tags ) +#define SCENARIO_METHOD( className, name, tags ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " name, tags ) +#endif +#define GIVEN( desc ) SECTION( std::string(" Given: ") + desc, "" ) +#define WHEN( desc ) SECTION( std::string(" When: ") + desc, "" ) +#define AND_WHEN( desc ) SECTION( std::string("And when: ") + desc, "" ) +#define THEN( desc ) SECTION( std::string(" Then: ") + desc, "" ) +#define AND_THEN( desc ) SECTION( std::string(" And: ") + desc, "" ) using Catch::Detail::Approx; -#else -////// -// If this config identifier is defined then all CATCH macros are prefixed with CATCH_ -#ifdef CATCH_CONFIG_PREFIX_ALL - -#define CATCH_REQUIRE( ... ) (void)(0) -#define CATCH_REQUIRE_FALSE( ... ) (void)(0) - -#define CATCH_REQUIRE_THROWS( ... ) (void)(0) -#define CATCH_REQUIRE_THROWS_AS( expr, exceptionType ) (void)(0) -#define CATCH_REQUIRE_THROWS_WITH( expr, matcher ) (void)(0) -#if !defined(CATCH_CONFIG_DISABLE_MATCHERS) -#define CATCH_REQUIRE_THROWS_MATCHES( expr, exceptionType, matcher ) (void)(0) -#endif// CATCH_CONFIG_DISABLE_MATCHERS -#define CATCH_REQUIRE_NOTHROW( ... ) (void)(0) - -#define CATCH_CHECK( ... ) (void)(0) -#define CATCH_CHECK_FALSE( ... ) (void)(0) -#define CATCH_CHECKED_IF( ... ) if (__VA_ARGS__) -#define CATCH_CHECKED_ELSE( ... ) if (!(__VA_ARGS__)) -#define CATCH_CHECK_NOFAIL( ... ) (void)(0) - -#define CATCH_CHECK_THROWS( ... ) (void)(0) -#define CATCH_CHECK_THROWS_AS( expr, exceptionType ) (void)(0) -#define CATCH_CHECK_THROWS_WITH( expr, matcher ) (void)(0) -#if !defined(CATCH_CONFIG_DISABLE_MATCHERS) -#define CATCH_CHECK_THROWS_MATCHES( expr, exceptionType, matcher ) (void)(0) -#endif // CATCH_CONFIG_DISABLE_MATCHERS -#define CATCH_CHECK_NOTHROW( ... ) (void)(0) - -#if !defined(CATCH_CONFIG_DISABLE_MATCHERS) -#define CATCH_CHECK_THAT( arg, matcher ) (void)(0) - -#define CATCH_REQUIRE_THAT( arg, matcher ) (void)(0) -#endif // CATCH_CONFIG_DISABLE_MATCHERS - -#define CATCH_INFO( msg ) (void)(0) -#define CATCH_WARN( msg ) (void)(0) -#define CATCH_CAPTURE( msg ) (void)(0) - -#define CATCH_TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )) -#define CATCH_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )) -#define CATCH_METHOD_AS_TEST_CASE( method, ... ) -#define CATCH_REGISTER_TEST_CASE( Function, ... ) (void)(0) -#define CATCH_SECTION( ... ) -#define CATCH_FAIL( ... ) (void)(0) -#define CATCH_FAIL_CHECK( ... ) (void)(0) -#define CATCH_SUCCEED( ... ) (void)(0) - -#define CATCH_ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )) - -// "BDD-style" convenience wrappers -#define CATCH_SCENARIO( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )) -#define CATCH_SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_METHOD_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), className ) -#define CATCH_GIVEN( desc ) -#define CATCH_WHEN( desc ) -#define CATCH_AND_WHEN( desc ) -#define CATCH_THEN( desc ) -#define CATCH_AND_THEN( desc ) - -// If CATCH_CONFIG_PREFIX_ALL is not defined then the CATCH_ prefix is not required -#else - -#define REQUIRE( ... ) (void)(0) -#define REQUIRE_FALSE( ... ) (void)(0) - -#define REQUIRE_THROWS( ... ) (void)(0) -#define REQUIRE_THROWS_AS( expr, exceptionType ) (void)(0) -#define REQUIRE_THROWS_WITH( expr, matcher ) (void)(0) -#if !defined(CATCH_CONFIG_DISABLE_MATCHERS) -#define REQUIRE_THROWS_MATCHES( expr, exceptionType, matcher ) (void)(0) -#endif // CATCH_CONFIG_DISABLE_MATCHERS -#define REQUIRE_NOTHROW( ... ) (void)(0) - -#define CHECK( ... ) (void)(0) -#define CHECK_FALSE( ... ) (void)(0) -#define CHECKED_IF( ... ) if (__VA_ARGS__) -#define CHECKED_ELSE( ... ) if (!(__VA_ARGS__)) -#define CHECK_NOFAIL( ... ) (void)(0) - -#define CHECK_THROWS( ... ) (void)(0) -#define CHECK_THROWS_AS( expr, exceptionType ) (void)(0) -#define CHECK_THROWS_WITH( expr, matcher ) (void)(0) -#if !defined(CATCH_CONFIG_DISABLE_MATCHERS) -#define CHECK_THROWS_MATCHES( expr, exceptionType, matcher ) (void)(0) -#endif // CATCH_CONFIG_DISABLE_MATCHERS -#define CHECK_NOTHROW( ... ) (void)(0) - -#if !defined(CATCH_CONFIG_DISABLE_MATCHERS) -#define CHECK_THAT( arg, matcher ) (void)(0) - -#define REQUIRE_THAT( arg, matcher ) (void)(0) -#endif // CATCH_CONFIG_DISABLE_MATCHERS - -#define INFO( msg ) (void)(0) -#define WARN( msg ) (void)(0) -#define CAPTURE( msg ) (void)(0) - -#define TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )) -#define TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )) -#define METHOD_AS_TEST_CASE( method, ... ) -#define REGISTER_TEST_CASE( Function, ... ) (void)(0) -#define SECTION( ... ) -#define FAIL( ... ) (void)(0) -#define FAIL_CHECK( ... ) (void)(0) -#define SUCCEED( ... ) (void)(0) -#define ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )) - -#endif - -#define CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION_NO_REG( INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator ), signature ) - -// "BDD-style" convenience wrappers -#define SCENARIO( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ) ) -#define SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_METHOD_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), className ) - -#define GIVEN( desc ) -#define WHEN( desc ) -#define AND_WHEN( desc ) -#define THEN( desc ) -#define AND_THEN( desc ) - -using Catch::Detail::Approx; - -#endif - -// start catch_reenable_warnings.h +// #included from: internal/catch_reenable_warnings.h +#define TWOBLUECUBES_CATCH_REENABLE_WARNINGS_H_INCLUDED #ifdef __clang__ # ifdef __ICC // icpc defines the __clang__ macro @@ -12006,7 +11614,5 @@ using Catch::Detail::Approx; # pragma GCC diagnostic pop #endif -// end catch_reenable_warnings.h -// end catch.hpp #endif // TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED From 261caec2de8cbec09829fadd3a5d6e38919b18e4 Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Thu, 14 Dec 2017 22:29:39 +0100 Subject: [PATCH 6/6] :busts_in_silhouette: added contributor image --- README.md | 2 ++ doc/avatars.png | Bin 0 -> 543063 bytes 2 files changed, 2 insertions(+) create mode 100644 doc/avatars.png diff --git a/README.md b/README.md index 7b50c8412..e6a686264 100644 --- a/README.md +++ b/README.md @@ -820,6 +820,8 @@ Only if your request would contain confidential information, please [send me an I deeply appreciate the help of the following people. +![Contributors](https://raw.githubusercontent.com/nlohmann/json/develop/doc/avatars.png) + - [Teemperor](https://github.com/Teemperor) implemented CMake support and lcov integration, realized escape and Unicode handling in the string parser, and fixed the JSON serialization. - [elliotgoodrich](https://github.com/elliotgoodrich) fixed an issue with double deletion in the iterator classes. - [kirkshoop](https://github.com/kirkshoop) made the iterators of the class composable to other libraries. diff --git a/doc/avatars.png b/doc/avatars.png new file mode 100644 index 0000000000000000000000000000000000000000..b416a2854c9485ea1afa5204e8599075d1595bb6 GIT binary patch literal 543063 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ðwtxoJ9(bh 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

!DFFc3mJlEOEBgN|>!i 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�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 z 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 Ef`X8P!2kdN literal 0 HcmV?d00001

zbIc-C9QpDm)-QW4Qz*S# zZcXRIf~T)sk5(nnPGgEWzIm9Ku&-V8eK;!3o-9d+0(nZNn9j)Ffq}41+y=I*Sh~YC z!k{m}p%JJHz4GxfO%Xr>&(N$F{9{9`}F$b$bO}EIg_3XHcDOEhyYwr z?6+S+AK)w1+BPV(%;_<0molGr{x)vj7K!--(DL(*uIia8xovxS){|$v!`hs#&UwYl zV9qX+M8VvgjSccz#;H#R29-)ni3e?s{8+<@ zQP7-8J$Iw^t441XiU#f=n!N=^!E zp%83oi5;=LDFF!z*^f{Za3~`%%7+81HpmN_T}!9cB$G$1hEn;B%naA z)j=$5%X?2WDs0ofN##^8EQ5#$tF=nFCR;6--9HBNEPT|QCiFc7WI*xyEQ z^re6s8XO#A=t|jru~vvUXA*6CnnluKb%Z`e)#o-J6QfFY>2*%7U{IQ*HEz*{az{UCs$@#N0M zQ=gXu*Asp0p8AGg#65=GPK3;=)sm7uRv8%^s+5wX#z4!vDial>6XHV}{>zPyy)>MK zR957=;$awA;%!Zr`>4uWSuteqnBilCXmP$cB&i+!K?KX-a=2SCT}%B^Do=SA4hcg) z?e2VVgM}c7!&wKDNN}JcMKa|CGQkOc8msSoG!Dv~{X~80T(?rgJ5!OFxgH{4AkuKDgUbWqWb2$rt(QH_a8KV@j&4;-A_28W7Dkq@FmI$1)Y2Bq*G z@pm4?J$g8(bW}FyOPDvQ64e@JuCz4H*j8n~fk=TZ%`iBHWO(e+_nF+!W7R9nIreg< zAKYU>lGK9QX@nUF)fr(H{Y)cEIwhqauQJT|rt<4TIdq>B!<4Yf>8@8tKlNns+^Qv>6l~x15^OGMU z&Xjm)la{77pk9x=Y z|IjOsIKAfhX<2PDN`v}S2cN8QD*d8+?ileyU39MF%o!0OVXoIsG!#l7$N&I`yP<9F zqUq`nu|9dpd)#NOJHK0V=N`lES}xp_br(G_p1dS}j|4tH`NqL@eka!qqV0FUc%N39 z>4;1oq+h?2mVn_p%7LH5%_zCoOVaVimAQ^?ibSnWk|CNcpN=oAeW1ZuE`ul&MU{gl z-;yO50W>Ziv{9RfO%MVmgtv_%af#3|AqJ%ceZdHxZ*6&*VNHL>g5-0Q_baH9IJ3w}Gc|?A8XLQTmBvkk^x!`U|M0B+{m#iOVWQGvO415_PBK2! z##4{FEnIvO8^U2#EeM+)GKk?qoS;`FkJz1Du`>#woBaAA63c?1%WRrDd7tw6x6zZ6 z*foOZhWq05OS*g$bFkm*t$(2K+rU?>mxc~!_qy5d-@ga!k{P}dQFd8*Tima;vp)Vi zAHCcd&~ytpy6nOdt?R7gnIj>RKI}UxRTc@j-wF;N26`XYKW?~h1OG^TvMD?V$IA8WFO<>#qp z$8rkM;Uh#HN&FJFF)k7e zhW{=~+vU5Zj-C7aC2X_=jc)43X%+#@|D1lAxkvqW;i9xYL^RZ{G04ow0DRfGH@IQc zG*7=CyI=Xkp2A=MF}_|RcQcj?$cXsu#>rxRt63HGE*GwfEbQSU%{m=9U#_=o<`r~% zIPNl={2?jgZ2Y>wnhqeXJBSDmLd993@f5!19v=EdYVXEp#{v39h1jWY+sLDW_s>e$ zN^6+msn4LrKX>zO+TO2HrLk^B=J;;X*2^b1whN>nD%09UJ6>TEVg=wHd3^6?wOiNF z)R1F-l-M5$=fZLPsZfEpf=<4nrG)`{>hTDiMOazKi)Q4Q>7hI@mR>5zjxBG^08{b$ zeCg>@%kFi1qvBUZ1qFQ3Q^K$mg^@Ve0XccAX-m)3GC+LI`XQssB#O&OQ1ERvzGNMGf7_-?SV{}qCn^e;GEHKzMVggG zK`H}$T!V%k>{AW~USm?-hs0uxpIoypP!>sMcyd7vY*y;1C92SAb4w5iB?yFS!IaXZ zMJm!{_jK9!XU8`1MAClgmC8WiexR^h_V+=8FN zd(*dvG9mm{)k=oiz1ff!9$s7q%uq^jVDtLx=lhfN=|!@*h6y9@tLj?sv-RiZ{Wins ziW?EuDwn9JJy1~Z{=QGO+MRk!aCxzvlMX|46)niWs%m+BL_U$(S5~LS*RCwU|H)Ey zn{$Te%!(WQmW?_kzt7KD{x_rcBT9HM-AcZhsN&WQ0foQ!3M;&TWfFW|dU$&{!9CK6 zn;eqr3!o6qY?w|mB2hfWG+cxEM+kUte{D2jd_V;uBuW?k@0N8X++DqR;%#>> zeD1Yu6tGv+WmpTCI$|YkyX-t3_6FNMtR_iHQD8Q56G|wTUv7`b=Q-x`TBuapP2jPBz5GuB0 z!7b!sPM=m9>fqq9-~1EyH0t55v5q-Wt1cwhIXsQN`nU50T__-N68B8u{czKOaAPT5 zg?ZWzy{4$8=sD!BS;b> z&B|$|EL837G54Pg?LL=l#uWZJpM9a@;O3T=0=($JVn3oZPxNJk7E9&hNAE5mi~Hv; zVG{*-<8v|uHemM$E5P+imJApf0O3YAM{n=U%s9?e1q%TFCanha&wyp3sAzXvTN`lA zx{7;vewmn<0Qze{N5==yN&^T+p6tm`WGt?$|G`HMbadKY9!~l>ss>U!M`ViBvf;@30Gc%A^mIKI3TeEu3EkA43i^Z_O zvOWuryl-8GL6Iq#4j>4QiXUNS?pQY#Zk{TL5<=a_HT+K!JrOy?L{L1e?#PT^t~&zQ zdN&cL2@Rs&X(3-}p=D8^BqsSBN@5ReXg6m`IgQ{>szcTt2q$4-*=6arFXBkF(jbQU z=1lP*AGuRph4Va-HW%|d`B|)sx(c?|dy4WQy_SPZ13d~`jA#{5CJqZN9{LV`6%K`$IHCZatx@wQ@{{i_4>=-8r{rvQM8 zb|8&$l56lh)$F1hp`J18lkI(Q5FSAYj1dzE`Bsg%F{D?Do6-`r%gQ2Z z#|BB8vy#63%gJ%@zi@S6T(@{+(CqFn%~w3mt|me|l^^{>vq3&U>XGDFTe3uN76>ag=Z&tsf`nw7{rGXt zyhY!Vm~S}B1~M@*B8-q>5{oCoMgIF&-zYdbHO7~z=j3KVl)h3YA)w1I?g}{{|21@3``kJ)fpm@adDWdc^se(%zX$|6I!TKd4>k) zGmMP={HS1`9zK67E2@CzA2ou~gU#$uG;;@_l1#03Pi5&wKQfgrH3X-8QWjK>TnrQl64O%T4U*5Lt`i7!`$sn*xBZ=6DlKlv)VusEEoC#Q zLN(_2dD_V=SYxGJ_pUsLnP2!r%P+K8J7}dXCmG7HtPUM%WDKYR!yt==FW$!toyQs% z_N6~a0WB?7#SGtVlal6rqEyf?d6N*~>3GU*__trRe>pyledLj^q6y*RxN5}fV9HZg zX7wLD|3UR8>Mzkx(oAOm&k7^*pUIZ$oZXzPta^{*D4Wl=c;o1vc}4GH5)?(xXPWe; zMXC*h-QQ%3u$UW|^g1{1cosEqP8>OY$Y7pvFo(#{`Tckf}87Bmk0Vc8Hv84%O)xWj6s1?ug*T#1-h#L(;AmV5^eGK88)$i(=ag->n6Rph_ zf_@VsB1hIGa#MmJAlvB-lDgVia-CKWS7T#ZnP|)m=e)-cClCHWk|QQ2W=5;+j@YpI zv5$z82qQNZ@OzG4@I@3)@0)S$-#lm?s26jKh#Vs=0`U5NNw3i>=261Cs|uibs}pl7==g_KKp=Gi6orF^k3 zkwp2(I(ps#NG{5zEw7jpMr;;aIYSOgtAkb(g_u`j_`Y+dMJ44hsK}!G$`*2(jtHG~ zzX`f+oNWQv2>@lz*_Uhh+~aw1z%{1T!z9DdibBMrYCe|pP*C<*KbWW(L4NFu8 z^falpfD59YOF0n9akXWm6+J(IcY4@gX{VcN9aJ)aGG|Y?i7|Il@fS2j?AJE|HVA3l zvW*OeqR^93{v?oM6oE+ef^ zC=L~CkLc6FK}=eNU0X}p_D^uhM3>{aA3{5ND&{!c^Mcwqo_=G4($m?H?`7jWQI9(Q zDqQwGT!WCPP_wFp%4UD#s++vhhyy3unwWP`3EIAG)A0zj7f@=?EJaF*npmpOFipw4_wGxY?C3?Cu;GOxC~4_HAclp9Tae zU?UYeXBB2dv5_#AaMCD95YrshF19tfkwkn@C4NJcJ~2V0ss(xvLA>Vg9+eIorLjjh zx>txU*W^~DYi$E$>vbUtzrW1!xlIy!?`jd5Bl%G;L~`NYwX}y4cn~fFQLARAsZUV& zdcox0t>%7IE+x3u?FksNi#Tl!#4*E%`(6z4RL<5_GYUC~Fw`|PfIrMfQPGu?n>dx$ zmWIa0M$ZSQx_4XW#$B3T<_$gal=zRZT`Wx=+LUuzMCsGVH;*e9x3ce~NjAI@d+<3e z$vif5yq{+3JYrVFQXP&Yp8(JJ!=b5&!$lNHrH~ZV@@Q)6HVIurUehK`7KbCGxXVie zyrOs?Vs<>smy67(DeYY)3xyz8LIW_6+r`lg_DYyB-$F1_zL7E_$3UPPTy}d_7Ra1P zf{+$=mWUzAG65X6%TANxMne^v2Grcj9-~*8n+)A<`at3_!4dzl_eSrfpY0neqN*$n ztsstnl;zCkfvpAGjSR?TV?!wzlC8vo%d)7IE8vR)G7N)q)g<4}^=|G>eg@Nt=jFbg z<&zq@dtgQA1L@8m@l0O6fAdC%@zXZ2v^!dA_+lfDm+qXn)1YW{X|QXlJuDt{b@kH{ z79E}F;Io+81OQ$>w4FQ@X$exJ%!y|;BceN3=^+B}r z1oD}=(E%z<810L=NbM*RT@;N;NGNhP_U86NKkrm^GzrOrs0eqbTjG@k=zvEjIp@On z%QXN9+-T#F)6H-Nf;O~Ba9{{%c1Ar0E*qUMXBv^x!SwsTK9{8Z$AJyVfh=iH1(x{u zz$9|6T~L@G&LhHHq+yRqOM1f0d^0Pws|x@)yC#J zdwl|kz1a+$Fh9tiq=Ff))pE=;%7w}$5MVZ`a$RlreK>9^n=~iq|G}j&36M9uZo9lC zp}_tJz`bJn>04QqEFJ-T4!4j=VBxmCvjb2wgsX-oGaqvS%{hPwB*Q?d(Hd@|a_<75 zGOM#^g9&WTP0RG@E(SniNhj<7G-q9db#S+X{up}8n&dwVixq~y^AmwWg~7mtBNs6h z8e(y5;|?eGOUH?~vej_sxo4AWkSF?E1DB}tm7En}ZNLAkUs@Mk z*rLcjwd~%P9isIv*N=7Hqt3@73duFr|Nt#rCV+~bc-0X!QWMjz;ZBR;=NHLjUlFWSl$f3hj+VyNZ1|=KN=5DIt=@Gep-8j31Pxu!M zD^f(Vg!JakIYb=4-;_8!;g&pKFqhC>`fO}C*ofitG&eT-O>CE-7tfdSgv&>7?2VIp z_m>vi=M-?rm;gxsHUkndLJQ@zc=tE@9gP?Xk(|+&=gghLyph*^;eHfJzzC4SL z&d_g}Z)Jp~yMH7vE;L4UlJ&F>uBCFa8A62U4fM^wnGZBG$bxXhqXR9I1cwgiWEgQ@ zWyc~a`?QCn;kAfd`Tg4=VwsY)5ZX7zlEI(E@#GIPxn!lpEeJ81J3O4* zJEN-9&Hm(OpQwlZ%DFHtZQegl>G|99+JAF>p1JAzxUgqhXf&)MhBHQXfHHD<+AE$A z9)R%F5gU~DMQqg;SrT$eSA?-i$}i~^Z+sG7p}TtD+8z4nH~IXE;yUg)DuJD};->c6 zKnjF{*RAUw7@aitktn6a*=gBe#B-c@tO&2?Y<*xF>(6vinjefIlmQD$YJt}oRjrTc zU^hGbWjHAs4Jok3)g5>L_UT9j6C3%&AZeC z>2nfWoWNTEf8FVN==Kh_i8zQVsXwzlnhcCDPV}Qk6Tg##5#@{9jS&t_%GTCA)3ws|mct&Ng97m6&Z#!5`%1~cJTFkhe#deU-9lY!%BsEaur z`W2rhfHMco_7U!VJ<@h}n9%BScsrr>V|{1|Cgs$+zdO>vn$hTX=z4 zLu_o4Mfj-Q_kMu`QgnR-Dn^^?c6{C=vX{rFE?tY#MPbg#$SWV5_7om#ve`Ni4d^uP zCJ_B?y4!vsV4nw)Oe;L+x!bUqX4}sDz{>>&+!gcXMm>+g4K1Gm?@908ge&cJnwL%8 zq08oX=Otg)_)TkJ5lD#CQC!drHknu1tcih0%=di>L^mJ_N^z=GN)v{6809D!xbICq z8Bp@yzEs?-*vC`MdQ!TL6c*{#H#ppEz8k{uL5M;{qy+iNU_}3;)EbYrny+kDFP}9( zs##fxt||7k&Ddgjkg3$bvXrTn?#KH_L+3*S#slHLZr_}nY8y zB<6}1je7Vb9WS=I1M#M`B7v2F^;be5_7HKlO^IAYob|u@azSED0Yr6r5{zbbGCAvY zZ&}M3-h&99!HDHzlyj28uR21%LaX2NaLeJLmHjb2q%f@14uhC(bhLs8Dc#FQHS z(@_O;OXs8Jp5-UFaxpb%Z{-78mWc^|D(c%YeB+bL9d|$$FZke=*AbkiZeF%7LO8<7 z@io?7O{^tJ!}!>x5}tlpOQ0MT_f#ZGSRhp>5tvLjsI13MP@@^A`)xTvcr|&?ul?d|>8cuHhcl2jH>Ni7ilPC9+?r_JGr!K2ILyG6fktXjg08dDU-FBU4n(@;4 z8X&}7N4_TiTkpLRHNo{f&Gzyjw^DolM)bP$s^)4yo$ljo{9DoMU@P;AMT?rz)K($Z zO7~;0s|z+^@9XsoUU>D5@X1}o_EcxZqD|sJt=U@E_8NDXVo)-{SNb-k!hF^F_{T7e zvhx~(y|^*{RW}WU+oeGCH{m=ohC(c}>XmBmxalp%BWGvJ;O;lpZ0V#wMAYqFS6~lZ z{TritUv)>BiVee)4bZsJi8OJDxQMCkmu&Jh*TQ*}bEP(-Kq-751?Kn5IAfR{FwTaZDhP+Dsm8G*Nz?9jdCDSNDGPxZjdA*1QBK9AY{p|$ zzDvX(EV1BLEFS4LIRO*pSFaoF&R62Ud?gui+c)D^DWE`;wNSvo+*ul?v~$A*>^o3MugnLVDj$TT~3Zqn19|zF`6&gdBdX;-I#CS)WP%VHq=Ut0_4g9C$uM*uIWd6?_n*4u-t9)Kv6WZd9TJ8u=T zy1%`kcYh)JNOEHNl;-_ZEPB8F`+8`$DJPq77Ccvv7CVqO9DL0!IDNm>!56w8o;wb5 z1YSgClLCb==3SO}_y49ue@dQ4X+#z@8+YZaeX94F`e!nWii1-Qnf0*?BIh8N6C zS}VvpLuubHIth$h;6bq!%BVr#ZFz{Wesy&`KBgH*<(s4V{Kuu=_?$mHbZ2(>uh%~H z@7}h_&BFPQC}Wtq`%5d5)&{^HLlV)#4@7}xM?#6zH>pQu3WXgm)O1Tq$|TGY;pmwh zD9Ff~IJoS5o5<*bc?^j#H8lc>3b01ptEkmF?8V)|YcRDwmH60>!LDXs%i4A zhe))~YF}w_awDfn<`5Q7d_>Bkq#~hF@bw2Xw5orRvB+g2pw1>IP^|N2`QcW2e%@w`)=Fvy3x-g@CJ{K=Y*?$Iln)vw&;B!}UH zaLe9RO+>VCn@^CKsJn30er9)> zwMNqT&Q|+?=!8|h7RMft>8~Nb&>3+or+dU&^`>mFZRzQsD?JgT%SxcgclLG+g4UIj z_Xbt-xoNoI1M29%<}TI<;Ea?M^f=Mc3*9meH8tr+;y=AlUfx{9uPCN)V)2MmYP0|? z-4St;*V*C&0Y#wG$d-5aZ%@NOA@9ChI;K)RFLsAyy8O{p_kDE5w&$PNn7=+zGY#(7 zYU^FK-aN(sT;$*%N~JTeO2?=w8Mit%AR3SOb2Dp{`!i3Ps>3M&(N`St8q|$AWRNIjG{w$n-i4vC)9>gJtHwD}!R3AT!J})cJaJ!=6HOOVM``NWKO130O7C~bn=QUf-?QYjERx4v0O6waa+TGfy9BLtnQ(HsZCT3@tV4y;{BtVTV*AG%hYt&E; zQi_iY($&^vPUTu0=8O2${fp8+mJ+OD&G~^*O#Fn%r^fUxuQq-!2+yNe+_G#k$zp1w zBtcN)cwRIiyw=K=`M{b|o4Rslk$O~!&jiA;Nbic<-aHUp6jWanBf`gz`o*XvG^aj^ zVat^oka>UKzNn5@krtOQ*dEZ@=}aQ5IEUm03CZPV^Ob%IWFZGhgCHf$9mR(3bZJ&n zJ^|vQ01Li&dV;G3fENx8$w$-l{-MZ7Pk-u@61iXX$NpAt_n(PS>tN+^c%@|a!2SA= zAHc2w=D@wle7&cAjoE`MV8fGZPHb_b&kkmF`YwS=&UodvtVL2;&cnllh->cU^*nEy zp%9%rdm#LDIVo1{2yBHec1Hh;+YJo~0bi0W?C%G>Y+Jy@O<4G8J(TTN;+U}ewPUaU z1ivJrZ}p7F%WKic4DY9>4GteF8fzbE4Hl;ymR7stuv$Vqf4JoVlasCzXoErBz{4oy zSbyv!C6}C0K9-&}I-tE3oNeSl}9Pdj6*G(3*2H8@V z@%f>GPaMA@ciQ-0@~GiNQG!+=)F?7O&~C9vGE_wH0CSoG0ws2b;c;V-ADb>W_$v{6 z>^JZfenpv(i>U{!=rkj&%q0N!6+g*G1TV`}3gG-vQzK*dWlvpC7{eTpchel=qypRh z)B+JRrTf%rj@)(@wg=q2YeY#+@{Hn`naGXr*qQ4|ZJ9mB`ROIHI`7_6+BKL-4IqKa zhpQ+FX5Pch>Sld{K#N|5t!m7Y!g1XTGOe|^?~6QA>Fzf#s*t&EL*st(lG4)Y8-A4Z_{a@L?=v+pcg69vo+R z3g}erAcY_J{MwUgkXddR3Xm~#huxB=!st$7FJ`LVNRGypBbO+Ro38n6;VVC!sz0*k7M$vfF=@ zOeexV301Jqyp5*gMt2*F^)y@0)ihgg zg_#wVu%1Zz9fDG)(3%dj?N#~yPh@Yjj#?NmD7JMu?RH+O8l74=IMCK`&k5{0;`22zR6Ibt0=U^r zZiXthh*bMV+s7Lz`6K9&!PKe)UvbaLL;4LbO5()I#JCs2pZovi{ZsQ%VH#x_TBP9y zO$o?iq#j(oy*@tCX*{g-(v@(kQ$2!wY#J&l|DyNpn+G6l79{`U?`y{w*@e~qUeL=C z7@&t_>nt&lZurkHvyyO;jw2azU3%l%|1WiH*{kDt#^8pzBc6$i>-!FQ)WMH0PHkY2 ziffqDUkWsW?1#7%rDs|YbNL7qE~EbL zu3zq+v|V0nVe2u3R40EqaV@9*CZTm5Q{*9n+|)4_Pym~bzWCMW|FZ%<#H@$;?o!oK z1^cz9h7qD+DOVwMEkK>@4ZWoM@cMFg-lwlsr9*>E+{*6@qqdr(Id1pVKk*FCxntk& zyYRi`rK_>p()<-gB^ohF-P_s3(|DFi`h|wOGNPpiX}G8VZ1?VXza)bucj8R4u5Oxy zvNPi;>x4Y)0%(i2*%_a0+L@o89yuS1y66|qy6+_=z#mTF?hlysUi<0pgtNSx=ktFa z7s@cozBRizy-bdhxvux`h+OSX4!ardElk|+PY9Pa>~-eJF4%JWAHtm=Hqa`merDx`;YpDe-R3>V=ELZ8H+=zh|7XHuVcqGAzPcv z>*2&i0cGkhS7r|HQ&K}>a*t9CaSvF0&?M14D=sv$zDBv!`7P_Q(!!N$GH84I6UrS0)*xobvLWg`)H?eo%W@G!@>RVY{CN50?lsL2)@BxJoc@)cvefgFC>Bt+`4+cT1r1M2AgG2KZ zGI@rdbmP=SMj9#c%r`s&K`d4b;+tf}y45ULJ^|1%cYF9JH7jcyoHcO{UCow-q{M>h z{YlQM5cWtA@Z@v-L^+=-r}idI)in~dVKc=x!uDO5ysF0EsVB|gk89XZy0G|>;iKRU zhQUg=mQs9c>udPMh_mAY%=<2-?dMBWu;Igw30-EH-;`N3HigL4$yLivB@vK>2YN2YQ%RGyE>CsVR#w2<^D){#@h5EUGyTV=h6aht z;RT7O_kS1^64W&;!+%ADsf45r7FqEfAFXg^bdLk||0?g5^aMQ-ZqYWoi(z^oT2j~0 zFm5%a$*2D7XLUuZtF^0)rRVNght>x*w7S|_ASwcsvK8>B4=`yvslTiLzN7f~^Y7ok zr8-UV;lJ=%I$*Xn)s)~9hEIN`eIr=>sfm75ii}4srcq-ENIur>t8sehxcF6;Kk1$a z^d1gai`cAfrl>cH{XUfYi_hhU8$HMWyBe(8DwwoUzy<1R;Z@O&DgySMSE{|ar0>Ug zm?9;E`A){21%iK4Bib9aM{2}ZcUPRLccW9rfP85r%_SCN)#yh!1pjp+c0yCSDw=Fw z^y2UKr}NZv8h%^{CM6Yiy~dU_SFo&UZG85{ejMq%+^lO`Tid9EmmXZ%>rTZaqPCP9 z(B+9d%;hV#-BN>G^zF&!ITDTRBTZLY@iU@d3Dp<pXsiDPa z$yX>tSB2fp6+esIF1#jpKdch#3ING`P?)3%L3Fzu=tY=4^21R=Md`)D?SO1O;8{b# zR`@fx=6Mzi_)+#FxXIb)A!BNDH-Xe+KH2Rw$hf}1aWCuKDh-KZh&dLa!(LOp#A;26 zwBJeo>~rP#)hK$0l%mrJPvsH!xy1R+L6ZDzaa5Vd{jn80cjSXkdZXOx8L5uYQ8Ijp}y@7Asc)V8=1m2Gd4Ch5t2E;Ail7$u>8vt zlg*RpyOlYrlb812@YB zTfJ-de53oiwcI7&97tjo7pXvV@lBJSmUe25F=WkQ5{&dJ2&zE@?Z*_@?8syAmAZyI zO`q)P`_3lcNkFg&>KgU5$(b+N zY6#A5=UNDiaTY@cF@&rGLgqfv+t)9v|M@gQkeCVC7#})cF zHdYgHNRSe9-h6_@cZF}RYzv8eA&m9wAKy!tAFqhy;-UFFjm#uZLbeGC$dw`4xthGnsZaB7hBU#XE|Nz$g1vIBqcF%sM5;Q^Qkj1v~I=AT}=%eU>N+z@&8Xg z1-!(|M4Q0?=pO60`bZj?NNS+61L&qsp3Jz=&hkk}NRFJ``AF4)i3T7FoSU2DbJ!jN zun&GL<^aRb(i0F21KtII!442hZrobJ!!fTt9&gWpPVb7#p^GwpNI?k@%x%6&NlAfD zonX?@{avsB1yK~b3%q%`?rjOL;c-ohvBPJSfCwxcs*MWYbz3!Yi*j=-7xP;FG^|P* z*>p+0ar389SR_gsq2c%dgN4c}%KLwys#|U^9o}u=%Nw8FdXe%VHG*DEqk0 z&@fs0vHWdGeRcg(5jSo@r9^Ufxa4vbj5|3+`^o$A;>Ezw@Zh)Csjz)f>Q61^gF}Fc zW?aa?C#gSHjQ~1zBJpzfL-WC5qEP_{WP$>v!5p#T3xU2kLWsecK?@_2C|GdqQ&|%n zcdY$gc5UM(iPnQ87HYw>;1UFJtmxNZevUQV#gBi>{Ijx3sI89dl zU?oViv37+s2nWdxA_;cDu%~z7Km8T^5sFWG@l_T&cVwbv8JgWb9R91W?;|VI0S`(5t9)N1cIV&YB9=?<;vD}doAU?b;7~DQM3~wwGPOpQ!+a81`Xt(p)QB1_sFn2)(LE7@Rx<=42G+SoXK z|6Z%32qCRnCL|BR!-xLsV?ZpxXI$!Gd2#vFiq%FgJZ?5MGkpEa6G>4ZJY0AG6L+l{XrXfsU{= zk*sQlNwcl|s&M6Lw?AKx>4$e$MHh*w2D#@8Jr>;Y_QS~?7JFj&#T=2u0x&p>1LOF6 zpUu;Uk(HET7Y+0%C+8~9m1*gj|Ax6;PTXyUzHGJu&5Py+?}OkSJ%L5@T9mk_VQi7R zqq3GW+ebEU7{k+g+w-iyk%?1Q9+b{j*yCv8htspgQ^cFk?b{o{Z+>q_470U4)^G^Y zlfSbPVWp#JY_Rvx3rX%wQ1nIw>6m1)v*9o4ctZsF#{@=} zkRRxjvik%HtCPWBT~FBJmu$HIFw$^Tl$vTbB)MyE0aY0ivHV%GNBD1%nWNHHV0>7O z1z4zNwE5UuH|DIX(vZ^bACVJkvKkvjh&9zRQnhrNu3KLopTmb?ae1L#YnkH(E8esI zPrC6C%gy2f$^6muXWo}%jpT=y9kr&jvzOD>-xP_$XYCm`8tF=I>d}krX)vp2C!HU@asg{R7C_cF-sOX_7O6RnK~Ae_ak4#^5CJ zbG7}@*Z-mp&TjvFewq}c!TN2vPp%w1Y=Y;1ffeGR(L2OWRE&KF@jG*$Shi1|ga;#NaIrR!Il2%^DcA;p7-~02LHj zI5!0aHHqy~VKZJLNac)QR|GK7Xm{I_(zH<}@ykRj?Lv)&$bVaw!eE})RT%_Pz(7n3 zMrdV%B+yz}`H={NkdP1n2(<7)PHXpn@(z@so6XM`5us}%JHjmxb0&t@f&vEyTv2dN z;Yf@sMg}q1oC;{jX;nkGAXKn>eoM$kUu3D3mG!ZeuI5Qd2=Y2#<$6FDDicm41i6b) zzy*pu7iBM*$>3U>&u-_;J?Y; z%)Wo`sA_S$vLKb>)C$o8)R~DQCHSa#LKi?GHN%Tf6XU398^c>zToPWe2Z&}-&{#Q&r zVa63g{b!>dVC?-Va{?xj9E?K<&(Q8l7CWg{yWO!YU}UM+Q0elxTcMn!nUdHCMnv1b z`xJT}#Lf6Xt8P}iVD_4g<(szd-k+Y9HGt;eR5czPqgBF@t)(?74&YXB zr&OHOtjeofC*&FQY2R`Wd>iQm5kq3QEY6_C;|2Lq6C>)i)qSjNvPKN=iUw>kj;@w} zUrkR}veZiEd@k-FKhLfN$?i1>yFXvL!!Is(D5UawHgF{h#loSPg+=GN@W;N_D=%*W zrF`#(AJ|oJDja{$Ds|amHtl6k^towdYG`|#sZws;=!Z#V-8ighfWHj?U5+wB?5u6rvnwo-M}=QX96+2_l#^Ok7@zr*DWB{k@Z1ilEW&0kd8# z4lGx>CbG1HV39@ZtxPJg3aw=8=V$U=#HOI}Qj;gQ3HWiNkD$HmYz($j8@iw=*NJD_ z%1#=opb2XTkk=8|3FG)KNbLAIT=Ko$a14#iFb8TIi1gGw1f!Zb{YHL{!RFJCLRLvw3U>-I765?lgC$tjEH#*>d%2yodYUKOu<-!g9Cd+kd8ez88Pw#dk7g&zV~b25(dGrU8Apfkg1N%3`CV1g z$xb5*4?YXW;t;%Un#QJt<{?#>&d4@{l++r8*wA&l%_n4ui81T(oEvX-=a4KvHlBaf zOnHj_Oo)hBRMFvg!_v?UL*X4XOR5SkQ|51p+ zZ|He=c}Fuuy@6dvO-;?3U427?>t`*-F-DlrZ`kgnTa90ur4x@mLifjDR}mCMNBj z^JY&?Ufxwzf(neDUf{?{-kc0IFn6doI3ihj=*yQHH(1c$`>!W|c=AY(CvARwXVtKd z>NKg`YumT`UCugF^T|A`mi+wA;$|7y{m(B5bK*y;^d zddM!63(*(nz10`zW-#Y5jziZn2-GeH3ll_i%Fcu>9iJ!##dSd`Q}L8*G5;E+MB}l{ zzZiLZdc9uj5`_`PA)4t=AKuTPJm zUbq_cg88`F#*;HpJfJyM5X_ZKStPD1&mvM1iwwU)$x+dHzoadC+rEE4$O)tQtcCvY zry-P0x8;W`Uy(pe6^D%rSAh5kGqMVC?jiQf>*cKyBELH6%IW2Ss*)enGMwf-o@%%d z(q4FjeOboUuR#sAmQ)_oogF~0oN~y;9c(&?fcWY)1Wehdn~L)OQK6gCa9h9gOYyY$ zC#hDEt*D^Rv%TVGK;^vh+^^_$UfkTb_?>6hV&0RyrQ$w%F(~y+t^Sd_^ z;Ou5Xh^i0u?kiQ6_1~l^{gRQ9k(|DtU}0f1`n-n}JRVR=rr2V4 zEqk#2X(Sgu|54^o^PTRNRDlfmA0tu>?9Ic3TMYFFS=#lTwAQ;ZSU%RbCXZtknC=^T zFf{|>s_^d|flL-^@0XO;6`d#XrP8Zkkb!nA%^C)@D7Fa%5M+$#=$N+i%1{CPd~ zVOL5N4OF-6L_+<`&^6QVSMP5lcM!PfEId5iVQ1v%c*!r({AQCv9`}>fkGGkazf_yl zsm}kEEV8pJueU(h&j><--@kf574%5~CB<{2;HFA8pdf<3fCwU0vZH>7rT7U)%a`LY zzT&nnE^d*c6hqFVGWt}781zmFf+YW**T=yZv7CAjZKa9^QA&yR{{xemFnlevZr;&d2?-52PYHj$Q0If5$yny`6Eta@p98 zx~*Wot0|sc2)}m`QV-b%K1@wTujcY?TJN@jW#86ik^}JH3@`--D-TUyjz?{+o%AF& ziYb6Itmw;;AVsNtV=(M9BO9>;{RORGZ5}#JNVCMDSTP+8nOaYCv1E4Q*MWSJ4F`c# zPEW33N<^iK{n1k3R#m>9+hU6Diu62(uJ#E57KTbiO>Nzz0AJHfZBEtOw{@&AY_?Ji zpw;gP`ojG+(Gu?Ba=mcBaB$qP<*R*T1%rJRj4<%;+^|>Q%4t+4uAi|`mxe^)giC4a zVjM)NAJwaeUX&E%Vd5$lPJ(4pp?~8OnipDjziHYIa~&v0{h7!ew^6KK#5C=7jdC9y zGS@0LmY^fA8J`863+d_TkcCSk{6lRK1%U;!mcO+_=rF6#RyFAby%K$E&_EsWLR_R> z8@L<_lb`deq*G!cX2w*y-jIUZpk#B>}v=D@)czCYCBl-&k_<4x4EmXr{*C}jzVY$D7B zU4Yscrv_1+Hl(F4nNso}jyY{Gdkn!uh`&32@v8Ih0&u`QLMDN25NON|9TBcMHMhL) zTOjs=8fe#bw)kxi$>22zrhf2vcQH6P2-JYeysnmkg^+CF^z^ii?Ie-mkWt;DTy!<( zc_1odC5<}uRhz1k>x&&;^eQ_Wt|US?N>pU#v1c&!^IWVG;2em;najUaxqjYagt_V>CGjOb?R*EYbcdbRrGuwuU zl-|4!MW;(oPyaG?6ftm2d4N@^9?i8cvrxdzd|FtDn@w28M_8POPcCMd6FW@O)4Aqb{ z&xxBb)-|(^pb&N1dmIF1`asNS`pyl$dp*CW@OXK-Oz{4;=VJ2Lyk)~0Ga|AR*hJ)K zxF74ioU=VmDLw`u$wxOjl+K>uQi<(W`Zy!_^o(UG%kF5}?~X;;diM&#A6oT9t6w1A z>=t!`N5Jh0e<-_-o44%H&n}<4iutoahYoX&h87Q6zefC@mB*s|jHgbQ*!R-8jx6H^ z1MkXzWP=Ellw&C~--o=n>W)HDmNryu$TZZ@I)Q8jE?0V~ilH?-+c?>5mVVPwFnBLW zsO>|PT>z>5^KFssE3z24`#oww`|B2X*0G$Eb5n(4llzp;XS_qJSI%X2PqY4WK}o#4 zyv_-Ke2Ug1tX=exC=J?u#S4{XX=U($8&URjc{g&sK;N;y$WLqQBTIGgv(ck7g>2!= z)63(FZnNXoSjQ8^!|nSFkIOH^CWhv&N0S-u`==eAIrdJ^>su^rK?QXUy0$g36B0bE z=ZBVoTqM$m1t*BQp};@fpccjCa%p4Up zBS13D54^TK@sfQ*j#1e7wH+t=`WDSeN+n-BwjG!iyQnn*>r z7JFJyBtw>w5(>quwR-pF=-(Tc-VXdBE!JXX<+x!o85zpT^KL+&v5pSDU5S0tzVk-t&vIfs1EZG32z>RLZ6?=z;=P zJ2Y11@JvoHlyY;8=s-~AWS^EYA%9Sy&pKHq1>{vlYE5Qb&3TXe=jH=n|AVIzUe@OSG> zef@e02ev16Kgws0SK3zioq@H=s<7MsRH0jouG;kFB^Ncy`rQ7$ML8Wq2sPBKw4}re z2)c@RxHvdm1k*sWK!dHwwo_{bG~;Wy}+4C{gHvZ`9d0us733JO`fvsV8*p;T~cZj<~CdEIQmT| z$)bjiUVuC26^t)Je&Vl|#nja1k|ckP<6fX))tBEk^+z#^>3AVk#}jZ9&y&M|aV8F? z38i?Ov-1gP({gGVFY!-&mfnVo2&Dwqvxz~rGMli*mgezf`v~v5m1j5n6pH(`8z>Vl z3N>-Ky3nhcbsj7t-Wth7rI@Eh5OAGtmAhBW#kZj^Jp)o2(9gun~x?eGmj5PzH< zDKTopEX1?vZT6^$1_#&P(JhkKTlBiJ%+&^g-%x|jUqED+wr3ULSs+wqP*6_exE3Rx zBU}*gO#fB0138o`6U6)}WL%vf#z5advgZ_cC-A1#E*-Wpu(jUqeg=2Fu0KjFEb_U@ zl(>{8?g)mIk8a?=(F$VKWtsD;;kpujs%b4gd?5XJ5T$DvGR`Z{Esw2O^$Kcw_K{}b zxun;L(cN}9+V#cDtDYoja6l8eeeUX#!5}bG9!gh7o}9+@k@l$*w1C4;GAANPjE4rK z_K(C;M?wH!7J8aqN0#MuJ-|ZhgN}e}zlOXMzz`(=s>^j%+bvgyt5kNUD$nosXPp!0)4|t{ z$uyctiFn`; zC_2lasM;_LFO7&&i*&6tNJ}G~N=hT$4blzL9nvYObeFJncPO*HU_le?V zO=B)uXS()g?P?KF7y;HUKR5HdK1{@otgm6wTznpeK6&gnU7RWPw1t0|hdn=}W&crB zaK$zpx7ieedxR?A-?4hH5B^L+%YSsKY&krm)5ktzVmkED^F0Wz&ueu!>M7?LRlt@> zr(In@dccatXz{)Geu!D>KWZA#@p^aSwf9kJs%Zqzc1$9UnOP|_4<=zX_P4u!Az}k< z?ereF>4`N8fIEMkd<>b=oISj9tu0bA+V;KKS8P2#c2i`vThZzIZq>tK*GSOD)pc+~ zvANEFN;}bs_$_hw4(-!v0B|6(0vH_7u*iYzsfehga!`LzHE>pPeY5~TD}c}jic`r1 z!Msm$2hxg9@(PZgW@>3mfB5n3N!DE-Mm)G0J+eX*A2yfN=%2k^laFhdWJrO7sDI{J z`Tc$Jk6+01=QHoeBp5p>lfkG3$LdiK2gHApVW7ZDR)+D4b${NosYup9kW6-#r9u3()bDTeUGOF&~nCei<5&z^m3~l^*+(ZkM3MV5fOM zc$XH)IqePPoSm7LZY7kOPFS3I#Bk~k$PM2@ogj=f*fNUV0?1Hk&_tDMVXR!NCMj*vNI*5W|ufj=7d0lMm5+v4(Y+=vyLq1EoC zFx|6rIt_mUQjPcAe_oa3i_vU`RGux91&gW#ma2oHR?ZJ-E)5O(2f5C40&#Cq+rImFplSp}SIE3P=MZD13(&X(?R=Ble zkf!2vSyD zNUZB|2x1hqKuit7j^PeSP{-N}s@J}zucv3nMGS<{YM;h9dI*sKHW8X6iGg7%F|z)N%K?}pT1>S^r`J4a~**#|C-Jp?fAKg|9P4$0!U z%EXQP}5N1fqcM>xz1qiQ+WC-to2Cia%vD%df#5e=A=##BsY?Kc8dd}lg=g(re!d7CdN0F`jgP33XAC{diNce zQk-@_eI&$8RLN41wq5}=Z%=Ju7PgzbLmVxK4!6m4z@}~5`XtL8PAzr^SDV-YN6|FB&*U?`nDcld&SP>+S>f5y8 zX(3Dld)J7uM_R$&s< z1xgI(tBgt5#S@7H@n*H3#?GV5<;z`EA~UaGfhs{DWHGtuhyybC-KxFcoPbm?O)m3r z7J zQ&{GH@tn596{&RcVA*l)F#Czrt4rh!8Zxqq$^64$aa#Fmh`BOqfMe#u*wzeSI=}JV z8h?^e-*QY4aWF8yJQ7I-CqN4KD4z6R_OdnBoL&Me+dZFWX1)kTWGH8P_OI@=m6UBx zC?MbjBO^;#O~9Y#b6#GP93Dn$R6cGgJ~oGv`x@sfFZuoJsLm~zlRmjac4tLp5G zK9)Ye zo?+DayTUM-V1$@T@5TRRIk7-Y6Agot+_HVr_tqWu%FFWx%FC!hKL|;`YV{zhLV{)d zW6u4lsFK5$id;t&OaRx5BCa%mPWxb8m$mmdEy!#k&dI{1sG`gn>dp zc4#q(AY`Qxki$j~@SyF!G2FJK|AQO>WQiwPEov)kjfW$S+y4{qXIFwob0P}=&&G`y z>615wb)$Ft@s(lD2r@=$9hriZc*JDbuA;ID^CqTxiPSR4dItSGpOpATsW2d%uR-n* z$Aa?BzYGgB63EQ|gqR|*b@fb5D`&Ll61XY~C91`6Pa%1gx~qboe#lFAT>8sDI&EXw zL?pQ6NK7}bFKukU4}tw*A!-<+X-!2xLn5Nw$=^s>vu1u<)BgPBn+HMe6nau=hZhc2 zhi3taGJA#Vj}w0xoLXbny?8JrK8&)Xq29ZymIH^9Q4ClJ3&kVOhmea=#pGE4LvFH; z9aSE1G72>N>gq0&8(X)#ffmuk1AMLh1t^kfX=-A}3yzDE#)n;cLV+`=wWpOepXrR% zy1#z`eGbv`XAmVR>feME6o3&jik^rr#_~xFoq}`GooYcI*|<#k!_>={VVBL;JB%l|I7YoS6ESkoO$7Ouq~f|r&L7s z%?%&--Z)RRp8U%TL-y~`OAS_hW`-V&*9g_kD#hd2*{L{4se1H+aXg}M8(;Ol%R?dI4^G-=jdybo zy+G^rgZ+Zj(Z9!^`tH?wpKY|l+$Brqj>CW9qQdJ!v_CW-?ik0mUK)8+S!)+plu_?@ zwHdoww>qA07aHN6wD48%Fue=boGyX#5x)Hl>pjZecWZkf%kkOToc=kgZlztXO2UB( zbs9S};3a+2*Xw?`7fAB0iN(2=+v76poMMk4yAj70o50*5X^ z>R{V@GFE;$`~U|;bky>lX>;ID>yQc_elxUT)eZJ)V!M<8RhBpVr3KYl*@vlled23cqF*)T??y?62K+JQq%T z3C3g5Tbvw!R?at)Nx~4Gtft-VB&WOJ`uvCAydkWafNT$+U)ED6kmBwn)K1`g)1Pzt z3UbPalfRCrJ56C+#L;H8uRyuc{~HBr zYR*SE$Cn+t-~39fUJ|9qIQGQ>xF^&OOe1P$ zRc_0jv0^tzXk1$IXXvvAi}yb_VTW<3+nW33zNuw1J)8;us zY1ETlU3$n#`(H>HBZg`z-l93xavm!jy7}(9*|i^Er!Ay$$)g2|DuV+%{n10ZML~#_ zdQk1;Z8+1{mi`v|nxBgl4kzBg{K`WP4Zu`4%~d<)cEE5fUAlsOw6auF2TNMwR+h0q z50W>v(|8qt_}<@@Q9XP2=c&Rad!bHP^==hW$1mg)>yN6=-YaoaN!v~R+Ebt~7d<0~a*_rFR1i-ni?ryS$^L-79EeHW zAyC0Kdic=STcvEn1ukGG`toqsq@U=q-io5Om^=6t{|)JGvT^=v{b(C4ZF3>#eh=EI zOq(Jgh@aHwn9wt7Cd5H~^zc;Sl&zJ=Rj8?j9WiorlsNV3sIK#y>9lA0Y?|vP0;uL< zLnx0jelkpglk>GlnvONpX>{El`Pj=ZuNW{+^ED(5ZWMga`1WE{9lS>b+<7cb1LHF%Ag z^I44g$tL*?@?GsF6)3(Aykm$#n0)Y}BHCCoV4J3!i1K=A2*EHf`oi}}2)$qk+;%P{ z9bep`!OWb1gee3LGd|qVw*BX>gt(XfZppGIzjG)1J)N1knYy}$iwWXTyG}LEB)n?G zP+B-Bj8X=Xa>A+}IQgb;orC%Yk>cy~+DmV{V$PA5*-=imVNg@v6&!Ywu{mXp#t7-8px_#LGS?fWaDMx=6J;#L? z+U0Vl-M6PfUR`?muvi@9`!XydA!632x8}lcVzdk$mqbqch=bTfNE$I&Ff|X^l=;?) zJV39PNr0msFmyzeIk!<=QjjHumND4fs35P{rz1W`VzLsy#MyG1^U2xJti<=+NHp&0 zn1UB|jGY03jRU^SCPFHXA)4o7(u0^PP4G*Jz<)6w1LbZ|0^F5I1RIKchtNW{^j8e&sYEJ0553va6lHub?h==4)pwik_ZkBmjIl5jz1&n+;ZQNXFVSaFc$M3-7WJoX1X3lS7Z7hC zsC`mViO^df9&_`y6IWENX$b!)iaot9Ji~U@BKpF5k;GQBN9Pbb2nPkE{H4s8EF8S# zAXHU_ErKfzGRVS0Mp%6gj+glfNSDWXhivzeL1|ihk%S@uGX-eZjkKDNXVXVWD9($1t#+rrHUU``sdoPbV57|T+2EZYT5A#z08c)6?_& zca8%372qlY99umfnG3g6Rf)*i+SviocdL3tv}0f${#!988*oaidoX=e6n^O0NRmt# zXo-MM$+Xdn_8<`#^3uB@w_ZhQ;;*JQP20H~95<&yO|@)nZ5)y+Z*0^m)33B~22 z1da-_?Bb)S!}I=hZ>ug&a(tJ8cFx;h)pJk({NR{mE-lwvU$hnMpk>XIrEX48nceQa z5GlHXDqfO2P_%#5*ZyqX?$uxJMlGv~FIoHU^IFaA#NB)!XXW%A1l1B3i5=lJ<@xoD zPcIt}dK6-#Yeo&^(|q~S)K9mad+tJ$->D~`dQZ40A;}n`uJ@ZuD%8j@WoL?PaL*UB-crDt)fNZ()|O8GQ7c!1WMSVi*J*` z*7;GQg~%N!Vz{+v=K{Z8|NL?MwW&UAYhj@VBC$;S@y_N*5GmZd2z}!pHTtN;ODD_rHYCopHwXh~$kF3&V`!tk zUZIpvU?uZt#`-FejTBkWQFJ|PLh{bY@7R7u1V~f|>M9O6t|Ynm8S4`swes<-d0!kI z9cg$l2KwfqQzDPu}eU+kNTPBFAI< z$6Ni@nxZ+rYIonY{Mifa6nuKMT7h1in^(-@VAO;Ii*+H z$8ktDy$b<5myaei>X8xACzlu3zcN#;tN^o>Po>YlJ+M8C{xY#f2Fa7CFcZ@*^v32V z?><%^{PrtWqjmJgmEVEUO}l!maQPQz{o?18%Fhj0(ud5$|5M7$b9}gCHi2G2feaPK z$Kjfl7Mr=%d(XF)N+ihDD-_SIEpLAOvn7++Yr}s<6?Pt$P0vi789Ae@=S(h#u+2Jq zTk<;)9i>B4l$PzBSDg}s+H5o=#3nADk5u8$6elNv-pHrgL?#5V$hr_m#F`yYK>nm( zz{r9DxC6?bprBvaAHvM*(CPCK&_L)2=J!Uh(-Ul_Z*11j#@$}%-)dA}qI2%k_1h75 zNvXy7V_*?B(;Cx`QEvtPYe`EraYkh1lrF#NAOkmFE^=T(!4tal5kC#D> zlZws{%{W}~MaJ$`*5lLAVi9sr@{-C|(Xg$+I>5n6Rw!;n!kN4;pD9Hh9V1?6)JtHx{8o?wa*!q_|y)6)Y6s zxwX0C1aiu2^-nhLj;e~+6nf27=iy&ha7}$mg?~{c%R4M zO->b@I2o74KM7cMwd6^TN8a5mH@J;o&cJrm(`U5kBR1(H(3M*)@<8hV`d_`aFflzf z6=xavn{v4=bCY;vA;zSFhpFr-0%pYDMdVjqqtlAmm>ewJcD`NZMAjKRy~683amrPS;V~ z#Go(>L2}Lu_e{%jAg*2!u$}_rG4D+l!Pv_9k{Lwb0KO?~>-on_-upo~@;$OCH_%lJDx+ zt!zOSl*Uta+{ABmO%XtXR^bv79e8{(E?BfuafFTWMr$)J0*uulP~N;Gj{Jw^i8Q`b zYq(d=xU{m7|9nq8o@1Z8+2NxJ?nf&ZumN1Un+hODyz_Y1@0bqzVp0bYK>^XTDCDhR ziBaJ&mdkHv-Nd9dnsTDk#}`aHEfGO{(JYHox$%cLo$ zwv{rjPi*e-dnGf|!Wj)|cO?fn$>R07-`4&hhL086L#saa+KZA}bzNA>5^tZEy`HPQ zu)eB&5k>bIL`>wTys6}BDxLe`J>?Rutj+M#1Mo5MHd3fPXj*dziQf2s*&Up(427094?}_S;CRbMKq2;4niScOh&V0co3CBk&uyveYCM?ZaPE z7+mk?tM%38h>S~07ERxO%#bfs)k^MOS8^3R5mO7_Y|^U?Wrm*KR>cGjqb}2D;KL7WYlc@P?S1RA`hvwJ&Ja=!`r@W%kR}s+z#Z>f=1$EwS3nBTd z(04STGZh(~j%fdMS{i5!qeQtv0sWvvhj7fKG8)MIl(D}2S0=6`r#vwGT2yPS+JAVs z)1B?anSWI3tKv8XIymfQN40cl@>h%CNCdU*A9^#hDp+$a;?8o!Ft52{5%bel&t<^- z&~leTl31QloMNf6h1wfEoVU=SFNre+^cX5Ka=rX=;M@>Bza9nexSD?rht6?tDd}<4 zt(KTRjMz3;j06jXhAn$vjOI`Nzi9!M@pnCRpB#a5OLKEGrDVJ7@#2TZW!$P9AZ6L{ z8M>S8_38O6R`~W`V5iluS*s5$EGJ8itQMc^VFavtUlL4!`g5}A|G*#!a*nzh(A*3F z4oyo+0ELQ}1mGQPa#$AwC4YL_2bdWfk5-pV+% z4lG|c;hd~j*f}Roj%^7!ILwhKtoSWS&NoO z$GpdvW=9W;LuV=!VWd_zZ2!>IJxx_uCsJGtiH3~CyrJ?xPonvfSkp&olu4kq%}6bQ zY4&Yt8c7r-Qc*;*KvXaR1-ZNqHbf|Hg18#EhY%JVK!l7f^drw!MMd*ITnL+(iN*^D zZy?2D(i+xv)Ji8NVu0iDE@{?8$z8xhHZ=%a2}gTZtk)?Ue}6co!p_+X@25)x0tcFy znc1$7L{n=kH#vbaF3KssW}QeF=r!dVv{-(_Q<}(+;Gb3K4%>06BITz{xCoD;;vz;I zPRjkio}WOth{-mGjL(b2bkzh1@GKs=SHG?r^h&YrH+RP~1>77xEG@AuyG_l?-L}J; zqe!M-KfwRCULFNc=h(Sk*A?B&9dL>ZiEe&spd;oPk@IS6teZKsHCc%B309%%jki-K zZO)TRuq>H-tTuX*28HS!$OMd7&~c6aGg?v%t)CveUVh?Gnn8n8uTvjBcs-*k zG*vm1!yD5*=hwnoAwNzQw*?fLzl=gR z+kJ1p9;W=SC44#cYJ14~`uerL`(yFA;B#*Hgi&x70Z^vlKX-@?zubIUJr zY{EBPkuZFF@4f7$SaSEhij4k40^|4bF+|ab;2eV0AHS75$6LMc8{qDT^V{V93z2J| zbQlXG^TZ}ry~^d4!K;xnvuPGDmx?d;?T>K3<8Zp1f1`FzzBNJ%V;7j%r8QA%J$iMp z8zFZ^%L_ejiQvuWKjGIvBoVqc9#K*Q0xXcX^p1k<(E^>dqHYy=A3+_ zH1+hXLY@?scuXv+hc};mYU(POzmd{8=5?Np9GNW2*g-dYj@?#xsSoU&RfLLur! z$|bIC2~)+m@`BJer%-)m{)NqrfDr;nRYW`Eu-8RWW$|9i((JinY7%w?@Jg7SqLWLC zmEj;pNpgVE#6a5qO6Z0o^U_2(VIU-nM8b|-X9Pla{7L^W9hj6RRL*{tBwg6!l2^tq zNhOt_fAMk&&_N27m3Hzuc(Z69mw5evnLK^vU2Cq@(IfqM5EPe-SXmk`o)#^}K{KjS zjGN+P0y>%!Y*T8>$4_;JU5;vOc<92y=>F968*^;!ekM9Iw#zVw=-25YJen9L4(%`j zTA0lo!jkeRL<8|kb9W>B3iH=@HFYgiqBqKkA0q;0u!)rT3J<5F?+r*vjvKgdohZ z?JZfV=Z%1#u07(9_xTi0UBl+AcAiOPcHr{no#pIiYFl@#XsLdSuV56bQJW7sVl+q2 z1(Jj~8}up#skIZSOY)kphR&4=k+d;^4{&gUu8b&FVspa>Q4Y%nfiM&^UXms@oLuQnd<5h&=+ccl_Zx4Y$3#4^XntV{%(!*>N4>s=pGqU#t*MmT~b)r?D5SB#Lq z@*Y_g1Q$$4KgO8%eE;tvLy`OUBHCM0i^e5MWp{X){734%9|wT-LajhuWow=P(h0j-Ux8j$}(L3UO<4ga0pwBJVpZ#s^dm#}6k&2shH zdk{Kfg}NVP!M*!?dXRI+Y9?VYbs$F8pe;)Zke=ovMAR1koy;D)C{vd0g_)$S-IKv@ zKMP-JU>w>e_w!f7@YS|c5eWUo89(IB9PVrKl9&UK_ zm->Rud-5a%beVRqmmO}9gk6pru%ItKzZIYpGRDDqGAj8U>>AvMF$3b6J+g_(rk}{) zpi^_mQ4t1X1Q8K-rl{$u@^%VH<08*HFw_9$y_F_lKn$;DAC z#F8!(+<)*$>o-lHu4mg!`u%9MfTiA%$t!aB8T=EO_Ec27akg`DVJLJ*p_-Qn<;r+Gzh$ zJgw2_wK8{nk1gvj>K|CW;_@SAMZM$yU7YV_J_XeM%;+@zb^GKAs-o-2oUkiq5;Iz+C_7ZFA8!&=wUJ3C*fmU)BqR%fBI zI=G0f&xO+sIe%*yNyb#_YHSXRm>^^A&jU=IfIn(>lMbP%$;Qh8H_--l^!U}oka8yFLKb3sN zdflgBUOLzzAsN*htXda(Vg z41-}csdmFf;y46gq#u1Nu2;nmDY*(olzBIai!bM~bL=VFGa`K1&?p4NZMg(K&Yn1T zt?ZV4X#L$!G5$O#ywK$7k_MoLBr)<-7|f&SYDO>vSefdS4x}FcL^(C~5WkqyHk*Op_ro|FYGi zedzBn=c$YB(C-^YmndqH=z)3 zIIuWJcVR?B5-U$ydxNg2zCFKKWAu)eBgi1?6(SQv479w^mOGim_S%c}3%!6>lL#*W zAvsv@4%K&G2X0$;0O1R5Y_6xL=l7?p;{E;oJbK{dsHwi*mI`2;b03m>W=mLyGfVC$}(Bu4I_Wu;vSTh=hw*xOJqDbki z=T^M*^Ldu=_41}-j!+}|udEx0NDzcDp~b>{_iqMa^%B=vc3nhfe~F1LL=?Z!6TS|U za&t1ZY^L#;VRL2sQe|aq+A=KIl&n+^%RY^xlT}fhb?1WQ(aYt@2w(x;f?AyhUKdkG z-n#PeW{oUf+_{5{3=&6^x=D|;Qr`1-(Xzt#XZ?CNr-41!Q-zTx=#AxOjR7p^dhf%~ zQE>u)|3oZTqN3usCG+gO@`?w!!uOgdDI-9PC?X1(DgLOzwiqW0+M@3auoq{ksUV2q zx2(AlK@=KY_zL~@b{P>_>%u~6+ECG^|LFgR=1 zWNK}j*_WLbX0WT$BJfakhwQp;mCKMDEw(KC<|*Au7JH&bKa3xq+PsV9k&3Q*v~NwP zwA*nC=^gX(_k=dIHa!Nl${8-n)6+s0J1*4=N%Ke$RkaJXl|CxdRGWxL9P$_A=SO=BQgfi=x0$5T{8?S@@%iRCWp*ay(WG(QQ22H1ctM3s)a5_T-cU7loNfej0EqB zKHc2b5@=LB_U1gEt=$&BJnR@h(5rNJCQqe@m6X((%3|glN)l4J9w-ZvCs90JE;PN1 zy=YBNb^X9na=uSc$pxujK6FEqEK^ff19_(6Q+D>?XV%MA5u4}RwO8nbhrd!r2ko8q zY}M`(Y{Ha@-WIO7H|x0_&aJLXceh?-jwll=+FdWju>IYI)~cBd+t7a>5SJ@b?<^ z+zUztQ^INQn2X;fgR_u1TU;f!DDp%gOIjs@5KWaBZ~Q=Tu6qZutZo(c9}z~Ww+p-j zRMj#_Ve5zm2A6Wof$ks)oCd_Vy|2Q4VRIm)K;HY4M<7)pA_m|GzC#v;AkZm=L?R-} z@XAt&d|?Av_%NJ9$`1jbI!=@HgW^7CKa4duyN&p4=R|Z+1Y!DQRa9!FD<9OG?YxrX z0_|N_?Y-5dz+T*wRsg3k&v2bt@#&otSvV`XbXuCqnTJY#DvOBlKB^B}yEKIl6>38p zHa^p^k@TlIStitcfEIbYc@rOnTt}3jqwv*umarN>jY;QlH}uY=G>cI;0PVNjR2WO? zxtND!7%gLI31!I8^m&zp(_VdJZ!upTyMg`p&)cLQXgzoBl)R zoc+4g%U)nD+DxBnwO`C5ye!A-c@9WMAaZ4gT9B7;&+LG5P||{|kZjg=t~b6uF9U^= zm%V=4qU;fpGwU_a8+o_2(S7oHzn9g}wK@W+1+2&Rmu)&d_lslcY~Smd&%aYDDlThU z=Y@sk(IvGK)v^T$nB=A`1c_~JFSWDMZ}`0AnQ~$$X%$Iy?5RCL8L} zfu6)<5tD_VdDQa3S`rK@a@HJDmZPf?{`83P6Z^HWlVlXQ&%Xq;!O4oNxG+Gt{4cq0 zBtXHge1#?)NyLIR4*_Rr6oo`9K=TKXcDuW~v19@OiH1OCyK|2I z64J6_N7;ZTFV*Dh?ut`9Cy+E+I%O3!bf3rUY?4U;+<<65=Y1olo3-f4#Tkqv2v%PF z%UIt3&GQ|~qB|Vl5}AJJY}*=IIvg1v4#MZu;3hCE);(1CMDUqm9D|9%i*mTW4*nFr5XeX1$vc8B3j9o+9c7V?t(zj z0kB1Bx2(L4d9MwuMhyf4dx(sGM6X|=D14i3x+ouQS-l=@a#=Eqd+qHweYcYz>UYH> zeEK-}mClYo*_?)rQK>qHJ3>!+>q_c9$(x5j!}3X9AepgvudV%gLtBCz2pu}@lKJhz zpPr1pVnYT>}lu{bCY^sm&$w#lu6h2=Ul zFliQlp7xhY@AGr$+9{Ap?B|3t9fpAst8RY$YX$y3{ZL7n&9+1kRB^gTT}>}pj*|g_ z*6chR>V`N35m|Ql%S}(rxK`#=)DbR+1s8HPv-BBXUdDQySM=Vv`EX01*~TR08DJMeEoJ}_quwoWNV-vpx)9|)d0VrB^&_lLE89HSX-sPz_7j8~ z7ZDW^=dbmbBqM+FUy+VobY72^dFliuE-r5TB7RMQY)R4>(`Rb!!`3p?ZW~%zH^W%$ z(+5+!!4wN?*Y@v1p2z|ZrH8&4*x1M@72@h$d}I^+0>oyG%N{pxc-E{w-~2ly_q=R; zxyT=HyM>{_W9r0y$V^1^Xd_KG4VBj>-6Z$Eb~g_mKnPU9SIWjeYBn4B@|%w{-oKLA z>GjnPav*DIKz%&Stc4XLAh4UBaGt-#%wTB>09vKykeu|czVisf{rJ9Skd zz=pgD4W=AZfPFQ>F;v~qve2m(!zbBLJxrJFDK&X}J{RDAX73iSP>-_UY zo@?5|Gy|$ZW+9+caUG$o&_>pNzjOUt?}%JC?0GqdUzIa^!8S#I7{(8JcSe~wb2YV1 zET!-y-}Rn{|;WM5n~+GT{e#<+6Pw15(zV_g-X0ZGRAAupzlOk+5LzvKqj)5FV# z{*jQU^NnqBNeQ6x^n$J~t#W(LmL9P_iajs2>mq`~P(%t7Xa7zu3WScWyP(?X>zQAo zVc~dOH}9I6o0FL4uh>8gwX{R39uXqmor$!4(^C5>U#f=gvHmYJmp;ZCpRqWToA^~( z{g{B^_)$Gf7WZ`mpi+2ki2aB1b==X`3n-HJjCQN5C|u5p8AbCtn}IhD_k{O5qKX4C z9u8{qgmzRn>v?Fm3}k9Wo9Hd4zvsR!DUF4dBN%~k_uO$Gl<7|}z7f=mRC94ujtz>} zK6rPkMdXgj1FY+Kjm3vi!nFk!kMYG4*#s54bgK-e}2M`l2#jRT{TUuOaOX__)Q>zl99BK@`@?{Ws5!g^| z_dx@cY1vle)--Ckf=!q@x4Pm$xoL>|Q(O{R?)<%D=4=yeMxOgHJo@UbcR_-`wAJyM5ETnGRG4 zK3aoBa8Q!5FozhBe<2>fcVEV|G!gAQp*dwnkV5{Ei)LmZ_!($3Ay85raCYT^T0yTp zUJ<)+@FHS@$zF*qQt~^b1!6;}aIt@g;v-d~ejkmUL*N0guV z_H7DHEw-e;UX$u#Et*8=o`gXd98=bzpx&q&@>cXcdOVEu^9)VIg0Zl^;~0Yqp~EYH z;z;TIu3I#9ATkUB`GQTBN2Mx?#;!^SMKe>9dqw%6 zj2~{_Otz<*lav(1B_y`_q^p?aB*4G?f4PHk3{>OZvsYLRAS|Qyp4p2RxBG^cE?ri=al`j!$S}Puk;!yYR1ERIAAK4_LH(xYk2ye=kD1_g%$d>c@mS z#VfkkUIw_xGcx{^ZB@hK$PkE>^5s|ItFM6GT)0`C;o$>50x}u*#oF@l>y{ec7@!tKIQ8CZ$@;EZpHPsc4xBEOMw5G+9eLMHE=BHXN_rYoz zX!2i;wYonw^r^M1t;m!tJmS3n5h6$|EyK(nj!ysPiv|5BVL!W-5c#CRzQNwwBx*Ie z0DpCD5LrDqte!V9m^T?jjQeR3f(HxCsdXg#h&eTqYL-g=_X=HS{34;&;8^< zD64Kaq5YfqSeaMDU(LsaTHssDkKbFqj%DdY;0e1`xJ*ZDtlh=9m5~d3niPXnwV@Tw zkfR*&Ty8;#HT7?Uc_wWn0et@yhWOSJ!iD#o7xVL}LK|9C9{<$hl6l`L^kl}?E55MM0wufUr70$I1abapqh}w!a#}&2b%)P!(EwN@^MUZtks{m!Fsa^YVzZ$acio#@Rds}B#9E75RnBAH$*FZ}_idI2PJtISD+NQlze=u*OLiIB&A|{JpcuDi_1WN%f1nO5H*d0S+ zK>UxQvy5x14dd|W2?!fq;us)98Vsa6B}Gz7N%zu(#6JkN9A_y4*OiIW?n*$o!fL=P*KRt+)>eT{8V9FzhtUL>v0uXz_Q)+qIt z6D@JoSuXbNEfq5R9m@MbUgkagb9eW5h%)p}zMcUw#gVBaDMqRP$i;=MW2zjqt-%B6yf0^RPZw^FUPB*J=BG{a!TCQ4n zbUx!}=r8EpO;jCR_VBa;6Il<{#NC|jOB0jdl}FVWU>&qMwb`>TTWdl~l{7`Y5AC+z zCCG4;b7g8x>DE!7FOxG{U3i~!ohbvEDC16xak!&){p5REV5I0Dg>&p>$9D$C<9AoX6UwIBjb@0=mRg)&t?xCHr5f`t)1Tue|4*$4h} zgmIE`o%*yphBkTKdL%c_{gu`Dl<|Ko2D9M#o)*UGX?yG7XDl0aFgUvfjZ6jy9xeop z2}L5iLy;IE2o(jBgyjLJe~#|CiKs0lQ$X&37Y`^%B6PQnDG%1cj^Nytg(z3|-_vj{jX8aEl7(K!%2;j1K!gn{?^%sP47KJkhR!s9B(E55wdbZcMz5}}zXr92_*q84LE+0lDw^e%9 zX;6Kip#JJGUn|M(9F4{}lAU?oa*lD#l$|v!*&EkfhwGypPv>els+zm0SWW-T8#jEE z7gYr?SgE9bf9}1nwu)PMie}X^Q^YS<5AK(vA0?wK+g7f7#Q#-Z_5ASO0!*Z3%3=7_Bt!Fm1yK?OdSHK`Gi# z+k86~w}>N$kQ*D+s@bo|btczcBOswA2RG3im6tVu^Wjf4Udg8{*=Kof(K5BZ9aDRh zwlllWRs8#Ka#0{&S=%>%o4BKT?MLp+Is2bom@FayRGG$Q9cBHQ_ z5#w&l{m}aT@JBs#D=VaC*wtf|)cdf~(?Eu)Nxwz)LaIRqu|)p?oXTO^7X> zE~=Yv%81F2XiboF@^v>I|NL%e@w6`pJg_6-(sp+u5ZcPVJmMhH`nUIti$QSO(i!KD z5Cj%*)yL!i@w!L|`}rvi6Vwv_Z;|wmNx5DBY9DMSdwk|(dtgsA{prTZ8<*dFX! zMY`Ons zp4+uZMjLR^E&J#txd88sM!=6b>UCl!{zX7wNzIqPt^xK`c4*a?g$}NAnMv zIv3b$M6@(dOdwZ?q`6EVvcyE<96L{flb|0@4W$3s)GRLmD+>QS+}YiLpM?vS3j%}5 zJg|a81B6Po@Zly^H1LcKS&f9yw9o`?nW5h2_%HN&N__oC>!`;^)-uQ&2|3n&heKw!)3XpU>x6DdO z*>n~{>+hx6RcPXG7vDonO|8^Cxu<)YY3-RmuG5A`dj*-XR&E-S- z7Znv1Kq&s>VuP&4^ua}OQPC(s=(;+!KDhn&@86$4EKuOc!SL!c3o;S={#kV$@PUA1 z-|F8d%K%!rz*@g*HaRJ&vg7Wmu#i>84y`W_OmYGG6=0|z7&hE@19sPstx)=-QZJp~!URKI4lefC+`M@z|6W4qfkCzAr zBg=UYA~aI#gefsa;K;yn)uS^n3Ka%noECxZ_=Gw&5Bqj6N26$f9`3;%m~0@8gWSWzJej1wB!b`s1_3B`}y z$QGZow@|VcM<^1%TN#?<=H#?N_1M3idv$OoLBOD^1eK!!KOpVI$A;lhL$m@#{-H1D zItsfzNO7U;2e;DM*J~%&r1E8@4?RaUo)Kd6#{}5bINjARw9Z&5^9fhg=aju=i~qJ< z?pk~PIhB$^RwxRTllPW=*$w`b9PdoYt~K0qDcJk0bz(uQKcUk7KxhvSn~;po)P|^+ z8;Nz9Oi-aHHxWQA6^Y#RpMZYQq%+n;9xfMKUp>4B8ymJV{me&m#>`UvqVwIG_2r`Y zXLQ2Kq$?}O1Tonf%1b`e(RLeoQPtrsy;r%2R$OQkvkoIS(~`+CjIB8kPQPf5==-2e z7X}Oo4Qwy)1@^_jNR3C)=#K-988iuC%}%-H+yC9}MdhtDkgd>+imNdIt(Kl0to%=(kE-51FuuNai(+QPBw@SOl5^z|dy zm@hcRzf9`kPu_afle*&X2Dr*;h7Z)?LQ*{A_|uzE4M;OKRY8HoH+-H=4eS7WaAHgs zx2!H9L^4c5L_v9kI)+is1W_f~@en2j^N-8r_#cu*mt(TaG_Cj-mlWp@Xi?GE; zkZ=8zH!^RFzBZz0Dd-mE(WRhD?UetcRP>XYG4iNz(k788##gGk{#&?R(x{t@LECka z^Ji=aVgS-+G{x8_kvff55TsiK~sGHG> zk>}As1VCIn?GQ}7Jrws|yA{8kjeFd7Zb=ikJ2+K-Jl(UCEn5BQPt*4k(zfb2?b)|Z z!(&&80iFcQey&@!wsdYkUC*LXV#|;pqWwqbd*Zk9e&y}f$`|TK)8sri^M3aZ#S zO6BEZ4YKq;@6|B-7uOy&lgDc&j%Z^QvzckAEQ@-n_GdPEH7W!|Y;%{qWoL#*UpYsPtLXHA?*75E0RBBK(B2oQg<0vAKXM-xDA4>4p~HDe?&Zq&RJ(VpnGeALId=+%C{0lI1*VK zz*c1ds8G$?y#QEPW0}IUd#=9)89k~A2AYV`k-Ri65?`=aKgQX7AqxVww)q-WeU8sn zlMOhOG^$24Obbelga4TO|jGr;~EO8FFDy#!g{ z+;yQ4&AIsn7OqAuIh z=X;A898qDAPrkm(G*es737Y!W_#M_$ayxb%$uHBR099BX!gc?rMp7Yqz2Tz)u;2lp zSusFQ{3qTkDLJ|EV|nBEsWEY#Qf>Qh z+i8jGiFH=0nWAo$ZNNcl*E*Z}H_*rQyuI}C8m?U_dFgp8MrP#n11%rj_U(7=(oRwF z*KEOt*7{vts${B-Bx(*tI$0=4O-1GH)%?kIR(5)JdS)gXQ`w*$&mx&%RAuX*sJ(l; zdwTlycCVv6zRb&+WFSL^?|Hq}j)nEGuSOC^SYH3tflXpKxWS;@Xy;jU z*fKYgmiHXC)|wH+oee!F#WRqkizx^#NHM(EN0t7vgFOQii`kmqGt zm^Os%Ntm-xHTCST_R(Vzo{yL@;U&)DaC?pB*7{%`1!y~Nrv{2ekn>mm1TqMzZ!4=W zpO)}Kqk>-si?Wyys?nrA>9ysiq=XfV#$3j!Kkwr}>z`5ffs9_WU0tPK25%^ol<0yO zr~M=XKB-r&lw)lC&aw{t4h&Z&>{KbDn^`$j@K_#S?;nUC&xCyC%s6aMVa!&Te1`zr)=zgd^(SJz^VwBg({Ed8=UwOIM4>tzJR}e9hoiS!LKzbZpJkR6a5|>eK{&nf`;*41~3+OsC+3 zeAmm@lXEwWW%dEId=e5!m0w* zar5lEVL(OANKYS;SE60+sL>#_q_73&sn?8zhucOfb8soFxx`OBatLlhC}U5`CE~>w z*9;y7lXD=gnTTefqgM1Jd9+30MJlO6d(1XDUSX@rZKmr4C5-9A` zG#wdCHZ*scJv2vwIaF@iKjMhcj2L8?TE)plIm#T0S?~yhgeFir20T&a8=j-yqm{6dB$6Ys`@Ja($gbpnT`CUg^?YcYX2oyVj8u_c}-zw=Zg0T*7SMG0(uO^e%1l#Yfc1}cA+I_s@Scr&-;K%-? z-m3u5?*9Pyc!*fN#c)y}0qObmEfBw0YHBOYcgp?OZFGX!#rQ}HUUN$K**_L>|Fn{u&kHGunVSYFd1=*gLL>&PGb-_C|r_>KY|Tpifu_Cg$xZC*iCJ-+R3mu;-rE?G-?oq zpK`=$SBc0*)gb@Wy0D35Btjj>xne%C-Um)-bWlo{BUEga*gHXL=LHl<2wA>npo2Co z3NoNi|6(_wKpl6^YvL*NfxajKJM{VAELCZXah+tgc#X&K~!w3lRPPvqe1 zAbk$d;WAz+;f4s*`q6-k>BnPGB%(mk*3k1wVX$tDe{lVNmfr*F0S-6@oBK5+6`DcLE-Hve*BK$Nb>$c7tT&iV@wYltI(C&S+kgAoaupH6=)krSXNtTw7Smh&XkBo1`dPVsLZ zhCLCEIH}Rk%1}t?(zm19Fkmd48ODr7FL@7B0(o!6^&D;G{yrO7)5Y7k)VgUhljo&p zZ>v^#MmV2hXKLZHPTKSo>3N+_UpP3L)$g)Ei53J&6E1Rg3i4h2aYKWUPaUti zyKeo?Q`r`qs0n83$%;$e#CQm;i1J++%q+ZHJ-+{FtvwyBGxo78?fU7JX>1&-k^iCo zG9=gMX!A&UOFqB&c3rLB^^o~})Q#LC8#9 zDGHVth60&tMqF744HStxPmuRK9Ouygs}czG4sg3uVU31SY(A7w8G(jAPCDjyrUzN# zj4I`j(!{!V;ROi|J?%LG(JB!tVE02W!UYrhY;Ss3_$S806%BOEcRfe@a4AEB45j6> zUP+1?|Do7<#-r6{>5MBkqm>c(HNifu*XB{8#dBAmgU?Xrlp+mWxeVh$&s`_u&-r?& zx}i(~r7?>~4L~RwrCoX%o~GgWNN}>=Cc=rexTHvdi%RdW3UjNZkyi@vZ2|@Hq>ng(Tfho#v$L<-^HT7 zE!%trZ;+1q9DVgW>0Hj|$$Ev3Y?v(hd6PT5D`d1wNxqSE{&4@3z1Z%5r8p&uBpqD%R{9+Ux(E5_cU?@(CD1*p1 zMDQC}o?G`a-THHO)6v?`-WB?4%*IJe87;RJMyLc2ET#2e7YvyMgS>}zJj+uj+t+j% z;n*u0B1{NiP*Envq?V!cZJ-odo~1C4-|8deLH!HIicE_Fa95x^)_doH5>O&inhAtA zBv5yZNghEWM*}!zD`Y7LaP~%#M+`^+Nva$hK-e{WkB{!`AvzaNGK%nZxa|;HN(~ zO_%yE=}5tir-^A?h8@}LvevAI`nqKWN9b9@+YrB-eqcuUjgHC}4OC+Dd0BbYPajrn zyM<~=a?y*MlN3zfOAM7xQcZmZWu@^?&tWc)Bp@KkDEhfzWiRyb2Jj|2Z9M72aEQq5jyvZdCZ8vR_JHv^RO{3~V*^#l!7 zm?l$b68rE0z&w_c#)395zHni%XC%%;v_S;@gv9P%4N>J`QYoD+SInrWuW+)6$-x2@ zQqn#un2+KUidNU4=!bVRS|c^R2HlhjBDE2lpF`FJmg+FH0yO2u$-d4L^HuC$sWv)$j2f+k zHhKp1ZVI)T&XM7eH_`}?QABhbISXZAc4Z$BrHg-Vrg^$#RO>|W{keqgwTDr&VC7vW z=})iO>*czG)nEOLw`(U}q^=8M(fNpQ(-Kq&oMF`m-X$>iDtSXTj-^Y?saNl@OCdD^WQ%gWklI)sj0v;wBR?^kO#~+qvFPdSp2 zsLzFB0<()XtaaQmG$L4hi}~_j`y59`DP?YJYE(AH2(olP!0_k`fZ`tlBm%-W-ZrJ4 z=X=@TZ{@aUgQ{@fkkifP9By8+2Rz%rG19lgn4)cc{e91uyCt{AyPGlPgB}L57bl<` zKq*KFYE`0a0k)&VPpT9qDNG7ib}p{kzP;)jDZv(-Dr9~9%IQT`+I!7+mZ71r!XKGz zkLa16zo@hSb$SFJPS9X-dw2q2N>j+yE_B&!O<0S`3?)C1p@`sxSW6Asz0xRuvi2F3 zFu}c{V2dlm1f@7vC2{I7w#t=UbB=C}pBu%JWhUU9QY^s87 z72t-&F!M^QkDFN*F+pLx>yF4V61Im<`$!>bx?_t}FHIv65X1&98-#2}+%z9471Uc% z3HFG&BSV0J{PSWX&xszI*xo9Z3ZY z7WQ-1rocIQh*M# z!s@|wZll*ZCF^tk?_kX&?X;Fu6Z&;lmP~NX@v-X`x4m)R^JQUshsd|hw~54uf3{9I zI3D4PJ{PTXy1gphVjuhC(;W#mD)r~f;e&$UWz~gGhxx>CLrWD=4sP}%~06fby` zuGeDgbbS6V-sD2RH+}Q zsR!W-@?K+OLCnvyXn}_oL?H)(N#GyhU}5!jtrDMGB9W$=QZ=02SRTjPN%a33!VqO2 zDE%QYupkywC`4LKHX;;B)s>?KT5BaReXgEMuKGR@BJ3c0#b4hAniyRVC6s`&7vj^q zh>y%AgnwZM7_D$pT+$FgdVbP=y3ALHiN%0dQ)$C`V0c(kno3NHj-Fkcy6~e>_PoON z8Ex^G1u3FP+yvSX3zgPtyfFMMC8ZiPjy|skHcRAOiza%lq*B4)hohxAzK2|lc^~W@ zw**LiOs$*VhS`oV(nzO)B0)wmvB3$W8`0;~W5s4J4NX+e?`d7WwyY_mrlz&%-t5>k zaN1>Ec>SSR1g^Qod1<6PFQU3rwqT-ZM~vi2+7PLeT7%t2k=eyS0>;IOYC+g!;c}+| za2j*s2M~48ym8uHN0$9iqfF3s`RoqxM0M>@iFjw;vVp2GOmTc^6bL5xk6o1vIXX&B zy@Uv-2o4l;8)x}T4g<{CbbJa}Mo*NXJeXAasN-gBnAD(7YhHzZdW;ypF4OoUH6%v}4aJYLIW-E`RLvHC zE}9f+V1ugMK5|CC$uPE|%?IU8CKWn`v>#KtoTt3a#MDwVL(^wZmJI2bLpSw#w@L=C zYk3|lo^|{=;(1yHgL6noYlha-_M>BZNY;+HQB_`nDLe`mjq)J1O$kDLg1q3=YKj36 zVN#9&81kWkGcW;Pgj7KxU^TckXN-1~sD5HLhE2jXpe5{Qd>&)0d3HjCCR~DWoIo8W z^o=1`_X{(~FeWJHmnrQkUd#zdr7L*$KGn~uC&GP9+5(XLmFd23)3>yy@CbgSBNVGk3zOoJ5J}aV2&3MjrbURO;t1suJ)e&Wz-j8v zotM9#)itho%&yG~Y|XP4Pqo(}g}P~EJ>QYVFhRa#@kp|h_qTPwB31qLof_|z3gMjY zMq5#<;d@PG#c}6_6Oe~vd$I^XjXhy&u7R7=_bciNIU~B8=2D~Rmpyh+1b_?(;N3Qy z?rGnbaa8@RwZ5(!6PvC3o+^Nnb86Qvy&kDrtZp+K$T_!!|}rkXfh(C0M9Ik(X}u(K`J`E~SP!MU=4DJ$nsE!@ z0yyv(oglGjvV-2{xP+&fQ$vu@3$OxsRnojfj)Wuw!b_T<0l3aZ#^k?aR&~7rx_K1+ zOV<`r%a`4EAq})}U}7&1(Ru^OUUQy%C<_aERl03 zTilqed$6v!{Kxk6oFG#Ca7~OnU0<}4>fwQjrHvs<-*FkpE}Zqv&Cw7}$Nj10GQjD6%t0#%?~jtZ+8{Cb!8_-csy-tO*{=>2f*C-`bF zJ4&ccn{B62|F-quWJe40zdTUC8duC4 zK*&B(rA+PZ4d&7l!QN!zypj4GkQ2oh{_QlWkW;|mPv5kh@zrK(KI7n~8c%vmNB0Sq zh>3|84jjRVCCL$#b<*+jHd7@$B<*&R1AsVy#O_G(YT^Bq7+)G`rYm) zyi9@wHOqsr7zbW5!E+{;>v(yGZ8&CgFsO2kl3Z-2?`uB4S}9G{?0i%t-&Y&(U%@g# z&$Plb?0S{=CO?G2#n9X5S&pJ1`v1-!nTdN|{IzX(nGa6VZo1*i5gKG3f*tftZio`v zHt?6;zEg0&VNs0YL0co{ug5YlAm1}kTT$JhYc$%|cf3>S}W9T z?&sxS_bFxfY$K42KlbsOVlLSv%dV_UYbf;-jZg})IGe%-)87fAPEsHdFN&En(e{0LOqmwBQX_e{k$Q3i z7E@+UY!XN50r)!5`W$=9+cvh=)|WRww~VTGGHe?cO&O`N%<^Dg!Jq@5gO-=}@9s|p z)Xs=#s+x)m#pRe*uPMw>!8Z1=Wfc7in`K4<$+Y;gT~n^V5i z=)c>}HX10k%vycH!K2)t+?k-v4|z8@{7A7L{gmrYaBCx%l4X5O_tXN5P+CMD z^+_w@vut?V#jftS7M+mNOEyYXo2B?`*Rt)s_?FtMIoj?mjLlbzL=-u@KbHWrxu%dS z<2Up3PR`{A!sm>?2C1|D^?5frXhudw`PA|Ja{0c!z5Vi0gCzft3XWS6mXo>N(KL3O^WT;eO{jm%vlo&f}zV<>UfF@YSNQ=V5nmiPw zKKEs<8%9moo(l)F1c)H3h7Rkg>9iV`JcrY79<((bp?vRs%fH^IFFW=FS2WUT{nuT$ zva9TF$Tx6bE?`17j?)$BUtC7Y*dmS0ms1DfntUl@W`wb+gS%Y$r9!(Klmn=N>#%F! z*ORc?QE=>bHTgGx;SEZlr9^_fOukCm$+$isM`!{A!;A2|>^nE{!UT8$4V+A0Z(rmz zbu3fRvy4-hz~SkJVoK&qIh{3@31Uw28TTC-(J!A}mwGW=>3#HDBd5-yr7=KEmGK{oRBDdQ8SM^Z-9>x1+6oqwN}PL`fu5s{ zwJhYb0hnVFz?3|H-nUtrdNf=)hqf60(kFwizL6F`5371!-_E+GoPA{#s81Lw_2`rm zL_y4D=53M`bPvU`eo`?Q#Gpl0uUY8Ev3EX5UflYfrIabRPS)t}#s*dTk0e*_hR9E-$bsMl#7nPW8$>c~Ppd;5cXmQ9<@qC7xepW#7#5a~gw4 z@RFdcppUGeWIhqBt@k(m3thA{{>fn8_PC@e0ZTJWv6Vk<2e>q1Feg-$*d+ z6&%va9w>Tp{%Dr%_l#2AkSwjdP$i4wl2%!w((_VGT#03#jIFF(s$kgbe<>8~LA+x~ z^#R2K=U>gOXw2uNrrOzq%JW(y5`Z^_9>vnzX}!Sc9n75*ecki{EfIM^{E@fR{Sb!H zAY~4dRMBDeD1j0hEU)vsCeg2LO*p42(Ux_WX+~@eo2d$*_N8QLAF-c0#S4>lb32Zb zLr*nD5W39BHU1gr?<`9qrd4z}fZ-OO@KselF2G_ox{g@E=HnB?m&U5lFt7)y=MWh- zPpAl$5tA}B2EEEC^x^R*alLiw%R` z2JUm~!%_aa6Lqyo)fTtSf0r)gQMdAH4^mS;czSyOw(FsZ?{iGuX!~hHJZ{52Jo$lg zc@X*I3-+2uOlsT7s1WE$aQ~?bLkwJ+@qEF96!Qlksemn0qIJk2DSq=4LQp1Vv-$6N z_@QM8jXjC;FHkKO$O;Ae$5aU8e=;cq0}@e%PH>69Apw{~0RT48_OFZzz2DXGr3|C9 z)>oW5^x-2teqlxo#Vt_%uuk>>DybeIxrbW|9}6E5=6j+v^(-6?G5OlGw+JUcz~VjB zQHaGT*_uUahevA0YHMtw!MakKLD&|0t`T{&2L#+LC()sk2*uyJ{zx;9Rd*xhawN45P~-x%B5&`CdhQRnE6!6Yz#NI8o*q*-FklJH zeQ%etWd|XKYAXPtsb?Dy+sY8}_`KNg2rw+91199mOw{a7d3iaTYL+twV}k~m@j&Z$ zZ?Q33%qK0is_Cyje4);2?5&O=z{b4(6R-AyE($26&Ckz|s}dVuf|u&F&CH+G%3r*S z+7t|0*vz5L1h7JEu^NhGvoGHt!<&OyKrs@OB)cMA$=j8oIY_X8<{>dzY_7~?P8Bgi z1_aj^;pP4OiE%A=sRdl7PKUM1Yk-@p@L;$g6p2rfQ!N_cpmf1nP|3k@xX#l9oW-u_ z6{@!AKoG{8pQK-BD!*Mf`2AbpW+L{t0v1o|>ZT{j5UwvxzmGoXZzgxxaUv6~8)mSQ2upw~A{vlfWXd$&19SFO#IdU>N{` zS9RIK+CAm>uk)1pOmP$;Uxr_RLe3qv&@%ETsb?!{29&q5evqR8OXsuEub6h3emx!o{&HE&fR!W^8*{!eV4*< zXX9iS60Q1oz0SjTC`lOow?Gqime(tDB$*Uh{b{uBWR1`ukCdLNde1_68`&t(=y%Y! z*kNliW_7>%??i`l*6m~4=ycyl+gGgd5#&_rLji1Z!Gu_}v5-fBAl_PIC+3bv4*iQq zuC0%%gv`I`=v~8%{>4W&B!hRcLR|6?n))0D|0-674Wl^=5Yc4u1&(AjR<^WXuCx9B zcG4BbJ}B4c%&L@i5* z@Hl`Qk4TudP(g26aM)A7z2d&|Kz;68pjO%%hehzng3spbtge@`F0w=;K+F*e1&O>g zX6l0285ObuQQMf*K{-*wmtqaRmd*1O&*;wdN6`;61mHa%S;GwwR0WonkZw+zIbj&C1F)uGD#hDjo3fXu_Kt zt@F04;A`6AA>c_m)Ok-8kA0Bn~A^EMSQQ^lmBvbu6b|wN3un^du#v< z%1vWfzJ|S|*;edUW;F_^>{+n-vcN}jbe5YWf_OXleO?wMPU;W@l6XK&vzjY5gj#WO z0ZyiaG0_MqDQq&T!!@p!M5BIx4nRUCJm6%7I*V>&wne!x`p?B%IX2;eusAcTo^v?n zDRRWeXol*`_96HaKExOBVOy`y^(h4s>i&l5 zS99_&@s-PZiuZwbBf3at8jtzH;Wy3T2#K&FwN0ySI&HP3KfUBPUPSLx(J~q~#c-qo zqEl5*_Gvh?#LU6PiAZAuaR>=MRh4>AtNNBcPC6AW=W4!3V5qx#H*2rIgSIwXg=&O#8-zvJ?mB4H%Yz`+^+ zCKux}tu|0>vEV_;Qo-MoN!sji%@mn%=aFAFv*y%vaF-V-oxc9QI9)cyg%8jA08@>2 zYE~-1ZYF!Wp@bC}OD3~@Ic|(clcogy1BSrhuFh3oF1rEc0 zLmLyIC58kuhmz(6;KphM4PoWDjb4&b@ItWFVeA1?>flbWlDddL-GI@&#%o01ZPPugMh5dO_v`q%~jZf!8W+G;Gv|1^qgE$9T`fs01()j0WKfk?&N zNjn3p&IN%V#@a5#{yF$ve0?!$@3jg5el9BSKLhyi|HaEydu96`tNsKBZ5LU7_v_kD z{nFg+XXC~<3jpl9&hX%FK3&W?vdm=rg7J28#rrN-HG_CHmhtUUstSgkROFrHE1Iv+ z4b0E_;nCNM_JQ&XIY<1xJS1X-ARbL!eq6dP0y)tjQ9ftkC6_nkJKNkm7?*3eu3PsF zA5wA8!RvI?1lL97Gq=iSF{Uo{U4Coyq;JRVPim@gpF4a*zuHClAV)3vp_>U+TfS0G z!Hd@&f@Z_-%qOn#x0D#<&uYXJ(hEmCS0C{Qg6jguoyoK%N`8O%OdfW)eKYxn6kWG` zWxKL6cN;x+a6j4g#%sUKPB&Q<=?0>SObX(I*KDRfND!=%f)SI@es6C$*x7Rj8nlhS z_aH2i@;NwEA3`nsCA*)$e$D+yvNIf^T5d5R?6`JV)5F8~^Lpg?=5nq?4p?IxeLfSu zwy^2>lG#$3o~2i%K;49QD%eeDDuGLy)B6h;F8}fmKX0{4Q3@MSnnp?|`hg_qKHU0| zgP#4rklU=ySj?_uP3#6tc18wZBLmFHdGB<~&Bu%jSP~Dq!(NX>-`UisI|q6}>So)he5@i3v8|Sv;yO_6=s7 zlob#9h(2&bg*J|m7?h)ahkR{;D<|~Un2s&$=SNBA=t4gSf4VhyDqNTtQkkpI>)xc53N|GL>m@I3ptQ_u4AwZ~mkYVex@CJn$In^ph zr%@-pp0>Uqee|kzZi|rapoUJZVS#HyGK{FGxPh}d6LZ;g;>ZOYAy?M?rCpP*`mF)OS2EEKd*|*(2+|_PiuoBkIG)wzyC^rN8+`u^7)z za=POfx!3v7ABgFC58V^+1xaX(CO<{ZJA*R9*O?mmv>K4DJOgQ&bKk$bOtm4c2w5;l z`UgHpnn{T^7#LwLKx-(`YU*pq$gme7L1|ht3Q8b|s25N2UKZ4Ov2spOPnkxthBw0M zXw>6;Il_s1hZ5ASn&E=Env8H8edU1aucbhsFG?|RlB>coC4(f!*i5(OI%S=xl(6>+p}1B;*ujEOl899G5woA63rpHn(w z*4d(GYqfahZ+r5QHvhR2enP(ny`s@*u1M(j5JT*z-MY4x4lxvUQq%hJnsV$?oI{${ zg}^Nek1H_8$gxsL{}u6KrF%eYp3^TR=v`8d4T4PsM<;>uiG_OuUkRi*;zm#b(JjrO zKx({H9`keTH58tCVJKK$lnhP=K|T9$yVG%h*cE?b?0ZwH{n7#LSyF=d>2SYg1};nM zT@tyk>(9bR+N4F#7HUM{w#mJFXOsEr<^9htW<4X{{fU0R&8)9JH~aK`+m0RPxImHq zbXT%h2sfDKL3KD;H3>+aDTJ2I*$=xt-BdxCu=ES=4Fi)65CPB(=l*#HXTQ!E~tNRD5%V0-n3%vqOGkz%wds~j7s{53J=w!L;luf zn`u_E-2yDxeR^+f^8}s{Hyknha^$N1&di^oeXakVwj*j`=#irYT)1dJ^ zqV~0Z-|BHVo(tfbGl9_v8LzBmr`xlayW*cDpy3iNQ?I^5J9>QitK&SPI`xvH%|XEZVA~KAMWz__H_hQGGPI23yWLUV0VeJGv&H;4&=Og-CE@xa2?` z{ah$EF5}C*-JdmP74s?C;ySe`mLG&$@jUG@7E4Oc9T5rzF^Q8J6c0S5mE;}U=69VJ zZtX2miA08ZppajO1`3h*@w58GL?9Rmjd&OPlTWhvWz3yi4 zuzbts_+Ps94_YZZD2lXa*Pq4C!zAAtZxGzkkKk-L6v_-PQVeel)O^`L^NjwcoViZ|r+mRO9mRB)j=) z+3PWI6TSA^F5aHTbf5VBYOGYT$s{k%Zn3}eI*7mC@1LC$ZT=sJ(Xo+re>wZuIQQY# zzuUFH)$Si(Gu~di-3(CM-*0kdCe8$pKI6Xc8M~hyN#R9KU}=A>7rki4^?SgsfQ!!E zsd`GF%~j=WL;UZx7URTkyk?`g-prF=ltMo3^XB!Tr%O&_IHbO7KA#2+TKB4WW-Rq9 zANOJci{R|D=_Nhn*>z(g>`VL|zGk;>V=l|0+SjjJZrL(jpG=O{=F8gqQ((bqP)>Pd zx!tpfPIjP3r;BYp{#ti{BQqe3UM}xhhgWV-d#@nH6 z<4p9dw3PY6TFN61bB%6XmH`q4e-M+WX;(!5*H*`i@99u?$%osE&z9|$Heb@KJgK_D zKisKi3KY_u{sSUG-M*xx0%gL4t#euF_aAuXnMXf2v-Pr@ZhiOmE3Xr; zoGS->^&!YnhPl=Ngcq>LB7_P?sF_jKRWt(dkoir7Ab4r|@Yb)@f9vmA-j2U)1f00m z>g^uVD+L28lp&N(0KgI`6dk4s01u!L6-ba6X9$81C|<~-E1};9TYz^2GEiVf5N82b z5e@2ubPXyECeO-=Ns!b)BLWE|2GWQi4guXraZ`Xn6!Z}?L{u`E9&>>lR22vTUN3q{ zDV1f}sZ*yG7Z;s#fo~K7Lotp>MDjcjZn&Y11g{A-cKPf$S_N;WYBF~-q1h=4@e zd-v=!hYlV-eZ#faI9HxKKUb9YA7ZetWwoU8ds9aj%~A~Hg7zAM8$E=2@01*fd5dhHhLWDXpNt%!%r8Nz7pa3u^ z>53qT_aqL*vjxr(K%Dc!0G`1!vv@BcB95K2y%)~Z>y>Bz=;_Jr>n;2FL+6WbUkC>^ z@!%9K$_s;d8RSBtk*HZoqC_deEc4bn9b-L>E0w5~ zIZZHLjXW^3(gX$iB#Kc}K1>oo+!sFRIF8u|Dx_y-Awnb( zcHV;;J(rt0OBNxFkxn3Apv17%OWfC zl}=kwB2sY_Uo@Ove|qrB3BVhEd|j4yYJ75{-Z*gJz}(`(Rl9aoll0J`gWqxY2NxC> zpL_oKN5A;_%XVzrx_#&I<43N$?yCRv$xlA>%$_}`&iwF?{>YIRk2qKU!q5NG9e3PG zLJvOhyWji09|2(NY@=R_8(fs?)oeC?{^x(`JHP8A`}ZG6lGHhO=FFJ@fP&$YZ;TmP(gprnNN}}~Cej2R zKpR|{UjfI}B=z1e&7GS&Gk4jpt?$0`T~R&K5vB>$YYE%@Y_EOn_?gm+AelHZ6os1~ zY4A@eji{K{P|O5CWXskqv+Ji9me0;Dv`IBmP3@KCc59_ltthRkX(g#tj8dsd$~+VA z3~BJtFZxTX%fUPe)|le~01cEXhtRMK)W+~m2mHywuObW%y!Ilb+4j5Mxg#$g{oEIx z=ofa+p%<6C{d%=li>tHinpf@KwsB_q`m1+MPfaCCXMJW*q6cg$M2#qbLIPGeplgUl zaEP&?km&#j69fnnIbj@58H1Mf*Aq{;2nX~v$K|k8^mU#e9^AJN7Z)%5`cl=-S2+IK zt9s?w* zm@7Lbrm#??F5Xsxwl5<9h{)ENjT`*dEfOpxU-8s}#2`c$9YwU(igc@$P0mzm6>e9W z>cdw9;-yYVm6?t$NvS|6MiC(3c5dbu^DQ1WSEBuO+@EDn^t($6p6>O}I!l6H9FaB< z$am)k0>4)_G$D6l*xOmsc zo?V@9&!66UeyQdHw--ea(OWNyRN(wV(38C6(}^%rsMg%FZ>?aFQoiMBv#&W2p!z1G zz4ABJ+Z4f6zIF=`L0DYzO1G?zkrckd7R(j=*58DDi^f{r{I_HXqE;BK**d-CuK>tm zMeG~cLsE>0K}Q-X6siIvXoOe?1cD$ghlFFTXmmZP!P>|F2F@ukZKzL8%;Gx@p8v6AsRyfvr6N z9?I|v)Ub1_LOllndZ*?!&tNKmU)y_2HI4EnTIQv`;6BS|mcwsCf>-l(LFN>WdgdaXJ+F;;I>k~A{L=qS=g zBcTwHAwY$Mg1{_>6bOO>G7;%SFbK6NAgb1?skN1247@9|yw~r0@26+ijZI9RICct< zj-Ec{yv=j3jIlw6!vLco!0ha7=3ez`ZZLgQTlkL4SA}2;Yas#z0TN~*MM0H_2qlyp zkP$)~28CH0SXo{D>Qm2`p1$Mm_b$!NJ$vwQrP_$KTyf>jjT>fcS)N~9I&u2^i4!MK zbhTRT_1bx6TfI)BQBeS^?JfeYwtC$xS41dMZ`7tH$Hy9ttvhBm@7VCv6Z=<}+PBF0Y z2?7-gAj>KceM~wMURq+@pL>|KHVz1HdYz}RYDIuvI93J zpptP^Mh>)QiCMIm!!&po=a~-n*>23V=Vg%ry8E=71pdZ>#4xd zcxj+nr41k|Z2(X_Ba)(#D~Nc{q_v1Jdl9OqNxN76<6r!}z58B7^wl&XBCSDK+TDT( zsudF%WxaHZu&hZhx5h+BK1#$ylx18L+_qU-i>|nA>Ng+wqgJ=|Z$I(Bv{u_C1Az?K zmVwNOL7J2q2Xr4{83e+RE(t)Wh8lvTl-Ak=PnYo7I35`|5m8VLLIhGO;7$Ml2!H|_ zkVg%es#Xc~O$W<42EZr5lav@BHrXo;!DTW@h^FuYBd?sgtX# zE$_Y2=C?of8`_XE(a-$M&u-ql>DaMjTB$$y{okurt1Qx}*MIN_f8gPVA2wQRt^eC^ z|2JdI%F0T$x~Ed9EG#T&t-beZ*nS+*jGS}fku^GUgN8(SvWRF@5$OzA0~ck+>}Q(I zMy)Eqd9Ud7?7qGGmR4K0zUS6EZ@ozv#XDz z>g?H*0C8CI-Sqm|ojWe;b$e&dE-Ez}*I?gXYfB5)AUw&FC+B)65V%OHY?s(5#x88y=XVxk(fC2=5;4v9Q@suL; zC|WS6Ap;EZ3<)L#0w`V$<{Jfw&cpI^M6o74+I# zMNAJHM z?z`{K`|o}5=RS4y)TYY$)BXSLhxXlf-<|j4qp$5^f_UBE{*9-f@a9No85sWj+S~8m zJ$qYIA73iI!tQTB`N!`)cX%nOY4HF6ilZ$Bq=h(vFmbP4DUpE1T)nGEQ|$L&Iad<^ zL~f=IikJCgTs6xpy)j>@*ORzM?L2w;gLp&~0U`=^T&$vK{s^9asJ}5I9mD02{Hw+J zV>T}{z3f;4I$=R{VgV45goTI@2pI?J+``Uz=bd(gD+_zzfoJ8Kt}J`!%Ul6Paka-T zIlL#HJGH#?rm1&)C_nmqx_@6%lt{|?LO_55t(rv0iPwO#hOZ$Y5k_BVfB9H(Ji_>` z#zR5?2X0DFesJu4--ay$0Z@n;^M9P1?=uf|b>H~2{NUvHj4@W;=nkR)61YO1eW2xv z3$A3NKm>20Hm$GxNJCzR`wt?ZBRulC?&6U`$1g*k2+z6dqmAmM_D){M1o?KnOhi#s zmT%qOt$-+ud->t{)@RkrO<#!UIUldxHdejGbN+f3(6zw|K!lJ3w`l}e8=MmmP?#l( zbe6UM^S}GA5B>K)xqQR)U-{m<#~U%1*15hbTr5sUs4>za?4U1w5{f9fZu7<)cJA2o z{0sl#XYTvHAN|``U4KK?%OGH_2Wi9LMk2(ao$&=o;&5}z07}3I@T#mqU0ehiF$SM` zu6_1=t~I^Irhfng?`5oMZoPTzZ9dBX@F5~m6z$ltb$oK{$P35k=jR8Y&bQ;zPzs5F z02D!t5XImeA^;Lv9?&3tD3bu7fM)O|mN{izEDK>j5Z)P7lXysN49b{n%OXywRxxE! zdRzK#hdlZ;mLw81z#2FQ6i@`LU{G=v00gC=rlGW81NE3tRRq=pnM*LL8vzpe@O0AMM8`a2!qJq{$ zpcQIGT8SbshLM6oI{<(nkO5;@0e}M1f`p17Mr2dLDmYH8t(HZRW!<>Foy8b4cmDkJ z_++=$UGghT5@}tsFUn$Rxdlj9UVHVcDf-9=dKpNJU2P=5^pA?1W)>?%q zL}VWLIl-Voa;Znr8fMi?&5%aN7ZFl~vgVA4z&yaMhUsCAbJB%rcF+hOq~l6at(r1R zx0j8cQ=abBEwZ~&s?pmoRyz`iH+48U5@3?V1d_( zI}!n-aqqtVxjAdh%kS^LiGc{-Nu!}|zM=Y>uZ;jSDerAPu1t=P_4{1`Nn#@+4pGOk zSgV1w#?(Zqj=Z;}<7TCi=RIfpWv8gd5r`%hV~mbXx8E;{Vqka*1GHLTX?$JCJFJ;8 zNNLYr5uwr^&JPto^7K5B^m;|5np#)%3)YHE ztckGGE6UQvk!B=jEPzQvH6;)+G1VdiaapZKw)B7~zMPpE`_h-5|H)7M#~=TnJ~}mC zv(68?$^wCrgNP9BTnQ5xkx{}DWY*RSKNzL7F*=GWX`04yUKC+s413s70|^neR^EF> z%IH7_0s$dXdI&uU^Cb}m=cK^c9Q2Jw(qF@R{@P>%5yRvegjJat33(_h8hY?XYg<}P z+Eh#>tyF8(G)=%W5*lMVoo=VIyx4D*STC-y(Pc=Y&erMYe6)@!f0Z1-i`CnhJm z-R_AKr;E~gW)NAoW2f`Jv{ppcjZO8}b$fY!?9{35(HD<)RS`z9u47h33CsR%SF zg$N+*MH`JoDpKfd;jFVx*gGU~?AeF>(4aOZs#Pl@)GM9v1roV{XiQFaes87Nt1x-> zJsxB!D|*w8vA-_jE`@l$NypbpQ>B^!qEd=IE3H{({Th))qxEHZ~SU_C-A6kq|Asw5hN*8(?NZHi{~dGA8PZtwehB^mub(A}fkz zTJ_wYqKUKT&OP|RA1|Ih_ftRqzckWxsn;r<%d;YHcdJS2t#!_c1QEqSCP9jnCKU7{ zfM~5>H$8jBmDk6K+J9&-tFh_vi8Lx+Jous)XN-y~Nt#q*ZJM>l#KgEl>UVqf#&}*X zEwp-hSrE~vW*OeXfLI-7D+)UY1OU8fB@qFXApPlFFRD~d9D4T4UwL}Zp5yzE&h?oH z8(Y^Y@5y@`YYiZzAuFwQ$O_M_xP6~}_AkD0;QPMw>F@o>T{}1Igdv27MI*5gD8RsF zCIkZTz(^2;T?Bwb6AMEF5&(qB0(_&*hlU>o!tyelI01;z>A=LqH~Ja?0N~zxAH3&* zd;Y;a5B|~v*VP;P=YQkcefu8JnuYuT0RR9=L_t)1_~AS6!bbrfy&v#@`j@c1wgHTG zWw!s(1suxL-S_aFS1(Ne!hgLvsk-Hba!+Ukm3#4G+7kuXWsoEw@9D%r>U_Fe@5+jD z(>nUSrKO`q?hsBEnFC}HkAuwup;Dv~5pW=`Iz&+c5;A-1n1F@^HSvQqK@f=mJWw(* zts0Zcq_xSdetKiCyUgBg=$%SY>8u8_%{@l_vfy!=}eAdQPhisN7EMOAv){g((_{{A|ydlN4H+dkg) zu6J2$_w3m-A|k)VLJ)Q7mXW)axchYDR)^7hA6s6aE-q5-Uz4_3T53pJS z0A`;i)w%gIKl{(`Keq4Shu(F|ZM(O5o0YvTmQHJqj2beQ$e@o*14&0Zb=nw;w4(RD z_m*uZ&i>&if3^L6AAi>!cl9$jy7slyWf^!C1i;{s20fDO8`?gGDjR?VaP!)CLWF0} z75ff#lbGIu8~D=7hS}t{TgKjM*YEcaxBx-qSXkIQN+P9639vZVZ(*5w ztZ=O<-U>Jb2Lhrr5Ci+r)CP(~6KDZTSc;$k5~>75z%2+|*bc)bjiS+mm;P#uSy)&& ze*AdYftF=C!W095b1qbNMg<)hZpjfbiXv<6!otGj5Eje32uS+7>&Y8o}_mB>WZYLcdL6vf7vIF2J@fC!Ze z9WW*YPzn`GDJY~OAR|VBB1A-`0Z53#X4^YQB#c5Dt5M{vs}**v*T}N|`MG(mxLT{U zx?P`_suGXYn*B0AbLPy#{KD9}nO8H;kj0(q?=889a7hC9MudRus=fPFb*E&6UIhRg zVkic6LeLs$xMzHP-TU5i)BN1IFMN3~Vlq2DX*3-=cm#m9Y}(Z6 zcBiJtCa0%bt#%s0`X?_Sv!UUNHLU9L$Mi&gn4wF!OIm1OR#fadm{wFy6u}c z{l{PYr+c11^!NYC&yB7h^`IdHNQe};4*{kK2tp)`3cS*WbR^1H1x81p3A9q0ND+}H zqj4aAC!`f3RO<2vj zn*-9d@q|M5;xx0UIPo8wCIAHhUw-V%WA)l+Kl9K(`{$qd$$#{TXU^uIJHy8^Q;8Wx zX+P*@55^>d5@If&>FR5z-k4;X2+qyfLx=M?!B_k7yxD;Swv?F}bIXk{X&{a6vNdsJBg}HQ=L69(XR>GahYg)pi>s*V07%&aAQd+YJ3ZhnnPLv2RG6Ay$ z`VV*kk3_)e*>RGlbMuQo@qd5v$!8DM6C;`kbwA6aII2{{3kyTP$GK$z5-Wu*0H9ip zU1>|3XSrwaV+~VFVg=U36d4u-5tSFkCx7R2b4$Jd^mBiwEIYxi9ub*6QP9@{X7t{L zH>Zdg*Z>81G*bW#5GoZ#QIsV0T1_D#syK;?&_)vR&WVUI5fOQB0|JNHE2ZK%CPHJ3 zhWvx*#BoeY zDI^tZMar{7=2m-kt~)0y%M1Gs_Li2mt(&>!>T7Sj{<>?f*;TEi%+l-irzh7fEG_kV zy-Jc=@3Jgo=5DuZjDbe2D9d_cR@?2x<%N@ve)^g_-j8GJ=Q~8M6b6f)*%xImV781g zid3vLAr{v5#TBJ1%YvE7ORQ8SNwkitRTRqd-daSdAnKK3@7eC38EU**tvLj8l8wbz z?|>iv8c%ssj;~=2dV+1oJaMAYXk35&_04AU(4j*(l$wPBwM{}p@*?Hg5q-Wa%P{6f=f%-V zkE}sewNBzXmjyz5{p{q#%=%*|&j=wYK_!zDW9_p07mq&NX|4WmKk?&NZQp>Nt4XwJ z-B=uhaL!U6Wenj5rGN+p5s+A9-OTzMZ@5Jpz5l>7oo;XamMhYf&K-WC+iFEgq#}xw zs9LR#)$2wnU%IH0>L@B1yS=WUQc8L6F2Y_7K6CU$1T+A?hVBur$>)Ft0KBj!7qNTt zi=X+=zxA0TCtG#X+&n&AuSVKi%>tl%S-z6zr3M6=O;fFLxzp<^GZD`e;C|~*zVyY% z_x&G#>j!VS<@&%)RKg%EB823a5kv!upb}I79B9-5eiTGKLn&qGM*XIgU|%_yK`A(V z7*s+yj6Jzwn!kN@;`l-w*fS|LDK`&E1Vk%@~8E6cQkUz}6j? zfAEK$EsI{O^Z&W)Q2_Xb-@K;QOy&_5`kYrF5+ z-1yLzDPfNQUz+QmpIiOqr~V}JdCw$T#Cy;iEly_qwOSiQke6oXWBM> zG(`$gxqi88%jU8A#BV?N>routeEXewmR)eP#-L0kh(Vo>Km?G7*%}VB9t;957_@$d zOo5BS7))b|-jWR@B8j56d4=B=;n{<@qAa={TwYx!B=HjVbl>btd+Ws@Pe&9KC%{8r zPy|s3P6MH61qkSKAPZnI%U}S-6+%I+l{O3oFp(nfT-eMhrQ$dWRT~iY&WZ=6Rbt5b ztX!UV)bRBh6n$WjU?oiq!XO^VfYN{fUIC+kgHTik091f6z-w7Vj4{j0%g2u&_uezJ zb8blBp&(&5(ytpqu-ERygLJ&Lc5!iWW@cvOKycAnMuoOZn@MY{gaA;D6VS?KIf&$W znPr*QF?umd#YVY2Z>EV++^p3rl_ZY!ShHS9lPHR`qTt&UuE8^F7z}S=1}mh1(FsUM z-3dzY8pS}Mha!U@lMootBp%kD~~Lqgbm2Z%za0)mog&P_1Zy_zo)H!ieC-A|QfBAr{sVoIZW#3t!x$P36w_ zz9TQQFFv`yEZtZwb-r9$%4@Z1QS=s;=Ci)tvU$Uilc(Z1?dI;t6Hjm7y6L*BcRO!E zYDr2joIcZ9J+*Pey6JUe-g!mnxtN(9&wAzl{fBFfC{3#yH_hI7-4#!Lb>ESr$FA6Q zIXk{U02&US;Mk-n6pjP{c5d19fByL2ICc8m1Hbo~|Mb8g0RV<4jD+z6^fjay0*cTL zNrnIeP5!ktYeg#H$4B)pMZ^PX^YDp@42eyFlY>JX@aVg6-jPzxX5AQd^EJEw=Kt%S z|MXkG3j!=+6K#yvCf0EjRU)l*oEnoxNgBmTWU5J$#8Il#YLY}zn#4NMablvx7;U0R zM`>&f7^Ah)nzYiQNhu(Y9sylZvar7US|V&McmK^l{%`GWj}&;%0q)5tL?nQoZFBuZ zzS=E186djw8L_Z)fWX7I4+73RkBlrNaA}(YO+;}8eIevDYUEBPcWv&+HMP@$u#-{>lCAcI#jL%U`^0 zgZ#mf^3Uc>ilPC_z*rlWs~9*&IMqUcQLp0lrf0@r9Ag~46&Xl`5SdqcgBSAgHTTp@ zyEx#%BdBiHMRDWxv=N)kS;~902RzY%DG>2YpWDA$NEvg7r17^8z^ul@bJI9tvoM-mGF_5K%~gj0hZR zQ3H0dAD>8GJZoP(aVCzUD30%X@6Dh8%F}a8eUrP=x^?3f9mO7cAOF}LTQ+a#^|JPA z|GE7y96NQkUaOCf*Dl+#>85LUn^^zb|M)vban`qq)@Zb|>_sNV(>;4%c;cBCZn$bw z-nZIl?;WDhP}nW_6^XD2LU26`6lA3W8k>d=Lj(XUI#NlRD6OjY`Hf4O{kFQ}3lta;gQwGDn4h|$`0fwEG;8iv1-ymWz*u4Dm%bjz_jvaH(A&U2Y z*nZ^j%vP&a6vgJvn`dTbo_gx3PNx&c@yO+9bh@=3hG8MsS_i+uZ~+0|5iW_D30Ny5 zI!Z`4Qi4tdEGDA$8`kx@Z4xe(WY)*5T#`QV%z?l2zyFh8`se>-`_7%u9y~f$uSc;d zS-j`a?H+Zf5J_vTkg~FvS-;^Ox4f&_tnGh(&*@WhJ9k`BNh^zsCl}|>D-$WDjL{}C zL}JUFNjYa%R##f>c0bQ^TUv<1hxW30Hj=qi@jq;6AaEdon7xkR?7@A1{QIB&{J!J9 ztn8fK*o;*JsUAm)3^@isnySus`pf;yJ0TDhoJf-@I}fH1-_YxOS?{?+N4Ia?)SPIL zB0^>mK|o;|tT+U~gCrCOY(zmo<{(9>2}Q)qz%LSD&6^4xL3~{xLAbk8x{B7``|#x?l-R;n>0W7n^#sVwXv~UqgfRp??HS(GXN=23cPnKE1m!6 z!A4#dwT4-oEB^Ptwl^H%bzaGjXA=v}`gd)J-n+ih?qz8lt>*5}7rH-o=&@VpUtEqV zM%W9eDW_-4;F|gJ2NFO=ylNL~O{IP1WX22B4L^1^{mMe~`?h-#92x%zpokcaQKWmh zod8Hu6IYE z!wzo3uAyLf18=_QyTj+KOBdKq78J#Tj>Hf#pb@2otzdynO7`)kj@miPz|TPdiGiPM z!g~My=A}9LiOK+dUk87-O&H|3u<#ng)vum-cWG~SDgfzudp0Zxf`=Y@XmWCLadFW* zGtX6Pi=3R)zZBqSJnV(yQGZ|f+$V?v5VWIyhzRbJ|M(AkckO=J6&IX;+9rupVF3ho zNN9urF((WZ8Zc;rg4Q9i1t7_p$dXn-%t^Lsbm--mU-bD;|I^6Et%LnTHp`HxjUB<- zqDEfK2Ufi=5nx2ZcC986VFL2CBJpvqj=z0BAeZDx?77*h=k1v_5n<;>$3`!_`ilLJ zJS=(sqHC^HCb;XncO|V<>E|(|lUh5|2pB;5SOo|pXg@Y7AcZc4ECZEe)`BGQ!D25< z?sCVLeJEbM^0%NO3d0~Q1nlf{mrikdHHogM3*RM0ibU-8D zTl`AgFZ{DCQ%Yr7Ha9mnH1xDma86=*ZiTJ0PJwpTDN=@E7DpcB0DEai7>X)rwCX8k%&F#K@bTTkO0tGi>MW{&mutuen(K6v=-|G zQ5Or^C}vB9N)Z5LX;!UNmR6RF#iA1+B1N>aywX!|Jl*SEom(I8z&!)@J-YWk+fKxD zNdbHal?mHp1q%lT<`x$3ePFj^bM0jpmWt}@x7<0qP#fv*Qwp>ytXo%IUan6cTNadc zV|_En78Yh#mefj~OLw{0tT%V>-k+pdAqs)ulI^E2)mn?o3zc#)P17V!(=4-@8(%lP zasBw=qtlJ%a=D=Mq;dAyr{8(^gJUE0YPs4e-rk8XOFKBhi0B;mc2)l0-+0@nKJ%5M zN00vcTi*cS{`IT3EiBipbE|NV*Oy!cpF~)=T_3KUatOE@0rRyCSH=B&yb=h>FIass zcRn5uJ)Y#$ZXpXP1VHCpSGD}U_x@%z48L>h?T_r*^UH62OS9GZ#J_x5YyH}Hyr@_# z6~oXJbY#dVt&}1~h7b`@P#kkE&azmxnT1?9O|xSul!_U^;*ohql{;%QXRUMW(pDlF zVPG6{v08A%jbn{QttEhQVpSmoASImJl#JG(kN^nD1wnU}0i9Ans1O7kum~Sd&k_+9 zX6J+mMVOf%zlwO`1;!JZU%)(B2Y$AXf5O>V6s3Ds)JOM7i^HNqCt3kGaR~5ZoAYZ2 z!u^N#{msYz>gJoj97drrp;%rwGVrm#`s?Ld>mBcS=XK|t-WRn#eb_7smAI|cFKzC) zfC?5ePI4O=C4f&C{XI#8<@nEY%}&~?wc+K}*dcb}z-xeQ@nK{qj2fy@QG*zwv4Mf= zhEgTe-GzXNhKGkXt=||J<1&i?xy>{Qy4>YSvr%kX+f}U;3&ro;`*4k=r?-nmR%$Dn zz$5RTJm$xTr|2f-S>~KWR76Ci*6f4WPQ7RkP^btHgvCVW8@E6Dr+@RgmF4F6*uWqE zuV1T{%y;j7xVNjiZe-{+FTL!Q*Icw?@4@c=%8M>K+XM!YjnRwC&6(NRD2)31ddr1S z8#Oz>GIea}=C6J;PxAzz60n0D5Q|Z8Y;N%j-@Nati_eIYWe~{oT!e`ldMcn zt9omo+Vk3%zv4A7eOZ5R4{P07)oo??6IjwrY7?$)})v>vszqlCN1kk5t$6o<;u2zl;6d-Rc3R{6 zlkcFNd|?1kN_j-8(<)f)h@Mg6(|`jYO_--iZe4dz-zAsz&rD7BuGE%ST5%&il1>DW zFD)(n*Z=W9e(hJ^@xp6g(OO)~8pWaO?fs z;>*m4*WgEACCjtBqhV_(`ku~g|A>8`3Sl(NyGCKMNHMWiBa(CDse zWomvg%`G$MSyn|=k3|9#XWShY>P59@@4HZFuat*7mCt=7W>sc~94N?3e|B*yTZ;#>ae>;4O`yxp%v0s_7tujDK(Qc&C>32;nRm}!$%LlW5>6eD$pX# zpei;PPZ&;J{~SS_qplL1wn6gzDS&{ekUx2(TZM)3UXwGg-30*@=!(jQdmcEtID@1GtW(-CYhgnw7jE!Lsy{t%&)f6%ysfn)N$$GquBTfx z;y;PWs$?7htV!%)5hxT3cYNzBx7~K@1!rtJf6FM_Trvybgn$H;UyCc!q?A^mHF?$? zA%RhdP8dKm6|~lA(z^8Q^A1kTe&dUu{+XZuHRsvY9t2vQr`wCzHmw0x3k^7gHm21k zC}OAC&)f6%95O@{fEQkKRbNlf==$-=z55oIS2m1|Z``&yGUhwq{%#tlr0DssyVeLu zkifH!ETUJm^NEQ9q6G}2IB*$I4$T^*O$4U`?S0QRYc)X@FOdcW%8w)&3$p^uvy80^ zq6o+kq1arU4Y5uuD{23bM01ckKn)OpWFP`iMyUv{05q{3-9`Y1`K)kLR0+x#Lt_tg zG9Dhg)Ox)6sN8`A2WqvNF~;k(_`ppVhQ(qL0JPQ~J@VF$t*&xg&1R!Bxy7n zl}hCay3mX;PLCg)VBhx_|`tA+b^9++QhRHMRqXP?&JQ?{vH zH$GY}m3(;77o6X-`(P`npSf-G?A*fs{YR5j_Ut=6JTkEPwDCO$d1iX)$l;@BZ9jcv zWZ=l*sdLZiV#c)+HLGnu-ubmL1H*mce*O8IztdF;UvkamFTU#XkN)##ckelPY+=c< zkOI$n?UYLTp3SWZrLAUm3R1iFA-2^Z9RT$8RQ~9{|4M&3`hyRBY-)Bv6P&sAv~$lq z?Oy_uJ5Cql=CNk&Xf17~*4oTkmq~7&&78|EYlCF8R$3__%>Y3mP(~@l%3!Z4scgBW zi$xO#p$SZAOr#2fD$t~(APRL8T`JhApLOLDoWHQ&v&ANYv&6=@c~OxYM`fktiSh+P2)Xb)LSZ7BC3>1)vl`1 z8WDr8k~o)V8QUalrlN%kMw&J?dUT+FH{@p5?WAGt#E9QhV_g+h2M0CBOVX{hh~!`?6Q`_xJfH zOjdxMLO_KC>|0xj%FI#-qwfCR+}b!zJkpV61I0oqD4J5Kcn+!YJv+Z}*N(YNCE{`i zE@#_DOjwK3faEw3?VZr!@IR4VPF&O85gHK?L=ggQorEgT6e0DNyEAruBmF`qX=D)Qqr-zU z$L6fYg;xB&KmPEWe(EP*dhIn~RPGUpr)Tn3E(iopp=k0vlyK9w^DnvNvM?&nEgU{J zKYhj-mv2A&%sqP_I=pv>ORYtqJP$D}l`4I`{axKX)vjvXOe)nbMf%{reQC4lb^RYN zs@qZI^DhY#$|^AInQedq=orADz5Q!n`NTheV{wIgtEHlfyN&6hARtlX0^$%Uh{C{V zWegB@jSj@jX`bat3Zj~+U1_zN1Ub9mpfcCUzJ14iy?ur5Qb1Ht%1E2XBMtsD*VQu=Sb6)xK@hh7XRz4@#3BVEp zfKrlWxN8@LA+}mDH`h7P+5@ireeFE-_*0zf)KA6U^B%bV`ftDIkJt5<3jG6pih{VA z%W>Gq^TFD|C=mc~&Wf{GF7<$@8n67xC(eE6>mPd0dtP+?_22%Un^A_!XsLQu#1^5I zq?*)3EqQRR^}Ze7>`m&mpr|ZE!3G;*p{z}PJE0ErTSTWDo*VTsqX;G+DZ;E9fUU zknvxn^D&wNg{`cyv3D$X(m)&NP$@0qEL%VlVw+jVsmHB62#NxTh7g3EfI|R5|2YAy z>JbSlA`y0JGoRR5GT~@gOw*VbkH+&yvLid_;+KE9fB33PFWz$J9gB<0PMI9h%VG$# zLeg|1gW!34-k!JTZLM_(bnw{a(DMe+nY&Q{1Qpb#Pj2t+_yL>#cfKx<=+QChR&+_{%rap@<&_?7+p_io<2 zIf+w5Um#k%pdEQX2V`}Y^eMzzz#+F0^&4Ms;)`>L3Y=T!* zRxNa<>9UUQ$&Iwn46oMot^dT`VJb@ z*}bzS?flYFs9P1QQF)$=h?ig`qBxE#mCBR$q7E$;9tSBAk#kDK3NR5W(#^C9h$K=f z6|K#)G{aI+5rPO?w$@3&AmE%6b}SA>S!=Z-f_7XCKv0mhLIARW*0DzeSN{vOi$d+Kq|AzSS> zo=1T!+{ukvT{uG$x9+)r*TBF~saRr8|Lv=HEv+>Ax=V!M97kHs%q&dI%y(BR>xTNr z#)t2Jcvl>!XKo(fe#Yj(-mX9!9Ry(z5`m8$Ap#PddFJNNfAw35wbxv6(bm&89y&BN zF+F+Y@YL>oht56gjC0ODW7n?z2M-)67AwLo&vT#l1FPM2RVrpp@oa$Q`NieMWl;Dp zH{bHvuif5LDO~sJm;U~5zU?nR`I%3A=HDDM0*J`zo5xGVNC2G!1t=&0qL7>u09K?N zu(RyRyr@wTW_gOFk;owBxg}CgSZP{bZXBGL0>8$8tUCOLk>L&FBk%l`pPQXN^1C1S z%QVf)#R7>u_~5>u{plZl)isxW=H^@X?3*Vdakfw`6v|O=xmYR}OXaXo3X7$v5Cvfn z1fdE-6B-k=Ykn!Ml=4j@1Yvdn0_+@HaaP3T78qF4h7%CTb2el-cUcaZOPyaXJ7!Lu z&8>CLxg-y&MVr~ie1n1WJa^Wz55fD9D|gO0>mbi^X3Na%*g1w@{`c*#|4zmXf`S>q zKkZVB&7f=~13@7Ih#A(E=*1%f5M+7wxzGJep&0gdbvwt*4iLyFmvK+EE2%C2;xGOD zCwu<+B`s?zpcVIQmZqA$8CQcq}jj=-FXNK0xiK zKP!<6K$w$MYu#Ng7SQ&F(rvOZDisPr6c&QOXsvXh9OqzMmTK)ZIY!PBC5FThSIc42 zw9Ab+X|>`sw?e`qj7W-{0Ei<%KnJqQDtnA#$q5rHJExRpW~B)b+oewcI#_aN0Z4?$ zmX^M8_XC!(uc!LH>))|qynk_d#gOi+RsbQl=}Ilv0)Uuixpypl^wl}nY*_$A0<9=x z9v&VT7#{e_H}3wU|MwmL;}8G3nWTkcSb{urwp1z|n>)7q;N*)hKR3&=AkdwfL(t9- z0WX~u1X@IZfrzv*I?&<-00Lu-F>7;!06=T)TwBjmK!8vO#$cee7H01US$1s*N^1`U zbd;0*=RW62L_9py_6_`D*Q7TQDOgS3>MWnxL)^mP%T*y%m5wA294Be6tyGNBfpU>* zG&2CsmKSJcey9{~Ubpcj*SxU5zYqM2)?xhk*+>xrX!1D^6h$TW&IFMar_w&(_|>WaiDAH&?6G0|yRdZ9QoA-OKlz4va)Z9!ByfGRCZ| ztTda=@$vB&z34^v-h1!D!a^8^u%?H>Dn8Vy^GQVhlTHCH-=&mB%TB<72x)DCKry@8 zLJcx8VV>tbJrxxMD|7QaJzFe9@k(6M%G&g!|M2m-#l;uD^c7*XgbJ+WLLyFU3{lcb zsrSs6UC}?bO~6T>=|G>mJ*yUbCnxsackeA}BNt)koKXM)G#U*eWR~fvV`-9>qTX}Sj|KCH{uDp=85QzhoL7XU~&?I02+-pfb@jSyC;B% zzEAY%z3+v>_S1?~8Cf@wCzR)H&_(qQ;R{!&VI~L%)SSXW%<(1_>`NVneeABnT zA0fN#;}<0aVWbHmPPkeMzCN37n%V!lBM&xBKw?=*G?q!2ihGh94ghlcMyFOY`PY~e z(8sS1gt1`w#zU2sEnGfS$lZwrAp}qa3CO4X1Bf<`kQ=pS0C>-P;rioS0=8w!33Bcq z(RQ%7uE{%+^pEG~=N*)T;<8P<3*Doo!G~&-#i%4Ae)_OBXXls!P>6zd#Wo-T6aW+p z=-2K9>=2MUkER_WKqMW8LDH&2sXNm_LFpp9RuUH~T`jP++ddaz*HjRz-R!f`-wJW6i3?ZSQpiE#;&}gL%p%P;1KaY_PX?^XTZE-?@47mbamw=un_tfn;^IM(39>oz4e{KF-``>LI}oL!W%! z{=?gGrYB2Oj7)csC&}dD!$@jsVsicZbt9uAje2cHYU$9KeXm~u6?1M z|I8LB(1f{&B2WmOz=k2v2!O(j%#gFBRtX~#0g7XBvPz2+0Mvj?BIrz@i^YP?vn+{? zG0G_C7>x$!tji$<5ot9VCJ3CcO_nH+$#!vdOrkO{fij>SiW34L1zHKRpG8m=5XL2+ zL@YeT(Z^3r{+GGAxjfH1Vssurl2wt9j&j{vKxj4M|Cm}Y#u#g@F(%70FN1Tc!Eo)N zIw;p;DaphvHp?XlgCGzGN+~BS0_9SnwX~3=iPoePDMAGbfy67XBQRTM5j7wpI|dfE zOac2kKHz|q7G!3I+?O*(mos{qc(kOIF#GD?4mfyEtkrbGtTIl zTUyTTQWS=yO%Mhup-QD(DHH{N=mS7&L$?fVSw>*#V2aJOdFLGujE#+T_eQsVXR6jp zbG8J*_{eacCC=hXE18^Hh)Tt=;lT~-2OfTO|NcYA&Od9@m6x91)7zcr)*swC>zo9} z9GN^eH#>Xw*;{u!x_4o=7B}rTZ@YJJpnuDms) zuv98V&apAa1Ch+^bB&o3z9CN2fBcs(3=a0b^Ot{a z?|~x^J-RnevyJOVKl}&(Q){rfB^^eAcEHX8yBxf35*g44&L&xIl!*!^O|#skr9v@D z9b2ab(O}AXu~0oWyZDaZ{sWM9ZUnYH1QdXG|H{v9J#D?U@OS_8#f61hwN%WVi;CeF zzIofw*ucO*F95vcrCXIEr2`TYVQ@}z?5 z4W&swv;UY5v;c@`PujIk1W*TBg=%no5CT23cQQ>fKv|hukjw#!wQQXaMvJGxWO3HN zby!dq_s%Lq&Q}Wtc9uJRgS|Grcz;O%0q{R&O1%KFh{pVLhx9`==rWuMQCoHg9KyC9 zN#d1n-g4)r@v(dFzqhBS%emF64gi1!DuqEL3WGvu5v&s|6d-m05CoyJxmI8_+1zGn#vTa~0Z@oOZsm^ii;q9i zQyOXo%78;8YUc?Hq6iW)`nl#fgV3_{^i)pYy#D5IKJeSW{VtleQkFWkImU(WWzHY2H&RoHiganu~mSQm|h3r!L+|75r_=sY9~ds0nfb3pao9<_GS3g%wxNNyq@9yeSncBba(dmiFW;4+S5P?~g)>?rtpH(Onj~<tTmc^yz>J9cmNhwv$dF*5J4O$^7*ld0^*zk9dsRe@LPZR(VH4-c%WGB3ZP=B zVoVuwg{%~YT1VPMnv}vI2$--PuXmtNaeE-}xQ* zkspEgy$^ox_aF>mbQDHLVB0o0_gvV%9X4%({{F|{NhgTiJ@H`eZ{p6KP_IL8FCZSz zK>Bw!f$cY4_ulv3)O}`gc(f;Np@74-3Lvx#DF{Et84y_2Rs|4nXaijcO@fgA$&Kf} z{`EIqcO%^N`tPMJaiDb&MGBlau{^bs?OcrCv;VeIR$mUwXfwUuLQf|7lQ<{h7)ll1 zu+dprn@Y_Bh)@nBP6bf`iU5QPW}0xr{+=zv<*|~9?aAj^1c;3Cj5b9|kqY3%%7p0C z+z^2|arr%WEEi{>T+tf~;T!q}ch1gb=&aa*uxo#P4vkVo&M^Q336ZjSE+~pZ(8$g) zJ9ZX90U!ed=R^jPNGov`#rm2S3YBNHAPFE9%3Vp^YIO}c!a{9PpK*bN#VTS@>Td0O zu#q*s7KU#e>cQESI!b^Lf;ey)vR9;k-k!JT?U}W9W$aaM=?Q;62hIC7rBZ3@)~);Y z?MspbR$Zw|rBW`J!!X>udGr4L`wtyDbV3mAKeKg~MdamQ7!eT=*n!qCdvwA!;=#=$ z1T3Ht7?@ay6dDyED)e)=j}hOt%g=`WOOLYv*pDa z3-=H9504E!aMyz?%ga4|J#ic#I&{bwJwJcUIk&uIj~<;~w|;E>rcHO=`d#N(DH<3Y zSXo}_&^&+8m-T}(2ckqFXhcMD0E8eY&MR~X0DwYJLWY4wTw6WU4;TWd6@|vIaIqXA zfMnbq28D7N*fB~YPGhkYMK#Nb%dE9NI+N$Q2?EQOxkZf}f^IHaz$S1e8bA=B3}nFo zXb=a$1R#JBnDv4PF#Y%|ITb5TYn`U)^768*=G+)#lu}-KMnwFQ9M%K@0Kl*1J4f#1 zC)rhznJmlFG%b~mmsUP$M>=WO@-wFMPCKD>R%`8qi73k%S+XokGn*t%n2ZSkKqP0U z@*J`>E0{n8nIX%q5irKs+>#IgFaRo1Xl#~>b7V9CaB7tnR4k~0NKz0hr~nO+CSU{r z(rALPzi(imt2a%Op>?B&4;?;oc%o1&>E(JDg=wCpaa<}FHf|U%8RPzAiB9>boCtU5 z_F0zQci$sXp)@u=@U3s&QmIsRf##QL7o5MPsBkukNvXq=GeKmA`@6Pn9o})^z(cza zhhemR`_}H>QmYk{B3LaJC?ZPJu6+lE-PGjt9rrw9jar$F!%*+tcQkYM>@&7raA9$J za`MsL2k*b{;Y%+&_x$tEzUQvpEUh)w*f3Q4|GHAu3iXrBc*gR6RpIVGy2v#rege35*Fs zWeh1}0%MdxV<-q!R1A=`20=oX%HRIpjk7b0VH7DvpwT&B0$YTc02!TQ+jm~Yix{%7 zV<(Q89W#sn-#K>9q5wcU1L;4aiHJsdU{QVjsH19(nZ7Km4If zF1{EM6%n@6)!T7YMN}%4#ED~$8_i$*rMDHr2w830viUvl`F~#ZvX`3ivPHFXIse*3 zI=O-u^qSR}_~Y2S|Iy6{kULRgZzoJ-o@Wf`i=lu6*K8$mlBU*zGNg@G9v|T}%Y=e* zvCJS2Gl3+t%sB`}WO5{M&{Cujz{{_l=)*tu-an~dq?A(HpcN#7HTZ|8ovkL_wv#T9 zSQyXWw(-1kw!P{l=QnC~t=hb`r%Pu?0C0AAs5>kLU;4_uy?tFr4y^>n6#{BCk^rJg zF}nSp9lQ5WZy4)IJ&Ml)?3kIzJ1*j!4NL$aT4`g<+ANNaXcp0Nww#}@{o}CC3arlH zj=fM7FbIp|)ie?jVFmza9bmf>%_?PqM0{m60Q5k#fIVIli`s!cuZg$X4LXPv_)-)+ zJMk#wt;H-);(An!hKEOVu?xsB7HW%&(pcFve%hAJo7RnQ3JQUU^B^sOAo)0_myRSr z5+XnZLP6zIlLQoyMp72Uho==HD-Z>$TDtP8tENBu)kQK3TIobtt)qaGR?B8doLj94 zjW#UWvGV19Y#uwv#AqQWOr-dS-{o#sKeE<(CQ&D;YAs!;QxVG;Lcjn>NJ6AB zZ_NJV4WF87>A{g6Wm{1gm6bLm1|>3q(yE|!NIEn+3M0}=1sYLjS&Ga?DF$)OBAi=b zM=9%=Sy#&FY8LdNJ+n7|^^Q0G*fqoni)jxK&T*FJF3xkC5-cn&A2>Xf} z!gJ0!v#*$?tvE^Qeh?mf5SEwW(MRE?n;;CKzaKVj zg6-R3`*t|RIQ7N|>fqdx3^A~qKuvXXYsheXRnJ@^oV-ag_ zTjt*7saGC(s2N1)tQySqKq}TfiBE!vd9K$FNN*on*J+1iCP5oO6N*S}P2ZS)6r_5edYPZ|npJ6(I=c4CF)z zKm@F{M0pTIQ4}_hJ_;jS!r@KHgWseLXXYEvD{Q+2$F>FceIt#Rzg%DbsnH7#PtCAa zv4x_7Ou+r{PXN!`bIwlMr)2f#sqFp)M|g_6pK8lze`(VRT>*eGrdTYdY1+YK;JKIi z;eDHGwfcrPydjR`d+xbs!-fre_U!Tg$<~ zy_EGjclg}uiq9JWJo_P-A8?2V5xt^A6ct9+j}{8i19v}ETd6P1&L^#Ak|dMU(^hP6 zPZvv`q?U*qE6bBJ^R1>MMT(HcWqG=BZ2iVf8+Y&CKQ}Xrglmh@{^v61Gg}Z0K`w3h zSfd2A>IpLtBjw;Sae&fRzaWK$FeF5=E;1Sv4U|fK)ndue*kJeO^<$+dT&k@cIx_pn z-iaiLY;LnO7l5{yj3A;4j7rlCt&_$qRtJR`ITk>GB4`3+KmkL5f=&xN1P0VkZ7v5` z9bkQF;Ur0X1jpAp@>Pn%FcgtAO`|CCi)%#mEYDSdhkdS6Cu;8tUwfi)ygIh>Sd)6{oX92~C zK>(!{2(s5BLl9;}LI!4GaAZt7xZ#CM+wA6c4fjH&REQ$57920l%^#gODyURo>h*fY zF3IA!SwDNr_R-N1McjzvlV0m7K75KE*!OQw%YpN<<|HD%Ky2p=rS#m~e6!XZ-B9}G z*YBuy^#jQxdyiam)kWwUhYrm(nrXe>FhSJSRX+F3&2h^hCrt zWD%lvC<&2Tt!#Q`{_;!DJ+{(&pHilI`}CcX)!nOAA9AM7ysV-KVlshwOLqcCRwV9=9lUUv8!6T`PPSWYei&n zY31O=Op<1eM!d9KYqXNuOsmysFu+p1b?f~*`noD*f)!@g=IN%O91Q3RG& znq8G*n&s7Ud7!`V-S7IZfAYugw>C>s0EBv+G#Y6s3agdqz_bH^%m2#-rE*j#hEXvr z6bgkX2qP0kVN}vl7#U-X4wMq3ltPU_h(aI?!YP9lW|d~Cb(R<<7n|E8X}Cu2EH<)i zA#<#CveZl(tt`)zdW?I_EIXWMN_DwDDeX%;J38M1=Wx+lqyP@3FKRbnPh3dN`mX_a%O|76C-Z z&av|s%(Dj_I~Gt%2}nn@%(q023%|FMpE@mP zU}moEeMH%M=5j<NeCH` zu!9~Ek|IPP1O!BdNT?8%VueVAfTWbQGBP@P<;7=y=i!4=C}k>b#&NyX2#Qe1wsA zlX8vtH0Qx_+s4w7ImD*K3WXg)EC3^#)p0 z+P8{D+8#Nx_0lx0R!b8($3`pXT$W{dZk;$HQi{?fbIxh4O`!b?<6I6PL_``8d|ggK zB0(*PELJJ~;9WOA^5Ar}XF~y{8kk6FC8!0o3ADx_2ts2b6&Pc55QI?>1fdmFS_^05 zvoNd^=Zp#1F)4ynL#Dc_oO0Yq_3qt^^9%K%Ud1dR;Bwb&)@pHbXky`^M-T6xTADmI z-)O}Sj8Z1fG853YoipP->WWLx?Ct8S%`b-q109qe(ZAvV055;JTy+(G>|^qGe+NrT z*xxVAu)GX+-U+wfibPN@%g6|B-3r^c!`WxUwrwyv3QBdB=Hio+0ARHmmj4!Z>;Pjx z1eC(XML)Wn(5E|K{t1hgXM|;W-Hq`2*WdJ!8_#26n`<3{&2#5OX=YAYSdjr2S(_Vk zJlCpyUAQ_Yi7<#(3Pl%+uGw(cUk}^2UkC8Ch3qn*vNohp2`nYNKT|(_Fd+m(C3X3ji*|VblX7|7u zqm_-7FwNcZ!0sv|3=xFI1QbPDg#C51bGgj{0N#82%q#?6bu}aNhz*?jMl1eOZ80?A zG8!Rg*+x2i;kxs_HuFd#7Q~U#;%uY7$bvx-DWjYxRwyl6BWVPbJOy^*1lWo&GP77B zL^8yd+lf`c!daTIldxDQcJ-u_du*QKwu{}Kd-eQmOPlE27v&ef{I$vS*Y5bn9oh5+ z)!xN=jgeB}0x97i`XYGG+jGj0PU^S<2%v(eqL_&46mL5MJ_V1(p9R$^!R(XZ;?JCQ zhUizk;uUXs%UjMn@4T+Au4c3O=%bH*;uD{^>86|D85+i)ar^z>|NUS4wO>QTFMa7t zKlzhC=^J^`MHk(0!wu`#ulL(rb=6g`eeG+#i`8*po>@bnyb%OuoSR=HEpaPuG>Tn?0thlY6b3;DtXB1ZK?DOQ%uWClp=jd(Kr_2M zx0={bNu-Tsr$}{It8t@=qHE&QHgl zG|2mGAOA@V5wk4Yyk&Ei=ZE$mJbGxVTrMzY+s{6$Tq!1TYs31D4?OUo&8;Y?#|;8x zkn+e_HZj-V*EcZKlce!WUizYkAABfH{}idZ4U&3o45A?K_VcMS;;y*jne z(L?l$Cv;Yc%SE%z{0{{pSP_c7Fs{L?12f%tla}Gr8^FW-_f=X#cDh$ok z^i*#1R+2X2Mzvb4R=TuN1VE3=K*Cdw4}zc&o^{D<1o9_3RSf!s`M0ec>r*V+`91AB zmfLt>u=|1w&ba&jUF+75uGClVeqi?{7ha?#yYJB>;tU}u9rRYKXKz2PP%3@>JKw4l zOQF#tL;ZUX9=ZFT?yIl7FiA65<*;jICMS;tN_SO@x7~gpAQVEn^uq1Muyo;t=T6Sd zfAc$czvM-ij*X9P+O*zTx$E8s@4ok;tFL?kkruWdf&ySf0T4tl6bH@*fcQM*Hg;GfkO&t zaJi9M*WXnsN9NGff;KqZ(-UX;k-52QsW>*&J2Smh?@q=CyG;-rJ+>GcRjm}7t!#33 zaj37_Rfsan5AHi^G;JL1Z?x>a`wqPS`gi~4fBo-Y`|=kb-9MpFl_Kq|0{|iJu2i<3 zwsFsaDFE0!)|<3qZYH*#)ugc^kmW9k6WdJFG;;}inf7MGrmfgA5TLW{GFRQum)DZ! zV!c=`D3s;JG;UfUrHu(94Y^D6^xRipP#*1@xM%>pdNWCy#8QmH zfe}9Ay#Dp;`j=C6bg5ZMqa6>;HkU0pP>~f1(w42&FbpFVY0|`wvozz}ie>t~ro!i_ zu>c|d+e~n@4pr?vK>z>*NF9w8?dN#+DYB=BKB>Ir-@?|I0uB>lgm@Lm&LJa|TNHEpw@vZR?4YuRspRPx>F* zyqv0tILEkVI9)rP5fN}(91;KkScLK{Z?=+FlIBk0%mpEaT7%YwQdbZbb8)0iH40r2 zHfu`?gC^8Cx7^HK&S{!7>ve0L`8#`tY$55>lZ@KOM?yh2QcUNtx;Y$#n>gIH2)|0w2A`k>Tajf~l zzxwpZSYPmfP7+Hh42{+WXfCl8&>F;f5DuLc5%HyoyaV8z3&U`2zLBhojrr0?xGMeC z&izug>c7#$wyAL#Ar4WkH{(P#t&$AAa| z-u3ask@mESt5cyO@d-z(#bpqIh`b91h@=S^PCs+ozGKUS#oo-p(n@W5cDmkdic?|& z$t?n+0uyMZlmMc2mL;^rLdxh|z|ROj)TTX?h*wKpd0YfmeLk-s2dk{N_3PJnb#?9E zzdu_Q(RR+2N~Lw{);;pbBc0Mm9m??H;$opt$g-@}YT;_(ALm>g$9bNYN+th-6pO`) ziHWYRt{1-Wg*$id+_Ps-5Crg8NxiiJ7r!>}coi9qga(lTL@9=?koypwcNtyYp& z)@s#SajU+PIM>Oc#n`9ea*Euz%{I zofFe5F|Z~emMCNA(kv)MmhB@uj_$;CdZGT4uf1xlx0t2&`1rf}Yybe9gJKbW^;hvV zuYnJJ2tNOLM1*n~!mvFFIEP1$z`lL(g)e|H(9A@6!Jpk8dj*A6Nr1Cto z);Vq^ak;m2Q5beLS~K-*mkC9(P#e|B-*+r5&j0Bb&(`sgl@FV|t!Rudt(|g_n z*I)mnO?Zq2ppcM>73gWFAj^N`@WT!i2F`4-Obq-KE>jqTKsK&tWFoB6o_-nayHDNvFRd)bbFMuwIQ$mL|MkJUw?$ZNP^g1k*yb7F({`ZcS&lmX=ix5> z2Q&nm2wOSHGZa7tS(Bf*`v^nU(y# z)*t!EN8bMSx3B$b+qP{#_G3Tx=}&+9t#5s6qtSToU`W0teSLjze)F4u>$iSuY;5e; zfBo0r_{KN<-QRs20N(!gx2<2l{$n5e*qwLY`6EB_Bd>k!Yk%cee&wC-d}rHRcov%D zBoVexuqGi2@mXB|o9qpPd1=xxL$a3o(f>%%xaZV`$5o9M>Q;G)205|~h;~Mzd&Ws>{f+9J9 zfGPl-SX;MaYcIC5(&=c+`-QWQC3y)u&-qdAOOS%_J_B%D3P7;MJiX8W=u(%Xl+wKJeg{r(*X&)76JJlM1M$W)r~ z_N`;=mOh=_dmQF5&!RBe+L@PEOX1tEn|XWcQvdQjWNz~mggL& z#^q;h8@Tey(bT59cFbq3j4kzyL}p#rtFE|YtS{>BFMsmmw|(tvlcnz7s8|BWX%gF3 zvUS_YxmRp1uIny3YZhZ5SXpjiD=|fihPt|?%cV9;GNw)S3h@%Y{&t@w}(MR;g( zMI2>`ICgB6V7WS|h%nF6xS8Z>nr0ah79#pyGO(YZ|E@AnpJeyW&q?k3<0Uu-McG8G zZk9#cW=~gt*RcNFr~WBRlfS#+A2%1(2Os9XWA5rfKBHR&%8w7^*$QnR zS2`*0PXIYQtGDOL?fZGWYn$dLmyY}0#*U>^G9I09D@oGKHd<+aSGC;J)!Q==MHOR; zL0AxCQUuHiX>p)bWJNdU7c$ETB#vvf6&4JGFiEp^jBd5|n+FtDi|icNy;#k9Y!kA5 z0*yk2i0siO08*NrV_y`cEx8GZ$d3Kx8?BDc9vd9!^=VZkC+B-wW)v~nXstjX%X5(v zqfLlloeXpZzx1=O`NKcGF}JQ%2nYem{os)hiP!^3fI=XI2wr_+b(si&N-;{QySQn?&{6|)6)6Hj zJ~lU7YsSv97~tFjU}EzCAqc}TFr*NOL#tTO1}@J}>B61LRlpxx4;`^KjnJ&2C0l-Tt(fNy93U#D%gv)R6AN>*1Ks6~BmJ#7TZ~g7j39y} zcA0Z|f&hYnWyx*cXf>UU*(PJ_hCw*9ahhiZUAqc?QMf`?{{4>Ow8~?APwT{ow=i4bGe*DwD>{W;U~}*ji^z>Z+AWu^3tx-MedUx%K7i zUV72^(Adell~O1I%&=(_eDH(t<3A36`loQuJy0rP7=o8O2t$aX_D~(i`0&GU@4fJe zPe7pn0|Ri{X|R1eoO2GGaR#hg2SES;aOe=u%|W36BB&J9YEZ9x00~c_ztM5=Pw@4> zH}vSn8?SpkUjLzg+O9&%5(y3D*5-MuKYZC$SNzIQ{{|w+a^8FJ&O3JfQA$SyDn=`7 zt##~&BLF}oaSS5HXd=Zd<*IIp1pv6_MR5JMpJt;-0ciloyr0$3%E2=i54MzvMiVS1 zl0O9!3nEyndV6JXfUOh3u2A+ZtKYnHU~jtq7cLsSXR1~xERPnF`IhP{$mb4~K6j}5 zC8rk$imI991Q3=(tzhBE)Z(!@6VULc(+WMMWF<%Tmn;ZmS%KuIAN_Ruj2#m|Rv-{= zA+F_eSL+pp(idIpmk0X3U0XSnr7ThnOWFh$Bmju(H3m^Z7zR$pMBUR7aGi$;S6zIVl7mwZ>2Sqwn&&pFqI*AJ*0xH1zvHa_QID5)-Ah=Xac*=t# z!d-v2fG5kVM+BQm&w6vkJNi!wP<@})2_}Bx6Q8*5y6e1mu{If6M1JBYexj$R=QXc+ zO`hi`u-bpHHZn5u=}&+910VRnOJ4lq7hQeTC6``)!~gx~?(Uw^vGKXtnVs{}%_GvqgPig|JsW>_N$>rufnu@1z5M|TwuNQ)KEa@}NZWKgi zUF*Q~pIX<#lk`z!$%^5IO~bz`a-4Xzx*inr@gN_(22en>os6?h!U zdhCjEZRoSp<=Xzk^I-jR$OJKLHolpryATUcALc=k%$Si%^~X-J@3VdUCo&Pqvs`H< zB12=N4qc$3wz51kIhp3RI@Fz{DIhwQ9XlTC?(UkKUs_pek zN(uS#vYkMJ0+InuxrpidH&L9p^QmCV&RX0SbUx$bdmiL9Fu0zsL!KAgrozFe;SkVdM_MNy=k|a;JhE}IZ zM3iJnmgU7liAY=Pq9}-pQKOXrqRYieMu>_Oi)D7qioh@fA&LNzF*@|=MMj`|PqXh{8kx+<)2%Q6G0R$XFE~LpJ3X3A$KR6@+E47t+tv)z5 zx>R3UT%2d#3=GUp`1mCYa6p9z7QZ;rdN`oMN#|byxuEMuDrUevt|qMj8;YjlT@Nk) zo1y4rdAgKwysdJ@=JE@2jvp835dg|1xo7FKPBMTK=U)W0lJ%Ies|J3S*UY~@tOh6y z&c|nEl_o*t4jwuL6s;TWzWft zcj*P^95^)b?K>X~0(1Yvd!opkd-fTHLdmhjacg>hxvN|`aA-Qq+!^O@+J5@BqerK^ zyQ_0YCTjKg>@!X~e0b*OuipKNmt8hE(7*l6)AsC{*tzS#=1m(5VdSjq#5cK(^-3pe z!FN9^vgNeX&e*zc$L@n+6iS+$e){HJyLLu_E*C-~+;eF1{4+Nmn4XKm;FkM#7o&g> zkIv5-WwfTdcOJZO^Z2n^LmAq8bb8zRvFXL-+`4A7H9fbmQg4|+&n-7rRvLZP@{yT& zqwvu50x|ACGPPlJC^Y8Q`*v2#rT6^qZ(V-X%N}{~{$q1XrBW0H=E%&v6Q?rWis{0! z!LQzS*L}P8Yo)^8;*b6Krrut&Yv;nl_s>sHX3|QiNQFvhN>yzPIa$oI+wNPb6q%K_ zNJx;SN}B5HU)#lv*203Dns%k?AR;ttO_wAD))*v6(|WyI^-GolCWTTMFJ%OnEJ1D? zWRwmArOo2J{^*Ae|7HHLiF9Rbpnh}$I06-_NE@Sp892+98hM)J)`GQ4K@r4&kO)0p z07<0#+8@>3{bKWzKp7&a4V;Qug(P`azWAEbxi2^w3?hJvvv}p}pXD?LQr{c92LV9n zD@T%M9u*Aw_nQ$7aLdW2io3AeeDa^ZdE0H@ZN&|vv^duu!~vjPSH_W2nYGrrFp6{# zP?DxeQV1iXG_vGLs)%aMT7}Bv8#dhhm4E%jKYjEUe)g9}3XQK%!9&Y57{Hd2J*Q7? z>yk=x^aw`{KP&#*e;iS{K=f|9ptLt2Qo0exyY}s;$*5B99_Sldw{EPq4pvS(*{h@nlv30O+k&l~&Vp3(K=B zn)K+%fL7dWp`{0Q?kPnff)KIIflv~*qDR`VZol^~bq-=*!=*FE~p;BH~dfFQ{jXRhlS7RHzh*5=RE87&p*_VKEGY(6kFZ zf+!$pvjshg-=9N}6#D+B2z<&B2qFO~B66O@L&SdeA@Wp5Q3!+^*Nx`;X45dTE^~R& z!00EcVX00B#n$9@@L{eHSt*HB-Y2R-;MXG&hqvMeyVwPp)a(UCH zP4#+xVPT;ItIDcA^3u{$qtUqf>Z_Ug;fEjg{%9D69(*FAEnBu+a>*re9N%=)O>rC- zi$$$U=W z6XZO@!J*z_(X`@*%bFmpNCV`~SrPUGJpl9|kkY!@Y8q|QG)1C9Arb(aWoeq_Nk&A_ zR&NAj0uXf8uB}Q60HCyZo)ifPGoT0~1WR+vX{syTWrdQ(&8|onLZcNEvm&KP5osh; zTIKA>Nn`?Hj?*N~Vh3$zEdV%U5FyL0W65pK&WU3YG$f&NOH0ipv0-iH>)(0!wnru! zS*cPDowzt@rAg9i#mv5Kbaz`Av?Wec2h4lFK$ zbASlUpcFKlu(ARJ15c%+KZC|dp~2jNvo6c)x^?-*XTP(jyC-)s2?4?OGcK=|KlG(L z-=4|5aKSo@lsP8^1pvux9l!>r?6|GXX!G{s>%G@}`)MX1`3V&QRI{yQGE3idY*%ly zxiTK=9xHZjRV6xQ*a8u(rSTD4E@3O{ir`BV=3RFT_x5gh=Xt&CvfHPY|MJR)b*>Po zLo4|I+&3~hP`zrj6en3!h;#r)AA0z^|M#O0f91=0YXux2;z z5G<3hz5e>^ueWgkM%Py*xKC`s=iCPVHV4dC2H4+42 z!a2uD7#8w8ZMK>~N>{q8-Mu;D!pxLnK@~s{^6E4O+JFTSLG}zol6Jx}u{cBo(E^SE ztUyRedDd!LtwIS3n6{dG?#6AGL=S&Ec<>u}sq&30Ui;4B&7%`{gP~A#39Ut))6&_}Rj2d<^UV{Gb1G-F4S_?#Sb}$+GOlFMja{Kls64`lVm;3HZ-aW1g<%dERQZ zM0kE-;gMZO(#Bk0l=YTc$jRZObwp&Bee)Y%-@SYHWtUy%cX?V7x2J6AB(bi3Ql&Tm z@cg4^`lOFJzI9FOnuw2gK#?VJd}7fE&oNx3p|!yq6aj=RPcq8^kwWh6t`IsFCap9C z3Ph`Lbuot^N>LCR6Q?Oarb+1_)L}?LpeX26IA+J7q0wwE)@!9!Yju^ddS(J{uUAnX zN15-?syZL8UEDrz&k+;JM0_9nUH~4ECn-+$Y#;w5yCM3zv!m9Hhq9Tk; z5SVBoULr*+EA=z4vE%UMv*~QK4R|e{Ta+hub$fIr*tied=%j_HQ3~ zF@7<)vI3h%fI}~mtTIlU)gnPH6!A|g9mr--hJ)0*ZT52PeAtS@C)y{>#jfl z^FROUSHC(tJL{Y)7K`28-NVDf+qZAO_S$P-^{Q754-a=j6^}m(h(^_}f&)JBNB}Z{ z0wZYw4S)~?f(XEXMr&0r7W%u2{oPS!v02Z+SrQ=NYEhA7p$Qmt=Gc%fSIW(U3-vUw zHM3Sd4hx}jY^~LrNNE7DmJtL2!6gW>sA4;Kg&Ir=XvMRgeWd}={Qy1=^W+a=?e+RQ z?D3u;2xL{SzECK@Dh}s!k~-*-U+sDr2@yNoO%FkJ?x)8EpP(gchs_fvJ`xO+%Fb1~l$NjD>rYA5aC=?1>YgFjhlc*3-07+@X zAgCF1K-w@1k`V+_C|1M=)X+x-{p{dulBCUMSSXq>aCz<+iczFV)s|PX+;;c$sDNgU zO>$cR8y@eaSjjSOo@$;Ikct`T3C13uAtb;76<6|OPeA+<;DW032J2F8J{~|qP#HIU z10Ej$@&HmU$w{A1TSY?J!b?8a$8ox}v@$Y09z~7g%b@%m&qBgs4irmA(5Xn$2X}mJOq0LlZ~l#bT1DMkWgh^NoD z=V}sOi{6R&gn*fuV{?luzwqYQ|M}nCFh4ifsxANC^}n~gaBOPgaH&){G(E4BdSuVh z&Ex$Ov&-dDWQ-ac>RqhYTa7F-!3C#pT&UHAU1ZE~U-u*X4_hbIQXyw<#(5M4gWZ+c zx#cv^jaL0V)jda!5m6NA&_qY3=3A{6kbd7E{jW=}xRQuJ^5MUjIC^wwV4&8B3y~@4 zaJil=)tf&tFciBbzb+=_zVPW?fdUFtxd+xqlGO4vZq_DipizZEp;9iEO07Ihn_5IN zo7j4?ylipeXd|{{iq*bKwHNCPOYCfKSEP#J_OrH(cXv@3tQ#JyhUMY&w_eiI8$~9I zZ5V2;RBo*}tC6(P6evT?z?_NLRKrE0oKZ@WthF#tR&+TExX00WWdvP90Pg(Uoo>f|H;q45T@3em^NTEI^b^w$y`5VW5z~0T=*K zA{M|Z_ww;j*nZ)QUwH7oyG;~oL(FVUfY=uNL_}kZW#@BQTFs^}dg{w;Dy0O#1Oexn zhw}-k5S2cE)921Q>*Cj)bKw%p-es&e<&LJlZI=5Ba(WM(UUuj7V_5?ru?U@d{U!pH zaytX>@kR>b_+-Ko&!}~G>w!Lu|4{#6UwLtHuD@Ezaz+#u&SQK2=FOW%yK~D%D{;JL28Y$Tn>t*^4vORb zF>cFkF|+sunzN2skQAWbM%wCjjvaypMiF$VKap65zy;?<0k_F_tK^+jL1 z+FDiSKmcH$e8ZPU|>*7!wr4$%Y3(&^fQ*mMiv$pR#sMEH7{?q z0ucKQq@6o=zTgEfxb)IXmzS3p7Z*#Vl21kI?d=^N9^SZd z$DDIVjvN^n7`XcCt9R|%^~fWSc#;&X7S;v;MC@qm8Ex8-AQ6E|vTU%}uhC2`&zoaq zn>IA6Qn|3Ol1v>t)=V-aA*~ImD3mm_)>$HA=ae>uVlhr?VOXhDOL4u`YBrs-d1|5k zcF}78M(=Nz%jGz3YSMlKt&~>@AjD>~i7Z-cKf@YhlqQ#Rp68uJJpbBQ@{0#**WnWl zAOdb~av}j&0OPVuqkuS+FmNn0OUY8}$@&+OpEST2__?2hSG@{8{9*X?r@>k%7X3)po*~vQR*iumXn)QO z2M)k(x501x1}rQb-wY9w1Qr(o;K>u8p9vEI#GC%=#*127}D(0=_6P|HI@LJ07O5rtB0_0BOr7I{E;2yKX_>D zveQOiyRjOOd}`mymM-_gfu+=v1NR$uj4es`+c$RwNUA%U-FxsGfAir7KJy8HxpL3e z%@ZR)419{Qt2NGN);8A`ZsJE&a!=v?o1cwl{Tof zI1A3A)*yo500G1Tvu85^1FT|~hz0Bx~I zmtA`Cz|iRZ_urrI`s3>^efVcS<>scAi}^bikG&c(YPJ%9VB6{2_U+y69j#}t1`?vi zQ+A+deWFBE{^#)k5`unw5r}q_v)wiXuhT>fNMTedhB~cfNahuX3pGyX!7?7DA`1D=W3Wf&TIJW1O@S8*ey$%jQiRl*YsRk1Q`P`-G>b)zl71@VmeJ zyMO-Yf9_M7{1R{L)~!jBh{(#y%KZHN4L96y!won5xBvFv-v9ph13(9zotT)o?6S+| z=H}k=mbZNT;~#$laKfWUi;IizeCIp={_p?3^LeRMYBrm#R%>c%>c0E#yWxf#1_lN` z@PQBf?9cuzoGj-F8~`FX1cRQ5ECNU<49I>s(f|Z#h!mLswILGc@@h32=rU2ccgLd> ztyWqoMK3si+oqu*1rQj;BG$SzNq0Uvb;sTNR_gIevsEtXjaxSzIxw}kxa?H!bzz(X z1%k+EMOZ+2I7tAiNCOZY1F#@~q{J}*w*y)gfX2yt%c(wL<}AznXjUi`N~Kb#1Ofo$ zc^=1cxm@;P(9YcI0VkzYy;QoS9rSf~=b2quUUqqmEW(^6`Gid7dEVF4+uPk!>ZuG440ctzN|ln< zfQH%?7XSglktU^;MrWB=Y%6KjR+eikjw#O)u~O;kDpxB>mZwQ#)5PeYSSf?!Qnkw{ z4XJI^n#F1*DnzZg(c9ZwD0tO$ZpO6}Z#Cd*t)r9AzfN*1*+~H;63y}?lw=mSy8B50 zBt9%y&#XOqZ0X92FJ4($92p)VBYXGH z4E1*}%r3?m2VoR|j1Kgcs$~?aH|x9i92o5HotaMr#Q8xQn+Q~#)C&EF2DHvzJdOu6Eks=6`T3e!h&T(2FtYdX%;CwIMl%^6?!V}Q3x4LOUjKs2UKq#m-klF0Jai}s!Z^(W zt&~z-<8{9NqCWzJdGJ-#WNnP{vmpco{jSTJj)w#AAX zL8MHzRP8Fca#tQ_oaKYv#x`5o;&PHZQ;hls2fF&B4EVKgeBt?h1vNUTwYFKJwhR*@ z3kxE%b3QQaEVDRvF1MU#*4flKVaVb*X*E${b84mDQi3GifgbHjSDLxCmc%)6nXt|C zJj-o%&J*|7$G-qJmpqgFWEn{9p87;nq&N#FcliZ~#eV#}DzLrY@0KpoNUSJuSB?8atX@GypFc zl)-`qU?)T<*haq}W6sH`mPEv0?X&K(S}S=jxjiLPb;9R<5!b1~)80m*_OJyawjFN< zBSqLfmR7n=KuiERZdPdSUjMjq~1eX<>0`W_mIV zgY_H6qSBTFM-GQ|TMcEjd+_k|VhrdM0E<{Bs$J2_i^Zb=`jS5+Ubb5BF*LGVaz$Ev zhQsPoW|d&(lXnnNA$mvb>h8>lMO`}ZBKuQZ701mu(ekrAD{=$tbj+<7={T2nA_l7gtD zmH)y|zr3%fytL8`jF!g~I`SFAAc9^!>jbVzC(DOB8g{Em#{MZeCjcHla)cy+?Ft