From 6b78b5c2be7e24cd4a1c59c7fa13a62c2ae33508 Mon Sep 17 00:00:00 2001 From: Alex Astashyn Date: Sat, 3 Dec 2016 19:05:09 -0500 Subject: [PATCH 01/80] Added strtonum for locale-independent number parsing --- src/json.hpp | 374 ++++++++++++++++++++++------------- src/json.hpp.re2c | 374 ++++++++++++++++++++++------------- test/src/unit-regression.cpp | 4 +- 3 files changed, 483 insertions(+), 269 deletions(-) diff --git a/src/json.hpp b/src/json.hpp index 6fed0a12..e28333bd 100644 --- a/src/json.hpp +++ b/src/json.hpp @@ -9060,65 +9060,225 @@ basic_json_parser_66: return result; } + + + + + + + + + + + + + + + + + /*! - @brief parse floating point number + @brief parse string into a built-in arithmetic type as if + the current locale is POSIX. - This function (and its overloads) serves to select the most approprate - standard floating point number parsing function based on the type - supplied via the first parameter. Set this to @a - static_cast(nullptr). + e.g. const auto x = static_cast("123.4"); - @param[in] type the @ref number_float_t in use - - @param[in,out] endptr recieves a pointer to the first character after - the number - - @return the floating point number + throw if can't parse the entire string as a number, + or if the destination type is integral and the value + is outside of the type's range. */ - long double str_to_float_t(long double* /* type */, char** endptr) const + struct strtonum { - return std::strtold(reinterpret_cast(m_start), endptr); - } + public: + strtonum(const char* start, const char* end) + : m_start(start), m_end(end) + {} - /*! - @brief parse floating point number + template::value>::type > + operator T() const + { + T val{0}; - This function (and its overloads) serves to select the most approprate - standard floating point number parsing function based on the type - supplied via the first parameter. Set this to @a - static_cast(nullptr). + if(parse(val, std::is_integral())) { + return val; + } - @param[in] type the @ref number_float_t in use + throw std::invalid_argument( + std::string() + + "Can't parse '" + + std::string(m_start, m_end) + + "' as type " + + typeid(T).name()); + } - @param[in,out] endptr recieves a pointer to the first character after - the number + /// return true iff token matches ^[+-]\d+$ + bool is_integral() const + { + const char* p = m_start; - @return the floating point number - */ - double str_to_float_t(double* /* type */, char** endptr) const - { - return std::strtod(reinterpret_cast(m_start), endptr); - } + if(!p) { + return false; + } - /*! - @brief parse floating point number + if(*p == '-' or *p == '+') { + ++p; + } - This function (and its overloads) serves to select the most approprate - standard floating point number parsing function based on the type - supplied via the first parameter. Set this to @a - static_cast(nullptr). + if(p == m_end) { + return false; + } - @param[in] type the @ref number_float_t in use + while(p < m_end and *p >= '0' and *p <= '9') { + ++p; + } - @param[in,out] endptr recieves a pointer to the first character after - the number + return p == m_end; + } - @return the floating point number - */ - float str_to_float_t(float* /* type */, char** endptr) const - { - return std::strtof(reinterpret_cast(m_start), endptr); - } + private: + const char* const m_start = nullptr; + const char* const m_end = nullptr; + + static void strtof(float& f, + const char* str, + char** endptr) + { + f = std::strtof(str, endptr); + } + + static void strtof(double& f, + const char* str, + char** endptr) + { + f = std::strtod(str, endptr); + } + + static void strtof(long double& f, + const char* str, + char** endptr) + { + f = std::strtold(str, endptr); + } + + template + bool parse(T& value, /*is_integral=*/std::false_type) const + { + const char* data = m_start; + const size_t len = static_cast(m_end - m_start); + + const char decimal_point_char = + std::use_facet< std::numpunct >( + std::locale()).decimal_point(); + + // replace decimal separator with locale-specific + // version, if necessary; data will be repointed + // to either buf or tempstr containing the fixed + // string. + std::string tempstr; + std::array buf; + do { + if(decimal_point_char == '.') { + break; // don't need to convert + } + + const size_t ds_pos = static_cast( + std::find(m_start, m_end, '.') - m_start ); + + if(ds_pos == len) { + break; // no decimal separator + } + + // copy the data into the local buffer or + // tempstr, if buffer is too small; + // replace decimal separator, and update + // data to point to the modified bytes + if(len + 1 < buf.size()) { + std::copy(m_start, m_end, buf.data()); + buf[len] = 0; + buf[ds_pos] = decimal_point_char; + data = buf.data(); + } else { + tempstr.assign(m_start, m_end); + tempstr[ds_pos] = decimal_point_char; + data = tempstr.c_str(); + } + } while(0); + + char* endptr = nullptr; + value = 0; + strtof(value, data, &endptr); + + + + // note that reading past the end is OK, the data may be, + // for example, "123.", where the parsed token only contains "123", + // but strtod will read the dot as well. + const bool ok = endptr >= data + len + and len > 0; + + if(ok and value == 0.0 and *data == '-') { + // some implementations forget to negate the zero + value = -0.0; + } + + if(!ok) { + std::cerr << "data:" << data + << " token:" << std::string(m_start, len) + << " value:" << value + << " len:" << len + << " parsed_len:" << (endptr - data) << std::endl; + } + + return ok; + } + + template + bool parse(T& value, /*is_integral=*/std::true_type) const + { + const char* beg = m_start; + const char* const end = m_end; + + if(beg == end) { + return false; + } + + const bool is_negative = (*beg == '-'); + + // json numbers can't start with '+' but + // this code is not json-specific + if(is_negative or *beg == '+') { + ++beg; // skip the leading sign + } + + bool valid = beg < end // must have some digits; + and ( T(-1) < 0 // type must be signed + or !is_negative); // if value is negative + value = 0; + + while(beg < end and valid) { + const uint8_t c = static_cast(*beg - '0'); + const T upd_value = value * 10 + c; + valid &= value <= std::numeric_limits::max() / 10 + and value <= upd_value // did not overflow + and c < 10; // char was digit + value = upd_value; + ++beg; + } + + if(is_negative) { + value = 0 - value; + } + + if(!valid) { + std::cerr << " token:" << std::string(m_start, m_end) + << std::endl; + } + + return valid; + } + }; /*! @brief return number value for number tokens @@ -9126,111 +9286,57 @@ basic_json_parser_66: This function translates the last token into the most appropriate number type (either integer, unsigned integer or floating point), which is passed back to the caller via the result parameter. + + integral numbers that don't fit into the the range of the respective + type are parsed as number_float_t - This function parses the integer component up to the radix point or - exponent while collecting information about the 'floating point - representation', which it stores in the result parameter. If there is - no radix point or exponent, and the number can fit into a @ref - number_integer_t or @ref number_unsigned_t then it sets the result - parameter accordingly. + floating-point values do not satisfy std::isfinite predicate + are converted to value_t::null + + throws if the entire string [m_start .. m_cursor) cannot be + interpreted as a number - If the number is a floating point number the number is then parsed - using @a std:strtod (or @a std:strtof or @a std::strtold). - - @param[out] result @ref basic_json object to receive the number, or - NAN if the conversion read past the current token. The latter case - needs to be treated by the caller function. + @param[out] result @ref basic_json object to receive the number. */ void get_number(basic_json& result) const { assert(m_start != nullptr); + assert(m_start < m_cursor); + + strtonum num(reinterpret_cast(m_start), + reinterpret_cast(m_cursor)); - const lexer::lexer_char_t* curptr = m_start; + const bool is_negative = *m_start == '-'; - // accumulate the integer conversion result (unsigned for now) - number_unsigned_t value = 0; - - // maximum absolute value of the relevant integer type - number_unsigned_t max; - - // temporarily store the type to avoid unecessary bitfield access - value_t type; - - // look for sign - if (*curptr == '-') - { - type = value_t::number_integer; - max = static_cast((std::numeric_limits::max)()) + 1; - curptr++; - } - else - { - type = value_t::number_unsigned; - max = static_cast((std::numeric_limits::max)()); - } - - // count the significant figures - for (; curptr < m_cursor; curptr++) - { - // quickly skip tests if a digit - if (*curptr < '0' || *curptr > '9') + try { + if(not num.is_integral()) { + ; + } + else if(is_negative) { - if (*curptr == '.') - { - // don't count '.' but change to float - type = value_t::number_float; - continue; - } - // assume exponent (if not then will fail parse): change to - // float, stop counting and record exponent details - type = value_t::number_float; - break; - } - - // skip if definitely not an integer - if (type != value_t::number_float) + result.m_type = value_t::number_integer; + result.m_value = static_cast(num); + return; + } + else { - // multiply last value by ten and add the new digit - auto temp = value * 10 + *curptr - '0'; - - // test for overflow - if (temp < value || temp > max) - { - // overflow - type = value_t::number_float; - } - else - { - // no overflow - save it - value = temp; - } + result.m_type = value_t::number_unsigned; + result.m_value = static_cast(num); + return; } + } catch (std::invalid_argument&) { + ; // overflow - will parse as double } - // save the value (if not a float) - if (type == value_t::number_unsigned) - { - result.m_value.number_unsigned = value; - } - else if (type == value_t::number_integer) - { - result.m_value.number_integer = -static_cast(value); - } - else - { - // parse with strtod - result.m_value.number_float = str_to_float_t(static_cast(nullptr), NULL); + result.m_type = value_t::number_float; + result.m_value = static_cast(num); - // replace infinity and NAN by null - if (not std::isfinite(result.m_value.number_float)) - { - type = value_t::null; - result.m_value = basic_json::json_value(); - } + // replace infinity and NAN by null + if (not std::isfinite(result.m_value.number_float)) + { + result.m_type = value_t::null; + result.m_value = basic_json::json_value(); } - - // save the type - result.m_type = type; } private: diff --git a/src/json.hpp.re2c b/src/json.hpp.re2c index c6a99b89..72c413ba 100644 --- a/src/json.hpp.re2c +++ b/src/json.hpp.re2c @@ -8209,65 +8209,225 @@ class basic_json return result; } + + + + + + + + + + + + + + + + + /*! - @brief parse floating point number + @brief parse string into a built-in arithmetic type as if + the current locale is POSIX. - This function (and its overloads) serves to select the most approprate - standard floating point number parsing function based on the type - supplied via the first parameter. Set this to @a - static_cast(nullptr). + e.g. const auto x = static_cast("123.4"); - @param[in] type the @ref number_float_t in use - - @param[in,out] endptr recieves a pointer to the first character after - the number - - @return the floating point number + throw if can't parse the entire string as a number, + or if the destination type is integral and the value + is outside of the type's range. */ - long double str_to_float_t(long double* /* type */, char** endptr) const + struct strtonum { - return std::strtold(reinterpret_cast(m_start), endptr); - } + public: + strtonum(const char* start, const char* end) + : m_start(start), m_end(end) + {} - /*! - @brief parse floating point number + template::value>::type > + operator T() const + { + T val{0}; - This function (and its overloads) serves to select the most approprate - standard floating point number parsing function based on the type - supplied via the first parameter. Set this to @a - static_cast(nullptr). + if(parse(val, std::is_integral())) { + return val; + } - @param[in] type the @ref number_float_t in use + throw std::invalid_argument( + std::string() + + "Can't parse '" + + std::string(m_start, m_end) + + "' as type " + + typeid(T).name()); + } - @param[in,out] endptr recieves a pointer to the first character after - the number + /// return true iff token matches ^[+-]\d+$ + bool is_integral() const + { + const char* p = m_start; - @return the floating point number - */ - double str_to_float_t(double* /* type */, char** endptr) const - { - return std::strtod(reinterpret_cast(m_start), endptr); - } + if(!p) { + return false; + } - /*! - @brief parse floating point number + if(*p == '-' or *p == '+') { + ++p; + } - This function (and its overloads) serves to select the most approprate - standard floating point number parsing function based on the type - supplied via the first parameter. Set this to @a - static_cast(nullptr). + if(p == m_end) { + return false; + } - @param[in] type the @ref number_float_t in use + while(p < m_end and *p >= '0' and *p <= '9') { + ++p; + } - @param[in,out] endptr recieves a pointer to the first character after - the number + return p == m_end; + } - @return the floating point number - */ - float str_to_float_t(float* /* type */, char** endptr) const - { - return std::strtof(reinterpret_cast(m_start), endptr); - } + private: + const char* const m_start = nullptr; + const char* const m_end = nullptr; + + static void strtof(float& f, + const char* str, + char** endptr) + { + f = std::strtof(str, endptr); + } + + static void strtof(double& f, + const char* str, + char** endptr) + { + f = std::strtod(str, endptr); + } + + static void strtof(long double& f, + const char* str, + char** endptr) + { + f = std::strtold(str, endptr); + } + + template + bool parse(T& value, /*is_integral=*/std::false_type) const + { + const char* data = m_start; + const size_t len = static_cast(m_end - m_start); + + const char decimal_point_char = + std::use_facet< std::numpunct >( + std::locale()).decimal_point(); + + // replace decimal separator with locale-specific + // version, if necessary; data will be repointed + // to either buf or tempstr containing the fixed + // string. + std::string tempstr; + std::array buf; + do { + if(decimal_point_char == '.') { + break; // don't need to convert + } + + const size_t ds_pos = static_cast( + std::find(m_start, m_end, '.') - m_start ); + + if(ds_pos == len) { + break; // no decimal separator + } + + // copy the data into the local buffer or + // tempstr, if buffer is too small; + // replace decimal separator, and update + // data to point to the modified bytes + if(len + 1 < buf.size()) { + std::copy(m_start, m_end, buf.data()); + buf[len] = 0; + buf[ds_pos] = decimal_point_char; + data = buf.data(); + } else { + tempstr.assign(m_start, m_end); + tempstr[ds_pos] = decimal_point_char; + data = tempstr.c_str(); + } + } while(0); + + char* endptr = nullptr; + value = 0; + strtof(value, data, &endptr); + + + + // note that reading past the end is OK, the data may be, + // for example, "123.", where the parsed token only contains "123", + // but strtod will read the dot as well. + const bool ok = endptr >= data + len + and len > 0; + + if(ok and value == 0.0 and *data == '-') { + // some implementations forget to negate the zero + value = -0.0; + } + + if(!ok) { + std::cerr << "data:" << data + << " token:" << std::string(m_start, len) + << " value:" << value + << " len:" << len + << " parsed_len:" << (endptr - data) << std::endl; + } + + return ok; + } + + template + bool parse(T& value, /*is_integral=*/std::true_type) const + { + const char* beg = m_start; + const char* const end = m_end; + + if(beg == end) { + return false; + } + + const bool is_negative = (*beg == '-'); + + // json numbers can't start with '+' but + // this code is not json-specific + if(is_negative or *beg == '+') { + ++beg; // skip the leading sign + } + + bool valid = beg < end // must have some digits; + and ( T(-1) < 0 // type must be signed + or !is_negative); // if value is negative + value = 0; + + while(beg < end and valid) { + const uint8_t c = static_cast(*beg - '0'); + const T upd_value = value * 10 + c; + valid &= value <= std::numeric_limits::max() / 10 + and value <= upd_value // did not overflow + and c < 10; // char was digit + value = upd_value; + ++beg; + } + + if(is_negative) { + value = 0 - value; + } + + if(!valid) { + std::cerr << " token:" << std::string(m_start, m_end) + << std::endl; + } + + return valid; + } + }; /*! @brief return number value for number tokens @@ -8275,111 +8435,57 @@ class basic_json This function translates the last token into the most appropriate number type (either integer, unsigned integer or floating point), which is passed back to the caller via the result parameter. + + integral numbers that don't fit into the the range of the respective + type are parsed as number_float_t - This function parses the integer component up to the radix point or - exponent while collecting information about the 'floating point - representation', which it stores in the result parameter. If there is - no radix point or exponent, and the number can fit into a @ref - number_integer_t or @ref number_unsigned_t then it sets the result - parameter accordingly. + floating-point values do not satisfy std::isfinite predicate + are converted to value_t::null + + throws if the entire string [m_start .. m_cursor) cannot be + interpreted as a number - If the number is a floating point number the number is then parsed - using @a std:strtod (or @a std:strtof or @a std::strtold). - - @param[out] result @ref basic_json object to receive the number, or - NAN if the conversion read past the current token. The latter case - needs to be treated by the caller function. + @param[out] result @ref basic_json object to receive the number. */ void get_number(basic_json& result) const { assert(m_start != nullptr); + assert(m_start < m_cursor); + + strtonum num(reinterpret_cast(m_start), + reinterpret_cast(m_cursor)); - const lexer::lexer_char_t* curptr = m_start; + const bool is_negative = *m_start == '-'; - // accumulate the integer conversion result (unsigned for now) - number_unsigned_t value = 0; - - // maximum absolute value of the relevant integer type - number_unsigned_t max; - - // temporarily store the type to avoid unecessary bitfield access - value_t type; - - // look for sign - if (*curptr == '-') - { - type = value_t::number_integer; - max = static_cast((std::numeric_limits::max)()) + 1; - curptr++; - } - else - { - type = value_t::number_unsigned; - max = static_cast((std::numeric_limits::max)()); - } - - // count the significant figures - for (; curptr < m_cursor; curptr++) - { - // quickly skip tests if a digit - if (*curptr < '0' || *curptr > '9') + try { + if(not num.is_integral()) { + ; + } + else if(is_negative) { - if (*curptr == '.') - { - // don't count '.' but change to float - type = value_t::number_float; - continue; - } - // assume exponent (if not then will fail parse): change to - // float, stop counting and record exponent details - type = value_t::number_float; - break; - } - - // skip if definitely not an integer - if (type != value_t::number_float) + result.m_type = value_t::number_integer; + result.m_value = static_cast(num); + return; + } + else { - // multiply last value by ten and add the new digit - auto temp = value * 10 + *curptr - '0'; - - // test for overflow - if (temp < value || temp > max) - { - // overflow - type = value_t::number_float; - } - else - { - // no overflow - save it - value = temp; - } + result.m_type = value_t::number_unsigned; + result.m_value = static_cast(num); + return; } + } catch (std::invalid_argument&) { + ; // overflow - will parse as double } - // save the value (if not a float) - if (type == value_t::number_unsigned) - { - result.m_value.number_unsigned = value; - } - else if (type == value_t::number_integer) - { - result.m_value.number_integer = -static_cast(value); - } - else - { - // parse with strtod - result.m_value.number_float = str_to_float_t(static_cast(nullptr), NULL); + result.m_type = value_t::number_float; + result.m_value = static_cast(num); - // replace infinity and NAN by null - if (not std::isfinite(result.m_value.number_float)) - { - type = value_t::null; - result.m_value = basic_json::json_value(); - } + // replace infinity and NAN by null + if (not std::isfinite(result.m_value.number_float)) + { + result.m_type = value_t::null; + result.m_value = basic_json::json_value(); } - - // save the type - result.m_type = type; } private: diff --git a/test/src/unit-regression.cpp b/test/src/unit-regression.cpp index e04513ca..679b7f3d 100644 --- a/test/src/unit-regression.cpp +++ b/test/src/unit-regression.cpp @@ -375,7 +375,7 @@ TEST_CASE("regression tests") }; // change locale to mess with decimal points - std::locale::global(std::locale(std::locale(), new CommaDecimalSeparator)); + auto orig_locale = std::locale::global(std::locale(std::locale(), new CommaDecimalSeparator)); CHECK(j1a.dump() == "23.42"); CHECK(j1b.dump() == "23.42"); @@ -399,6 +399,8 @@ TEST_CASE("regression tests") CHECK(j3c.dump() == "10000"); //CHECK(j3b.dump() == "1E04"); // roundtrip error //CHECK(j3c.dump() == "1e04"); // roundtrip error + + std::locale::global(orig_locale); } SECTION("issue #233 - Can't use basic_json::iterator as a base iterator for std::move_iterator") From 4eafaab8164667a2c309ac5b346981542b0873e5 Mon Sep 17 00:00:00 2001 From: Alex Astashyn Date: Sat, 3 Dec 2016 22:54:36 -0500 Subject: [PATCH 02/80] Improved overflow detection; removed debugging output statements. --- src/json.hpp | 47 ++++++++++++++++++++++++----------------------- src/json.hpp.re2c | 47 ++++++++++++++++++++++++----------------------- 2 files changed, 48 insertions(+), 46 deletions(-) diff --git a/src/json.hpp b/src/json.hpp index e28333bd..70bfce5a 100644 --- a/src/json.hpp +++ b/src/json.hpp @@ -9223,14 +9223,6 @@ basic_json_parser_66: value = -0.0; } - if(!ok) { - std::cerr << "data:" << data - << " token:" << std::string(m_start, len) - << " value:" << value - << " len:" << len - << " parsed_len:" << (endptr - data) << std::endl; - } - return ok; } @@ -9252,31 +9244,40 @@ basic_json_parser_66: ++beg; // skip the leading sign } + // using unsigned accumulator x because the signed + // type can't hold absolute value of largest + // negative value of this type, so overflow detection + // becomes problematic. + using unsigned_T = typename std::make_unsigned::type; + unsigned_T x = 0; + bool valid = beg < end // must have some digits; and ( T(-1) < 0 // type must be signed or !is_negative); // if value is negative - value = 0; while(beg < end and valid) { const uint8_t c = static_cast(*beg - '0'); - const T upd_value = value * 10 + c; - valid &= value <= std::numeric_limits::max() / 10 - and value <= upd_value // did not overflow - and c < 10; // char was digit - value = upd_value; + const unsigned_T upd_x = x * 10 + c; + + using lim_T = std::numeric_limits; + constexpr unsigned_T thr1 = lim_T::max() / 10; + valid &= c < 10 // char was digit + and x <= thr1 // multiplication did not overflow + and x <= upd_x; // addition did not overflow. + + // note that x <= upd_x alone can't detect overflow since + // we're not just adding a value of decltype(x) but + // also multiplying by 10 + + x = upd_x; ++beg; } - if(is_negative) { - value = 0 - value; - } + value = static_cast(is_negative ? 0 - x : x); - if(!valid) { - std::cerr << " token:" << std::string(m_start, m_end) - << std::endl; - } - - return valid; + // the final check to make sure the value did not roll over + // into positives is for edge cases, e.g. -2^63 + return valid && (is_negative == (value < 0)); } }; diff --git a/src/json.hpp.re2c b/src/json.hpp.re2c index 72c413ba..418e302c 100644 --- a/src/json.hpp.re2c +++ b/src/json.hpp.re2c @@ -8372,14 +8372,6 @@ class basic_json value = -0.0; } - if(!ok) { - std::cerr << "data:" << data - << " token:" << std::string(m_start, len) - << " value:" << value - << " len:" << len - << " parsed_len:" << (endptr - data) << std::endl; - } - return ok; } @@ -8401,31 +8393,40 @@ class basic_json ++beg; // skip the leading sign } + // using unsigned accumulator x because the signed + // type can't hold absolute value of largest + // negative value of this type, so overflow detection + // becomes problematic. + using unsigned_T = typename std::make_unsigned::type; + unsigned_T x = 0; + bool valid = beg < end // must have some digits; and ( T(-1) < 0 // type must be signed or !is_negative); // if value is negative - value = 0; while(beg < end and valid) { const uint8_t c = static_cast(*beg - '0'); - const T upd_value = value * 10 + c; - valid &= value <= std::numeric_limits::max() / 10 - and value <= upd_value // did not overflow - and c < 10; // char was digit - value = upd_value; + const unsigned_T upd_x = x * 10 + c; + + using lim_T = std::numeric_limits; + constexpr unsigned_T thr1 = lim_T::max() / 10; + valid &= c < 10 // char was digit + and x <= thr1 // multiplication did not overflow + and x <= upd_x; // addition did not overflow. + + // note that x <= upd_x alone can't detect overflow since + // we're not just adding a value of decltype(x) but + // also multiplying by 10 + + x = upd_x; ++beg; } - if(is_negative) { - value = 0 - value; - } + value = static_cast(is_negative ? 0 - x : x); - if(!valid) { - std::cerr << " token:" << std::string(m_start, m_end) - << std::endl; - } - - return valid; + // the final check to make sure the value did not roll over + // into positives is for edge cases, e.g. -2^63 + return valid && (is_negative == (value < 0)); } }; From c75efedc6ec7048244300a6305b25b2e117b440c Mon Sep 17 00:00:00 2001 From: Alex Astashyn Date: Sat, 3 Dec 2016 23:19:43 -0500 Subject: [PATCH 03/80] stylistic changes --- src/json.hpp | 92 ++++++++++++++++++++++++++--------------------- src/json.hpp.re2c | 92 ++++++++++++++++++++++++++--------------------- 2 files changed, 104 insertions(+), 80 deletions(-) diff --git a/src/json.hpp b/src/json.hpp index 70bfce5a..56949a4c 100644 --- a/src/json.hpp +++ b/src/json.hpp @@ -9060,22 +9060,6 @@ basic_json_parser_66: return result; } - - - - - - - - - - - - - - - - /*! @brief parse string into a built-in arithmetic type as if @@ -9086,6 +9070,9 @@ basic_json_parser_66: throw if can't parse the entire string as a number, or if the destination type is integral and the value is outside of the type's range. + + note: in floating-point case strtod may parse + past the token's end - this is not an error. */ struct strtonum { @@ -9101,7 +9088,8 @@ basic_json_parser_66: { T val{0}; - if(parse(val, std::is_integral())) { + if (parse(val, std::is_integral())) + { return val; } @@ -9113,24 +9101,35 @@ basic_json_parser_66: + typeid(T).name()); } - /// return true iff token matches ^[+-]\d+$ + // return true iff token matches ^[+-]\d+$ + // + // this is a helper to determine whether to + // parse the token into floating-point or + // integral type. We wouldn't need it if + // we had separate token types for interal + // and floating-point cases. bool is_integral() const { const char* p = m_start; - if(!p) { + if (!p) + { return false; } - if(*p == '-' or *p == '+') { + if (*p == '-' or *p == '+') + { ++p; } - if(p == m_end) { + if (p == m_end) + { return false; } - while(p < m_end and *p >= '0' and *p <= '9') { + while (p < m_end and *p >= '0' + and *p <= '9') + { ++p; } @@ -9141,6 +9140,9 @@ basic_json_parser_66: const char* const m_start = nullptr; const char* const m_end = nullptr; + // overloaded wrappers for strtod/strtof/strtold + // that will be called from parse + static void strtof(float& f, const char* str, char** endptr) @@ -9173,20 +9175,22 @@ basic_json_parser_66: std::locale()).decimal_point(); // replace decimal separator with locale-specific - // version, if necessary; data will be repointed + // version, when necessary; data will be repointed // to either buf or tempstr containing the fixed // string. std::string tempstr; std::array buf; do { - if(decimal_point_char == '.') { + if (decimal_point_char == '.') + { break; // don't need to convert } const size_t ds_pos = static_cast( std::find(m_start, m_end, '.') - m_start ); - if(ds_pos == len) { + if (ds_pos == len) + { break; // no decimal separator } @@ -9194,31 +9198,33 @@ basic_json_parser_66: // tempstr, if buffer is too small; // replace decimal separator, and update // data to point to the modified bytes - if(len + 1 < buf.size()) { + if (len + 1 < buf.size()) + { std::copy(m_start, m_end, buf.data()); buf[len] = 0; buf[ds_pos] = decimal_point_char; data = buf.data(); - } else { + } + else + { tempstr.assign(m_start, m_end); tempstr[ds_pos] = decimal_point_char; data = tempstr.c_str(); } - } while(0); + } while (0); char* endptr = nullptr; value = 0; strtof(value, data, &endptr); - - // note that reading past the end is OK, the data may be, - // for example, "123.", where the parsed token only contains "123", - // but strtod will read the dot as well. + // for example, "123.", where the parsed token only + // contains "123", but strtod will read the dot as well. const bool ok = endptr >= data + len and len > 0; - if(ok and value == 0.0 and *data == '-') { + if (ok and value == 0.0 and *data == '-') + { // some implementations forget to negate the zero value = -0.0; } @@ -9232,15 +9238,17 @@ basic_json_parser_66: const char* beg = m_start; const char* const end = m_end; - if(beg == end) { + if (beg == end) + { return false; } const bool is_negative = (*beg == '-'); // json numbers can't start with '+' but - // this code is not json-specific - if(is_negative or *beg == '+') { + // this code is not strictly json-specific + if (is_negative or *beg == '+') + { ++beg; // skip the leading sign } @@ -9255,7 +9263,8 @@ basic_json_parser_66: and ( T(-1) < 0 // type must be signed or !is_negative); // if value is negative - while(beg < end and valid) { + while (beg < end and valid) + { const uint8_t c = static_cast(*beg - '0'); const unsigned_T upd_x = x * 10 + c; @@ -9310,10 +9319,11 @@ basic_json_parser_66: const bool is_negative = *m_start == '-'; try { - if(not num.is_integral()) { + if (not num.is_integral()) + { ; } - else if(is_negative) + else if (is_negative) { result.m_type = value_t::number_integer; result.m_value = static_cast(num); @@ -9325,7 +9335,9 @@ basic_json_parser_66: result.m_value = static_cast(num); return; } - } catch (std::invalid_argument&) { + } + catch (std::invalid_argument&) + { ; // overflow - will parse as double } diff --git a/src/json.hpp.re2c b/src/json.hpp.re2c index 418e302c..d97057a8 100644 --- a/src/json.hpp.re2c +++ b/src/json.hpp.re2c @@ -8209,22 +8209,6 @@ class basic_json return result; } - - - - - - - - - - - - - - - - /*! @brief parse string into a built-in arithmetic type as if @@ -8235,6 +8219,9 @@ class basic_json throw if can't parse the entire string as a number, or if the destination type is integral and the value is outside of the type's range. + + note: in floating-point case strtod may parse + past the token's end - this is not an error. */ struct strtonum { @@ -8250,7 +8237,8 @@ class basic_json { T val{0}; - if(parse(val, std::is_integral())) { + if (parse(val, std::is_integral())) + { return val; } @@ -8262,24 +8250,35 @@ class basic_json + typeid(T).name()); } - /// return true iff token matches ^[+-]\d+$ + // return true iff token matches ^[+-]\d+$ + // + // this is a helper to determine whether to + // parse the token into floating-point or + // integral type. We wouldn't need it if + // we had separate token types for interal + // and floating-point cases. bool is_integral() const { const char* p = m_start; - if(!p) { + if (!p) + { return false; } - if(*p == '-' or *p == '+') { + if (*p == '-' or *p == '+') + { ++p; } - if(p == m_end) { + if (p == m_end) + { return false; } - while(p < m_end and *p >= '0' and *p <= '9') { + while (p < m_end and *p >= '0' + and *p <= '9') + { ++p; } @@ -8290,6 +8289,9 @@ class basic_json const char* const m_start = nullptr; const char* const m_end = nullptr; + // overloaded wrappers for strtod/strtof/strtold + // that will be called from parse + static void strtof(float& f, const char* str, char** endptr) @@ -8322,20 +8324,22 @@ class basic_json std::locale()).decimal_point(); // replace decimal separator with locale-specific - // version, if necessary; data will be repointed + // version, when necessary; data will be repointed // to either buf or tempstr containing the fixed // string. std::string tempstr; std::array buf; do { - if(decimal_point_char == '.') { + if (decimal_point_char == '.') + { break; // don't need to convert } const size_t ds_pos = static_cast( std::find(m_start, m_end, '.') - m_start ); - if(ds_pos == len) { + if (ds_pos == len) + { break; // no decimal separator } @@ -8343,31 +8347,33 @@ class basic_json // tempstr, if buffer is too small; // replace decimal separator, and update // data to point to the modified bytes - if(len + 1 < buf.size()) { + if (len + 1 < buf.size()) + { std::copy(m_start, m_end, buf.data()); buf[len] = 0; buf[ds_pos] = decimal_point_char; data = buf.data(); - } else { + } + else + { tempstr.assign(m_start, m_end); tempstr[ds_pos] = decimal_point_char; data = tempstr.c_str(); } - } while(0); + } while (0); char* endptr = nullptr; value = 0; strtof(value, data, &endptr); - - // note that reading past the end is OK, the data may be, - // for example, "123.", where the parsed token only contains "123", - // but strtod will read the dot as well. + // for example, "123.", where the parsed token only + // contains "123", but strtod will read the dot as well. const bool ok = endptr >= data + len and len > 0; - if(ok and value == 0.0 and *data == '-') { + if (ok and value == 0.0 and *data == '-') + { // some implementations forget to negate the zero value = -0.0; } @@ -8381,15 +8387,17 @@ class basic_json const char* beg = m_start; const char* const end = m_end; - if(beg == end) { + if (beg == end) + { return false; } const bool is_negative = (*beg == '-'); // json numbers can't start with '+' but - // this code is not json-specific - if(is_negative or *beg == '+') { + // this code is not strictly json-specific + if (is_negative or *beg == '+') + { ++beg; // skip the leading sign } @@ -8404,7 +8412,8 @@ class basic_json and ( T(-1) < 0 // type must be signed or !is_negative); // if value is negative - while(beg < end and valid) { + while (beg < end and valid) + { const uint8_t c = static_cast(*beg - '0'); const unsigned_T upd_x = x * 10 + c; @@ -8459,10 +8468,11 @@ class basic_json const bool is_negative = *m_start == '-'; try { - if(not num.is_integral()) { + if (not num.is_integral()) + { ; } - else if(is_negative) + else if (is_negative) { result.m_type = value_t::number_integer; result.m_value = static_cast(num); @@ -8474,7 +8484,9 @@ class basic_json result.m_value = static_cast(num); return; } - } catch (std::invalid_argument&) { + } + catch (std::invalid_argument&) + { ; // overflow - will parse as double } From 21cae35930a734fa726b1dc7cc73365b2b6c41b2 Mon Sep 17 00:00:00 2001 From: Alex Astashyn Date: Sun, 4 Dec 2016 01:27:22 -0500 Subject: [PATCH 04/80] Added locale-independent numtostr --- src/json.hpp | 179 ++++++++++++++++++++++++++++++++++++---------- src/json.hpp.re2c | 179 ++++++++++++++++++++++++++++++++++++---------- 2 files changed, 286 insertions(+), 72 deletions(-) diff --git a/src/json.hpp b/src/json.hpp index 6fed0a12..a4f28e03 100644 --- a/src/json.hpp +++ b/src/json.hpp @@ -2180,14 +2180,6 @@ class basic_json string_t dump(const int indent = -1) const { std::stringstream ss; - // fix locale problems - ss.imbue(std::locale::classic()); - - // 6, 15 or 16 digits of precision allows round-trip IEEE 754 - // string->float->string, string->double->string or string->long - // double->string; to be safe, we read this value from - // std::numeric_limits::digits10 - ss.precision(std::numeric_limits::digits10); if (indent >= 0) { @@ -5878,10 +5870,6 @@ class basic_json `std::setw(4)` on @a o sets the indentation level to `4` and the serialization result is the same as calling `dump(4)`. - @note During serializaion, the locale and the precision of the output - stream @a o are changed. The original values are restored when the - function returns. - @param[in,out] o stream to serialize to @param[in] j JSON value to serialize @@ -5903,22 +5891,9 @@ class basic_json // reset width to 0 for subsequent calls to this stream o.width(0); - // fix locale problems - const auto old_locale = o.imbue(std::locale::classic()); - // set precision - - // 6, 15 or 16 digits of precision allows round-trip IEEE 754 - // string->float->string, string->double->string or string->long - // double->string; to be safe, we read this value from - // std::numeric_limits::digits10 - const auto old_precision = o.precision(std::numeric_limits::digits10); - // do the actual serialization j.dump(o, pretty_print, static_cast(indentation)); - // reset locale and precision - o.imbue(old_locale); - o.precision(old_precision); return o; } @@ -6419,6 +6394,146 @@ class basic_json return result; } + + /*! + @brief locale-independent serialization for built-in arithmetic types + */ + struct numtostr + { + public: + template + numtostr(T value) + { + x_write(value, std::is_integral()); + } + + operator const char*() const + { + return m_buf.data(); + } + + const char* c_str() const + { + return m_buf.data(); + } + + private: + static constexpr size_t s_capacity = 30; + std::array m_buf{}; + + template + void x_write(T x, std::true_type) + { + const bool is_neg = x < 0; + size_t i = 0; + + while(x and i < s_capacity) + { + m_buf[i++] = '0' + abs(x % 10); + x /= 10; + } + + if(i == s_capacity) + { + std::runtime_error( + "Number is unexpectedly long: " + + std::to_string(x)); + } + + if(i == 0) + { + m_buf[i++] = '0'; + } + + if(is_neg) + { + m_buf[i++] = '-'; + } + + std::reverse(m_buf.begin(), m_buf.begin() + i); + } + + template + void x_write(T x, std::false_type) + { + if (x == 0) + { + std::strcpy(m_buf.data(), + std::signbit(x) ? "-0.0" : "0.0"); + return; + } + + static constexpr auto d = + std::numeric_limits::digits10+1; + + // I'm not sure why we need that +1 above, if at all, + // but without it there's a unit-test that fails + // that asserts precision of the output + + static_assert(d == 6 or d == 15 or d == 16 or d == 17, ""); + static constexpr auto fmt = d == 6 ? "%.6g" + : d == 15 ? "%.15g" + : d == 16 ? "%.16g" + : d == 17 ? "%.17g" + : "%.18g"; + + snprintf(m_buf.data(), m_buf.size(), fmt, x); + + const std::locale loc; + + // erase thousands separator + { + const char sep = + std::use_facet< std::numpunct >( + loc).thousands_sep(); + + auto end = std::remove(m_buf.begin(), + m_buf.end(), + sep); + + std::fill(end, m_buf.end(), '\0'); + } + + // convert decimal point to '.' + { + const char decimal_point = + std::use_facet< std::numpunct >( + loc).decimal_point(); + + for(auto& c : m_buf) + { + if(decimal_point == '.') { + break; + } + + if(c == decimal_point) + { + c = '.'; + break; + } + } + } + + // determine if need to apperd ".0" + auto data_end = m_buf.begin() + strlen(m_buf.data()); + + const bool value_is_int_like = + std::find_if(m_buf.begin(), data_end, + [](const char c) + { return (c >= '0' and c <= '9') + or c == '-'; }) + == data_end; + + assert(data_end + 2 < m_buf.end()); + if(value_is_int_like) + { + strcat(m_buf.data(), ".0"); + } + } + }; + + + /*! @brief internal implementation of the serialization function @@ -6538,27 +6653,19 @@ class basic_json case value_t::number_integer: { - o << m_value.number_integer; + o << numtostr(m_value.number_integer).c_str(); return; } case value_t::number_unsigned: { - o << m_value.number_unsigned; + o << numtostr(m_value.number_unsigned).c_str(); return; } case value_t::number_float: { - if (m_value.number_float == 0) - { - // special case for zero to get "0.0"/"-0.0" - o << (std::signbit(m_value.number_float) ? "-0.0" : "0.0"); - } - else - { - o << m_value.number_float; - } + o << numtostr(m_value.number_float).c_str(); return; } diff --git a/src/json.hpp.re2c b/src/json.hpp.re2c index c6a99b89..b9716c9e 100644 --- a/src/json.hpp.re2c +++ b/src/json.hpp.re2c @@ -2180,14 +2180,6 @@ class basic_json string_t dump(const int indent = -1) const { std::stringstream ss; - // fix locale problems - ss.imbue(std::locale::classic()); - - // 6, 15 or 16 digits of precision allows round-trip IEEE 754 - // string->float->string, string->double->string or string->long - // double->string; to be safe, we read this value from - // std::numeric_limits::digits10 - ss.precision(std::numeric_limits::digits10); if (indent >= 0) { @@ -5878,10 +5870,6 @@ class basic_json `std::setw(4)` on @a o sets the indentation level to `4` and the serialization result is the same as calling `dump(4)`. - @note During serializaion, the locale and the precision of the output - stream @a o are changed. The original values are restored when the - function returns. - @param[in,out] o stream to serialize to @param[in] j JSON value to serialize @@ -5903,22 +5891,9 @@ class basic_json // reset width to 0 for subsequent calls to this stream o.width(0); - // fix locale problems - const auto old_locale = o.imbue(std::locale::classic()); - // set precision - - // 6, 15 or 16 digits of precision allows round-trip IEEE 754 - // string->float->string, string->double->string or string->long - // double->string; to be safe, we read this value from - // std::numeric_limits::digits10 - const auto old_precision = o.precision(std::numeric_limits::digits10); - // do the actual serialization j.dump(o, pretty_print, static_cast(indentation)); - // reset locale and precision - o.imbue(old_locale); - o.precision(old_precision); return o; } @@ -6419,6 +6394,146 @@ class basic_json return result; } + + /*! + @brief locale-independent serialization for built-in arithmetic types + */ + struct numtostr + { + public: + template + numtostr(T value) + { + x_write(value, std::is_integral()); + } + + operator const char*() const + { + return m_buf.data(); + } + + const char* c_str() const + { + return m_buf.data(); + } + + private: + static constexpr size_t s_capacity = 30; + std::array m_buf{}; + + template + void x_write(T x, std::true_type) + { + const bool is_neg = x < 0; + size_t i = 0; + + while(x and i < s_capacity) + { + m_buf[i++] = '0' + abs(x % 10); + x /= 10; + } + + if(i == s_capacity) + { + std::runtime_error( + "Number is unexpectedly long: " + + std::to_string(x)); + } + + if(i == 0) + { + m_buf[i++] = '0'; + } + + if(is_neg) + { + m_buf[i++] = '-'; + } + + std::reverse(m_buf.begin(), m_buf.begin() + i); + } + + template + void x_write(T x, std::false_type) + { + if (x == 0) + { + std::strcpy(m_buf.data(), + std::signbit(x) ? "-0.0" : "0.0"); + return; + } + + static constexpr auto d = + std::numeric_limits::digits10+1; + + // I'm not sure why we need that +1 above, if at all, + // but without it there's a unit-test that fails + // that asserts precision of the output + + static_assert(d == 6 or d == 15 or d == 16 or d == 17, ""); + static constexpr auto fmt = d == 6 ? "%.6g" + : d == 15 ? "%.15g" + : d == 16 ? "%.16g" + : d == 17 ? "%.17g" + : "%.18g"; + + snprintf(m_buf.data(), m_buf.size(), fmt, x); + + const std::locale loc; + + // erase thousands separator + { + const char sep = + std::use_facet< std::numpunct >( + loc).thousands_sep(); + + auto end = std::remove(m_buf.begin(), + m_buf.end(), + sep); + + std::fill(end, m_buf.end(), '\0'); + } + + // convert decimal point to '.' + { + const char decimal_point = + std::use_facet< std::numpunct >( + loc).decimal_point(); + + for(auto& c : m_buf) + { + if(decimal_point == '.') { + break; + } + + if(c == decimal_point) + { + c = '.'; + break; + } + } + } + + // determine if need to apperd ".0" + auto data_end = m_buf.begin() + strlen(m_buf.data()); + + const bool value_is_int_like = + std::find_if(m_buf.begin(), data_end, + [](const char c) + { return (c >= '0' and c <= '9') + or c == '-'; }) + == data_end; + + assert(data_end + 2 < m_buf.end()); + if(value_is_int_like) + { + strcat(m_buf.data(), ".0"); + } + } + }; + + + /*! @brief internal implementation of the serialization function @@ -6538,27 +6653,19 @@ class basic_json case value_t::number_integer: { - o << m_value.number_integer; + o << numtostr(m_value.number_integer).c_str(); return; } case value_t::number_unsigned: { - o << m_value.number_unsigned; + o << numtostr(m_value.number_unsigned).c_str(); return; } case value_t::number_float: { - if (m_value.number_float == 0) - { - // special case for zero to get "0.0"/"-0.0" - o << (std::signbit(m_value.number_float) ? "-0.0" : "0.0"); - } - else - { - o << m_value.number_float; - } + o << numtostr(m_value.number_float).c_str(); return; } From 219785639595d5f0276df1b9e21d14956233c3da Mon Sep 17 00:00:00 2001 From: Alex Astashyn Date: Sun, 4 Dec 2016 01:38:23 -0500 Subject: [PATCH 05/80] Fixed suffixing .0 and modified the unit tests accordingly --- src/json.hpp | 5 +++-- src/json.hpp.re2c | 5 +++-- test/src/unit-regression.cpp | 6 +++--- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/src/json.hpp b/src/json.hpp index a4f28e03..a886c436 100644 --- a/src/json.hpp +++ b/src/json.hpp @@ -6520,8 +6520,9 @@ class basic_json const bool value_is_int_like = std::find_if(m_buf.begin(), data_end, [](const char c) - { return (c >= '0' and c <= '9') - or c == '-'; }) + { return c == '.' + or c == 'e' + or c == 'E'; }) == data_end; assert(data_end + 2 < m_buf.end()); diff --git a/src/json.hpp.re2c b/src/json.hpp.re2c index b9716c9e..dd7af5dd 100644 --- a/src/json.hpp.re2c +++ b/src/json.hpp.re2c @@ -6520,8 +6520,9 @@ class basic_json const bool value_is_int_like = std::find_if(m_buf.begin(), data_end, [](const char c) - { return (c >= '0' and c <= '9') - or c == '-'; }) + { return c == '.' + or c == 'e' + or c == 'E'; }) == data_end; assert(data_end + 2 < m_buf.end()); diff --git a/test/src/unit-regression.cpp b/test/src/unit-regression.cpp index e04513ca..ada1e104 100644 --- a/test/src/unit-regression.cpp +++ b/test/src/unit-regression.cpp @@ -394,9 +394,9 @@ TEST_CASE("regression tests") //issue #230 //CHECK(j2b.dump() == "23.42"); - CHECK(j3a.dump() == "10000"); - CHECK(j3b.dump() == "10000"); - CHECK(j3c.dump() == "10000"); + CHECK(j3a.dump() == "10000.0"); + CHECK(j3b.dump() == "10000.0"); + CHECK(j3c.dump() == "10000.0"); //CHECK(j3b.dump() == "1E04"); // roundtrip error //CHECK(j3c.dump() == "1e04"); // roundtrip error } From e41a956782fd64a2bdf253a13f05bc5e8239ec61 Mon Sep 17 00:00:00 2001 From: Alex Astashyn Date: Sun, 4 Dec 2016 13:23:39 -0500 Subject: [PATCH 06/80] Alternative handling of integer types relying on strto[u]ll --- src/json.hpp | 46 ++++++++++++++++++++++++++++++++++++++++++++-- src/json.hpp.re2c | 46 ++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 88 insertions(+), 4 deletions(-) diff --git a/src/json.hpp b/src/json.hpp index 56949a4c..51b19518 100644 --- a/src/json.hpp +++ b/src/json.hpp @@ -9073,6 +9073,8 @@ basic_json_parser_66: note: in floating-point case strtod may parse past the token's end - this is not an error. + + any leading blanks are not handled. */ struct strtonum { @@ -9232,6 +9234,45 @@ basic_json_parser_66: return ok; } + +#if 1 // parsing with strto[u]ll - easier to understand but slightly slower + + signed long long parse_integral( + char** endptr, + /*is_signed*/std::true_type) const + { + return std::strtoll(m_start, endptr, 10); + } + + unsigned long long parse_integral( + char** endptr, + /*is_signed*/std::false_type) const + { + return std::strtoull(m_start, endptr, 10); + } + + template + bool parse(T& value, /*is_integral=*/std::true_type) const + { + char* endptr = nullptr; + errno = 0; // these are thread-local + const auto x = parse_integral(&endptr, std::is_signed()); + + static_assert(std::is_signed() // called right overload? + == std::is_signed(), ""); + + value = static_cast(x); + + return x == static_cast(value) // x fits into destination T + and (x != 0 or is_integral()) // strto[u]ll did nto fail + and errno == 0 // strto[u]ll did not overflow + and m_start < m_end // token was not empty + and endptr == m_end // parsed entire token exactly + and (x < 0) == (*m_start == '-'); // input was sign-compatible + } + +#else // parsing integral types manually + template bool parse(T& value, /*is_integral=*/std::true_type) const { @@ -9240,7 +9281,7 @@ basic_json_parser_66: if (beg == end) { - return false; + return false; // empty token } const bool is_negative = (*beg == '-'); @@ -9261,7 +9302,7 @@ basic_json_parser_66: bool valid = beg < end // must have some digits; and ( T(-1) < 0 // type must be signed - or !is_negative); // if value is negative + or !is_negative); // ...if value is negative while (beg < end and valid) { @@ -9288,6 +9329,7 @@ basic_json_parser_66: // into positives is for edge cases, e.g. -2^63 return valid && (is_negative == (value < 0)); } +#endif }; /*! diff --git a/src/json.hpp.re2c b/src/json.hpp.re2c index d97057a8..e5f344b2 100644 --- a/src/json.hpp.re2c +++ b/src/json.hpp.re2c @@ -8222,6 +8222,8 @@ class basic_json note: in floating-point case strtod may parse past the token's end - this is not an error. + + any leading blanks are not handled. */ struct strtonum { @@ -8381,6 +8383,45 @@ class basic_json return ok; } + +#if 1 // parsing with strto[u]ll - easier to understand but slightly slower + + signed long long parse_integral( + char** endptr, + /*is_signed*/std::true_type) const + { + return std::strtoll(m_start, endptr, 10); + } + + unsigned long long parse_integral( + char** endptr, + /*is_signed*/std::false_type) const + { + return std::strtoull(m_start, endptr, 10); + } + + template + bool parse(T& value, /*is_integral=*/std::true_type) const + { + char* endptr = nullptr; + errno = 0; // these are thread-local + const auto x = parse_integral(&endptr, std::is_signed()); + + static_assert(std::is_signed() // called right overload? + == std::is_signed(), ""); + + value = static_cast(x); + + return x == static_cast(value) // x fits into destination T + and (x != 0 or is_integral()) // strto[u]ll did nto fail + and errno == 0 // strto[u]ll did not overflow + and m_start < m_end // token was not empty + and endptr == m_end // parsed entire token exactly + and (x < 0) == (*m_start == '-'); // input was sign-compatible + } + +#else // parsing integral types manually + template bool parse(T& value, /*is_integral=*/std::true_type) const { @@ -8389,7 +8430,7 @@ class basic_json if (beg == end) { - return false; + return false; // empty token } const bool is_negative = (*beg == '-'); @@ -8410,7 +8451,7 @@ class basic_json bool valid = beg < end // must have some digits; and ( T(-1) < 0 // type must be signed - or !is_negative); // if value is negative + or !is_negative); // ...if value is negative while (beg < end and valid) { @@ -8437,6 +8478,7 @@ class basic_json // into positives is for edge cases, e.g. -2^63 return valid && (is_negative == (value < 0)); } +#endif }; /*! From 509447b4d5ca42c03d15e4de810c528c0fb25986 Mon Sep 17 00:00:00 2001 From: Alex Astashyn Date: Mon, 5 Dec 2016 19:03:39 -0500 Subject: [PATCH 07/80] Small bufix related to creation of fmt string for snprintf --- src/json.hpp | 17 ++++++++--------- src/json.hpp.re2c | 17 ++++++++--------- 2 files changed, 16 insertions(+), 18 deletions(-) diff --git a/src/json.hpp b/src/json.hpp index a886c436..14780ca8 100644 --- a/src/json.hpp +++ b/src/json.hpp @@ -6464,19 +6464,18 @@ class basic_json } static constexpr auto d = - std::numeric_limits::digits10+1; + std::numeric_limits::digits10; + static_assert(d == 6 or d == 15 or d == 16 or d == 17, ""); - // I'm not sure why we need that +1 above, if at all, + static constexpr auto fmt = d == 6 ? "%.7g" + : d == 15 ? "%.16g" + : d == 16 ? "%.17g" + : d == 17 ? "%.18g" + : "%.19g"; + // I'm not sure why we need to +1 the precision, // but without it there's a unit-test that fails // that asserts precision of the output - static_assert(d == 6 or d == 15 or d == 16 or d == 17, ""); - static constexpr auto fmt = d == 6 ? "%.6g" - : d == 15 ? "%.15g" - : d == 16 ? "%.16g" - : d == 17 ? "%.17g" - : "%.18g"; - snprintf(m_buf.data(), m_buf.size(), fmt, x); const std::locale loc; diff --git a/src/json.hpp.re2c b/src/json.hpp.re2c index dd7af5dd..cac41603 100644 --- a/src/json.hpp.re2c +++ b/src/json.hpp.re2c @@ -6464,19 +6464,18 @@ class basic_json } static constexpr auto d = - std::numeric_limits::digits10+1; + std::numeric_limits::digits10; + static_assert(d == 6 or d == 15 or d == 16 or d == 17, ""); - // I'm not sure why we need that +1 above, if at all, + static constexpr auto fmt = d == 6 ? "%.7g" + : d == 15 ? "%.16g" + : d == 16 ? "%.17g" + : d == 17 ? "%.18g" + : "%.19g"; + // I'm not sure why we need to +1 the precision, // but without it there's a unit-test that fails // that asserts precision of the output - static_assert(d == 6 or d == 15 or d == 16 or d == 17, ""); - static constexpr auto fmt = d == 6 ? "%.6g" - : d == 15 ? "%.15g" - : d == 16 ? "%.16g" - : d == 17 ? "%.17g" - : "%.18g"; - snprintf(m_buf.data(), m_buf.size(), fmt, x); const std::locale loc; From 82b82fd48709429d7e87a72e4c11d1f290bf5752 Mon Sep 17 00:00:00 2001 From: Alex Astashyn Date: Mon, 5 Dec 2016 20:33:28 -0500 Subject: [PATCH 08/80] Addressing msvc-specific compilation issues. --- src/json.hpp | 2 +- src/json.hpp.re2c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/json.hpp b/src/json.hpp index 14780ca8..e0d94f77 100644 --- a/src/json.hpp +++ b/src/json.hpp @@ -6429,7 +6429,7 @@ class basic_json while(x and i < s_capacity) { - m_buf[i++] = '0' + abs(x % 10); + m_buf[i++] = static_cast('0' + std::labs(x % 10)); x /= 10; } diff --git a/src/json.hpp.re2c b/src/json.hpp.re2c index cac41603..87977da6 100644 --- a/src/json.hpp.re2c +++ b/src/json.hpp.re2c @@ -6429,7 +6429,7 @@ class basic_json while(x and i < s_capacity) { - m_buf[i++] = '0' + abs(x % 10); + m_buf[i++] = static_cast('0' + std::labs(x % 10)); x /= 10; } From 738d4629554eae1870ea4f79308b22d12107c83f Mon Sep 17 00:00:00 2001 From: Alex Astashyn Date: Tue, 6 Dec 2016 00:23:58 -0500 Subject: [PATCH 09/80] Bugfix: when working with C formatting functions we need to query C locales (localeconv) rather than std::locale --- src/json.hpp | 59 +++++++++++++++++++++++++++++------------------ src/json.hpp.re2c | 59 +++++++++++++++++++++++++++++------------------ 2 files changed, 72 insertions(+), 46 deletions(-) diff --git a/src/json.hpp b/src/json.hpp index e0d94f77..876c35b6 100644 --- a/src/json.hpp +++ b/src/json.hpp @@ -6419,11 +6419,14 @@ class basic_json private: static constexpr size_t s_capacity = 30; - std::array m_buf{}; + std::array m_buf{}; // +2 for leading '-' + // and trailing '\0' template void x_write(T x, std::true_type) { + static_assert(std::numeric_limits::digits10 <= s_capacity, ""); + const bool is_neg = x < 0; size_t i = 0; @@ -6433,12 +6436,7 @@ class basic_json x /= 10; } - if(i == s_capacity) - { - std::runtime_error( - "Number is unexpectedly long: " - + std::to_string(x)); - } + assert(i < s_capacity); if(i == 0) { @@ -6478,34 +6476,49 @@ class basic_json snprintf(m_buf.data(), m_buf.size(), fmt, x); +#if 0 + // C locales and C++ locales are similar but + // different. + // + // If working with C++ streams we'd've used + // these, but for C formatting functions we + // have to use C locales (setlocale / localeconv), + // rather than C++ locales (std::locale installed + // by std::locale::global()). const std::locale loc; - // erase thousands separator - { - const char sep = - std::use_facet< std::numpunct >( - loc).thousands_sep(); + const char thousands_sep = + std::use_facet< std::numpunct >( + loc).thousands_sep(); + const char decimal_point = + std::use_facet< std::numpunct >( + loc).decimal_point(); +#else + const auto loc = localeconv(); + assert(loc != nullptr); + const char thousands_sep = !loc->thousands_sep ? '\0' + : loc->thousands_sep[0]; + + const char decimal_point = !loc->decimal_point ? '\0' + : loc->decimal_point[0]; +#endif + + // erase thousands separator + if (thousands_sep) { auto end = std::remove(m_buf.begin(), m_buf.end(), - sep); + thousands_sep); std::fill(end, m_buf.end(), '\0'); } // convert decimal point to '.' + if (decimal_point and decimal_point != '.') { - const char decimal_point = - std::use_facet< std::numpunct >( - loc).decimal_point(); - - for(auto& c : m_buf) + for (auto& c : m_buf) { - if(decimal_point == '.') { - break; - } - - if(c == decimal_point) + if (c == decimal_point) { c = '.'; break; diff --git a/src/json.hpp.re2c b/src/json.hpp.re2c index 87977da6..55574bee 100644 --- a/src/json.hpp.re2c +++ b/src/json.hpp.re2c @@ -6419,11 +6419,14 @@ class basic_json private: static constexpr size_t s_capacity = 30; - std::array m_buf{}; + std::array m_buf{}; // +2 for leading '-' + // and trailing '\0' template void x_write(T x, std::true_type) { + static_assert(std::numeric_limits::digits10 <= s_capacity, ""); + const bool is_neg = x < 0; size_t i = 0; @@ -6433,12 +6436,7 @@ class basic_json x /= 10; } - if(i == s_capacity) - { - std::runtime_error( - "Number is unexpectedly long: " - + std::to_string(x)); - } + assert(i < s_capacity); if(i == 0) { @@ -6478,34 +6476,49 @@ class basic_json snprintf(m_buf.data(), m_buf.size(), fmt, x); +#if 0 + // C locales and C++ locales are similar but + // different. + // + // If working with C++ streams we'd've used + // these, but for C formatting functions we + // have to use C locales (setlocale / localeconv), + // rather than C++ locales (std::locale installed + // by std::locale::global()). const std::locale loc; - // erase thousands separator - { - const char sep = - std::use_facet< std::numpunct >( - loc).thousands_sep(); + const char thousands_sep = + std::use_facet< std::numpunct >( + loc).thousands_sep(); + const char decimal_point = + std::use_facet< std::numpunct >( + loc).decimal_point(); +#else + const auto loc = localeconv(); + assert(loc != nullptr); + const char thousands_sep = !loc->thousands_sep ? '\0' + : loc->thousands_sep[0]; + + const char decimal_point = !loc->decimal_point ? '\0' + : loc->decimal_point[0]; +#endif + + // erase thousands separator + if (thousands_sep) { auto end = std::remove(m_buf.begin(), m_buf.end(), - sep); + thousands_sep); std::fill(end, m_buf.end(), '\0'); } // convert decimal point to '.' + if (decimal_point and decimal_point != '.') { - const char decimal_point = - std::use_facet< std::numpunct >( - loc).decimal_point(); - - for(auto& c : m_buf) + for (auto& c : m_buf) { - if(decimal_point == '.') { - break; - } - - if(c == decimal_point) + if (c == decimal_point) { c = '.'; break; From d64336057569281386aafed096a6db77d8aa901a Mon Sep 17 00:00:00 2001 From: Alex Astashyn Date: Tue, 6 Dec 2016 00:43:12 -0500 Subject: [PATCH 10/80] Bugfix: when working with C formatting functions we need to query C locales (localeconv) rather than std::locale --- src/json.hpp | 12 +++++++++++- src/json.hpp.re2c | 12 +++++++++++- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/src/json.hpp b/src/json.hpp index 51b19518..f1666c6c 100644 --- a/src/json.hpp +++ b/src/json.hpp @@ -9108,7 +9108,7 @@ basic_json_parser_66: // this is a helper to determine whether to // parse the token into floating-point or // integral type. We wouldn't need it if - // we had separate token types for interal + // we had separate token types for integral // and floating-point cases. bool is_integral() const { @@ -9172,9 +9172,19 @@ basic_json_parser_66: const char* data = m_start; const size_t len = static_cast(m_end - m_start); +#if 0 const char decimal_point_char = std::use_facet< std::numpunct >( std::locale()).decimal_point(); +#else + // Since dealing with strtod family of functions, + // need to use the C locales instead of C++ + const auto loc = localeconv(); + assert(loc != nullptr); + const char decimal_point_char = + !loc->decimal_point ? '.' + : loc->decimal_point[0]; +#endif // replace decimal separator with locale-specific // version, when necessary; data will be repointed diff --git a/src/json.hpp.re2c b/src/json.hpp.re2c index e5f344b2..b8059035 100644 --- a/src/json.hpp.re2c +++ b/src/json.hpp.re2c @@ -8257,7 +8257,7 @@ class basic_json // this is a helper to determine whether to // parse the token into floating-point or // integral type. We wouldn't need it if - // we had separate token types for interal + // we had separate token types for integral // and floating-point cases. bool is_integral() const { @@ -8321,9 +8321,19 @@ class basic_json const char* data = m_start; const size_t len = static_cast(m_end - m_start); +#if 0 const char decimal_point_char = std::use_facet< std::numpunct >( std::locale()).decimal_point(); +#else + // Since dealing with strtod family of functions, + // need to use the C locales instead of C++ + const auto loc = localeconv(); + assert(loc != nullptr); + const char decimal_point_char = + !loc->decimal_point ? '.' + : loc->decimal_point[0]; +#endif // replace decimal separator with locale-specific // version, when necessary; data will be repointed From 0c87d5d6b34d8595ceb645be1e0b82c4a4eaafe2 Mon Sep 17 00:00:00 2001 From: Alex Astashyn Date: Tue, 6 Dec 2016 19:41:05 -0500 Subject: [PATCH 11/80] Refactored preprocessing with a lambda instead of do{...}while(0) --- src/json.hpp | 48 ++++++++++++++++++++++-------------------------- 1 file changed, 22 insertions(+), 26 deletions(-) diff --git a/src/json.hpp b/src/json.hpp index f1666c6c..19f1f109 100644 --- a/src/json.hpp +++ b/src/json.hpp @@ -9169,33 +9169,28 @@ basic_json_parser_66: template bool parse(T& value, /*is_integral=*/std::false_type) const { - const char* data = m_start; - const size_t len = static_cast(m_end - m_start); - -#if 0 - const char decimal_point_char = - std::use_facet< std::numpunct >( - std::locale()).decimal_point(); -#else - // Since dealing with strtod family of functions, - // need to use the C locales instead of C++ - const auto loc = localeconv(); - assert(loc != nullptr); - const char decimal_point_char = - !loc->decimal_point ? '.' - : loc->decimal_point[0]; -#endif - // replace decimal separator with locale-specific - // version, when necessary; data will be repointed - // to either buf or tempstr containing the fixed - // string. + // version, when necessary; data will point to + // either the original string, or buf, or tempstr + // containing the fixed string. std::string tempstr; std::array buf; - do { + const size_t len = static_cast(m_end - m_start); + + const char* const data = [this, &tempstr, &buf, len]() -> const char* + { + // Since dealing with strtod family of functions, + // we're getting the decimal point char from the + // C locale facilities instead of C++'s numpunct + // facet of the current std::locale; + const auto loc = localeconv(); + assert(loc != nullptr); + const char decimal_point_char = !loc->decimal_point ? '.' + : loc->decimal_point[0]; + if (decimal_point_char == '.') { - break; // don't need to convert + return m_start; // don't need to convert } const size_t ds_pos = static_cast( @@ -9203,7 +9198,7 @@ basic_json_parser_66: if (ds_pos == len) { - break; // no decimal separator + return m_start; // no decimal separator } // copy the data into the local buffer or @@ -9215,18 +9210,19 @@ basic_json_parser_66: std::copy(m_start, m_end, buf.data()); buf[len] = 0; buf[ds_pos] = decimal_point_char; - data = buf.data(); + return buf.data(); } else { tempstr.assign(m_start, m_end); tempstr[ds_pos] = decimal_point_char; - data = tempstr.c_str(); + return tempstr.c_str(); } - } while (0); + }(); char* endptr = nullptr; value = 0; + // this calls appropriate overload depending on T strtof(value, data, &endptr); // note that reading past the end is OK, the data may be, From 7a081244a575284246d38a594fb0436ca2b6dacc Mon Sep 17 00:00:00 2001 From: Alex Astashyn Date: Tue, 6 Dec 2016 19:41:31 -0500 Subject: [PATCH 12/80] Refactored preprocessing with a lambda instead of do{...}while(0) --- src/json.hpp.re2c | 48 ++++++++++++++++++++++------------------------- 1 file changed, 22 insertions(+), 26 deletions(-) diff --git a/src/json.hpp.re2c b/src/json.hpp.re2c index b8059035..27a53fb7 100644 --- a/src/json.hpp.re2c +++ b/src/json.hpp.re2c @@ -8318,33 +8318,28 @@ class basic_json template bool parse(T& value, /*is_integral=*/std::false_type) const { - const char* data = m_start; - const size_t len = static_cast(m_end - m_start); - -#if 0 - const char decimal_point_char = - std::use_facet< std::numpunct >( - std::locale()).decimal_point(); -#else - // Since dealing with strtod family of functions, - // need to use the C locales instead of C++ - const auto loc = localeconv(); - assert(loc != nullptr); - const char decimal_point_char = - !loc->decimal_point ? '.' - : loc->decimal_point[0]; -#endif - // replace decimal separator with locale-specific - // version, when necessary; data will be repointed - // to either buf or tempstr containing the fixed - // string. + // version, when necessary; data will point to + // either the original string, or buf, or tempstr + // containing the fixed string. std::string tempstr; std::array buf; - do { + const size_t len = static_cast(m_end - m_start); + + const char* const data = [this, &tempstr, &buf, len]() -> const char* + { + // Since dealing with strtod family of functions, + // we're getting the decimal point char from the + // C locale facilities instead of C++'s numpunct + // facet of the current std::locale; + const auto loc = localeconv(); + assert(loc != nullptr); + const char decimal_point_char = !loc->decimal_point ? '.' + : loc->decimal_point[0]; + if (decimal_point_char == '.') { - break; // don't need to convert + return m_start; // don't need to convert } const size_t ds_pos = static_cast( @@ -8352,7 +8347,7 @@ class basic_json if (ds_pos == len) { - break; // no decimal separator + return m_start; // no decimal separator } // copy the data into the local buffer or @@ -8364,18 +8359,19 @@ class basic_json std::copy(m_start, m_end, buf.data()); buf[len] = 0; buf[ds_pos] = decimal_point_char; - data = buf.data(); + return buf.data(); } else { tempstr.assign(m_start, m_end); tempstr[ds_pos] = decimal_point_char; - data = tempstr.c_str(); + return tempstr.c_str(); } - } while (0); + }(); char* endptr = nullptr; value = 0; + // this calls appropriate overload depending on T strtof(value, data, &endptr); // note that reading past the end is OK, the data may be, From 6e8da7d8c4aada79740076755ed487da505ceb28 Mon Sep 17 00:00:00 2001 From: Alex Astashyn Date: Tue, 6 Dec 2016 19:45:48 -0500 Subject: [PATCH 13/80] Added unit-test for issue #379 (locale-independent str-to-num) --- test/src/unit-regression.cpp | 38 ++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/test/src/unit-regression.cpp b/test/src/unit-regression.cpp index 679b7f3d..2787fe26 100644 --- a/test/src/unit-regression.cpp +++ b/test/src/unit-regression.cpp @@ -403,6 +403,44 @@ TEST_CASE("regression tests") std::locale::global(orig_locale); } + SECTION("issue #379 - locale-independent str-to-num") + { + const std::string orig_locale_name(setlocale(LC_ALL, NULL)); + + setlocale(LC_NUMERIC, "de_DE"); + std::array buf; + + { + // verify that snprintf now uses commas as decimal-separator + std::snprintf(buf.data(), buf.size(), "%.2f", 3.14); + assert(std::strcmp(buf.data(), "3,14") == 0); + + // verify that strtod now uses commas as decimal-separator + const double d1 = std::strtod(buf.data(), nullptr); + assert(d1 == 3.14); + + // verify that strtod does not understand dots as decimal separator + const double d2 = std::strtod("3.14", nullptr); + assert(d2 == 3); + } + + const json j1 = json::parse("3.14"); + + // verify that parsed correctly despite using strtod internally + CHECK(j1.get() == 3.14); + + // verify that dumped correctly despite using snprintf internally + CHECK(j1.dump() == "3.14"); + + // check a different code path + const json j2 = json::parse("1.000000000000000000000000000000000000000000000000000000000000000000000000"); + CHECK(j2.get() == 1.0); + + // restore original locale + setlocale(LC_ALL, orig_locale_name.c_str()); + } + + SECTION("issue #233 - Can't use basic_json::iterator as a base iterator for std::move_iterator") { json source = {"a", "b", "c"}; From d2e9ce270a642e4ca7e00fc160c81eadb55a5639 Mon Sep 17 00:00:00 2001 From: Alex Astashyn Date: Tue, 6 Dec 2016 22:18:20 -0500 Subject: [PATCH 14/80] Trying to coerce setlocale to make snprintf use commas as delimiter; the behavior appears to be compiler/platform-specific --- test/src/unit-regression.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/src/unit-regression.cpp b/test/src/unit-regression.cpp index 2787fe26..17616a3e 100644 --- a/test/src/unit-regression.cpp +++ b/test/src/unit-regression.cpp @@ -407,21 +407,21 @@ TEST_CASE("regression tests") { const std::string orig_locale_name(setlocale(LC_ALL, NULL)); - setlocale(LC_NUMERIC, "de_DE"); + setlocale(LC_NUMERIC, "fr_Fr.UTF-8"); std::array buf; { // verify that snprintf now uses commas as decimal-separator std::snprintf(buf.data(), buf.size(), "%.2f", 3.14); - assert(std::strcmp(buf.data(), "3,14") == 0); + CHECK(std::strcmp(buf.data(), "3,14") == 0); // verify that strtod now uses commas as decimal-separator const double d1 = std::strtod(buf.data(), nullptr); - assert(d1 == 3.14); + CHECK(d1 == 3.14); // verify that strtod does not understand dots as decimal separator const double d2 = std::strtod("3.14", nullptr); - assert(d2 == 3); + CHECK(d2 == 3); } const json j1 = json::parse("3.14"); From d169598c6c236ce115a8453d917d99efc79fa3a3 Mon Sep 17 00:00:00 2001 From: Alex Astashyn Date: Tue, 6 Dec 2016 22:20:48 -0500 Subject: [PATCH 15/80] simplified code a bit based on @gregmarr's suggestions --- src/json.hpp | 69 ++++++++++++++++++++++------------------------- src/json.hpp.re2c | 69 ++++++++++++++++++++++------------------------- 2 files changed, 64 insertions(+), 74 deletions(-) diff --git a/src/json.hpp b/src/json.hpp index 19f1f109..1644d91f 100644 --- a/src/json.hpp +++ b/src/json.hpp @@ -9177,48 +9177,43 @@ basic_json_parser_66: std::array buf; const size_t len = static_cast(m_end - m_start); - const char* const data = [this, &tempstr, &buf, len]() -> const char* + // Since dealing with strtod family of functions, + // we're getting the decimal point char from the + // C locale facilities instead of C++'s numpunct + // facet of the current std::locale; + const auto loc = localeconv(); + assert(loc != nullptr); + const char decimal_point_char = !loc->decimal_point ? '.' + : loc->decimal_point[0]; + + const char *data = m_start; + + if (decimal_point_char != '.') { - // Since dealing with strtod family of functions, - // we're getting the decimal point char from the - // C locale facilities instead of C++'s numpunct - // facet of the current std::locale; - const auto loc = localeconv(); - assert(loc != nullptr); - const char decimal_point_char = !loc->decimal_point ? '.' - : loc->decimal_point[0]; - - if (decimal_point_char == '.') - { - return m_start; // don't need to convert - } - const size_t ds_pos = static_cast( std::find(m_start, m_end, '.') - m_start ); - - if (ds_pos == len) + + if (ds_pos != len) { - return m_start; // no decimal separator + // copy the data into the local buffer or + // tempstr, if buffer is too small; + // replace decimal separator, and update + // data to point to the modified bytes + if (len + 1 < buf.size()) + { + std::copy(m_start, m_end, buf.data()); + buf[len] = 0; + buf[ds_pos] = decimal_point_char; + data = buf.data(); + } + else + { + tempstr.assign(m_start, m_end); + tempstr[ds_pos] = decimal_point_char; + data = tempstr.c_str(); + } } - - // copy the data into the local buffer or - // tempstr, if buffer is too small; - // replace decimal separator, and update - // data to point to the modified bytes - if (len + 1 < buf.size()) - { - std::copy(m_start, m_end, buf.data()); - buf[len] = 0; - buf[ds_pos] = decimal_point_char; - return buf.data(); - } - else - { - tempstr.assign(m_start, m_end); - tempstr[ds_pos] = decimal_point_char; - return tempstr.c_str(); - } - }(); + } char* endptr = nullptr; value = 0; diff --git a/src/json.hpp.re2c b/src/json.hpp.re2c index 27a53fb7..b541db1e 100644 --- a/src/json.hpp.re2c +++ b/src/json.hpp.re2c @@ -8326,48 +8326,43 @@ class basic_json std::array buf; const size_t len = static_cast(m_end - m_start); - const char* const data = [this, &tempstr, &buf, len]() -> const char* + // Since dealing with strtod family of functions, + // we're getting the decimal point char from the + // C locale facilities instead of C++'s numpunct + // facet of the current std::locale; + const auto loc = localeconv(); + assert(loc != nullptr); + const char decimal_point_char = !loc->decimal_point ? '.' + : loc->decimal_point[0]; + + const char *data = m_start; + + if (decimal_point_char != '.') { - // Since dealing with strtod family of functions, - // we're getting the decimal point char from the - // C locale facilities instead of C++'s numpunct - // facet of the current std::locale; - const auto loc = localeconv(); - assert(loc != nullptr); - const char decimal_point_char = !loc->decimal_point ? '.' - : loc->decimal_point[0]; - - if (decimal_point_char == '.') - { - return m_start; // don't need to convert - } - const size_t ds_pos = static_cast( std::find(m_start, m_end, '.') - m_start ); - - if (ds_pos == len) + + if (ds_pos != len) { - return m_start; // no decimal separator + // copy the data into the local buffer or + // tempstr, if buffer is too small; + // replace decimal separator, and update + // data to point to the modified bytes + if (len + 1 < buf.size()) + { + std::copy(m_start, m_end, buf.data()); + buf[len] = 0; + buf[ds_pos] = decimal_point_char; + data = buf.data(); + } + else + { + tempstr.assign(m_start, m_end); + tempstr[ds_pos] = decimal_point_char; + data = tempstr.c_str(); + } } - - // copy the data into the local buffer or - // tempstr, if buffer is too small; - // replace decimal separator, and update - // data to point to the modified bytes - if (len + 1 < buf.size()) - { - std::copy(m_start, m_end, buf.data()); - buf[len] = 0; - buf[ds_pos] = decimal_point_char; - return buf.data(); - } - else - { - tempstr.assign(m_start, m_end); - tempstr[ds_pos] = decimal_point_char; - return tempstr.c_str(); - } - }(); + } char* endptr = nullptr; value = 0; From 6774457733524e81d7aa6fd0f3df6fd48423d0f7 Mon Sep 17 00:00:00 2001 From: Alex Astashyn Date: Tue, 6 Dec 2016 22:59:12 -0500 Subject: [PATCH 16/80] Trying to coerce setlocale to make snprintf use commas as delimiter some more --- test/src/unit-regression.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/test/src/unit-regression.cpp b/test/src/unit-regression.cpp index 17616a3e..41ddfa40 100644 --- a/test/src/unit-regression.cpp +++ b/test/src/unit-regression.cpp @@ -405,9 +405,14 @@ TEST_CASE("regression tests") SECTION("issue #379 - locale-independent str-to-num") { - const std::string orig_locale_name(setlocale(LC_ALL, NULL)); + // If I save the locale here and restore it in the end + // of this block, then setLocale(LC_NUMERIC, "de_DE") + // does not actually make snprintf use "," as decimal separator + // on some compilers. I have no idea... + // + //const std::string orig_locale_name(setlocale(LC_ALL, NULL)); - setlocale(LC_NUMERIC, "fr_Fr.UTF-8"); + setlocale(LC_NUMERIC, "de_DE"); std::array buf; { @@ -437,7 +442,7 @@ TEST_CASE("regression tests") CHECK(j2.get() == 1.0); // restore original locale - setlocale(LC_ALL, orig_locale_name.c_str()); + // setlocale(LC_ALL, orig_locale_name.c_str()); } From 0a4a6a8399d1f4194d009c50ec076dd287cafa9e Mon Sep 17 00:00:00 2001 From: Alex Astashyn Date: Wed, 7 Dec 2016 19:53:27 -0500 Subject: [PATCH 17/80] Refactored to avoid using exceptions, as there are plans to support exceptionless mode --- src/json.hpp | 78 +++++++++++++++++++++++++++++++++++------------ src/json.hpp.re2c | 78 +++++++++++++++++++++++++++++++++++------------ 2 files changed, 118 insertions(+), 38 deletions(-) diff --git a/src/json.hpp b/src/json.hpp index 1644d91f..79d6bb02 100644 --- a/src/json.hpp +++ b/src/json.hpp @@ -9079,10 +9079,42 @@ basic_json_parser_66: struct strtonum { public: - strtonum(const char* start, const char* end) + template + struct maybe + { + T x; + bool valid; + + maybe(const T& xx) + : x(xx), valid(true) + {} + + maybe() : x(), valid(false) + {} + + operator bool() const + { + return valid; + } + + const T& operator*() const + { + return x; + } + }; + + strtonum(const char* start, const char* end) : m_start(start), m_end(end) {} + template::value>::type > + bool to(T& val) const + { + return parse(val, std::is_integral()); + } + template::value>::type > @@ -9361,31 +9393,39 @@ basic_json_parser_66: const bool is_negative = *m_start == '-'; - try { - if (not num.is_integral()) - { - ; - } - else if (is_negative) - { + result.m_type = value_t::discarded; + + if (not num.is_integral()) + { + ; // will parse as float below + } + else if (is_negative) + { + number_integer_t val{0}; + if(num.to(val)) { result.m_type = value_t::number_integer; - result.m_value = static_cast(num); - return; - } - else - { - result.m_type = value_t::number_unsigned; - result.m_value = static_cast(num); - return; + result.m_value = val; } } - catch (std::invalid_argument&) + else { - ; // overflow - will parse as double + number_unsigned_t val{0}; + if(num.to(val)) { + result.m_type = value_t::number_unsigned; + result.m_value = val; + } + } + + number_float_t val{0}; + if (result.m_type != value_t::discarded + or !num.to(val)) + { + return; // already have a value from above + // or couldn't parse as float_t } result.m_type = value_t::number_float; - result.m_value = static_cast(num); + result.m_value = val; // replace infinity and NAN by null if (not std::isfinite(result.m_value.number_float)) diff --git a/src/json.hpp.re2c b/src/json.hpp.re2c index b541db1e..24c54975 100644 --- a/src/json.hpp.re2c +++ b/src/json.hpp.re2c @@ -8228,10 +8228,42 @@ class basic_json struct strtonum { public: - strtonum(const char* start, const char* end) + template + struct maybe + { + T x; + bool valid; + + maybe(const T& xx) + : x(xx), valid(true) + {} + + maybe() : x(), valid(false) + {} + + operator bool() const + { + return valid; + } + + const T& operator*() const + { + return x; + } + }; + + strtonum(const char* start, const char* end) : m_start(start), m_end(end) {} + template::value>::type > + bool to(T& val) const + { + return parse(val, std::is_integral()); + } + template::value>::type > @@ -8510,31 +8542,39 @@ class basic_json const bool is_negative = *m_start == '-'; - try { - if (not num.is_integral()) - { - ; - } - else if (is_negative) - { + result.m_type = value_t::discarded; + + if (not num.is_integral()) + { + ; // will parse as float below + } + else if (is_negative) + { + number_integer_t val{0}; + if(num.to(val)) { result.m_type = value_t::number_integer; - result.m_value = static_cast(num); - return; - } - else - { - result.m_type = value_t::number_unsigned; - result.m_value = static_cast(num); - return; + result.m_value = val; } } - catch (std::invalid_argument&) + else { - ; // overflow - will parse as double + number_unsigned_t val{0}; + if(num.to(val)) { + result.m_type = value_t::number_unsigned; + result.m_value = val; + } + } + + number_float_t val{0}; + if (result.m_type != value_t::discarded + or !num.to(val)) + { + return; // already have a value from above + // or couldn't parse as float_t } result.m_type = value_t::number_float; - result.m_value = static_cast(num); + result.m_value = val; // replace infinity and NAN by null if (not std::isfinite(result.m_value.number_float)) From 27d9740ad6d9b564beb0e995e0ab393c6ab3daf7 Mon Sep 17 00:00:00 2001 From: Alex Astashyn Date: Wed, 7 Dec 2016 19:55:07 -0500 Subject: [PATCH 18/80] Tweaks to unit-test for issue #379 --- test/src/unit-regression.cpp | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/test/src/unit-regression.cpp b/test/src/unit-regression.cpp index 41ddfa40..deace862 100644 --- a/test/src/unit-regression.cpp +++ b/test/src/unit-regression.cpp @@ -406,22 +406,27 @@ TEST_CASE("regression tests") SECTION("issue #379 - locale-independent str-to-num") { // If I save the locale here and restore it in the end - // of this block, then setLocale(LC_NUMERIC, "de_DE") + // of this block, then setLocale(LC_NUMERIC, "de_DE") // does not actually make snprintf use "," as decimal separator // on some compilers. I have no idea... - // //const std::string orig_locale_name(setlocale(LC_ALL, NULL)); - - setlocale(LC_NUMERIC, "de_DE"); + + + // Still, just setting some comma-using locale does not + // make snprintf output commas on all platforms, so instead + // will change dot to comma in the current locale below + //setlocale(LC_NUMERIC, "de_DE"); + + auto loc = localeconv(); + auto orig_decimal_point = loc->decimal_point; + char comma[] = ","; + loc->decimal_point = comma; + std::array buf; { - // verify that snprintf now uses commas as decimal-separator - std::snprintf(buf.data(), buf.size(), "%.2f", 3.14); - CHECK(std::strcmp(buf.data(), "3,14") == 0); - // verify that strtod now uses commas as decimal-separator - const double d1 = std::strtod(buf.data(), nullptr); + const double d1 = std::strtod("3,14", nullptr); CHECK(d1 == 3.14); // verify that strtod does not understand dots as decimal separator @@ -429,18 +434,15 @@ TEST_CASE("regression tests") CHECK(d2 == 3); } - const json j1 = json::parse("3.14"); - // verify that parsed correctly despite using strtod internally + const json j1 = json::parse("3.14"); CHECK(j1.get() == 3.14); - // verify that dumped correctly despite using snprintf internally - CHECK(j1.dump() == "3.14"); - // check a different code path const json j2 = json::parse("1.000000000000000000000000000000000000000000000000000000000000000000000000"); CHECK(j2.get() == 1.0); + loc->decimal_point = orig_decimal_point; // restore original locale // setlocale(LC_ALL, orig_locale_name.c_str()); } From 50f0484ad532635ee362da9406b9f3948a3ee10c Mon Sep 17 00:00:00 2001 From: Alex Astashyn Date: Wed, 7 Dec 2016 20:23:25 -0500 Subject: [PATCH 19/80] Added unit test for issue #378 --- test/src/unit-regression.cpp | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/test/src/unit-regression.cpp b/test/src/unit-regression.cpp index ada1e104..3e303fbb 100644 --- a/test/src/unit-regression.cpp +++ b/test/src/unit-regression.cpp @@ -401,6 +401,41 @@ TEST_CASE("regression tests") //CHECK(j3c.dump() == "1e04"); // roundtrip error } + SECTION("issue #378 - locale-independent num-to-str") + { + setlocale(LC_NUMERIC, ""); + + auto loc = localeconv(); + auto orig_decimal_point = loc->decimal_point; + auto orig_thousands_sep = loc->thousands_sep; + char comma[] = ","; + char thsep[] = "'"; + + loc->decimal_point = comma; + loc->thousands_sep = thsep; + + // verify that snprintf uses special decimal and grouping characters + { + std::array buf; + std::snprintf(buf.data(), buf.size(), "%.2f", 12345.67); + CHECK(strcmp(buf.data(), "12345,67") == 0); + + buf.fill(0); + std::snprintf(buf.data(), buf.size(), "%'d", 1234567); + CHECK(strcmp(buf.data(), "1'234'567") == 0); + } + + // verify that dumped correctly with '.' and no grouping + const json j1 = 12345.67; + CHECK(j1.dump() == "12345.67"); + + const json j2 = 1234567; + CHECK(j2.dump() == "1234567"); + + loc->decimal_point = orig_decimal_point; + loc->thousands_sep = orig_thousands_sep; + } + SECTION("issue #233 - Can't use basic_json::iterator as a base iterator for std::move_iterator") { json source = {"a", "b", "c"}; From 38499e84fc771b21db7764ff4e014f7c3939d4b0 Mon Sep 17 00:00:00 2001 From: Alex Astashyn Date: Thu, 8 Dec 2016 21:38:14 -0500 Subject: [PATCH 20/80] Removed unused struct; fixed comments --- src/json.hpp | 69 +++++++++-------------------------------------- src/json.hpp.re2c | 69 +++++++++-------------------------------------- 2 files changed, 24 insertions(+), 114 deletions(-) diff --git a/src/json.hpp b/src/json.hpp index 79d6bb02..867afbb3 100644 --- a/src/json.hpp +++ b/src/json.hpp @@ -9065,12 +9065,6 @@ basic_json_parser_66: @brief parse string into a built-in arithmetic type as if the current locale is POSIX. - e.g. const auto x = static_cast("123.4"); - - throw if can't parse the entire string as a number, - or if the destination type is integral and the value - is outside of the type's range. - note: in floating-point case strtod may parse past the token's end - this is not an error. @@ -9079,34 +9073,15 @@ basic_json_parser_66: struct strtonum { public: - template - struct maybe - { - T x; - bool valid; - - maybe(const T& xx) - : x(xx), valid(true) - {} - - maybe() : x(), valid(false) - {} - - operator bool() const - { - return valid; - } - - const T& operator*() const - { - return x; - } - }; - strtonum(const char* start, const char* end) : m_start(start), m_end(end) {} + /// return true iff parsed successfully as + /// number of type T. + /// + /// @val shall contain parsed value, or + /// undefined value if could not parse. template::value>::type > @@ -9115,33 +9090,13 @@ basic_json_parser_66: return parse(val, std::is_integral()); } - template::value>::type > - operator T() const - { - T val{0}; - - if (parse(val, std::is_integral())) - { - return val; - } - - throw std::invalid_argument( - std::string() - + "Can't parse '" - + std::string(m_start, m_end) - + "' as type " - + typeid(T).name()); - } - - // return true iff token matches ^[+-]\d+$ - // - // this is a helper to determine whether to - // parse the token into floating-point or - // integral type. We wouldn't need it if - // we had separate token types for integral - // and floating-point cases. + /// return true iff token matches ^[+-]\d+$ + /// + /// this is a helper to determine whether to + /// parse the token into floating-point or + /// integral type. We wouldn't need it if + /// we had separate token types for integral + /// and floating-point cases. bool is_integral() const { const char* p = m_start; diff --git a/src/json.hpp.re2c b/src/json.hpp.re2c index 24c54975..5b2dc8d2 100644 --- a/src/json.hpp.re2c +++ b/src/json.hpp.re2c @@ -8214,12 +8214,6 @@ class basic_json @brief parse string into a built-in arithmetic type as if the current locale is POSIX. - e.g. const auto x = static_cast("123.4"); - - throw if can't parse the entire string as a number, - or if the destination type is integral and the value - is outside of the type's range. - note: in floating-point case strtod may parse past the token's end - this is not an error. @@ -8228,34 +8222,15 @@ class basic_json struct strtonum { public: - template - struct maybe - { - T x; - bool valid; - - maybe(const T& xx) - : x(xx), valid(true) - {} - - maybe() : x(), valid(false) - {} - - operator bool() const - { - return valid; - } - - const T& operator*() const - { - return x; - } - }; - strtonum(const char* start, const char* end) : m_start(start), m_end(end) {} + /// return true iff parsed successfully as + /// number of type T. + /// + /// @val shall contain parsed value, or + /// undefined value if could not parse. template::value>::type > @@ -8264,33 +8239,13 @@ class basic_json return parse(val, std::is_integral()); } - template::value>::type > - operator T() const - { - T val{0}; - - if (parse(val, std::is_integral())) - { - return val; - } - - throw std::invalid_argument( - std::string() - + "Can't parse '" - + std::string(m_start, m_end) - + "' as type " - + typeid(T).name()); - } - - // return true iff token matches ^[+-]\d+$ - // - // this is a helper to determine whether to - // parse the token into floating-point or - // integral type. We wouldn't need it if - // we had separate token types for integral - // and floating-point cases. + /// return true iff token matches ^[+-]\d+$ + /// + /// this is a helper to determine whether to + /// parse the token into floating-point or + /// integral type. We wouldn't need it if + /// we had separate token types for integral + /// and floating-point cases. bool is_integral() const { const char* p = m_start; From 1c029b97c0ebc90b5b7f1cb875b0904f115668b8 Mon Sep 17 00:00:00 2001 From: Alex Astashyn Date: Thu, 8 Dec 2016 22:13:05 -0500 Subject: [PATCH 21/80] Still trying to invoke locale-specific behavior in CI --- test/src/unit-regression.cpp | 35 +++++------------------------------ 1 file changed, 5 insertions(+), 30 deletions(-) diff --git a/test/src/unit-regression.cpp b/test/src/unit-regression.cpp index deace862..5cd6356d 100644 --- a/test/src/unit-regression.cpp +++ b/test/src/unit-regression.cpp @@ -405,46 +405,21 @@ TEST_CASE("regression tests") SECTION("issue #379 - locale-independent str-to-num") { - // If I save the locale here and restore it in the end - // of this block, then setLocale(LC_NUMERIC, "de_DE") - // does not actually make snprintf use "," as decimal separator - // on some compilers. I have no idea... - //const std::string orig_locale_name(setlocale(LC_ALL, NULL)); - - - // Still, just setting some comma-using locale does not - // make snprintf output commas on all platforms, so instead - // will change dot to comma in the current locale below - //setlocale(LC_NUMERIC, "de_DE"); - - auto loc = localeconv(); - auto orig_decimal_point = loc->decimal_point; - char comma[] = ","; - loc->decimal_point = comma; - - std::array buf; + setlocale(LC_NUMERIC, "de_DE.UTF-8"); { // verify that strtod now uses commas as decimal-separator - const double d1 = std::strtod("3,14", nullptr); - CHECK(d1 == 3.14); + CHECK(std::strtod("3,14", nullptr) == 3.14); // verify that strtod does not understand dots as decimal separator - const double d2 = std::strtod("3.14", nullptr); - CHECK(d2 == 3); + CHECK(std::strtod("3.14", nullptr) == 3); } // verify that parsed correctly despite using strtod internally - const json j1 = json::parse("3.14"); - CHECK(j1.get() == 3.14); + CHECK(json::parse("3.14").get() == 3.14); // check a different code path - const json j2 = json::parse("1.000000000000000000000000000000000000000000000000000000000000000000000000"); - CHECK(j2.get() == 1.0); - - loc->decimal_point = orig_decimal_point; - // restore original locale - // setlocale(LC_ALL, orig_locale_name.c_str()); + CHECK(json::parse("1.000000000000000000000000000000000000000000000000000000000000000000000000").get() == 1.0); } From 343c9f9baa7bc210bd0984fa56760b8f3092d2d4 Mon Sep 17 00:00:00 2001 From: Alex Astashyn Date: Thu, 8 Dec 2016 22:36:18 -0500 Subject: [PATCH 22/80] Addressing compiler warnings --- src/json.hpp | 8 ++++---- src/json.hpp.re2c | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/json.hpp b/src/json.hpp index 876c35b6..bd172559 100644 --- a/src/json.hpp +++ b/src/json.hpp @@ -6419,9 +6419,8 @@ class basic_json private: static constexpr size_t s_capacity = 30; - std::array m_buf{}; // +2 for leading '-' - // and trailing '\0' - + std::array m_buf{{}}; // +2 for leading '-' + // and trailing '\0' template void x_write(T x, std::true_type) { @@ -6432,7 +6431,8 @@ class basic_json while(x and i < s_capacity) { - m_buf[i++] = static_cast('0' + std::labs(x % 10)); + const auto digit = std::labs(static_cast(x % 10)); + m_buf[i++] = static_cast('0' + digit); x /= 10; } diff --git a/src/json.hpp.re2c b/src/json.hpp.re2c index 55574bee..4411c64a 100644 --- a/src/json.hpp.re2c +++ b/src/json.hpp.re2c @@ -6419,9 +6419,8 @@ class basic_json private: static constexpr size_t s_capacity = 30; - std::array m_buf{}; // +2 for leading '-' - // and trailing '\0' - + std::array m_buf{{}}; // +2 for leading '-' + // and trailing '\0' template void x_write(T x, std::true_type) { @@ -6432,7 +6431,8 @@ class basic_json while(x and i < s_capacity) { - m_buf[i++] = static_cast('0' + std::labs(x % 10)); + const auto digit = std::labs(static_cast(x % 10)); + m_buf[i++] = static_cast('0' + digit); x /= 10; } From 01930357f7bd52672bffbb3aef76f241d03e4906 Mon Sep 17 00:00:00 2001 From: Alex Astashyn Date: Thu, 8 Dec 2016 22:39:38 -0500 Subject: [PATCH 23/80] Tweaking unit test, as digits grouping is failing to be invoked in CI --- test/src/unit-regression.cpp | 24 +++--------------------- 1 file changed, 3 insertions(+), 21 deletions(-) diff --git a/test/src/unit-regression.cpp b/test/src/unit-regression.cpp index 3e303fbb..c4b87399 100644 --- a/test/src/unit-regression.cpp +++ b/test/src/unit-regression.cpp @@ -403,37 +403,19 @@ TEST_CASE("regression tests") SECTION("issue #378 - locale-independent num-to-str") { - setlocale(LC_NUMERIC, ""); - - auto loc = localeconv(); - auto orig_decimal_point = loc->decimal_point; - auto orig_thousands_sep = loc->thousands_sep; - char comma[] = ","; - char thsep[] = "'"; - - loc->decimal_point = comma; - loc->thousands_sep = thsep; + setlocale(LC_NUMERIC, "de_DE.UTF-8"); // verify that snprintf uses special decimal and grouping characters { std::array buf; std::snprintf(buf.data(), buf.size(), "%.2f", 12345.67); CHECK(strcmp(buf.data(), "12345,67") == 0); - - buf.fill(0); - std::snprintf(buf.data(), buf.size(), "%'d", 1234567); - CHECK(strcmp(buf.data(), "1'234'567") == 0); } // verify that dumped correctly with '.' and no grouping const json j1 = 12345.67; - CHECK(j1.dump() == "12345.67"); - - const json j2 = 1234567; - CHECK(j2.dump() == "1234567"); - - loc->decimal_point = orig_decimal_point; - loc->thousands_sep = orig_thousands_sep; + CHECK(json(12345.67).dump() == "12345.67"); + setlocale(LC_NUMERIC, "C"); } SECTION("issue #233 - Can't use basic_json::iterator as a base iterator for std::move_iterator") From cd0b651d43c303dbe0b8016a1305ab9e5fef6449 Mon Sep 17 00:00:00 2001 From: Alex Astashyn Date: Mon, 12 Dec 2016 19:46:47 -0500 Subject: [PATCH 24/80] Tweaked check for preserved sign; added LCOV_EXCL_LINE --- src/json.hpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/json.hpp b/src/json.hpp index 867afbb3..b526400c 100644 --- a/src/json.hpp +++ b/src/json.hpp @@ -9103,7 +9103,7 @@ basic_json_parser_66: if (!p) { - return false; + return false; // LCOV_EXCL_LINE } if (*p == '-' or *p == '+') @@ -9113,7 +9113,7 @@ basic_json_parser_66: if (p == m_end) { - return false; + return false; // LCOV_EXCL_LINE } while (p < m_end and *p >= '0' @@ -9252,11 +9252,11 @@ basic_json_parser_66: value = static_cast(x); return x == static_cast(value) // x fits into destination T + and (x < 0) == (value < 0) // preserved sign and (x != 0 or is_integral()) // strto[u]ll did nto fail and errno == 0 // strto[u]ll did not overflow and m_start < m_end // token was not empty - and endptr == m_end // parsed entire token exactly - and (x < 0) == (*m_start == '-'); // input was sign-compatible + and endptr == m_end; // parsed entire token exactly } #else // parsing integral types manually From 0f8de48ddbc03b842ef5523b10553d3d319e1666 Mon Sep 17 00:00:00 2001 From: Alex Astashyn Date: Mon, 12 Dec 2016 19:48:14 -0500 Subject: [PATCH 25/80] Disabling strtod pre-check, since can't get locale-specific behavior to manifest in AppVeyor --- test/src/unit-regression.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/test/src/unit-regression.cpp b/test/src/unit-regression.cpp index 5cd6356d..7016fcaf 100644 --- a/test/src/unit-regression.cpp +++ b/test/src/unit-regression.cpp @@ -407,6 +407,9 @@ TEST_CASE("regression tests") { setlocale(LC_NUMERIC, "de_DE.UTF-8"); + // disabled, because locale-specific beharivor is not + // triggered in AppVeyor for some reason +#if 0 { // verify that strtod now uses commas as decimal-separator CHECK(std::strtod("3,14", nullptr) == 3.14); @@ -414,6 +417,7 @@ TEST_CASE("regression tests") // verify that strtod does not understand dots as decimal separator CHECK(std::strtod("3.14", nullptr) == 3); } +#endif // verify that parsed correctly despite using strtod internally CHECK(json::parse("3.14").get() == 3.14); From 65b9b0c429b6ecd1d255fd8dde5decc7fec0120f Mon Sep 17 00:00:00 2001 From: Alex Astashyn Date: Mon, 12 Dec 2016 19:50:21 -0500 Subject: [PATCH 26/80] Disabling snprintf pre-check, since can't get locale-specific behavior to manifest in AppVeyor --- test/src/unit-regression.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/test/src/unit-regression.cpp b/test/src/unit-regression.cpp index c4b87399..2763114a 100644 --- a/test/src/unit-regression.cpp +++ b/test/src/unit-regression.cpp @@ -405,12 +405,15 @@ TEST_CASE("regression tests") { setlocale(LC_NUMERIC, "de_DE.UTF-8"); - // verify that snprintf uses special decimal and grouping characters + // Verify that snprintf uses special decimal and grouping characters. + // Disabled, because can't trigger locale-specific behavior in AppVeyor +#if 0 { std::array buf; std::snprintf(buf.data(), buf.size(), "%.2f", 12345.67); CHECK(strcmp(buf.data(), "12345,67") == 0); } +#endif // verify that dumped correctly with '.' and no grouping const json j1 = 12345.67; From 5cad2006eb99534274c380af1ad92d5b257c83bc Mon Sep 17 00:00:00 2001 From: Alex Astashyn Date: Mon, 12 Dec 2016 20:15:57 -0500 Subject: [PATCH 27/80] Tweaked check for preserved sign; added LCOV_EXCL_LINE --- src/json.hpp.re2c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/json.hpp.re2c b/src/json.hpp.re2c index 5b2dc8d2..208489ea 100644 --- a/src/json.hpp.re2c +++ b/src/json.hpp.re2c @@ -8252,7 +8252,7 @@ class basic_json if (!p) { - return false; + return false; // LCOV_EXCL_LINE } if (*p == '-' or *p == '+') @@ -8262,7 +8262,7 @@ class basic_json if (p == m_end) { - return false; + return false; // LCOV_EXCL_LINE } while (p < m_end and *p >= '0' @@ -8401,11 +8401,11 @@ class basic_json value = static_cast(x); return x == static_cast(value) // x fits into destination T + and (x < 0) == (value < 0) // preserved sign and (x != 0 or is_integral()) // strto[u]ll did nto fail and errno == 0 // strto[u]ll did not overflow and m_start < m_end // token was not empty - and endptr == m_end // parsed entire token exactly - and (x < 0) == (*m_start == '-'); // input was sign-compatible + and endptr == m_end; // parsed entire token exactly } #else // parsing integral types manually From 6198439f59be82dd82e102a0c07bfe1c5bb48f5d Mon Sep 17 00:00:00 2001 From: Mihai STAN Date: Tue, 3 Jan 2017 00:49:33 +0200 Subject: [PATCH 28/80] fix #414 - comparing to 0 literal Overload comparison operators for all types that could be converted to nullptr. --- src/json.hpp | 1403 +++++++++++----------------------- src/json.hpp.re2c | 65 +- test/src/unit-regression.cpp | 18 + 3 files changed, 490 insertions(+), 996 deletions(-) diff --git a/src/json.hpp b/src/json.hpp index 9d48e7a6..a0f57a18 100644 --- a/src/json.hpp +++ b/src/json.hpp @@ -5625,36 +5625,23 @@ class basic_json return false; } - /*! - @brief comparison: equal - - The functions compares the given JSON value against a null pointer. As the - null pointer can be used to initialize a JSON value to null, a comparison - of JSON value @a v with a null pointer should be equivalent to call - `v.is_null()`. - - @param[in] v JSON value to consider - @return whether @a v is null - - @complexity Constant. - - @liveexample{The example compares several JSON types to the null pointer. - ,operator__equal__nullptr_t} - - @since version 1.0.0 + /*!@brief comparison: equal + @copydoc operator==(const_reference, const_reference) */ - friend bool operator==(const_reference v, std::nullptr_t) noexcept - { - return v.is_null(); + template::value, int>::type = 0> + friend bool operator==(const_reference lhs, const ScalarType rhs) noexcept { + return (lhs == basic_json(rhs)); } /*! @brief comparison: equal - @copydoc operator==(const_reference, std::nullptr_t) + @copydoc operator==(const_reference, const_reference) */ - friend bool operator==(std::nullptr_t, const_reference v) noexcept - { - return v.is_null(); + template::value, int>::type = 0> + friend bool operator==(const ScalarType lhs, const_reference rhs) noexcept { + return (basic_json(lhs) == rhs); } /*! @@ -5680,34 +5667,24 @@ class basic_json /*! @brief comparison: not equal - - The functions compares the given JSON value against a null pointer. As the - null pointer can be used to initialize a JSON value to null, a comparison - of JSON value @a v with a null pointer should be equivalent to call - `not v.is_null()`. - - @param[in] v JSON value to consider - @return whether @a v is not null - - @complexity Constant. - - @liveexample{The example compares several JSON types to the null pointer. - ,operator__notequal__nullptr_t} - - @since version 1.0.0 + @copydoc operator!=(const_reference, const_reference) */ - friend bool operator!=(const_reference v, std::nullptr_t) noexcept + template::value, int>::type = 0> + friend bool operator!=(const_reference lhs, const ScalarType rhs) noexcept { - return not v.is_null(); + return (lhs != basic_json(rhs)); } /*! @brief comparison: not equal - @copydoc operator!=(const_reference, std::nullptr_t) + @copydoc operator!=(const_reference, const_reference) */ - friend bool operator!=(std::nullptr_t, const_reference v) noexcept + template::value, int>::type = 0> + friend bool operator!=(const ScalarType lhs, const_reference rhs) noexcept { - return not v.is_null(); + return (basic_json(lhs) != rhs); } /*! @@ -9249,915 +9226,437 @@ class basic_json m_start = m_cursor; assert(m_start != nullptr); - - { - lexer_char_t yych; - unsigned int yyaccept = 0; - static const unsigned char yybm[] = - { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 32, 32, 0, 0, 32, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 160, 128, 0, 128, 128, 128, 128, 128, - 128, 128, 128, 128, 128, 128, 128, 128, - 192, 192, 192, 192, 192, 192, 192, 192, - 192, 192, 128, 128, 128, 128, 128, 128, - 128, 128, 128, 128, 128, 128, 128, 128, - 128, 128, 128, 128, 128, 128, 128, 128, - 128, 128, 128, 128, 128, 128, 128, 128, - 128, 128, 128, 128, 0, 128, 128, 128, - 128, 128, 128, 128, 128, 128, 128, 128, - 128, 128, 128, 128, 128, 128, 128, 128, - 128, 128, 128, 128, 128, 128, 128, 128, - 128, 128, 128, 128, 128, 128, 128, 128, - 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, - 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, - 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, - 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, - }; - if ((m_limit - m_cursor) < 5) - { - fill_line_buffer(5); // LCOV_EXCL_LINE - } - yych = *m_cursor; - if (yybm[0 + yych] & 32) - { - goto basic_json_parser_6; - } - if (yych <= '[') - { - if (yych <= '-') - { - if (yych <= '"') - { - if (yych <= 0x00) - { - goto basic_json_parser_2; - } - if (yych <= '!') - { - goto basic_json_parser_4; - } - goto basic_json_parser_9; - } - else - { - if (yych <= '+') - { - goto basic_json_parser_4; - } - if (yych <= ',') - { - goto basic_json_parser_10; - } - goto basic_json_parser_12; - } - } - else - { - if (yych <= '9') - { - if (yych <= '/') - { - goto basic_json_parser_4; - } - if (yych <= '0') - { - goto basic_json_parser_13; - } - goto basic_json_parser_15; - } - else - { - if (yych <= ':') - { - goto basic_json_parser_17; - } - if (yych <= 'Z') - { - goto basic_json_parser_4; - } - goto basic_json_parser_19; - } - } - } - else - { - if (yych <= 'n') - { - if (yych <= 'e') - { - if (yych == ']') - { - goto basic_json_parser_21; - } - goto basic_json_parser_4; - } - else - { - if (yych <= 'f') - { - goto basic_json_parser_23; - } - if (yych <= 'm') - { - goto basic_json_parser_4; - } - goto basic_json_parser_24; - } - } - else - { - if (yych <= 'z') - { - if (yych == 't') - { - goto basic_json_parser_25; - } - goto basic_json_parser_4; - } - else - { - if (yych <= '{') - { - goto basic_json_parser_26; - } - if (yych == '}') - { - goto basic_json_parser_28; - } - goto basic_json_parser_4; - } - } - } -basic_json_parser_2: - ++m_cursor; - { - last_token_type = token_type::end_of_input; - break; - } -basic_json_parser_4: - ++m_cursor; -basic_json_parser_5: - { - last_token_type = token_type::parse_error; - break; - } -basic_json_parser_6: - ++m_cursor; - if (m_limit <= m_cursor) - { - fill_line_buffer(1); // LCOV_EXCL_LINE - } - yych = *m_cursor; - if (yybm[0 + yych] & 32) - { - goto basic_json_parser_6; - } - { - continue; - } -basic_json_parser_9: - yyaccept = 0; - yych = *(m_marker = ++m_cursor); - if (yych <= 0x1F) - { - goto basic_json_parser_5; - } - if (yych <= 0x7F) - { - goto basic_json_parser_31; - } - if (yych <= 0xC1) - { - goto basic_json_parser_5; - } - if (yych <= 0xF4) - { - goto basic_json_parser_31; - } - goto basic_json_parser_5; -basic_json_parser_10: - ++m_cursor; - { - last_token_type = token_type::value_separator; - break; - } -basic_json_parser_12: - yych = *++m_cursor; - if (yych <= '/') - { - goto basic_json_parser_5; - } - if (yych <= '0') - { - goto basic_json_parser_13; - } - if (yych <= '9') - { - goto basic_json_parser_15; - } - goto basic_json_parser_5; -basic_json_parser_13: - yyaccept = 1; - yych = *(m_marker = ++m_cursor); - if (yych <= 'D') - { - if (yych == '.') - { - goto basic_json_parser_43; - } - } - else - { - if (yych <= 'E') - { - goto basic_json_parser_44; - } - if (yych == 'e') - { - goto basic_json_parser_44; - } - } -basic_json_parser_14: - { - last_token_type = token_type::value_number; - break; - } -basic_json_parser_15: - yyaccept = 1; - m_marker = ++m_cursor; - if ((m_limit - m_cursor) < 3) - { - fill_line_buffer(3); // LCOV_EXCL_LINE - } - yych = *m_cursor; - if (yybm[0 + yych] & 64) - { - goto basic_json_parser_15; - } - if (yych <= 'D') - { - if (yych == '.') - { - goto basic_json_parser_43; - } - goto basic_json_parser_14; - } - else - { - if (yych <= 'E') - { - goto basic_json_parser_44; - } - if (yych == 'e') - { - goto basic_json_parser_44; - } - goto basic_json_parser_14; - } -basic_json_parser_17: - ++m_cursor; - { - last_token_type = token_type::name_separator; - break; - } -basic_json_parser_19: - ++m_cursor; - { - last_token_type = token_type::begin_array; - break; - } -basic_json_parser_21: - ++m_cursor; - { - last_token_type = token_type::end_array; - break; - } -basic_json_parser_23: - yyaccept = 0; - yych = *(m_marker = ++m_cursor); - if (yych == 'a') - { - goto basic_json_parser_45; - } - goto basic_json_parser_5; -basic_json_parser_24: - yyaccept = 0; - yych = *(m_marker = ++m_cursor); - if (yych == 'u') - { - goto basic_json_parser_46; - } - goto basic_json_parser_5; -basic_json_parser_25: - yyaccept = 0; - yych = *(m_marker = ++m_cursor); - if (yych == 'r') - { - goto basic_json_parser_47; - } - goto basic_json_parser_5; -basic_json_parser_26: - ++m_cursor; - { - last_token_type = token_type::begin_object; - break; - } -basic_json_parser_28: - ++m_cursor; - { - last_token_type = token_type::end_object; - break; - } -basic_json_parser_30: - ++m_cursor; - if (m_limit <= m_cursor) - { - fill_line_buffer(1); // LCOV_EXCL_LINE - } - yych = *m_cursor; -basic_json_parser_31: - if (yybm[0 + yych] & 128) - { - goto basic_json_parser_30; - } - if (yych <= 0xE0) - { - if (yych <= '\\') - { - if (yych <= 0x1F) - { - goto basic_json_parser_32; - } - if (yych <= '"') - { - goto basic_json_parser_33; - } - goto basic_json_parser_35; - } - else - { - if (yych <= 0xC1) - { - goto basic_json_parser_32; - } - if (yych <= 0xDF) - { - goto basic_json_parser_36; - } - goto basic_json_parser_37; - } - } - else - { - if (yych <= 0xEF) - { - if (yych == 0xED) - { - goto basic_json_parser_39; - } - goto basic_json_parser_38; - } - else - { - if (yych <= 0xF0) - { - goto basic_json_parser_40; - } - if (yych <= 0xF3) - { - goto basic_json_parser_41; - } - if (yych <= 0xF4) - { - goto basic_json_parser_42; - } - } - } -basic_json_parser_32: - m_cursor = m_marker; - if (yyaccept == 0) - { - goto basic_json_parser_5; - } - else - { - goto basic_json_parser_14; - } -basic_json_parser_33: - ++m_cursor; - { - last_token_type = token_type::value_string; - break; - } -basic_json_parser_35: - ++m_cursor; - if (m_limit <= m_cursor) - { - fill_line_buffer(1); // LCOV_EXCL_LINE - } - yych = *m_cursor; - if (yych <= 'e') - { - if (yych <= '/') - { - if (yych == '"') - { - goto basic_json_parser_30; - } - if (yych <= '.') - { - goto basic_json_parser_32; - } - goto basic_json_parser_30; - } - else - { - if (yych <= '\\') - { - if (yych <= '[') - { - goto basic_json_parser_32; - } - goto basic_json_parser_30; - } - else - { - if (yych == 'b') - { - goto basic_json_parser_30; - } - goto basic_json_parser_32; - } - } - } - else - { - if (yych <= 'q') - { - if (yych <= 'f') - { - goto basic_json_parser_30; - } - if (yych == 'n') - { - goto basic_json_parser_30; - } - goto basic_json_parser_32; - } - else - { - if (yych <= 's') - { - if (yych <= 'r') - { - goto basic_json_parser_30; - } - goto basic_json_parser_32; - } - else - { - if (yych <= 't') - { - goto basic_json_parser_30; - } - if (yych <= 'u') - { - goto basic_json_parser_48; - } - goto basic_json_parser_32; - } - } - } -basic_json_parser_36: - ++m_cursor; - if (m_limit <= m_cursor) - { - fill_line_buffer(1); // LCOV_EXCL_LINE - } - yych = *m_cursor; - if (yych <= 0x7F) - { - goto basic_json_parser_32; - } - if (yych <= 0xBF) - { - goto basic_json_parser_30; - } - goto basic_json_parser_32; -basic_json_parser_37: - ++m_cursor; - if (m_limit <= m_cursor) - { - fill_line_buffer(1); // LCOV_EXCL_LINE - } - yych = *m_cursor; - if (yych <= 0x9F) - { - goto basic_json_parser_32; - } - if (yych <= 0xBF) - { - goto basic_json_parser_36; - } - goto basic_json_parser_32; -basic_json_parser_38: - ++m_cursor; - if (m_limit <= m_cursor) - { - fill_line_buffer(1); // LCOV_EXCL_LINE - } - yych = *m_cursor; - if (yych <= 0x7F) - { - goto basic_json_parser_32; - } - if (yych <= 0xBF) - { - goto basic_json_parser_36; - } - goto basic_json_parser_32; -basic_json_parser_39: - ++m_cursor; - if (m_limit <= m_cursor) - { - fill_line_buffer(1); // LCOV_EXCL_LINE - } - yych = *m_cursor; - if (yych <= 0x7F) - { - goto basic_json_parser_32; - } - if (yych <= 0x9F) - { - goto basic_json_parser_36; - } - goto basic_json_parser_32; -basic_json_parser_40: - ++m_cursor; - if (m_limit <= m_cursor) - { - fill_line_buffer(1); // LCOV_EXCL_LINE - } - yych = *m_cursor; - if (yych <= 0x8F) - { - goto basic_json_parser_32; - } - if (yych <= 0xBF) - { - goto basic_json_parser_38; - } - goto basic_json_parser_32; -basic_json_parser_41: - ++m_cursor; - if (m_limit <= m_cursor) - { - fill_line_buffer(1); // LCOV_EXCL_LINE - } - yych = *m_cursor; - if (yych <= 0x7F) - { - goto basic_json_parser_32; - } - if (yych <= 0xBF) - { - goto basic_json_parser_38; - } - goto basic_json_parser_32; -basic_json_parser_42: - ++m_cursor; - if (m_limit <= m_cursor) - { - fill_line_buffer(1); // LCOV_EXCL_LINE - } - yych = *m_cursor; - if (yych <= 0x7F) - { - goto basic_json_parser_32; - } - if (yych <= 0x8F) - { - goto basic_json_parser_38; - } - goto basic_json_parser_32; -basic_json_parser_43: - yych = *++m_cursor; - if (yych <= '/') - { - goto basic_json_parser_32; - } - if (yych <= '9') - { - goto basic_json_parser_49; - } - goto basic_json_parser_32; -basic_json_parser_44: - yych = *++m_cursor; - if (yych <= ',') - { - if (yych == '+') - { - goto basic_json_parser_51; - } - goto basic_json_parser_32; - } - else - { - if (yych <= '-') - { - goto basic_json_parser_51; - } - if (yych <= '/') - { - goto basic_json_parser_32; - } - if (yych <= '9') - { - goto basic_json_parser_52; - } - goto basic_json_parser_32; - } -basic_json_parser_45: - yych = *++m_cursor; - if (yych == 'l') - { - goto basic_json_parser_54; - } - goto basic_json_parser_32; -basic_json_parser_46: - yych = *++m_cursor; - if (yych == 'l') - { - goto basic_json_parser_55; - } - goto basic_json_parser_32; -basic_json_parser_47: - yych = *++m_cursor; - if (yych == 'u') - { - goto basic_json_parser_56; - } - goto basic_json_parser_32; -basic_json_parser_48: - ++m_cursor; - if (m_limit <= m_cursor) - { - fill_line_buffer(1); // LCOV_EXCL_LINE - } - yych = *m_cursor; - if (yych <= '@') - { - if (yych <= '/') - { - goto basic_json_parser_32; - } - if (yych <= '9') - { - goto basic_json_parser_57; - } - goto basic_json_parser_32; - } - else - { - if (yych <= 'F') - { - goto basic_json_parser_57; - } - if (yych <= '`') - { - goto basic_json_parser_32; - } - if (yych <= 'f') - { - goto basic_json_parser_57; - } - goto basic_json_parser_32; - } -basic_json_parser_49: - yyaccept = 1; - m_marker = ++m_cursor; - if ((m_limit - m_cursor) < 3) - { - fill_line_buffer(3); // LCOV_EXCL_LINE - } - yych = *m_cursor; - if (yych <= 'D') - { - if (yych <= '/') - { - goto basic_json_parser_14; - } - if (yych <= '9') - { - goto basic_json_parser_49; - } - goto basic_json_parser_14; - } - else - { - if (yych <= 'E') - { - goto basic_json_parser_44; - } - if (yych == 'e') - { - goto basic_json_parser_44; - } - goto basic_json_parser_14; - } -basic_json_parser_51: - yych = *++m_cursor; - if (yych <= '/') - { - goto basic_json_parser_32; - } - if (yych >= ':') - { - goto basic_json_parser_32; - } -basic_json_parser_52: - ++m_cursor; - if (m_limit <= m_cursor) - { - fill_line_buffer(1); // LCOV_EXCL_LINE - } - yych = *m_cursor; - if (yych <= '/') - { - goto basic_json_parser_14; - } - if (yych <= '9') - { - goto basic_json_parser_52; - } - goto basic_json_parser_14; -basic_json_parser_54: - yych = *++m_cursor; - if (yych == 's') - { - goto basic_json_parser_58; - } - goto basic_json_parser_32; -basic_json_parser_55: - yych = *++m_cursor; - if (yych == 'l') - { - goto basic_json_parser_59; - } - goto basic_json_parser_32; -basic_json_parser_56: - yych = *++m_cursor; - if (yych == 'e') - { - goto basic_json_parser_61; - } - goto basic_json_parser_32; -basic_json_parser_57: - ++m_cursor; - if (m_limit <= m_cursor) - { - fill_line_buffer(1); // LCOV_EXCL_LINE - } - yych = *m_cursor; - if (yych <= '@') - { - if (yych <= '/') - { - goto basic_json_parser_32; - } - if (yych <= '9') - { - goto basic_json_parser_63; - } - goto basic_json_parser_32; - } - else - { - if (yych <= 'F') - { - goto basic_json_parser_63; - } - if (yych <= '`') - { - goto basic_json_parser_32; - } - if (yych <= 'f') - { - goto basic_json_parser_63; - } - goto basic_json_parser_32; - } -basic_json_parser_58: - yych = *++m_cursor; - if (yych == 'e') - { - goto basic_json_parser_64; - } - goto basic_json_parser_32; -basic_json_parser_59: - ++m_cursor; - { - last_token_type = token_type::literal_null; - break; - } -basic_json_parser_61: - ++m_cursor; - { - last_token_type = token_type::literal_true; - break; - } -basic_json_parser_63: - ++m_cursor; - if (m_limit <= m_cursor) - { - fill_line_buffer(1); // LCOV_EXCL_LINE - } - yych = *m_cursor; - if (yych <= '@') - { - if (yych <= '/') - { - goto basic_json_parser_32; - } - if (yych <= '9') - { - goto basic_json_parser_66; - } - goto basic_json_parser_32; - } - else - { - if (yych <= 'F') - { - goto basic_json_parser_66; - } - if (yych <= '`') - { - goto basic_json_parser_32; - } - if (yych <= 'f') - { - goto basic_json_parser_66; - } - goto basic_json_parser_32; - } -basic_json_parser_64: - ++m_cursor; - { - last_token_type = token_type::literal_false; - break; - } -basic_json_parser_66: - ++m_cursor; - if (m_limit <= m_cursor) - { - fill_line_buffer(1); // LCOV_EXCL_LINE - } - yych = *m_cursor; - if (yych <= '@') - { - if (yych <= '/') - { - goto basic_json_parser_32; - } - if (yych <= '9') - { - goto basic_json_parser_30; - } - goto basic_json_parser_32; - } - else - { - if (yych <= 'F') - { - goto basic_json_parser_30; - } - if (yych <= '`') - { - goto basic_json_parser_32; - } - if (yych <= 'f') - { - goto basic_json_parser_30; - } - goto basic_json_parser_32; - } + + { + lexer_char_t yych; + unsigned int yyaccept = 0; + static const unsigned char yybm[] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 32, 32, 0, 0, 32, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 160, 128, 0, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 192, 192, 192, 192, 192, 192, 192, 192, + 192, 192, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 0, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 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, + 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, + 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, + 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, + }; + if ((m_limit - m_cursor) < 5) fill_line_buffer(5); // LCOV_EXCL_LINE + yych = *m_cursor; + if (yybm[0+yych] & 32) { + goto basic_json_parser_6; + } + if (yych <= '[') { + if (yych <= '-') { + if (yych <= '"') { + if (yych <= 0x00) goto basic_json_parser_2; + if (yych <= '!') goto basic_json_parser_4; + goto basic_json_parser_9; + } else { + if (yych <= '+') goto basic_json_parser_4; + if (yych <= ',') goto basic_json_parser_10; + goto basic_json_parser_12; } + } else { + if (yych <= '9') { + if (yych <= '/') goto basic_json_parser_4; + if (yych <= '0') goto basic_json_parser_13; + goto basic_json_parser_15; + } else { + if (yych <= ':') goto basic_json_parser_17; + if (yych <= 'Z') goto basic_json_parser_4; + goto basic_json_parser_19; + } + } + } else { + if (yych <= 'n') { + if (yych <= 'e') { + if (yych == ']') goto basic_json_parser_21; + goto basic_json_parser_4; + } else { + if (yych <= 'f') goto basic_json_parser_23; + if (yych <= 'm') goto basic_json_parser_4; + goto basic_json_parser_24; + } + } else { + if (yych <= 'z') { + if (yych == 't') goto basic_json_parser_25; + goto basic_json_parser_4; + } else { + if (yych <= '{') goto basic_json_parser_26; + if (yych == '}') goto basic_json_parser_28; + goto basic_json_parser_4; + } + } + } +basic_json_parser_2: + ++m_cursor; + { last_token_type = token_type::end_of_input; break; } +basic_json_parser_4: + ++m_cursor; +basic_json_parser_5: + { last_token_type = token_type::parse_error; break; } +basic_json_parser_6: + ++m_cursor; + if (m_limit <= m_cursor) fill_line_buffer(1); // LCOV_EXCL_LINE + yych = *m_cursor; + if (yybm[0+yych] & 32) { + goto basic_json_parser_6; + } + { continue; } +basic_json_parser_9: + yyaccept = 0; + yych = *(m_marker = ++m_cursor); + if (yych <= 0x1F) goto basic_json_parser_5; + if (yych <= 0x7F) goto basic_json_parser_31; + if (yych <= 0xC1) goto basic_json_parser_5; + if (yych <= 0xF4) goto basic_json_parser_31; + goto basic_json_parser_5; +basic_json_parser_10: + ++m_cursor; + { last_token_type = token_type::value_separator; break; } +basic_json_parser_12: + yych = *++m_cursor; + if (yych <= '/') goto basic_json_parser_5; + if (yych <= '0') goto basic_json_parser_13; + if (yych <= '9') goto basic_json_parser_15; + goto basic_json_parser_5; +basic_json_parser_13: + yyaccept = 1; + yych = *(m_marker = ++m_cursor); + if (yych <= 'D') { + if (yych == '.') goto basic_json_parser_43; + } else { + if (yych <= 'E') goto basic_json_parser_44; + if (yych == 'e') goto basic_json_parser_44; + } +basic_json_parser_14: + { last_token_type = token_type::value_number; break; } +basic_json_parser_15: + yyaccept = 1; + m_marker = ++m_cursor; + if ((m_limit - m_cursor) < 3) fill_line_buffer(3); // LCOV_EXCL_LINE + yych = *m_cursor; + if (yybm[0+yych] & 64) { + goto basic_json_parser_15; + } + if (yych <= 'D') { + if (yych == '.') goto basic_json_parser_43; + goto basic_json_parser_14; + } else { + if (yych <= 'E') goto basic_json_parser_44; + if (yych == 'e') goto basic_json_parser_44; + goto basic_json_parser_14; + } +basic_json_parser_17: + ++m_cursor; + { last_token_type = token_type::name_separator; break; } +basic_json_parser_19: + ++m_cursor; + { last_token_type = token_type::begin_array; break; } +basic_json_parser_21: + ++m_cursor; + { last_token_type = token_type::end_array; break; } +basic_json_parser_23: + yyaccept = 0; + yych = *(m_marker = ++m_cursor); + if (yych == 'a') goto basic_json_parser_45; + goto basic_json_parser_5; +basic_json_parser_24: + yyaccept = 0; + yych = *(m_marker = ++m_cursor); + if (yych == 'u') goto basic_json_parser_46; + goto basic_json_parser_5; +basic_json_parser_25: + yyaccept = 0; + yych = *(m_marker = ++m_cursor); + if (yych == 'r') goto basic_json_parser_47; + goto basic_json_parser_5; +basic_json_parser_26: + ++m_cursor; + { last_token_type = token_type::begin_object; break; } +basic_json_parser_28: + ++m_cursor; + { last_token_type = token_type::end_object; break; } +basic_json_parser_30: + ++m_cursor; + if (m_limit <= m_cursor) fill_line_buffer(1); // LCOV_EXCL_LINE + yych = *m_cursor; +basic_json_parser_31: + if (yybm[0+yych] & 128) { + goto basic_json_parser_30; + } + if (yych <= 0xE0) { + if (yych <= '\\') { + if (yych <= 0x1F) goto basic_json_parser_32; + if (yych <= '"') goto basic_json_parser_33; + goto basic_json_parser_35; + } else { + if (yych <= 0xC1) goto basic_json_parser_32; + if (yych <= 0xDF) goto basic_json_parser_36; + goto basic_json_parser_37; + } + } else { + if (yych <= 0xEF) { + if (yych == 0xED) goto basic_json_parser_39; + goto basic_json_parser_38; + } else { + if (yych <= 0xF0) goto basic_json_parser_40; + if (yych <= 0xF3) goto basic_json_parser_41; + if (yych <= 0xF4) goto basic_json_parser_42; + } + } +basic_json_parser_32: + m_cursor = m_marker; + if (yyaccept == 0) { + goto basic_json_parser_5; + } else { + goto basic_json_parser_14; + } +basic_json_parser_33: + ++m_cursor; + { last_token_type = token_type::value_string; break; } +basic_json_parser_35: + ++m_cursor; + if (m_limit <= m_cursor) fill_line_buffer(1); // LCOV_EXCL_LINE + yych = *m_cursor; + if (yych <= 'e') { + if (yych <= '/') { + if (yych == '"') goto basic_json_parser_30; + if (yych <= '.') goto basic_json_parser_32; + goto basic_json_parser_30; + } else { + if (yych <= '\\') { + if (yych <= '[') goto basic_json_parser_32; + goto basic_json_parser_30; + } else { + if (yych == 'b') goto basic_json_parser_30; + goto basic_json_parser_32; + } + } + } else { + if (yych <= 'q') { + if (yych <= 'f') goto basic_json_parser_30; + if (yych == 'n') goto basic_json_parser_30; + goto basic_json_parser_32; + } else { + if (yych <= 's') { + if (yych <= 'r') goto basic_json_parser_30; + goto basic_json_parser_32; + } else { + if (yych <= 't') goto basic_json_parser_30; + if (yych <= 'u') goto basic_json_parser_48; + goto basic_json_parser_32; + } + } + } +basic_json_parser_36: + ++m_cursor; + if (m_limit <= m_cursor) fill_line_buffer(1); // LCOV_EXCL_LINE + yych = *m_cursor; + if (yych <= 0x7F) goto basic_json_parser_32; + if (yych <= 0xBF) goto basic_json_parser_30; + goto basic_json_parser_32; +basic_json_parser_37: + ++m_cursor; + if (m_limit <= m_cursor) fill_line_buffer(1); // LCOV_EXCL_LINE + yych = *m_cursor; + if (yych <= 0x9F) goto basic_json_parser_32; + if (yych <= 0xBF) goto basic_json_parser_36; + goto basic_json_parser_32; +basic_json_parser_38: + ++m_cursor; + if (m_limit <= m_cursor) fill_line_buffer(1); // LCOV_EXCL_LINE + yych = *m_cursor; + if (yych <= 0x7F) goto basic_json_parser_32; + if (yych <= 0xBF) goto basic_json_parser_36; + goto basic_json_parser_32; +basic_json_parser_39: + ++m_cursor; + if (m_limit <= m_cursor) fill_line_buffer(1); // LCOV_EXCL_LINE + yych = *m_cursor; + if (yych <= 0x7F) goto basic_json_parser_32; + if (yych <= 0x9F) goto basic_json_parser_36; + goto basic_json_parser_32; +basic_json_parser_40: + ++m_cursor; + if (m_limit <= m_cursor) fill_line_buffer(1); // LCOV_EXCL_LINE + yych = *m_cursor; + if (yych <= 0x8F) goto basic_json_parser_32; + if (yych <= 0xBF) goto basic_json_parser_38; + goto basic_json_parser_32; +basic_json_parser_41: + ++m_cursor; + if (m_limit <= m_cursor) fill_line_buffer(1); // LCOV_EXCL_LINE + yych = *m_cursor; + if (yych <= 0x7F) goto basic_json_parser_32; + if (yych <= 0xBF) goto basic_json_parser_38; + goto basic_json_parser_32; +basic_json_parser_42: + ++m_cursor; + if (m_limit <= m_cursor) fill_line_buffer(1); // LCOV_EXCL_LINE + yych = *m_cursor; + if (yych <= 0x7F) goto basic_json_parser_32; + if (yych <= 0x8F) goto basic_json_parser_38; + goto basic_json_parser_32; +basic_json_parser_43: + yych = *++m_cursor; + if (yych <= '/') goto basic_json_parser_32; + if (yych <= '9') goto basic_json_parser_49; + goto basic_json_parser_32; +basic_json_parser_44: + yych = *++m_cursor; + if (yych <= ',') { + if (yych == '+') goto basic_json_parser_51; + goto basic_json_parser_32; + } else { + if (yych <= '-') goto basic_json_parser_51; + if (yych <= '/') goto basic_json_parser_32; + if (yych <= '9') goto basic_json_parser_52; + goto basic_json_parser_32; + } +basic_json_parser_45: + yych = *++m_cursor; + if (yych == 'l') goto basic_json_parser_54; + goto basic_json_parser_32; +basic_json_parser_46: + yych = *++m_cursor; + if (yych == 'l') goto basic_json_parser_55; + goto basic_json_parser_32; +basic_json_parser_47: + yych = *++m_cursor; + if (yych == 'u') goto basic_json_parser_56; + goto basic_json_parser_32; +basic_json_parser_48: + ++m_cursor; + if (m_limit <= m_cursor) fill_line_buffer(1); // LCOV_EXCL_LINE + yych = *m_cursor; + if (yych <= '@') { + if (yych <= '/') goto basic_json_parser_32; + if (yych <= '9') goto basic_json_parser_57; + goto basic_json_parser_32; + } else { + if (yych <= 'F') goto basic_json_parser_57; + if (yych <= '`') goto basic_json_parser_32; + if (yych <= 'f') goto basic_json_parser_57; + goto basic_json_parser_32; + } +basic_json_parser_49: + yyaccept = 1; + m_marker = ++m_cursor; + if ((m_limit - m_cursor) < 3) fill_line_buffer(3); // LCOV_EXCL_LINE + yych = *m_cursor; + if (yych <= 'D') { + if (yych <= '/') goto basic_json_parser_14; + if (yych <= '9') goto basic_json_parser_49; + goto basic_json_parser_14; + } else { + if (yych <= 'E') goto basic_json_parser_44; + if (yych == 'e') goto basic_json_parser_44; + goto basic_json_parser_14; + } +basic_json_parser_51: + yych = *++m_cursor; + if (yych <= '/') goto basic_json_parser_32; + if (yych >= ':') goto basic_json_parser_32; +basic_json_parser_52: + ++m_cursor; + if (m_limit <= m_cursor) fill_line_buffer(1); // LCOV_EXCL_LINE + yych = *m_cursor; + if (yych <= '/') goto basic_json_parser_14; + if (yych <= '9') goto basic_json_parser_52; + goto basic_json_parser_14; +basic_json_parser_54: + yych = *++m_cursor; + if (yych == 's') goto basic_json_parser_58; + goto basic_json_parser_32; +basic_json_parser_55: + yych = *++m_cursor; + if (yych == 'l') goto basic_json_parser_59; + goto basic_json_parser_32; +basic_json_parser_56: + yych = *++m_cursor; + if (yych == 'e') goto basic_json_parser_61; + goto basic_json_parser_32; +basic_json_parser_57: + ++m_cursor; + if (m_limit <= m_cursor) fill_line_buffer(1); // LCOV_EXCL_LINE + yych = *m_cursor; + if (yych <= '@') { + if (yych <= '/') goto basic_json_parser_32; + if (yych <= '9') goto basic_json_parser_63; + goto basic_json_parser_32; + } else { + if (yych <= 'F') goto basic_json_parser_63; + if (yych <= '`') goto basic_json_parser_32; + if (yych <= 'f') goto basic_json_parser_63; + goto basic_json_parser_32; + } +basic_json_parser_58: + yych = *++m_cursor; + if (yych == 'e') goto basic_json_parser_64; + goto basic_json_parser_32; +basic_json_parser_59: + ++m_cursor; + { last_token_type = token_type::literal_null; break; } +basic_json_parser_61: + ++m_cursor; + { last_token_type = token_type::literal_true; break; } +basic_json_parser_63: + ++m_cursor; + if (m_limit <= m_cursor) fill_line_buffer(1); // LCOV_EXCL_LINE + yych = *m_cursor; + if (yych <= '@') { + if (yych <= '/') goto basic_json_parser_32; + if (yych <= '9') goto basic_json_parser_66; + goto basic_json_parser_32; + } else { + if (yych <= 'F') goto basic_json_parser_66; + if (yych <= '`') goto basic_json_parser_32; + if (yych <= 'f') goto basic_json_parser_66; + goto basic_json_parser_32; + } +basic_json_parser_64: + ++m_cursor; + { last_token_type = token_type::literal_false; break; } +basic_json_parser_66: + ++m_cursor; + if (m_limit <= m_cursor) fill_line_buffer(1); // LCOV_EXCL_LINE + yych = *m_cursor; + if (yych <= '@') { + if (yych <= '/') goto basic_json_parser_32; + if (yych <= '9') goto basic_json_parser_30; + goto basic_json_parser_32; + } else { + if (yych <= 'F') goto basic_json_parser_30; + if (yych <= '`') goto basic_json_parser_32; + if (yych <= 'f') goto basic_json_parser_30; + goto basic_json_parser_32; + } + } } diff --git a/src/json.hpp.re2c b/src/json.hpp.re2c index e1a43b54..e3d5a400 100644 --- a/src/json.hpp.re2c +++ b/src/json.hpp.re2c @@ -5625,36 +5625,23 @@ class basic_json return false; } - /*! - @brief comparison: equal - - The functions compares the given JSON value against a null pointer. As the - null pointer can be used to initialize a JSON value to null, a comparison - of JSON value @a v with a null pointer should be equivalent to call - `v.is_null()`. - - @param[in] v JSON value to consider - @return whether @a v is null - - @complexity Constant. - - @liveexample{The example compares several JSON types to the null pointer. - ,operator__equal__nullptr_t} - - @since version 1.0.0 + /*!@brief comparison: equal + @copydoc operator==(const_reference, const_reference) */ - friend bool operator==(const_reference v, std::nullptr_t) noexcept - { - return v.is_null(); + template::value, int>::type = 0> + friend bool operator==(const_reference lhs, const ScalarType rhs) noexcept { + return (lhs == basic_json(rhs)); } /*! @brief comparison: equal - @copydoc operator==(const_reference, std::nullptr_t) + @copydoc operator==(const_reference, const_reference) */ - friend bool operator==(std::nullptr_t, const_reference v) noexcept - { - return v.is_null(); + template::value, int>::type = 0> + friend bool operator==(const ScalarType lhs, const_reference rhs) noexcept { + return (basic_json(lhs) == rhs); } /*! @@ -5680,34 +5667,24 @@ class basic_json /*! @brief comparison: not equal - - The functions compares the given JSON value against a null pointer. As the - null pointer can be used to initialize a JSON value to null, a comparison - of JSON value @a v with a null pointer should be equivalent to call - `not v.is_null()`. - - @param[in] v JSON value to consider - @return whether @a v is not null - - @complexity Constant. - - @liveexample{The example compares several JSON types to the null pointer. - ,operator__notequal__nullptr_t} - - @since version 1.0.0 + @copydoc operator!=(const_reference, const_reference) */ - friend bool operator!=(const_reference v, std::nullptr_t) noexcept + template::value, int>::type = 0> + friend bool operator!=(const_reference lhs, const ScalarType rhs) noexcept { - return not v.is_null(); + return (lhs != basic_json(rhs)); } /*! @brief comparison: not equal - @copydoc operator!=(const_reference, std::nullptr_t) + @copydoc operator!=(const_reference, const_reference) */ - friend bool operator!=(std::nullptr_t, const_reference v) noexcept + template::value, int>::type = 0> + friend bool operator!=(const ScalarType lhs, const_reference rhs) noexcept { - return not v.is_null(); + return (basic_json(lhs) != rhs); } /*! diff --git a/test/src/unit-regression.cpp b/test/src/unit-regression.cpp index 401867c2..9235d36c 100644 --- a/test/src/unit-regression.cpp +++ b/test/src/unit-regression.cpp @@ -663,4 +663,22 @@ TEST_CASE("regression tests") std::vector vec3 {0xbf, 0x61, 0x61, 0x01}; CHECK_THROWS_AS(json::from_cbor(vec3), std::out_of_range); } + + SECTION("issue #414 - compare with literal 0)") + { + #define CHECK_TYPE(v) \ + CHECK((json(v) == v));\ + CHECK((v == json(v)));\ + CHECK_FALSE((json(v) != v));\ + CHECK_FALSE((v != json(v))); + + CHECK_TYPE(nullptr); + CHECK_TYPE(0); + CHECK_TYPE(0u); + CHECK_TYPE(0L); + CHECK_TYPE(0.0); + CHECK_TYPE(""); + + #undef CHECK_TYPE + } } From f2873e6d3a46847126c03ac754dd9993d32a98a5 Mon Sep 17 00:00:00 2001 From: Jared Grubb Date: Sun, 29 Jan 2017 02:46:58 +0000 Subject: [PATCH 29/80] README: adjust boost::optional example The "from_json" example for boost::optional is not complete and should also handle the 'none' case. --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 1ee358e5..6451e2c5 100644 --- a/README.md +++ b/README.md @@ -563,7 +563,9 @@ namespace nlohmann { } static void from_json(const json& j, boost::optional& opt) { - if (!j.is_null()) { + if (j.is_null()) { + opt = boost::none; + } else { opt = j.get(); // same as above, but with // adl_serializer::from_json } From 0164b10e102f2f8694d380554389a4a4a917f781 Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Sun, 29 Jan 2017 17:18:56 +0100 Subject: [PATCH 30/80] :white_check_mark: added missing tests found by mutate++ --- test/src/unit-class_parser.cpp | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/test/src/unit-class_parser.cpp b/test/src/unit-class_parser.cpp index 3dfad5bd..59ea3cef 100644 --- a/test/src/unit-class_parser.cpp +++ b/test/src/unit-class_parser.cpp @@ -596,6 +596,32 @@ TEST_CASE("parser class") "missing or wrong low surrogate"); } + SECTION("tests found by mutate++") + { + // test case to make sure no comma preceeds the first key + CHECK_THROWS_AS(json::parser("{,\"key\": false}").parse(), std::invalid_argument); + // test case to make sure an object is properly closed + CHECK_THROWS_AS(json::parser("[{\"key\": false true]").parse(), std::invalid_argument); + + // test case to make sure the callback is properly evaluated after reading a key + { + json::parser_callback_t cb = [](int depth, json::parse_event_t event, json & parsed) + { + if (event == json::parse_event_t::key) + { + return false; + } + else + { + return true; + } + }; + + json x = json::parse("{\"key\": false}", cb); + CHECK(x == json::object()); + } + } + SECTION("callback function") { auto s_object = R"( From b210f2dbf41fc207a91e57359c8b2cffdba64ebf Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Sun, 29 Jan 2017 21:40:37 +0100 Subject: [PATCH 31/80] :lipstick: minor refactoring --- src/json.hpp | 6 ++---- src/json.hpp.re2c | 6 ++---- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/src/json.hpp b/src/json.hpp index 5fdd83d6..d7af3a70 100644 --- a/src/json.hpp +++ b/src/json.hpp @@ -3036,10 +3036,8 @@ class basic_json { return m_value.boolean; } - else - { - JSON_THROW(std::domain_error("type must be boolean, but is " + type_name())); - } + + JSON_THROW(std::domain_error("type must be boolean, but is " + type_name())); } /// get a pointer to the value (object) diff --git a/src/json.hpp.re2c b/src/json.hpp.re2c index 068b8763..cc11457f 100644 --- a/src/json.hpp.re2c +++ b/src/json.hpp.re2c @@ -3036,10 +3036,8 @@ class basic_json { return m_value.boolean; } - else - { - JSON_THROW(std::domain_error("type must be boolean, but is " + type_name())); - } + + JSON_THROW(std::domain_error("type must be boolean, but is " + type_name())); } /// get a pointer to the value (object) From c75865d88c0176b85f3e8d073a784602323b2160 Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Wed, 1 Feb 2017 15:13:21 +0100 Subject: [PATCH 32/80] :bug: fixed `-Weffc++` warnings --- src/json.hpp | 10 ++++++---- src/json.hpp.re2c | 10 ++++++---- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/src/json.hpp b/src/json.hpp index d7af3a70..c77945a8 100644 --- a/src/json.hpp +++ b/src/json.hpp @@ -8532,10 +8532,11 @@ class basic_json return *this; } - primitive_iterator_t& operator++(int) + primitive_iterator_t operator++(int) { + auto result = *this; m_it++; - return *this; + return result; } primitive_iterator_t& operator--() @@ -8544,10 +8545,11 @@ class basic_json return *this; } - primitive_iterator_t& operator--(int) + primitive_iterator_t operator--(int) { + auto result = *this; m_it--; - return *this; + return result; } primitive_iterator_t& operator+=(difference_type n) diff --git a/src/json.hpp.re2c b/src/json.hpp.re2c index cc11457f..109a4f26 100644 --- a/src/json.hpp.re2c +++ b/src/json.hpp.re2c @@ -8532,10 +8532,11 @@ class basic_json return *this; } - primitive_iterator_t& operator++(int) + primitive_iterator_t operator++(int) { + auto result = *this; m_it++; - return *this; + return result; } primitive_iterator_t& operator--() @@ -8544,10 +8545,11 @@ class basic_json return *this; } - primitive_iterator_t& operator--(int) + primitive_iterator_t operator--(int) { + auto result = *this; m_it--; - return *this; + return result; } primitive_iterator_t& operator+=(difference_type n) From bf8fdac99a3e327a2a054d1d9a7eb1827d2f5c0f Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Wed, 1 Feb 2017 16:41:05 +0100 Subject: [PATCH 33/80] :construction_worker: dropped Doozer.io support --- .doozer.json | 24 ------------------------ README.md | 1 - 2 files changed, 25 deletions(-) delete mode 100644 .doozer.json diff --git a/.doozer.json b/.doozer.json deleted file mode 100644 index 7dbaa5d2..00000000 --- a/.doozer.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "targets": { - "xenial-i386": { - "buildenv": "xenial-i386", - "builddeps": ["build-essential", "cmake"], - "buildcmd": ["mkdir cm", "cd cm", "cmake ..", "cmake --build .", "ctest --output-on-failure"] - }, - "xenial-amd64": { - "buildenv": "xenial-amd64", - "builddeps": ["build-essential", "cmake"], - "buildcmd": ["mkdir cm", "cd cm", "cmake ..", "cmake --build .", "ctest --output-on-failure"] - }, - "fedora24-x86_64": { - "buildenv": "fedora24-x86_64", - "builddeps": ["cmake", "make", "clang"], - "buildcmd": ["mkdir cm", "cd cm", "CXX=clang++ cmake ..", "cmake --build .", "ctest --output-on-failure"] - }, - "osx": { - "buildenv": "osx", - "builddeps": ["build-essential"], - "buildcmd": ["make check"] - } - } -} diff --git a/README.md b/README.md index 6451e2c5..6ebd30e4 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,6 @@ [![Build Status](https://travis-ci.org/nlohmann/json.svg?branch=master)](https://travis-ci.org/nlohmann/json) [![Build Status](https://ci.appveyor.com/api/projects/status/1acb366xfyg3qybk/branch/develop?svg=true)](https://ci.appveyor.com/project/nlohmann/json) -[![Build status](https://doozer.io/badge/nlohmann/json/buildstatus/develop)](https://doozer.io/user/nlohmann/json) [![Coverage Status](https://img.shields.io/coveralls/nlohmann/json.svg)](https://coveralls.io/r/nlohmann/json) [![Coverity Scan Build Status](https://scan.coverity.com/projects/5550/badge.svg)](https://scan.coverity.com/projects/nlohmann-json) [![Try online](https://img.shields.io/badge/try-online-blue.svg)](http://melpon.org/wandbox/permlink/4NEU6ZZMoM9lpIex) From 16af771277612ac56e03585b267555e4f31c7930 Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Wed, 1 Feb 2017 17:34:39 +0100 Subject: [PATCH 34/80] :white_check_mark: added roundtrip test for the Big List of Naughty Strings --- README.md | 2 +- test/src/unit-testsuites.cpp | 45 +++++++++++++++++++++++++++++++++++- 2 files changed, 45 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 6ebd30e4..5cb91abb 100644 --- a/README.md +++ b/README.md @@ -839,7 +839,7 @@ $ make json_unit -Ctest $ ./test/json_unit "*"" =============================================================================== -All tests passed (11202052 assertions in 47 test cases) +All tests passed (11202549 assertions in 47 test cases) ``` Alternatively, you can use [CMake](https://cmake.org) and run diff --git a/test/src/unit-testsuites.cpp b/test/src/unit-testsuites.cpp index 9a9de127..62e7e37e 100644 --- a/test/src/unit-testsuites.cpp +++ b/test/src/unit-testsuites.cpp @@ -816,13 +816,56 @@ TEST_CASE("nst's JSONTestSuite") } } +// from http://stackoverflow.com/a/25829178/266378 +std::string trim(const std::string& str) +{ + size_t first = str.find_first_not_of(' '); + if (std::string::npos == first) + { + return str; + } + size_t last = str.find_last_not_of(' '); + return str.substr(first, (last - first + 1)); +} + TEST_CASE("Big List of Naughty Strings") { // test from https://github.com/minimaxir/big-list-of-naughty-strings - SECTION("blns.json") + SECTION("parsing blns.json") { std::ifstream f("test/data/big-list-of-naughty-strings/blns.json"); json j; CHECK_NOTHROW(j << f); } + + // check if parsed strings roundtrip + // https://www.reddit.com/r/cpp/comments/5qpbie/json_form_modern_c_version_210/dd12mpq/ + SECTION("roundtripping") + { + std::ifstream f("test/data/big-list-of-naughty-strings/blns.json"); + + while (not f.eof()) + { + // read line + std::string line; + getline(f, line); + + // trim whitespace + line = trim(line); + + // remove trailing comma + line = line.substr(0, line.find_last_of(",")); + + // discard lines without at least two characters (quotes) + if (line.size() < 2) + { + continue; + } + + // check roundtrip + CAPTURE(line); + json j = json::parse(line); + CHECK(j.dump() == line); + } + } } From 5976caf032726b59e92a482c25cb34cc5946c33b Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Fri, 3 Feb 2017 18:09:55 +0100 Subject: [PATCH 35/80] :zap: improved test compilation speed #445 --- test/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/Makefile b/test/Makefile index 0b235ba1..a8cbade8 100644 --- a/test/Makefile +++ b/test/Makefile @@ -71,9 +71,9 @@ json_unit: $(OBJECTS) ../src/json.hpp thirdparty/catch/catch.hpp # individual test cases ############################################################################## -test-%: src/unit-%.cpp ../src/json.hpp thirdparty/catch/catch.hpp +test-%: src/unit.o src/unit-%.o ../src/json.hpp thirdparty/catch/catch.hpp @echo "[CXXLD] $@" - @$(CXX) $(CXXFLAGS) $(CPPFLAGS) $(LDFLAGS) -DCATCH_CONFIG_MAIN $< -o $@ + @$(CXX) $(CXXFLAGS) $(CPPFLAGS) $(LDFLAGS) $< -o $@ TEST_PATTERN ?= "*" TEST_PREFIX = "" From d6afaa8e168219d2809e8842314fe3dcd759318f Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Fri, 3 Feb 2017 18:15:37 +0100 Subject: [PATCH 36/80] :memo: fixing a documentation issue #442 --- README.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 5cb91abb..43f428fc 100644 --- a/README.md +++ b/README.md @@ -166,8 +166,14 @@ auto j2 = R"( "pi": 3.141 } )"_json; +``` -// or explicitly +Note that without appending the `_json` suffix, the passed string literal is not parsed, but just used as JSON string value. That is, `json j = "{ \"happy\": true, \"pi\": 3.141 }"` would just store the string `"{ "happy": true, "pi": 3.141 }"` rather than parsing the acutal object. + +The above example can also be expressed explicitly using `json::parse()`: + +```cpp +// parse explicitly auto j3 = json::parse("{ \"happy\": true, \"pi\": 3.141 }"); ``` From 77d6f7060208d6d3ca89d8a3850990f11ea719a0 Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Fri, 3 Feb 2017 18:28:22 +0100 Subject: [PATCH 37/80] :memo: acknowledgments for #442 and #445 --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index 43f428fc..1933c12a 100644 --- a/README.md +++ b/README.md @@ -818,6 +818,9 @@ I deeply appreciate the help of the following people. - [Alexej Harm](https://github.com/qis) helped to get the user-defined types working with Visual Studio. - [Jared Grubb](https://github.com/jaredgrubb) supported the implementation of user-defined types. - [EnricoBilla](https://github.com/EnricoBilla) noted a typo in an example. +- [Martin HoÅ™eňovský](https://github.com/horenmar) found a way for a 2x speedup for the compilation time of the test suite. +- [ukhegg](https://github.com/ukhegg) found proposed an improvement for the examples section. + Thanks a lot for helping out! Please [let me know](mailto:mail@nlohmann.me) if I forgot someone. From 1cfdc2a7537d18e21651f6b47d25e8668a4396ca Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Sat, 4 Feb 2017 08:25:55 +0100 Subject: [PATCH 38/80] :bug: fixed test compilation --- test/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/Makefile b/test/Makefile index a8cbade8..8f4e215f 100644 --- a/test/Makefile +++ b/test/Makefile @@ -71,9 +71,9 @@ json_unit: $(OBJECTS) ../src/json.hpp thirdparty/catch/catch.hpp # individual test cases ############################################################################## -test-%: src/unit.o src/unit-%.o ../src/json.hpp thirdparty/catch/catch.hpp +test-%: src/unit-%.o src/unit.o ../src/json.hpp thirdparty/catch/catch.hpp @echo "[CXXLD] $@" - @$(CXX) $(CXXFLAGS) $(CPPFLAGS) $(LDFLAGS) $< -o $@ + @$(CXX) $(CXXFLAGS) $(CPPFLAGS) $(LDFLAGS) $< src/unit.o -o $@ TEST_PATTERN ?= "*" TEST_PREFIX = "" From 922fe693e1c73fb298b9e8dfb8aa2776c9a4e722 Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Sat, 4 Feb 2017 15:30:28 +0100 Subject: [PATCH 39/80] :arrow_up: updated Catch to v1.7.0 --- test/src/unit-allocator.cpp | 50 +- test/thirdparty/catch/catch.hpp | 21572 +++++++++++++++--------------- 2 files changed, 11021 insertions(+), 10601 deletions(-) diff --git a/test/src/unit-allocator.cpp b/test/src/unit-allocator.cpp index ae45ac26..9fc2681f 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 j(bad_json::value_t::object), std::bad_alloc); + CHECK_THROWS_AS(bad_json(bad_json::value_t::object), std::bad_alloc); } } @@ -141,39 +141,27 @@ TEST_CASE("controlled bad_alloc") { next_construct_fails = false; auto t = my_json::value_t::object; - auto clean_up = [](my_json::json_value & j) - { - my_allocator_clean_up(j.object); - }; - CHECK_NOTHROW(my_json::json_value j(t); clean_up(j)); + CHECK_NOTHROW(my_allocator_clean_up(my_json::json_value(t).object)); next_construct_fails = true; - CHECK_THROWS_AS(my_json::json_value j(t), std::bad_alloc); + CHECK_THROWS_AS(my_json::json_value(t), std::bad_alloc); next_construct_fails = false; } SECTION("array") { next_construct_fails = false; auto t = my_json::value_t::array; - auto clean_up = [](my_json::json_value & j) - { - my_allocator_clean_up(j.array); - }; - CHECK_NOTHROW(my_json::json_value j(t); clean_up(j)); + CHECK_NOTHROW(my_allocator_clean_up(my_json::json_value(t).array)); next_construct_fails = true; - CHECK_THROWS_AS(my_json::json_value j(t), std::bad_alloc); + CHECK_THROWS_AS(my_json::json_value(t), std::bad_alloc); next_construct_fails = false; } SECTION("string") { next_construct_fails = false; auto t = my_json::value_t::string; - auto clean_up = [](my_json::json_value & j) - { - my_allocator_clean_up(j.string); - }; - CHECK_NOTHROW(my_json::json_value j(t); clean_up(j)); + CHECK_NOTHROW(my_allocator_clean_up(my_json::json_value(t).string)); next_construct_fails = true; - CHECK_THROWS_AS(my_json::json_value j(t), std::bad_alloc); + CHECK_THROWS_AS(my_json::json_value(t), std::bad_alloc); next_construct_fails = false; } } @@ -182,13 +170,9 @@ TEST_CASE("controlled bad_alloc") { next_construct_fails = false; my_json::string_t v("foo"); - auto clean_up = [](my_json::json_value & j) - { - my_allocator_clean_up(j.string); - }; - CHECK_NOTHROW(my_json::json_value j(v); clean_up(j)); + CHECK_NOTHROW(my_allocator_clean_up(my_json::json_value(v).string)); next_construct_fails = true; - CHECK_THROWS_AS(my_json::json_value j(v), std::bad_alloc); + CHECK_THROWS_AS(my_json::json_value(v), std::bad_alloc); next_construct_fails = false; } @@ -222,9 +206,9 @@ TEST_CASE("controlled bad_alloc") { next_construct_fails = false; std::map v {{"foo", "bar"}}; - CHECK_NOTHROW(my_json j(v)); + CHECK_NOTHROW(my_json(v)); next_construct_fails = true; - CHECK_THROWS_AS(my_json j(v), std::bad_alloc); + CHECK_THROWS_AS(my_json(v), std::bad_alloc); next_construct_fails = false; } @@ -232,18 +216,18 @@ TEST_CASE("controlled bad_alloc") { next_construct_fails = false; std::vector v {"foo", "bar", "baz"}; - CHECK_NOTHROW(my_json j(v)); + CHECK_NOTHROW(my_json(v)); next_construct_fails = true; - CHECK_THROWS_AS(my_json j(v), std::bad_alloc); + CHECK_THROWS_AS(my_json(v), std::bad_alloc); next_construct_fails = false; } SECTION("basic_json(const typename string_t::value_type*)") { next_construct_fails = false; - CHECK_NOTHROW(my_json v("foo")); + CHECK_NOTHROW(my_json("foo")); next_construct_fails = true; - CHECK_THROWS_AS(my_json v("foo"), std::bad_alloc); + CHECK_THROWS_AS(my_json("foo"), std::bad_alloc); next_construct_fails = false; } @@ -251,9 +235,9 @@ TEST_CASE("controlled bad_alloc") { next_construct_fails = false; std::string s("foo"); - CHECK_NOTHROW(my_json v(s)); + CHECK_NOTHROW(my_json(s)); next_construct_fails = true; - CHECK_THROWS_AS(my_json v(s), std::bad_alloc); + CHECK_THROWS_AS(my_json(s), std::bad_alloc); next_construct_fails = false; } } diff --git a/test/thirdparty/catch/catch.hpp b/test/thirdparty/catch/catch.hpp index 1d49e738..c1ef3ed6 100644 --- a/test/thirdparty/catch/catch.hpp +++ b/test/thirdparty/catch/catch.hpp @@ -1,10568 +1,11004 @@ -/* - * Catch v1.6.0 - * Generated: 2017-01-11 16:38:09.405017 - * ---------------------------------------------------------- - * This file has been merged from multiple headers. Please don't edit it directly - * Copyright (c) 2012 Two Blue Cubes Ltd. All rights reserved. - * - * Distributed under the Boost Software License, Version 1.0. (See accompanying - * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) - */ -#ifndef TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED -#define TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED - -#define TWOBLUECUBES_CATCH_HPP_INCLUDED - -#ifdef __clang__ -# pragma clang system_header -#elif defined __GNUC__ -# pragma GCC system_header -#endif - -// #included from: internal/catch_suppress_warnings.h - -#ifdef __clang__ -# ifdef __ICC // icpc defines the __clang__ macro -# pragma warning(push) -# pragma warning(disable: 161 1682) -# else // __ICC -# pragma clang diagnostic ignored "-Wglobal-constructors" -# pragma clang diagnostic ignored "-Wvariadic-macros" -# pragma clang diagnostic ignored "-Wc99-extensions" -# pragma clang diagnostic ignored "-Wunused-variable" -# pragma clang diagnostic push -# pragma clang diagnostic ignored "-Wpadded" -# pragma clang diagnostic ignored "-Wc++98-compat" -# pragma clang diagnostic ignored "-Wc++98-compat-pedantic" -# pragma clang diagnostic ignored "-Wswitch-enum" -# pragma clang diagnostic ignored "-Wcovered-switch-default" -# endif -#elif defined __GNUC__ -# pragma GCC diagnostic ignored "-Wvariadic-macros" -# pragma GCC diagnostic ignored "-Wunused-variable" -# pragma GCC diagnostic push -# pragma GCC diagnostic ignored "-Wpadded" -#endif -#if defined(CATCH_CONFIG_MAIN) || defined(CATCH_CONFIG_RUNNER) -# define CATCH_IMPL -#endif - -#ifdef CATCH_IMPL -# ifndef CLARA_CONFIG_MAIN -# define CLARA_CONFIG_MAIN_NOT_DEFINED -# define CLARA_CONFIG_MAIN -# endif -#endif - -// #included from: internal/catch_notimplemented_exception.h -#define TWOBLUECUBES_CATCH_NOTIMPLEMENTED_EXCEPTION_H_INCLUDED - -// #included from: catch_common.h -#define TWOBLUECUBES_CATCH_COMMON_H_INCLUDED - -// #included from: catch_compiler_capabilities.h -#define TWOBLUECUBES_CATCH_COMPILER_CAPABILITIES_HPP_INCLUDED - -// Detect a number of compiler features - mostly C++11/14 conformance - by compiler -// The following features are defined: -// -// CATCH_CONFIG_CPP11_NULLPTR : is nullptr supported? -// CATCH_CONFIG_CPP11_NOEXCEPT : is noexcept supported? -// CATCH_CONFIG_CPP11_GENERATED_METHODS : The delete and default keywords for compiler generated methods -// CATCH_CONFIG_CPP11_IS_ENUM : std::is_enum is supported? -// CATCH_CONFIG_CPP11_TUPLE : std::tuple is supported -// CATCH_CONFIG_CPP11_LONG_LONG : is long long supported? -// CATCH_CONFIG_CPP11_OVERRIDE : is override supported? -// CATCH_CONFIG_CPP11_UNIQUE_PTR : is unique_ptr supported (otherwise use auto_ptr) - -// CATCH_CONFIG_CPP11_OR_GREATER : Is C++11 supported? - -// CATCH_CONFIG_VARIADIC_MACROS : are variadic macros supported? -// CATCH_CONFIG_COUNTER : is the __COUNTER__ macro supported? -// **************** -// Note to maintainers: if new toggles are added please document them -// in configuration.md, too -// **************** - -// In general each macro has a _NO_ form -// (e.g. CATCH_CONFIG_CPP11_NO_NULLPTR) which disables the feature. -// Many features, at point of detection, define an _INTERNAL_ macro, so they -// can be combined, en-mass, with the _NO_ forms later. - -// All the C++11 features can be disabled with CATCH_CONFIG_NO_CPP11 - -#ifdef __cplusplus - -# if __cplusplus >= 201103L -# define CATCH_CPP11_OR_GREATER -# endif - -# if __cplusplus >= 201402L -# define CATCH_CPP14_OR_GREATER -# endif - -#endif - -#ifdef __clang__ - -# if __has_feature(cxx_nullptr) -# define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR -# endif - -# if __has_feature(cxx_noexcept) -# define CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT -# endif - -# if defined(CATCH_CPP11_OR_GREATER) -# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS _Pragma( "clang diagnostic ignored \"-Wparentheses\"" ) -# endif - -#endif // __clang__ - -//////////////////////////////////////////////////////////////////////////////// -// Borland -#ifdef __BORLANDC__ - -#endif // __BORLANDC__ - -//////////////////////////////////////////////////////////////////////////////// -// EDG -#ifdef __EDG_VERSION__ - -#endif // __EDG_VERSION__ - -//////////////////////////////////////////////////////////////////////////////// -// Digital Mars -#ifdef __DMC__ - -#endif // __DMC__ - -//////////////////////////////////////////////////////////////////////////////// -// GCC -#ifdef __GNUC__ - -# if __GNUC__ == 4 && __GNUC_MINOR__ >= 6 && defined(__GXX_EXPERIMENTAL_CXX0X__) -# define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR -# endif - -# if !defined(CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS) && defined(CATCH_CPP11_OR_GREATER) -# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS _Pragma( "GCC diagnostic ignored \"-Wparentheses\"" ) -# endif - -// - otherwise more recent versions define __cplusplus >= 201103L -// and will get picked up below - -#endif // __GNUC__ - -//////////////////////////////////////////////////////////////////////////////// -// Visual C++ -#ifdef _MSC_VER - -#if (_MSC_VER >= 1600) -# define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR -# define CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR -#endif - -#if (_MSC_VER >= 1900 ) // (VC++ 13 (VS2015)) -#define CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT -#define CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS -#define CATCH_INTERNAL_CONFIG_CPP11_SHUFFLE -#endif - -#endif // _MSC_VER - -//////////////////////////////////////////////////////////////////////////////// - -// Use variadic macros if the compiler supports them -#if ( defined _MSC_VER && _MSC_VER > 1400 && !defined __EDGE__) || \ - ( defined __WAVE__ && __WAVE_HAS_VARIADICS ) || \ - ( defined __GNUC__ && __GNUC__ >= 3 ) || \ - ( !defined __cplusplus && __STDC_VERSION__ >= 199901L || __cplusplus >= 201103L ) - -#define CATCH_INTERNAL_CONFIG_VARIADIC_MACROS - -#endif - -// Use __COUNTER__ if the compiler supports it -#if ( defined _MSC_VER && _MSC_VER >= 1300 ) || \ - ( defined __GNUC__ && __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 - -#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 -#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_SUPPRESS_PARENTHESES_WARNINGS) -# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS -#endif - -// noexcept support: -#if defined(CATCH_CONFIG_CPP11_NOEXCEPT) && !defined(CATCH_NOEXCEPT) -# define CATCH_NOEXCEPT noexcept -# define CATCH_NOEXCEPT_IS(x) noexcept(x) -#else -# define CATCH_NOEXCEPT throw() -# define CATCH_NOEXCEPT_IS(x) -#endif - -// nullptr support -#ifdef CATCH_CONFIG_CPP11_NULLPTR -# define CATCH_NULL nullptr -#else -# define CATCH_NULL NULL -#endif - -// override support -#ifdef CATCH_CONFIG_CPP11_OVERRIDE -# define CATCH_OVERRIDE override -#else -# define CATCH_OVERRIDE -#endif - -// unique_ptr support -#ifdef CATCH_CONFIG_CPP11_UNIQUE_PTR -# define CATCH_AUTO_PTR( T ) std::unique_ptr -#else -# define CATCH_AUTO_PTR( T ) std::auto_ptr -#endif - -#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 -# define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __COUNTER__ ) -#else -# 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 - -namespace Catch { - - struct IConfig; - - struct CaseSensitive { enum Choice { - Yes, - No - }; }; - - class NonCopyable { -#ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS - NonCopyable( NonCopyable const& ) = delete; - NonCopyable( NonCopyable && ) = delete; - NonCopyable& operator = ( NonCopyable const& ) = delete; - NonCopyable& operator = ( NonCopyable && ) = delete; -#else - NonCopyable( NonCopyable const& info ); - NonCopyable& operator = ( NonCopyable const& ); -#endif - - protected: - NonCopyable() {} - virtual ~NonCopyable(); - }; - - class SafeBool { - public: - typedef void (SafeBool::*type)() const; - - static type makeSafe( bool value ) { - return value ? &SafeBool::trueValue : 0; - } - private: - void trueValue() const {} - }; - - template - inline void deleteAll( ContainerT& container ) { - typename ContainerT::const_iterator it = container.begin(); - typename ContainerT::const_iterator itEnd = container.end(); - for(; it != itEnd; ++it ) - delete *it; - } - template - inline void deleteAllValues( AssociativeContainerT& container ) { - typename AssociativeContainerT::const_iterator it = container.begin(); - typename AssociativeContainerT::const_iterator itEnd = container.end(); - for(; it != itEnd; ++it ) - delete it->second; - } - - bool startsWith( std::string const& s, std::string const& prefix ); - bool endsWith( std::string const& s, std::string const& suffix ); - bool contains( std::string const& s, std::string const& infix ); - void toLowerInPlace( std::string& s ); - std::string toLower( std::string const& s ); - std::string trim( std::string const& str ); - bool replaceInPlace( std::string& str, std::string const& replaceThis, std::string const& withThis ); - - struct pluralise { - pluralise( std::size_t count, std::string const& label ); - - friend std::ostream& operator << ( std::ostream& os, pluralise const& pluraliser ); - - std::size_t m_count; - std::string m_label; - }; - - struct SourceLineInfo { - - SourceLineInfo(); - SourceLineInfo( char const* _file, std::size_t _line ); - SourceLineInfo( SourceLineInfo const& other ); -# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS - SourceLineInfo( SourceLineInfo && ) = default; - SourceLineInfo& operator = ( SourceLineInfo const& ) = default; - SourceLineInfo& operator = ( SourceLineInfo && ) = default; -# endif - bool empty() const; - bool operator == ( SourceLineInfo const& other ) const; - bool operator < ( SourceLineInfo const& other ) const; - - std::string file; - std::size_t line; - }; - - std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info ); - - // This is just here to avoid compiler warnings with macro constants and boolean literals - inline bool isTrue( bool value ){ return value; } - inline bool alwaysTrue() { return true; } - inline bool alwaysFalse() { return false; } - - void throwLogicError( std::string const& message, SourceLineInfo const& locationInfo ); - - void seedRng( IConfig const& config ); - unsigned int rngSeed(); - - // Use this in variadic streaming macros to allow - // >> +StreamEndStop - // as well as - // >> stuff +StreamEndStop - struct StreamEndStop { - std::string operator+() { - return std::string(); - } - }; - template - T const& operator + ( T const& value, StreamEndStop ) { - return value; - } -} - -#define CATCH_INTERNAL_LINEINFO ::Catch::SourceLineInfo( __FILE__, static_cast( __LINE__ ) ) -#define CATCH_INTERNAL_ERROR( msg ) ::Catch::throwLogicError( msg, CATCH_INTERNAL_LINEINFO ); - -#include - -namespace Catch { - - class NotImplementedException : public std::exception - { - public: - NotImplementedException( SourceLineInfo const& lineInfo ); - NotImplementedException( NotImplementedException const& ) {} - - virtual ~NotImplementedException() CATCH_NOEXCEPT {} - - virtual const char* what() const CATCH_NOEXCEPT; - - private: - std::string m_what; - SourceLineInfo m_lineInfo; - }; - -} // end namespace Catch - -/////////////////////////////////////////////////////////////////////////////// -#define CATCH_NOT_IMPLEMENTED throw Catch::NotImplementedException( CATCH_INTERNAL_LINEINFO ) - -// #included from: internal/catch_context.h -#define TWOBLUECUBES_CATCH_CONTEXT_H_INCLUDED - -// #included from: catch_interfaces_generators.h -#define TWOBLUECUBES_CATCH_INTERFACES_GENERATORS_H_INCLUDED - -#include - -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 - -#include -#include -#include - -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 - -namespace Catch { - - class TestSpec; - - struct ITestCase : IShared { - virtual void invoke () const = 0; - protected: - virtual ~ITestCase(); - }; - - class TestCase; - struct IConfig; - - struct ITestCaseRegistry { - virtual ~ITestCaseRegistry(); - virtual std::vector const& getAllTests() const = 0; - virtual std::vector const& getAllTestsSorted( IConfig const& config ) const = 0; - }; - - bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config ); - std::vector filterTests( std::vector const& testCases, TestSpec const& testSpec, IConfig const& config ); - std::vector const& getAllTestCasesSorted( IConfig const& config ); - -} - -namespace Catch { - -template -class MethodTestCase : public SharedImpl { - -public: - MethodTestCase( void (C::*method)() ) : m_method( method ) {} - - virtual void invoke() const { - C obj; - (obj.*m_method)(); - } - -private: - virtual ~MethodTestCase() {} - - void (C::*m_method)(); -}; - -typedef void(*TestFunction)(); - -struct NameAndDesc { - NameAndDesc( const char* _name = "", const char* _description= "" ) - : name( _name ), description( _description ) - {} - - const char* name; - const char* description; -}; - -void registerTestCase - ( ITestCase* testCase, - char const* className, - NameAndDesc const& nameAndDesc, - SourceLineInfo const& lineInfo ); - -struct AutoReg { - - AutoReg - ( TestFunction function, - SourceLineInfo const& lineInfo, - NameAndDesc const& nameAndDesc ); - - template - 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 - -#ifdef CATCH_CONFIG_VARIADIC_MACROS - /////////////////////////////////////////////////////////////////////////////// - #define INTERNAL_CATCH_TESTCASE2( TestName, ... ) \ - static void TestName(); \ - namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &TestName, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( __VA_ARGS__ ) ); }\ - 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, ... ) \ - namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &QualifiedMethod, "&" #QualifiedMethod, Catch::NameAndDesc( __VA_ARGS__ ), CATCH_INTERNAL_LINEINFO ); } - - /////////////////////////////////////////////////////////////////////////////// - #define INTERNAL_CATCH_TEST_CASE_METHOD2( TestName, ClassName, ... )\ - namespace{ \ - struct TestName : ClassName{ \ - void test(); \ - }; \ - Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( &TestName::test, #ClassName, Catch::NameAndDesc( __VA_ARGS__ ), CATCH_INTERNAL_LINEINFO ); \ - } \ - 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::AutoReg( Function, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( __VA_ARGS__ ) ); - -#else - /////////////////////////////////////////////////////////////////////////////// - #define INTERNAL_CATCH_TESTCASE2( TestName, Name, Desc ) \ - static void TestName(); \ - namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &TestName, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( Name, Desc ) ); }\ - 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 ) - - /////////////////////////////////////////////////////////////////////////////// - #define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, Name, Desc ) \ - namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &QualifiedMethod, "&" #QualifiedMethod, Catch::NameAndDesc( Name, Desc ), CATCH_INTERNAL_LINEINFO ); } - - /////////////////////////////////////////////////////////////////////////////// - #define INTERNAL_CATCH_TEST_CASE_METHOD2( TestCaseName, ClassName, TestName, Desc )\ - namespace{ \ - struct TestCaseName : ClassName{ \ - void test(); \ - }; \ - Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( &TestCaseName::test, #ClassName, Catch::NameAndDesc( TestName, Desc ), CATCH_INTERNAL_LINEINFO ); \ - } \ - 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 ) - - /////////////////////////////////////////////////////////////////////////////// - #define INTERNAL_CATCH_REGISTER_TESTCASE( Function, Name, Desc ) \ - Catch::AutoReg( Function, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( Name, Desc ) ); -#endif - -// #included from: internal/catch_capture.hpp -#define TWOBLUECUBES_CATCH_CAPTURE_HPP_INCLUDED - -// #included from: catch_result_builder.h -#define TWOBLUECUBES_CATCH_RESULT_BUILDER_H_INCLUDED - -// #included from: catch_result_type.h -#define TWOBLUECUBES_CATCH_RESULT_TYPE_H_INCLUDED - -namespace Catch { - - // ResultWas::OfType enum - struct ResultWas { enum OfType { - Unknown = -1, - Ok = 0, - Info = 1, - Warning = 2, - - FailureBit = 0x10, - - ExpressionFailed = FailureBit | 1, - ExplicitFailure = FailureBit | 2, - - Exception = 0x100 | FailureBit, - - ThrewException = Exception | 1, - DidntThrowException = Exception | 2, - - FatalErrorCondition = 0x200 | FailureBit - - }; }; - - inline bool isOk( ResultWas::OfType resultType ) { - return ( resultType & ResultWas::FailureBit ) == 0; - } - inline bool isJustInfo( int flags ) { - return flags == ResultWas::Info; - } - - // ResultDisposition::Flags enum - struct ResultDisposition { enum Flags { - Normal = 0x01, - - ContinueOnFailure = 0x02, // Failures fail test, but execution continues - FalseTest = 0x04, // Prefix expression with ! - SuppressFail = 0x08 // Failures are reported but do not fail the test - }; }; - - inline ResultDisposition::Flags operator | ( ResultDisposition::Flags lhs, ResultDisposition::Flags rhs ) { - return static_cast( 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 AssertionInfo - { - AssertionInfo() {} - AssertionInfo( std::string const& _macroName, - SourceLineInfo const& _lineInfo, - std::string const& _capturedExpression, - ResultDisposition::Flags _resultDisposition ); - - std::string macroName; - SourceLineInfo lineInfo; - std::string capturedExpression; - ResultDisposition::Flags resultDisposition; - }; - - struct AssertionResultData - { - AssertionResultData() : resultType( ResultWas::Unknown ) {} - - std::string reconstructedExpression; - std::string message; - ResultWas::OfType resultType; - }; - - class AssertionResult { - public: - AssertionResult(); - AssertionResult( AssertionInfo const& info, AssertionResultData const& data ); - ~AssertionResult(); -# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS - AssertionResult( AssertionResult const& ) = default; - AssertionResult( AssertionResult && ) = default; - AssertionResult& operator = ( AssertionResult const& ) = default; - AssertionResult& operator = ( AssertionResult && ) = default; -# endif - - bool isOk() const; - bool succeeded() const; - ResultWas::OfType getResultType() const; - bool hasExpression() const; - bool hasMessage() const; - std::string getExpression() const; - std::string getExpressionInMacro() const; - bool hasExpandedExpression() const; - std::string getExpandedExpression() const; - std::string getMessage() const; - SourceLineInfo getSourceInfo() const; - std::string getTestMacroName() const; - - protected: - AssertionInfo m_info; - AssertionResultData m_resultData; - }; - -} // end namespace Catch - -// #included from: catch_matchers.hpp -#define TWOBLUECUBES_CATCH_MATCHERS_HPP_INCLUDED - -namespace Catch { -namespace Matchers { - namespace Impl { - - namespace Generic { - template class AllOf; - template class AnyOf; - template class Not; - } - - template - struct Matcher : SharedImpl - { - typedef ExpressionT ExpressionType; - - virtual ~Matcher() {} - virtual Ptr clone() const = 0; - virtual bool match( ExpressionT const& expr ) const = 0; - virtual std::string toString() const = 0; - - Generic::AllOf operator && ( Matcher const& other ) const; - Generic::AnyOf operator || ( Matcher const& other ) const; - Generic::Not operator ! () const; - }; - - template - struct MatcherImpl : Matcher { - - virtual Ptr > clone() const { - return Ptr >( new DerivedT( static_cast( *this ) ) ); - } - }; - - namespace Generic { - template - class Not : public MatcherImpl, ExpressionT> { - public: - explicit Not( Matcher const& matcher ) : m_matcher(matcher.clone()) {} - Not( Not const& other ) : m_matcher( other.m_matcher ) {} - - virtual bool match( ExpressionT const& expr ) const CATCH_OVERRIDE { - return !m_matcher->match( expr ); - } - - virtual std::string toString() const CATCH_OVERRIDE { - return "not " + m_matcher->toString(); - } - private: - Ptr< Matcher > m_matcher; - }; - - template - class AllOf : public MatcherImpl, ExpressionT> { - public: - - AllOf() {} - AllOf( AllOf const& other ) : m_matchers( other.m_matchers ) {} - - AllOf& add( Matcher const& matcher ) { - m_matchers.push_back( matcher.clone() ); - return *this; - } - virtual bool match( ExpressionT const& expr ) const - { - for( std::size_t i = 0; i < m_matchers.size(); ++i ) - if( !m_matchers[i]->match( expr ) ) - return false; - return true; - } - virtual std::string toString() const { - std::ostringstream oss; - oss << "( "; - for( std::size_t i = 0; i < m_matchers.size(); ++i ) { - if( i != 0 ) - oss << " and "; - oss << m_matchers[i]->toString(); - } - oss << " )"; - return oss.str(); - } - - AllOf operator && ( Matcher const& other ) const { - AllOf allOfExpr( *this ); - allOfExpr.add( other ); - return allOfExpr; - } - - private: - std::vector > > m_matchers; - }; - - template - class AnyOf : public MatcherImpl, ExpressionT> { - public: - - AnyOf() {} - AnyOf( AnyOf const& other ) : m_matchers( other.m_matchers ) {} - - AnyOf& add( Matcher const& matcher ) { - m_matchers.push_back( matcher.clone() ); - return *this; - } - virtual bool match( ExpressionT const& expr ) const - { - for( std::size_t i = 0; i < m_matchers.size(); ++i ) - if( m_matchers[i]->match( expr ) ) - return true; - return false; - } - virtual std::string toString() const { - std::ostringstream oss; - oss << "( "; - for( std::size_t i = 0; i < m_matchers.size(); ++i ) { - if( i != 0 ) - oss << " or "; - oss << m_matchers[i]->toString(); - } - oss << " )"; - return oss.str(); - } - - AnyOf operator || ( Matcher const& other ) const { - AnyOf anyOfExpr( *this ); - anyOfExpr.add( other ); - return anyOfExpr; - } - - private: - std::vector > > m_matchers; - }; - - } // namespace Generic - - template - Generic::AllOf Matcher::operator && ( Matcher const& other ) const { - Generic::AllOf allOfExpr; - allOfExpr.add( *this ); - allOfExpr.add( other ); - return allOfExpr; - } - - template - Generic::AnyOf Matcher::operator || ( Matcher const& other ) const { - Generic::AnyOf anyOfExpr; - anyOfExpr.add( *this ); - anyOfExpr.add( other ); - return anyOfExpr; - } - - template - Generic::Not Matcher::operator ! () const { - return Generic::Not( *this ); - } - - namespace StdString { - - inline std::string makeString( std::string const& str ) { return str; } - inline std::string makeString( const char* str ) { return str ? std::string( str ) : std::string(); } - - struct CasedString - { - CasedString( std::string const& str, CaseSensitive::Choice caseSensitivity ) - : m_caseSensitivity( caseSensitivity ), - m_str( adjustString( str ) ) - {} - std::string adjustString( std::string const& str ) const { - return m_caseSensitivity == CaseSensitive::No - ? toLower( str ) - : str; - - } - std::string toStringSuffix() const - { - return m_caseSensitivity == CaseSensitive::No - ? " (case insensitive)" - : ""; - } - CaseSensitive::Choice m_caseSensitivity; - std::string m_str; - }; - - struct Equals : MatcherImpl { - Equals( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) - : m_data( str, caseSensitivity ) - {} - Equals( Equals const& other ) : m_data( other.m_data ){} - - virtual ~Equals(); - - virtual bool match( std::string const& expr ) const { - return m_data.m_str == m_data.adjustString( expr );; - } - virtual std::string toString() const { - return "equals: \"" + m_data.m_str + "\"" + m_data.toStringSuffix(); - } - - CasedString m_data; - }; - - struct Contains : MatcherImpl { - Contains( std::string const& substr, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) - : m_data( substr, caseSensitivity ){} - Contains( Contains const& other ) : m_data( other.m_data ){} - - virtual ~Contains(); - - virtual bool match( std::string const& expr ) const { - return m_data.adjustString( expr ).find( m_data.m_str ) != std::string::npos; - } - virtual std::string toString() const { - return "contains: \"" + m_data.m_str + "\"" + m_data.toStringSuffix(); - } - - CasedString m_data; - }; - - struct StartsWith : MatcherImpl { - StartsWith( std::string const& substr, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) - : m_data( substr, caseSensitivity ){} - - StartsWith( StartsWith const& other ) : m_data( other.m_data ){} - - virtual ~StartsWith(); - - virtual bool match( std::string const& expr ) const { - return startsWith( m_data.adjustString( expr ), m_data.m_str ); - } - virtual std::string toString() const { - return "starts with: \"" + m_data.m_str + "\"" + m_data.toStringSuffix(); - } - - CasedString m_data; - }; - - struct EndsWith : MatcherImpl { - EndsWith( std::string const& substr, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) - : m_data( substr, caseSensitivity ){} - EndsWith( EndsWith const& other ) : m_data( other.m_data ){} - - virtual ~EndsWith(); - - virtual bool match( std::string const& expr ) const { - return endsWith( m_data.adjustString( expr ), m_data.m_str ); - } - virtual std::string toString() const { - return "ends with: \"" + m_data.m_str + "\"" + m_data.toStringSuffix(); - } - - CasedString m_data; - }; - } // namespace StdString - } // namespace Impl - - // The following functions create the actual matcher objects. - // This allows the types to be inferred - template - inline Impl::Generic::Not Not( Impl::Matcher const& m ) { - return Impl::Generic::Not( m ); - } - - template - inline Impl::Generic::AllOf AllOf( Impl::Matcher const& m1, - Impl::Matcher const& m2 ) { - return Impl::Generic::AllOf().add( m1 ).add( m2 ); - } - template - inline Impl::Generic::AllOf AllOf( Impl::Matcher const& m1, - Impl::Matcher const& m2, - Impl::Matcher const& m3 ) { - return Impl::Generic::AllOf().add( m1 ).add( m2 ).add( m3 ); - } - template - inline Impl::Generic::AnyOf AnyOf( Impl::Matcher const& m1, - Impl::Matcher const& m2 ) { - return Impl::Generic::AnyOf().add( m1 ).add( m2 ); - } - template - inline Impl::Generic::AnyOf AnyOf( Impl::Matcher const& m1, - Impl::Matcher const& m2, - Impl::Matcher const& m3 ) { - return Impl::Generic::AnyOf().add( m1 ).add( m2 ).add( m3 ); - } - - inline Impl::StdString::Equals Equals( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) { - return Impl::StdString::Equals( str, caseSensitivity ); - } - inline Impl::StdString::Equals Equals( const char* str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) { - return Impl::StdString::Equals( Impl::StdString::makeString( str ), caseSensitivity ); - } - inline Impl::StdString::Contains Contains( std::string const& substr, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) { - return Impl::StdString::Contains( substr, caseSensitivity ); - } - inline Impl::StdString::Contains Contains( const char* substr, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) { - return Impl::StdString::Contains( Impl::StdString::makeString( substr ), caseSensitivity ); - } - inline Impl::StdString::StartsWith StartsWith( std::string const& substr ) { - return Impl::StdString::StartsWith( substr ); - } - inline Impl::StdString::StartsWith StartsWith( const char* substr ) { - return Impl::StdString::StartsWith( Impl::StdString::makeString( substr ) ); - } - inline Impl::StdString::EndsWith EndsWith( std::string const& substr ) { - return Impl::StdString::EndsWith( substr ); - } - inline Impl::StdString::EndsWith EndsWith( const char* substr ) { - return Impl::StdString::EndsWith( Impl::StdString::makeString( substr ) ); - } - -} // namespace Matchers - -using namespace Matchers; - -} // namespace Catch - -namespace Catch { - - struct TestFailureException{}; - - template class ExpressionLhs; - - struct STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison; - - struct CopyableStream { - CopyableStream() {} - CopyableStream( CopyableStream const& other ) { - oss << other.oss.str(); - } - CopyableStream& operator=( CopyableStream const& other ) { - oss.str(""); - oss << other.oss.str(); - return *this; - } - std::ostringstream oss; - }; - - class ResultBuilder { - public: - ResultBuilder( char const* macroName, - SourceLineInfo const& lineInfo, - char const* capturedExpression, - ResultDisposition::Flags resultDisposition, - char const* secondArg = "" ); - - template - ExpressionLhs operator <= ( T const& operand ); - ExpressionLhs operator <= ( bool value ); - - template - ResultBuilder& operator << ( T const& value ) { - m_stream.oss << value; - return *this; - } - - template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator && ( RhsT const& ); - template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator || ( RhsT const& ); - - ResultBuilder& setResultType( ResultWas::OfType result ); - ResultBuilder& setResultType( bool result ); - ResultBuilder& setLhs( std::string const& lhs ); - ResultBuilder& setRhs( std::string const& rhs ); - ResultBuilder& setOp( std::string const& op ); - - void endExpression(); - - std::string reconstructExpression() const; - AssertionResult build() const; - - void useActiveException( ResultDisposition::Flags resultDisposition = ResultDisposition::Normal ); - void captureResult( ResultWas::OfType resultType ); - void captureExpression(); - void captureExpectedException( std::string const& expectedMessage ); - void captureExpectedException( Matchers::Impl::Matcher const& matcher ); - void handleResult( AssertionResult const& result ); - void react(); - bool shouldDebugBreak() const; - bool allowThrows() const; - - private: - AssertionInfo m_assertionInfo; - AssertionResultData m_data; - struct ExprComponents { - ExprComponents() : testFalse( false ) {} - bool testFalse; - std::string lhs, rhs, op; - } m_exprComponents; - CopyableStream m_stream; - - bool m_shouldDebugBreak; - bool m_shouldThrow; - }; - -} // namespace Catch - -// Include after due to circular dependency: -// #included from: catch_expression_lhs.hpp -#define TWOBLUECUBES_CATCH_EXPRESSION_LHS_HPP_INCLUDED - -// #included from: catch_evaluate.hpp -#define TWOBLUECUBES_CATCH_EVALUATE_HPP_INCLUDED - -#ifdef _MSC_VER -#pragma warning(push) -#pragma warning(disable:4389) // '==' : signed/unsigned mismatch -#endif - -#include - -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 - inline T& opCast(T const& t) { return const_cast(t); } - -// nullptr_t support based on pull request #154 from Konstantin Baumann -#ifdef CATCH_CONFIG_CPP11_NULLPTR - inline std::nullptr_t opCast(std::nullptr_t) { return nullptr; } -#endif // CATCH_CONFIG_CPP11_NULLPTR - - // So the compare overloads can be operator agnostic we convey the operator as a template - // enum, which is used to specialise an Evaluator for doing the comparison. - template - class Evaluator{}; - - 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__ -// #included from: catch_objc_arc.hpp -#define TWOBLUECUBES_CATCH_OBJC_ARC_HPP_INCLUDED - -#import - -#ifdef __has_feature -#define CATCH_ARC_ENABLED __has_feature(objc_arc) -#else -#define CATCH_ARC_ENABLED 0 -#endif - -void arcSafeRelease( NSObject* obj ); -id performOptionalSelector( id obj, SEL sel ); - -#if !CATCH_ARC_ENABLED -inline void arcSafeRelease( NSObject* obj ) { - [obj release]; -} -inline id performOptionalSelector( id obj, SEL sel ) { - if( [obj respondsToSelector: sel] ) - return [obj performSelector: sel]; - return nil; -} -#define CATCH_UNSAFE_UNRETAINED -#define CATCH_ARC_STRONG -#else -inline void arcSafeRelease( NSObject* ){} -inline id performOptionalSelector( id obj, SEL sel ) { -#ifdef __clang__ -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Warc-performSelector-leaks" -#endif - if( [obj respondsToSelector: sel] ) - return [obj performSelector: sel]; -#ifdef __clang__ -#pragma clang diagnostic pop -#endif - return nil; -} -#define CATCH_UNSAFE_UNRETAINED __unsafe_unretained -#define CATCH_ARC_STRONG __strong -#endif - -#endif - -#ifdef CATCH_CONFIG_CPP11_TUPLE -#include -#endif - -#ifdef CATCH_CONFIG_CPP11_IS_ENUM -#include -#endif - -namespace Catch { - -// Why we're here. -template -std::string toString( T const& value ); - -// Built in overloads - -std::string toString( std::string const& value ); -std::string toString( std::wstring const& value ); -std::string toString( const char* const value ); -std::string toString( char* const value ); -std::string toString( const wchar_t* const value ); -std::string toString( wchar_t* const value ); -std::string toString( int value ); -std::string toString( unsigned long value ); -std::string toString( unsigned int value ); -std::string toString( const double value ); -std::string toString( const float value ); -std::string toString( bool value ); -std::string toString( char value ); -std::string toString( signed char value ); -std::string toString( unsigned char value ); - -#ifdef CATCH_CONFIG_CPP11_LONG_LONG -std::string toString( long long value ); -std::string toString( unsigned long long value ); -#endif - -#ifdef CATCH_CONFIG_CPP11_NULLPTR -std::string toString( std::nullptr_t ); -#endif - -#ifdef __OBJC__ - std::string toString( NSString const * const& nsstring ); - std::string toString( NSString * CATCH_ARC_STRONG const& nsstring ); - std::string toString( NSObject* const& nsObject ); -#endif - -namespace Detail { - - extern const std::string unprintableString; - - struct BorgType { - template BorgType( T const& ); - }; - - struct TrueType { char sizer[1]; }; - struct FalseType { char sizer[2]; }; - - TrueType& testStreamable( std::ostream& ); - FalseType testStreamable( FalseType ); - - FalseType operator<<( std::ostream const&, BorgType const& ); - - template - struct IsStreamInsertable { - static std::ostream &s; - static T const&t; - enum { value = sizeof( testStreamable(s << t) ) == sizeof( TrueType ) }; - }; - -#if defined(CATCH_CONFIG_CPP11_IS_ENUM) - template::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) - ); - } - }; -#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 - inline 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 - -namespace Catch { - -// Wraps the LHS of an expression and captures the operator and RHS (if any) - -// wrapping them all in a ResultBuilder object -template -class ExpressionLhs { - ExpressionLhs& operator = ( ExpressionLhs const& ); -# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS - ExpressionLhs& operator = ( ExpressionLhs && ) = delete; -# endif - -public: - ExpressionLhs( ResultBuilder& rb, T lhs ) : m_rb( rb ), m_lhs( lhs ) {} -# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS - ExpressionLhs( ExpressionLhs const& ) = default; - ExpressionLhs( ExpressionLhs && ) = default; -# endif - - template - ResultBuilder& operator == ( RhsT const& rhs ) { - return captureExpression( rhs ); - } - - template - ResultBuilder& operator != ( RhsT const& rhs ) { - return captureExpression( rhs ); - } - - template - ResultBuilder& operator < ( RhsT const& rhs ) { - return captureExpression( rhs ); - } - - template - ResultBuilder& operator > ( RhsT const& rhs ) { - return captureExpression( rhs ); - } - - template - ResultBuilder& operator <= ( RhsT const& rhs ) { - return captureExpression( rhs ); - } - - template - ResultBuilder& operator >= ( RhsT const& rhs ) { - return captureExpression( rhs ); - } - - ResultBuilder& operator == ( bool rhs ) { - return captureExpression( rhs ); - } - - ResultBuilder& operator != ( bool rhs ) { - return captureExpression( rhs ); - } - - void endExpression() { - bool value = m_lhs ? true : false; - m_rb - .setLhs( Catch::toString( value ) ) - .setResultType( value ) - .endExpression(); - } - - // Only simple binary expressions are allowed on the LHS. - // If more complex compositions are required then place the sub expression in parentheses - template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator + ( RhsT const& ); - template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator - ( RhsT const& ); - template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator / ( RhsT const& ); - template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator * ( RhsT const& ); - template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator && ( RhsT const& ); - template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator || ( RhsT const& ); - -private: - template - ResultBuilder& captureExpression( RhsT const& rhs ) { - return m_rb - .setResultType( Internal::compare( m_lhs, rhs ) ) - .setLhs( Catch::toString( m_lhs ) ) - .setRhs( Catch::toString( rhs ) ) - .setOp( Internal::OperatorTraits::getName() ); - } - -private: - ResultBuilder& m_rb; - T m_lhs; -}; - -} // end namespace Catch - - -namespace Catch { - - template - inline ExpressionLhs ResultBuilder::operator <= ( T const& operand ) { - return ExpressionLhs( *this, operand ); - } - - inline ExpressionLhs ResultBuilder::operator <= ( bool value ) { - return ExpressionLhs( *this, value ); - } - -} // namespace Catch - -// #included from: catch_message.h -#define TWOBLUECUBES_CATCH_MESSAGE_H_INCLUDED - -#include - -namespace Catch { - - struct MessageInfo { - MessageInfo( std::string const& _macroName, - SourceLineInfo const& _lineInfo, - ResultWas::OfType _type ); - - std::string macroName; - SourceLineInfo lineInfo; - ResultWas::OfType type; - std::string message; - unsigned int sequence; - - bool operator == ( MessageInfo const& other ) const { - return sequence == other.sequence; - } - bool operator < ( MessageInfo const& other ) const { - return sequence < other.sequence; - } - private: - static unsigned int globalCount; - }; - - struct MessageBuilder { - MessageBuilder( std::string const& macroName, - SourceLineInfo const& lineInfo, - ResultWas::OfType type ) - : m_info( macroName, lineInfo, type ) - {} - - template - MessageBuilder& operator << ( T const& value ) { - m_stream << value; - return *this; - } - - MessageInfo m_info; - std::ostringstream m_stream; - }; - - class ScopedMessage { - public: - ScopedMessage( MessageBuilder const& builder ); - ScopedMessage( ScopedMessage const& other ); - ~ScopedMessage(); - - MessageInfo m_info; - }; - -} // end namespace Catch - -// #included from: catch_interfaces_capture.h -#define TWOBLUECUBES_CATCH_INTERFACES_CAPTURE_H_INCLUDED - -#include - -namespace Catch { - - class TestCase; - class AssertionResult; - struct AssertionInfo; - struct SectionInfo; - struct SectionEndInfo; - struct MessageInfo; - class ScopedMessageBuilder; - struct Counts; - - struct IResultCapture { - - virtual ~IResultCapture(); - - virtual void assertionEnded( AssertionResult const& result ) = 0; - virtual bool sectionStarted( SectionInfo const& sectionInfo, - Counts& assertions ) = 0; - virtual void sectionEnded( SectionEndInfo const& endInfo ) = 0; - virtual void sectionEndedEarly( SectionEndInfo const& endInfo ) = 0; - virtual void pushScopedMessage( MessageInfo const& message ) = 0; - virtual void popScopedMessage( MessageInfo const& message ) = 0; - - virtual std::string getCurrentTestName() const = 0; - virtual const AssertionResult* getLastResult() const = 0; - - virtual void handleFatalErrorCondition( std::string const& message ) = 0; - }; - - IResultCapture& getResultCapture(); -} - -// #included from: catch_debugger.h -#define TWOBLUECUBES_CATCH_DEBUGGER_H_INCLUDED - -// #included from: catch_platform.h -#define TWOBLUECUBES_CATCH_PLATFORM_H_INCLUDED - -#if defined(__MAC_OS_X_VERSION_MIN_REQUIRED) -#define CATCH_PLATFORM_MAC -#elif defined(__IPHONE_OS_VERSION_MIN_REQUIRED) -#define CATCH_PLATFORM_IPHONE -#elif defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) -#define CATCH_PLATFORM_WINDOWS -#endif - -#include - -namespace Catch{ - - bool isDebuggerActive(); - void writeToDebugConsole( std::string const& text ); -} - -#ifdef CATCH_PLATFORM_MAC - - // The following code snippet based on: - // http://cocoawithlove.com/2008/03/break-into-debugger.html - #ifdef DEBUG - #if defined(__ppc64__) || defined(__ppc__) - #define CATCH_BREAK_INTO_DEBUGGER() \ - if( Catch::isDebuggerActive() ) { \ - __asm__("li r0, 20\nsc\nnop\nli r0, 37\nli r4, 2\nsc\nnop\n" \ - : : : "memory","r0","r3","r4" ); \ - } - #else - #define CATCH_BREAK_INTO_DEBUGGER() if( Catch::isDebuggerActive() ) {__asm__("int $3\n" : : );} - #endif - #endif - -#elif defined(_MSC_VER) - #define CATCH_BREAK_INTO_DEBUGGER() if( Catch::isDebuggerActive() ) { __debugbreak(); } -#elif defined(__MINGW32__) - extern "C" __declspec(dllimport) void __stdcall DebugBreak(); - #define CATCH_BREAK_INTO_DEBUGGER() if( Catch::isDebuggerActive() ) { DebugBreak(); } -#endif - -#ifndef CATCH_BREAK_INTO_DEBUGGER -#define CATCH_BREAK_INTO_DEBUGGER() Catch::alwaysTrue(); -#endif - -// #included from: catch_interfaces_runner.h -#define TWOBLUECUBES_CATCH_INTERFACES_RUNNER_H_INCLUDED - -namespace Catch { - class TestCase; - - struct IRunner { - virtual ~IRunner(); - virtual bool aborting() const = 0; - }; -} - -/////////////////////////////////////////////////////////////////////////////// -// In the event of a failure works out if the debugger needs to be invoked -// and/or an exception thrown and takes appropriate action. -// This needs to be done as a macro so the debugger will stop in the user -// source code rather than in Catch library code -#define INTERNAL_CATCH_REACT( resultBuilder ) \ - if( resultBuilder.shouldDebugBreak() ) CATCH_BREAK_INTO_DEBUGGER(); \ - resultBuilder.react(); - -/////////////////////////////////////////////////////////////////////////////// -#define INTERNAL_CATCH_TEST( expr, resultDisposition, macroName ) \ - do { \ - Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \ - try { \ - CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \ - ( __catchResult <= expr ).endExpression(); \ - } \ - catch( ... ) { \ - __catchResult.useActiveException( Catch::ResultDisposition::Normal ); \ - } \ - INTERNAL_CATCH_REACT( __catchResult ) \ - } while( Catch::isTrue( false && !!(expr) ) ) // expr here is never evaluated at runtime but it forces the compiler to give it a look - -/////////////////////////////////////////////////////////////////////////////// -#define INTERNAL_CATCH_IF( expr, resultDisposition, macroName ) \ - INTERNAL_CATCH_TEST( expr, resultDisposition, macroName ); \ - if( Catch::getResultCapture().getLastResult()->succeeded() ) - -/////////////////////////////////////////////////////////////////////////////// -#define INTERNAL_CATCH_ELSE( expr, resultDisposition, macroName ) \ - INTERNAL_CATCH_TEST( expr, resultDisposition, macroName ); \ - if( !Catch::getResultCapture().getLastResult()->succeeded() ) - -/////////////////////////////////////////////////////////////////////////////// -#define INTERNAL_CATCH_NO_THROW( expr, resultDisposition, macroName ) \ - do { \ - Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \ - try { \ - expr; \ - __catchResult.captureResult( Catch::ResultWas::Ok ); \ - } \ - catch( ... ) { \ - __catchResult.useActiveException( resultDisposition ); \ - } \ - INTERNAL_CATCH_REACT( __catchResult ) \ - } while( Catch::alwaysFalse() ) - -/////////////////////////////////////////////////////////////////////////////// -#define INTERNAL_CATCH_THROWS( expr, resultDisposition, matcher, macroName ) \ - do { \ - Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition, #matcher ); \ - if( __catchResult.allowThrows() ) \ - try { \ - expr; \ - __catchResult.captureResult( Catch::ResultWas::DidntThrowException ); \ - } \ - catch( ... ) { \ - __catchResult.captureExpectedException( matcher ); \ - } \ - else \ - __catchResult.captureResult( Catch::ResultWas::Ok ); \ - INTERNAL_CATCH_REACT( __catchResult ) \ - } while( Catch::alwaysFalse() ) - -/////////////////////////////////////////////////////////////////////////////// -#define INTERNAL_CATCH_THROWS_AS( expr, exceptionType, resultDisposition, macroName ) \ - do { \ - Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \ - if( __catchResult.allowThrows() ) \ - try { \ - expr; \ - __catchResult.captureResult( Catch::ResultWas::DidntThrowException ); \ - } \ - catch( exceptionType ) { \ - __catchResult.captureResult( Catch::ResultWas::Ok ); \ - } \ - catch( ... ) { \ - __catchResult.useActiveException( resultDisposition ); \ - } \ - else \ - __catchResult.captureResult( Catch::ResultWas::Ok ); \ - INTERNAL_CATCH_REACT( __catchResult ) \ - } while( Catch::alwaysFalse() ) - -/////////////////////////////////////////////////////////////////////////////// -#ifdef CATCH_CONFIG_VARIADIC_MACROS - #define INTERNAL_CATCH_MSG( messageType, resultDisposition, macroName, ... ) \ - do { \ - Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, "", resultDisposition ); \ - __catchResult << __VA_ARGS__ + ::Catch::StreamEndStop(); \ - __catchResult.captureResult( messageType ); \ - INTERNAL_CATCH_REACT( __catchResult ) \ - } while( Catch::alwaysFalse() ) -#else - #define INTERNAL_CATCH_MSG( messageType, resultDisposition, macroName, log ) \ - do { \ - Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, "", resultDisposition ); \ - __catchResult << log + ::Catch::StreamEndStop(); \ - __catchResult.captureResult( messageType ); \ - INTERNAL_CATCH_REACT( __catchResult ) \ - } while( Catch::alwaysFalse() ) -#endif - -/////////////////////////////////////////////////////////////////////////////// -#define INTERNAL_CATCH_INFO( log, macroName ) \ - Catch::ScopedMessage INTERNAL_CATCH_UNIQUE_NAME( scopedMessage ) = Catch::MessageBuilder( macroName, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info ) << log; - -/////////////////////////////////////////////////////////////////////////////// -#define INTERNAL_CHECK_THAT( arg, matcher, resultDisposition, macroName ) \ - do { \ - Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #arg ", " #matcher, resultDisposition ); \ - try { \ - std::string matcherAsString = (matcher).toString(); \ - __catchResult \ - .setLhs( Catch::toString( arg ) ) \ - .setRhs( matcherAsString == Catch::Detail::unprintableString ? #matcher : matcherAsString ) \ - .setOp( "matches" ) \ - .setResultType( (matcher).match( arg ) ); \ - __catchResult.captureExpression(); \ - } catch( ... ) { \ - __catchResult.useActiveException( resultDisposition | Catch::ResultDisposition::ContinueOnFailure ); \ - } \ - INTERNAL_CATCH_REACT( __catchResult ) \ - } while( Catch::alwaysFalse() ) - -// #included from: internal/catch_section.h -#define TWOBLUECUBES_CATCH_SECTION_H_INCLUDED - -// #included from: catch_section_info.h -#define TWOBLUECUBES_CATCH_SECTION_INFO_H_INCLUDED - -// #included from: catch_totals.hpp -#define TWOBLUECUBES_CATCH_TOTALS_HPP_INCLUDED - -#include - -namespace Catch { - - struct Counts { - Counts() : passed( 0 ), failed( 0 ), failedButOk( 0 ) {} - - Counts operator - ( Counts const& other ) const { - Counts diff; - diff.passed = passed - other.passed; - diff.failed = failed - other.failed; - diff.failedButOk = failedButOk - other.failedButOk; - return diff; - } - Counts& operator += ( Counts const& other ) { - passed += other.passed; - failed += other.failed; - failedButOk += other.failedButOk; - return *this; - } - - std::size_t total() const { - return passed + failed + failedButOk; - } - bool allPassed() const { - return failed == 0 && failedButOk == 0; - } - bool allOk() const { - return failed == 0; - } - - std::size_t passed; - std::size_t failed; - std::size_t failedButOk; - }; - - struct Totals { - - Totals operator - ( Totals const& other ) const { - Totals diff; - diff.assertions = assertions - other.assertions; - diff.testCases = testCases - other.testCases; - return diff; - } - - Totals delta( Totals const& prevTotals ) const { - Totals diff = *this - prevTotals; - if( diff.assertions.failed > 0 ) - ++diff.testCases.failed; - else if( diff.assertions.failedButOk > 0 ) - ++diff.testCases.failedButOk; - else - ++diff.testCases.passed; - return diff; - } - - Totals& operator += ( Totals const& other ) { - assertions += other.assertions; - testCases += other.testCases; - return *this; - } - - Counts assertions; - Counts testCases; - }; -} - -namespace Catch { - - struct SectionInfo { - SectionInfo - ( SourceLineInfo const& _lineInfo, - std::string const& _name, - std::string const& _description = std::string() ); - - std::string name; - std::string description; - SourceLineInfo lineInfo; - }; - - struct SectionEndInfo { - SectionEndInfo( SectionInfo const& _sectionInfo, Counts const& _prevAssertions, double _durationInSeconds ) - : sectionInfo( _sectionInfo ), prevAssertions( _prevAssertions ), durationInSeconds( _durationInSeconds ) - {} - - SectionInfo sectionInfo; - Counts prevAssertions; - double durationInSeconds; - }; - -} // end namespace Catch - -// #included from: catch_timer.h -#define TWOBLUECUBES_CATCH_TIMER_H_INCLUDED - -#ifdef CATCH_PLATFORM_WINDOWS -typedef unsigned long long uint64_t; -#else -#include -#endif - -namespace Catch { - - class Timer { - public: - Timer() : m_ticks( 0 ) {} - void start(); - unsigned int getElapsedMicroseconds() const; - unsigned int getElapsedMilliseconds() const; - double getElapsedSeconds() const; - - private: - uint64_t m_ticks; - }; - -} // namespace Catch - -#include - -namespace Catch { - - class Section : NonCopyable { - public: - Section( SectionInfo const& info ); - ~Section(); - - // This indicates whether the section should be executed or not - operator bool() const; - - private: - SectionInfo m_info; - - std::string m_name; - Counts m_assertions; - bool m_sectionIncluded; - Timer m_timer; - }; - -} // end namespace Catch - -#ifdef CATCH_CONFIG_VARIADIC_MACROS - #define INTERNAL_CATCH_SECTION( ... ) \ - if( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::SectionInfo( CATCH_INTERNAL_LINEINFO, __VA_ARGS__ ) ) -#else - #define INTERNAL_CATCH_SECTION( name, desc ) \ - if( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::SectionInfo( CATCH_INTERNAL_LINEINFO, name, desc ) ) -#endif - -// #included from: internal/catch_generators.hpp -#define TWOBLUECUBES_CATCH_GENERATORS_HPP_INCLUDED - -#include -#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; -}; - -template -class BetweenGenerator : public IGenerator { -public: - BetweenGenerator( T from, T to ) : m_from( from ), m_to( to ){} - - virtual T getValue( std::size_t index ) const { - return m_from+static_cast( index ); - } - - virtual 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 ) - { - 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 - } - - void add( const IGenerator* generator ) { - m_totalSize += generator->size(); - m_composed.push_back( generator ); - } - - CompositeGenerator& then( CompositeGenerator& other ) { - move( other ); - return *this; - } - - CompositeGenerator& then( T value ) { - ValuesGenerator* valuesGen = new ValuesGenerator(); - valuesGen->add( value ); - add( valuesGen ); - return *this; - } - -private: - - void move( CompositeGenerator& other ) { - std::copy( other.m_composed.begin(), other.m_composed.end(), std::back_inserter( m_composed ) ); - m_totalSize += other.m_totalSize; - other.m_composed.clear(); - } - - std::vector*> 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 INTERNAL_CATCH_LINESTR2( line ) #line -#define INTERNAL_CATCH_LINESTR( line ) INTERNAL_CATCH_LINESTR2( line ) - -#define INTERNAL_CATCH_GENERATE( expr ) expr.setFileInfo( __FILE__ "(" INTERNAL_CATCH_LINESTR( __LINE__ ) ")" ) - -// #included from: internal/catch_interfaces_exception.h -#define TWOBLUECUBES_CATCH_INTERFACES_EXCEPTION_H_INCLUDED - -#include -#include - -// #included from: catch_interfaces_registry_hub.h -#define TWOBLUECUBES_CATCH_INTERFACES_REGISTRY_HUB_H_INCLUDED - -#include - -namespace Catch { - - class TestCase; - struct ITestCaseRegistry; - struct IExceptionTranslatorRegistry; - struct IExceptionTranslator; - struct IReporterRegistry; - struct IReporterFactory; - - struct IRegistryHub { - virtual ~IRegistryHub(); - - virtual IReporterRegistry const& getReporterRegistry() const = 0; - virtual ITestCaseRegistry const& getTestCaseRegistry() const = 0; - virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() = 0; - }; - - struct IMutableRegistryHub { - virtual ~IMutableRegistryHub(); - virtual void registerReporter( std::string const& name, Ptr const& factory ) = 0; - virtual void registerListener( Ptr const& factory ) = 0; - virtual void registerTest( TestCase const& testInfo ) = 0; - virtual void registerTranslator( const IExceptionTranslator* translator ) = 0; - }; - - IRegistryHub& getRegistryHub(); - IMutableRegistryHub& getMutableRegistryHub(); - void cleanUp(); - std::string translateActiveException(); - -} - -namespace Catch { - - typedef std::string(*exceptionTranslateFunction)(); - - struct IExceptionTranslator; - typedef std::vector ExceptionTranslators; - - struct IExceptionTranslator { - virtual ~IExceptionTranslator(); - virtual std::string translate( ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd ) const = 0; - }; - - struct IExceptionTranslatorRegistry { - virtual ~IExceptionTranslatorRegistry(); - - virtual std::string translateActiveException() const = 0; - }; - - class ExceptionTranslatorRegistrar { - template - class ExceptionTranslator : public IExceptionTranslator { - public: - - ExceptionTranslator( std::string(*translateFunction)( T& ) ) - : m_translateFunction( translateFunction ) - {} - - virtual std::string translate( ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd ) const CATCH_OVERRIDE { - try { - if( it == itEnd ) - throw; - else - return (*it)->translate( it+1, itEnd ); - } - catch( T& ex ) { - return m_translateFunction( ex ); - } - } - - protected: - std::string(*m_translateFunction)( T& ); - }; - - public: - template - ExceptionTranslatorRegistrar( std::string(*translateFunction)( T& ) ) { - getMutableRegistryHub().registerTranslator - ( new ExceptionTranslator( translateFunction ) ); - } - }; -} - -/////////////////////////////////////////////////////////////////////////////// -#define INTERNAL_CATCH_TRANSLATE_EXCEPTION2( translatorName, signature ) \ - static std::string translatorName( signature ); \ - namespace{ Catch::ExceptionTranslatorRegistrar INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionRegistrar )( &translatorName ); }\ - static std::string translatorName( signature ) - -#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 - -#include -#include - -namespace Catch { -namespace Detail { - - class Approx { - public: - explicit Approx ( double value ) - : m_epsilon( std::numeric_limits::epsilon()*100 ), - m_scale( 1.0 ), - m_value( value ) - {} - - Approx( Approx const& other ) - : m_epsilon( other.m_epsilon ), - m_scale( other.m_scale ), - m_value( other.m_value ) - {} - - static Approx custom() { - return Approx( 0 ); - } - - Approx operator()( double value ) { - Approx approx( value ); - approx.epsilon( m_epsilon ); - approx.scale( m_scale ); - return approx; - } - - friend bool operator == ( double lhs, Approx const& rhs ) { - // Thanks to Richard Harris for his help refining this formula - return fabs( lhs - rhs.m_value ) < rhs.m_epsilon * (rhs.m_scale + (std::max)( fabs(lhs), fabs(rhs.m_value) ) ); - } - - friend bool operator == ( Approx const& lhs, double rhs ) { - return operator==( rhs, lhs ); - } - - friend bool operator != ( double lhs, Approx const& rhs ) { - return !operator==( lhs, rhs ); - } - - friend bool operator != ( Approx const& lhs, double rhs ) { - return !operator==( rhs, lhs ); - } - - 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& scale( double newScale ) { - m_scale = newScale; - return *this; - } - - std::string toString() const { - std::ostringstream oss; - oss << "Approx( " << Catch::toString( m_value ) << " )"; - return oss.str(); - } - - private: - double m_epsilon; - double m_scale; - double m_value; - }; -} - -template<> -inline std::string toString( Detail::Approx const& value ) { - return value.toString(); -} - -} // end namespace Catch - -// #included from: internal/catch_interfaces_tag_alias_registry.h -#define TWOBLUECUBES_CATCH_INTERFACES_TAG_ALIAS_REGISTRY_H_INCLUDED - -// #included from: catch_tag_alias.h -#define TWOBLUECUBES_CATCH_TAG_ALIAS_H_INCLUDED - -#include - -namespace Catch { - - struct TagAlias { - TagAlias( std::string _tag, SourceLineInfo _lineInfo ) : tag( _tag ), lineInfo( _lineInfo ) {} - - std::string tag; - SourceLineInfo lineInfo; - }; - - struct RegistrarForTagAliases { - RegistrarForTagAliases( char const* alias, char const* tag, SourceLineInfo const& lineInfo ); - }; - -} // end namespace Catch - -#define CATCH_REGISTER_TAG_ALIAS( alias, spec ) namespace{ Catch::RegistrarForTagAliases INTERNAL_CATCH_UNIQUE_NAME( AutoRegisterTagAlias )( alias, spec, CATCH_INTERNAL_LINEINFO ); } -// #included from: catch_option.hpp -#define TWOBLUECUBES_CATCH_OPTION_HPP_INCLUDED - -namespace Catch { - - // An optional type - template - class Option { - public: - Option() : nullableValue( CATCH_NULL ) {} - Option( T const& _value ) - : nullableValue( new( storage ) T( _value ) ) - {} - Option( Option const& _other ) - : nullableValue( _other ? new( storage ) T( *_other ) : CATCH_NULL ) - {} - - ~Option() { - reset(); - } - - Option& operator= ( Option const& _other ) { - if( &_other != this ) { - reset(); - if( _other ) - nullableValue = new( storage ) T( *_other ); - } - return *this; - } - Option& operator = ( T const& _value ) { - reset(); - nullableValue = new( storage ) T( _value ); - return *this; - } - - void reset() { - if( nullableValue ) - nullableValue->~T(); - nullableValue = CATCH_NULL; - } - - T& operator*() { return *nullableValue; } - T const& operator*() const { return *nullableValue; } - T* operator->() { return nullableValue; } - const T* operator->() const { return nullableValue; } - - T valueOr( T const& defaultValue ) const { - return nullableValue ? *nullableValue : defaultValue; - } - - bool some() const { return nullableValue != CATCH_NULL; } - bool none() const { return nullableValue == CATCH_NULL; } - - bool operator !() const { return nullableValue == CATCH_NULL; } - operator SafeBool::type() const { - return SafeBool::makeSafe( some() ); - } - - private: - T* nullableValue; - char storage[sizeof(T)]; - }; - -} // end namespace Catch - -namespace Catch { - - struct ITagAliasRegistry { - virtual ~ITagAliasRegistry(); - virtual Option find( std::string const& alias ) const = 0; - virtual std::string expandAliases( std::string const& unexpandedTestSpec ) const = 0; - - static ITagAliasRegistry const& get(); - }; - -} // end namespace Catch - -// These files are included here so the single_include script doesn't put them -// in the conditionally compiled sections -// #included from: internal/catch_test_case_info.h -#define TWOBLUECUBES_CATCH_TEST_CASE_INFO_H_INCLUDED - -#include -#include - -#ifdef __clang__ -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wpadded" -#endif - -namespace Catch { - - struct ITestCase; - - struct TestCaseInfo { - enum SpecialProperties{ - None = 0, - IsHidden = 1 << 1, - ShouldFail = 1 << 2, - MayFail = 1 << 3, - Throws = 1 << 4 - }; - - TestCaseInfo( std::string const& _name, - std::string const& _className, - std::string const& _description, - std::set const& _tags, - SourceLineInfo const& _lineInfo ); - - 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 name; - std::string className; - std::string description; - std::set tags; - std::set lcaseTags; - std::string tagsAsString; - SourceLineInfo lineInfo; - SpecialProperties properties; - }; - - class TestCase : public TestCaseInfo { - public: - - TestCase( ITestCase* testCase, TestCaseInfo const& info ); - TestCase( TestCase const& other ); - - TestCase withName( std::string const& _newName ) const; - - void invoke() const; - - TestCaseInfo const& getTestCaseInfo() const; - - void swap( TestCase& other ); - bool operator == ( TestCase const& other ) const; - bool operator < ( TestCase const& other ) const; - TestCase& operator = ( TestCase const& other ); - - private: - Ptr test; - }; - - TestCase makeTestCase( ITestCase* testCase, - std::string const& className, - std::string const& name, - std::string const& description, - SourceLineInfo const& lineInfo ); -} - -#ifdef __clang__ -#pragma clang diagnostic pop -#endif - - -#ifdef __OBJC__ -// #included from: internal/catch_objc.hpp -#define TWOBLUECUBES_CATCH_OBJC_HPP_INCLUDED - -#import - -#include - -// NB. Any general catch headers included here must be included -// in catch.hpp first to make sure they are included by the single -// header for non obj-usage - -/////////////////////////////////////////////////////////////////////////////// -// This protocol is really only here for (self) documenting purposes, since -// all its methods are optional. -@protocol OcFixture - -@optional - --(void) setUp; --(void) tearDown; - -@end - -namespace Catch { - - class OcMethod : public SharedImpl { - - public: - OcMethod( Class cls, SEL sel ) : m_cls( cls ), m_sel( sel ) {} - - virtual void invoke() const { - id obj = [[m_cls alloc] init]; - - performOptionalSelector( obj, @selector(setUp) ); - performOptionalSelector( obj, m_sel ); - performOptionalSelector( obj, @selector(tearDown) ); - - arcSafeRelease( obj ); - } - private: - virtual ~OcMethod() {} - - Class m_cls; - SEL m_sel; - }; - - namespace Detail{ - - inline std::string getAnnotation( Class cls, - std::string const& annotationName, - std::string const& testCaseName ) { - NSString* selStr = [[NSString alloc] initWithFormat:@"Catch_%s_%s", annotationName.c_str(), testCaseName.c_str()]; - SEL sel = NSSelectorFromString( selStr ); - arcSafeRelease( selStr ); - id value = performOptionalSelector( cls, sel ); - if( value ) - return [(NSString*)value UTF8String]; - return ""; - } - } - - inline size_t registerTestMethods() { - size_t noTestMethods = 0; - int noClasses = objc_getClassList( CATCH_NULL, 0 ); - - Class* classes = (CATCH_UNSAFE_UNRETAINED Class *)malloc( sizeof(Class) * noClasses); - objc_getClassList( classes, noClasses ); - - for( int c = 0; c < noClasses; c++ ) { - Class cls = classes[c]; - { - u_int count; - Method* methods = class_copyMethodList( cls, &count ); - for( u_int m = 0; m < count ; m++ ) { - SEL selector = method_getName(methods[m]); - std::string methodName = sel_getName(selector); - if( startsWith( methodName, "Catch_TestCase_" ) ) { - std::string testCaseName = methodName.substr( 15 ); - std::string name = Detail::getAnnotation( cls, "Name", testCaseName ); - std::string desc = Detail::getAnnotation( cls, "Description", testCaseName ); - const char* className = class_getName( cls ); - - getMutableRegistryHub().registerTest( makeTestCase( new OcMethod( cls, selector ), className, name.c_str(), desc.c_str(), SourceLineInfo() ) ); - noTestMethods++; - } - } - free(methods); - } - } - return noTestMethods; - } - - namespace Matchers { - namespace Impl { - namespace NSStringMatchers { - - template - struct StringHolder : MatcherImpl{ - StringHolder( NSString* substr ) : m_substr( [substr copy] ){} - StringHolder( StringHolder const& other ) : m_substr( [other.m_substr copy] ){} - StringHolder() { - arcSafeRelease( m_substr ); - } - - NSString* m_substr; - }; - - struct Equals : StringHolder { - Equals( NSString* substr ) : StringHolder( substr ){} - - virtual bool match( ExpressionType const& str ) const { - return (str != nil || m_substr == nil ) && - [str isEqualToString:m_substr]; - } - - virtual std::string toString() const { - return "equals string: " + Catch::toString( m_substr ); - } - }; - - struct Contains : StringHolder { - Contains( NSString* substr ) : StringHolder( substr ){} - - virtual bool match( ExpressionType const& str ) const { - return (str != nil || m_substr == nil ) && - [str rangeOfString:m_substr].location != NSNotFound; - } - - virtual std::string toString() const { - return "contains string: " + Catch::toString( m_substr ); - } - }; - - struct StartsWith : StringHolder { - StartsWith( NSString* substr ) : StringHolder( substr ){} - - virtual bool match( ExpressionType const& str ) const { - return (str != nil || m_substr == nil ) && - [str rangeOfString:m_substr].location == 0; - } - - virtual std::string toString() const { - return "starts with: " + Catch::toString( m_substr ); - } - }; - struct EndsWith : StringHolder { - EndsWith( NSString* substr ) : StringHolder( substr ){} - - virtual bool match( ExpressionType const& str ) const { - return (str != nil || m_substr == nil ) && - [str rangeOfString:m_substr].location == [str length] - [m_substr length]; - } - - virtual std::string toString() const { - return "ends with: " + Catch::toString( m_substr ); - } - }; - - } // namespace NSStringMatchers - } // namespace Impl - - inline Impl::NSStringMatchers::Equals - Equals( NSString* substr ){ return Impl::NSStringMatchers::Equals( substr ); } - - inline Impl::NSStringMatchers::Contains - Contains( NSString* substr ){ return Impl::NSStringMatchers::Contains( substr ); } - - inline Impl::NSStringMatchers::StartsWith - StartsWith( NSString* substr ){ return Impl::NSStringMatchers::StartsWith( substr ); } - - inline Impl::NSStringMatchers::EndsWith - EndsWith( NSString* substr ){ return Impl::NSStringMatchers::EndsWith( substr ); } - - } // namespace Matchers - - using namespace Matchers; - -} // namespace Catch - -/////////////////////////////////////////////////////////////////////////////// -#define OC_TEST_CASE( name, desc )\ -+(NSString*) INTERNAL_CATCH_UNIQUE_NAME( Catch_Name_test ) \ -{\ -return @ name; \ -}\ -+(NSString*) INTERNAL_CATCH_UNIQUE_NAME( Catch_Description_test ) \ -{ \ -return @ desc; \ -} \ --(void) INTERNAL_CATCH_UNIQUE_NAME( Catch_TestCase_test ) - -#endif - -#ifdef CATCH_IMPL -// #included from: internal/catch_impl.hpp -#define TWOBLUECUBES_CATCH_IMPL_HPP_INCLUDED - -// Collect all the implementation files together here -// These are the equivalent of what would usually be cpp files - -#ifdef __clang__ -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wweak-vtables" -#endif - -// #included from: ../catch_session.hpp -#define TWOBLUECUBES_CATCH_RUNNER_HPP_INCLUDED - -// #included from: internal/catch_commandline.hpp -#define TWOBLUECUBES_CATCH_COMMANDLINE_HPP_INCLUDED - -// #included from: catch_config.hpp -#define TWOBLUECUBES_CATCH_CONFIG_HPP_INCLUDED - -// #included from: catch_test_spec_parser.hpp -#define TWOBLUECUBES_CATCH_TEST_SPEC_PARSER_HPP_INCLUDED - -#ifdef __clang__ -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wpadded" -#endif - -// #included from: catch_test_spec.hpp -#define TWOBLUECUBES_CATCH_TEST_SPEC_HPP_INCLUDED - -#ifdef __clang__ -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wpadded" -#endif - -// #included from: catch_wildcard_pattern.hpp -#define TWOBLUECUBES_CATCH_WILDCARD_PATTERN_HPP_INCLUDED - -namespace Catch -{ - class WildcardPattern { - enum WildcardPosition { - NoWildcard = 0, - WildcardAtStart = 1, - WildcardAtEnd = 2, - WildcardAtBothEnds = WildcardAtStart | WildcardAtEnd - }; - - public: - - WildcardPattern( std::string const& pattern, CaseSensitive::Choice caseSensitivity ) - : m_caseSensitivity( caseSensitivity ), - m_wildcard( NoWildcard ), - m_pattern( adjustCase( pattern ) ) - { - if( startsWith( m_pattern, "*" ) ) { - m_pattern = m_pattern.substr( 1 ); - m_wildcard = WildcardAtStart; - } - if( endsWith( m_pattern, "*" ) ) { - m_pattern = m_pattern.substr( 0, m_pattern.size()-1 ); - m_wildcard = static_cast( m_wildcard | WildcardAtEnd ); - } - } - virtual ~WildcardPattern(); - virtual bool matches( std::string const& str ) const { - switch( m_wildcard ) { - case NoWildcard: - return m_pattern == adjustCase( str ); - case WildcardAtStart: - return endsWith( adjustCase( str ), m_pattern ); - case WildcardAtEnd: - return startsWith( adjustCase( str ), m_pattern ); - case WildcardAtBothEnds: - return contains( adjustCase( str ), m_pattern ); - } - -#ifdef __clang__ -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wunreachable-code" -#endif - throw std::logic_error( "Unknown enum" ); -#ifdef __clang__ -#pragma clang diagnostic pop -#endif - } - private: - std::string adjustCase( std::string const& str ) const { - return m_caseSensitivity == CaseSensitive::No ? toLower( str ) : str; - } - CaseSensitive::Choice m_caseSensitivity; - WildcardPosition m_wildcard; - std::string m_pattern; - }; -} - -#include -#include - -namespace Catch { - - class TestSpec { - struct Pattern : SharedImpl<> { - virtual ~Pattern(); - virtual bool matches( TestCaseInfo const& testCase ) const = 0; - }; - class NamePattern : public Pattern { - public: - NamePattern( std::string const& name ) - : m_wildcardPattern( toLower( name ), CaseSensitive::No ) - {} - virtual ~NamePattern(); - virtual bool matches( TestCaseInfo const& testCase ) const { - return m_wildcardPattern.matches( toLower( testCase.name ) ); - } - private: - WildcardPattern m_wildcardPattern; - }; - - class TagPattern : public Pattern { - public: - TagPattern( std::string const& tag ) : m_tag( toLower( tag ) ) {} - virtual ~TagPattern(); - virtual bool matches( TestCaseInfo const& testCase ) const { - return testCase.lcaseTags.find( m_tag ) != testCase.lcaseTags.end(); - } - private: - std::string m_tag; - }; - - class ExcludedPattern : public Pattern { - public: - ExcludedPattern( Ptr const& underlyingPattern ) : m_underlyingPattern( underlyingPattern ) {} - virtual ~ExcludedPattern(); - virtual bool matches( TestCaseInfo const& testCase ) const { return !m_underlyingPattern->matches( testCase ); } - private: - Ptr m_underlyingPattern; - }; - - struct Filter { - std::vector > m_patterns; - - bool matches( TestCaseInfo const& testCase ) const { - // All patterns in a filter must match for the filter to be a match - for( std::vector >::const_iterator it = m_patterns.begin(), itEnd = m_patterns.end(); it != itEnd; ++it ) { - if( !(*it)->matches( testCase ) ) - return false; - } - return true; - } - }; - - public: - bool hasFilters() const { - return !m_filters.empty(); - } - bool matches( TestCaseInfo const& testCase ) const { - // A TestSpec matches if any filter matches - for( std::vector::const_iterator it = m_filters.begin(), itEnd = m_filters.end(); it != itEnd; ++it ) - if( it->matches( testCase ) ) - return true; - return false; - } - - private: - std::vector m_filters; - - friend class TestSpecParser; - }; -} - -#ifdef __clang__ -#pragma clang diagnostic pop -#endif - -namespace Catch { - - class TestSpecParser { - enum Mode{ None, Name, QuotedName, Tag, EscapedName }; - 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; - - public: - TestSpecParser( ITagAliasRegistry const& tagAliases ) : m_tagAliases( &tagAliases ) {} - - TestSpecParser& parse( std::string const& arg ) { - m_mode = None; - m_exclusion = false; - m_start = std::string::npos; - m_arg = m_tagAliases->expandAliases( arg ); - 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() { - 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( size_t i = 0; i < m_escapeChars.size(); ++i ) - token = token.substr( 0, m_escapeChars[i] ) + token.substr( m_escapeChars[i]+1 ); - m_escapeChars.clear(); - if( startsWith( token, "exclude:" ) ) { - m_exclusion = true; - token = token.substr( 8 ); - } - if( !token.empty() ) { - Ptr pattern = new T( token ); - if( m_exclusion ) - pattern = new TestSpec::ExcludedPattern( pattern ); - m_currentFilter.m_patterns.push_back( pattern ); - } - m_exclusion = false; - m_mode = None; - } - void addFilter() { - if( !m_currentFilter.m_patterns.empty() ) { - m_testSpec.m_filters.push_back( m_currentFilter ); - m_currentFilter = TestSpec::Filter(); - } - } - }; - inline TestSpec parseTestSpec( std::string const& arg ) { - return TestSpecParser( ITagAliasRegistry::get() ).parse( arg ).testSpec(); - } - -} // namespace Catch - -#ifdef __clang__ -#pragma clang diagnostic pop -#endif - -// #included from: catch_interfaces_config.h -#define TWOBLUECUBES_CATCH_INTERFACES_CONFIG_H_INCLUDED - -#include -#include -#include - -namespace Catch { - - struct Verbosity { enum Level { - NoOutput = 0, - Quiet, - Normal - }; }; - - struct WarnAbout { enum What { - Nothing = 0x00, - NoAssertions = 0x01 - }; }; - - struct ShowDurations { enum OrNot { - DefaultForReporter, - Always, - Never - }; }; - struct RunTests { enum InWhatOrder { - InDeclarationOrder, - InLexicographicalOrder, - InRandomOrder - }; }; - struct UseColour { enum YesOrNo { - Auto, - Yes, - No - }; }; - - class TestSpec; - - struct IConfig : IShared { - - virtual ~IConfig(); - - virtual bool allowThrows() const = 0; - virtual std::ostream& stream() const = 0; - virtual std::string name() const = 0; - virtual bool includeSuccessfulResults() const = 0; - virtual bool shouldDebugBreak() const = 0; - virtual bool warnAboutMissingAssertions() const = 0; - virtual int abortAfter() const = 0; - virtual bool showInvisibles() const = 0; - virtual ShowDurations::OrNot showDurations() const = 0; - virtual TestSpec const& testSpec() const = 0; - virtual RunTests::InWhatOrder runOrder() const = 0; - virtual unsigned int rngSeed() const = 0; - virtual UseColour::YesOrNo useColour() const = 0; - }; -} - -// #included from: catch_stream.h -#define TWOBLUECUBES_CATCH_STREAM_H_INCLUDED - -// #included from: catch_streambuf.h -#define TWOBLUECUBES_CATCH_STREAMBUF_H_INCLUDED - -#include - -namespace Catch { - - class StreamBufBase : public std::streambuf { - public: - virtual ~StreamBufBase() CATCH_NOEXCEPT; - }; -} - -#include -#include -#include -#include - -namespace Catch { - - std::ostream& cout(); - std::ostream& cerr(); - - struct IStream { - virtual ~IStream() CATCH_NOEXCEPT; - virtual std::ostream& stream() const = 0; - }; - - class FileStream : public IStream { - mutable std::ofstream m_ofs; - public: - FileStream( std::string const& filename ); - virtual ~FileStream() CATCH_NOEXCEPT; - public: // IStream - virtual std::ostream& stream() const CATCH_OVERRIDE; - }; - - class CoutStream : public IStream { - mutable std::ostream m_os; - public: - CoutStream(); - virtual ~CoutStream() CATCH_NOEXCEPT; - - public: // IStream - virtual std::ostream& stream() const CATCH_OVERRIDE; - }; - - class DebugOutStream : public IStream { - CATCH_AUTO_PTR( StreamBufBase ) m_streamBuf; - mutable std::ostream m_os; - public: - DebugOutStream(); - virtual ~DebugOutStream() CATCH_NOEXCEPT; - - public: // IStream - virtual std::ostream& stream() const CATCH_OVERRIDE; - }; -} - -#include -#include -#include -#include -#include - -#ifndef CATCH_CONFIG_CONSOLE_WIDTH -#define CATCH_CONFIG_CONSOLE_WIDTH 80 -#endif - -namespace Catch { - - struct ConfigData { - - ConfigData() - : listTests( false ), - listTags( false ), - listReporters( false ), - listTestNamesOnly( false ), - showSuccessfulTests( false ), - shouldDebugBreak( false ), - noThrow( false ), - showHelp( false ), - showInvisibles( false ), - filenamesAsTags( false ), - abortAfter( -1 ), - rngSeed( 0 ), - verbosity( Verbosity::Normal ), - warnings( WarnAbout::Nothing ), - showDurations( ShowDurations::DefaultForReporter ), - runOrder( RunTests::InDeclarationOrder ), - useColour( UseColour::Auto ) - {} - - bool listTests; - bool listTags; - bool listReporters; - bool listTestNamesOnly; - - bool showSuccessfulTests; - bool shouldDebugBreak; - bool noThrow; - bool showHelp; - bool showInvisibles; - bool filenamesAsTags; - - int abortAfter; - unsigned int rngSeed; - - Verbosity::Level verbosity; - WarnAbout::What warnings; - ShowDurations::OrNot showDurations; - RunTests::InWhatOrder runOrder; - UseColour::YesOrNo useColour; - - std::string outputFilename; - std::string name; - std::string processName; - - std::vector reporterNames; - std::vector testsOrTags; - }; - - class Config : public SharedImpl { - private: - Config( Config const& other ); - Config& operator = ( Config const& other ); - virtual void dummy(); - public: - - Config() - {} - - Config( ConfigData const& data ) - : m_data( data ), - m_stream( openStream() ) - { - if( !data.testsOrTags.empty() ) { - TestSpecParser parser( ITagAliasRegistry::get() ); - for( std::size_t i = 0; i < data.testsOrTags.size(); ++i ) - parser.parse( data.testsOrTags[i] ); - m_testSpec = parser.testSpec(); - } - } - - virtual ~Config() { - } - - std::string const& getFilename() const { - return m_data.outputFilename ; - } - - bool listTests() const { return m_data.listTests; } - bool listTestNamesOnly() const { return m_data.listTestNamesOnly; } - bool listTags() const { return m_data.listTags; } - bool listReporters() const { return m_data.listReporters; } - - std::string getProcessName() const { return m_data.processName; } - - bool shouldDebugBreak() const { return m_data.shouldDebugBreak; } - - std::vector getReporterNames() const { return m_data.reporterNames; } - - int abortAfter() const { return m_data.abortAfter; } - - TestSpec const& testSpec() const { return m_testSpec; } - - bool showHelp() const { return m_data.showHelp; } - bool showInvisibles() const { return m_data.showInvisibles; } - - // IConfig interface - virtual bool allowThrows() const { return !m_data.noThrow; } - virtual std::ostream& stream() const { return m_stream->stream(); } - virtual std::string name() const { return m_data.name.empty() ? m_data.processName : m_data.name; } - virtual bool includeSuccessfulResults() const { return m_data.showSuccessfulTests; } - virtual bool warnAboutMissingAssertions() const { return m_data.warnings & WarnAbout::NoAssertions; } - virtual ShowDurations::OrNot showDurations() const { return m_data.showDurations; } - virtual RunTests::InWhatOrder runOrder() const { return m_data.runOrder; } - virtual unsigned int rngSeed() const { return m_data.rngSeed; } - virtual UseColour::YesOrNo useColour() const { return m_data.useColour; } - - private: - - IStream const* openStream() { - if( m_data.outputFilename.empty() ) - return new CoutStream(); - else if( m_data.outputFilename[0] == '%' ) { - if( m_data.outputFilename == "%debug" ) - return new DebugOutStream(); - else - throw std::domain_error( "Unrecognised stream: " + m_data.outputFilename ); - } - else - return new FileStream( m_data.outputFilename ); - } - ConfigData m_data; - - CATCH_AUTO_PTR( IStream const ) m_stream; - TestSpec m_testSpec; - }; - -} // end namespace Catch - -// #included from: catch_clara.h -#define TWOBLUECUBES_CATCH_CLARA_H_INCLUDED - -// Use Catch's value for console width (store Clara's off to the side, if present) -#ifdef CLARA_CONFIG_CONSOLE_WIDTH -#define CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH CLARA_CONFIG_CONSOLE_WIDTH -#undef CLARA_CONFIG_CONSOLE_WIDTH -#endif -#define CLARA_CONFIG_CONSOLE_WIDTH CATCH_CONFIG_CONSOLE_WIDTH - -// Declare Clara inside the Catch namespace -#define STITCH_CLARA_OPEN_NAMESPACE namespace Catch { -// #included from: ../external/clara.h - -// Version 0.0.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 -#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(); - } - - 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 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( ::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( 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[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 - -namespace Catch { - - inline void abortAfterFirst( ConfigData& config ) { config.abortAfter = 1; } - inline void abortAfterX( ConfigData& config, int x ) { - if( x < 1 ) - throw std::runtime_error( "Value after -x or --abortAfter must be greater than zero" ); - config.abortAfter = x; - } - inline void addTestOrTags( ConfigData& config, std::string const& _testSpec ) { config.testsOrTags.push_back( _testSpec ); } - inline void addReporterName( ConfigData& config, std::string const& _reporterName ) { config.reporterNames.push_back( _reporterName ); } - - inline void addWarning( ConfigData& config, std::string const& _warning ) { - if( _warning == "NoAssertions" ) - config.warnings = static_cast( 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( "Argment to --rng-seed should be the word 'time' or a number" ); - } - } - inline void setVerbosity( ConfigData& config, int level ) { - // !TBD: accept strings? - config.verbosity = static_cast( 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 ); - - // Less common commands which don't have a short form - cli["--list-test-names-only"] - .describe( "list all/matching test cases names only" ) - .bind( &ConfigData::listTestNamesOnly ); - - cli["--list-reporters"] - .describe( "list all reporters" ) - .bind( &ConfigData::listReporters ); - - cli["--order"] - .describe( "test case order (defaults to decl)" ) - .bind( &setOrder, "decl|lex|rand" ); - - cli["--rng-seed"] - .describe( "set a specific seed for random numbers" ) - .bind( &setRngSeed, "'time'|number" ); - - cli["--force-colour"] - .describe( "force colourised output (deprecated)" ) - .bind( &forceColour ); - - cli["--use-colour"] - .describe( "should output be colourised" ) - .bind( &setUseColour, "yes|no" ); - - return cli; - } - -} // end namespace Catch - -// #included from: internal/catch_list.hpp -#define TWOBLUECUBES_CATCH_LIST_HPP_INCLUDED - -// #included from: catch_text.h -#define TWOBLUECUBES_CATCH_TEXT_H_INCLUDED - -#define TBC_TEXT_FORMAT_CONSOLE_WIDTH CATCH_CONFIG_CONSOLE_WIDTH - -#define CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE Catch -// #included from: ../external/tbc_text_format.h -// Only use header guard if we are not using an outer namespace -#ifndef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE -# ifdef TWOBLUECUBES_TEXT_FORMAT_H_INCLUDED -# ifndef TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED -# define TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED -# endif -# else -# define TWOBLUECUBES_TEXT_FORMAT_H_INCLUDED -# endif -#endif -#ifndef TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED -#include -#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 ), - 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(); - } - - 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 { - - struct Colour { - enum Code { - None = 0, - - White, - Red, - Green, - Blue, - Cyan, - Yellow, - Grey, - - Bright = 0x10, - - BrightRed = Bright | Red, - BrightGreen = Bright | Green, - LightGrey = Bright | Grey, - BrightWhite = Bright | White, - - // By intention - FileName = LightGrey, - Warning = Yellow, - ResultError = BrightRed, - ResultSuccess = BrightGreen, - ResultExpectedFailure = Warning, - - Error = BrightRed, - Success = Green, - - OriginalExpression = Cyan, - ReconstructedExpression = Yellow, - - SecondaryText = LightGrey, - Headers = White - }; - - // Use constructed object for RAII guard - Colour( Code _colourCode ); - Colour( Colour const& other ); - ~Colour(); - - // Use static method for one-shot changes - static void use( Code _colourCode ); - - private: - bool m_moved; - }; - - inline std::ostream& operator << ( std::ostream& os, Colour const& ) { return os; } - -} // end namespace Catch - -// #included from: catch_interfaces_reporter.h -#define TWOBLUECUBES_CATCH_INTERFACES_REPORTER_H_INCLUDED - -#include -#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 ) { - - TestSpec testSpec = config.testSpec(); - if( config.testSpec().hasFilters() ) - Catch::cout() << "Matching test cases:\n"; - else { - Catch::cout() << "All available test cases:\n"; - testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "*" ).testSpec(); - } - - std::size_t matchedTests = 0; - TextAttributes nameAttr, tagsAttr; - nameAttr.setInitialIndent( 2 ).setIndent( 4 ); - tagsAttr.setIndent( 6 ); - - std::vector 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( !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 << "\"" << std::endl; - else - Catch::cout() << testCaseInfo.name << std::endl; - } - return matchedTests; - } - - struct TagInfo { - TagInfo() : count ( 0 ) {} - void add( std::string const& spelling ) { - ++count; - spellings.insert( spelling ); - } - std::string all() const { - std::string out; - for( std::set::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(); - } - - std::map tagCounts; - - 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 ); - } - } - - 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(); - } - - inline std::size_t listReporters( Config const& /*config*/ ) { - Catch::cout() << "Available reporters:\n"; - IReporterRegistry::FactoryMap const& factories = getRegistryHub().getReporterRegistry().getFactories(); - IReporterRegistry::FactoryMap::const_iterator itBegin = factories.begin(), itEnd = factories.end(), it; - std::size_t maxNameLen = 0; - for(it = itBegin; it != itEnd; ++it ) - maxNameLen = (std::max)( maxNameLen, it->first.size() ); - - for(it = itBegin; it != itEnd; ++it ) { - Text wrapper( it->second->getDescription(), TextAttributes() - .setInitialIndent( 0 ) - .setIndent( 7+maxNameLen ) - .setWidth( CATCH_CONFIG_CONSOLE_WIDTH - maxNameLen-8 ) ); - Catch::cout() << " " - << it->first - << ":" - << std::string( maxNameLen - it->first.size() + 2, ' ' ) - << wrapper << "\n"; - } - Catch::cout() << std::endl; - return factories.size(); - } - - inline Option 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 - -// #included from: internal/catch_run_context.hpp -#define TWOBLUECUBES_CATCH_RUNNER_IMPL_HPP_INCLUDED - -// #included from: catch_test_case_tracker.hpp -#define TWOBLUECUBES_CATCH_TEST_CASE_TRACKER_HPP_INCLUDED - -#include -#include -#include -#include - -namespace Catch { -namespace TestCaseTracking { - - struct ITracker : SharedImpl<> { - virtual ~ITracker(); - - // static queries - virtual std::string name() const = 0; - - // dynamic queries - virtual bool isComplete() const = 0; // Successfully completed or failed - virtual bool isSuccessfullyCompleted() const = 0; - virtual bool isOpen() const = 0; // Started but not complete - virtual bool hasChildren() const = 0; - - virtual ITracker& parent() = 0; - - // actions - virtual void close() = 0; // Successfully complete - virtual void fail() = 0; - virtual void markAsNeedingAnotherRun() = 0; - - virtual void addChild( Ptr const& child ) = 0; - virtual ITracker* findChild( std::string const& name ) = 0; - virtual void openChild() = 0; - - // Debug/ checking - virtual bool isSectionTracker() const = 0; - virtual bool isIndexTracker() const = 0; - }; - - class TrackerContext { - - enum RunState { - NotStarted, - Executing, - CompletedCycle - }; - - Ptr m_rootTracker; - ITracker* m_currentTracker; - RunState m_runState; - - public: - - static TrackerContext& instance() { - static TrackerContext s_instance; - return s_instance; - } - - TrackerContext() - : m_currentTracker( CATCH_NULL ), - m_runState( NotStarted ) - {} - - ITracker& startRun(); - - void endRun() { - m_rootTracker.reset(); - m_currentTracker = CATCH_NULL; - m_runState = NotStarted; - } - - void startCycle() { - m_currentTracker = m_rootTracker.get(); - m_runState = Executing; - } - void completeCycle() { - m_runState = CompletedCycle; - } - - bool completedCycle() const { - return m_runState == CompletedCycle; - } - ITracker& currentTracker() { - return *m_currentTracker; - } - void setCurrentTracker( ITracker* tracker ) { - m_currentTracker = tracker; - } - }; - - class TrackerBase : public ITracker { - protected: - enum CycleState { - NotStarted, - Executing, - ExecutingChildren, - NeedsAnotherRun, - CompletedSuccessfully, - Failed - }; - class TrackerHasName { - std::string m_name; - public: - TrackerHasName( std::string const& name ) : m_name( name ) {} - bool operator ()( Ptr const& tracker ) { - return tracker->name() == m_name; - } - }; - typedef std::vector > Children; - std::string m_name; - TrackerContext& m_ctx; - ITracker* m_parent; - Children m_children; - CycleState m_runState; - public: - TrackerBase( std::string const& name, TrackerContext& ctx, ITracker* parent ) - : m_name( name ), - m_ctx( ctx ), - m_parent( parent ), - m_runState( NotStarted ) - {} - virtual ~TrackerBase(); - - virtual std::string name() const CATCH_OVERRIDE { - return m_name; - } - virtual bool isComplete() const CATCH_OVERRIDE { - return m_runState == CompletedSuccessfully || m_runState == Failed; - } - virtual bool isSuccessfullyCompleted() const CATCH_OVERRIDE { - return m_runState == CompletedSuccessfully; - } - virtual bool isOpen() const CATCH_OVERRIDE { - return m_runState != NotStarted && !isComplete(); - } - virtual bool hasChildren() const CATCH_OVERRIDE { - return !m_children.empty(); - } - - virtual void addChild( Ptr const& child ) CATCH_OVERRIDE { - m_children.push_back( child ); - } - - virtual ITracker* findChild( std::string const& name ) CATCH_OVERRIDE { - Children::const_iterator it = std::find_if( m_children.begin(), m_children.end(), TrackerHasName( name ) ); - return( it != m_children.end() ) - ? it->get() - : CATCH_NULL; - } - virtual ITracker& parent() CATCH_OVERRIDE { - assert( m_parent ); // Should always be non-null except for root - return *m_parent; - } - - virtual void openChild() CATCH_OVERRIDE { - if( m_runState != ExecutingChildren ) { - m_runState = ExecutingChildren; - if( m_parent ) - m_parent->openChild(); - } - } - - virtual bool isSectionTracker() const CATCH_OVERRIDE { return false; } - virtual bool isIndexTracker() const CATCH_OVERRIDE { return false; } - - void open() { - m_runState = Executing; - moveToThis(); - if( m_parent ) - m_parent->openChild(); - } - - virtual void close() CATCH_OVERRIDE { - - // Close any still open children (e.g. generators) - while( &m_ctx.currentTracker() != this ) - m_ctx.currentTracker().close(); - - switch( m_runState ) { - case NotStarted: - case CompletedSuccessfully: - case Failed: - throw std::logic_error( "Illogical state" ); - - case NeedsAnotherRun: - break;; - - case Executing: - m_runState = CompletedSuccessfully; - break; - case ExecutingChildren: - if( m_children.empty() || m_children.back()->isComplete() ) - m_runState = CompletedSuccessfully; - break; - - default: - throw std::logic_error( "Unexpected state" ); - } - moveToParent(); - m_ctx.completeCycle(); - } - virtual void fail() CATCH_OVERRIDE { - m_runState = Failed; - if( m_parent ) - m_parent->markAsNeedingAnotherRun(); - moveToParent(); - m_ctx.completeCycle(); - } - virtual void markAsNeedingAnotherRun() CATCH_OVERRIDE { - m_runState = NeedsAnotherRun; - } - private: - void moveToParent() { - assert( m_parent ); - m_ctx.setCurrentTracker( m_parent ); - } - void moveToThis() { - m_ctx.setCurrentTracker( this ); - } - }; - - class SectionTracker : public TrackerBase { - public: - SectionTracker( std::string const& name, TrackerContext& ctx, ITracker* parent ) - : TrackerBase( name, ctx, parent ) - {} - virtual ~SectionTracker(); - - virtual bool isSectionTracker() const CATCH_OVERRIDE { return true; } - - static SectionTracker& acquire( TrackerContext& ctx, std::string const& name ) { - SectionTracker* section = CATCH_NULL; - - ITracker& currentTracker = ctx.currentTracker(); - if( ITracker* childTracker = currentTracker.findChild( name ) ) { - assert( childTracker ); - assert( childTracker->isSectionTracker() ); - section = static_cast( childTracker ); - } - else { - section = new SectionTracker( name, ctx, ¤tTracker ); - currentTracker.addChild( section ); - } - if( !ctx.completedCycle() && !section->isComplete() ) { - - section->open(); - } - return *section; - } - }; - - class IndexTracker : public TrackerBase { - int m_size; - int m_index; - public: - IndexTracker( std::string const& name, TrackerContext& ctx, ITracker* parent, int size ) - : TrackerBase( name, ctx, parent ), - m_size( size ), - m_index( -1 ) - {} - virtual ~IndexTracker(); - - virtual bool isIndexTracker() const CATCH_OVERRIDE { return true; } - - static IndexTracker& acquire( TrackerContext& ctx, std::string const& name, int size ) { - IndexTracker* tracker = CATCH_NULL; - - ITracker& currentTracker = ctx.currentTracker(); - if( ITracker* childTracker = currentTracker.findChild( name ) ) { - assert( childTracker ); - assert( childTracker->isIndexTracker() ); - tracker = static_cast( childTracker ); - } - else { - tracker = new IndexTracker( name, ctx, ¤tTracker, size ); - currentTracker.addChild( tracker ); - } - - if( !ctx.completedCycle() && !tracker->isComplete() ) { - if( tracker->m_runState != ExecutingChildren && tracker->m_runState != NeedsAnotherRun ) - tracker->moveNext(); - tracker->open(); - } - - return *tracker; - } - - int index() const { return m_index; } - - void moveNext() { - m_index++; - m_children.clear(); - } - - virtual void close() CATCH_OVERRIDE { - TrackerBase::close(); - if( m_runState == CompletedSuccessfully && m_index < m_size-1 ) - m_runState = Executing; - } - }; - - inline ITracker& TrackerContext::startRun() { - m_rootTracker = new SectionTracker( "{root}", *this, CATCH_NULL ); - m_currentTracker = CATCH_NULL; - m_runState = Executing; - return *m_rootTracker; - } - -} // namespace TestCaseTracking - -using TestCaseTracking::ITracker; -using TestCaseTracking::TrackerContext; -using TestCaseTracking::SectionTracker; -using TestCaseTracking::IndexTracker; - -} // namespace Catch - -// #included from: catch_fatal_condition.hpp -#define TWOBLUECUBES_CATCH_FATAL_CONDITION_H_INCLUDED - -namespace Catch { - - // Report the error condition then exit the process - inline void fatal( std::string const& message, int exitCode ) { - IContext& context = Catch::getCurrentContext(); - IResultCapture* resultCapture = context.getResultCapture(); - resultCapture->handleFatalErrorCondition( message ); - - if( Catch::alwaysTrue() ) // avoids "no return" warnings - exit( exitCode ); - } - -} // namespace Catch - -#if defined ( CATCH_PLATFORM_WINDOWS ) ///////////////////////////////////////// - -namespace Catch { - - struct FatalConditionHandler { - void reset() {} - }; - -} // namespace Catch - -#else // Not Windows - assumed to be POSIX compatible ////////////////////////// - -#include - -namespace Catch { - - struct SignalDefs { int id; const char* name; }; - extern SignalDefs signalDefs[]; - SignalDefs signalDefs[] = { - { SIGINT, "SIGINT - Terminal interrupt signal" }, - { SIGILL, "SIGILL - Illegal instruction signal" }, - { SIGFPE, "SIGFPE - Floating point error signal" }, - { SIGSEGV, "SIGSEGV - Segmentation violation signal" }, - { SIGTERM, "SIGTERM - Termination request signal" }, - { SIGABRT, "SIGABRT - Abort (abnormal termination) signal" } - }; - - struct FatalConditionHandler { - - static void handleSignal( int sig ) { - for( std::size_t i = 0; i < sizeof(signalDefs)/sizeof(SignalDefs); ++i ) - if( sig == signalDefs[i].id ) - fatal( signalDefs[i].name, -sig ); - fatal( "", -sig ); - } - - FatalConditionHandler() : m_isSet( true ) { - for( std::size_t i = 0; i < sizeof(signalDefs)/sizeof(SignalDefs); ++i ) - signal( signalDefs[i].id, handleSignal ); - } - ~FatalConditionHandler() { - reset(); - } - void reset() { - if( m_isSet ) { - for( std::size_t i = 0; i < sizeof(signalDefs)/sizeof(SignalDefs); ++i ) - signal( signalDefs[i].id, SIG_DFL ); - m_isSet = false; - } - } - - bool m_isSet; - }; - -} // namespace Catch - -#endif // not Windows - -#include -#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; - }; - - /////////////////////////////////////////////////////////////////////////// - - 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_context.setRunner( this ); - m_context.setConfig( m_config ); - m_context.setResultCapture( this ); - m_reporter->testRunStarting( m_runInfo ); - } - - virtual ~RunContext() { - m_reporter->testRunEnded( TestRunStats( m_runInfo, m_totals, aborting() ) ); - } - - void testGroupStarting( std::string const& testSpec, std::size_t groupIndex, std::size_t groupsCount ) { - m_reporter->testGroupStarting( GroupInfo( testSpec, groupIndex, groupsCount ) ); - } - void testGroupEnded( std::string const& testSpec, Totals const& totals, std::size_t groupIndex, std::size_t groupsCount ) { - m_reporter->testGroupEnded( TestGroupStats( GroupInfo( testSpec, groupIndex, groupsCount ), totals, aborting() ) ); - } - - Totals runTest( TestCase const& testCase ) { - Totals prevTotals = m_totals; - - std::string redirectedCout; - std::string redirectedCerr; - - TestCaseInfo testInfo = testCase.getTestCaseInfo(); - - m_reporter->testCaseStarting( testInfo ); - - m_activeTestCase = &testCase; - - do { - m_trackerContext.startRun(); - do { - m_trackerContext.startCycle(); - m_testCaseTracker = &SectionTracker::acquire( m_trackerContext, testInfo.name ); - runCurrentTest( redirectedCout, redirectedCerr ); - } - while( !m_testCaseTracker->isSuccessfullyCompleted() && !aborting() ); - } - // !TBD: deprecated - this will be replaced by indexed trackers - while( getCurrentContext().advanceGeneratorsForCurrentTest() && !aborting() ); - - Totals deltaTotals = m_totals.delta( prevTotals ); - 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++; - } - - if( m_reporter->assertionEnded( AssertionStats( result, m_messages, m_totals ) ) ) - m_messages.clear(); - - // Reset working state - m_lastAssertionInfo = AssertionInfo( "", m_lastAssertionInfo.lineInfo, "{Unknown expression after the reported line}" , m_lastAssertionInfo.resultDisposition ); - m_lastResult = result; - } - - virtual bool sectionStarted ( - SectionInfo const& sectionInfo, - Counts& assertions - ) - { - std::ostringstream oss; - oss << sectionInfo.name << "@" << sectionInfo.lineInfo; - - ITracker& sectionTracker = SectionTracker::acquire( m_trackerContext, oss.str() ); - if( !sectionTracker.isOpen() ) - return false; - m_activeSections.push_back( §ionTracker ); - - m_lastAssertionInfo.lineInfo = sectionInfo.lineInfo; - - m_reporter->sectionStarting( sectionInfo ); - - assertions = m_totals.assertions; - - return true; - } - bool testForMissingAssertions( Counts& assertions ) { - if( assertions.total() != 0 ) - return false; - if( !m_config->warnAboutMissingAssertions() ) - return false; - if( m_trackerContext.currentTracker().hasChildren() ) - return false; - m_totals.assertions.failed++; - assertions.failed++; - return true; - } - - virtual void sectionEnded( SectionEndInfo const& endInfo ) { - Counts assertions = m_totals.assertions - endInfo.prevAssertions; - bool missingAssertions = testForMissingAssertions( assertions ); - - if( !m_activeSections.empty() ) { - m_activeSections.back()->close(); - m_activeSections.pop_back(); - } - - m_reporter->sectionEnded( SectionStats( endInfo.sectionInfo, assertions, endInfo.durationInSeconds, missingAssertions ) ); - m_messages.clear(); - } - - virtual void sectionEndedEarly( SectionEndInfo const& endInfo ) { - if( m_unfinishedSections.empty() ) - m_activeSections.back()->fail(); - else - m_activeSections.back()->close(); - m_activeSections.pop_back(); - - m_unfinishedSections.push_back( endInfo ); - } - - virtual void pushScopedMessage( MessageInfo const& message ) { - m_messages.push_back( message ); - } - - virtual void popScopedMessage( MessageInfo const& message ) { - m_messages.erase( std::remove( m_messages.begin(), m_messages.end(), message ), m_messages.end() ); - } - - virtual std::string getCurrentTestName() const { - return m_activeTestCase - ? m_activeTestCase->getTestCaseInfo().name - : ""; - } - - virtual const AssertionResult* getLastResult() const { - return &m_lastResult; - } - - virtual void handleFatalErrorCondition( std::string const& message ) { - ResultBuilder resultBuilder = makeUnexpectedResultBuilder(); - resultBuilder.setResultType( ResultWas::FatalErrorCondition ); - resultBuilder << message; - resultBuilder.captureExpression(); - - handleUnfinishedSections(); - - // Recreate section for test case (as we will lose the one that was in scope) - TestCaseInfo const& testCaseInfo = m_activeTestCase->getTestCaseInfo(); - SectionInfo testCaseSection( testCaseInfo.lineInfo, testCaseInfo.name, testCaseInfo.description ); - - Counts assertions; - assertions.failed = 1; - SectionStats testCaseSectionStats( testCaseSection, assertions, 0, false ); - m_reporter->sectionEnded( testCaseSectionStats ); - - TestCaseInfo testInfo = m_activeTestCase->getTestCaseInfo(); - - Totals deltaTotals; - deltaTotals.testCases.failed = 1; - m_reporter->testCaseEnded( TestCaseStats( testInfo, - deltaTotals, - "", - "", - false ) ); - m_totals.testCases.failed++; - testGroupEnded( "", m_totals, 1, 1 ); - m_reporter->testRunEnded( TestRunStats( m_runInfo, m_totals, false ) ); - } - - public: - // !TBD We need to do this another way! - bool aborting() const { - return m_totals.assertions.failed == static_cast( m_config->abortAfter() ); - } - - private: - - void runCurrentTest( std::string& redirectedCout, std::string& redirectedCerr ) { - TestCaseInfo const& testCaseInfo = m_activeTestCase->getTestCaseInfo(); - SectionInfo testCaseSection( testCaseInfo.lineInfo, testCaseInfo.name, testCaseInfo.description ); - m_reporter->sectionStarting( testCaseSection ); - Counts prevAssertions = m_totals.assertions; - double duration = 0; - try { - m_lastAssertionInfo = AssertionInfo( "TEST_CASE", testCaseInfo.lineInfo, "", ResultDisposition::Normal ); - - seedRng( *m_config ); - - Timer timer; - timer.start(); - if( m_reporter->getPreferences().shouldRedirectStdOut ) { - StreamRedirect coutRedir( Catch::cout(), redirectedCout ); - StreamRedirect cerrRedir( Catch::cerr(), redirectedCerr ); - invokeActiveTestCase(); - } - else { - invokeActiveTestCase(); - } - duration = timer.getElapsedSeconds(); - } - catch( TestFailureException& ) { - // This just means the test was aborted due to failure - } - catch(...) { - makeUnexpectedResultBuilder().useActiveException(); - } - m_testCaseTracker->close(); - handleUnfinishedSections(); - m_messages.clear(); - - Counts assertions = m_totals.assertions - prevAssertions; - bool missingAssertions = testForMissingAssertions( assertions ); - - if( testCaseInfo.okToFail() ) { - std::swap( assertions.failedButOk, assertions.failed ); - m_totals.assertions.failed -= assertions.failedButOk; - m_totals.assertions.failedButOk += assertions.failedButOk; - } - - SectionStats testCaseSectionStats( testCaseSection, assertions, duration, missingAssertions ); - m_reporter->sectionEnded( testCaseSectionStats ); - } - - void invokeActiveTestCase() { - FatalConditionHandler fatalConditionHandler; // Handle signals - m_activeTestCase->invoke(); - fatalConditionHandler.reset(); - } - - private: - - ResultBuilder makeUnexpectedResultBuilder() const { - return ResultBuilder( m_lastAssertionInfo.macroName.c_str(), - m_lastAssertionInfo.lineInfo, - m_lastAssertionInfo.capturedExpression.c_str(), - m_lastAssertionInfo.resultDisposition ); - } - - void handleUnfinishedSections() { - // If sections ended prematurely due to an exception we stored their - // infos here so we can tear them down outside the unwind process. - for( std::vector::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; - }; - - IResultCapture& getResultCapture() { - if( IResultCapture* capture = getCurrentContext().getResultCapture() ) - return *capture; - else - throw std::logic_error( "No result capture instance" ); - } - -} // end namespace Catch - -// #included from: internal/catch_version.h -#define TWOBLUECUBES_CATCH_VERSION_H_INCLUDED - -namespace Catch { - - // Versioning information - struct Version { - Version( unsigned int _majorVersion, - unsigned int _minorVersion, - unsigned int _patchNumber, - std::string const& _branchName, - unsigned int _buildNumber ); - - unsigned int const majorVersion; - unsigned int const minorVersion; - unsigned int const patchNumber; - - // buildNumber is only used if branchName is not null - std::string const branchName; - unsigned int const buildNumber; - - friend std::ostream& operator << ( std::ostream& os, Version const& version ); - - private: - void operator=( Version const& ); - }; - - extern Version libraryVersion; -} - -#include -#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; - } - - Ptr makeReporter( Ptr const& config ) { - std::vector reporters = config->getReporterNames(); - if( reporters.empty() ) - reporters.push_back( "console" ); - - 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; - } - - 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 -#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 == "" ) { - 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; - }; -} - -namespace Catch { - - namespace { - - class RegistryHub : public IRegistryHub, public IMutableRegistryHub { - - RegistryHub( RegistryHub const& ); - void operator=( RegistryHub const& ); - - public: // IRegistryHub - RegistryHub() { - } - virtual IReporterRegistry const& getReporterRegistry() const CATCH_OVERRIDE { - return m_reporterRegistry; - } - virtual ITestCaseRegistry const& getTestCaseRegistry() const CATCH_OVERRIDE { - return m_testCaseRegistry; - } - virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() CATCH_OVERRIDE { - return m_exceptionTranslatorRegistry; - } - - public: // IMutableRegistryHub - virtual void registerReporter( std::string const& name, Ptr 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 ); - } - - private: - TestRegistry m_testCaseRegistry; - ReporterRegistry m_reporterRegistry; - ExceptionTranslatorRegistry m_exceptionTranslatorRegistry; - }; - - // Single, global, instance - inline RegistryHub*& getTheRegistryHub() { - static RegistryHub* theRegistryHub = CATCH_NULL; - if( !theRegistryHub ) - theRegistryHub = new RegistryHub(); - return theRegistryHub; - } - } - - IRegistryHub& getRegistryHub() { - return *getTheRegistryHub(); - } - IMutableRegistryHub& getMutableRegistryHub() { - return *getTheRegistryHub(); - } - void cleanUp() { - delete getTheRegistryHub(); - getTheRegistryHub() = CATCH_NULL; - cleanUpContext(); - } - std::string translateActiveException() { - return getRegistryHub().getExceptionTranslatorRegistry().translateActiveException(); - } - -} // end namespace Catch - -// #included from: catch_notimplemented_exception.hpp -#define TWOBLUECUBES_CATCH_NOTIMPLEMENTED_EXCEPTION_HPP_INCLUDED - -#include - -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; - } -#endif -} - -namespace Catch { - - class Context : public IMutableContext { - - Context() : m_config( CATCH_NULL ), m_runner( CATCH_NULL ), m_resultCapture( CATCH_NULL ) {} - Context( Context const& ); - void operator=( Context const& ); - - public: // IContext - virtual IResultCapture* getResultCapture() { - return m_resultCapture; - } - virtual IRunner* getRunner() { - return m_runner; - } - virtual size_t getGeneratorIndex( std::string const& fileInfo, size_t totalSize ) { - return getGeneratorsForCurrentTest() - .getGeneratorInfo( fileInfo, totalSize ) - .getCurrentIndex(); - } - virtual bool advanceGeneratorsForCurrentTest() { - IGeneratorsForTest* generators = findGeneratorsForCurrentTest(); - return generators && generators->moveNext(); - } - - virtual Ptr 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 - -namespace Catch { - namespace { - - struct IColourImpl { - virtual ~IColourImpl() {} - virtual void use( Colour::Code _colourCode ) = 0; - }; - - struct NoColourImpl : IColourImpl { - void use( Colour::Code ) {} - - static IColourImpl* instance() { - static NoColourImpl s_instance; - return &s_instance; - } - }; - - } // anon namespace -} // namespace Catch - -#if !defined( CATCH_CONFIG_COLOUR_NONE ) && !defined( CATCH_CONFIG_COLOUR_WINDOWS ) && !defined( CATCH_CONFIG_COLOUR_ANSI ) -# ifdef CATCH_PLATFORM_WINDOWS -# define CATCH_CONFIG_COLOUR_WINDOWS -# else -# define CATCH_CONFIG_COLOUR_ANSI -# endif -#endif - -#if defined ( CATCH_CONFIG_COLOUR_WINDOWS ) ///////////////////////////////////////// - -#ifndef NOMINMAX -#define NOMINMAX -#endif - -#ifdef __AFXDLL -#include -#else -#include -#endif - -namespace Catch { -namespace { - - class Win32ColourImpl : public IColourImpl { - public: - Win32ColourImpl() : stdoutHandle( GetStdHandle(STD_OUTPUT_HANDLE) ) - { - CONSOLE_SCREEN_BUFFER_INFO csbiInfo; - GetConsoleScreenBufferInfo( stdoutHandle, &csbiInfo ); - originalForegroundAttributes = csbiInfo.wAttributes & ~( BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_BLUE | BACKGROUND_INTENSITY ); - originalBackgroundAttributes = csbiInfo.wAttributes & ~( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY ); - } - - virtual void use( Colour::Code _colourCode ) { - switch( _colourCode ) { - case Colour::None: return setTextAttribute( originalForegroundAttributes ); - case Colour::White: return setTextAttribute( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE ); - case Colour::Red: return setTextAttribute( FOREGROUND_RED ); - case Colour::Green: return setTextAttribute( FOREGROUND_GREEN ); - case Colour::Blue: return setTextAttribute( FOREGROUND_BLUE ); - case Colour::Cyan: return setTextAttribute( FOREGROUND_BLUE | FOREGROUND_GREEN ); - case Colour::Yellow: return setTextAttribute( FOREGROUND_RED | FOREGROUND_GREEN ); - case Colour::Grey: return setTextAttribute( 0 ); - - case Colour::LightGrey: return setTextAttribute( FOREGROUND_INTENSITY ); - case Colour::BrightRed: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_RED ); - case Colour::BrightGreen: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN ); - case Colour::BrightWhite: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE ); - - case Colour::Bright: throw std::logic_error( "not a colour" ); - } - } - - private: - void setTextAttribute( WORD _textAttribute ) { - SetConsoleTextAttribute( stdoutHandle, _textAttribute | originalBackgroundAttributes ); - } - HANDLE stdoutHandle; - WORD originalForegroundAttributes; - WORD originalBackgroundAttributes; - }; - - IColourImpl* platformColourInstance() { - static Win32ColourImpl s_instance; - - Ptr config = getCurrentContext().getConfig(); - UseColour::YesOrNo colourMode = config - ? config->useColour() - : UseColour::Auto; - if( colourMode == UseColour::Auto ) - colourMode = !isDebuggerActive() - ? UseColour::Yes - : UseColour::No; - return colourMode == UseColour::Yes - ? &s_instance - : NoColourImpl::instance(); - } - -} // end anon namespace -} // end namespace Catch - -#elif defined( CATCH_CONFIG_COLOUR_ANSI ) ////////////////////////////////////// - -#include - -namespace Catch { -namespace { - - // use POSIX/ ANSI console terminal codes - // Thanks to Adam Strzelecki for original contribution - // (http://github.com/nanoant) - // https://github.com/philsquared/Catch/pull/131 - class PosixColourImpl : public IColourImpl { - public: - virtual void use( Colour::Code _colourCode ) { - switch( _colourCode ) { - case Colour::None: - case Colour::White: return setColour( "[0m" ); - case Colour::Red: return setColour( "[0;31m" ); - case Colour::Green: return setColour( "[0;32m" ); - case Colour::Blue: return setColour( "[0;34m" ); - case Colour::Cyan: return setColour( "[0;36m" ); - case Colour::Yellow: return setColour( "[0;33m" ); - case Colour::Grey: return setColour( "[1;30m" ); - - case Colour::LightGrey: return setColour( "[0;37m" ); - case Colour::BrightRed: return setColour( "[1;31m" ); - case Colour::BrightGreen: return setColour( "[1;32m" ); - case Colour::BrightWhite: return setColour( "[1;37m" ); - - case Colour::Bright: throw std::logic_error( "not a colour" ); - } - } - static IColourImpl* instance() { - static PosixColourImpl s_instance; - return &s_instance; - } - - private: - void setColour( const char* _escapeCode ) { - Catch::cout() << '\033' << _escapeCode; - } - }; - - IColourImpl* platformColourInstance() { - Ptr config = getCurrentContext().getConfig(); - UseColour::YesOrNo colourMode = config - ? config->useColour() - : UseColour::Auto; - if( colourMode == UseColour::Auto ) - colourMode = (!isDebuggerActive() && isatty(STDOUT_FILENO) ) - ? UseColour::Yes - : UseColour::No; - return colourMode == UseColour::Yes - ? PosixColourImpl::instance() - : NoColourImpl::instance(); - } - -} // end anon namespace -} // end namespace Catch - -#else // not Windows or ANSI /////////////////////////////////////////////// - -namespace Catch { - - static IColourImpl* platformColourInstance() { return NoColourImpl::instance(); } - -} // end namespace Catch - -#endif // Windows/ ANSI/ None - -namespace Catch { - - Colour::Colour( Code _colourCode ) : m_moved( false ) { use( _colourCode ); } - Colour::Colour( Colour const& _other ) : m_moved( false ) { const_cast( _other ).m_moved = true; } - Colour::~Colour(){ if( !m_moved ) use( None ); } - - void Colour::use( Code _colourCode ) { - static IColourImpl* impl = platformColourInstance(); - impl->use( _colourCode ); - } - -} // end namespace Catch - -// #included from: catch_generators_impl.hpp -#define TWOBLUECUBES_CATCH_GENERATORS_IMPL_HPP_INCLUDED - -#include -#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( std::string const& _macroName, - SourceLineInfo const& _lineInfo, - std::string const& _capturedExpression, - ResultDisposition::Flags _resultDisposition ) - : macroName( _macroName ), - lineInfo( _lineInfo ), - capturedExpression( _capturedExpression ), - resultDisposition( _resultDisposition ) - {} - - AssertionResult::AssertionResult() {} - - AssertionResult::AssertionResult( AssertionInfo const& info, AssertionResultData const& data ) - : m_info( info ), - m_resultData( data ) - {} - - AssertionResult::~AssertionResult() {} - - // Result was a success - bool AssertionResult::succeeded() const { - return Catch::isOk( m_resultData.resultType ); - } - - // Result was a success, or failure is suppressed - bool AssertionResult::isOk() const { - return Catch::isOk( m_resultData.resultType ) || shouldSuppressFailure( m_info.resultDisposition ); - } - - ResultWas::OfType AssertionResult::getResultType() const { - return m_resultData.resultType; - } - - bool AssertionResult::hasExpression() const { - return !m_info.capturedExpression.empty(); - } - - bool AssertionResult::hasMessage() const { - return !m_resultData.message.empty(); - } - - std::string AssertionResult::getExpression() const { - if( isFalseTest( m_info.resultDisposition ) ) - return "!" + m_info.capturedExpression; - else - return m_info.capturedExpression; - } - std::string AssertionResult::getExpressionInMacro() const { - if( m_info.macroName.empty() ) - return m_info.capturedExpression; - else - return m_info.macroName + "( " + m_info.capturedExpression + " )"; - } - - bool AssertionResult::hasExpandedExpression() const { - return hasExpression() && getExpandedExpression() != getExpression(); - } - - std::string AssertionResult::getExpandedExpression() const { - return m_resultData.reconstructedExpression; - } - - std::string AssertionResult::getMessage() const { - return m_resultData.message; - } - SourceLineInfo AssertionResult::getSourceInfo() const { - return m_info.lineInfo; - } - - std::string AssertionResult::getTestMacroName() const { - return m_info.macroName; - } - -} // end namespace Catch - -// #included from: catch_test_case_info.hpp -#define TWOBLUECUBES_CATCH_TEST_CASE_INFO_HPP_INCLUDED - -namespace Catch { - - inline TestCaseInfo::SpecialProperties parseSpecialTag( std::string const& tag ) { - if( startsWith( tag, "." ) || - tag == "hide" || - tag == "!hide" ) - return TestCaseInfo::IsHidden; - else if( tag == "!throws" ) - return TestCaseInfo::Throws; - else if( tag == "!shouldfail" ) - return TestCaseInfo::ShouldFail; - else if( tag == "!mayfail" ) - return TestCaseInfo::MayFail; - else - return TestCaseInfo::None; - } - inline bool isReservedTag( std::string const& tag ) { - return parseSpecialTag( tag ) == TestCaseInfo::None && tag.size() > 0 && !isalnum( tag[0] ); - } - inline void enforceNotReservedTag( std::string const& tag, SourceLineInfo const& _lineInfo ) { - if( isReservedTag( tag ) ) { - { - Colour colourGuard( Colour::Red ); - Catch::cerr() - << "Tag name [" << tag << "] not allowed.\n" - << "Tag names starting with non alpha-numeric characters are reserved\n"; - } - { - Colour colourGuard( Colour::FileName ); - Catch::cerr() << _lineInfo << std::endl; - } - exit(1); - } - } - - TestCase makeTestCase( ITestCase* _testCase, - std::string const& _className, - std::string const& _name, - std::string const& _descOrTags, - SourceLineInfo const& _lineInfo ) - { - bool isHidden( startsWith( _name, "./" ) ); // Legacy support - - // Parse out tags - std::set 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, - std::string const& _branchName, - unsigned int _buildNumber ) - : majorVersion( _majorVersion ), - minorVersion( _minorVersion ), - patchNumber( _patchNumber ), - branchName( _branchName ), - buildNumber( _buildNumber ) - {} - - std::ostream& operator << ( std::ostream& os, Version const& version ) { - os << version.majorVersion << "." - << version.minorVersion << "." - << version.patchNumber; - - if( !version.branchName.empty() ) { - os << "-" << version.branchName - << "." << version.buildNumber; - } - return os; - } - - Version libraryVersion( 1, 6, 0, "", 0 ); - -} - -// #included from: catch_message.hpp -#define TWOBLUECUBES_CATCH_MESSAGE_HPP_INCLUDED - -namespace Catch { - - MessageInfo::MessageInfo( std::string const& _macroName, - SourceLineInfo const& _lineInfo, - ResultWas::OfType _type ) - : macroName( _macroName ), - lineInfo( _lineInfo ), - type( _type ), - sequence( ++globalCount ) - {} - - // This may need protecting if threading support is added - unsigned int MessageInfo::globalCount = 0; - - //////////////////////////////////////////////////////////////////////////// - - ScopedMessage::ScopedMessage( MessageBuilder const& builder ) - : m_info( builder.m_info ) - { - m_info.message = builder.m_stream.str(); - getResultCapture().pushScopedMessage( m_info ); - } - ScopedMessage::ScopedMessage( ScopedMessage const& other ) - : m_info( other.m_info ) - {} - - ScopedMessage::~ScopedMessage() { - getResultCapture().popScopedMessage( m_info ); - } - -} // end namespace Catch - -// #included from: catch_legacy_reporter_adapter.hpp -#define TWOBLUECUBES_CATCH_LEGACY_REPORTER_ADAPTER_HPP_INCLUDED - -// #included from: catch_legacy_reporter_adapter.h -#define TWOBLUECUBES_CATCH_LEGACY_REPORTER_ADAPTER_H_INCLUDED - -namespace Catch -{ - // Deprecated - struct IReporter : IShared { - virtual ~IReporter(); - - virtual bool shouldRedirectStdout() const = 0; - - virtual void StartTesting() = 0; - virtual void EndTesting( Totals const& totals ) = 0; - virtual void StartGroup( std::string const& groupName ) = 0; - virtual void EndGroup( std::string const& groupName, Totals const& totals ) = 0; - virtual void StartTestCase( TestCaseInfo const& testInfo ) = 0; - virtual void EndTestCase( TestCaseInfo const& testInfo, Totals const& totals, std::string const& stdOut, std::string const& stdErr ) = 0; - virtual void StartSection( std::string const& sectionName, std::string const& description ) = 0; - virtual void EndSection( std::string const& sectionName, Counts const& assertions ) = 0; - virtual void NoAssertionsInSection( std::string const& sectionName ) = 0; - virtual void NoAssertionsInTestCase( std::string const& testName ) = 0; - virtual void Aborted() = 0; - virtual void Result( AssertionResult const& result ) = 0; - }; - - class LegacyReporterAdapter : public SharedImpl - { - 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" -#endif - -#ifdef CATCH_PLATFORM_WINDOWS -#include -#else -#include -#endif - -namespace Catch { - - namespace { -#ifdef CATCH_PLATFORM_WINDOWS - uint64_t getCurrentTicks() { - static uint64_t hz=0, hzo=0; - if (!hz) { - QueryPerformanceFrequency( reinterpret_cast( &hz ) ); - QueryPerformanceCounter( reinterpret_cast( &hzo ) ); - } - uint64_t t; - QueryPerformanceCounter( reinterpret_cast( &t ) ); - return ((t-hzo)*1000000)/hz; - } -#else - uint64_t 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 - -namespace Catch { - - bool startsWith( std::string const& s, std::string const& prefix ) { - return s.size() >= prefix.size() && s.substr( 0, prefix.size() ) == prefix; - } - bool endsWith( std::string const& s, std::string const& suffix ) { - return s.size() >= suffix.size() && s.substr( s.size()-suffix.size(), suffix.size() ) == suffix; - } - bool contains( std::string const& s, std::string const& infix ) { - return s.find( infix ) != std::string::npos; - } - char toLowerCh(char c) { - return static_cast( ::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 ) : ""; - } - - bool replaceInPlace( std::string& str, std::string const& replaceThis, std::string const& withThis ) { - bool replaced = false; - std::size_t i = str.find( replaceThis ); - while( i != std::string::npos ) { - replaced = true; - str = str.substr( 0, i ) + withThis + str.substr( i+replaceThis.size() ); - if( i < str.size()-withThis.size() ) - i = str.find( replaceThis, i+withThis.size() ); - else - i = std::string::npos; - } - return replaced; - } - - pluralise::pluralise( std::size_t count, std::string const& label ) - : m_count( count ), - m_label( label ) - {} - - std::ostream& operator << ( std::ostream& os, pluralise const& pluraliser ) { - os << pluraliser.m_count << " " << pluraliser.m_label; - if( pluraliser.m_count != 1 ) - os << "s"; - return os; - } - - SourceLineInfo::SourceLineInfo() : line( 0 ){} - SourceLineInfo::SourceLineInfo( char const* _file, std::size_t _line ) - : file( _file ), - line( _line ) - {} - SourceLineInfo::SourceLineInfo( SourceLineInfo const& other ) - : file( other.file ), - line( other.line ) - {} - bool SourceLineInfo::empty() const { - return file.empty(); - } - bool SourceLineInfo::operator == ( SourceLineInfo const& other ) const { - return line == other.line && file == other.file; - } - bool SourceLineInfo::operator < ( SourceLineInfo const& other ) const { - return line < other.line || ( line == other.line && file < other.file ); - } - - void seedRng( IConfig const& config ) { - if( config.rngSeed() != 0 ) - std::srand( config.rngSeed() ); - } - unsigned int rngSeed() { - return getCurrentContext().getConfig()->rngSeed(); - } - - std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info ) { -#ifndef __GNUG__ - os << info.file << "(" << info.line << ")"; -#else - os << info.file << ":" << info.line; -#endif - return os; - } - - void throwLogicError( std::string const& message, SourceLineInfo const& locationInfo ) { - std::ostringstream oss; - oss << locationInfo << ": Internal Catch error: '" << message << "'"; - if( alwaysTrue() ) - throw std::logic_error( oss.str() ); - } -} - -// #included from: catch_section.hpp -#define TWOBLUECUBES_CATCH_SECTION_HPP_INCLUDED - -namespace Catch { - - SectionInfo::SectionInfo - ( SourceLineInfo const& _lineInfo, - std::string const& _name, - std::string const& _description ) - : name( _name ), - description( _description ), - lineInfo( _lineInfo ) - {} - - Section::Section( SectionInfo const& info ) - : m_info( info ), - m_sectionIncluded( getResultCapture().sectionStarted( m_info, m_assertions ) ) - { - m_timer.start(); - } - - Section::~Section() { - if( m_sectionIncluded ) { - SectionEndInfo endInfo( m_info, m_assertions, m_timer.getElapsedSeconds() ); - if( std::uncaught_exception() ) - getResultCapture().sectionEndedEarly( endInfo ); - else - getResultCapture().sectionEnded( endInfo ); - } - } - - // This indicates whether the section should be executed or not - Section::operator bool() const { - return m_sectionIncluded; - } - -} // end namespace Catch - -// #included from: catch_debugger.hpp -#define TWOBLUECUBES_CATCH_DEBUGGER_HPP_INCLUDED - -#include - -#ifdef CATCH_PLATFORM_MAC - - #include - #include - #include - #include - #include - - namespace Catch{ - - // The following function is taken directly from the following technical note: - // http://developer.apple.com/library/mac/#qa/qa2004/qa1361.html - - // Returns true if the current process is being debugged (either - // running under the debugger or has a debugger attached post facto). - bool isDebuggerActive(){ - - int mib[4]; - struct kinfo_proc info; - size_t size; - - // Initialize the flags so that, if sysctl fails for some bizarre - // reason, we get a predictable result. - - info.kp_proc.p_flag = 0; - - // Initialize mib, which tells sysctl the info we want, in this case - // we're looking for information about a specific process ID. - - mib[0] = CTL_KERN; - mib[1] = KERN_PROC; - mib[2] = KERN_PROC_PID; - mib[3] = getpid(); - - // Call sysctl. - - size = sizeof(info); - if( sysctl(mib, sizeof(mib) / sizeof(*mib), &info, &size, CATCH_NULL, 0) != 0 ) { - Catch::cerr() << "\n** Call to sysctl failed - unable to determine if debugger is active **\n" << std::endl; - return false; - } - - // We're being debugged if the P_TRACED flag is set. - - return ( (info.kp_proc.p_flag & P_TRACED) != 0 ); - } - } // namespace Catch - -#elif defined(_MSC_VER) - extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent(); - namespace Catch { - bool isDebuggerActive() { - return IsDebuggerPresent() != 0; - } - } -#elif defined(__MINGW32__) - extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent(); - namespace Catch { - bool isDebuggerActive() { - return IsDebuggerPresent() != 0; - } - } -#else - namespace Catch { - inline bool isDebuggerActive() { return false; } - } -#endif // Platform - -#ifdef CATCH_PLATFORM_WINDOWS - extern "C" __declspec(dllimport) void __stdcall OutputDebugStringA( const char* ); - namespace Catch { - void writeToDebugConsole( std::string const& text ) { - ::OutputDebugStringA( text.c_str() ); - } - } -#else - namespace Catch { - void writeToDebugConsole( std::string const& text ) { - // !TBD: Need a version for Mac/ XCode and other IDEs - Catch::cout() << text; - } - } -#endif // Platform - -// #included from: catch_tostring.hpp -#define TWOBLUECUBES_CATCH_TOSTRING_HPP_INCLUDED - -namespace Catch { - -namespace Detail { - - const std::string unprintableString = "{?}"; - - namespace { - const int hexThreshold = 255; - - struct Endianness { - enum Arch { Big, Little }; - - static Arch which() { - union _{ - int asInt; - char asChar[sizeof (int)]; - } u; - - u.asInt = 1; - return ( u.asChar[sizeof(int)-1] == 1 ) ? Big : Little; - } - }; - } - - std::string rawMemoryToString( const void *object, std::size_t size ) - { - // Reverse order for little endian architectures - int i = 0, end = static_cast( size ), inc = 1; - if( Endianness::which() == Endianness::Little ) { - i = end-1; - end = inc = -1; - } - - unsigned char const *bytes = static_cast(object); - std::ostringstream os; - os << "0x" << std::setfill('0') << std::hex; - for( ; i != end; i += inc ) - os << std::setw(2) << static_cast(bytes[i]); - return os.str(); - } -} - -std::string toString( std::string const& value ) { - std::string s = value; - if( getCurrentContext().getConfig()->showInvisibles() ) { - for(size_t i = 0; i < s.size(); ++i ) { - std::string subs; - switch( s[i] ) { - case '\n': subs = "\\n"; break; - case '\t': subs = "\\t"; break; - default: break; - } - if( !subs.empty() ) { - s = s.substr( 0, i ) + subs + s.substr( i+1 ); - ++i; - } - } - } - return "\"" + s + "\""; -} -std::string toString( std::wstring const& value ) { - - std::string 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 ); -} - -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 ) { - return value < ' ' - ? toString( static_cast( value ) ) - : Detail::makeString( value ); -} - -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 - -#ifdef __OBJC__ - std::string toString( NSString const * const& nsstring ) { - if( !nsstring ) - return "nil"; - return "@" + toString([nsstring UTF8String]); - } - std::string toString( NSString * CATCH_ARC_STRONG const& nsstring ) { - if( !nsstring ) - return "nil"; - return "@" + toString([nsstring UTF8String]); - } - std::string toString( NSObject* const& nsObject ) { - return toString( [nsObject description] ); - } -#endif - -} // end namespace Catch - -// #included from: catch_result_builder.hpp -#define TWOBLUECUBES_CATCH_RESULT_BUILDER_HPP_INCLUDED - -namespace Catch { - - std::string capturedExpressionWithSecondArgument( std::string const& capturedExpression, std::string const& secondArg ) { - return secondArg.empty() || secondArg == "\"\"" - ? capturedExpression - : capturedExpression + ", " + secondArg; - } - ResultBuilder::ResultBuilder( char const* macroName, - SourceLineInfo const& lineInfo, - char const* capturedExpression, - ResultDisposition::Flags resultDisposition, - char const* secondArg ) - : m_assertionInfo( macroName, lineInfo, capturedExpressionWithSecondArgument( capturedExpression, secondArg ), resultDisposition ), - m_shouldDebugBreak( false ), - m_shouldThrow( false ) - {} - - ResultBuilder& ResultBuilder::setResultType( ResultWas::OfType result ) { - m_data.resultType = result; - return *this; - } - ResultBuilder& ResultBuilder::setResultType( bool result ) { - m_data.resultType = result ? ResultWas::Ok : ResultWas::ExpressionFailed; - return *this; - } - ResultBuilder& ResultBuilder::setLhs( std::string const& lhs ) { - m_exprComponents.lhs = lhs; - return *this; - } - ResultBuilder& ResultBuilder::setRhs( std::string const& rhs ) { - m_exprComponents.rhs = rhs; - return *this; - } - ResultBuilder& ResultBuilder::setOp( std::string const& op ) { - m_exprComponents.op = op; - return *this; - } - - void ResultBuilder::endExpression() { - m_exprComponents.testFalse = isFalseTest( m_assertionInfo.resultDisposition ); - captureExpression(); - } - - void ResultBuilder::useActiveException( ResultDisposition::Flags resultDisposition ) { - m_assertionInfo.resultDisposition = resultDisposition; - m_stream.oss << Catch::translateActiveException(); - captureResult( ResultWas::ThrewException ); - } - - void ResultBuilder::captureResult( ResultWas::OfType resultType ) { - setResultType( resultType ); - captureExpression(); - } - void ResultBuilder::captureExpectedException( std::string const& expectedMessage ) { - if( expectedMessage.empty() ) - captureExpectedException( Matchers::Impl::Generic::AllOf() ); - else - captureExpectedException( Matchers::Equals( expectedMessage ) ); - } - - void ResultBuilder::captureExpectedException( Matchers::Impl::Matcher const& matcher ) { - - assert( m_exprComponents.testFalse == false ); - AssertionResultData data = m_data; - data.resultType = ResultWas::Ok; - data.reconstructedExpression = m_assertionInfo.capturedExpression; - - std::string actualMessage = Catch::translateActiveException(); - if( !matcher.match( actualMessage ) ) { - data.resultType = ResultWas::ExpressionFailed; - data.reconstructedExpression = actualMessage; - } - AssertionResult result( m_assertionInfo, data ); - handleResult( result ); - } - - void ResultBuilder::captureExpression() { - AssertionResult result = build(); - handleResult( result ); - } - void ResultBuilder::handleResult( AssertionResult const& result ) - { - getResultCapture().assertionEnded( result ); - - if( !result.isOk() ) { - if( getCurrentContext().getConfig()->shouldDebugBreak() ) - m_shouldDebugBreak = true; - if( getCurrentContext().getRunner()->aborting() || (m_assertionInfo.resultDisposition & ResultDisposition::Normal) ) - m_shouldThrow = true; - } - } - void ResultBuilder::react() { - if( m_shouldThrow ) - throw Catch::TestFailureException(); - } - - bool ResultBuilder::shouldDebugBreak() const { return m_shouldDebugBreak; } - bool ResultBuilder::allowThrows() const { return getCurrentContext().getConfig()->allowThrows(); } - - AssertionResult ResultBuilder::build() const - { - assert( m_data.resultType != ResultWas::Unknown ); - - AssertionResultData data = m_data; - - // Flip bool results if testFalse is set - if( m_exprComponents.testFalse ) { - if( data.resultType == ResultWas::Ok ) - data.resultType = ResultWas::ExpressionFailed; - else if( data.resultType == ResultWas::ExpressionFailed ) - data.resultType = ResultWas::Ok; - } - - data.message = m_stream.oss.str(); - data.reconstructedExpression = reconstructExpression(); - if( m_exprComponents.testFalse ) { - if( m_exprComponents.op == "" ) - data.reconstructedExpression = "!" + data.reconstructedExpression; - else - data.reconstructedExpression = "!(" + data.reconstructedExpression + ")"; - } - return AssertionResult( m_assertionInfo, data ); - } - std::string ResultBuilder::reconstructExpression() const { - if( m_exprComponents.op == "" ) - return m_exprComponents.lhs.empty() ? m_assertionInfo.capturedExpression : m_exprComponents.lhs; - else if( m_exprComponents.op == "matches" ) - return m_exprComponents.lhs + " " + m_exprComponents.rhs; - else if( m_exprComponents.op != "!" ) { - if( m_exprComponents.lhs.size() + m_exprComponents.rhs.size() < 40 && - m_exprComponents.lhs.find("\n") == std::string::npos && - m_exprComponents.rhs.find("\n") == std::string::npos ) - return m_exprComponents.lhs + " " + m_exprComponents.op + " " + m_exprComponents.rhs; - else - return m_exprComponents.lhs + "\n" + m_exprComponents.op + "\n" + m_exprComponents.rhs; - } - else - return "{can't expand - use " + m_assertionInfo.macroName + "_FALSE( " + m_assertionInfo.capturedExpression.substr(1) + " ) instead of " + m_assertionInfo.macroName + "( " + m_assertionInfo.capturedExpression + " ) for better diagnostics}"; - } - -} // end namespace Catch - -// #included from: catch_tag_alias_registry.hpp -#define TWOBLUECUBES_CATCH_TAG_ALIAS_REGISTRY_HPP_INCLUDED - -// #included from: catch_tag_alias_registry.h -#define TWOBLUECUBES_CATCH_TAG_ALIAS_REGISTRY_H_INCLUDED - -#include - -namespace Catch { - - class TagAliasRegistry : public ITagAliasRegistry { - public: - virtual ~TagAliasRegistry(); - virtual Option find( std::string const& alias ) const; - virtual std::string expandAliases( std::string const& unexpandedTestSpec ) const; - void add( char const* alias, char const* tag, SourceLineInfo const& lineInfo ); - static TagAliasRegistry& get(); - - private: - std::map m_registry; - }; - -} // end namespace Catch - -#include -#include - -namespace Catch { - - 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; - } - - void TagAliasRegistry::add( char const* alias, char const* tag, SourceLineInfo const& lineInfo ) { - - if( !startsWith( alias, "[@" ) || !endsWith( alias, "]" ) ) { - std::ostringstream oss; - oss << "error: tag alias, \"" << alias << "\" is not of the form [@alias name].\n" << lineInfo; - throw std::domain_error( oss.str().c_str() ); - } - if( !m_registry.insert( std::make_pair( alias, TagAlias( tag, lineInfo ) ) ).second ) { - std::ostringstream oss; - oss << "error: tag alias, \"" << alias << "\" already registered.\n" - << "\tFirst seen at " << find(alias)->lineInfo << "\n" - << "\tRedefined at " << lineInfo; - throw std::domain_error( oss.str().c_str() ); - } - } - - TagAliasRegistry& TagAliasRegistry::get() { - static TagAliasRegistry instance; - return instance; - - } - - ITagAliasRegistry::~ITagAliasRegistry() {} - ITagAliasRegistry const& ITagAliasRegistry::get() { return TagAliasRegistry::get(); } - - RegistrarForTagAliases::RegistrarForTagAliases( char const* alias, char const* tag, SourceLineInfo const& lineInfo ) { - try { - TagAliasRegistry::get().add( alias, tag, lineInfo ); - } - catch( std::exception& ex ) { - Colour colourGuard( Colour::Red ); - Catch::cerr() << ex.what() << std::endl; - exit(1); - } - } - -} // end namespace Catch - -// #included from: ../reporters/catch_reporter_multi.hpp -#define TWOBLUECUBES_CATCH_REPORTER_MULTI_HPP_INCLUDED - -namespace Catch { - -class MultipleReporters : public SharedImpl { - typedef std::vector > Reporters; - Reporters m_reporters; - -public: - void add( Ptr const& reporter ) { - m_reporters.push_back( reporter ); - } - -public: // IStreamingReporter - - virtual ReporterPreferences getPreferences() const CATCH_OVERRIDE { - return m_reporters[0]->getPreferences(); - } - - virtual void noMatchingTestCases( std::string const& spec ) CATCH_OVERRIDE { - for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); - it != itEnd; - ++it ) - (*it)->noMatchingTestCases( spec ); - } - - virtual void testRunStarting( TestRunInfo const& testRunInfo ) CATCH_OVERRIDE { - for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); - it != itEnd; - ++it ) - (*it)->testRunStarting( testRunInfo ); - } - - virtual void testGroupStarting( GroupInfo const& groupInfo ) CATCH_OVERRIDE { - for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); - it != itEnd; - ++it ) - (*it)->testGroupStarting( groupInfo ); - } - - virtual void testCaseStarting( TestCaseInfo const& testInfo ) CATCH_OVERRIDE { - for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); - it != itEnd; - ++it ) - (*it)->testCaseStarting( testInfo ); - } - - virtual void sectionStarting( SectionInfo const& sectionInfo ) CATCH_OVERRIDE { - for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); - it != itEnd; - ++it ) - (*it)->sectionStarting( sectionInfo ); - } - - virtual void assertionStarting( AssertionInfo const& assertionInfo ) CATCH_OVERRIDE { - for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); - it != itEnd; - ++it ) - (*it)->assertionStarting( assertionInfo ); - } - - // The return value indicates if the messages buffer should be cleared: - virtual bool assertionEnded( AssertionStats const& assertionStats ) CATCH_OVERRIDE { - bool clearBuffer = false; - for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); - it != itEnd; - ++it ) - clearBuffer |= (*it)->assertionEnded( assertionStats ); - return clearBuffer; - } - - virtual void sectionEnded( SectionStats const& sectionStats ) CATCH_OVERRIDE { - for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); - it != itEnd; - ++it ) - (*it)->sectionEnded( sectionStats ); - } - - virtual void testCaseEnded( TestCaseStats const& testCaseStats ) CATCH_OVERRIDE { - for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); - it != itEnd; - ++it ) - (*it)->testCaseEnded( testCaseStats ); - } - - virtual void testGroupEnded( TestGroupStats const& testGroupStats ) CATCH_OVERRIDE { - for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); - it != itEnd; - ++it ) - (*it)->testGroupEnded( testGroupStats ); - } - - virtual void testRunEnded( TestRunStats const& testRunStats ) CATCH_OVERRIDE { - for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); - it != itEnd; - ++it ) - (*it)->testRunEnded( testRunStats ); - } - - virtual void skipTest( TestCaseInfo const& testInfo ) CATCH_OVERRIDE { - for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); - it != itEnd; - ++it ) - (*it)->skipTest( testInfo ); - } - - 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; - - return resultingReporter; -} - -} // end namespace Catch - -// #included from: ../reporters/catch_reporter_xml.hpp -#define TWOBLUECUBES_CATCH_REPORTER_XML_HPP_INCLUDED - -// #included from: catch_reporter_bases.hpp -#define TWOBLUECUBES_CATCH_REPORTER_BASES_HPP_INCLUDED - -#include - -namespace Catch { - - 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; - } - bool operator == ( Ptr const& other ) const { - return operator==( *other ); - } - - SectionStats stats; - typedef std::vector > ChildSections; - typedef std::vector Assertions; - ChildSections childSections; - Assertions assertions; - std::string stdOut; - std::string stdErr; - }; - - struct BySectionInfo { - BySectionInfo( SectionInfo const& other ) : m_other( other ) {} - BySectionInfo( BySectionInfo const& other ) : m_other( other.m_other ) {} - bool operator() ( Ptr const& node ) const { - return node->stats.sectionInfo.lineInfo == m_other.lineInfo; - } - private: - void operator=( BySectionInfo const& ); - SectionInfo const& m_other; - }; - - typedef Node TestCaseNode; - typedef Node TestGroupNode; - typedef Node TestRunNode; - - CumulativeReporterBase( ReporterConfig const& _config ) - : m_config( _config.fullConfig() ), - stream( _config.stream() ) - { - m_reporterPrefs.shouldRedirectStdOut = false; - } - ~CumulativeReporterBase(); - - virtual ReporterPreferences getPreferences() const CATCH_OVERRIDE { - return m_reporterPrefs; - } - - virtual void testRunStarting( TestRunInfo const& ) CATCH_OVERRIDE {} - virtual void testGroupStarting( GroupInfo const& ) CATCH_OVERRIDE {} - - virtual void testCaseStarting( TestCaseInfo const& ) CATCH_OVERRIDE {} - - virtual void sectionStarting( SectionInfo const& sectionInfo ) CATCH_OVERRIDE { - SectionStats incompleteStats( sectionInfo, Counts(), 0, false ); - Ptr 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 ); - 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 {} - - 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 ) { - memset( line, C, CATCH_CONFIG_CONSOLE_WIDTH-1 ); - line[CATCH_CONFIG_CONSOLE_WIDTH-1] = 0; - } - return line; - } - - struct TestEventListenerBase : StreamingReporterBase { - TestEventListenerBase( ReporterConfig const& _config ) - : StreamingReporterBase( _config ) - {} - - virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE {} - virtual bool assertionEnded( AssertionStats const& ) CATCH_OVERRIDE { - return false; - } - }; - -} // end namespace Catch - -// #included from: ../internal/catch_reporter_registrars.hpp -#define TWOBLUECUBES_CATCH_REPORTER_REGISTRARS_HPP_INCLUDED - -namespace Catch { - - template - class LegacyReporterRegistrar { - - class ReporterFactory : public IReporterFactory { - virtual IStreamingReporter* create( ReporterConfig const& config ) const { - return new LegacyReporterAdapter( new T( config ) ); - } - - virtual std::string getDescription() const { - return T::getDescription(); - } - }; - - public: - - LegacyReporterRegistrar( std::string const& name ) { - getMutableRegistryHub().registerReporter( name, new ReporterFactory() ); - } - }; - - template - 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 ""; - } - }; - - public: - - ListenerRegistrar() { - getMutableRegistryHub().registerListener( new ListenerFactory() ); - } - }; -} - -#define INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) \ - namespace{ Catch::LegacyReporterRegistrar catch_internal_RegistrarFor##reporterType( name ); } - -#define INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType ) \ - namespace{ Catch::ReporterRegistrar catch_internal_RegistrarFor##reporterType( name ); } - -#define INTERNAL_CATCH_REGISTER_LISTENER( listenerType ) \ - namespace{ Catch::ListenerRegistrar catch_internal_RegistrarFor##listenerType; } - -// #included from: ../internal/catch_xmlwriter.hpp -#define TWOBLUECUBES_CATCH_XMLWRITER_HPP_INCLUDED - -#include -#include -#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 ) - {} - - 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' ) - 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; - ForWhat m_forWhat; - }; - - class XmlWriter { - public: - - class ScopedElement { - public: - ScopedElement( XmlWriter* writer ) - : m_writer( writer ) - {} - - ScopedElement( ScopedElement const& other ) - : m_writer( other.m_writer ){ - other.m_writer = CATCH_NULL; - } - - ~ScopedElement() { - if( m_writer ) - m_writer->endElement(); - } - - ScopedElement& writeText( std::string const& text, bool indent = true ) { - m_writer->writeText( text, indent ); - return *this; - } - - template - ScopedElement& writeAttribute( std::string const& name, T const& attribute ) { - m_writer->writeAttribute( name, attribute ); - return *this; - } - - private: - mutable XmlWriter* m_writer; - }; - - XmlWriter() - : m_tagIsOpen( false ), - m_needsNewline( false ), - m_os( &Catch::cout() ) - { - // We encode control characters, which requires - // XML 1.1 - // see http://stackoverflow.com/questions/404107/why-are-control-characters-illegal-in-xml-1-0 - *m_os << "\n"; - } - - XmlWriter( std::ostream& os ) - : m_tagIsOpen( false ), - m_needsNewline( false ), - m_os( &os ) - { - *m_os << "\n"; - } - - ~XmlWriter() { - while( !m_tags.empty() ) - endElement(); - } - - XmlWriter& startElement( std::string const& name ) { - ensureTagClosed(); - newlineIfNecessary(); - stream() << m_indent << "<" << name; - m_tags.push_back( name ); - m_indent += " "; - m_tagIsOpen = true; - return *this; - } - - ScopedElement scopedElement( std::string const& name ) { - ScopedElement scoped( this ); - startElement( name ); - return scoped; - } - - XmlWriter& endElement() { - newlineIfNecessary(); - m_indent = m_indent.substr( 0, m_indent.size()-2 ); - if( m_tagIsOpen ) { - stream() << "/>\n"; - m_tagIsOpen = false; - } - else { - stream() << m_indent << "\n"; - } - m_tags.pop_back(); - return *this; - } - - XmlWriter& writeAttribute( std::string const& name, std::string const& attribute ) { - if( !name.empty() && !attribute.empty() ) - stream() << " " << name << "=\"" << XmlEncode( attribute, XmlEncode::ForAttributes ) << "\""; - return *this; - } - - XmlWriter& writeAttribute( std::string const& name, bool attribute ) { - stream() << " " << name << "=\"" << ( attribute ? "true" : "false" ) << "\""; - return *this; - } - - template - XmlWriter& writeAttribute( std::string const& name, T const& attribute ) { - std::ostringstream oss; - oss << attribute; - return writeAttribute( name, oss.str() ); - } - - XmlWriter& writeText( std::string const& text, bool indent = true ) { - if( !text.empty() ){ - bool tagWasOpen = m_tagIsOpen; - ensureTagClosed(); - if( tagWasOpen && indent ) - stream() << m_indent; - stream() << XmlEncode( text ); - m_needsNewline = true; - } - return *this; - } - - XmlWriter& writeComment( std::string const& text ) { - ensureTagClosed(); - stream() << m_indent << ""; - m_needsNewline = true; - return *this; - } - - XmlWriter& writeBlankLine() { - ensureTagClosed(); - stream() << "\n"; - return *this; - } - - void setStream( std::ostream& os ) { - m_os = &os; - } - - private: - XmlWriter( XmlWriter const& ); - void operator=( XmlWriter const& ); - - std::ostream& stream() { - return *m_os; - } - - void ensureTagClosed() { - if( m_tagIsOpen ) { - stream() << ">\n"; - m_tagIsOpen = false; - } - } - - void newlineIfNecessary() { - if( m_needsNewline ) { - stream() << "\n"; - m_needsNewline = false; - } - } - - bool m_tagIsOpen; - bool m_needsNewline; - std::vector m_tags; - std::string m_indent; - std::ostream* m_os; - }; - -} -// #included from: catch_reenable_warnings.h - -#define TWOBLUECUBES_CATCH_REENABLE_WARNINGS_H_INCLUDED - -#ifdef __clang__ -# ifdef __ICC // icpc defines the __clang__ macro -# pragma warning(pop) -# else -# pragma clang diagnostic pop -# endif -#elif defined __GNUC__ -# pragma GCC diagnostic pop -#endif - - -namespace Catch { - class XmlReporter : public StreamingReporterBase { - public: - XmlReporter( ReporterConfig const& _config ) - : StreamingReporterBase( _config ), - m_xml(_config.stream()), - m_sectionDepth( 0 ) - { - m_reporterPrefs.shouldRedirectStdOut = true; - } - - virtual ~XmlReporter() CATCH_OVERRIDE; - - static std::string getDescription() { - return "Reports test results as an XML document"; - } - - public: // StreamingReporterBase - - virtual void noMatchingTestCases( std::string const& s ) CATCH_OVERRIDE { - StreamingReporterBase::noMatchingTestCases( s ); - } - - virtual void testRunStarting( TestRunInfo const& testInfo ) CATCH_OVERRIDE { - StreamingReporterBase::testRunStarting( testInfo ); - m_xml.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", testInfo.name ); - - if ( m_config->showDurations() == ShowDurations::Always ) - m_testCaseTimer.start(); - } - - virtual void sectionStarting( SectionInfo const& sectionInfo ) CATCH_OVERRIDE { - StreamingReporterBase::sectionStarting( sectionInfo ); - if( m_sectionDepth++ > 0 ) { - m_xml.startElement( "Section" ) - .writeAttribute( "name", trim( sectionInfo.name ) ) - .writeAttribute( "description", sectionInfo.description ); - } - } - - virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE { } - - virtual bool assertionEnded( AssertionStats const& assertionStats ) CATCH_OVERRIDE { - const AssertionResult& assertionResult = assertionStats.assertionResult; - - // Print any info messages in tags. - 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 ) { - m_xml.scopedElement( "Info" ) - .writeText( it->message ); - } else if ( it->type == ResultWas::Warning ) { - m_xml.scopedElement( "Warning" ) - .writeText( it->message ); - } - } - } - - // Drop out if result was successful but we're not printing them. - if( !m_config->includeSuccessfulResults() && isOk(assertionResult.getResultType()) ) - return true; - - // Print the expression if there is one. - if( assertionResult.hasExpression() ) { - m_xml.startElement( "Expression" ) - .writeAttribute( "success", assertionResult.succeeded() ) - .writeAttribute( "type", assertionResult.getTestMacroName() ) - .writeAttribute( "filename", assertionResult.getSourceInfo().file ) - .writeAttribute( "line", assertionResult.getSourceInfo().line ); - - m_xml.scopedElement( "Original" ) - .writeText( assertionResult.getExpression() ); - m_xml.scopedElement( "Expanded" ) - .writeText( assertionResult.getExpandedExpression() ); - } - - // And... Print a result applicable to each result type. - switch( assertionResult.getResultType() ) { - case ResultWas::ThrewException: - m_xml.scopedElement( "Exception" ) - .writeAttribute( "filename", assertionResult.getSourceInfo().file ) - .writeAttribute( "line", assertionResult.getSourceInfo().line ) - .writeText( assertionResult.getMessage() ); - break; - case ResultWas::FatalErrorCondition: - m_xml.scopedElement( "FatalErrorCondition" ) - .writeAttribute( "filename", assertionResult.getSourceInfo().file ) - .writeAttribute( "line", assertionResult.getSourceInfo().line ) - .writeText( assertionResult.getMessage() ); - break; - case ResultWas::Info: - m_xml.scopedElement( "Info" ) - .writeText( assertionResult.getMessage() ); - break; - case ResultWas::Warning: - // Warning will already have been written - break; - case ResultWas::ExplicitFailure: - m_xml.scopedElement( "Failure" ) - .writeText( assertionResult.getMessage() ); - break; - default: - break; - } - - if( assertionResult.hasExpression() ) - m_xml.endElement(); - - return true; - } - - virtual void sectionEnded( SectionStats const& sectionStats ) CATCH_OVERRIDE { - StreamingReporterBase::sectionEnded( sectionStats ); - if( --m_sectionDepth > 0 ) { - XmlWriter::ScopedElement e = m_xml.scopedElement( "OverallResults" ); - e.writeAttribute( "successes", sectionStats.assertions.passed ); - e.writeAttribute( "failures", sectionStats.assertions.failed ); - e.writeAttribute( "expectedFailures", sectionStats.assertions.failedButOk ); - - if ( m_config->showDurations() == ShowDurations::Always ) - e.writeAttribute( "durationInSeconds", sectionStats.durationInSeconds ); - - m_xml.endElement(); - } - } - - virtual void testCaseEnded( TestCaseStats const& testCaseStats ) CATCH_OVERRIDE { - StreamingReporterBase::testCaseEnded( testCaseStats ); - XmlWriter::ScopedElement e = m_xml.scopedElement( "OverallResult" ); - e.writeAttribute( "success", testCaseStats.totals.assertions.allOk() ); - - if ( m_config->showDurations() == ShowDurations::Always ) - e.writeAttribute( "durationInSeconds", m_testCaseTimer.getElapsedSeconds() ); - - m_xml.endElement(); - } - - virtual void testGroupEnded( TestGroupStats const& testGroupStats ) CATCH_OVERRIDE { - StreamingReporterBase::testGroupEnded( testGroupStats ); - // TODO: Check testGroupStats.aborting and act accordingly. - m_xml.scopedElement( "OverallResults" ) - .writeAttribute( "successes", testGroupStats.totals.assertions.passed ) - .writeAttribute( "failures", testGroupStats.totals.assertions.failed ) - .writeAttribute( "expectedFailures", testGroupStats.totals.assertions.failedButOk ); - m_xml.endElement(); - } - - virtual void testRunEnded( TestRunStats const& testRunStats ) CATCH_OVERRIDE { - StreamingReporterBase::testRunEnded( testRunStats ); - m_xml.scopedElement( "OverallResults" ) - .writeAttribute( "successes", testRunStats.totals.assertions.passed ) - .writeAttribute( "failures", testRunStats.totals.assertions.failed ) - .writeAttribute( "expectedFailures", testRunStats.totals.assertions.failedButOk ); - m_xml.endElement(); - } - - private: - Timer m_testCaseTimer; - XmlWriter m_xml; - int m_sectionDepth; - }; - - INTERNAL_CATCH_REGISTER_REPORTER( "xml", XmlReporter ) - -} // end namespace Catch - -// #included from: ../reporters/catch_reporter_junit.hpp -#define TWOBLUECUBES_CATCH_REPORTER_JUNIT_HPP_INCLUDED - -#include - -namespace Catch { - - class JunitReporter : public CumulativeReporterBase { - public: - JunitReporter( ReporterConfig const& _config ) - : CumulativeReporterBase( _config ), - xml( _config.stream() ) - { - m_reporterPrefs.shouldRedirectStdOut = true; - } - - virtual ~JunitReporter() CATCH_OVERRIDE; - - static std::string getDescription() { - return "Reports test results in an XML format that looks like Ant's junitreport target"; - } - - virtual void noMatchingTestCases( std::string const& /*spec*/ ) CATCH_OVERRIDE {} - - virtual void testRunStarting( TestRunInfo const& runInfo ) CATCH_OVERRIDE { - CumulativeReporterBase::testRunStarting( runInfo ); - xml.startElement( "testsuites" ); - } - - virtual void testGroupStarting( GroupInfo const& groupInfo ) CATCH_OVERRIDE { - suiteTimer.start(); - stdOutForSuite.str(""); - stdErrForSuite.str(""); - unexpectedExceptions = 0; - CumulativeReporterBase::testGroupStarting( groupInfo ); - } - - virtual bool assertionEnded( AssertionStats const& assertionStats ) CATCH_OVERRIDE { - if( assertionStats.assertionResult.getResultType() == ResultWas::ThrewException ) - unexpectedExceptions++; - return CumulativeReporterBase::assertionEnded( assertionStats ); - } - - virtual void testCaseEnded( TestCaseStats const& testCaseStats ) CATCH_OVERRIDE { - stdOutForSuite << testCaseStats.stdOut; - stdErrForSuite << testCaseStats.stdErr; - CumulativeReporterBase::testCaseEnded( testCaseStats ); - } - - virtual void testGroupEnded( TestGroupStats const& testGroupStats ) CATCH_OVERRIDE { - double suiteTime = suiteTimer.getElapsedSeconds(); - CumulativeReporterBase::testGroupEnded( testGroupStats ); - writeGroup( *m_testGroups.back(), suiteTime ); - } - - virtual void testRunEndedCumulative() CATCH_OVERRIDE { - xml.endElement(); - } - - void writeGroup( TestGroupNode const& groupNode, double suiteTime ) { - XmlWriter::ScopedElement e = xml.scopedElement( "testsuite" ); - TestGroupStats const& stats = groupNode.value; - xml.writeAttribute( "name", stats.groupInfo.name ); - xml.writeAttribute( "errors", unexpectedExceptions ); - xml.writeAttribute( "failures", stats.totals.assertions.failed-unexpectedExceptions ); - xml.writeAttribute( "tests", stats.totals.assertions.total() ); - xml.writeAttribute( "hostname", "tbd" ); // !TBD - if( m_config->showDurations() == ShowDurations::Never ) - xml.writeAttribute( "time", "" ); - else - xml.writeAttribute( "time", suiteTime ); - xml.writeAttribute( "timestamp", "tbd" ); // !TBD - - // Write test cases - for( TestGroupNode::ChildNodes::const_iterator - it = groupNode.children.begin(), itEnd = groupNode.children.end(); - it != itEnd; - ++it ) - writeTestCase( **it ); - - xml.scopedElement( "system-out" ).writeText( trim( stdOutForSuite.str() ), false ); - xml.scopedElement( "system-err" ).writeText( trim( stdErrForSuite.str() ), false ); - } - - void writeTestCase( TestCaseNode const& testCaseNode ) { - TestCaseStats const& stats = testCaseNode.value; - - // All test cases have exactly one section - which represents the - // test case itself. That section may have 0-n nested sections - assert( testCaseNode.children.size() == 1 ); - SectionNode const& rootSection = *testCaseNode.children.front(); - - std::string className = stats.testInfo.className; - - if( className.empty() ) { - if( rootSection.childSections.empty() ) - className = "global"; - } - writeSection( className, "", rootSection ); - } - - void writeSection( std::string const& className, - std::string const& rootName, - SectionNode const& sectionNode ) { - std::string name = trim( sectionNode.stats.sectionInfo.name ); - if( !rootName.empty() ) - name = rootName + "/" + name; - - if( !sectionNode.assertions.empty() || - !sectionNode.stdOut.empty() || - !sectionNode.stdErr.empty() ) { - XmlWriter::ScopedElement e = xml.scopedElement( "testcase" ); - if( className.empty() ) { - xml.writeAttribute( "classname", name ); - xml.writeAttribute( "name", "root" ); - } - else { - xml.writeAttribute( "classname", className ); - xml.writeAttribute( "name", name ); - } - xml.writeAttribute( "time", Catch::toString( sectionNode.stats.durationInSeconds ) ); - - writeAssertions( sectionNode ); - - if( !sectionNode.stdOut.empty() ) - xml.scopedElement( "system-out" ).writeText( trim( sectionNode.stdOut ), false ); - if( !sectionNode.stdErr.empty() ) - xml.scopedElement( "system-err" ).writeText( trim( sectionNode.stdErr ), false ); - } - for( SectionNode::ChildSections::const_iterator - it = sectionNode.childSections.begin(), - itEnd = sectionNode.childSections.end(); - it != itEnd; - ++it ) - if( className.empty() ) - writeSection( name, "", **it ); - else - writeSection( className, name, **it ); - } - - void writeAssertions( SectionNode const& sectionNode ) { - for( SectionNode::Assertions::const_iterator - it = sectionNode.assertions.begin(), itEnd = sectionNode.assertions.end(); - it != itEnd; - ++it ) - writeAssertion( *it ); - } - void writeAssertion( AssertionStats const& stats ) { - AssertionResult const& result = stats.assertionResult; - if( !result.isOk() ) { - std::string elementName; - switch( result.getResultType() ) { - case ResultWas::ThrewException: - case ResultWas::FatalErrorCondition: - elementName = "error"; - break; - case ResultWas::ExplicitFailure: - elementName = "failure"; - break; - case ResultWas::ExpressionFailed: - elementName = "failure"; - break; - case ResultWas::DidntThrowException: - elementName = "failure"; - break; - - // We should never see these here: - case ResultWas::Info: - case ResultWas::Warning: - case ResultWas::Ok: - case ResultWas::Unknown: - case ResultWas::FailureBit: - case ResultWas::Exception: - elementName = "internalError"; - break; - } - - XmlWriter::ScopedElement e = xml.scopedElement( elementName ); - - xml.writeAttribute( "message", result.getExpandedExpression() ); - xml.writeAttribute( "type", result.getTestMacroName() ); - - std::ostringstream oss; - if( !result.getMessage().empty() ) - oss << result.getMessage() << "\n"; - for( std::vector::const_iterator - it = stats.infoMessages.begin(), - itEnd = stats.infoMessages.end(); - it != itEnd; - ++it ) - if( it->type == ResultWas::Info ) - oss << it->message << "\n"; - - oss << "at " << result.getSourceInfo(); - xml.writeText( oss.str(), false ); - } - } - - XmlWriter xml; - Timer suiteTimer; - std::ostringstream stdOutForSuite; - std::ostringstream stdErrForSuite; - unsigned int unexpectedExceptions; - }; - - INTERNAL_CATCH_REGISTER_REPORTER( "junit", JunitReporter ) - -} // end namespace Catch - -// #included from: ../reporters/catch_reporter_console.hpp -#define TWOBLUECUBES_CATCH_REPORTER_CONSOLE_HPP_INCLUDED - -namespace Catch { - - struct ConsoleReporter : StreamingReporterBase { - ConsoleReporter( ReporterConfig const& _config ) - : StreamingReporterBase( _config ), - m_headerPrinted( false ) - {} - - virtual ~ConsoleReporter() CATCH_OVERRIDE; - static std::string getDescription() { - return "Reports test results as plain lines of text"; - } - - virtual void noMatchingTestCases( std::string const& spec ) CATCH_OVERRIDE { - stream << "No test cases matched '" << spec << "'" << std::endl; - } - - virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE { - } - - virtual bool assertionEnded( AssertionStats const& _assertionStats ) CATCH_OVERRIDE { - AssertionResult const& result = _assertionStats.assertionResult; - - bool printInfoMessages = true; - - // Drop out if result was successful and we're not printing those - if( !m_config->includeSuccessfulResults() && result.isOk() ) { - if( result.getResultType() != ResultWas::Warning ) - return false; - printInfoMessages = false; - } - - lazyPrint(); - - AssertionPrinter printer( stream, _assertionStats, printInfoMessages ); - printer.print(); - stream << std::endl; - return true; - } - - virtual void sectionStarting( SectionInfo const& _sectionInfo ) CATCH_OVERRIDE { - m_headerPrinted = false; - StreamingReporterBase::sectionStarting( _sectionInfo ); - } - virtual void sectionEnded( SectionStats const& _sectionStats ) CATCH_OVERRIDE { - if( _sectionStats.missingAssertions ) { - lazyPrint(); - Colour colour( Colour::ResultError ); - if( m_sectionStack.size() > 1 ) - stream << "\nNo assertions in section"; - else - stream << "\nNo assertions in test case"; - stream << " '" << _sectionStats.sectionInfo.name << "'\n" << std::endl; - } - if( m_headerPrinted ) { - if( m_config->showDurations() == ShowDurations::Always ) - stream << "Completed in " << _sectionStats.durationInSeconds << "s" << std::endl; - m_headerPrinted = false; - } - else { - if( m_config->showDurations() == ShowDurations::Always ) - stream << _sectionStats.sectionInfo.name << " completed in " << _sectionStats.durationInSeconds << "s" << std::endl; - } - StreamingReporterBase::sectionEnded( _sectionStats ); - } - - virtual void testCaseEnded( TestCaseStats const& _testCaseStats ) CATCH_OVERRIDE { - StreamingReporterBase::testCaseEnded( _testCaseStats ); - m_headerPrinted = false; - } - virtual void testGroupEnded( TestGroupStats const& _testGroupStats ) CATCH_OVERRIDE { - if( currentGroupInfo.used ) { - printSummaryDivider(); - stream << "Summary for group '" << _testGroupStats.groupInfo.name << "':\n"; - printTotals( _testGroupStats.totals ); - stream << "\n" << std::endl; - } - StreamingReporterBase::testGroupEnded( _testGroupStats ); - } - virtual void testRunEnded( TestRunStats const& _testRunStats ) CATCH_OVERRIDE { - printTotalsDivider( _testRunStats.totals ); - printTotals( _testRunStats.totals ); - stream << std::endl; - StreamingReporterBase::testRunEnded( _testRunStats ); - } - - private: - - class AssertionPrinter { - void operator= ( AssertionPrinter const& ); - public: - AssertionPrinter( std::ostream& _stream, AssertionStats const& _stats, bool _printInfoMessages ) - : stream( _stream ), - stats( _stats ), - result( _stats.assertionResult ), - colour( Colour::None ), - message( result.getMessage() ), - messages( _stats.infoMessages ), - printInfoMessages( _printInfoMessages ) - { - switch( result.getResultType() ) { - case ResultWas::Ok: - colour = Colour::Success; - passOrFail = "PASSED"; - //if( result.hasMessage() ) - if( _stats.infoMessages.size() == 1 ) - messageLabel = "with message"; - if( _stats.infoMessages.size() > 1 ) - messageLabel = "with messages"; - break; - case ResultWas::ExpressionFailed: - if( result.isOk() ) { - colour = Colour::Success; - passOrFail = "FAILED - but was ok"; - } - else { - colour = Colour::Error; - passOrFail = "FAILED"; - } - if( _stats.infoMessages.size() == 1 ) - messageLabel = "with message"; - if( _stats.infoMessages.size() > 1 ) - messageLabel = "with messages"; - break; - case ResultWas::ThrewException: - colour = Colour::Error; - passOrFail = "FAILED"; - messageLabel = "due to unexpected exception with message"; - break; - case ResultWas::FatalErrorCondition: - colour = Colour::Error; - passOrFail = "FAILED"; - messageLabel = "due to a fatal error condition"; - break; - case ResultWas::DidntThrowException: - colour = Colour::Error; - passOrFail = "FAILED"; - messageLabel = "because no exception was thrown where one was expected"; - break; - case ResultWas::Info: - messageLabel = "info"; - break; - case ResultWas::Warning: - messageLabel = "warning"; - break; - case ResultWas::ExplicitFailure: - passOrFail = "FAILED"; - colour = Colour::Error; - if( _stats.infoMessages.size() == 1 ) - messageLabel = "explicitly with message"; - if( _stats.infoMessages.size() > 1 ) - messageLabel = "explicitly with messages"; - break; - // These cases are here to prevent compiler warnings - case ResultWas::Unknown: - case ResultWas::FailureBit: - case ResultWas::Exception: - passOrFail = "** internal error **"; - colour = Colour::Error; - break; - } - } - - void print() const { - printSourceInfo(); - if( stats.totals.assertions.total() > 0 ) { - if( result.isOk() ) - stream << "\n"; - printResultType(); - printOriginalExpression(); - printReconstructedExpression(); - } - else { - stream << "\n"; - } - printMessage(); - } - - private: - void printResultType() const { - if( !passOrFail.empty() ) { - Colour colourGuard( colour ); - stream << passOrFail << ":\n"; - } - } - void printOriginalExpression() const { - if( result.hasExpression() ) { - Colour colourGuard( Colour::OriginalExpression ); - stream << " "; - stream << result.getExpressionInMacro(); - stream << "\n"; - } - } - void printReconstructedExpression() const { - if( result.hasExpandedExpression() ) { - stream << "with expansion:\n"; - Colour colourGuard( Colour::ReconstructedExpression ); - stream << Text( result.getExpandedExpression(), TextAttributes().setIndent(2) ) << "\n"; - } - } - void printMessage() const { - if( !messageLabel.empty() ) - stream << messageLabel << ":" << "\n"; - for( std::vector::const_iterator it = messages.begin(), itEnd = messages.end(); - it != itEnd; - ++it ) { - // If this assertion is a warning ignore any INFO messages - if( printInfoMessages || it->type != ResultWas::Info ) - stream << Text( it->message, TextAttributes().setIndent(2) ) << "\n"; - } - } - void printSourceInfo() const { - Colour colourGuard( Colour::FileName ); - stream << result.getSourceInfo() << ": "; - } - - std::ostream& stream; - AssertionStats const& stats; - AssertionResult const& result; - Colour::Code colour; - std::string passOrFail; - std::string messageLabel; - std::string message; - std::vector messages; - bool printInfoMessages; - }; - - void lazyPrint() { - - if( !currentTestRunInfo.used ) - lazyPrintRunInfo(); - if( !currentGroupInfo.used ) - lazyPrintGroupInfo(); - - if( !m_headerPrinted ) { - printTestCaseAndSectionHeader(); - m_headerPrinted = true; - } - } - void lazyPrintRunInfo() { - stream << "\n" << getLineOfChars<'~'>() << "\n"; - Colour colour( Colour::SecondaryText ); - stream << currentTestRunInfo->name - << " is a Catch v" << libraryVersion << " host application.\n" - << "Run with -? for options\n\n"; - - if( m_config->rngSeed() != 0 ) - stream << "Randomness seeded to: " << m_config->rngSeed() << "\n\n"; - - currentTestRunInfo.used = true; - } - void lazyPrintGroupInfo() { - if( !currentGroupInfo->name.empty() && currentGroupInfo->groupsCounts > 1 ) { - printClosedHeader( "Group: " + currentGroupInfo->name ); - currentGroupInfo.used = true; - } - } - void printTestCaseAndSectionHeader() { - assert( !m_sectionStack.empty() ); - printOpenHeader( currentTestCaseInfo->name ); - - if( m_sectionStack.size() > 1 ) { - Colour colourGuard( Colour::Headers ); - - std::vector::const_iterator - it = m_sectionStack.begin()+1, // Skip first section (test case) - itEnd = m_sectionStack.end(); - for( ; it != itEnd; ++it ) - printHeaderString( it->name, 2 ); - } - - SourceLineInfo lineInfo = m_sectionStack.front().lineInfo; - - if( !lineInfo.empty() ){ - stream << getLineOfChars<'-'>() << "\n"; - Colour colourGuard( Colour::FileName ); - stream << lineInfo << "\n"; - } - stream << getLineOfChars<'.'>() << "\n" << std::endl; - } - - void printClosedHeader( std::string const& _name ) { - printOpenHeader( _name ); - stream << getLineOfChars<'.'>() << "\n"; - } - void printOpenHeader( std::string const& _name ) { - stream << getLineOfChars<'-'>() << "\n"; - { - Colour colourGuard( Colour::Headers ); - printHeaderString( _name ); - } - } - - // if string has a : in first line will set indent to follow it on - // subsequent lines - void printHeaderString( std::string const& _string, std::size_t indent = 0 ) { - std::size_t i = _string.find( ": " ); - if( i != std::string::npos ) - i+=2; - else - i = 0; - stream << Text( _string, TextAttributes() - .setIndent( indent+i) - .setInitialIndent( indent ) ) << "\n"; - } - - struct SummaryColumn { - - SummaryColumn( std::string const& _label, Colour::Code _colour ) - : label( _label ), - colour( _colour ) - {} - SummaryColumn addRow( std::size_t count ) { - std::ostringstream oss; - oss << count; - std::string row = oss.str(); - for( std::vector::iterator it = rows.begin(); it != rows.end(); ++it ) { - while( it->size() < row.size() ) - *it = " " + *it; - while( it->size() > row.size() ) - row = " " + row; - } - rows.push_back( row ); - return *this; - } - - std::string label; - Colour::Code colour; - std::vector rows; - - }; - - void printTotals( Totals const& totals ) { - if( totals.testCases.total() == 0 ) { - stream << Colour( Colour::Warning ) << "No tests ran\n"; - } - else if( totals.assertions.total() > 0 && totals.testCases.allPassed() ) { - stream << Colour( Colour::ResultSuccess ) << "All tests passed"; - stream << " (" - << pluralise( totals.assertions.passed, "assertion" ) << " in " - << pluralise( totals.testCases.passed, "test case" ) << ")" - << "\n"; - } - else { - - std::vector columns; - columns.push_back( SummaryColumn( "", Colour::None ) - .addRow( totals.testCases.total() ) - .addRow( totals.assertions.total() ) ); - columns.push_back( SummaryColumn( "passed", Colour::Success ) - .addRow( totals.testCases.passed ) - .addRow( totals.assertions.passed ) ); - columns.push_back( SummaryColumn( "failed", Colour::ResultError ) - .addRow( totals.testCases.failed ) - .addRow( totals.assertions.failed ) ); - columns.push_back( SummaryColumn( "failed as expected", Colour::ResultExpectedFailure ) - .addRow( totals.testCases.failedButOk ) - .addRow( totals.assertions.failedButOk ) ); - - printSummaryRow( "test cases", columns, 0 ); - printSummaryRow( "assertions", columns, 1 ); - } - } - void printSummaryRow( std::string const& label, std::vector const& cols, std::size_t row ) { - for( std::vector::const_iterator it = cols.begin(); it != cols.end(); ++it ) { - std::string value = it->rows[row]; - if( it->label.empty() ) { - stream << label << ": "; - if( value != "0" ) - stream << value; - else - stream << Colour( Colour::Warning ) << "- none -"; - } - else if( value != "0" ) { - stream << Colour( Colour::LightGrey ) << " | "; - stream << Colour( it->colour ) - << value << " " << it->label; - } - } - stream << "\n"; - } - - static std::size_t makeRatio( std::size_t number, std::size_t total ) { - std::size_t ratio = total > 0 ? CATCH_CONFIG_CONSOLE_WIDTH * number/ total : 0; - return ( ratio == 0 && number > 0 ) ? 1 : ratio; - } - static std::size_t& findMax( std::size_t& i, std::size_t& j, std::size_t& k ) { - if( i > j && i > k ) - return i; - else if( j > k ) - return j; - else - return k; - } - - void printTotalsDivider( Totals const& totals ) { - if( totals.testCases.total() > 0 ) { - std::size_t failedRatio = makeRatio( totals.testCases.failed, totals.testCases.total() ); - std::size_t failedButOkRatio = makeRatio( totals.testCases.failedButOk, totals.testCases.total() ); - std::size_t passedRatio = makeRatio( totals.testCases.passed, totals.testCases.total() ); - while( failedRatio + failedButOkRatio + passedRatio < CATCH_CONFIG_CONSOLE_WIDTH-1 ) - findMax( failedRatio, failedButOkRatio, passedRatio )++; - while( failedRatio + failedButOkRatio + passedRatio > CATCH_CONFIG_CONSOLE_WIDTH-1 ) - findMax( failedRatio, failedButOkRatio, passedRatio )--; - - stream << Colour( Colour::Error ) << std::string( failedRatio, '=' ); - stream << Colour( Colour::ResultExpectedFailure ) << std::string( failedButOkRatio, '=' ); - if( totals.testCases.allPassed() ) - stream << Colour( Colour::ResultSuccess ) << std::string( passedRatio, '=' ); - else - stream << Colour( Colour::Success ) << std::string( passedRatio, '=' ); - } - else { - stream << Colour( Colour::Warning ) << std::string( CATCH_CONFIG_CONSOLE_WIDTH-1, '=' ); - } - stream << "\n"; - } - void printSummaryDivider() { - stream << getLineOfChars<'-'>() << "\n"; - } - - private: - bool m_headerPrinted; - }; - - INTERNAL_CATCH_REGISTER_REPORTER( "console", ConsoleReporter ) - -} // end namespace Catch - -// #included from: ../reporters/catch_reporter_compact.hpp -#define TWOBLUECUBES_CATCH_REPORTER_COMPACT_HPP_INCLUDED - -namespace Catch { - - struct CompactReporter : StreamingReporterBase { - - CompactReporter( ReporterConfig const& _config ) - : StreamingReporterBase( _config ) - {} - - virtual ~CompactReporter(); - - static std::string getDescription() { - return "Reports test results on a single line, suitable for IDEs"; - } - - virtual ReporterPreferences getPreferences() const { - ReporterPreferences prefs; - prefs.shouldRedirectStdOut = false; - return prefs; - } - - virtual void noMatchingTestCases( std::string const& spec ) { - stream << "No test cases matched '" << spec << "'" << std::endl; - } - - virtual void assertionStarting( AssertionInfo const& ) { - } - - virtual bool assertionEnded( AssertionStats const& _assertionStats ) { - AssertionResult const& result = _assertionStats.assertionResult; - - bool printInfoMessages = true; - - // Drop out if result was successful and we're not printing those - if( !m_config->includeSuccessfulResults() && result.isOk() ) { - if( result.getResultType() != ResultWas::Warning ) - return false; - printInfoMessages = false; - } - - AssertionPrinter printer( stream, _assertionStats, printInfoMessages ); - printer.print(); - - stream << std::endl; - return true; - } - - virtual void testRunEnded( TestRunStats const& _testRunStats ) { - printTotals( _testRunStats.totals ); - stream << "\n" << std::endl; - StreamingReporterBase::testRunEnded( _testRunStats ); - } - - private: - class AssertionPrinter { - void operator= ( AssertionPrinter const& ); - public: - AssertionPrinter( std::ostream& _stream, AssertionStats const& _stats, bool _printInfoMessages ) - : stream( _stream ) - , stats( _stats ) - , result( _stats.assertionResult ) - , messages( _stats.infoMessages ) - , itMessage( _stats.infoMessages.begin() ) - , printInfoMessages( _printInfoMessages ) - {} - - void print() { - printSourceInfo(); - - itMessage = messages.begin(); - - switch( result.getResultType() ) { - case ResultWas::Ok: - printResultType( Colour::ResultSuccess, passedString() ); - printOriginalExpression(); - printReconstructedExpression(); - if ( ! result.hasExpression() ) - printRemainingMessages( Colour::None ); - else - printRemainingMessages(); - break; - case ResultWas::ExpressionFailed: - if( result.isOk() ) - printResultType( Colour::ResultSuccess, failedString() + std::string( " - but was ok" ) ); - else - printResultType( Colour::Error, failedString() ); - printOriginalExpression(); - printReconstructedExpression(); - printRemainingMessages(); - break; - case ResultWas::ThrewException: - printResultType( Colour::Error, failedString() ); - printIssue( "unexpected exception with message:" ); - printMessage(); - printExpressionWas(); - printRemainingMessages(); - break; - case ResultWas::FatalErrorCondition: - printResultType( Colour::Error, failedString() ); - printIssue( "fatal error condition with message:" ); - printMessage(); - printExpressionWas(); - printRemainingMessages(); - break; - case ResultWas::DidntThrowException: - printResultType( Colour::Error, failedString() ); - printIssue( "expected exception, got none" ); - printExpressionWas(); - printRemainingMessages(); - break; - case ResultWas::Info: - printResultType( Colour::None, "info" ); - printMessage(); - printRemainingMessages(); - break; - case ResultWas::Warning: - printResultType( Colour::None, "warning" ); - printMessage(); - printRemainingMessages(); - break; - case ResultWas::ExplicitFailure: - printResultType( Colour::Error, failedString() ); - printIssue( "explicitly" ); - printRemainingMessages( Colour::None ); - break; - // These cases are here to prevent compiler warnings - case ResultWas::Unknown: - case ResultWas::FailureBit: - case ResultWas::Exception: - printResultType( Colour::Error, "** internal error **" ); - break; - } - } - - private: - // Colour::LightGrey - - static Colour::Code dimColour() { return Colour::FileName; } - -#ifdef CATCH_PLATFORM_MAC - static const char* failedString() { return "FAILED"; } - static const char* passedString() { return "PASSED"; } -#else - static const char* failedString() { return "failed"; } - static const char* passedString() { return "passed"; } -#endif - - void printSourceInfo() const { - Colour colourGuard( Colour::FileName ); - stream << result.getSourceInfo() << ":"; - } - - void printResultType( Colour::Code colour, std::string passOrFail ) const { - if( !passOrFail.empty() ) { - { - Colour colourGuard( colour ); - stream << " " << passOrFail; - } - stream << ":"; - } - } - - void printIssue( std::string issue ) const { - stream << " " << issue; - } - - void printExpressionWas() { - if( result.hasExpression() ) { - stream << ";"; - { - Colour colour( dimColour() ); - stream << " expression was:"; - } - printOriginalExpression(); - } - } - - void printOriginalExpression() const { - if( result.hasExpression() ) { - stream << " " << result.getExpression(); - } - } - - void printReconstructedExpression() const { - if( result.hasExpandedExpression() ) { - { - Colour colour( dimColour() ); - stream << " for: "; - } - stream << result.getExpandedExpression(); - } - } - - void printMessage() { - if ( itMessage != messages.end() ) { - stream << " '" << itMessage->message << "'"; - ++itMessage; - } - } - - void printRemainingMessages( Colour::Code colour = dimColour() ) { - if ( itMessage == messages.end() ) - return; - - // using messages.end() directly yields compilation error: - std::vector::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 ? "" : count == 2 ? "both " : "all " ; - } - - void printTotals( const Totals& totals ) const { - if( totals.testCases.total() == 0 ) { - stream << "No tests ran."; - } - else if( totals.testCases.failed == totals.testCases.total() ) { - Colour colour( Colour::ResultError ); - const std::string qualify_assertions_failed = - totals.assertions.failed == totals.assertions.total() ? - bothOrAll( totals.assertions.failed ) : ""; - stream << - "Failed " << bothOrAll( totals.testCases.failed ) - << pluralise( totals.testCases.failed, "test case" ) << ", " - "failed " << qualify_assertions_failed << - pluralise( totals.assertions.failed, "assertion" ) << "."; - } - else if( totals.assertions.total() == 0 ) { - stream << - "Passed " << bothOrAll( totals.testCases.total() ) - << pluralise( totals.testCases.total(), "test case" ) - << " (no assertions)."; - } - else if( totals.assertions.failed ) { - Colour colour( Colour::ResultError ); - stream << - "Failed " << pluralise( totals.testCases.failed, "test case" ) << ", " - "failed " << pluralise( totals.assertions.failed, "assertion" ) << "."; - } - else { - Colour colour( Colour::ResultSuccess ); - stream << - "Passed " << bothOrAll( totals.testCases.passed ) - << pluralise( totals.testCases.passed, "test case" ) << - " with " << pluralise( totals.assertions.passed, "assertion" ) << "."; - } - } - }; - - INTERNAL_CATCH_REGISTER_REPORTER( "compact", CompactReporter ) - -} // end namespace Catch - -namespace Catch { - // These are all here to avoid warnings about not having any out of line - // virtual methods - NonCopyable::~NonCopyable() {} - IShared::~IShared() {} - IStream::~IStream() CATCH_NOEXCEPT {} - FileStream::~FileStream() CATCH_NOEXCEPT {} - CoutStream::~CoutStream() CATCH_NOEXCEPT {} - DebugOutStream::~DebugOutStream() CATCH_NOEXCEPT {} - StreamBufBase::~StreamBufBase() CATCH_NOEXCEPT {} - IContext::~IContext() {} - IResultCapture::~IResultCapture() {} - ITestCase::~ITestCase() {} - ITestCaseRegistry::~ITestCaseRegistry() {} - IRegistryHub::~IRegistryHub() {} - IMutableRegistryHub::~IMutableRegistryHub() {} - IExceptionTranslator::~IExceptionTranslator() {} - IExceptionTranslatorRegistry::~IExceptionTranslatorRegistry() {} - IReporter::~IReporter() {} - IReporterFactory::~IReporterFactory() {} - IReporterRegistry::~IReporterRegistry() {} - IStreamingReporter::~IStreamingReporter() {} - AssertionStats::~AssertionStats() {} - SectionStats::~SectionStats() {} - TestCaseStats::~TestCaseStats() {} - TestGroupStats::~TestGroupStats() {} - TestRunStats::~TestRunStats() {} - CumulativeReporterBase::SectionNode::~SectionNode() {} - CumulativeReporterBase::~CumulativeReporterBase() {} - - StreamingReporterBase::~StreamingReporterBase() {} - ConsoleReporter::~ConsoleReporter() {} - CompactReporter::~CompactReporter() {} - IRunner::~IRunner() {} - IMutableContext::~IMutableContext() {} - IConfig::~IConfig() {} - XmlReporter::~XmlReporter() {} - JunitReporter::~JunitReporter() {} - TestRegistry::~TestRegistry() {} - FreeFunctionTestCase::~FreeFunctionTestCase() {} - IGeneratorInfo::~IGeneratorInfo() {} - IGeneratorsForTest::~IGeneratorsForTest() {} - WildcardPattern::~WildcardPattern() {} - TestSpec::Pattern::~Pattern() {} - TestSpec::NamePattern::~NamePattern() {} - TestSpec::TagPattern::~TagPattern() {} - TestSpec::ExcludedPattern::~ExcludedPattern() {} - - Matchers::Impl::StdString::Equals::~Equals() {} - Matchers::Impl::StdString::Contains::~Contains() {} - Matchers::Impl::StdString::StartsWith::~StartsWith() {} - Matchers::Impl::StdString::EndsWith::~EndsWith() {} - - void Config::dummy() {} - - namespace TestCaseTracking { - ITracker::~ITracker() {} - TrackerBase::~TrackerBase() {} - SectionTracker::~SectionTracker() {} - IndexTracker::~IndexTracker() {} - } -} - -#ifdef __clang__ -#pragma clang diagnostic pop -#endif - -#endif - -#ifdef CATCH_CONFIG_MAIN -// #included from: internal/catch_default_main.hpp -#define TWOBLUECUBES_CATCH_DEFAULT_MAIN_HPP_INCLUDED - -#ifndef __OBJC__ - -// Standard C/C++ main entry point -int main (int argc, char * argv[]) { - return Catch::Session().run( argc, argv ); -} - -#else // __OBJC__ - -// Objective-C entry point -int main (int argc, char * const argv[]) { -#if !CATCH_ARC_ENABLED - NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; -#endif - - Catch::registerTestMethods(); - int result = Catch::Session().run( argc, (char* const*)argv ); - -#if !CATCH_ARC_ENABLED - [pool drain]; -#endif - - return result; -} - -#endif // __OBJC__ - -#endif - -#ifdef CLARA_CONFIG_MAIN_NOT_DEFINED -# undef CLARA_CONFIG_MAIN -#endif - -////// - -// If this config identifier is defined then all CATCH macros are prefixed with CATCH_ -#ifdef CATCH_CONFIG_PREFIX_ALL - -#define CATCH_REQUIRE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal, "CATCH_REQUIRE" ) -#define CATCH_REQUIRE_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, "CATCH_REQUIRE_FALSE" ) - -#define CATCH_REQUIRE_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::Normal, "", "CATCH_REQUIRE_THROWS" ) -#define CATCH_REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_THROWS_AS" ) -#define CATCH_REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::Normal, matcher, "CATCH_REQUIRE_THROWS_WITH" ) -#define CATCH_REQUIRE_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_NOTHROW" ) - -#define CATCH_CHECK( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK" ) -#define CATCH_CHECK_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::FalseTest, "CATCH_CHECK_FALSE" ) -#define CATCH_CHECKED_IF( expr ) INTERNAL_CATCH_IF( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECKED_IF" ) -#define CATCH_CHECKED_ELSE( expr ) INTERNAL_CATCH_ELSE( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECKED_ELSE" ) -#define CATCH_CHECK_NOFAIL( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, "CATCH_CHECK_NOFAIL" ) - -#define CATCH_CHECK_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::ContinueOnFailure, "", "CATCH_CHECK_THROWS" ) -#define CATCH_CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_THROWS_AS" ) -#define CATCH_CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::ContinueOnFailure, matcher, "CATCH_CHECK_THROWS_WITH" ) -#define CATCH_CHECK_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_NOTHROW" ) - -#define CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_THAT" ) -#define CATCH_REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_THAT" ) - -#define CATCH_INFO( msg ) INTERNAL_CATCH_INFO( msg, "CATCH_INFO" ) -#define CATCH_WARN( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, "CATCH_WARN", msg ) -#define CATCH_SCOPED_INFO( msg ) INTERNAL_CATCH_INFO( msg, "CATCH_INFO" ) -#define CATCH_CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CATCH_CAPTURE" ) -#define CATCH_SCOPED_CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CATCH_CAPTURE" ) - -#ifdef CATCH_CONFIG_VARIADIC_MACROS - #define CATCH_TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ ) - #define CATCH_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ ) - #define CATCH_METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ ) - #define CATCH_REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ ) - #define CATCH_SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ ) - #define CATCH_FAIL( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "CATCH_FAIL", __VA_ARGS__ ) - #define CATCH_SUCCEED( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "CATCH_SUCCEED", __VA_ARGS__ ) -#else - #define CATCH_TEST_CASE( name, description ) INTERNAL_CATCH_TESTCASE( name, description ) - #define CATCH_TEST_CASE_METHOD( className, name, description ) INTERNAL_CATCH_TEST_CASE_METHOD( className, name, description ) - #define CATCH_METHOD_AS_TEST_CASE( method, name, description ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, name, description ) - #define CATCH_REGISTER_TEST_CASE( function, name, description ) INTERNAL_CATCH_REGISTER_TESTCASE( function, name, description ) - #define CATCH_SECTION( name, description ) INTERNAL_CATCH_SECTION( name, description ) - #define CATCH_FAIL( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "CATCH_FAIL", msg ) - #define CATCH_SUCCEED( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "CATCH_SUCCEED", msg ) -#endif -#define CATCH_ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE( "", "" ) - -#define CATCH_REGISTER_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType ) -#define CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) - -#define CATCH_GENERATE( expr) INTERNAL_CATCH_GENERATE( expr ) - -// "BDD-style" convenience wrappers -#ifdef CATCH_CONFIG_VARIADIC_MACROS -#define CATCH_SCENARIO( ... ) CATCH_TEST_CASE( "Scenario: " __VA_ARGS__ ) -#define CATCH_SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ ) -#else -#define CATCH_SCENARIO( name, tags ) CATCH_TEST_CASE( "Scenario: " name, tags ) -#define CATCH_SCENARIO_METHOD( className, name, tags ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " name, tags ) -#endif -#define CATCH_GIVEN( desc ) CATCH_SECTION( std::string( "Given: ") + desc, "" ) -#define CATCH_WHEN( desc ) CATCH_SECTION( std::string( " When: ") + desc, "" ) -#define CATCH_AND_WHEN( desc ) CATCH_SECTION( std::string( " And: ") + desc, "" ) -#define CATCH_THEN( desc ) CATCH_SECTION( std::string( " Then: ") + desc, "" ) -#define CATCH_AND_THEN( desc ) CATCH_SECTION( std::string( " And: ") + desc, "" ) - -// If CATCH_CONFIG_PREFIX_ALL is not defined then the CATCH_ prefix is not required -#else - -#define REQUIRE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal, "REQUIRE" ) -#define REQUIRE_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, "REQUIRE_FALSE" ) - -#define REQUIRE_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::Normal, "", "REQUIRE_THROWS" ) -#define REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::Normal, "REQUIRE_THROWS_AS" ) -#define REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::Normal, matcher, "REQUIRE_THROWS_WITH" ) -#define REQUIRE_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::Normal, "REQUIRE_NOTHROW" ) - -#define CHECK( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECK" ) -#define CHECK_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::FalseTest, "CHECK_FALSE" ) -#define CHECKED_IF( expr ) INTERNAL_CATCH_IF( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECKED_IF" ) -#define CHECKED_ELSE( expr ) INTERNAL_CATCH_ELSE( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECKED_ELSE" ) -#define CHECK_NOFAIL( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, "CHECK_NOFAIL" ) - -#define CHECK_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::ContinueOnFailure, "", "CHECK_THROWS" ) -#define CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::ContinueOnFailure, "CHECK_THROWS_AS" ) -#define CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::ContinueOnFailure, matcher, "CHECK_THROWS_WITH" ) -#define CHECK_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECK_NOTHROW" ) - -#define CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::ContinueOnFailure, "CHECK_THAT" ) -#define REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::Normal, "REQUIRE_THAT" ) - -#define INFO( msg ) INTERNAL_CATCH_INFO( msg, "INFO" ) -#define WARN( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, "WARN", msg ) -#define SCOPED_INFO( msg ) INTERNAL_CATCH_INFO( msg, "INFO" ) -#define CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CAPTURE" ) -#define SCOPED_CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CAPTURE" ) - -#ifdef CATCH_CONFIG_VARIADIC_MACROS - #define TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ ) - #define TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ ) - #define METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ ) - #define REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ ) - #define SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ ) - #define FAIL( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "FAIL", __VA_ARGS__ ) - #define SUCCEED( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "SUCCEED", __VA_ARGS__ ) -#else - #define TEST_CASE( name, description ) INTERNAL_CATCH_TESTCASE( name, description ) - #define TEST_CASE_METHOD( className, name, description ) INTERNAL_CATCH_TEST_CASE_METHOD( className, name, description ) - #define METHOD_AS_TEST_CASE( method, name, description ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, name, description ) - #define REGISTER_TEST_CASE( method, name, description ) INTERNAL_CATCH_REGISTER_TESTCASE( method, name, description ) - #define SECTION( name, description ) INTERNAL_CATCH_SECTION( name, description ) - #define FAIL( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "FAIL", msg ) - #define SUCCEED( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "SUCCEED", msg ) -#endif -#define ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE( "", "" ) - -#define REGISTER_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType ) -#define REGISTER_LEGACY_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) - -#define GENERATE( expr) INTERNAL_CATCH_GENERATE( expr ) - -#endif - -#define CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) - -// "BDD-style" convenience wrappers -#ifdef CATCH_CONFIG_VARIADIC_MACROS -#define SCENARIO( ... ) TEST_CASE( "Scenario: " __VA_ARGS__ ) -#define SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ ) -#else -#define SCENARIO( name, tags ) TEST_CASE( "Scenario: " name, tags ) -#define SCENARIO_METHOD( className, name, tags ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " name, tags ) -#endif -#define GIVEN( desc ) SECTION( std::string(" Given: ") + desc, "" ) -#define WHEN( desc ) SECTION( std::string(" When: ") + desc, "" ) -#define AND_WHEN( desc ) SECTION( std::string("And when: ") + desc, "" ) -#define THEN( desc ) SECTION( std::string(" Then: ") + desc, "" ) -#define AND_THEN( desc ) SECTION( std::string(" And: ") + desc, "" ) - -using Catch::Detail::Approx; - -#endif // TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED - +/* + * Catch v1.7.0 + * Generated: 2017-02-01 21:32:13.239291 + * ---------------------------------------------------------- + * This file has been merged from multiple headers. Please don't edit it directly + * Copyright (c) 2012 Two Blue Cubes Ltd. All rights reserved. + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + */ +#ifndef TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED +#define TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED + +#define TWOBLUECUBES_CATCH_HPP_INCLUDED + +#ifdef __clang__ +# pragma clang system_header +#elif defined __GNUC__ +# pragma GCC system_header +#endif + +// #included from: internal/catch_suppress_warnings.h + +#ifdef __clang__ +# ifdef __ICC // icpc defines the __clang__ macro +# pragma warning(push) +# pragma warning(disable: 161 1682) +# else // __ICC +# pragma clang diagnostic ignored "-Wglobal-constructors" +# pragma clang diagnostic ignored "-Wvariadic-macros" +# pragma clang diagnostic ignored "-Wc99-extensions" +# pragma clang diagnostic ignored "-Wunused-variable" +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wpadded" +# pragma clang diagnostic ignored "-Wc++98-compat" +# pragma clang diagnostic ignored "-Wc++98-compat-pedantic" +# pragma clang diagnostic ignored "-Wswitch-enum" +# pragma clang diagnostic ignored "-Wcovered-switch-default" +# endif +#elif defined __GNUC__ +# pragma GCC diagnostic ignored "-Wvariadic-macros" +# pragma GCC diagnostic ignored "-Wunused-variable" +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wpadded" +#endif +#if defined(CATCH_CONFIG_MAIN) || defined(CATCH_CONFIG_RUNNER) +# define CATCH_IMPL +#endif + +#ifdef CATCH_IMPL +# ifndef CLARA_CONFIG_MAIN +# define CLARA_CONFIG_MAIN_NOT_DEFINED +# define CLARA_CONFIG_MAIN +# endif +#endif + +// #included from: internal/catch_notimplemented_exception.h +#define TWOBLUECUBES_CATCH_NOTIMPLEMENTED_EXCEPTION_H_INCLUDED + +// #included from: catch_common.h +#define TWOBLUECUBES_CATCH_COMMON_H_INCLUDED + +// #included from: catch_compiler_capabilities.h +#define TWOBLUECUBES_CATCH_COMPILER_CAPABILITIES_HPP_INCLUDED + +// Detect a number of compiler features - mostly C++11/14 conformance - by compiler +// The following features are defined: +// +// CATCH_CONFIG_CPP11_NULLPTR : is nullptr supported? +// CATCH_CONFIG_CPP11_NOEXCEPT : is noexcept supported? +// CATCH_CONFIG_CPP11_GENERATED_METHODS : The delete and default keywords for compiler generated methods +// CATCH_CONFIG_CPP11_IS_ENUM : std::is_enum is supported? +// CATCH_CONFIG_CPP11_TUPLE : std::tuple is supported +// CATCH_CONFIG_CPP11_LONG_LONG : is long long supported? +// CATCH_CONFIG_CPP11_OVERRIDE : is override supported? +// CATCH_CONFIG_CPP11_UNIQUE_PTR : is unique_ptr supported (otherwise use auto_ptr) +// CATCH_CONFIG_CPP11_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? +// **************** +// Note to maintainers: if new toggles are added please document them +// in configuration.md, too +// **************** + +// In general each macro has a _NO_ form +// (e.g. CATCH_CONFIG_CPP11_NO_NULLPTR) which disables the feature. +// Many features, at point of detection, define an _INTERNAL_ macro, so they +// can be combined, en-mass, with the _NO_ forms later. + +// All the C++11 features can be disabled with CATCH_CONFIG_NO_CPP11 + +#ifdef __cplusplus + +# if __cplusplus >= 201103L +# define CATCH_CPP11_OR_GREATER +# endif + +# if __cplusplus >= 201402L +# define CATCH_CPP14_OR_GREATER +# endif + +#endif + +#ifdef __clang__ + +# if __has_feature(cxx_nullptr) +# define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR +# endif + +# if __has_feature(cxx_noexcept) +# define CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT +# endif + +# if defined(CATCH_CPP11_OR_GREATER) +# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS _Pragma( "clang diagnostic ignored \"-Wparentheses\"" ) +# endif + +#endif // __clang__ + +//////////////////////////////////////////////////////////////////////////////// +// Borland +#ifdef __BORLANDC__ + +#endif // __BORLANDC__ + +//////////////////////////////////////////////////////////////////////////////// +// EDG +#ifdef __EDG_VERSION__ + +#endif // __EDG_VERSION__ + +//////////////////////////////////////////////////////////////////////////////// +// Digital Mars +#ifdef __DMC__ + +#endif // __DMC__ + +//////////////////////////////////////////////////////////////////////////////// +// GCC +#ifdef __GNUC__ + +# if __GNUC__ == 4 && __GNUC_MINOR__ >= 6 && defined(__GXX_EXPERIMENTAL_CXX0X__) +# define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR +# endif + +# if !defined(CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS) && defined(CATCH_CPP11_OR_GREATER) +# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS _Pragma( "GCC diagnostic ignored \"-Wparentheses\"" ) +# endif + +// - otherwise more recent versions define __cplusplus >= 201103L +// and will get picked up below + +#endif // __GNUC__ + +//////////////////////////////////////////////////////////////////////////////// +// Visual C++ +#ifdef _MSC_VER + +#if (_MSC_VER >= 1600) +# define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR +# define CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR +#endif + +#if (_MSC_VER >= 1900 ) // (VC++ 13 (VS2015)) +#define CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT +#define CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS +#define CATCH_INTERNAL_CONFIG_CPP11_SHUFFLE +#define CATCH_INTERNAL_CONFIG_CPP11_TYPE_TRAITS +#endif + +#endif // _MSC_VER + +//////////////////////////////////////////////////////////////////////////////// + +// Use variadic macros if the compiler supports them +#if ( defined _MSC_VER && _MSC_VER > 1400 && !defined __EDGE__) || \ + ( defined __WAVE__ && __WAVE_HAS_VARIADICS ) || \ + ( defined __GNUC__ && __GNUC__ >= 3 ) || \ + ( !defined __cplusplus && __STDC_VERSION__ >= 199901L || __cplusplus >= 201103L ) + +#define CATCH_INTERNAL_CONFIG_VARIADIC_MACROS + +#endif + +// Use __COUNTER__ if the compiler supports it +#if ( defined _MSC_VER && _MSC_VER >= 1300 ) || \ + ( defined __GNUC__ && __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_SUPPRESS_PARENTHESES_WARNINGS) +# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS +#endif + +// noexcept support: +#if defined(CATCH_CONFIG_CPP11_NOEXCEPT) && !defined(CATCH_NOEXCEPT) +# define CATCH_NOEXCEPT noexcept +# define CATCH_NOEXCEPT_IS(x) noexcept(x) +#else +# define CATCH_NOEXCEPT throw() +# define CATCH_NOEXCEPT_IS(x) +#endif + +// nullptr support +#ifdef CATCH_CONFIG_CPP11_NULLPTR +# define CATCH_NULL nullptr +#else +# define CATCH_NULL NULL +#endif + +// override support +#ifdef CATCH_CONFIG_CPP11_OVERRIDE +# define CATCH_OVERRIDE override +#else +# define CATCH_OVERRIDE +#endif + +// unique_ptr support +#ifdef CATCH_CONFIG_CPP11_UNIQUE_PTR +# define CATCH_AUTO_PTR( T ) std::unique_ptr +#else +# define CATCH_AUTO_PTR( T ) std::auto_ptr +#endif + +#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 +# define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __COUNTER__ ) +#else +# 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 + +namespace Catch { + + struct IConfig; + + struct CaseSensitive { enum Choice { + Yes, + No + }; }; + + class NonCopyable { +#ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS + NonCopyable( NonCopyable const& ) = delete; + NonCopyable( NonCopyable && ) = delete; + NonCopyable& operator = ( NonCopyable const& ) = delete; + NonCopyable& operator = ( NonCopyable && ) = delete; +#else + NonCopyable( NonCopyable const& info ); + NonCopyable& operator = ( NonCopyable const& ); +#endif + + protected: + NonCopyable() {} + virtual ~NonCopyable(); + }; + + class SafeBool { + public: + typedef void (SafeBool::*type)() const; + + static type makeSafe( bool value ) { + return value ? &SafeBool::trueValue : 0; + } + private: + void trueValue() const {} + }; + + template + inline void deleteAll( ContainerT& container ) { + typename ContainerT::const_iterator it = container.begin(); + typename ContainerT::const_iterator itEnd = container.end(); + for(; it != itEnd; ++it ) + delete *it; + } + template + inline void deleteAllValues( AssociativeContainerT& container ) { + typename AssociativeContainerT::const_iterator it = container.begin(); + typename AssociativeContainerT::const_iterator itEnd = container.end(); + for(; it != itEnd; ++it ) + delete it->second; + } + + 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 ); + 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( 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; + + char const* file; + std::size_t line; + }; + + std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info ); + + // This is just here to avoid compiler warnings with macro constants and boolean literals + inline bool isTrue( bool value ){ return value; } + inline bool alwaysTrue() { return true; } + inline bool alwaysFalse() { return false; } + + void throwLogicError( std::string const& message, SourceLineInfo const& locationInfo ); + + void seedRng( IConfig const& config ); + unsigned int rngSeed(); + + // Use this in variadic streaming macros to allow + // >> +StreamEndStop + // as well as + // >> stuff +StreamEndStop + struct StreamEndStop { + std::string operator+() { + return std::string(); + } + }; + template + T const& operator + ( T const& value, StreamEndStop ) { + return value; + } +} + +#define CATCH_INTERNAL_LINEINFO ::Catch::SourceLineInfo( __FILE__, static_cast( __LINE__ ) ) +#define CATCH_INTERNAL_ERROR( msg ) ::Catch::throwLogicError( msg, CATCH_INTERNAL_LINEINFO ); + +#include + +namespace Catch { + + class NotImplementedException : public std::exception + { + public: + NotImplementedException( SourceLineInfo const& lineInfo ); + NotImplementedException( NotImplementedException const& ) {} + + virtual ~NotImplementedException() CATCH_NOEXCEPT {} + + virtual const char* what() const CATCH_NOEXCEPT; + + private: + std::string m_what; + SourceLineInfo m_lineInfo; + }; + +} // end namespace Catch + +/////////////////////////////////////////////////////////////////////////////// +#define CATCH_NOT_IMPLEMENTED throw Catch::NotImplementedException( CATCH_INTERNAL_LINEINFO ) + +// #included from: internal/catch_context.h +#define TWOBLUECUBES_CATCH_CONTEXT_H_INCLUDED + +// #included from: catch_interfaces_generators.h +#define TWOBLUECUBES_CATCH_INTERFACES_GENERATORS_H_INCLUDED + +#include + +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 + +#include +#include +#include + +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 + +namespace Catch { + + class TestSpec; + + struct ITestCase : IShared { + virtual void invoke () const = 0; + protected: + virtual ~ITestCase(); + }; + + class TestCase; + struct IConfig; + + struct ITestCaseRegistry { + virtual ~ITestCaseRegistry(); + virtual std::vector const& getAllTests() const = 0; + virtual std::vector const& getAllTestsSorted( IConfig const& config ) const = 0; + }; + + bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config ); + std::vector filterTests( std::vector const& testCases, TestSpec const& testSpec, IConfig const& config ); + std::vector const& getAllTestCasesSorted( IConfig const& config ); + +} + +namespace Catch { + +template +class MethodTestCase : public SharedImpl { + +public: + MethodTestCase( void (C::*method)() ) : m_method( method ) {} + + virtual void invoke() const { + C obj; + (obj.*m_method)(); + } + +private: + virtual ~MethodTestCase() {} + + void (C::*m_method)(); +}; + +typedef void(*TestFunction)(); + +struct NameAndDesc { + NameAndDesc( const char* _name = "", const char* _description= "" ) + : name( _name ), description( _description ) + {} + + const char* name; + const char* description; +}; + +void registerTestCase + ( ITestCase* testCase, + char const* className, + NameAndDesc const& nameAndDesc, + SourceLineInfo const& lineInfo ); + +struct AutoReg { + + AutoReg + ( TestFunction function, + SourceLineInfo const& lineInfo, + NameAndDesc const& nameAndDesc ); + + template + 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 + +#ifdef CATCH_CONFIG_VARIADIC_MACROS + /////////////////////////////////////////////////////////////////////////////// + #define INTERNAL_CATCH_TESTCASE2( TestName, ... ) \ + static void TestName(); \ + namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &TestName, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( __VA_ARGS__ ) ); }\ + 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, ... ) \ + namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &QualifiedMethod, "&" #QualifiedMethod, Catch::NameAndDesc( __VA_ARGS__ ), CATCH_INTERNAL_LINEINFO ); } + + /////////////////////////////////////////////////////////////////////////////// + #define INTERNAL_CATCH_TEST_CASE_METHOD2( TestName, ClassName, ... )\ + namespace{ \ + struct TestName : ClassName{ \ + void test(); \ + }; \ + Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( &TestName::test, #ClassName, Catch::NameAndDesc( __VA_ARGS__ ), CATCH_INTERNAL_LINEINFO ); \ + } \ + 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::AutoReg( Function, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( __VA_ARGS__ ) ); + +#else + /////////////////////////////////////////////////////////////////////////////// + #define INTERNAL_CATCH_TESTCASE2( TestName, Name, Desc ) \ + static void TestName(); \ + namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &TestName, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( Name, Desc ) ); }\ + 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 ) + + /////////////////////////////////////////////////////////////////////////////// + #define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, Name, Desc ) \ + namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &QualifiedMethod, "&" #QualifiedMethod, Catch::NameAndDesc( Name, Desc ), CATCH_INTERNAL_LINEINFO ); } + + /////////////////////////////////////////////////////////////////////////////// + #define INTERNAL_CATCH_TEST_CASE_METHOD2( TestCaseName, ClassName, TestName, Desc )\ + namespace{ \ + struct TestCaseName : ClassName{ \ + void test(); \ + }; \ + Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( &TestCaseName::test, #ClassName, Catch::NameAndDesc( TestName, Desc ), CATCH_INTERNAL_LINEINFO ); \ + } \ + 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 ) + + /////////////////////////////////////////////////////////////////////////////// + #define INTERNAL_CATCH_REGISTER_TESTCASE( Function, Name, Desc ) \ + Catch::AutoReg( Function, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( Name, Desc ) ); +#endif + +// #included from: internal/catch_capture.hpp +#define TWOBLUECUBES_CATCH_CAPTURE_HPP_INCLUDED + +// #included from: catch_result_builder.h +#define TWOBLUECUBES_CATCH_RESULT_BUILDER_H_INCLUDED + +// #included from: catch_result_type.h +#define TWOBLUECUBES_CATCH_RESULT_TYPE_H_INCLUDED + +namespace Catch { + + // ResultWas::OfType enum + struct ResultWas { enum OfType { + Unknown = -1, + Ok = 0, + Info = 1, + Warning = 2, + + FailureBit = 0x10, + + ExpressionFailed = FailureBit | 1, + ExplicitFailure = FailureBit | 2, + + Exception = 0x100 | FailureBit, + + ThrewException = Exception | 1, + DidntThrowException = Exception | 2, + + FatalErrorCondition = 0x200 | FailureBit + + }; }; + + inline bool isOk( ResultWas::OfType resultType ) { + return ( resultType & ResultWas::FailureBit ) == 0; + } + inline bool isJustInfo( int flags ) { + return flags == ResultWas::Info; + } + + // ResultDisposition::Flags enum + struct ResultDisposition { enum Flags { + Normal = 0x01, + + ContinueOnFailure = 0x02, // Failures fail test, but execution continues + FalseTest = 0x04, // Prefix expression with ! + SuppressFail = 0x08 // Failures are reported but do not fail the test + }; }; + + inline ResultDisposition::Flags operator | ( ResultDisposition::Flags lhs, ResultDisposition::Flags rhs ) { + return static_cast( 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& ); + }; + + struct AssertionInfo + { + AssertionInfo() {} + AssertionInfo( std::string const& _macroName, + SourceLineInfo const& _lineInfo, + std::string const& _capturedExpression, + ResultDisposition::Flags _resultDisposition ); + + std::string macroName; + SourceLineInfo lineInfo; + std::string capturedExpression; + ResultDisposition::Flags resultDisposition; + }; + + struct AssertionResultData + { + AssertionResultData() : 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 { + + namespace Generic { + template class AllOf; + template class AnyOf; + template class Not; + } + + template + struct Matcher : SharedImpl + { + typedef ExpressionT ExpressionType; + + virtual ~Matcher() {} + virtual Ptr clone() const = 0; + virtual bool match( ExpressionT const& expr ) const = 0; + virtual std::string toString() const = 0; + + Generic::AllOf operator && ( Matcher const& other ) const; + Generic::AnyOf operator || ( Matcher const& other ) const; + Generic::Not operator ! () const; + }; + + template + struct MatcherImpl : Matcher { + + virtual Ptr > clone() const { + return Ptr >( new DerivedT( static_cast( *this ) ) ); + } + }; + + namespace Generic { + template + class Not : public MatcherImpl, ExpressionT> { + public: + explicit Not( Matcher const& matcher ) : m_matcher(matcher.clone()) {} + Not( Not const& other ) : m_matcher( other.m_matcher ) {} + + virtual bool match( ExpressionT const& expr ) const CATCH_OVERRIDE { + return !m_matcher->match( expr ); + } + + virtual std::string toString() const CATCH_OVERRIDE { + return "not " + m_matcher->toString(); + } + private: + Ptr< Matcher > m_matcher; + }; + + template + class AllOf : public MatcherImpl, ExpressionT> { + public: + + AllOf() {} + AllOf( AllOf const& other ) : m_matchers( other.m_matchers ) {} + + AllOf& add( Matcher const& matcher ) { + m_matchers.push_back( matcher.clone() ); + return *this; + } + virtual bool match( ExpressionT const& expr ) const + { + for( std::size_t i = 0; i < m_matchers.size(); ++i ) + if( !m_matchers[i]->match( expr ) ) + return false; + return true; + } + virtual std::string toString() const { + std::ostringstream oss; + oss << "( "; + for( std::size_t i = 0; i < m_matchers.size(); ++i ) { + if( i != 0 ) + oss << " and "; + oss << m_matchers[i]->toString(); + } + oss << " )"; + return oss.str(); + } + + AllOf operator && ( Matcher const& other ) const { + AllOf allOfExpr( *this ); + allOfExpr.add( other ); + return allOfExpr; + } + + private: + std::vector > > m_matchers; + }; + + template + class AnyOf : public MatcherImpl, ExpressionT> { + public: + + AnyOf() {} + AnyOf( AnyOf const& other ) : m_matchers( other.m_matchers ) {} + + AnyOf& add( Matcher const& matcher ) { + m_matchers.push_back( matcher.clone() ); + return *this; + } + virtual bool match( ExpressionT const& expr ) const + { + for( std::size_t i = 0; i < m_matchers.size(); ++i ) + if( m_matchers[i]->match( expr ) ) + return true; + return false; + } + virtual std::string toString() const { + std::ostringstream oss; + oss << "( "; + for( std::size_t i = 0; i < m_matchers.size(); ++i ) { + if( i != 0 ) + oss << " or "; + oss << m_matchers[i]->toString(); + } + oss << " )"; + return oss.str(); + } + + AnyOf operator || ( Matcher const& other ) const { + AnyOf anyOfExpr( *this ); + anyOfExpr.add( other ); + return anyOfExpr; + } + + private: + std::vector > > m_matchers; + }; + + } // namespace Generic + + template + Generic::AllOf Matcher::operator && ( Matcher const& other ) const { + Generic::AllOf allOfExpr; + allOfExpr.add( *this ); + allOfExpr.add( other ); + return allOfExpr; + } + + template + Generic::AnyOf Matcher::operator || ( Matcher const& other ) const { + Generic::AnyOf anyOfExpr; + anyOfExpr.add( *this ); + anyOfExpr.add( other ); + return anyOfExpr; + } + + template + Generic::Not Matcher::operator ! () const { + return Generic::Not( *this ); + } + + namespace StdString { + + inline std::string makeString( std::string const& str ) { return str; } + inline std::string makeString( const char* str ) { return str ? std::string( str ) : std::string(); } + + struct CasedString + { + CasedString( std::string const& str, CaseSensitive::Choice caseSensitivity ) + : m_caseSensitivity( caseSensitivity ), + m_str( adjustString( str ) ) + {} + std::string adjustString( std::string const& str ) const { + return m_caseSensitivity == CaseSensitive::No + ? toLower( str ) + : str; + + } + std::string toStringSuffix() const + { + return m_caseSensitivity == CaseSensitive::No + ? " (case insensitive)" + : std::string(); + } + CaseSensitive::Choice m_caseSensitivity; + std::string m_str; + }; + + struct Equals : MatcherImpl { + Equals( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) + : m_data( str, caseSensitivity ) + {} + Equals( Equals const& other ) : m_data( other.m_data ){} + + virtual ~Equals(); + + virtual bool match( std::string const& expr ) const { + return m_data.m_str == m_data.adjustString( expr );; + } + virtual std::string toString() const { + return "equals: \"" + m_data.m_str + '"' + m_data.toStringSuffix(); + } + + CasedString m_data; + }; + + struct Contains : MatcherImpl { + Contains( std::string const& substr, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) + : m_data( substr, caseSensitivity ){} + Contains( Contains const& other ) : m_data( other.m_data ){} + + virtual ~Contains(); + + virtual bool match( std::string const& expr ) const { + return m_data.adjustString( expr ).find( m_data.m_str ) != std::string::npos; + } + virtual std::string toString() const { + return "contains: \"" + m_data.m_str + '"' + m_data.toStringSuffix(); + } + + CasedString m_data; + }; + + struct StartsWith : MatcherImpl { + StartsWith( std::string const& substr, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) + : m_data( substr, caseSensitivity ){} + + StartsWith( StartsWith const& other ) : m_data( other.m_data ){} + + virtual ~StartsWith(); + + virtual bool match( std::string const& expr ) const { + return startsWith( m_data.adjustString( expr ), m_data.m_str ); + } + virtual std::string toString() const { + return "starts with: \"" + m_data.m_str + '"' + m_data.toStringSuffix(); + } + + CasedString m_data; + }; + + struct EndsWith : MatcherImpl { + EndsWith( std::string const& substr, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) + : m_data( substr, caseSensitivity ){} + EndsWith( EndsWith const& other ) : m_data( other.m_data ){} + + virtual ~EndsWith(); + + virtual bool match( std::string const& expr ) const { + return endsWith( m_data.adjustString( expr ), m_data.m_str ); + } + virtual std::string toString() const { + return "ends with: \"" + m_data.m_str + '"' + m_data.toStringSuffix(); + } + + CasedString m_data; + }; + } // namespace StdString + } // namespace Impl + + // The following functions create the actual matcher objects. + // This allows the types to be inferred + template + inline Impl::Generic::Not Not( Impl::Matcher const& m ) { + return Impl::Generic::Not( m ); + } + + template + inline Impl::Generic::AllOf AllOf( Impl::Matcher const& m1, + Impl::Matcher const& m2 ) { + return Impl::Generic::AllOf().add( m1 ).add( m2 ); + } + template + inline Impl::Generic::AllOf AllOf( Impl::Matcher const& m1, + Impl::Matcher const& m2, + Impl::Matcher const& m3 ) { + return Impl::Generic::AllOf().add( m1 ).add( m2 ).add( m3 ); + } + template + inline Impl::Generic::AnyOf AnyOf( Impl::Matcher const& m1, + Impl::Matcher const& m2 ) { + return Impl::Generic::AnyOf().add( m1 ).add( m2 ); + } + template + inline Impl::Generic::AnyOf AnyOf( Impl::Matcher const& m1, + Impl::Matcher const& m2, + Impl::Matcher const& m3 ) { + return Impl::Generic::AnyOf().add( m1 ).add( m2 ).add( m3 ); + } + + inline Impl::StdString::Equals Equals( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) { + return Impl::StdString::Equals( str, caseSensitivity ); + } + inline Impl::StdString::Equals Equals( const char* str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) { + return Impl::StdString::Equals( Impl::StdString::makeString( str ), caseSensitivity ); + } + inline Impl::StdString::Contains Contains( std::string const& substr, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) { + return Impl::StdString::Contains( substr, caseSensitivity ); + } + inline Impl::StdString::Contains Contains( const char* substr, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) { + return Impl::StdString::Contains( Impl::StdString::makeString( substr ), caseSensitivity ); + } + inline Impl::StdString::StartsWith StartsWith( std::string const& substr ) { + return Impl::StdString::StartsWith( substr ); + } + inline Impl::StdString::StartsWith StartsWith( const char* substr ) { + return Impl::StdString::StartsWith( Impl::StdString::makeString( substr ) ); + } + inline Impl::StdString::EndsWith EndsWith( std::string const& substr ) { + return Impl::StdString::EndsWith( substr ); + } + inline Impl::StdString::EndsWith EndsWith( const char* substr ) { + return Impl::StdString::EndsWith( Impl::StdString::makeString( substr ) ); + } + +} // namespace Matchers + +using namespace Matchers; + +} // namespace Catch + +namespace Catch { + + struct TestFailureException{}; + + template 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 = "" ); + + template + ExpressionLhs operator <= ( T const& operand ); + ExpressionLhs operator <= ( bool value ); + + template + ResultBuilder& operator << ( T const& value ) { + m_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::Matcher 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 ); + + private: + AssertionInfo m_assertionInfo; + AssertionResultData m_data; + CopyableStream m_stream; + + bool m_shouldDebugBreak; + bool m_shouldThrow; + }; + +} // namespace Catch + +// Include after due to circular dependency: +// #included from: catch_expression_lhs.hpp +#define TWOBLUECUBES_CATCH_EXPRESSION_LHS_HPP_INCLUDED + +// #included from: catch_evaluate.hpp +#define TWOBLUECUBES_CATCH_EVALUATE_HPP_INCLUDED + +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable:4389) // '==' : signed/unsigned mismatch +#endif + +#include + +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 + inline T& opCast(T const& t) { return const_cast(t); } + +// nullptr_t support based on pull request #154 from Konstantin Baumann +#ifdef CATCH_CONFIG_CPP11_NULLPTR + inline std::nullptr_t opCast(std::nullptr_t) { return nullptr; } +#endif // CATCH_CONFIG_CPP11_NULLPTR + + // So the compare overloads can be operator agnostic we convey the operator as a template + // enum, which is used to specialise an Evaluator for doing the comparison. + template + class Evaluator{}; + + 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__ +// #included from: catch_objc_arc.hpp +#define TWOBLUECUBES_CATCH_OBJC_ARC_HPP_INCLUDED + +#import + +#ifdef __has_feature +#define CATCH_ARC_ENABLED __has_feature(objc_arc) +#else +#define CATCH_ARC_ENABLED 0 +#endif + +void arcSafeRelease( NSObject* obj ); +id performOptionalSelector( id obj, SEL sel ); + +#if !CATCH_ARC_ENABLED +inline void arcSafeRelease( NSObject* obj ) { + [obj release]; +} +inline id performOptionalSelector( id obj, SEL sel ) { + if( [obj respondsToSelector: sel] ) + return [obj performSelector: sel]; + return nil; +} +#define CATCH_UNSAFE_UNRETAINED +#define CATCH_ARC_STRONG +#else +inline void arcSafeRelease( NSObject* ){} +inline id performOptionalSelector( id obj, SEL sel ) { +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Warc-performSelector-leaks" +#endif + if( [obj respondsToSelector: sel] ) + return [obj performSelector: sel]; +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + return nil; +} +#define CATCH_UNSAFE_UNRETAINED __unsafe_unretained +#define CATCH_ARC_STRONG __strong +#endif + +#endif + +#ifdef CATCH_CONFIG_CPP11_TUPLE +#include +#endif + +#ifdef CATCH_CONFIG_CPP11_IS_ENUM +#include +#endif + +namespace Catch { + +// Why we're here. +template +std::string toString( T const& value ); + +// Built in overloads + +std::string toString( std::string const& value ); +std::string toString( std::wstring const& value ); +std::string toString( const char* const value ); +std::string toString( char* const value ); +std::string toString( const wchar_t* const value ); +std::string toString( wchar_t* const value ); +std::string toString( int value ); +std::string toString( unsigned long value ); +std::string toString( unsigned int value ); +std::string toString( const double value ); +std::string toString( const float value ); +std::string toString( bool value ); +std::string toString( char value ); +std::string toString( signed char value ); +std::string toString( unsigned char value ); + +#ifdef CATCH_CONFIG_CPP11_LONG_LONG +std::string toString( long long value ); +std::string toString( unsigned long long value ); +#endif + +#ifdef CATCH_CONFIG_CPP11_NULLPTR +std::string toString( std::nullptr_t ); +#endif + +#ifdef __OBJC__ + std::string toString( NSString const * const& nsstring ); + std::string toString( NSString * CATCH_ARC_STRONG const& nsstring ); + std::string toString( NSObject* const& nsObject ); +#endif + +namespace Detail { + + extern const std::string unprintableString; + + struct BorgType { + template BorgType( T const& ); + }; + + struct TrueType { char sizer[1]; }; + struct FalseType { char sizer[2]; }; + + TrueType& testStreamable( std::ostream& ); + FalseType testStreamable( FalseType ); + + FalseType operator<<( std::ostream const&, BorgType const& ); + + template + struct IsStreamInsertable { + static std::ostream &s; + static T const&t; + enum { value = sizeof( testStreamable(s << t) ) == sizeof( TrueType ) }; + }; + +#if defined(CATCH_CONFIG_CPP11_IS_ENUM) + template::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) + ); + } + }; +#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 + inline 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 + +namespace Catch { + +template +class BinaryExpression; + +template +class MatchExpression; + +// 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) {} + + template + BinaryExpression + operator == ( RhsT const& rhs ) const { + return captureExpression( rhs ); + } + + template + BinaryExpression + operator != ( RhsT const& rhs ) const { + return captureExpression( rhs ); + } + + template + BinaryExpression + operator < ( RhsT const& rhs ) const { + return captureExpression( rhs ); + } + + template + BinaryExpression + operator > ( RhsT const& rhs ) const { + return captureExpression( rhs ); + } + + template + BinaryExpression + operator <= ( RhsT const& rhs ) const { + return captureExpression( rhs ); + } + + template + BinaryExpression + operator >= ( RhsT const& rhs ) const { + return captureExpression( rhs ); + } + + BinaryExpression operator == ( bool rhs ) const { + return captureExpression( rhs ); + } + + BinaryExpression operator != ( bool rhs ) const { + 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_truthy ); + } + +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 ) {} + + 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 + inline ExpressionLhs ResultBuilder::operator <= ( T const& operand ) { + return ExpressionLhs( *this, operand ); + } + + inline ExpressionLhs ResultBuilder::operator <= ( bool value ) { + return ExpressionLhs( *this, value ); + } + + template + inline 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 + +// #included from: catch_message.h +#define TWOBLUECUBES_CATCH_MESSAGE_H_INCLUDED + +#include + +namespace Catch { + + struct MessageInfo { + MessageInfo( std::string const& _macroName, + SourceLineInfo const& _lineInfo, + ResultWas::OfType _type ); + + std::string macroName; + SourceLineInfo lineInfo; + ResultWas::OfType type; + std::string message; + unsigned int sequence; + + bool operator == ( MessageInfo const& other ) const { + return sequence == other.sequence; + } + bool operator < ( MessageInfo const& other ) const { + return sequence < other.sequence; + } + private: + static unsigned int globalCount; + }; + + struct MessageBuilder { + MessageBuilder( std::string const& macroName, + SourceLineInfo const& lineInfo, + ResultWas::OfType type ) + : m_info( macroName, lineInfo, type ) + {} + + template + MessageBuilder& operator << ( T const& value ) { + m_stream << value; + return *this; + } + + MessageInfo m_info; + std::ostringstream m_stream; + }; + + class ScopedMessage { + public: + ScopedMessage( MessageBuilder const& builder ); + ScopedMessage( ScopedMessage const& other ); + ~ScopedMessage(); + + MessageInfo m_info; + }; + +} // end namespace Catch + +// #included from: catch_interfaces_capture.h +#define TWOBLUECUBES_CATCH_INTERFACES_CAPTURE_H_INCLUDED + +#include + +namespace Catch { + + class TestCase; + class AssertionResult; + struct AssertionInfo; + struct SectionInfo; + struct SectionEndInfo; + struct MessageInfo; + class ScopedMessageBuilder; + struct Counts; + + struct IResultCapture { + + virtual ~IResultCapture(); + + virtual void assertionEnded( AssertionResult const& result ) = 0; + virtual bool sectionStarted( SectionInfo const& sectionInfo, + Counts& assertions ) = 0; + virtual void sectionEnded( SectionEndInfo const& endInfo ) = 0; + virtual void sectionEndedEarly( SectionEndInfo const& endInfo ) = 0; + virtual void pushScopedMessage( MessageInfo const& message ) = 0; + virtual void popScopedMessage( MessageInfo const& message ) = 0; + + virtual std::string getCurrentTestName() const = 0; + virtual const AssertionResult* getLastResult() const = 0; + + virtual void handleFatalErrorCondition( std::string const& message ) = 0; + }; + + IResultCapture& getResultCapture(); +} + +// #included from: catch_debugger.h +#define TWOBLUECUBES_CATCH_DEBUGGER_H_INCLUDED + +// #included from: catch_platform.h +#define TWOBLUECUBES_CATCH_PLATFORM_H_INCLUDED + +#if defined(__MAC_OS_X_VERSION_MIN_REQUIRED) +# define CATCH_PLATFORM_MAC +#elif defined(__IPHONE_OS_VERSION_MIN_REQUIRED) +# define CATCH_PLATFORM_IPHONE +#elif defined(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{ + + 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" ) + #else + #define CATCH_TRAP() __asm__("int $3\n" : : ) + #endif + +#elif defined(CATCH_PLATFORM_LINUX) + // If we can use inline assembler, do it because this allows us to break + // directly at the location of the failing check instead of breaking inside + // raise() called from it, i.e. one stack frame below. + #if defined(__GNUC__) && (defined(__i386) || defined(__x86_64)) + #define CATCH_TRAP() asm volatile ("int $3") + #else // Fall back to the generic way. + #include + + #define CATCH_TRAP() raise(SIGTRAP) + #endif +#elif defined(_MSC_VER) + #define CATCH_TRAP() __debugbreak() +#elif defined(__MINGW32__) + extern "C" __declspec(dllimport) void __stdcall DebugBreak(); + #define CATCH_TRAP() DebugBreak() +#endif + +#ifdef CATCH_TRAP + #define CATCH_BREAK_INTO_DEBUGGER() if( Catch::isDebuggerActive() ) { CATCH_TRAP(); } +#else + #define CATCH_BREAK_INTO_DEBUGGER() Catch::alwaysTrue(); +#endif + +// #included from: catch_interfaces_runner.h +#define TWOBLUECUBES_CATCH_INTERFACES_RUNNER_H_INCLUDED + +namespace Catch { + class TestCase; + + struct IRunner { + virtual ~IRunner(); + virtual bool aborting() const = 0; + }; +} + +/////////////////////////////////////////////////////////////////////////////// +// In the event of a failure works out if the debugger needs to be invoked +// and/or an exception thrown and takes appropriate action. +// This needs to be done as a macro so the debugger will stop in the user +// source code rather than in Catch library code +#define INTERNAL_CATCH_REACT( resultBuilder ) \ + if( resultBuilder.shouldDebugBreak() ) CATCH_BREAK_INTO_DEBUGGER(); \ + resultBuilder.react(); + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_TEST( expr, resultDisposition, macroName ) \ + do { \ + Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \ + try { \ + CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \ + ( __catchResult <= expr ).endExpression(); \ + } \ + catch( ... ) { \ + __catchResult.useActiveException( 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( expr, resultDisposition, macroName ) \ + INTERNAL_CATCH_TEST( expr, resultDisposition, macroName ); \ + if( Catch::getResultCapture().getLastResult()->succeeded() ) + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_ELSE( expr, resultDisposition, macroName ) \ + INTERNAL_CATCH_TEST( expr, resultDisposition, macroName ); \ + if( !Catch::getResultCapture().getLastResult()->succeeded() ) + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_NO_THROW( expr, resultDisposition, macroName ) \ + do { \ + Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \ + try { \ + static_cast(expr); \ + __catchResult.captureResult( Catch::ResultWas::Ok ); \ + } \ + catch( ... ) { \ + __catchResult.useActiveException( resultDisposition ); \ + } \ + INTERNAL_CATCH_REACT( __catchResult ) \ + } while( Catch::alwaysFalse() ) + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_THROWS( expr, resultDisposition, matcher, macroName ) \ + do { \ + Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition, #matcher ); \ + if( __catchResult.allowThrows() ) \ + try { \ + static_cast(expr); \ + __catchResult.captureResult( Catch::ResultWas::DidntThrowException ); \ + } \ + catch( ... ) { \ + __catchResult.captureExpectedException( matcher ); \ + } \ + else \ + __catchResult.captureResult( Catch::ResultWas::Ok ); \ + INTERNAL_CATCH_REACT( __catchResult ) \ + } while( Catch::alwaysFalse() ) + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_THROWS_AS( expr, exceptionType, resultDisposition, macroName ) \ + do { \ + Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \ + if( __catchResult.allowThrows() ) \ + try { \ + static_cast(expr); \ + __catchResult.captureResult( Catch::ResultWas::DidntThrowException ); \ + } \ + catch( exceptionType ) { \ + __catchResult.captureResult( Catch::ResultWas::Ok ); \ + } \ + catch( ... ) { \ + __catchResult.useActiveException( resultDisposition ); \ + } \ + else \ + __catchResult.captureResult( Catch::ResultWas::Ok ); \ + INTERNAL_CATCH_REACT( __catchResult ) \ + } while( Catch::alwaysFalse() ) + +/////////////////////////////////////////////////////////////////////////////// +#ifdef CATCH_CONFIG_VARIADIC_MACROS + #define INTERNAL_CATCH_MSG( messageType, resultDisposition, macroName, ... ) \ + do { \ + Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, "", resultDisposition ); \ + __catchResult << __VA_ARGS__ + ::Catch::StreamEndStop(); \ + __catchResult.captureResult( messageType ); \ + INTERNAL_CATCH_REACT( __catchResult ) \ + } while( Catch::alwaysFalse() ) +#else + #define INTERNAL_CATCH_MSG( messageType, resultDisposition, macroName, log ) \ + do { \ + Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, "", resultDisposition ); \ + __catchResult << log + ::Catch::StreamEndStop(); \ + __catchResult.captureResult( messageType ); \ + INTERNAL_CATCH_REACT( __catchResult ) \ + } while( Catch::alwaysFalse() ) +#endif + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_INFO( log, macroName ) \ + Catch::ScopedMessage INTERNAL_CATCH_UNIQUE_NAME( scopedMessage ) = Catch::MessageBuilder( macroName, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info ) << log; + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CHECK_THAT( arg, matcher, resultDisposition, macroName ) \ + do { \ + Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #arg ", " #matcher, resultDisposition ); \ + try { \ + __catchResult.captureMatch( arg, matcher, #matcher ); \ + } catch( ... ) { \ + __catchResult.useActiveException( resultDisposition | Catch::ResultDisposition::ContinueOnFailure ); \ + } \ + INTERNAL_CATCH_REACT( __catchResult ) \ + } while( Catch::alwaysFalse() ) + +// #included from: internal/catch_section.h +#define TWOBLUECUBES_CATCH_SECTION_H_INCLUDED + +// #included from: catch_section_info.h +#define TWOBLUECUBES_CATCH_SECTION_INFO_H_INCLUDED + +// #included from: catch_totals.hpp +#define TWOBLUECUBES_CATCH_TOTALS_HPP_INCLUDED + +#include + +namespace Catch { + + struct Counts { + Counts() : passed( 0 ), failed( 0 ), failedButOk( 0 ) {} + + Counts operator - ( Counts const& other ) const { + Counts diff; + diff.passed = passed - other.passed; + diff.failed = failed - other.failed; + diff.failedButOk = failedButOk - other.failedButOk; + return diff; + } + Counts& operator += ( Counts const& other ) { + passed += other.passed; + failed += other.failed; + failedButOk += other.failedButOk; + return *this; + } + + std::size_t total() const { + return passed + failed + failedButOk; + } + bool allPassed() const { + return failed == 0 && failedButOk == 0; + } + bool allOk() const { + return failed == 0; + } + + std::size_t passed; + std::size_t failed; + std::size_t failedButOk; + }; + + struct Totals { + + Totals operator - ( Totals const& other ) const { + Totals diff; + diff.assertions = assertions - other.assertions; + diff.testCases = testCases - other.testCases; + return diff; + } + + Totals delta( Totals const& prevTotals ) const { + Totals diff = *this - prevTotals; + if( diff.assertions.failed > 0 ) + ++diff.testCases.failed; + else if( diff.assertions.failedButOk > 0 ) + ++diff.testCases.failedButOk; + else + ++diff.testCases.passed; + return diff; + } + + Totals& operator += ( Totals const& other ) { + assertions += other.assertions; + testCases += other.testCases; + return *this; + } + + Counts assertions; + Counts testCases; + }; +} + +namespace Catch { + + struct SectionInfo { + SectionInfo + ( SourceLineInfo const& _lineInfo, + std::string const& _name, + std::string const& _description = std::string() ); + + std::string name; + std::string description; + SourceLineInfo lineInfo; + }; + + struct SectionEndInfo { + SectionEndInfo( SectionInfo const& _sectionInfo, Counts const& _prevAssertions, double _durationInSeconds ) + : sectionInfo( _sectionInfo ), prevAssertions( _prevAssertions ), durationInSeconds( _durationInSeconds ) + {} + + SectionInfo sectionInfo; + Counts prevAssertions; + double durationInSeconds; + }; + +} // end namespace Catch + +// #included from: catch_timer.h +#define TWOBLUECUBES_CATCH_TIMER_H_INCLUDED + +#ifdef CATCH_PLATFORM_WINDOWS +typedef unsigned long long uint64_t; +#else +#include +#endif + +namespace Catch { + + class Timer { + public: + Timer() : m_ticks( 0 ) {} + void start(); + unsigned int getElapsedMicroseconds() const; + unsigned int getElapsedMilliseconds() const; + double getElapsedSeconds() const; + + private: + uint64_t m_ticks; + }; + +} // namespace Catch + +#include + +namespace Catch { + + class Section : NonCopyable { + public: + Section( SectionInfo const& info ); + ~Section(); + + // This indicates whether the section should be executed or not + operator bool() const; + + private: + SectionInfo m_info; + + std::string m_name; + Counts m_assertions; + bool m_sectionIncluded; + Timer m_timer; + }; + +} // end namespace Catch + +#ifdef CATCH_CONFIG_VARIADIC_MACROS + #define INTERNAL_CATCH_SECTION( ... ) \ + if( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::SectionInfo( CATCH_INTERNAL_LINEINFO, __VA_ARGS__ ) ) +#else + #define INTERNAL_CATCH_SECTION( name, desc ) \ + if( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::SectionInfo( CATCH_INTERNAL_LINEINFO, name, desc ) ) +#endif + +// #included from: internal/catch_generators.hpp +#define TWOBLUECUBES_CATCH_GENERATORS_HPP_INCLUDED + +#include +#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; +}; + +template +class BetweenGenerator : public IGenerator { +public: + BetweenGenerator( T from, T to ) : m_from( from ), m_to( to ){} + + virtual T getValue( std::size_t index ) const { + return m_from+static_cast( index ); + } + + virtual 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 ) + { + 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 + } + + void add( const IGenerator* generator ) { + m_totalSize += generator->size(); + m_composed.push_back( generator ); + } + + CompositeGenerator& then( CompositeGenerator& other ) { + move( other ); + return *this; + } + + CompositeGenerator& then( T value ) { + ValuesGenerator* valuesGen = new ValuesGenerator(); + valuesGen->add( value ); + add( valuesGen ); + return *this; + } + +private: + + void move( CompositeGenerator& other ) { + std::copy( other.m_composed.begin(), other.m_composed.end(), std::back_inserter( m_composed ) ); + m_totalSize += other.m_totalSize; + other.m_composed.clear(); + } + + std::vector*> 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 INTERNAL_CATCH_LINESTR2( line ) #line +#define INTERNAL_CATCH_LINESTR( line ) INTERNAL_CATCH_LINESTR2( line ) + +#define INTERNAL_CATCH_GENERATE( expr ) expr.setFileInfo( __FILE__ "(" INTERNAL_CATCH_LINESTR( __LINE__ ) ")" ) + +// #included from: internal/catch_interfaces_exception.h +#define TWOBLUECUBES_CATCH_INTERFACES_EXCEPTION_H_INCLUDED + +#include +#include + +// #included from: catch_interfaces_registry_hub.h +#define TWOBLUECUBES_CATCH_INTERFACES_REGISTRY_HUB_H_INCLUDED + +#include + +namespace Catch { + + class TestCase; + struct ITestCaseRegistry; + struct IExceptionTranslatorRegistry; + struct IExceptionTranslator; + struct IReporterRegistry; + struct IReporterFactory; + + struct IRegistryHub { + virtual ~IRegistryHub(); + + virtual IReporterRegistry const& getReporterRegistry() const = 0; + virtual ITestCaseRegistry const& getTestCaseRegistry() const = 0; + virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() = 0; + }; + + struct IMutableRegistryHub { + virtual ~IMutableRegistryHub(); + virtual void registerReporter( std::string const& name, Ptr const& factory ) = 0; + virtual void registerListener( Ptr const& factory ) = 0; + virtual void registerTest( TestCase const& testInfo ) = 0; + virtual void registerTranslator( const IExceptionTranslator* translator ) = 0; + }; + + IRegistryHub& getRegistryHub(); + IMutableRegistryHub& getMutableRegistryHub(); + void cleanUp(); + std::string translateActiveException(); + +} + +namespace Catch { + + typedef std::string(*exceptionTranslateFunction)(); + + struct IExceptionTranslator; + typedef std::vector ExceptionTranslators; + + struct IExceptionTranslator { + virtual ~IExceptionTranslator(); + virtual std::string translate( ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd ) const = 0; + }; + + struct IExceptionTranslatorRegistry { + virtual ~IExceptionTranslatorRegistry(); + + virtual std::string translateActiveException() const = 0; + }; + + class ExceptionTranslatorRegistrar { + template + class ExceptionTranslator : public IExceptionTranslator { + public: + + ExceptionTranslator( std::string(*translateFunction)( T& ) ) + : m_translateFunction( translateFunction ) + {} + + virtual std::string translate( ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd ) const CATCH_OVERRIDE { + try { + if( it == itEnd ) + throw; + else + return (*it)->translate( it+1, itEnd ); + } + catch( T& ex ) { + return m_translateFunction( ex ); + } + } + + protected: + std::string(*m_translateFunction)( T& ); + }; + + public: + template + ExceptionTranslatorRegistrar( std::string(*translateFunction)( T& ) ) { + getMutableRegistryHub().registerTranslator + ( new ExceptionTranslator( translateFunction ) ); + } + }; +} + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_TRANSLATE_EXCEPTION2( translatorName, signature ) \ + static std::string translatorName( signature ); \ + namespace{ Catch::ExceptionTranslatorRegistrar INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionRegistrar )( &translatorName ); }\ + static std::string translatorName( signature ) + +#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 + +#include +#include + +#if defined(CATCH_CONFIG_CPP11_TYPE_TRAITS) +#include +#endif + +namespace Catch { +namespace Detail { + + class Approx { + public: + explicit Approx ( double value ) + : m_epsilon( std::numeric_limits::epsilon()*100 ), + m_scale( 1.0 ), + m_value( value ) + {} + + Approx( Approx const& other ) + : m_epsilon( other.m_epsilon ), + m_scale( other.m_scale ), + m_value( other.m_value ) + {} + + static Approx custom() { + return Approx( 0 ); + } + + Approx operator()( double value ) { + Approx approx( value ); + approx.epsilon( m_epsilon ); + approx.scale( m_scale ); + return approx; + } + +#if defined(CATCH_CONFIG_CPP11_TYPE_TRAITS) + 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); + return fabs( lhs_v - rhs.m_value ) < rhs.m_epsilon * (rhs.m_scale + (std::max)( fabs(lhs_v), fabs(rhs.m_value) ) ); + } + + template ::value>::type> + friend bool operator == ( Approx const& lhs, const T& rhs ) { + return operator==( rhs, lhs ); + } + + template ::value>::type> + friend bool operator != ( T lhs, Approx const& rhs ) { + return !operator==( lhs, rhs ); + } + + template ::value>::type> + friend bool operator != ( Approx const& lhs, T rhs ) { + return !operator==( rhs, lhs ); + } + + template ::value>::type> + 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 rhs ) + { + return lhs.m_value < double(rhs) || lhs == rhs; + } + + template ::value>::type> + 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 rhs ) + { + return lhs.m_value > double(rhs) || lhs == rhs; + } +#else + friend bool operator == ( double lhs, Approx const& rhs ) { + // Thanks to Richard Harris for his help refining this formula + return fabs( lhs - rhs.m_value ) < rhs.m_epsilon * (rhs.m_scale + (std::max)( fabs(lhs), fabs(rhs.m_value) ) ); + } + + friend bool operator == ( Approx const& lhs, double rhs ) { + return operator==( rhs, lhs ); + } + + friend bool operator != ( double lhs, Approx const& rhs ) { + return !operator==( lhs, rhs ); + } + + friend bool operator != ( Approx const& lhs, double rhs ) { + return !operator==( rhs, lhs ); + } + + 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; + } +#endif + + Approx& epsilon( double newEpsilon ) { + m_epsilon = newEpsilon; + return *this; + } + + Approx& scale( double newScale ) { + m_scale = newScale; + return *this; + } + + std::string toString() const { + std::ostringstream oss; + oss << "Approx( " << Catch::toString( m_value ) << " )"; + return oss.str(); + } + + private: + double m_epsilon; + double m_scale; + double m_value; + }; +} + +template<> +inline std::string toString( Detail::Approx const& value ) { + return value.toString(); +} + +} // end namespace Catch + +// #included from: internal/catch_interfaces_tag_alias_registry.h +#define TWOBLUECUBES_CATCH_INTERFACES_TAG_ALIAS_REGISTRY_H_INCLUDED + +// #included from: catch_tag_alias.h +#define TWOBLUECUBES_CATCH_TAG_ALIAS_H_INCLUDED + +#include + +namespace Catch { + + struct TagAlias { + TagAlias( std::string _tag, SourceLineInfo _lineInfo ) : tag( _tag ), lineInfo( _lineInfo ) {} + + std::string tag; + SourceLineInfo lineInfo; + }; + + struct RegistrarForTagAliases { + RegistrarForTagAliases( char const* alias, char const* tag, SourceLineInfo const& lineInfo ); + }; + +} // end namespace Catch + +#define CATCH_REGISTER_TAG_ALIAS( alias, spec ) namespace{ Catch::RegistrarForTagAliases INTERNAL_CATCH_UNIQUE_NAME( AutoRegisterTagAlias )( alias, spec, CATCH_INTERNAL_LINEINFO ); } +// #included from: catch_option.hpp +#define TWOBLUECUBES_CATCH_OPTION_HPP_INCLUDED + +namespace Catch { + + // An optional type + template + class Option { + public: + Option() : nullableValue( CATCH_NULL ) {} + Option( T const& _value ) + : nullableValue( new( storage ) T( _value ) ) + {} + Option( Option const& _other ) + : nullableValue( _other ? new( storage ) T( *_other ) : CATCH_NULL ) + {} + + ~Option() { + reset(); + } + + Option& operator= ( Option const& _other ) { + if( &_other != this ) { + reset(); + if( _other ) + nullableValue = new( storage ) T( *_other ); + } + return *this; + } + Option& operator = ( T const& _value ) { + reset(); + nullableValue = new( storage ) T( _value ); + return *this; + } + + void reset() { + if( nullableValue ) + nullableValue->~T(); + nullableValue = CATCH_NULL; + } + + T& operator*() { return *nullableValue; } + T const& operator*() const { return *nullableValue; } + T* operator->() { return nullableValue; } + const T* operator->() const { return nullableValue; } + + T valueOr( T const& defaultValue ) const { + return nullableValue ? *nullableValue : defaultValue; + } + + bool some() const { return nullableValue != CATCH_NULL; } + bool none() const { return nullableValue == CATCH_NULL; } + + bool operator !() const { return nullableValue == CATCH_NULL; } + operator SafeBool::type() const { + return SafeBool::makeSafe( some() ); + } + + private: + T* nullableValue; + char storage[sizeof(T)]; + }; + +} // end namespace Catch + +namespace Catch { + + struct ITagAliasRegistry { + virtual ~ITagAliasRegistry(); + virtual Option find( std::string const& alias ) const = 0; + virtual std::string expandAliases( std::string const& unexpandedTestSpec ) const = 0; + + static ITagAliasRegistry const& get(); + }; + +} // end namespace Catch + +// These files are included here so the single_include script doesn't put them +// in the conditionally compiled sections +// #included from: internal/catch_test_case_info.h +#define TWOBLUECUBES_CATCH_TEST_CASE_INFO_H_INCLUDED + +#include +#include + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wpadded" +#endif + +namespace Catch { + + struct ITestCase; + + struct TestCaseInfo { + enum SpecialProperties{ + None = 0, + IsHidden = 1 << 1, + ShouldFail = 1 << 2, + MayFail = 1 << 3, + Throws = 1 << 4, + NonPortable = 1 << 5 + }; + + TestCaseInfo( std::string const& _name, + std::string const& _className, + std::string const& _description, + std::set const& _tags, + SourceLineInfo const& _lineInfo ); + + 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 name; + std::string className; + std::string description; + std::set tags; + std::set lcaseTags; + std::string tagsAsString; + SourceLineInfo lineInfo; + SpecialProperties properties; + }; + + class TestCase : public TestCaseInfo { + public: + + TestCase( ITestCase* testCase, TestCaseInfo const& info ); + TestCase( TestCase const& other ); + + TestCase withName( std::string const& _newName ) const; + + void invoke() const; + + TestCaseInfo const& getTestCaseInfo() const; + + void swap( TestCase& other ); + bool operator == ( TestCase const& other ) const; + bool operator < ( TestCase const& other ) const; + TestCase& operator = ( TestCase const& other ); + + private: + Ptr test; + }; + + TestCase makeTestCase( ITestCase* testCase, + std::string const& className, + std::string const& name, + std::string const& description, + SourceLineInfo const& lineInfo ); +} + +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + + +#ifdef __OBJC__ +// #included from: internal/catch_objc.hpp +#define TWOBLUECUBES_CATCH_OBJC_HPP_INCLUDED + +#import + +#include + +// NB. Any general catch headers included here must be included +// in catch.hpp first to make sure they are included by the single +// header for non obj-usage + +/////////////////////////////////////////////////////////////////////////////// +// This protocol is really only here for (self) documenting purposes, since +// all its methods are optional. +@protocol OcFixture + +@optional + +-(void) setUp; +-(void) tearDown; + +@end + +namespace Catch { + + class OcMethod : public SharedImpl { + + public: + OcMethod( Class cls, SEL sel ) : m_cls( cls ), m_sel( sel ) {} + + virtual void invoke() const { + id obj = [[m_cls alloc] init]; + + performOptionalSelector( obj, @selector(setUp) ); + performOptionalSelector( obj, m_sel ); + performOptionalSelector( obj, @selector(tearDown) ); + + arcSafeRelease( obj ); + } + private: + virtual ~OcMethod() {} + + Class m_cls; + SEL m_sel; + }; + + namespace Detail{ + + inline std::string getAnnotation( Class cls, + std::string const& annotationName, + std::string const& testCaseName ) { + NSString* selStr = [[NSString alloc] initWithFormat:@"Catch_%s_%s", annotationName.c_str(), testCaseName.c_str()]; + SEL sel = NSSelectorFromString( selStr ); + arcSafeRelease( selStr ); + id value = performOptionalSelector( cls, sel ); + if( value ) + return [(NSString*)value UTF8String]; + return ""; + } + } + + inline size_t registerTestMethods() { + size_t noTestMethods = 0; + int noClasses = objc_getClassList( CATCH_NULL, 0 ); + + Class* classes = (CATCH_UNSAFE_UNRETAINED Class *)malloc( sizeof(Class) * noClasses); + objc_getClassList( classes, noClasses ); + + for( int c = 0; c < noClasses; c++ ) { + Class cls = classes[c]; + { + u_int count; + Method* methods = class_copyMethodList( cls, &count ); + for( u_int m = 0; m < count ; m++ ) { + SEL selector = method_getName(methods[m]); + std::string methodName = sel_getName(selector); + if( startsWith( methodName, "Catch_TestCase_" ) ) { + std::string testCaseName = methodName.substr( 15 ); + std::string name = Detail::getAnnotation( cls, "Name", testCaseName ); + std::string desc = Detail::getAnnotation( cls, "Description", testCaseName ); + const char* className = class_getName( cls ); + + getMutableRegistryHub().registerTest( makeTestCase( new OcMethod( cls, selector ), className, name.c_str(), desc.c_str(), SourceLineInfo() ) ); + noTestMethods++; + } + } + free(methods); + } + } + return noTestMethods; + } + + namespace Matchers { + namespace Impl { + namespace NSStringMatchers { + + template + struct StringHolder : MatcherImpl{ + StringHolder( NSString* substr ) : m_substr( [substr copy] ){} + StringHolder( StringHolder const& other ) : m_substr( [other.m_substr copy] ){} + StringHolder() { + arcSafeRelease( m_substr ); + } + + NSString* m_substr; + }; + + struct Equals : StringHolder { + Equals( NSString* substr ) : StringHolder( substr ){} + + virtual bool match( ExpressionType const& str ) const { + return (str != nil || m_substr == nil ) && + [str isEqualToString:m_substr]; + } + + virtual std::string toString() const { + return "equals string: " + Catch::toString( m_substr ); + } + }; + + struct Contains : StringHolder { + Contains( NSString* substr ) : StringHolder( substr ){} + + virtual bool match( ExpressionType const& str ) const { + return (str != nil || m_substr == nil ) && + [str rangeOfString:m_substr].location != NSNotFound; + } + + virtual std::string toString() const { + return "contains string: " + Catch::toString( m_substr ); + } + }; + + struct StartsWith : StringHolder { + StartsWith( NSString* substr ) : StringHolder( substr ){} + + virtual bool match( ExpressionType const& str ) const { + return (str != nil || m_substr == nil ) && + [str rangeOfString:m_substr].location == 0; + } + + virtual std::string toString() const { + return "starts with: " + Catch::toString( m_substr ); + } + }; + struct EndsWith : StringHolder { + EndsWith( NSString* substr ) : StringHolder( substr ){} + + virtual bool match( ExpressionType const& str ) const { + return (str != nil || m_substr == nil ) && + [str rangeOfString:m_substr].location == [str length] - [m_substr length]; + } + + virtual std::string toString() const { + return "ends with: " + Catch::toString( m_substr ); + } + }; + + } // namespace NSStringMatchers + } // namespace Impl + + inline Impl::NSStringMatchers::Equals + Equals( NSString* substr ){ return Impl::NSStringMatchers::Equals( substr ); } + + inline Impl::NSStringMatchers::Contains + Contains( NSString* substr ){ return Impl::NSStringMatchers::Contains( substr ); } + + inline Impl::NSStringMatchers::StartsWith + StartsWith( NSString* substr ){ return Impl::NSStringMatchers::StartsWith( substr ); } + + inline Impl::NSStringMatchers::EndsWith + EndsWith( NSString* substr ){ return Impl::NSStringMatchers::EndsWith( substr ); } + + } // namespace Matchers + + using namespace Matchers; + +} // namespace Catch + +/////////////////////////////////////////////////////////////////////////////// +#define OC_TEST_CASE( name, desc )\ ++(NSString*) INTERNAL_CATCH_UNIQUE_NAME( Catch_Name_test ) \ +{\ +return @ name; \ +}\ ++(NSString*) INTERNAL_CATCH_UNIQUE_NAME( Catch_Description_test ) \ +{ \ +return @ desc; \ +} \ +-(void) INTERNAL_CATCH_UNIQUE_NAME( Catch_TestCase_test ) + +#endif + +#ifdef CATCH_IMPL +// #included from: internal/catch_impl.hpp +#define TWOBLUECUBES_CATCH_IMPL_HPP_INCLUDED + +// Collect all the implementation files together here +// These are the equivalent of what would usually be cpp files + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wweak-vtables" +#endif + +// #included from: ../catch_session.hpp +#define TWOBLUECUBES_CATCH_RUNNER_HPP_INCLUDED + +// #included from: internal/catch_commandline.hpp +#define TWOBLUECUBES_CATCH_COMMANDLINE_HPP_INCLUDED + +// #included from: catch_config.hpp +#define TWOBLUECUBES_CATCH_CONFIG_HPP_INCLUDED + +// #included from: catch_test_spec_parser.hpp +#define TWOBLUECUBES_CATCH_TEST_SPEC_PARSER_HPP_INCLUDED + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wpadded" +#endif + +// #included from: catch_test_spec.hpp +#define TWOBLUECUBES_CATCH_TEST_SPEC_HPP_INCLUDED + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wpadded" +#endif + +// #included from: catch_wildcard_pattern.hpp +#define TWOBLUECUBES_CATCH_WILDCARD_PATTERN_HPP_INCLUDED + +namespace Catch +{ + class WildcardPattern { + enum WildcardPosition { + NoWildcard = 0, + WildcardAtStart = 1, + WildcardAtEnd = 2, + WildcardAtBothEnds = WildcardAtStart | WildcardAtEnd + }; + + public: + + WildcardPattern( std::string const& pattern, CaseSensitive::Choice caseSensitivity ) + : m_caseSensitivity( caseSensitivity ), + m_wildcard( NoWildcard ), + m_pattern( adjustCase( pattern ) ) + { + if( startsWith( m_pattern, '*' ) ) { + m_pattern = m_pattern.substr( 1 ); + m_wildcard = WildcardAtStart; + } + if( endsWith( m_pattern, '*' ) ) { + m_pattern = m_pattern.substr( 0, m_pattern.size()-1 ); + m_wildcard = static_cast( m_wildcard | WildcardAtEnd ); + } + } + virtual ~WildcardPattern(); + virtual bool matches( std::string const& str ) const { + switch( m_wildcard ) { + case NoWildcard: + return m_pattern == adjustCase( str ); + case WildcardAtStart: + return endsWith( adjustCase( str ), m_pattern ); + case WildcardAtEnd: + return startsWith( adjustCase( str ), m_pattern ); + case WildcardAtBothEnds: + return contains( adjustCase( str ), m_pattern ); + } + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunreachable-code" +#endif + throw std::logic_error( "Unknown enum" ); +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + } + private: + std::string adjustCase( std::string const& str ) const { + return m_caseSensitivity == CaseSensitive::No ? toLower( str ) : str; + } + CaseSensitive::Choice m_caseSensitivity; + WildcardPosition m_wildcard; + std::string m_pattern; + }; +} + +#include +#include + +namespace Catch { + + class TestSpec { + struct Pattern : SharedImpl<> { + virtual ~Pattern(); + virtual bool matches( TestCaseInfo const& testCase ) const = 0; + }; + class NamePattern : public Pattern { + public: + NamePattern( std::string const& name ) + : m_wildcardPattern( toLower( name ), CaseSensitive::No ) + {} + virtual ~NamePattern(); + virtual bool matches( TestCaseInfo const& testCase ) const { + return m_wildcardPattern.matches( toLower( testCase.name ) ); + } + private: + WildcardPattern m_wildcardPattern; + }; + + class TagPattern : public Pattern { + public: + TagPattern( std::string const& tag ) : m_tag( toLower( tag ) ) {} + virtual ~TagPattern(); + virtual bool matches( TestCaseInfo const& testCase ) const { + return testCase.lcaseTags.find( m_tag ) != testCase.lcaseTags.end(); + } + private: + std::string m_tag; + }; + + class ExcludedPattern : public Pattern { + public: + ExcludedPattern( Ptr const& underlyingPattern ) : m_underlyingPattern( underlyingPattern ) {} + virtual ~ExcludedPattern(); + virtual bool matches( TestCaseInfo const& testCase ) const { return !m_underlyingPattern->matches( testCase ); } + private: + Ptr m_underlyingPattern; + }; + + struct Filter { + std::vector > m_patterns; + + bool matches( TestCaseInfo const& testCase ) const { + // All patterns in a filter must match for the filter to be a match + for( std::vector >::const_iterator it = m_patterns.begin(), itEnd = m_patterns.end(); it != itEnd; ++it ) { + if( !(*it)->matches( testCase ) ) + return false; + } + return true; + } + }; + + public: + bool hasFilters() const { + return !m_filters.empty(); + } + bool matches( TestCaseInfo const& testCase ) const { + // A TestSpec matches if any filter matches + for( std::vector::const_iterator it = m_filters.begin(), itEnd = m_filters.end(); it != itEnd; ++it ) + if( it->matches( testCase ) ) + return true; + return false; + } + + private: + std::vector m_filters; + + friend class TestSpecParser; + }; +} + +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + +namespace Catch { + + class TestSpecParser { + enum Mode{ None, Name, QuotedName, Tag, EscapedName }; + 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; + + public: + TestSpecParser( ITagAliasRegistry const& tagAliases ) : m_tagAliases( &tagAliases ) {} + + TestSpecParser& parse( std::string const& arg ) { + m_mode = None; + m_exclusion = false; + m_start = std::string::npos; + m_arg = m_tagAliases->expandAliases( arg ); + 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 ); } + template + void addPattern() { + std::string token = subString(); + for( size_t i = 0; i < m_escapeChars.size(); ++i ) + token = token.substr( 0, m_escapeChars[i]-i ) + token.substr( m_escapeChars[i]+1-i ); + m_escapeChars.clear(); + if( startsWith( token, "exclude:" ) ) { + m_exclusion = true; + token = token.substr( 8 ); + } + if( !token.empty() ) { + Ptr pattern = new T( token ); + if( m_exclusion ) + pattern = new TestSpec::ExcludedPattern( pattern ); + m_currentFilter.m_patterns.push_back( pattern ); + } + m_exclusion = false; + m_mode = None; + } + void addFilter() { + if( !m_currentFilter.m_patterns.empty() ) { + m_testSpec.m_filters.push_back( m_currentFilter ); + m_currentFilter = TestSpec::Filter(); + } + } + }; + inline TestSpec parseTestSpec( std::string const& arg ) { + return TestSpecParser( ITagAliasRegistry::get() ).parse( arg ).testSpec(); + } + +} // namespace Catch + +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + +// #included from: catch_interfaces_config.h +#define TWOBLUECUBES_CATCH_INTERFACES_CONFIG_H_INCLUDED + +#include +#include +#include + +namespace Catch { + + struct Verbosity { enum Level { + NoOutput = 0, + Quiet, + Normal + }; }; + + struct WarnAbout { enum What { + Nothing = 0x00, + NoAssertions = 0x01 + }; }; + + struct ShowDurations { enum OrNot { + DefaultForReporter, + Always, + Never + }; }; + struct RunTests { enum InWhatOrder { + InDeclarationOrder, + InLexicographicalOrder, + InRandomOrder + }; }; + struct UseColour { enum YesOrNo { + Auto, + Yes, + No + }; }; + + class TestSpec; + + struct IConfig : IShared { + + virtual ~IConfig(); + + virtual bool allowThrows() const = 0; + virtual std::ostream& stream() const = 0; + virtual std::string name() const = 0; + virtual bool includeSuccessfulResults() const = 0; + virtual bool shouldDebugBreak() const = 0; + virtual bool warnAboutMissingAssertions() const = 0; + virtual int abortAfter() const = 0; + virtual bool showInvisibles() const = 0; + virtual ShowDurations::OrNot showDurations() const = 0; + virtual TestSpec const& testSpec() const = 0; + virtual RunTests::InWhatOrder runOrder() const = 0; + virtual unsigned int rngSeed() const = 0; + virtual UseColour::YesOrNo useColour() const = 0; + virtual std::vector const& getSectionsToRun() const = 0; + + }; +} + +// #included from: catch_stream.h +#define TWOBLUECUBES_CATCH_STREAM_H_INCLUDED + +// #included from: catch_streambuf.h +#define TWOBLUECUBES_CATCH_STREAMBUF_H_INCLUDED + +#include + +namespace Catch { + + class StreamBufBase : public std::streambuf { + public: + virtual ~StreamBufBase() CATCH_NOEXCEPT; + }; +} + +#include +#include +#include +#include + +namespace Catch { + + std::ostream& cout(); + std::ostream& cerr(); + + struct IStream { + virtual ~IStream() CATCH_NOEXCEPT; + virtual std::ostream& stream() const = 0; + }; + + class FileStream : public IStream { + mutable std::ofstream m_ofs; + public: + FileStream( std::string const& filename ); + virtual ~FileStream() CATCH_NOEXCEPT; + public: // IStream + virtual std::ostream& stream() const CATCH_OVERRIDE; + }; + + class CoutStream : public IStream { + mutable std::ostream m_os; + public: + CoutStream(); + virtual ~CoutStream() CATCH_NOEXCEPT; + + public: // IStream + virtual std::ostream& stream() const CATCH_OVERRIDE; + }; + + class DebugOutStream : public IStream { + CATCH_AUTO_PTR( StreamBufBase ) m_streamBuf; + mutable std::ostream m_os; + public: + DebugOutStream(); + virtual ~DebugOutStream() CATCH_NOEXCEPT; + + public: // IStream + virtual std::ostream& stream() const CATCH_OVERRIDE; + }; +} + +#include +#include +#include +#include +#include + +#ifndef CATCH_CONFIG_CONSOLE_WIDTH +#define CATCH_CONFIG_CONSOLE_WIDTH 80 +#endif + +namespace Catch { + + struct ConfigData { + + ConfigData() + : listTests( false ), + listTags( false ), + listReporters( false ), + listTestNamesOnly( false ), + showSuccessfulTests( false ), + shouldDebugBreak( false ), + noThrow( false ), + showHelp( false ), + showInvisibles( false ), + filenamesAsTags( false ), + abortAfter( -1 ), + rngSeed( 0 ), + verbosity( Verbosity::Normal ), + warnings( WarnAbout::Nothing ), + showDurations( ShowDurations::DefaultForReporter ), + runOrder( RunTests::InDeclarationOrder ), + useColour( UseColour::Auto ) + {} + + bool listTests; + bool listTags; + bool listReporters; + bool listTestNamesOnly; + + bool showSuccessfulTests; + bool shouldDebugBreak; + bool noThrow; + bool showHelp; + bool showInvisibles; + bool filenamesAsTags; + + int abortAfter; + unsigned int rngSeed; + + Verbosity::Level verbosity; + WarnAbout::What warnings; + ShowDurations::OrNot showDurations; + RunTests::InWhatOrder runOrder; + UseColour::YesOrNo useColour; + + std::string outputFilename; + std::string name; + std::string processName; + + std::vector reporterNames; + std::vector testsOrTags; + std::vector sectionsToRun; + }; + + class Config : public SharedImpl { + private: + Config( Config const& other ); + Config& operator = ( Config const& other ); + virtual void dummy(); + public: + + Config() + {} + + Config( ConfigData const& data ) + : m_data( data ), + m_stream( openStream() ) + { + if( !data.testsOrTags.empty() ) { + TestSpecParser parser( ITagAliasRegistry::get() ); + for( std::size_t i = 0; i < data.testsOrTags.size(); ++i ) + parser.parse( data.testsOrTags[i] ); + m_testSpec = parser.testSpec(); + } + } + + virtual ~Config() { + } + + std::string const& getFilename() const { + return m_data.outputFilename ; + } + + bool listTests() const { return m_data.listTests; } + bool listTestNamesOnly() const { return m_data.listTestNamesOnly; } + bool listTags() const { return m_data.listTags; } + bool listReporters() const { return m_data.listReporters; } + + std::string getProcessName() const { return m_data.processName; } + + bool shouldDebugBreak() const { return m_data.shouldDebugBreak; } + + std::vector const& getReporterNames() const { return m_data.reporterNames; } + std::vector const& getSectionsToRun() const CATCH_OVERRIDE { return m_data.sectionsToRun; } + + int abortAfter() const { return m_data.abortAfter; } + + TestSpec const& testSpec() const { return m_testSpec; } + + bool showHelp() const { return m_data.showHelp; } + bool showInvisibles() const { return m_data.showInvisibles; } + + // IConfig interface + virtual bool allowThrows() const { return !m_data.noThrow; } + virtual std::ostream& stream() const { return m_stream->stream(); } + virtual std::string name() const { return m_data.name.empty() ? m_data.processName : m_data.name; } + virtual bool includeSuccessfulResults() const { return m_data.showSuccessfulTests; } + virtual bool warnAboutMissingAssertions() const { return m_data.warnings & WarnAbout::NoAssertions; } + virtual ShowDurations::OrNot showDurations() const { return m_data.showDurations; } + virtual RunTests::InWhatOrder runOrder() const { return m_data.runOrder; } + virtual unsigned int rngSeed() const { return m_data.rngSeed; } + virtual UseColour::YesOrNo useColour() const { return m_data.useColour; } + + private: + + IStream const* openStream() { + if( m_data.outputFilename.empty() ) + return new CoutStream(); + else if( m_data.outputFilename[0] == '%' ) { + if( m_data.outputFilename == "%debug" ) + return new DebugOutStream(); + else + throw std::domain_error( "Unrecognised stream: " + m_data.outputFilename ); + } + else + return new FileStream( m_data.outputFilename ); + } + ConfigData m_data; + + CATCH_AUTO_PTR( IStream const ) m_stream; + TestSpec m_testSpec; + }; + +} // end namespace Catch + +// #included from: catch_clara.h +#define TWOBLUECUBES_CATCH_CLARA_H_INCLUDED + +// Use Catch's value for console width (store Clara's off to the side, if present) +#ifdef CLARA_CONFIG_CONSOLE_WIDTH +#define CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH CLARA_CONFIG_CONSOLE_WIDTH +#undef CLARA_CONFIG_CONSOLE_WIDTH +#endif +#define CLARA_CONFIG_CONSOLE_WIDTH CATCH_CONFIG_CONSOLE_WIDTH + +// Declare Clara inside the Catch namespace +#define STITCH_CLARA_OPEN_NAMESPACE namespace Catch { +// #included from: ../external/clara.h + +// Version 0.0.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 +#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(); + } + + 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 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( ::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( 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[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 + +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( "Argment to --rng-seed should be the word 'time' or a number" ); + } + } + inline void setVerbosity( ConfigData& config, int level ) { + // !TBD: accept strings? + config.verbosity = static_cast( 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-reporters"] + .describe( "list all reporters" ) + .bind( &ConfigData::listReporters ); + + cli["--order"] + .describe( "test case order (defaults to decl)" ) + .bind( &setOrder, "decl|lex|rand" ); + + cli["--rng-seed"] + .describe( "set a specific seed for random numbers" ) + .bind( &setRngSeed, "'time'|number" ); + + cli["--force-colour"] + .describe( "force colourised output (deprecated)" ) + .bind( &forceColour ); + + cli["--use-colour"] + .describe( "should output be colourised" ) + .bind( &setUseColour, "yes|no" ); + + return cli; + } + +} // end namespace Catch + +// #included from: internal/catch_list.hpp +#define TWOBLUECUBES_CATCH_LIST_HPP_INCLUDED + +// #included from: catch_text.h +#define TWOBLUECUBES_CATCH_TEXT_H_INCLUDED + +#define TBC_TEXT_FORMAT_CONSOLE_WIDTH CATCH_CONFIG_CONSOLE_WIDTH + +#define CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE Catch +// #included from: ../external/tbc_text_format.h +// Only use header guard if we are not using an outer namespace +#ifndef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE +# ifdef TWOBLUECUBES_TEXT_FORMAT_H_INCLUDED +# ifndef TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED +# define TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED +# endif +# else +# define TWOBLUECUBES_TEXT_FORMAT_H_INCLUDED +# endif +#endif +#ifndef TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED +#include +#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 { + + struct Colour { + enum Code { + None = 0, + + White, + Red, + Green, + Blue, + Cyan, + Yellow, + Grey, + + Bright = 0x10, + + BrightRed = Bright | Red, + BrightGreen = Bright | Green, + LightGrey = Bright | Grey, + BrightWhite = Bright | White, + + // By intention + FileName = LightGrey, + Warning = Yellow, + ResultError = BrightRed, + ResultSuccess = BrightGreen, + ResultExpectedFailure = Warning, + + Error = BrightRed, + Success = Green, + + OriginalExpression = Cyan, + ReconstructedExpression = Yellow, + + SecondaryText = LightGrey, + Headers = White + }; + + // Use constructed object for RAII guard + Colour( Code _colourCode ); + Colour( Colour const& other ); + ~Colour(); + + // Use static method for one-shot changes + static void use( Code _colourCode ); + + private: + bool m_moved; + }; + + inline std::ostream& operator << ( std::ostream& os, Colour const& ) { return os; } + +} // end namespace Catch + +// #included from: catch_interfaces_reporter.h +#define TWOBLUECUBES_CATCH_INTERFACES_REPORTER_H_INCLUDED + +#include +#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 ) { + + TestSpec testSpec = config.testSpec(); + if( config.testSpec().hasFilters() ) + Catch::cout() << "Matching test cases:\n"; + else { + Catch::cout() << "All available test cases:\n"; + testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "*" ).testSpec(); + } + + std::size_t matchedTests = 0; + TextAttributes nameAttr, tagsAttr; + nameAttr.setInitialIndent( 2 ).setIndent( 4 ); + tagsAttr.setIndent( 6 ); + + std::vector 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( !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 << '"' << std::endl; + else + Catch::cout() << testCaseInfo.name << std::endl; + } + return matchedTests; + } + + struct TagInfo { + TagInfo() : count ( 0 ) {} + void add( std::string const& spelling ) { + ++count; + spellings.insert( spelling ); + } + std::string all() const { + std::string out; + for( std::set::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(); + } + + std::map tagCounts; + + 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 ); + } + } + + 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(); + } + + inline std::size_t listReporters( Config const& /*config*/ ) { + Catch::cout() << "Available reporters:\n"; + IReporterRegistry::FactoryMap const& factories = getRegistryHub().getReporterRegistry().getFactories(); + IReporterRegistry::FactoryMap::const_iterator itBegin = factories.begin(), itEnd = factories.end(), it; + std::size_t maxNameLen = 0; + for(it = itBegin; it != itEnd; ++it ) + maxNameLen = (std::max)( maxNameLen, it->first.size() ); + + for(it = itBegin; it != itEnd; ++it ) { + Text wrapper( it->second->getDescription(), TextAttributes() + .setInitialIndent( 0 ) + .setIndent( 7+maxNameLen ) + .setWidth( CATCH_CONFIG_CONSOLE_WIDTH - maxNameLen-8 ) ); + Catch::cout() << " " + << it->first + << ':' + << std::string( maxNameLen - it->first.size() + 2, ' ' ) + << wrapper << '\n'; + } + Catch::cout() << std::endl; + return factories.size(); + } + + inline Option 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 + +// #included from: internal/catch_run_context.hpp +#define TWOBLUECUBES_CATCH_RUNNER_IMPL_HPP_INCLUDED + +// #included from: catch_test_case_tracker.hpp +#define TWOBLUECUBES_CATCH_TEST_CASE_TRACKER_HPP_INCLUDED + +#include +#include +#include +#include +#include + +namespace Catch { +namespace TestCaseTracking { + + struct NameAndLocation { + std::string name; + SourceLineInfo location; + + NameAndLocation( std::string const& _name, SourceLineInfo const& _location ) + : name( _name ), + location( _location ) + {} + }; + + struct ITracker : SharedImpl<> { + virtual ~ITracker(); + + // static queries + virtual NameAndLocation const& nameAndLocation() const = 0; + + // dynamic queries + virtual bool isComplete() const = 0; // Successfully completed or failed + virtual bool isSuccessfullyCompleted() const = 0; + virtual bool isOpen() const = 0; // Started but not complete + virtual bool hasChildren() const = 0; + + virtual ITracker& parent() = 0; + + // actions + virtual void close() = 0; // Successfully complete + virtual void fail() = 0; + virtual void markAsNeedingAnotherRun() = 0; + + virtual void addChild( Ptr const& child ) = 0; + virtual ITracker* findChild( NameAndLocation const& nameAndLocation ) = 0; + virtual void openChild() = 0; + + // Debug/ checking + virtual bool isSectionTracker() const = 0; + virtual bool isIndexTracker() const = 0; + }; + + class TrackerContext { + + enum RunState { + NotStarted, + Executing, + CompletedCycle + }; + + Ptr m_rootTracker; + ITracker* m_currentTracker; + RunState m_runState; + + public: + + static TrackerContext& instance() { + static TrackerContext s_instance; + return s_instance; + } + + TrackerContext() + : m_currentTracker( CATCH_NULL ), + m_runState( NotStarted ) + {} + + ITracker& startRun(); + + void endRun() { + m_rootTracker.reset(); + m_currentTracker = CATCH_NULL; + m_runState = NotStarted; + } + + void startCycle() { + m_currentTracker = m_rootTracker.get(); + m_runState = Executing; + } + void completeCycle() { + m_runState = CompletedCycle; + } + + bool completedCycle() const { + return m_runState == CompletedCycle; + } + ITracker& currentTracker() { + return *m_currentTracker; + } + void setCurrentTracker( ITracker* tracker ) { + m_currentTracker = tracker; + } + }; + + class TrackerBase : public ITracker { + protected: + enum CycleState { + NotStarted, + Executing, + ExecutingChildren, + NeedsAnotherRun, + CompletedSuccessfully, + Failed + }; + class TrackerHasName { + 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; + } + }; + typedef std::vector > Children; + NameAndLocation m_nameAndLocation; + TrackerContext& m_ctx; + ITracker* m_parent; + Children m_children; + CycleState m_runState; + public: + TrackerBase( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent ) + : m_nameAndLocation( nameAndLocation ), + m_ctx( ctx ), + m_parent( parent ), + m_runState( NotStarted ) + {} + virtual ~TrackerBase(); + + 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(); + } + + virtual void addChild( Ptr const& child ) CATCH_OVERRIDE { + m_children.push_back( child ); + } + + 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; + } + + virtual void openChild() CATCH_OVERRIDE { + if( m_runState != ExecutingChildren ) { + m_runState = ExecutingChildren; + if( m_parent ) + m_parent->openChild(); + } + } + + virtual bool isSectionTracker() const CATCH_OVERRIDE { return false; } + virtual bool isIndexTracker() const CATCH_OVERRIDE { return false; } + + void open() { + m_runState = Executing; + moveToThis(); + if( m_parent ) + m_parent->openChild(); + } + + virtual void close() CATCH_OVERRIDE { + + // Close any still open children (e.g. generators) + while( &m_ctx.currentTracker() != this ) + m_ctx.currentTracker().close(); + + switch( m_runState ) { + case NotStarted: + case CompletedSuccessfully: + case Failed: + throw std::logic_error( "Illogical state" ); + + case NeedsAnotherRun: + break;; + + case Executing: + m_runState = CompletedSuccessfully; + break; + case ExecutingChildren: + if( m_children.empty() || m_children.back()->isComplete() ) + m_runState = CompletedSuccessfully; + break; + + default: + throw std::logic_error( "Unexpected state" ); + } + moveToParent(); + m_ctx.completeCycle(); + } + virtual void fail() CATCH_OVERRIDE { + m_runState = Failed; + if( m_parent ) + m_parent->markAsNeedingAnotherRun(); + moveToParent(); + m_ctx.completeCycle(); + } + virtual void markAsNeedingAnotherRun() CATCH_OVERRIDE { + m_runState = NeedsAnotherRun; + } + private: + void moveToParent() { + assert( m_parent ); + m_ctx.setCurrentTracker( m_parent ); + } + void moveToThis() { + m_ctx.setCurrentTracker( this ); + } + }; + + class SectionTracker : public TrackerBase { + 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& parentSection = static_cast( *parent ); + addNextFilters( parentSection.m_filters ); + } + } + virtual ~SectionTracker(); + + virtual bool isSectionTracker() const CATCH_OVERRIDE { return true; } + + static SectionTracker& acquire( TrackerContext& ctx, NameAndLocation const& nameAndLocation ) { + SectionTracker* section = CATCH_NULL; + + 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 + std::copy( filters.begin(), filters.end(), std::back_inserter( m_filters ) ); + } + } + void addNextFilters( std::vector const& filters ) { + if( filters.size() > 1 ) + std::copy( filters.begin()+1, filters.end(), std::back_inserter( m_filters ) ); + } + }; + + class IndexTracker : public TrackerBase { + int m_size; + int m_index; + public: + IndexTracker( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent, int size ) + : TrackerBase( nameAndLocation, ctx, parent ), + m_size( size ), + m_index( -1 ) + {} + virtual ~IndexTracker(); + + virtual bool isIndexTracker() const CATCH_OVERRIDE { return true; } + + static IndexTracker& acquire( TrackerContext& ctx, NameAndLocation const& nameAndLocation, int size ) { + IndexTracker* tracker = CATCH_NULL; + + 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 ); + } + + 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; +using TestCaseTracking::TrackerContext; +using TestCaseTracking::SectionTracker; +using TestCaseTracking::IndexTracker; + +} // namespace Catch + +// #included from: catch_fatal_condition.hpp +#define TWOBLUECUBES_CATCH_FATAL_CONDITION_H_INCLUDED + +namespace Catch { + + // Report the error condition + inline void reportFatal( std::string const& message ) { + IContext& context = Catch::getCurrentContext(); + IResultCapture* resultCapture = context.getResultCapture(); + resultCapture->handleFatalErrorCondition( message ); + } + +} // namespace Catch + +#if defined ( CATCH_PLATFORM_WINDOWS ) ///////////////////////////////////////// + +#define NOMINMAX +#define WIN32_LEAN_AND_MEAN +#include +#undef WIN32_LEAN_AND_MEAN +#undef NOMINMAX + +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; + } + + // 32k seems enough for Catch to handle stack overflow, + // but the value was found experimentally, so there is no strong guarantee + FatalConditionHandler():m_isSet(true), m_guaranteeSize(32 * 1024), m_exceptionHandlerHandle(CATCH_NULL) { + // Register as first handler in current chain + m_exceptionHandlerHandle = AddVectoredExceptionHandler(1, handleVectoredException); + // Pass in guarantee size to be filled + SetThreadStackGuarantee(&m_guaranteeSize); + } + + void reset() { + if (m_isSet) { + // Unregister handler and restore the old guarantee + RemoveVectoredExceptionHandler(m_exceptionHandlerHandle); + SetThreadStackGuarantee(&m_guaranteeSize); + m_exceptionHandlerHandle = CATCH_NULL; + m_isSet = false; + } + } + + ~FatalConditionHandler() { + reset(); + } + private: + bool m_isSet; + ULONG m_guaranteeSize; + PVOID m_exceptionHandlerHandle; + }; + +} // namespace Catch + +#else // Not Windows - assumed to be POSIX compatible ////////////////////////// + +#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 // 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; + }; + + /////////////////////////////////////////////////////////////////////////// + + 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_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(); + dynamic_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++; + } + + if( m_reporter->assertionEnded( AssertionStats( result, m_messages, m_totals ) ) ) + m_messages.clear(); + + // Reset working state + m_lastAssertionInfo = AssertionInfo( std::string(), m_lastAssertionInfo.lineInfo, "{Unknown expression after the reported line}" , m_lastAssertionInfo.resultDisposition ); + m_lastResult = result; + } + + 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 handleFatalErrorCondition( std::string const& message ) { + ResultBuilder resultBuilder = makeUnexpectedResultBuilder(); + resultBuilder.setResultType( ResultWas::FatalErrorCondition ); + resultBuilder << message; + resultBuilder.captureExpression(); + + handleUnfinishedSections(); + + // Recreate section for test case (as we will lose the one that was in scope) + TestCaseInfo const& testCaseInfo = m_activeTestCase->getTestCaseInfo(); + SectionInfo testCaseSection( testCaseInfo.lineInfo, testCaseInfo.name, testCaseInfo.description ); + + Counts assertions; + assertions.failed = 1; + SectionStats testCaseSectionStats( testCaseSection, assertions, 0, false ); + m_reporter->sectionEnded( testCaseSectionStats ); + + TestCaseInfo testInfo = m_activeTestCase->getTestCaseInfo(); + + Totals deltaTotals; + deltaTotals.testCases.failed = 1; + m_reporter->testCaseEnded( TestCaseStats( testInfo, + deltaTotals, + 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; + try { + m_lastAssertionInfo = AssertionInfo( "TEST_CASE", testCaseInfo.lineInfo, std::string(), ResultDisposition::Normal ); + + seedRng( *m_config ); + + Timer timer; + timer.start(); + if( m_reporter->getPreferences().shouldRedirectStdOut ) { + StreamRedirect coutRedir( Catch::cout(), redirectedCout ); + StreamRedirect cerrRedir( Catch::cerr(), redirectedCerr ); + invokeActiveTestCase(); + } + else { + invokeActiveTestCase(); + } + duration = timer.getElapsedSeconds(); + } + catch( TestFailureException& ) { + // This just means the test was aborted due to failure + } + catch(...) { + makeUnexpectedResultBuilder().useActiveException(); + } + m_testCaseTracker->close(); + handleUnfinishedSections(); + m_messages.clear(); + + Counts assertions = m_totals.assertions - prevAssertions; + bool missingAssertions = testForMissingAssertions( assertions ); + + if( testCaseInfo.okToFail() ) { + std::swap( assertions.failedButOk, assertions.failed ); + m_totals.assertions.failed -= assertions.failedButOk; + m_totals.assertions.failedButOk += assertions.failedButOk; + } + + SectionStats testCaseSectionStats( testCaseSection, assertions, duration, missingAssertions ); + m_reporter->sectionEnded( testCaseSectionStats ); + } + + void invokeActiveTestCase() { + FatalConditionHandler fatalConditionHandler; // Handle signals + m_activeTestCase->invoke(); + fatalConditionHandler.reset(); + } + + private: + + ResultBuilder makeUnexpectedResultBuilder() const { + return ResultBuilder( m_lastAssertionInfo.macroName.c_str(), + m_lastAssertionInfo.lineInfo, + m_lastAssertionInfo.capturedExpression.c_str(), + m_lastAssertionInfo.resultDisposition ); + } + + void handleUnfinishedSections() { + // If sections ended prematurely due to an exception we stored their + // infos here so we can tear them down outside the unwind process. + for( std::vector::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; + }; + + IResultCapture& getResultCapture() { + if( IResultCapture* capture = getCurrentContext().getResultCapture() ) + return *capture; + else + throw std::logic_error( "No result capture instance" ); + } + +} // end namespace Catch + +// #included from: internal/catch_version.h +#define TWOBLUECUBES_CATCH_VERSION_H_INCLUDED + +namespace Catch { + + // Versioning information + struct Version { + Version( unsigned int _majorVersion, + unsigned int _minorVersion, + unsigned int _patchNumber, + std::string const& _branchName, + unsigned int _buildNumber ); + + unsigned int const majorVersion; + unsigned int const minorVersion; + unsigned int const patchNumber; + + // buildNumber is only used if branchName is not null + std::string const branchName; + unsigned int const buildNumber; + + friend std::ostream& operator << ( std::ostream& os, Version const& version ); + + private: + void operator=( Version const& ); + }; + + extern Version libraryVersion; +} + +#include +#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; + } + + Ptr makeReporter( Ptr const& config ) { + std::vector reporters = config->getReporterNames(); + if( reporters.empty() ) + reporters.push_back( "console" ); + + 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; + } + + 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 +#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; + }; +} + +namespace Catch { + + namespace { + + class RegistryHub : public IRegistryHub, public IMutableRegistryHub { + + RegistryHub( RegistryHub const& ); + void operator=( RegistryHub const& ); + + public: // IRegistryHub + RegistryHub() { + } + virtual IReporterRegistry const& getReporterRegistry() const CATCH_OVERRIDE { + return m_reporterRegistry; + } + virtual ITestCaseRegistry const& getTestCaseRegistry() const CATCH_OVERRIDE { + return m_testCaseRegistry; + } + virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() CATCH_OVERRIDE { + return m_exceptionTranslatorRegistry; + } + + public: // IMutableRegistryHub + virtual void registerReporter( std::string const& name, Ptr 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 ); + } + + private: + TestRegistry m_testCaseRegistry; + ReporterRegistry m_reporterRegistry; + ExceptionTranslatorRegistry m_exceptionTranslatorRegistry; + }; + + // Single, global, instance + inline RegistryHub*& getTheRegistryHub() { + static RegistryHub* theRegistryHub = CATCH_NULL; + if( !theRegistryHub ) + theRegistryHub = new RegistryHub(); + return theRegistryHub; + } + } + + IRegistryHub& getRegistryHub() { + return *getTheRegistryHub(); + } + IMutableRegistryHub& getMutableRegistryHub() { + return *getTheRegistryHub(); + } + void cleanUp() { + delete getTheRegistryHub(); + getTheRegistryHub() = CATCH_NULL; + cleanUpContext(); + } + std::string translateActiveException() { + return getRegistryHub().getExceptionTranslatorRegistry().translateActiveException(); + } + +} // end namespace Catch + +// #included from: catch_notimplemented_exception.hpp +#define TWOBLUECUBES_CATCH_NOTIMPLEMENTED_EXCEPTION_HPP_INCLUDED + +#include + +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; + } +#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 + +namespace Catch { + namespace { + + struct IColourImpl { + virtual ~IColourImpl() {} + virtual void use( Colour::Code _colourCode ) = 0; + }; + + struct NoColourImpl : IColourImpl { + void use( Colour::Code ) {} + + static IColourImpl* instance() { + static NoColourImpl s_instance; + return &s_instance; + } + }; + + } // anon namespace +} // namespace Catch + +#if !defined( CATCH_CONFIG_COLOUR_NONE ) && !defined( CATCH_CONFIG_COLOUR_WINDOWS ) && !defined( CATCH_CONFIG_COLOUR_ANSI ) +# ifdef CATCH_PLATFORM_WINDOWS +# define CATCH_CONFIG_COLOUR_WINDOWS +# else +# define CATCH_CONFIG_COLOUR_ANSI +# endif +#endif + +#if defined ( CATCH_CONFIG_COLOUR_WINDOWS ) ///////////////////////////////////////// + +// #included from: catch_windows_h_proxy.h + +#define TWOBLUECUBES_CATCH_WINDOWS_H_PROXY_H_INCLUDED + +#ifdef CATCH_DEFINES_NOMINMAX +# define NOMINMAX +#endif +#ifdef CATCH_DEFINES_WIN32_LEAN_AND_MEAN +# define WIN32_LEAN_AND_MEAN +#endif + +#ifdef __AFXDLL +#include +#else +#include +#endif + +#ifdef CATCH_DEFINES_NOMINMAX +# undef NOMINMAX +#endif +#ifdef CATCH_DEFINES_WIN32_LEAN_AND_MEAN +# undef WIN32_LEAN_AND_MEAN +#endif + +namespace Catch { +namespace { + + class Win32ColourImpl : public IColourImpl { + public: + Win32ColourImpl() : stdoutHandle( GetStdHandle(STD_OUTPUT_HANDLE) ) + { + CONSOLE_SCREEN_BUFFER_INFO csbiInfo; + GetConsoleScreenBufferInfo( stdoutHandle, &csbiInfo ); + originalForegroundAttributes = csbiInfo.wAttributes & ~( BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_BLUE | BACKGROUND_INTENSITY ); + originalBackgroundAttributes = csbiInfo.wAttributes & ~( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY ); + } + + virtual void use( Colour::Code _colourCode ) { + switch( _colourCode ) { + case Colour::None: return setTextAttribute( originalForegroundAttributes ); + case Colour::White: return setTextAttribute( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE ); + case Colour::Red: return setTextAttribute( FOREGROUND_RED ); + case Colour::Green: return setTextAttribute( FOREGROUND_GREEN ); + case Colour::Blue: return setTextAttribute( FOREGROUND_BLUE ); + case Colour::Cyan: return setTextAttribute( FOREGROUND_BLUE | FOREGROUND_GREEN ); + case Colour::Yellow: return setTextAttribute( FOREGROUND_RED | FOREGROUND_GREEN ); + case Colour::Grey: return setTextAttribute( 0 ); + + case Colour::LightGrey: return setTextAttribute( FOREGROUND_INTENSITY ); + case Colour::BrightRed: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_RED ); + case Colour::BrightGreen: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN ); + case Colour::BrightWhite: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE ); + + case Colour::Bright: throw std::logic_error( "not a colour" ); + } + } + + private: + void setTextAttribute( WORD _textAttribute ) { + SetConsoleTextAttribute( stdoutHandle, _textAttribute | originalBackgroundAttributes ); + } + HANDLE stdoutHandle; + WORD originalForegroundAttributes; + WORD originalBackgroundAttributes; + }; + + IColourImpl* platformColourInstance() { + static Win32ColourImpl s_instance; + + Ptr config = getCurrentContext().getConfig(); + UseColour::YesOrNo colourMode = config + ? config->useColour() + : UseColour::Auto; + if( colourMode == UseColour::Auto ) + colourMode = !isDebuggerActive() + ? UseColour::Yes + : UseColour::No; + return colourMode == UseColour::Yes + ? &s_instance + : NoColourImpl::instance(); + } + +} // end anon namespace +} // end namespace Catch + +#elif defined( CATCH_CONFIG_COLOUR_ANSI ) ////////////////////////////////////// + +#include + +namespace Catch { +namespace { + + // use POSIX/ ANSI console terminal codes + // Thanks to Adam Strzelecki for original contribution + // (http://github.com/nanoant) + // https://github.com/philsquared/Catch/pull/131 + class PosixColourImpl : public IColourImpl { + public: + virtual void use( Colour::Code _colourCode ) { + switch( _colourCode ) { + case Colour::None: + case Colour::White: return setColour( "[0m" ); + case Colour::Red: return setColour( "[0;31m" ); + case Colour::Green: return setColour( "[0;32m" ); + case Colour::Blue: return setColour( "[0;34m" ); + case Colour::Cyan: return setColour( "[0;36m" ); + case Colour::Yellow: return setColour( "[0;33m" ); + case Colour::Grey: return setColour( "[1;30m" ); + + case Colour::LightGrey: return setColour( "[0;37m" ); + case Colour::BrightRed: return setColour( "[1;31m" ); + case Colour::BrightGreen: return setColour( "[1;32m" ); + case Colour::BrightWhite: return setColour( "[1;37m" ); + + case Colour::Bright: throw std::logic_error( "not a colour" ); + } + } + static IColourImpl* instance() { + static PosixColourImpl s_instance; + return &s_instance; + } + + private: + void setColour( const char* _escapeCode ) { + Catch::cout() << '\033' << _escapeCode; + } + }; + + IColourImpl* platformColourInstance() { + Ptr config = getCurrentContext().getConfig(); + UseColour::YesOrNo colourMode = config + ? config->useColour() + : UseColour::Auto; + if( colourMode == UseColour::Auto ) + colourMode = (!isDebuggerActive() && isatty(STDOUT_FILENO) ) + ? UseColour::Yes + : UseColour::No; + return colourMode == UseColour::Yes + ? PosixColourImpl::instance() + : NoColourImpl::instance(); + } + +} // end anon namespace +} // end namespace Catch + +#else // not Windows or ANSI /////////////////////////////////////////////// + +namespace Catch { + + static IColourImpl* platformColourInstance() { return NoColourImpl::instance(); } + +} // end namespace Catch + +#endif // Windows/ ANSI/ None + +namespace Catch { + + Colour::Colour( Code _colourCode ) : m_moved( false ) { use( _colourCode ); } + Colour::Colour( Colour const& _other ) : m_moved( false ) { const_cast( _other ).m_moved = true; } + Colour::~Colour(){ if( !m_moved ) use( None ); } + + void Colour::use( Code _colourCode ) { + static IColourImpl* impl = platformColourInstance(); + impl->use( _colourCode ); + } + +} // end namespace Catch + +// #included from: catch_generators_impl.hpp +#define TWOBLUECUBES_CATCH_GENERATORS_IMPL_HPP_INCLUDED + +#include +#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( std::string const& _macroName, + SourceLineInfo const& _lineInfo, + std::string const& _capturedExpression, + ResultDisposition::Flags _resultDisposition ) + : macroName( _macroName ), + lineInfo( _lineInfo ), + capturedExpression( _capturedExpression ), + resultDisposition( _resultDisposition ) + {} + + AssertionResult::AssertionResult() {} + + AssertionResult::AssertionResult( AssertionInfo const& info, AssertionResultData const& data ) + : m_info( info ), + m_resultData( data ) + {} + + AssertionResult::~AssertionResult() {} + + // Result was a success + bool AssertionResult::succeeded() const { + return Catch::isOk( m_resultData.resultType ); + } + + // Result was a success, or failure is suppressed + bool AssertionResult::isOk() const { + return Catch::isOk( m_resultData.resultType ) || shouldSuppressFailure( m_info.resultDisposition ); + } + + ResultWas::OfType AssertionResult::getResultType() const { + return m_resultData.resultType; + } + + bool AssertionResult::hasExpression() const { + return !m_info.capturedExpression.empty(); + } + + bool AssertionResult::hasMessage() const { + return !m_resultData.message.empty(); + } + + std::string AssertionResult::getExpression() const { + if( isFalseTest( m_info.resultDisposition ) ) + return '!' + m_info.capturedExpression; + else + return m_info.capturedExpression; + } + std::string AssertionResult::getExpressionInMacro() const { + if( m_info.macroName.empty() ) + return m_info.capturedExpression; + else + return m_info.macroName + "( " + m_info.capturedExpression + " )"; + } + + bool AssertionResult::hasExpandedExpression() const { + return hasExpression() && getExpandedExpression() != getExpression(); + } + + std::string AssertionResult::getExpandedExpression() const { + return m_resultData.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 + +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 && !isalnum( tag[0] ); + } + inline void enforceNotReservedTag( std::string const& tag, SourceLineInfo const& _lineInfo ) { + if( isReservedTag( tag ) ) { + { + Colour colourGuard( Colour::Red ); + Catch::cerr() + << "Tag name [" << tag << "] not allowed.\n" + << "Tag names starting with non alpha-numeric characters are reserved\n"; + } + { + Colour colourGuard( Colour::FileName ); + Catch::cerr() << _lineInfo << std::endl; + } + exit(1); + } + } + + TestCase makeTestCase( ITestCase* _testCase, + std::string const& _className, + std::string const& _name, + std::string const& _descOrTags, + SourceLineInfo const& _lineInfo ) + { + bool isHidden( startsWith( _name, "./" ) ); // Legacy support + + // Parse out tags + std::set 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, + std::string const& _branchName, + unsigned int _buildNumber ) + : majorVersion( _majorVersion ), + minorVersion( _minorVersion ), + patchNumber( _patchNumber ), + branchName( _branchName ), + buildNumber( _buildNumber ) + {} + + std::ostream& operator << ( std::ostream& os, Version const& version ) { + os << version.majorVersion << '.' + << version.minorVersion << '.' + << version.patchNumber; + + if( !version.branchName.empty() ) { + os << '-' << version.branchName + << '.' << version.buildNumber; + } + return os; + } + + Version libraryVersion( 1, 7, 0, "", 0 ); + +} + +// #included from: catch_message.hpp +#define TWOBLUECUBES_CATCH_MESSAGE_HPP_INCLUDED + +namespace Catch { + + MessageInfo::MessageInfo( std::string const& _macroName, + SourceLineInfo const& _lineInfo, + ResultWas::OfType _type ) + : macroName( _macroName ), + lineInfo( _lineInfo ), + type( _type ), + sequence( ++globalCount ) + {} + + // This may need protecting if threading support is added + unsigned int MessageInfo::globalCount = 0; + + //////////////////////////////////////////////////////////////////////////// + + ScopedMessage::ScopedMessage( MessageBuilder const& builder ) + : m_info( builder.m_info ) + { + m_info.message = builder.m_stream.str(); + getResultCapture().pushScopedMessage( m_info ); + } + ScopedMessage::ScopedMessage( ScopedMessage const& other ) + : m_info( other.m_info ) + {} + + ScopedMessage::~ScopedMessage() { + getResultCapture().popScopedMessage( m_info ); + } + +} // end namespace Catch + +// #included from: catch_legacy_reporter_adapter.hpp +#define TWOBLUECUBES_CATCH_LEGACY_REPORTER_ADAPTER_HPP_INCLUDED + +// #included from: catch_legacy_reporter_adapter.h +#define TWOBLUECUBES_CATCH_LEGACY_REPORTER_ADAPTER_H_INCLUDED + +namespace Catch +{ + // Deprecated + struct IReporter : IShared { + virtual ~IReporter(); + + virtual bool shouldRedirectStdout() const = 0; + + virtual void StartTesting() = 0; + virtual void EndTesting( Totals const& totals ) = 0; + virtual void StartGroup( std::string const& groupName ) = 0; + virtual void EndGroup( std::string const& groupName, Totals const& totals ) = 0; + virtual void StartTestCase( TestCaseInfo const& testInfo ) = 0; + virtual void EndTestCase( TestCaseInfo const& testInfo, Totals const& totals, std::string const& stdOut, std::string const& stdErr ) = 0; + virtual void StartSection( std::string const& sectionName, std::string const& description ) = 0; + virtual void EndSection( std::string const& sectionName, Counts const& assertions ) = 0; + virtual void NoAssertionsInSection( std::string const& sectionName ) = 0; + virtual void NoAssertionsInTestCase( std::string const& testName ) = 0; + virtual void Aborted() = 0; + virtual void Result( AssertionResult const& result ) = 0; + }; + + class LegacyReporterAdapter : public SharedImpl + { + 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" +#endif + +#ifdef CATCH_PLATFORM_WINDOWS +#else +#include +#endif + +namespace Catch { + + namespace { +#ifdef CATCH_PLATFORM_WINDOWS + uint64_t getCurrentTicks() { + static uint64_t hz=0, hzo=0; + if (!hz) { + QueryPerformanceFrequency( reinterpret_cast( &hz ) ); + QueryPerformanceCounter( reinterpret_cast( &hzo ) ); + } + uint64_t t; + QueryPerformanceCounter( reinterpret_cast( &t ) ); + return ((t-hzo)*1000000)/hz; + } +#else + uint64_t 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 + +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; + } + bool contains( std::string const& s, char infix ) { + return s.find(infix) != std::string::npos; + } + char toLowerCh(char c) { + return static_cast( ::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(); + } + + Section::~Section() { + if( m_sectionIncluded ) { + SectionEndInfo endInfo( m_info, m_assertions, m_timer.getElapsedSeconds() ); + if( std::uncaught_exception() ) + getResultCapture().sectionEndedEarly( endInfo ); + else + getResultCapture().sectionEnded( endInfo ); + } + } + + // This indicates whether the section should be executed or not + Section::operator bool() const { + return m_sectionIncluded; + } + +} // end namespace Catch + +// #included from: catch_debugger.hpp +#define TWOBLUECUBES_CATCH_DEBUGGER_HPP_INCLUDED + +#include + +#ifdef CATCH_PLATFORM_MAC + + #include + #include + #include + #include + #include + + namespace Catch{ + + // The following function is taken directly from the following technical note: + // http://developer.apple.com/library/mac/#qa/qa2004/qa1361.html + + // Returns true if the current process is being debugged (either + // running under the debugger or has a debugger attached post facto). + bool isDebuggerActive(){ + + int mib[4]; + struct kinfo_proc info; + size_t size; + + // Initialize the flags so that, if sysctl fails for some bizarre + // reason, we get a predictable result. + + info.kp_proc.p_flag = 0; + + // Initialize mib, which tells sysctl the info we want, in this case + // we're looking for information about a specific process ID. + + mib[0] = CTL_KERN; + mib[1] = KERN_PROC; + mib[2] = KERN_PROC_PID; + mib[3] = getpid(); + + // Call sysctl. + + size = sizeof(info); + if( sysctl(mib, sizeof(mib) / sizeof(*mib), &info, &size, CATCH_NULL, 0) != 0 ) { + Catch::cerr() << "\n** Call to sysctl failed - unable to determine if debugger is active **\n" << std::endl; + return false; + } + + // We're being debugged if the P_TRACED flag is set. + + return ( (info.kp_proc.p_flag & P_TRACED) != 0 ); + } + } // namespace Catch + +#elif defined(CATCH_PLATFORM_LINUX) + #include + #include + + namespace Catch{ + // The standard POSIX way of detecting a debugger is to attempt to + // ptrace() the process, but this needs to be done from a child and not + // this process itself to still allow attaching to this process later + // if wanted, so is rather heavy. Under Linux we have the PID of the + // "debugger" (which doesn't need to be gdb, of course, it could also + // be strace, for example) in /proc/$PID/status, so just get it from + // there instead. + bool isDebuggerActive(){ + std::ifstream in("/proc/self/status"); + for( std::string line; std::getline(in, line); ) { + static const int PREFIX_LEN = 11; + if( line.compare(0, PREFIX_LEN, "TracerPid:\t") == 0 ) { + // We're traced if the PID is not 0 and no other PID starts + // with 0 digit, so it's enough to check for just a single + // character. + return line.length() > PREFIX_LEN && line[PREFIX_LEN] != '0'; + } + } + + return false; + } + } // namespace Catch +#elif defined(_MSC_VER) + extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent(); + namespace Catch { + bool isDebuggerActive() { + return IsDebuggerPresent() != 0; + } + } +#elif defined(__MINGW32__) + extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent(); + namespace Catch { + bool isDebuggerActive() { + return IsDebuggerPresent() != 0; + } + } +#else + namespace Catch { + inline bool isDebuggerActive() { return false; } + } +#endif // Platform + +#ifdef CATCH_PLATFORM_WINDOWS + extern "C" __declspec(dllimport) void __stdcall OutputDebugStringA( const char* ); + namespace Catch { + void writeToDebugConsole( std::string const& text ) { + ::OutputDebugStringA( text.c_str() ); + } + } +#else + namespace Catch { + void writeToDebugConsole( std::string const& text ) { + // !TBD: Need a version for Mac/ XCode and other IDEs + Catch::cout() << text; + } + } +#endif // Platform + +// #included from: catch_tostring.hpp +#define TWOBLUECUBES_CATCH_TOSTRING_HPP_INCLUDED + +namespace Catch { + +namespace Detail { + + const std::string unprintableString = "{?}"; + + namespace { + const int hexThreshold = 255; + + struct Endianness { + enum Arch { Big, Little }; + + static Arch which() { + union _{ + int asInt; + char asChar[sizeof (int)]; + } u; + + u.asInt = 1; + return ( u.asChar[sizeof(int)-1] == 1 ) ? Big : Little; + } + }; + } + + std::string rawMemoryToString( const void *object, std::size_t size ) + { + // Reverse order for little endian architectures + int i = 0, end = static_cast( size ), inc = 1; + if( Endianness::which() == Endianness::Little ) { + i = end-1; + end = inc = -1; + } + + unsigned char const *bytes = static_cast(object); + std::ostringstream os; + os << "0x" << std::setfill('0') << std::hex; + for( ; i != end; i += inc ) + os << std::setw(2) << static_cast(bytes[i]); + return os.str(); + } +} + +std::string toString( std::string const& value ) { + std::string s = value; + if( getCurrentContext().getConfig()->showInvisibles() ) { + for(size_t i = 0; i < s.size(); ++i ) { + std::string subs; + switch( s[i] ) { + case '\n': subs = "\\n"; break; + case '\t': subs = "\\t"; break; + default: break; + } + if( !subs.empty() ) { + s = s.substr( 0, i ) + subs + s.substr( i+1 ); + ++i; + } + } + } + return '"' + s + '"'; +} +std::string toString( std::wstring const& value ) { + + std::string 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 ); +} + +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 + +#ifdef __OBJC__ + std::string toString( NSString const * const& nsstring ) { + if( !nsstring ) + return "nil"; + return "@" + toString([nsstring UTF8String]); + } + std::string toString( NSString * CATCH_ARC_STRONG const& nsstring ) { + if( !nsstring ) + return "nil"; + return "@" + toString([nsstring UTF8String]); + } + std::string toString( NSObject* const& nsObject ) { + return toString( [nsObject description] ); + } +#endif + +} // end namespace Catch + +// #included from: catch_result_builder.hpp +#define TWOBLUECUBES_CATCH_RESULT_BUILDER_HPP_INCLUDED + +namespace Catch { + + std::string capturedExpressionWithSecondArgument( std::string const& capturedExpression, std::string const& secondArg ) { + return secondArg.empty() || secondArg == "\"\"" + ? capturedExpression + : capturedExpression + ", " + secondArg; + } + ResultBuilder::ResultBuilder( char const* macroName, + SourceLineInfo const& lineInfo, + char const* capturedExpression, + ResultDisposition::Flags resultDisposition, + char const* secondArg ) + : m_assertionInfo( macroName, lineInfo, capturedExpressionWithSecondArgument( capturedExpression, secondArg ), resultDisposition ), + m_shouldDebugBreak( false ), + m_shouldThrow( false ) + {} + + ResultBuilder& ResultBuilder::setResultType( ResultWas::OfType result ) { + m_data.resultType = result; + return *this; + } + ResultBuilder& ResultBuilder::setResultType( bool result ) { + m_data.resultType = result ? ResultWas::Ok : ResultWas::ExpressionFailed; + return *this; + } + + void ResultBuilder::endExpression( DecomposedExpression const& expr ) { + AssertionResult result = build( expr ); + handleResult( result ); + } + + void ResultBuilder::useActiveException( ResultDisposition::Flags resultDisposition ) { + m_assertionInfo.resultDisposition = resultDisposition; + m_stream.oss << Catch::translateActiveException(); + captureResult( ResultWas::ThrewException ); + } + + void ResultBuilder::captureResult( ResultWas::OfType resultType ) { + setResultType( resultType ); + captureExpression(); + } + + void ResultBuilder::captureExpectedException( std::string const& expectedMessage ) { + if( expectedMessage.empty() ) + captureExpectedException( Matchers::Impl::Generic::AllOf() ); + else + captureExpectedException( Matchers::Equals( expectedMessage ) ); + } + + void ResultBuilder::captureExpectedException( Matchers::Impl::Matcher const& matcher ) { + + assert( !isFalseTest( m_assertionInfo.resultDisposition ) ); + AssertionResultData data = m_data; + data.resultType = ResultWas::Ok; + data.reconstructedExpression = m_assertionInfo.capturedExpression; + + std::string actualMessage = Catch::translateActiveException(); + if( !matcher.match( actualMessage ) ) { + data.resultType = ResultWas::ExpressionFailed; + data.reconstructedExpression = actualMessage; + } + AssertionResult result( m_assertionInfo, data ); + handleResult( result ); + } + + void ResultBuilder::captureExpression() { + AssertionResult result = build(); + handleResult( result ); + } + + void ResultBuilder::handleResult( AssertionResult const& result ) + { + getResultCapture().assertionEnded( result ); + + if( !result.isOk() ) { + if( getCurrentContext().getConfig()->shouldDebugBreak() ) + m_shouldDebugBreak = true; + if( getCurrentContext().getRunner()->aborting() || (m_assertionInfo.resultDisposition & ResultDisposition::Normal) ) + m_shouldThrow = true; + } + } + + void ResultBuilder::react() { + if( m_shouldThrow ) + throw Catch::TestFailureException(); + } + + bool ResultBuilder::shouldDebugBreak() const { return m_shouldDebugBreak; } + bool ResultBuilder::allowThrows() const { return getCurrentContext().getConfig()->allowThrows(); } + + AssertionResult ResultBuilder::build() const + { + 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; + + // Flip bool results if FalseTest flag is set + if( isFalseTest( m_assertionInfo.resultDisposition ) ) { + data.negate( expr.isBinaryExpression() ); + } + + 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 = m_assertionInfo.capturedExpression; + } + +} // end namespace Catch + +// #included from: catch_tag_alias_registry.hpp +#define TWOBLUECUBES_CATCH_TAG_ALIAS_REGISTRY_HPP_INCLUDED + +// #included from: catch_tag_alias_registry.h +#define TWOBLUECUBES_CATCH_TAG_ALIAS_REGISTRY_H_INCLUDED + +#include + +namespace Catch { + + class TagAliasRegistry : public ITagAliasRegistry { + public: + virtual ~TagAliasRegistry(); + virtual Option find( std::string const& alias ) const; + virtual std::string expandAliases( std::string const& unexpandedTestSpec ) const; + void add( char const* alias, char const* tag, SourceLineInfo const& lineInfo ); + static TagAliasRegistry& get(); + + private: + std::map m_registry; + }; + +} // end namespace Catch + +#include +#include + +namespace Catch { + + 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; + } + + void TagAliasRegistry::add( char const* alias, char const* tag, SourceLineInfo const& lineInfo ) { + + if( !startsWith( alias, "[@" ) || !endsWith( alias, ']' ) ) { + std::ostringstream oss; + oss << "error: tag alias, \"" << alias << "\" is not of the form [@alias name].\n" << lineInfo; + throw std::domain_error( oss.str().c_str() ); + } + if( !m_registry.insert( std::make_pair( alias, TagAlias( tag, lineInfo ) ) ).second ) { + std::ostringstream oss; + oss << "error: tag alias, \"" << alias << "\" already registered.\n" + << "\tFirst seen at " << find(alias)->lineInfo << '\n' + << "\tRedefined at " << lineInfo; + throw std::domain_error( oss.str().c_str() ); + } + } + + TagAliasRegistry& TagAliasRegistry::get() { + static TagAliasRegistry instance; + return instance; + + } + + ITagAliasRegistry::~ITagAliasRegistry() {} + ITagAliasRegistry const& ITagAliasRegistry::get() { return TagAliasRegistry::get(); } + + RegistrarForTagAliases::RegistrarForTagAliases( char const* alias, char const* tag, SourceLineInfo const& lineInfo ) { + try { + TagAliasRegistry::get().add( alias, tag, lineInfo ); + } + catch( std::exception& ex ) { + Colour colourGuard( Colour::Red ); + Catch::cerr() << ex.what() << std::endl; + exit(1); + } + } + +} // end namespace Catch + +// #included from: ../reporters/catch_reporter_multi.hpp +#define TWOBLUECUBES_CATCH_REPORTER_MULTI_HPP_INCLUDED + +namespace Catch { + +class MultipleReporters : public SharedImpl { + typedef std::vector > Reporters; + Reporters m_reporters; + +public: + void add( Ptr const& reporter ) { + m_reporters.push_back( reporter ); + } + +public: // IStreamingReporter + + virtual ReporterPreferences getPreferences() const CATCH_OVERRIDE { + return m_reporters[0]->getPreferences(); + } + + virtual void noMatchingTestCases( std::string const& spec ) CATCH_OVERRIDE { + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + (*it)->noMatchingTestCases( spec ); + } + + virtual void testRunStarting( TestRunInfo const& testRunInfo ) CATCH_OVERRIDE { + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + (*it)->testRunStarting( testRunInfo ); + } + + virtual void testGroupStarting( GroupInfo const& groupInfo ) CATCH_OVERRIDE { + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + (*it)->testGroupStarting( groupInfo ); + } + + virtual void testCaseStarting( TestCaseInfo const& testInfo ) CATCH_OVERRIDE { + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + (*it)->testCaseStarting( testInfo ); + } + + virtual void sectionStarting( SectionInfo const& sectionInfo ) CATCH_OVERRIDE { + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + (*it)->sectionStarting( sectionInfo ); + } + + virtual void assertionStarting( AssertionInfo const& assertionInfo ) CATCH_OVERRIDE { + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + (*it)->assertionStarting( assertionInfo ); + } + + // The return value indicates if the messages buffer should be cleared: + virtual bool assertionEnded( AssertionStats const& assertionStats ) CATCH_OVERRIDE { + bool clearBuffer = false; + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + clearBuffer |= (*it)->assertionEnded( assertionStats ); + return clearBuffer; + } + + virtual void sectionEnded( SectionStats const& sectionStats ) CATCH_OVERRIDE { + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + (*it)->sectionEnded( sectionStats ); + } + + virtual void testCaseEnded( TestCaseStats const& testCaseStats ) CATCH_OVERRIDE { + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + (*it)->testCaseEnded( testCaseStats ); + } + + virtual void testGroupEnded( TestGroupStats const& testGroupStats ) CATCH_OVERRIDE { + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + (*it)->testGroupEnded( testGroupStats ); + } + + virtual void testRunEnded( TestRunStats const& testRunStats ) CATCH_OVERRIDE { + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + (*it)->testRunEnded( testRunStats ); + } + + virtual void skipTest( TestCaseInfo const& testInfo ) CATCH_OVERRIDE { + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + (*it)->skipTest( testInfo ); + } + + 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; + + return resultingReporter; +} + +} // end namespace Catch + +// #included from: ../reporters/catch_reporter_xml.hpp +#define TWOBLUECUBES_CATCH_REPORTER_XML_HPP_INCLUDED + +// #included from: catch_reporter_bases.hpp +#define TWOBLUECUBES_CATCH_REPORTER_BASES_HPP_INCLUDED + +#include + +namespace Catch { + + 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; + } + bool operator == ( Ptr const& other ) const { + return operator==( *other ); + } + + SectionStats stats; + typedef std::vector > ChildSections; + typedef std::vector Assertions; + ChildSections childSections; + Assertions assertions; + std::string stdOut; + std::string stdErr; + }; + + struct BySectionInfo { + BySectionInfo( SectionInfo const& other ) : m_other( other ) {} + BySectionInfo( BySectionInfo const& other ) : m_other( other.m_other ) {} + bool operator() ( Ptr const& node ) const { + return node->stats.sectionInfo.lineInfo == m_other.lineInfo; + } + private: + void operator=( BySectionInfo const& ); + SectionInfo const& m_other; + }; + + typedef Node TestCaseNode; + typedef Node TestGroupNode; + typedef Node TestRunNode; + + CumulativeReporterBase( ReporterConfig const& _config ) + : m_config( _config.fullConfig() ), + stream( _config.stream() ) + { + m_reporterPrefs.shouldRedirectStdOut = false; + } + ~CumulativeReporterBase(); + + virtual ReporterPreferences getPreferences() const CATCH_OVERRIDE { + return m_reporterPrefs; + } + + virtual void testRunStarting( TestRunInfo const& ) CATCH_OVERRIDE {} + virtual void testGroupStarting( GroupInfo const& ) CATCH_OVERRIDE {} + + virtual void testCaseStarting( TestCaseInfo const& ) CATCH_OVERRIDE {} + + virtual void sectionStarting( SectionInfo const& sectionInfo ) CATCH_OVERRIDE { + SectionStats incompleteStats( sectionInfo, Counts(), 0, false ); + Ptr 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 ) { + memset( line, C, CATCH_CONFIG_CONSOLE_WIDTH-1 ); + line[CATCH_CONFIG_CONSOLE_WIDTH-1] = 0; + } + return line; + } + + struct TestEventListenerBase : StreamingReporterBase { + TestEventListenerBase( ReporterConfig const& _config ) + : StreamingReporterBase( _config ) + {} + + virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE {} + virtual bool assertionEnded( AssertionStats const& ) CATCH_OVERRIDE { + return false; + } + }; + +} // end namespace Catch + +// #included from: ../internal/catch_reporter_registrars.hpp +#define TWOBLUECUBES_CATCH_REPORTER_REGISTRARS_HPP_INCLUDED + +namespace Catch { + + template + class LegacyReporterRegistrar { + + class ReporterFactory : public IReporterFactory { + virtual IStreamingReporter* create( ReporterConfig const& config ) const { + return new LegacyReporterAdapter( new T( config ) ); + } + + virtual std::string getDescription() const { + return T::getDescription(); + } + }; + + public: + + LegacyReporterRegistrar( std::string const& name ) { + getMutableRegistryHub().registerReporter( name, new ReporterFactory() ); + } + }; + + template + 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() ); + } + }; +} + +#define INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) \ + namespace{ Catch::LegacyReporterRegistrar catch_internal_RegistrarFor##reporterType( name ); } + +#define INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType ) \ + namespace{ Catch::ReporterRegistrar catch_internal_RegistrarFor##reporterType( name ); } + +#define INTERNAL_CATCH_REGISTER_LISTENER( listenerType ) \ + namespace{ Catch::ListenerRegistrar catch_internal_RegistrarFor##listenerType; } + +// #included from: ../internal/catch_xmlwriter.hpp +#define TWOBLUECUBES_CATCH_XMLWRITER_HPP_INCLUDED + +#include +#include +#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 ) + {} + + 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' ) + 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; + ForWhat m_forWhat; + }; + + class XmlWriter { + public: + + class ScopedElement { + public: + ScopedElement( XmlWriter* writer ) + : m_writer( writer ) + {} + + ScopedElement( ScopedElement const& other ) + : m_writer( other.m_writer ){ + other.m_writer = CATCH_NULL; + } + + ~ScopedElement() { + if( m_writer ) + m_writer->endElement(); + } + + ScopedElement& writeText( std::string const& text, bool indent = true ) { + m_writer->writeText( text, indent ); + return *this; + } + + template + ScopedElement& writeAttribute( std::string const& name, T const& attribute ) { + m_writer->writeAttribute( name, attribute ); + return *this; + } + + private: + mutable XmlWriter* m_writer; + }; + + XmlWriter() + : m_tagIsOpen( false ), + m_needsNewline( false ), + m_os( &Catch::cout() ) + { + // We encode control characters, which requires + // XML 1.1 + // see http://stackoverflow.com/questions/404107/why-are-control-characters-illegal-in-xml-1-0 + *m_os << "\n"; + } + + XmlWriter( std::ostream& os ) + : m_tagIsOpen( false ), + m_needsNewline( false ), + m_os( &os ) + { + *m_os << "\n"; + } + + ~XmlWriter() { + while( !m_tags.empty() ) + endElement(); + } + + XmlWriter& startElement( std::string const& name ) { + ensureTagClosed(); + newlineIfNecessary(); + stream() << m_indent << '<' << name; + m_tags.push_back( name ); + m_indent += " "; + m_tagIsOpen = true; + return *this; + } + + ScopedElement scopedElement( std::string const& name ) { + ScopedElement scoped( this ); + startElement( name ); + return scoped; + } + + XmlWriter& endElement() { + newlineIfNecessary(); + m_indent = m_indent.substr( 0, m_indent.size()-2 ); + if( m_tagIsOpen ) { + stream() << "/>\n"; + m_tagIsOpen = false; + } + else { + stream() << m_indent << "\n"; + } + m_tags.pop_back(); + return *this; + } + + XmlWriter& writeAttribute( std::string const& name, std::string const& attribute ) { + if( !name.empty() && !attribute.empty() ) + stream() << ' ' << name << "=\"" << XmlEncode( attribute, XmlEncode::ForAttributes ) << '"'; + return *this; + } + + XmlWriter& writeAttribute( std::string const& name, bool attribute ) { + stream() << ' ' << name << "=\"" << ( attribute ? "true" : "false" ) << '"'; + return *this; + } + + template + XmlWriter& writeAttribute( std::string const& name, T const& attribute ) { + std::ostringstream oss; + oss << attribute; + return writeAttribute( name, oss.str() ); + } + + XmlWriter& writeText( std::string const& text, bool indent = true ) { + if( !text.empty() ){ + bool tagWasOpen = m_tagIsOpen; + ensureTagClosed(); + if( tagWasOpen && indent ) + stream() << m_indent; + stream() << XmlEncode( text ); + m_needsNewline = true; + } + return *this; + } + + XmlWriter& writeComment( std::string const& text ) { + ensureTagClosed(); + stream() << m_indent << ""; + m_needsNewline = true; + return *this; + } + + XmlWriter& writeBlankLine() { + ensureTagClosed(); + stream() << '\n'; + return *this; + } + + void setStream( std::ostream& os ) { + m_os = &os; + } + + private: + XmlWriter( XmlWriter const& ); + void operator=( XmlWriter const& ); + + std::ostream& stream() { + return *m_os; + } + + void ensureTagClosed() { + if( m_tagIsOpen ) { + stream() << ">\n"; + m_tagIsOpen = false; + } + } + + void newlineIfNecessary() { + if( m_needsNewline ) { + stream() << '\n'; + m_needsNewline = false; + } + } + + bool m_tagIsOpen; + bool m_needsNewline; + std::vector m_tags; + std::string m_indent; + std::ostream* m_os; + }; + +} +// #included from: catch_reenable_warnings.h + +#define TWOBLUECUBES_CATCH_REENABLE_WARNINGS_H_INCLUDED + +#ifdef __clang__ +# ifdef __ICC // icpc defines the __clang__ macro +# pragma warning(pop) +# else +# pragma clang diagnostic pop +# endif +#elif defined __GNUC__ +# pragma GCC diagnostic pop +#endif + + +namespace Catch { + class XmlReporter : public StreamingReporterBase { + public: + XmlReporter( ReporterConfig const& _config ) + : StreamingReporterBase( _config ), + m_xml(_config.stream()), + m_sectionDepth( 0 ) + { + m_reporterPrefs.shouldRedirectStdOut = true; + } + + virtual ~XmlReporter() CATCH_OVERRIDE; + + static std::string getDescription() { + return "Reports test results as an XML document"; + } + + public: // StreamingReporterBase + + virtual void noMatchingTestCases( std::string const& s ) CATCH_OVERRIDE { + StreamingReporterBase::noMatchingTestCases( s ); + } + + virtual void testRunStarting( TestRunInfo const& testInfo ) CATCH_OVERRIDE { + StreamingReporterBase::testRunStarting( testInfo ); + m_xml.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", testInfo.name ); + + if ( m_config->showDurations() == ShowDurations::Always ) + m_testCaseTimer.start(); + } + + virtual void sectionStarting( SectionInfo const& sectionInfo ) CATCH_OVERRIDE { + StreamingReporterBase::sectionStarting( sectionInfo ); + if( m_sectionDepth++ > 0 ) { + m_xml.startElement( "Section" ) + .writeAttribute( "name", trim( sectionInfo.name ) ) + .writeAttribute( "description", sectionInfo.description ); + } + } + + virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE { } + + virtual bool assertionEnded( AssertionStats const& assertionStats ) CATCH_OVERRIDE { + const AssertionResult& assertionResult = assertionStats.assertionResult; + + // Print any info messages in tags. + 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 ) { + m_xml.scopedElement( "Info" ) + .writeText( it->message ); + } else if ( it->type == ResultWas::Warning ) { + m_xml.scopedElement( "Warning" ) + .writeText( it->message ); + } + } + } + + // Drop out if result was successful but we're not printing them. + if( !m_config->includeSuccessfulResults() && isOk(assertionResult.getResultType()) ) + return true; + + // Print the expression if there is one. + if( assertionResult.hasExpression() ) { + m_xml.startElement( "Expression" ) + .writeAttribute( "success", assertionResult.succeeded() ) + .writeAttribute( "type", assertionResult.getTestMacroName() ) + .writeAttribute( "filename", assertionResult.getSourceInfo().file ) + .writeAttribute( "line", assertionResult.getSourceInfo().line ); + + m_xml.scopedElement( "Original" ) + .writeText( assertionResult.getExpression() ); + m_xml.scopedElement( "Expanded" ) + .writeText( assertionResult.getExpandedExpression() ); + } + + // And... Print a result applicable to each result type. + switch( assertionResult.getResultType() ) { + case ResultWas::ThrewException: + m_xml.scopedElement( "Exception" ) + .writeAttribute( "filename", assertionResult.getSourceInfo().file ) + .writeAttribute( "line", assertionResult.getSourceInfo().line ) + .writeText( assertionResult.getMessage() ); + break; + case ResultWas::FatalErrorCondition: + m_xml.scopedElement( "FatalErrorCondition" ) + .writeAttribute( "filename", assertionResult.getSourceInfo().file ) + .writeAttribute( "line", assertionResult.getSourceInfo().line ) + .writeText( assertionResult.getMessage() ); + break; + case ResultWas::Info: + m_xml.scopedElement( "Info" ) + .writeText( assertionResult.getMessage() ); + break; + case ResultWas::Warning: + // Warning will already have been written + break; + case ResultWas::ExplicitFailure: + m_xml.scopedElement( "Failure" ) + .writeText( assertionResult.getMessage() ); + break; + default: + break; + } + + if( assertionResult.hasExpression() ) + m_xml.endElement(); + + return true; + } + + virtual void sectionEnded( SectionStats const& sectionStats ) CATCH_OVERRIDE { + StreamingReporterBase::sectionEnded( sectionStats ); + if( --m_sectionDepth > 0 ) { + XmlWriter::ScopedElement e = m_xml.scopedElement( "OverallResults" ); + e.writeAttribute( "successes", sectionStats.assertions.passed ); + e.writeAttribute( "failures", sectionStats.assertions.failed ); + e.writeAttribute( "expectedFailures", sectionStats.assertions.failedButOk ); + + if ( m_config->showDurations() == ShowDurations::Always ) + e.writeAttribute( "durationInSeconds", sectionStats.durationInSeconds ); + + m_xml.endElement(); + } + } + + virtual void testCaseEnded( TestCaseStats const& testCaseStats ) CATCH_OVERRIDE { + StreamingReporterBase::testCaseEnded( testCaseStats ); + XmlWriter::ScopedElement e = m_xml.scopedElement( "OverallResult" ); + e.writeAttribute( "success", testCaseStats.totals.assertions.allOk() ); + + if ( m_config->showDurations() == ShowDurations::Always ) + e.writeAttribute( "durationInSeconds", m_testCaseTimer.getElapsedSeconds() ); + + m_xml.endElement(); + } + + virtual void testGroupEnded( TestGroupStats const& testGroupStats ) CATCH_OVERRIDE { + StreamingReporterBase::testGroupEnded( testGroupStats ); + // TODO: Check testGroupStats.aborting and act accordingly. + m_xml.scopedElement( "OverallResults" ) + .writeAttribute( "successes", testGroupStats.totals.assertions.passed ) + .writeAttribute( "failures", testGroupStats.totals.assertions.failed ) + .writeAttribute( "expectedFailures", testGroupStats.totals.assertions.failedButOk ); + m_xml.endElement(); + } + + virtual void testRunEnded( TestRunStats const& testRunStats ) CATCH_OVERRIDE { + StreamingReporterBase::testRunEnded( testRunStats ); + m_xml.scopedElement( "OverallResults" ) + .writeAttribute( "successes", testRunStats.totals.assertions.passed ) + .writeAttribute( "failures", testRunStats.totals.assertions.failed ) + .writeAttribute( "expectedFailures", testRunStats.totals.assertions.failedButOk ); + m_xml.endElement(); + } + + private: + Timer m_testCaseTimer; + XmlWriter m_xml; + int m_sectionDepth; + }; + + INTERNAL_CATCH_REGISTER_REPORTER( "xml", XmlReporter ) + +} // end namespace Catch + +// #included from: ../reporters/catch_reporter_junit.hpp +#define TWOBLUECUBES_CATCH_REPORTER_JUNIT_HPP_INCLUDED + +#include + +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 CATCH_PLATFORM_WINDOWS + 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 CATCH_PLATFORM_WINDOWS + 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() ) + { + m_reporterPrefs.shouldRedirectStdOut = true; + } + + virtual ~JunitReporter() CATCH_OVERRIDE; + + static std::string getDescription() { + return "Reports test results in an XML format that looks like Ant's junitreport target"; + } + + virtual void noMatchingTestCases( std::string const& /*spec*/ ) CATCH_OVERRIDE {} + + virtual void testRunStarting( TestRunInfo const& runInfo ) CATCH_OVERRIDE { + CumulativeReporterBase::testRunStarting( runInfo ); + xml.startElement( "testsuites" ); + } + + virtual void testGroupStarting( GroupInfo const& groupInfo ) CATCH_OVERRIDE { + suiteTimer.start(); + stdOutForSuite.str(""); + stdErrForSuite.str(""); + unexpectedExceptions = 0; + CumulativeReporterBase::testGroupStarting( groupInfo ); + } + + virtual bool assertionEnded( AssertionStats const& assertionStats ) CATCH_OVERRIDE { + if( assertionStats.assertionResult.getResultType() == ResultWas::ThrewException ) + unexpectedExceptions++; + return CumulativeReporterBase::assertionEnded( assertionStats ); + } + + virtual void testCaseEnded( TestCaseStats const& testCaseStats ) CATCH_OVERRIDE { + stdOutForSuite << testCaseStats.stdOut; + stdErrForSuite << testCaseStats.stdErr; + CumulativeReporterBase::testCaseEnded( testCaseStats ); + } + + virtual void testGroupEnded( TestGroupStats const& testGroupStats ) CATCH_OVERRIDE { + double suiteTime = suiteTimer.getElapsedSeconds(); + CumulativeReporterBase::testGroupEnded( testGroupStats ); + writeGroup( *m_testGroups.back(), suiteTime ); + } + + virtual void testRunEndedCumulative() CATCH_OVERRIDE { + xml.endElement(); + } + + void writeGroup( TestGroupNode const& groupNode, double suiteTime ) { + XmlWriter::ScopedElement e = xml.scopedElement( "testsuite" ); + TestGroupStats const& stats = groupNode.value; + xml.writeAttribute( "name", stats.groupInfo.name ); + xml.writeAttribute( "errors", unexpectedExceptions ); + xml.writeAttribute( "failures", stats.totals.assertions.failed-unexpectedExceptions ); + xml.writeAttribute( "tests", stats.totals.assertions.total() ); + xml.writeAttribute( "hostname", "tbd" ); // !TBD + if( m_config->showDurations() == ShowDurations::Never ) + xml.writeAttribute( "time", "" ); + else + xml.writeAttribute( "time", suiteTime ); + xml.writeAttribute( "timestamp", 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; + }; + + INTERNAL_CATCH_REGISTER_REPORTER( "junit", JunitReporter ) + +} // end namespace Catch + +// #included from: ../reporters/catch_reporter_console.hpp +#define TWOBLUECUBES_CATCH_REPORTER_CONSOLE_HPP_INCLUDED + +namespace Catch { + + struct ConsoleReporter : StreamingReporterBase { + ConsoleReporter( ReporterConfig const& _config ) + : StreamingReporterBase( _config ), + m_headerPrinted( false ) + {} + + virtual ~ConsoleReporter() CATCH_OVERRIDE; + static std::string getDescription() { + return "Reports test results as plain lines of text"; + } + + virtual void noMatchingTestCases( std::string const& spec ) CATCH_OVERRIDE { + stream << "No test cases matched '" << spec << '\'' << std::endl; + } + + virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE { + } + + virtual bool assertionEnded( AssertionStats const& _assertionStats ) CATCH_OVERRIDE { + AssertionResult const& result = _assertionStats.assertionResult; + + bool printInfoMessages = true; + + // Drop out if result was successful and we're not printing those + if( !m_config->includeSuccessfulResults() && result.isOk() ) { + if( result.getResultType() != ResultWas::Warning ) + return false; + printInfoMessages = false; + } + + lazyPrint(); + + AssertionPrinter printer( stream, _assertionStats, printInfoMessages ); + printer.print(); + stream << std::endl; + return true; + } + + virtual void sectionStarting( SectionInfo const& _sectionInfo ) CATCH_OVERRIDE { + m_headerPrinted = false; + StreamingReporterBase::sectionStarting( _sectionInfo ); + } + virtual void sectionEnded( SectionStats const& _sectionStats ) CATCH_OVERRIDE { + if( _sectionStats.missingAssertions ) { + lazyPrint(); + Colour colour( Colour::ResultError ); + if( m_sectionStack.size() > 1 ) + stream << "\nNo assertions in section"; + else + stream << "\nNo assertions in test case"; + stream << " '" << _sectionStats.sectionInfo.name << "'\n" << std::endl; + } + if( m_headerPrinted ) { + if( m_config->showDurations() == ShowDurations::Always ) + stream << "Completed in " << _sectionStats.durationInSeconds << 's' << std::endl; + m_headerPrinted = false; + } + else { + if( m_config->showDurations() == ShowDurations::Always ) + stream << _sectionStats.sectionInfo.name << " completed in " << _sectionStats.durationInSeconds << 's' << std::endl; + } + StreamingReporterBase::sectionEnded( _sectionStats ); + } + + virtual void testCaseEnded( TestCaseStats const& _testCaseStats ) CATCH_OVERRIDE { + StreamingReporterBase::testCaseEnded( _testCaseStats ); + m_headerPrinted = false; + } + virtual void testGroupEnded( TestGroupStats const& _testGroupStats ) CATCH_OVERRIDE { + if( currentGroupInfo.used ) { + printSummaryDivider(); + stream << "Summary for group '" << _testGroupStats.groupInfo.name << "':\n"; + printTotals( _testGroupStats.totals ); + stream << '\n' << std::endl; + } + StreamingReporterBase::testGroupEnded( _testGroupStats ); + } + virtual void testRunEnded( TestRunStats const& _testRunStats ) CATCH_OVERRIDE { + printTotalsDivider( _testRunStats.totals ); + printTotals( _testRunStats.totals ); + stream << std::endl; + StreamingReporterBase::testRunEnded( _testRunStats ); + } + + private: + + class AssertionPrinter { + void operator= ( AssertionPrinter const& ); + public: + AssertionPrinter( std::ostream& _stream, AssertionStats const& _stats, bool _printInfoMessages ) + : stream( _stream ), + stats( _stats ), + result( _stats.assertionResult ), + colour( Colour::None ), + message( result.getMessage() ), + messages( _stats.infoMessages ), + printInfoMessages( _printInfoMessages ) + { + switch( result.getResultType() ) { + case ResultWas::Ok: + colour = Colour::Success; + passOrFail = "PASSED"; + //if( result.hasMessage() ) + if( _stats.infoMessages.size() == 1 ) + messageLabel = "with message"; + if( _stats.infoMessages.size() > 1 ) + messageLabel = "with messages"; + break; + case ResultWas::ExpressionFailed: + if( result.isOk() ) { + colour = Colour::Success; + passOrFail = "FAILED - but was ok"; + } + else { + colour = Colour::Error; + passOrFail = "FAILED"; + } + if( _stats.infoMessages.size() == 1 ) + messageLabel = "with message"; + if( _stats.infoMessages.size() > 1 ) + messageLabel = "with messages"; + break; + case ResultWas::ThrewException: + colour = Colour::Error; + passOrFail = "FAILED"; + messageLabel = "due to unexpected exception with message"; + break; + case ResultWas::FatalErrorCondition: + colour = Colour::Error; + passOrFail = "FAILED"; + messageLabel = "due to a fatal error condition"; + break; + case ResultWas::DidntThrowException: + colour = Colour::Error; + passOrFail = "FAILED"; + messageLabel = "because no exception was thrown where one was expected"; + break; + case ResultWas::Info: + messageLabel = "info"; + break; + case ResultWas::Warning: + messageLabel = "warning"; + break; + case ResultWas::ExplicitFailure: + passOrFail = "FAILED"; + colour = Colour::Error; + if( _stats.infoMessages.size() == 1 ) + messageLabel = "explicitly with message"; + if( _stats.infoMessages.size() > 1 ) + messageLabel = "explicitly with messages"; + break; + // These cases are here to prevent compiler warnings + case ResultWas::Unknown: + case ResultWas::FailureBit: + case ResultWas::Exception: + passOrFail = "** internal error **"; + colour = Colour::Error; + break; + } + } + + void print() const { + printSourceInfo(); + if( stats.totals.assertions.total() > 0 ) { + if( result.isOk() ) + stream << '\n'; + printResultType(); + printOriginalExpression(); + printReconstructedExpression(); + } + else { + stream << '\n'; + } + printMessage(); + } + + private: + void printResultType() const { + if( !passOrFail.empty() ) { + Colour colourGuard( colour ); + stream << passOrFail << ":\n"; + } + } + void printOriginalExpression() const { + if( result.hasExpression() ) { + Colour colourGuard( Colour::OriginalExpression ); + stream << " "; + stream << result.getExpressionInMacro(); + stream << '\n'; + } + } + void printReconstructedExpression() const { + if( result.hasExpandedExpression() ) { + stream << "with expansion:\n"; + Colour colourGuard( Colour::ReconstructedExpression ); + stream << Text( result.getExpandedExpression(), TextAttributes().setIndent(2) ) << '\n'; + } + } + void printMessage() const { + if( !messageLabel.empty() ) + stream << messageLabel << ':' << '\n'; + for( std::vector::const_iterator it = messages.begin(), itEnd = messages.end(); + it != itEnd; + ++it ) { + // If this assertion is a warning ignore any INFO messages + if( printInfoMessages || it->type != ResultWas::Info ) + stream << Text( it->message, TextAttributes().setIndent(2) ) << '\n'; + } + } + void printSourceInfo() const { + Colour colourGuard( Colour::FileName ); + stream << result.getSourceInfo() << ": "; + } + + std::ostream& stream; + AssertionStats const& stats; + AssertionResult const& result; + Colour::Code colour; + std::string passOrFail; + std::string messageLabel; + std::string message; + std::vector messages; + bool printInfoMessages; + }; + + void lazyPrint() { + + if( !currentTestRunInfo.used ) + lazyPrintRunInfo(); + if( !currentGroupInfo.used ) + lazyPrintGroupInfo(); + + if( !m_headerPrinted ) { + printTestCaseAndSectionHeader(); + m_headerPrinted = true; + } + } + void lazyPrintRunInfo() { + stream << '\n' << getLineOfChars<'~'>() << '\n'; + Colour colour( Colour::SecondaryText ); + stream << currentTestRunInfo->name + << " is a Catch v" << libraryVersion << " host application.\n" + << "Run with -? for options\n\n"; + + if( m_config->rngSeed() != 0 ) + stream << "Randomness seeded to: " << m_config->rngSeed() << "\n\n"; + + currentTestRunInfo.used = true; + } + void lazyPrintGroupInfo() { + if( !currentGroupInfo->name.empty() && currentGroupInfo->groupsCounts > 1 ) { + printClosedHeader( "Group: " + currentGroupInfo->name ); + currentGroupInfo.used = true; + } + } + void printTestCaseAndSectionHeader() { + assert( !m_sectionStack.empty() ); + printOpenHeader( currentTestCaseInfo->name ); + + if( m_sectionStack.size() > 1 ) { + Colour colourGuard( Colour::Headers ); + + std::vector::const_iterator + it = m_sectionStack.begin()+1, // Skip first section (test case) + itEnd = m_sectionStack.end(); + for( ; it != itEnd; ++it ) + printHeaderString( it->name, 2 ); + } + + SourceLineInfo lineInfo = m_sectionStack.front().lineInfo; + + if( !lineInfo.empty() ){ + stream << getLineOfChars<'-'>() << '\n'; + Colour colourGuard( Colour::FileName ); + stream << lineInfo << '\n'; + } + stream << getLineOfChars<'.'>() << '\n' << std::endl; + } + + void printClosedHeader( std::string const& _name ) { + printOpenHeader( _name ); + stream << getLineOfChars<'.'>() << '\n'; + } + void printOpenHeader( std::string const& _name ) { + stream << getLineOfChars<'-'>() << '\n'; + { + Colour colourGuard( Colour::Headers ); + printHeaderString( _name ); + } + } + + // if string has a : in first line will set indent to follow it on + // subsequent lines + void printHeaderString( std::string const& _string, std::size_t indent = 0 ) { + std::size_t i = _string.find( ": " ); + if( i != std::string::npos ) + i+=2; + else + i = 0; + stream << Text( _string, TextAttributes() + .setIndent( indent+i) + .setInitialIndent( indent ) ) << '\n'; + } + + struct SummaryColumn { + + SummaryColumn( std::string const& _label, Colour::Code _colour ) + : label( _label ), + colour( _colour ) + {} + SummaryColumn addRow( std::size_t count ) { + std::ostringstream oss; + oss << count; + std::string row = oss.str(); + for( std::vector::iterator it = rows.begin(); it != rows.end(); ++it ) { + while( it->size() < row.size() ) + *it = ' ' + *it; + while( it->size() > row.size() ) + row = ' ' + row; + } + rows.push_back( row ); + return *this; + } + + std::string label; + Colour::Code colour; + std::vector rows; + + }; + + void printTotals( Totals const& totals ) { + if( totals.testCases.total() == 0 ) { + stream << Colour( Colour::Warning ) << "No tests ran\n"; + } + else if( totals.assertions.total() > 0 && totals.testCases.allPassed() ) { + stream << Colour( Colour::ResultSuccess ) << "All tests passed"; + stream << " (" + << pluralise( totals.assertions.passed, "assertion" ) << " in " + << pluralise( totals.testCases.passed, "test case" ) << ')' + << '\n'; + } + else { + + std::vector columns; + columns.push_back( SummaryColumn( "", Colour::None ) + .addRow( totals.testCases.total() ) + .addRow( totals.assertions.total() ) ); + columns.push_back( SummaryColumn( "passed", Colour::Success ) + .addRow( totals.testCases.passed ) + .addRow( totals.assertions.passed ) ); + columns.push_back( SummaryColumn( "failed", Colour::ResultError ) + .addRow( totals.testCases.failed ) + .addRow( totals.assertions.failed ) ); + columns.push_back( SummaryColumn( "failed as expected", Colour::ResultExpectedFailure ) + .addRow( totals.testCases.failedButOk ) + .addRow( totals.assertions.failedButOk ) ); + + printSummaryRow( "test cases", columns, 0 ); + printSummaryRow( "assertions", columns, 1 ); + } + } + void printSummaryRow( std::string const& label, std::vector const& cols, std::size_t row ) { + for( std::vector::const_iterator it = cols.begin(); it != cols.end(); ++it ) { + std::string value = it->rows[row]; + if( it->label.empty() ) { + stream << label << ": "; + if( value != "0" ) + stream << value; + else + stream << Colour( Colour::Warning ) << "- none -"; + } + else if( value != "0" ) { + stream << Colour( Colour::LightGrey ) << " | "; + stream << Colour( it->colour ) + << value << ' ' << it->label; + } + } + stream << '\n'; + } + + static std::size_t makeRatio( std::size_t number, std::size_t total ) { + std::size_t ratio = total > 0 ? CATCH_CONFIG_CONSOLE_WIDTH * number/ total : 0; + return ( ratio == 0 && number > 0 ) ? 1 : ratio; + } + static std::size_t& findMax( std::size_t& i, std::size_t& j, std::size_t& k ) { + if( i > j && i > k ) + return i; + else if( j > k ) + return j; + else + return k; + } + + void printTotalsDivider( Totals const& totals ) { + if( totals.testCases.total() > 0 ) { + std::size_t failedRatio = makeRatio( totals.testCases.failed, totals.testCases.total() ); + std::size_t failedButOkRatio = makeRatio( totals.testCases.failedButOk, totals.testCases.total() ); + std::size_t passedRatio = makeRatio( totals.testCases.passed, totals.testCases.total() ); + while( failedRatio + failedButOkRatio + passedRatio < CATCH_CONFIG_CONSOLE_WIDTH-1 ) + findMax( failedRatio, failedButOkRatio, passedRatio )++; + while( failedRatio + failedButOkRatio + passedRatio > CATCH_CONFIG_CONSOLE_WIDTH-1 ) + findMax( failedRatio, failedButOkRatio, passedRatio )--; + + stream << Colour( Colour::Error ) << std::string( failedRatio, '=' ); + stream << Colour( Colour::ResultExpectedFailure ) << std::string( failedButOkRatio, '=' ); + if( totals.testCases.allPassed() ) + stream << Colour( Colour::ResultSuccess ) << std::string( passedRatio, '=' ); + else + stream << Colour( Colour::Success ) << std::string( passedRatio, '=' ); + } + else { + stream << Colour( Colour::Warning ) << std::string( CATCH_CONFIG_CONSOLE_WIDTH-1, '=' ); + } + stream << '\n'; + } + void printSummaryDivider() { + stream << getLineOfChars<'-'>() << '\n'; + } + + private: + bool m_headerPrinted; + }; + + INTERNAL_CATCH_REGISTER_REPORTER( "console", ConsoleReporter ) + +} // end namespace Catch + +// #included from: ../reporters/catch_reporter_compact.hpp +#define TWOBLUECUBES_CATCH_REPORTER_COMPACT_HPP_INCLUDED + +namespace Catch { + + struct CompactReporter : StreamingReporterBase { + + CompactReporter( ReporterConfig const& _config ) + : StreamingReporterBase( _config ) + {} + + virtual ~CompactReporter(); + + static std::string getDescription() { + return "Reports test results on a single line, suitable for IDEs"; + } + + virtual ReporterPreferences getPreferences() const { + ReporterPreferences prefs; + prefs.shouldRedirectStdOut = false; + return prefs; + } + + virtual void noMatchingTestCases( std::string const& spec ) { + stream << "No test cases matched '" << spec << '\'' << std::endl; + } + + virtual void assertionStarting( AssertionInfo const& ) { + } + + virtual bool assertionEnded( AssertionStats const& _assertionStats ) { + AssertionResult const& result = _assertionStats.assertionResult; + + bool printInfoMessages = true; + + // Drop out if result was successful and we're not printing those + if( !m_config->includeSuccessfulResults() && result.isOk() ) { + if( result.getResultType() != ResultWas::Warning ) + return false; + printInfoMessages = false; + } + + AssertionPrinter printer( stream, _assertionStats, printInfoMessages ); + printer.print(); + + stream << std::endl; + return true; + } + + virtual void testRunEnded( TestRunStats const& _testRunStats ) { + printTotals( _testRunStats.totals ); + stream << '\n' << std::endl; + StreamingReporterBase::testRunEnded( _testRunStats ); + } + + private: + class AssertionPrinter { + void operator= ( AssertionPrinter const& ); + public: + AssertionPrinter( std::ostream& _stream, AssertionStats const& _stats, bool _printInfoMessages ) + : stream( _stream ) + , stats( _stats ) + , result( _stats.assertionResult ) + , messages( _stats.infoMessages ) + , itMessage( _stats.infoMessages.begin() ) + , printInfoMessages( _printInfoMessages ) + {} + + void print() { + printSourceInfo(); + + itMessage = messages.begin(); + + switch( result.getResultType() ) { + case ResultWas::Ok: + printResultType( Colour::ResultSuccess, passedString() ); + printOriginalExpression(); + printReconstructedExpression(); + if ( ! result.hasExpression() ) + printRemainingMessages( Colour::None ); + else + printRemainingMessages(); + break; + case ResultWas::ExpressionFailed: + if( result.isOk() ) + printResultType( Colour::ResultSuccess, failedString() + std::string( " - but was ok" ) ); + else + printResultType( Colour::Error, failedString() ); + printOriginalExpression(); + printReconstructedExpression(); + printRemainingMessages(); + break; + case ResultWas::ThrewException: + printResultType( Colour::Error, failedString() ); + printIssue( "unexpected exception with message:" ); + printMessage(); + printExpressionWas(); + printRemainingMessages(); + break; + case ResultWas::FatalErrorCondition: + printResultType( Colour::Error, failedString() ); + printIssue( "fatal error condition with message:" ); + printMessage(); + printExpressionWas(); + printRemainingMessages(); + break; + case ResultWas::DidntThrowException: + printResultType( Colour::Error, failedString() ); + printIssue( "expected exception, got none" ); + printExpressionWas(); + printRemainingMessages(); + break; + case ResultWas::Info: + printResultType( Colour::None, "info" ); + printMessage(); + printRemainingMessages(); + break; + case ResultWas::Warning: + printResultType( Colour::None, "warning" ); + printMessage(); + printRemainingMessages(); + break; + case ResultWas::ExplicitFailure: + printResultType( Colour::Error, failedString() ); + printIssue( "explicitly" ); + printRemainingMessages( Colour::None ); + break; + // These cases are here to prevent compiler warnings + case ResultWas::Unknown: + case ResultWas::FailureBit: + case ResultWas::Exception: + printResultType( Colour::Error, "** internal error **" ); + break; + } + } + + private: + // Colour::LightGrey + + static Colour::Code dimColour() { return Colour::FileName; } + +#ifdef CATCH_PLATFORM_MAC + static const char* failedString() { return "FAILED"; } + static const char* passedString() { return "PASSED"; } +#else + static const char* failedString() { return "failed"; } + static const char* passedString() { return "passed"; } +#endif + + void printSourceInfo() const { + Colour colourGuard( Colour::FileName ); + stream << result.getSourceInfo() << ':'; + } + + void printResultType( Colour::Code colour, std::string passOrFail ) const { + if( !passOrFail.empty() ) { + { + Colour colourGuard( colour ); + stream << ' ' << passOrFail; + } + stream << ':'; + } + } + + void printIssue( std::string issue ) const { + stream << ' ' << issue; + } + + void printExpressionWas() { + if( result.hasExpression() ) { + stream << ';'; + { + Colour colour( dimColour() ); + stream << " expression was:"; + } + printOriginalExpression(); + } + } + + void printOriginalExpression() const { + if( result.hasExpression() ) { + stream << ' ' << result.getExpression(); + } + } + + void printReconstructedExpression() const { + if( result.hasExpandedExpression() ) { + { + Colour colour( dimColour() ); + stream << " for: "; + } + stream << result.getExpandedExpression(); + } + } + + void printMessage() { + if ( itMessage != messages.end() ) { + stream << " '" << itMessage->message << '\''; + ++itMessage; + } + } + + void printRemainingMessages( Colour::Code colour = dimColour() ) { + if ( itMessage == messages.end() ) + return; + + // using messages.end() directly yields compilation error: + std::vector::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" ) << '.'; + } + } + }; + + INTERNAL_CATCH_REGISTER_REPORTER( "compact", CompactReporter ) + +} // end namespace Catch + +namespace Catch { + // These are all here to avoid warnings about not having any out of line + // virtual methods + NonCopyable::~NonCopyable() {} + IShared::~IShared() {} + IStream::~IStream() CATCH_NOEXCEPT {} + FileStream::~FileStream() CATCH_NOEXCEPT {} + CoutStream::~CoutStream() CATCH_NOEXCEPT {} + DebugOutStream::~DebugOutStream() CATCH_NOEXCEPT {} + StreamBufBase::~StreamBufBase() CATCH_NOEXCEPT {} + IContext::~IContext() {} + IResultCapture::~IResultCapture() {} + ITestCase::~ITestCase() {} + ITestCaseRegistry::~ITestCaseRegistry() {} + IRegistryHub::~IRegistryHub() {} + IMutableRegistryHub::~IMutableRegistryHub() {} + IExceptionTranslator::~IExceptionTranslator() {} + IExceptionTranslatorRegistry::~IExceptionTranslatorRegistry() {} + IReporter::~IReporter() {} + IReporterFactory::~IReporterFactory() {} + IReporterRegistry::~IReporterRegistry() {} + IStreamingReporter::~IStreamingReporter() {} + AssertionStats::~AssertionStats() {} + SectionStats::~SectionStats() {} + TestCaseStats::~TestCaseStats() {} + TestGroupStats::~TestGroupStats() {} + TestRunStats::~TestRunStats() {} + CumulativeReporterBase::SectionNode::~SectionNode() {} + CumulativeReporterBase::~CumulativeReporterBase() {} + + StreamingReporterBase::~StreamingReporterBase() {} + ConsoleReporter::~ConsoleReporter() {} + CompactReporter::~CompactReporter() {} + IRunner::~IRunner() {} + IMutableContext::~IMutableContext() {} + IConfig::~IConfig() {} + XmlReporter::~XmlReporter() {} + JunitReporter::~JunitReporter() {} + TestRegistry::~TestRegistry() {} + FreeFunctionTestCase::~FreeFunctionTestCase() {} + IGeneratorInfo::~IGeneratorInfo() {} + IGeneratorsForTest::~IGeneratorsForTest() {} + WildcardPattern::~WildcardPattern() {} + TestSpec::Pattern::~Pattern() {} + TestSpec::NamePattern::~NamePattern() {} + TestSpec::TagPattern::~TagPattern() {} + TestSpec::ExcludedPattern::~ExcludedPattern() {} + + Matchers::Impl::StdString::Equals::~Equals() {} + Matchers::Impl::StdString::Contains::~Contains() {} + Matchers::Impl::StdString::StartsWith::~StartsWith() {} + Matchers::Impl::StdString::EndsWith::~EndsWith() {} + + void Config::dummy() {} + + namespace TestCaseTracking { + ITracker::~ITracker() {} + TrackerBase::~TrackerBase() {} + SectionTracker::~SectionTracker() {} + IndexTracker::~IndexTracker() {} + } +} + +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + +#endif + +#ifdef CATCH_CONFIG_MAIN +// #included from: internal/catch_default_main.hpp +#define TWOBLUECUBES_CATCH_DEFAULT_MAIN_HPP_INCLUDED + +#ifndef __OBJC__ + +// Standard C/C++ main entry point +int main (int argc, char * argv[]) { + int result = Catch::Session().run( argc, argv ); + return ( result < 0xff ? result : 0xff ); +} + +#else // __OBJC__ + +// Objective-C entry point +int main (int argc, char * const argv[]) { +#if !CATCH_ARC_ENABLED + NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; +#endif + + Catch::registerTestMethods(); + int result = Catch::Session().run( argc, (char* const*)argv ); + +#if !CATCH_ARC_ENABLED + [pool drain]; +#endif + + return ( result < 0xff ? result : 0xff ); +} + +#endif // __OBJC__ + +#endif + +#ifdef CLARA_CONFIG_MAIN_NOT_DEFINED +# undef CLARA_CONFIG_MAIN +#endif + +////// + +// If this config identifier is defined then all CATCH macros are prefixed with CATCH_ +#ifdef CATCH_CONFIG_PREFIX_ALL + +#define CATCH_REQUIRE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal, "CATCH_REQUIRE" ) +#define CATCH_REQUIRE_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, "CATCH_REQUIRE_FALSE" ) + +#define CATCH_REQUIRE_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::Normal, "", "CATCH_REQUIRE_THROWS" ) +#define CATCH_REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_THROWS_AS" ) +#define CATCH_REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::Normal, matcher, "CATCH_REQUIRE_THROWS_WITH" ) +#define CATCH_REQUIRE_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_NOTHROW" ) + +#define CATCH_CHECK( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK" ) +#define CATCH_CHECK_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::FalseTest, "CATCH_CHECK_FALSE" ) +#define CATCH_CHECKED_IF( expr ) INTERNAL_CATCH_IF( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECKED_IF" ) +#define CATCH_CHECKED_ELSE( expr ) INTERNAL_CATCH_ELSE( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECKED_ELSE" ) +#define CATCH_CHECK_NOFAIL( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, "CATCH_CHECK_NOFAIL" ) + +#define CATCH_CHECK_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::ContinueOnFailure, "", "CATCH_CHECK_THROWS" ) +#define CATCH_CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_THROWS_AS" ) +#define CATCH_CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::ContinueOnFailure, matcher, "CATCH_CHECK_THROWS_WITH" ) +#define CATCH_CHECK_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_NOTHROW" ) + +#define CATCH_CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_THAT" ) +#define CATCH_REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_THAT" ) + +#define CATCH_INFO( msg ) INTERNAL_CATCH_INFO( msg, "CATCH_INFO" ) +#define CATCH_WARN( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, "CATCH_WARN", msg ) +#define CATCH_SCOPED_INFO( msg ) INTERNAL_CATCH_INFO( msg, "CATCH_INFO" ) +#define CATCH_CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CATCH_CAPTURE" ) +#define CATCH_SCOPED_CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CATCH_CAPTURE" ) + +#ifdef CATCH_CONFIG_VARIADIC_MACROS + #define CATCH_TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ ) + #define CATCH_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ ) + #define CATCH_METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ ) + #define CATCH_REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ ) + #define CATCH_SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ ) + #define CATCH_FAIL( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "CATCH_FAIL", __VA_ARGS__ ) + #define CATCH_SUCCEED( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "CATCH_SUCCEED", __VA_ARGS__ ) +#else + #define CATCH_TEST_CASE( name, description ) INTERNAL_CATCH_TESTCASE( name, description ) + #define CATCH_TEST_CASE_METHOD( className, name, description ) INTERNAL_CATCH_TEST_CASE_METHOD( className, name, description ) + #define CATCH_METHOD_AS_TEST_CASE( method, name, description ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, name, description ) + #define CATCH_REGISTER_TEST_CASE( function, name, description ) INTERNAL_CATCH_REGISTER_TESTCASE( function, name, description ) + #define CATCH_SECTION( name, description ) INTERNAL_CATCH_SECTION( name, description ) + #define CATCH_FAIL( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "CATCH_FAIL", msg ) + #define CATCH_SUCCEED( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "CATCH_SUCCEED", msg ) +#endif +#define CATCH_ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE( "", "" ) + +#define CATCH_REGISTER_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType ) +#define CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) + +#define CATCH_GENERATE( expr) INTERNAL_CATCH_GENERATE( expr ) + +// "BDD-style" convenience wrappers +#ifdef CATCH_CONFIG_VARIADIC_MACROS +#define CATCH_SCENARIO( ... ) CATCH_TEST_CASE( "Scenario: " __VA_ARGS__ ) +#define CATCH_SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ ) +#else +#define CATCH_SCENARIO( name, tags ) CATCH_TEST_CASE( "Scenario: " name, tags ) +#define CATCH_SCENARIO_METHOD( className, name, tags ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " name, tags ) +#endif +#define CATCH_GIVEN( desc ) CATCH_SECTION( std::string( "Given: ") + desc, "" ) +#define CATCH_WHEN( desc ) CATCH_SECTION( std::string( " When: ") + desc, "" ) +#define CATCH_AND_WHEN( desc ) CATCH_SECTION( std::string( " And: ") + desc, "" ) +#define CATCH_THEN( desc ) CATCH_SECTION( std::string( " Then: ") + desc, "" ) +#define CATCH_AND_THEN( desc ) CATCH_SECTION( std::string( " And: ") + desc, "" ) + +// If CATCH_CONFIG_PREFIX_ALL is not defined then the CATCH_ prefix is not required +#else + +#define REQUIRE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal, "REQUIRE" ) +#define REQUIRE_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, "REQUIRE_FALSE" ) + +#define REQUIRE_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::Normal, "", "REQUIRE_THROWS" ) +#define REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::Normal, "REQUIRE_THROWS_AS" ) +#define REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::Normal, matcher, "REQUIRE_THROWS_WITH" ) +#define REQUIRE_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::Normal, "REQUIRE_NOTHROW" ) + +#define CHECK( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECK" ) +#define CHECK_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::FalseTest, "CHECK_FALSE" ) +#define CHECKED_IF( expr ) INTERNAL_CATCH_IF( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECKED_IF" ) +#define CHECKED_ELSE( expr ) INTERNAL_CATCH_ELSE( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECKED_ELSE" ) +#define CHECK_NOFAIL( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, "CHECK_NOFAIL" ) + +#define CHECK_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::ContinueOnFailure, "", "CHECK_THROWS" ) +#define CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::ContinueOnFailure, "CHECK_THROWS_AS" ) +#define CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::ContinueOnFailure, matcher, "CHECK_THROWS_WITH" ) +#define CHECK_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECK_NOTHROW" ) + +#define CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::ContinueOnFailure, "CHECK_THAT" ) +#define REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::Normal, "REQUIRE_THAT" ) + +#define INFO( msg ) INTERNAL_CATCH_INFO( msg, "INFO" ) +#define WARN( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, "WARN", msg ) +#define SCOPED_INFO( msg ) INTERNAL_CATCH_INFO( msg, "INFO" ) +#define CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CAPTURE" ) +#define SCOPED_CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CAPTURE" ) + +#ifdef CATCH_CONFIG_VARIADIC_MACROS + #define TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ ) + #define TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ ) + #define METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ ) + #define REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ ) + #define SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ ) + #define FAIL( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "FAIL", __VA_ARGS__ ) + #define SUCCEED( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "SUCCEED", __VA_ARGS__ ) +#else + #define TEST_CASE( name, description ) INTERNAL_CATCH_TESTCASE( name, description ) + #define TEST_CASE_METHOD( className, name, description ) INTERNAL_CATCH_TEST_CASE_METHOD( className, name, description ) + #define METHOD_AS_TEST_CASE( method, name, description ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, name, description ) + #define REGISTER_TEST_CASE( method, name, description ) INTERNAL_CATCH_REGISTER_TESTCASE( method, name, description ) + #define SECTION( name, description ) INTERNAL_CATCH_SECTION( name, description ) + #define FAIL( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "FAIL", msg ) + #define SUCCEED( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "SUCCEED", msg ) +#endif +#define ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE( "", "" ) + +#define REGISTER_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType ) +#define REGISTER_LEGACY_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) + +#define GENERATE( expr) INTERNAL_CATCH_GENERATE( expr ) + +#endif + +#define CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) + +// "BDD-style" convenience wrappers +#ifdef CATCH_CONFIG_VARIADIC_MACROS +#define SCENARIO( ... ) TEST_CASE( "Scenario: " __VA_ARGS__ ) +#define SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ ) +#else +#define SCENARIO( name, tags ) TEST_CASE( "Scenario: " name, tags ) +#define SCENARIO_METHOD( className, name, tags ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " name, tags ) +#endif +#define GIVEN( desc ) SECTION( std::string(" Given: ") + desc, "" ) +#define WHEN( desc ) SECTION( std::string(" When: ") + desc, "" ) +#define AND_WHEN( desc ) SECTION( std::string("And when: ") + desc, "" ) +#define THEN( desc ) SECTION( std::string(" Then: ") + desc, "" ) +#define AND_THEN( desc ) SECTION( std::string(" And: ") + desc, "" ) + +using Catch::Detail::Approx; + +#endif // TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED + From d284c86dd1bb8c9e723c5834354a0329c091fe4d Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Sat, 4 Feb 2017 21:00:41 +0100 Subject: [PATCH 40/80] :white_check_mark: uncommented some tests --- test/src/unit-conversions.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/test/src/unit-conversions.cpp b/test/src/unit-conversions.cpp index fca807a0..7db56ee0 100644 --- a/test/src/unit-conversions.cpp +++ b/test/src/unit-conversions.cpp @@ -972,14 +972,14 @@ TEST_CASE("value conversion") auto m5 = j5.get>(); } - //SECTION("std::forward_list") - //{ - // auto m1 = j1.get>(); - // auto m2 = j2.get>(); - // auto m3 = j3.get>(); - // auto m4 = j4.get>(); - // auto m5 = j5.get>(); - //} + SECTION("std::forward_list") + { + auto m1 = j1.get>(); + auto m2 = j2.get>(); + auto m3 = j3.get>(); + auto m4 = j4.get>(); + auto m5 = j5.get>(); + } SECTION("std::vector") { From 163f8397fdc94b778eddcd2d22294e2f961d8b20 Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Sun, 5 Feb 2017 17:11:26 +0100 Subject: [PATCH 41/80] :pencil2: fixed a typo #446 --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 1933c12a..c1fd0d89 100644 --- a/README.md +++ b/README.md @@ -168,7 +168,7 @@ auto j2 = R"( )"_json; ``` -Note that without appending the `_json` suffix, the passed string literal is not parsed, but just used as JSON string value. That is, `json j = "{ \"happy\": true, \"pi\": 3.141 }"` would just store the string `"{ "happy": true, "pi": 3.141 }"` rather than parsing the acutal object. +Note that without appending the `_json` suffix, the passed string literal is not parsed, but just used as JSON string value. That is, `json j = "{ \"happy\": true, \"pi\": 3.141 }"` would just store the string `"{ "happy": true, "pi": 3.141 }"` rather than parsing the actual object. The above example can also be expressed explicitly using `json::parse()`: @@ -820,6 +820,7 @@ I deeply appreciate the help of the following people. - [EnricoBilla](https://github.com/EnricoBilla) noted a typo in an example. - [Martin HoÅ™eňovský](https://github.com/horenmar) found a way for a 2x speedup for the compilation time of the test suite. - [ukhegg](https://github.com/ukhegg) found proposed an improvement for the examples section. +- [rswanson-ihi](https://github.com/rswanson-ihi) noted a type in the README. Thanks a lot for helping out! Please [let me know](mailto:mail@nlohmann.me) if I forgot someone. From 4746a4c53622745fd1f3005cd560dcd443cc7a31 Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Wed, 8 Feb 2017 17:56:43 +0100 Subject: [PATCH 42/80] :lipstick: minor change --- src/json.hpp | 4 ++-- src/json.hpp.re2c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/json.hpp b/src/json.hpp index c77945a8..11c00162 100644 --- a/src/json.hpp +++ b/src/json.hpp @@ -12689,9 +12689,9 @@ inline nlohmann::json::json_pointer operator "" _json_pointer(const char* s, std #endif // clean up -#undef JSON_THROW -#undef JSON_TRY #undef JSON_CATCH #undef JSON_DEPRECATED +#undef JSON_THROW +#undef JSON_TRY #endif diff --git a/src/json.hpp.re2c b/src/json.hpp.re2c index 109a4f26..edc209bf 100644 --- a/src/json.hpp.re2c +++ b/src/json.hpp.re2c @@ -11839,9 +11839,9 @@ inline nlohmann::json::json_pointer operator "" _json_pointer(const char* s, std #endif // clean up -#undef JSON_THROW -#undef JSON_TRY #undef JSON_CATCH #undef JSON_DEPRECATED +#undef JSON_THROW +#undef JSON_TRY #endif From 662a9b8f3c75f51dc55b1b3887c3ac49ea76d142 Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Wed, 8 Feb 2017 18:19:41 +0100 Subject: [PATCH 43/80] :pencil2: fixed more typos --- src/json.hpp | 42 +++++++++++++++++++++--------------------- src/json.hpp.re2c | 42 +++++++++++++++++++++--------------------- 2 files changed, 42 insertions(+), 42 deletions(-) diff --git a/src/json.hpp b/src/json.hpp index 11c00162..233cf8fa 100644 --- a/src/json.hpp +++ b/src/json.hpp @@ -1106,7 +1106,7 @@ class basic_json /*! @brief returns version information on the library - This function returns a JSON object with infiormation about the library, + This function returns a JSON object with information about the library, including the version number and information on the platform and compiler. @return JSON object holding version information @@ -3417,7 +3417,7 @@ class basic_json /*! @brief get a reference value (implicit) - Implict reference access to the internally stored JSON value. No copies + Implicit reference access to the internally stored JSON value. No copies are made. @warning Writing data to the referee of the result yields an undefined @@ -3492,7 +3492,7 @@ class basic_json template < typename ValueType, typename std::enable_if < not std::is_pointer::value and not std::is_same::value -#ifndef _MSC_VER // fix for issue #167 operator<< abiguity under VS2015 +#ifndef _MSC_VER // fix for issue #167 operator<< ambiguity under VS2015 and not std::is_same>::value #endif , int >::type = 0 > @@ -4285,7 +4285,7 @@ class basic_json @complexity The complexity depends on the type: - objects: amortized constant - - arrays: linear in distance between pos and the end of the container + - arrays: linear in distance between @a pos and the end of the container - strings: linear in the length of the string - other types: constant @@ -5537,7 +5537,7 @@ class basic_json @throw std::domain_error if @a pos is not an iterator of *this; example: `"iterator does not fit current value"` - @complexity Constant plus linear in the distance between pos and end of + @complexity Constant plus linear in the distance between @a pos and end of the container. @liveexample{The example shows how `insert()` is used.,insert} @@ -6234,7 +6234,7 @@ class basic_json `std::setw(4)` on @a o sets the indentation level to `4` and the serialization result is the same as calling `dump(4)`. - @note During serializaion, the locale and the precision of the output + @note During serialization, the locale and the precision of the output stream @a o are changed. The original values are restored when the function returns. @@ -10624,7 +10624,7 @@ basic_json_parser_66: if (m_stream == nullptr or m_stream->eof()) { // m_start may or may not be pointing into m_line_buffer at - // this point. We trust the standand library to do the right + // this point. We trust the standard library to do the right // thing. See http://stackoverflow.com/q/28142011/266378 m_line_buffer.assign(m_start, m_limit); @@ -10712,7 +10712,7 @@ basic_json_parser_66: m_start + 1 + x < m_cursor - 1 must hold to loop indefinitely. This can be rephrased to m_cursor - m_start - 2 > x. With the precondition, we x <= 0, meaning that the loop condition holds - indefinitly if i is always decreased. However, observe that the value + indefinitely if i is always decreased. However, observe that the value of i is strictly increasing with each iteration, as it is incremented by 1 in the iteration expression and never decremented inside the loop body. Hence, the loop condition will eventually be false which @@ -10841,12 +10841,12 @@ basic_json_parser_66: /*! @brief parse floating point number - This function (and its overloads) serves to select the most approprate + This function (and its overloads) serves to select the most appropriate standard floating point number parsing function based on the type supplied via the first parameter. Set this to @a static_cast(nullptr). - @param[in,out] endptr recieves a pointer to the first character after + @param[in,out] endptr receives a pointer to the first character after the number @return the floating point number @@ -10859,12 +10859,12 @@ basic_json_parser_66: /*! @brief parse floating point number - This function (and its overloads) serves to select the most approprate + This function (and its overloads) serves to select the most appropriate standard floating point number parsing function based on the type supplied via the first parameter. Set this to @a static_cast(nullptr). - @param[in,out] endptr recieves a pointer to the first character after + @param[in,out] endptr receives a pointer to the first character after the number @return the floating point number @@ -10877,12 +10877,12 @@ basic_json_parser_66: /*! @brief parse floating point number - This function (and its overloads) serves to select the most approprate + This function (and its overloads) serves to select the most appropriate standard floating point number parsing function based on the type supplied via the first parameter. Set this to @a static_cast(nullptr). - @param[in,out] endptr recieves a pointer to the first character after + @param[in,out] endptr receives a pointer to the first character after the number @return the floating point number @@ -10925,7 +10925,7 @@ basic_json_parser_66: // maximum absolute value of the relevant integer type number_unsigned_t max; - // temporarily store the type to avoid unecessary bitfield access + // temporarily store the type to avoid unnecessary bitfield access value_t type; // look for sign @@ -11558,7 +11558,7 @@ basic_json_parser_66: if (reference_token == "-") { - // explicityly treat "-" as index beyond the end + // explicitly treat "-" as index beyond the end ptr = &ptr->operator[](ptr->m_value.array->size()); } else @@ -12065,7 +12065,7 @@ basic_json_parser_66: primitive. The original JSON value can be restored using the @ref unflatten() function. - @return an object that maps JSON pointers to primitve values + @return an object that maps JSON pointers to primitive values @note Empty objects and arrays are flattened to `null` and will not be reconstructed correctly by the @ref unflatten() function. @@ -12132,7 +12132,7 @@ basic_json_parser_66: [JSON Patch](http://jsonpatch.com) defines a JSON document structure for expressing a sequence of operations to apply to a JSON) document. With - this funcion, a JSON Patch is applied to the current JSON value by + this function, a JSON Patch is applied to the current JSON value by executing all operations from the patch. @param[in] json_patch JSON patch document @@ -12300,7 +12300,7 @@ basic_json_parser_66: JSON_THROW(std::invalid_argument("JSON patch must be an array of objects")); } - // iterate and apply th eoperations + // iterate and apply the operations for (const auto& val : json_patch) { // wrapper to get a value for an operation @@ -12439,8 +12439,8 @@ basic_json_parser_66: @note Currently, only `remove`, `add`, and `replace` operations are generated. - @param[in] source JSON value to copare from - @param[in] target JSON value to copare against + @param[in] source JSON value to compare from + @param[in] target JSON value to compare against @param[in] path helper value to create JSON pointers @return a JSON patch to convert the @a source to @a target diff --git a/src/json.hpp.re2c b/src/json.hpp.re2c index edc209bf..c477ba22 100644 --- a/src/json.hpp.re2c +++ b/src/json.hpp.re2c @@ -1106,7 +1106,7 @@ class basic_json /*! @brief returns version information on the library - This function returns a JSON object with infiormation about the library, + This function returns a JSON object with information about the library, including the version number and information on the platform and compiler. @return JSON object holding version information @@ -3417,7 +3417,7 @@ class basic_json /*! @brief get a reference value (implicit) - Implict reference access to the internally stored JSON value. No copies + Implicit reference access to the internally stored JSON value. No copies are made. @warning Writing data to the referee of the result yields an undefined @@ -3492,7 +3492,7 @@ class basic_json template < typename ValueType, typename std::enable_if < not std::is_pointer::value and not std::is_same::value -#ifndef _MSC_VER // fix for issue #167 operator<< abiguity under VS2015 +#ifndef _MSC_VER // fix for issue #167 operator<< ambiguity under VS2015 and not std::is_same>::value #endif , int >::type = 0 > @@ -4285,7 +4285,7 @@ class basic_json @complexity The complexity depends on the type: - objects: amortized constant - - arrays: linear in distance between pos and the end of the container + - arrays: linear in distance between @a pos and the end of the container - strings: linear in the length of the string - other types: constant @@ -5537,7 +5537,7 @@ class basic_json @throw std::domain_error if @a pos is not an iterator of *this; example: `"iterator does not fit current value"` - @complexity Constant plus linear in the distance between pos and end of + @complexity Constant plus linear in the distance between @a pos and end of the container. @liveexample{The example shows how `insert()` is used.,insert} @@ -6234,7 +6234,7 @@ class basic_json `std::setw(4)` on @a o sets the indentation level to `4` and the serialization result is the same as calling `dump(4)`. - @note During serializaion, the locale and the precision of the output + @note During serialization, the locale and the precision of the output stream @a o are changed. The original values are restored when the function returns. @@ -9774,7 +9774,7 @@ class basic_json if (m_stream == nullptr or m_stream->eof()) { // m_start may or may not be pointing into m_line_buffer at - // this point. We trust the standand library to do the right + // this point. We trust the standard library to do the right // thing. See http://stackoverflow.com/q/28142011/266378 m_line_buffer.assign(m_start, m_limit); @@ -9862,7 +9862,7 @@ class basic_json m_start + 1 + x < m_cursor - 1 must hold to loop indefinitely. This can be rephrased to m_cursor - m_start - 2 > x. With the precondition, we x <= 0, meaning that the loop condition holds - indefinitly if i is always decreased. However, observe that the value + indefinitely if i is always decreased. However, observe that the value of i is strictly increasing with each iteration, as it is incremented by 1 in the iteration expression and never decremented inside the loop body. Hence, the loop condition will eventually be false which @@ -9991,12 +9991,12 @@ class basic_json /*! @brief parse floating point number - This function (and its overloads) serves to select the most approprate + This function (and its overloads) serves to select the most appropriate standard floating point number parsing function based on the type supplied via the first parameter. Set this to @a static_cast(nullptr). - @param[in,out] endptr recieves a pointer to the first character after + @param[in,out] endptr receives a pointer to the first character after the number @return the floating point number @@ -10009,12 +10009,12 @@ class basic_json /*! @brief parse floating point number - This function (and its overloads) serves to select the most approprate + This function (and its overloads) serves to select the most appropriate standard floating point number parsing function based on the type supplied via the first parameter. Set this to @a static_cast(nullptr). - @param[in,out] endptr recieves a pointer to the first character after + @param[in,out] endptr receives a pointer to the first character after the number @return the floating point number @@ -10027,12 +10027,12 @@ class basic_json /*! @brief parse floating point number - This function (and its overloads) serves to select the most approprate + This function (and its overloads) serves to select the most appropriate standard floating point number parsing function based on the type supplied via the first parameter. Set this to @a static_cast(nullptr). - @param[in,out] endptr recieves a pointer to the first character after + @param[in,out] endptr receives a pointer to the first character after the number @return the floating point number @@ -10075,7 +10075,7 @@ class basic_json // maximum absolute value of the relevant integer type number_unsigned_t max; - // temporarily store the type to avoid unecessary bitfield access + // temporarily store the type to avoid unnecessary bitfield access value_t type; // look for sign @@ -10708,7 +10708,7 @@ class basic_json if (reference_token == "-") { - // explicityly treat "-" as index beyond the end + // explicitly treat "-" as index beyond the end ptr = &ptr->operator[](ptr->m_value.array->size()); } else @@ -11215,7 +11215,7 @@ class basic_json primitive. The original JSON value can be restored using the @ref unflatten() function. - @return an object that maps JSON pointers to primitve values + @return an object that maps JSON pointers to primitive values @note Empty objects and arrays are flattened to `null` and will not be reconstructed correctly by the @ref unflatten() function. @@ -11282,7 +11282,7 @@ class basic_json [JSON Patch](http://jsonpatch.com) defines a JSON document structure for expressing a sequence of operations to apply to a JSON) document. With - this funcion, a JSON Patch is applied to the current JSON value by + this function, a JSON Patch is applied to the current JSON value by executing all operations from the patch. @param[in] json_patch JSON patch document @@ -11450,7 +11450,7 @@ class basic_json JSON_THROW(std::invalid_argument("JSON patch must be an array of objects")); } - // iterate and apply th eoperations + // iterate and apply the operations for (const auto& val : json_patch) { // wrapper to get a value for an operation @@ -11589,8 +11589,8 @@ class basic_json @note Currently, only `remove`, `add`, and `replace` operations are generated. - @param[in] source JSON value to copare from - @param[in] target JSON value to copare against + @param[in] source JSON value to compare from + @param[in] target JSON value to compare against @param[in] path helper value to create JSON pointers @return a JSON patch to convert the @a source to @a target From 0ffa18aab8254973efb53aaa4ce805fa896e3889 Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Wed, 8 Feb 2017 19:16:38 +0100 Subject: [PATCH 44/80] :memo: listing projects using the library --- README.md | 6 ++++++ doc/usages/ios.png | Bin 0 -> 208669 bytes doc/usages/macos.png | Bin 0 -> 1305068 bytes 3 files changed, 6 insertions(+) create mode 100755 doc/usages/ios.png create mode 100644 doc/usages/macos.png diff --git a/README.md b/README.md index c1fd0d89..f8f75644 100644 --- a/README.md +++ b/README.md @@ -25,6 +25,7 @@ - [Supported compilers](#supported-compilers) - [License](#license) - [Thanks](#thanks) +- [Projects using JSON for Modern C++](#projects-using-json-for-modern-c) - [Notes](#notes) - [Execute unit tests](#execute-unit-tests) @@ -826,6 +827,11 @@ I deeply appreciate the help of the following people. Thanks a lot for helping out! Please [let me know](mailto:mail@nlohmann.me) if I forgot someone. +## Projects using JSON for Modern C++ + +The library is currently used in Apple macOS Sierra and iOS 10. I am not sure what they are using the library for, but I am happy that it runs on so many devices. + + ## Notes - The code contains numerous debug **assertions** which can be switched off by defining the preprocessor macro `NDEBUG`, see the [documentation of `assert`](http://en.cppreference.com/w/cpp/error/assert). In particular, note [`operator[]`](https://nlohmann.github.io/json/classnlohmann_1_1basic__json_a2e26bd0b0168abb61f67ad5bcd5b9fa1.html#a2e26bd0b0168abb61f67ad5bcd5b9fa1) implements **unchecked access** for const objects: If the given key is not present, the behavior is undefined (think of a dereferenced null pointer) and yields an [assertion failure](https://github.com/nlohmann/json/issues/289) if assertions are switched on. If you are not sure whether an element in an object exists, use checked access with the [`at()` function](https://nlohmann.github.io/json/classnlohmann_1_1basic__json_a674de1ee73e6bf4843fc5dc1351fb726.html#a674de1ee73e6bf4843fc5dc1351fb726). diff --git a/doc/usages/ios.png b/doc/usages/ios.png new file mode 100755 index 0000000000000000000000000000000000000000..1d2c1b80717bc563b8880882369b179d86840611 GIT binary patch literal 208669 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%0Douss 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 e3tx9u5&(VyoJs3x!1{ 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�M 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 ^K{(EcveNOEDWfe_1LHAMobzp1p&_#qN;?i;16R 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
x-Z)=}We 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 z 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 z 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
{srP7wQg`gG`v_jIrax^(R+LM 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

oZAgzZp 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. @@ -1136,10 +1136,10 @@ class basic_json result["url"] = "https://github.com/nlohmann/json"; result["version"] = { - {"string", "2.1.0"}, + {"string", "2.1.1"}, {"major", 2}, {"minor", 1}, - {"patch", 0}, + {"patch", 1} }; #ifdef _WIN32 @@ -1747,7 +1747,7 @@ class basic_json { if (t == value_t::null) { - JSON_THROW(std::domain_error("961c151d2e87f2686a955a9be24d316f1362bf21 2.1.0")); // LCOV_EXCL_LINE + JSON_THROW(std::domain_error("961c151d2e87f2686a955a9be24d316f1362bf21 2.1.1")); // LCOV_EXCL_LINE } break; } @@ -7969,7 +7969,7 @@ class basic_json @sa @ref from_cbor(const std::vector&, const size_t) for the related CBOR format - @since version 2.0.9, parameter @a start_index since 2.0.11 + @since version 2.0.9, parameter @a start_index since 2.1.1 */ static basic_json from_msgpack(const std::vector& v, const size_t start_index = 0) @@ -8032,7 +8032,7 @@ class basic_json @sa @ref from_msgpack(const std::vector&, const size_t) for the related MessagePack format - @since version 2.0.9, parameter @a start_index since 2.0.11 + @since version 2.0.9, parameter @a start_index since 2.1.1 */ static basic_json from_cbor(const std::vector& v, const size_t start_index = 0) diff --git a/src/json.hpp.re2c b/src/json.hpp.re2c index 6fda8290..a42daba6 100644 --- a/src/json.hpp.re2c +++ b/src/json.hpp.re2c @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ -| | |__ | | | | | | version 2.1.0 +| | |__ | | | | | | version 2.1.1 |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License . @@ -1136,10 +1136,10 @@ class basic_json result["url"] = "https://github.com/nlohmann/json"; result["version"] = { - {"string", "2.1.0"}, + {"string", "2.1.1"}, {"major", 2}, {"minor", 1}, - {"patch", 0}, + {"patch", 1} }; #ifdef _WIN32 @@ -1747,7 +1747,7 @@ class basic_json { if (t == value_t::null) { - JSON_THROW(std::domain_error("961c151d2e87f2686a955a9be24d316f1362bf21 2.1.0")); // LCOV_EXCL_LINE + JSON_THROW(std::domain_error("961c151d2e87f2686a955a9be24d316f1362bf21 2.1.1")); // LCOV_EXCL_LINE } break; } @@ -7969,7 +7969,7 @@ class basic_json @sa @ref from_cbor(const std::vector&, const size_t) for the related CBOR format - @since version 2.0.9, parameter @a start_index since 2.0.11 + @since version 2.0.9, parameter @a start_index since 2.1.1 */ static basic_json from_msgpack(const std::vector& v, const size_t start_index = 0) @@ -8032,7 +8032,7 @@ class basic_json @sa @ref from_msgpack(const std::vector&, const size_t) for the related MessagePack format - @since version 2.0.9, parameter @a start_index since 2.0.11 + @since version 2.0.9, parameter @a start_index since 2.1.1 */ static basic_json from_cbor(const std::vector& v, const size_t start_index = 0) diff --git a/test/src/fuzzer-driver_afl.cpp b/test/src/fuzzer-driver_afl.cpp index b1699f36..92e91475 100644 --- a/test/src/fuzzer-driver_afl.cpp +++ b/test/src/fuzzer-driver_afl.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (fuzz test support) -| | |__ | | | | | | version 2.1.0 +| | |__ | | | | | | version 2.1.1 |_____|_____|_____|_|___| https://github.com/nlohmann/json This file implements a driver for American Fuzzy Lop (afl-fuzz). It relies on diff --git a/test/src/fuzzer-parse_cbor.cpp b/test/src/fuzzer-parse_cbor.cpp index 1b6664f8..30fa6977 100644 --- a/test/src/fuzzer-parse_cbor.cpp +++ b/test/src/fuzzer-parse_cbor.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (fuzz test support) -| | |__ | | | | | | version 2.1.0 +| | |__ | | | | | | version 2.1.1 |_____|_____|_____|_|___| https://github.com/nlohmann/json This file implements a parser test suitable for fuzz testing. Given a byte diff --git a/test/src/fuzzer-parse_json.cpp b/test/src/fuzzer-parse_json.cpp index 40ccf587..bd2e5e39 100644 --- a/test/src/fuzzer-parse_json.cpp +++ b/test/src/fuzzer-parse_json.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (fuzz test support) -| | |__ | | | | | | version 2.1.0 +| | |__ | | | | | | version 2.1.1 |_____|_____|_____|_|___| https://github.com/nlohmann/json This file implements a parser test suitable for fuzz testing. Given a byte diff --git a/test/src/fuzzer-parse_msgpack.cpp b/test/src/fuzzer-parse_msgpack.cpp index 381dc75f..bf2fcab0 100644 --- a/test/src/fuzzer-parse_msgpack.cpp +++ b/test/src/fuzzer-parse_msgpack.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (fuzz test support) -| | |__ | | | | | | version 2.1.0 +| | |__ | | | | | | version 2.1.1 |_____|_____|_____|_|___| https://github.com/nlohmann/json This file implements a parser test suitable for fuzz testing. Given a byte diff --git a/test/src/unit-algorithms.cpp b/test/src/unit-algorithms.cpp index 3a73c104..8386238a 100644 --- a/test/src/unit-algorithms.cpp +++ b/test/src/unit-algorithms.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (test suite) -| | |__ | | | | | | version 2.1.0 +| | |__ | | | | | | version 2.1.1 |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License . diff --git a/test/src/unit-allocator.cpp b/test/src/unit-allocator.cpp index 78a48115..903d5950 100644 --- a/test/src/unit-allocator.cpp +++ b/test/src/unit-allocator.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (test suite) -| | |__ | | | | | | version 2.1.0 +| | |__ | | | | | | version 2.1.1 |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License . diff --git a/test/src/unit-capacity.cpp b/test/src/unit-capacity.cpp index 44a35b90..8f2c3112 100644 --- a/test/src/unit-capacity.cpp +++ b/test/src/unit-capacity.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (test suite) -| | |__ | | | | | | version 2.1.0 +| | |__ | | | | | | version 2.1.1 |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License . diff --git a/test/src/unit-cbor.cpp b/test/src/unit-cbor.cpp index da5603e8..84b280bc 100644 --- a/test/src/unit-cbor.cpp +++ b/test/src/unit-cbor.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (test suite) -| | |__ | | | | | | version 2.1.0 +| | |__ | | | | | | version 2.1.1 |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License . diff --git a/test/src/unit-class_const_iterator.cpp b/test/src/unit-class_const_iterator.cpp index 1a05becb..840549a3 100644 --- a/test/src/unit-class_const_iterator.cpp +++ b/test/src/unit-class_const_iterator.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (test suite) -| | |__ | | | | | | version 2.1.0 +| | |__ | | | | | | version 2.1.1 |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License . diff --git a/test/src/unit-class_iterator.cpp b/test/src/unit-class_iterator.cpp index e3ef6a0e..0238c337 100644 --- a/test/src/unit-class_iterator.cpp +++ b/test/src/unit-class_iterator.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (test suite) -| | |__ | | | | | | version 2.1.0 +| | |__ | | | | | | version 2.1.1 |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License . diff --git a/test/src/unit-class_lexer.cpp b/test/src/unit-class_lexer.cpp index 79dbb766..0b019bfe 100644 --- a/test/src/unit-class_lexer.cpp +++ b/test/src/unit-class_lexer.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (test suite) -| | |__ | | | | | | version 2.1.0 +| | |__ | | | | | | version 2.1.1 |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License . diff --git a/test/src/unit-class_parser.cpp b/test/src/unit-class_parser.cpp index 27eef5ce..e3ad3723 100644 --- a/test/src/unit-class_parser.cpp +++ b/test/src/unit-class_parser.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (test suite) -| | |__ | | | | | | version 2.1.0 +| | |__ | | | | | | version 2.1.1 |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License . diff --git a/test/src/unit-comparison.cpp b/test/src/unit-comparison.cpp index f1e1aeb3..ac243674 100644 --- a/test/src/unit-comparison.cpp +++ b/test/src/unit-comparison.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (test suite) -| | |__ | | | | | | version 2.1.0 +| | |__ | | | | | | version 2.1.1 |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License . diff --git a/test/src/unit-concepts.cpp b/test/src/unit-concepts.cpp index cdc104b6..79be78cd 100644 --- a/test/src/unit-concepts.cpp +++ b/test/src/unit-concepts.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (test suite) -| | |__ | | | | | | version 2.1.0 +| | |__ | | | | | | version 2.1.1 |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License . diff --git a/test/src/unit-constructor1.cpp b/test/src/unit-constructor1.cpp index 36666746..6bba7019 100644 --- a/test/src/unit-constructor1.cpp +++ b/test/src/unit-constructor1.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (test suite) -| | |__ | | | | | | version 2.1.0 +| | |__ | | | | | | version 2.1.1 |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License . diff --git a/test/src/unit-constructor2.cpp b/test/src/unit-constructor2.cpp index 95cb87da..7259edfb 100644 --- a/test/src/unit-constructor2.cpp +++ b/test/src/unit-constructor2.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (test suite) -| | |__ | | | | | | version 2.1.0 +| | |__ | | | | | | version 2.1.1 |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License . diff --git a/test/src/unit-convenience.cpp b/test/src/unit-convenience.cpp index a9355da0..891dbc14 100644 --- a/test/src/unit-convenience.cpp +++ b/test/src/unit-convenience.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (test suite) -| | |__ | | | | | | version 2.1.0 +| | |__ | | | | | | version 2.1.1 |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License . diff --git a/test/src/unit-conversions.cpp b/test/src/unit-conversions.cpp index 7db56ee0..106e37de 100644 --- a/test/src/unit-conversions.cpp +++ b/test/src/unit-conversions.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (test suite) -| | |__ | | | | | | version 2.1.0 +| | |__ | | | | | | version 2.1.1 |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License . diff --git a/test/src/unit-deserialization.cpp b/test/src/unit-deserialization.cpp index aaf4627b..9028fdfb 100644 --- a/test/src/unit-deserialization.cpp +++ b/test/src/unit-deserialization.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (test suite) -| | |__ | | | | | | version 2.1.0 +| | |__ | | | | | | version 2.1.1 |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License . diff --git a/test/src/unit-element_access1.cpp b/test/src/unit-element_access1.cpp index 5f264ac7..f0763c5d 100644 --- a/test/src/unit-element_access1.cpp +++ b/test/src/unit-element_access1.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (test suite) -| | |__ | | | | | | version 2.1.0 +| | |__ | | | | | | version 2.1.1 |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License . diff --git a/test/src/unit-element_access2.cpp b/test/src/unit-element_access2.cpp index 353d66d9..8e91e89d 100644 --- a/test/src/unit-element_access2.cpp +++ b/test/src/unit-element_access2.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (test suite) -| | |__ | | | | | | version 2.1.0 +| | |__ | | | | | | version 2.1.1 |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License . diff --git a/test/src/unit-inspection.cpp b/test/src/unit-inspection.cpp index d5a97b7e..aead1258 100644 --- a/test/src/unit-inspection.cpp +++ b/test/src/unit-inspection.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (test suite) -| | |__ | | | | | | version 2.1.0 +| | |__ | | | | | | version 2.1.1 |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License . diff --git a/test/src/unit-iterator_wrapper.cpp b/test/src/unit-iterator_wrapper.cpp index 79def908..b8e00659 100644 --- a/test/src/unit-iterator_wrapper.cpp +++ b/test/src/unit-iterator_wrapper.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (test suite) -| | |__ | | | | | | version 2.1.0 +| | |__ | | | | | | version 2.1.1 |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License . diff --git a/test/src/unit-iterators1.cpp b/test/src/unit-iterators1.cpp index 78ea3db4..eebee110 100644 --- a/test/src/unit-iterators1.cpp +++ b/test/src/unit-iterators1.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (test suite) -| | |__ | | | | | | version 2.1.0 +| | |__ | | | | | | version 2.1.1 |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License . diff --git a/test/src/unit-iterators2.cpp b/test/src/unit-iterators2.cpp index ef806ad7..b2bc4a38 100644 --- a/test/src/unit-iterators2.cpp +++ b/test/src/unit-iterators2.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (test suite) -| | |__ | | | | | | version 2.1.0 +| | |__ | | | | | | version 2.1.1 |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License . diff --git a/test/src/unit-json_patch.cpp b/test/src/unit-json_patch.cpp index 837691de..05ed7502 100644 --- a/test/src/unit-json_patch.cpp +++ b/test/src/unit-json_patch.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (test suite) -| | |__ | | | | | | version 2.1.0 +| | |__ | | | | | | version 2.1.1 |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License . diff --git a/test/src/unit-json_pointer.cpp b/test/src/unit-json_pointer.cpp index 24aa4a7d..495d7066 100644 --- a/test/src/unit-json_pointer.cpp +++ b/test/src/unit-json_pointer.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (test suite) -| | |__ | | | | | | version 2.1.0 +| | |__ | | | | | | version 2.1.1 |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License . diff --git a/test/src/unit-meta.cpp b/test/src/unit-meta.cpp index 28c1a9d8..8c614a6c 100644 --- a/test/src/unit-meta.cpp +++ b/test/src/unit-meta.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (test suite) -| | |__ | | | | | | version 2.1.0 +| | |__ | | | | | | version 2.1.1 |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License . @@ -36,5 +36,12 @@ TEST_CASE("version information") SECTION("version()") { CHECK(json::meta()["name"] == "JSON for Modern C++"); + CHECK(json::meta()["version"] == json( + { + {"string", "2.1.1"}, + {"major", 2}, + {"minor", 1}, + {"patch", 1} + })); } } diff --git a/test/src/unit-modifiers.cpp b/test/src/unit-modifiers.cpp index 80b1a711..0edc9a12 100644 --- a/test/src/unit-modifiers.cpp +++ b/test/src/unit-modifiers.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (test suite) -| | |__ | | | | | | version 2.1.0 +| | |__ | | | | | | version 2.1.1 |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License . diff --git a/test/src/unit-msgpack.cpp b/test/src/unit-msgpack.cpp index 2f79d31b..3a2ae5b1 100644 --- a/test/src/unit-msgpack.cpp +++ b/test/src/unit-msgpack.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (test suite) -| | |__ | | | | | | version 2.1.0 +| | |__ | | | | | | version 2.1.1 |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License . diff --git a/test/src/unit-noexcept.cpp b/test/src/unit-noexcept.cpp index ddd8102d..898e7796 100644 --- a/test/src/unit-noexcept.cpp +++ b/test/src/unit-noexcept.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (test suite) -| | |__ | | | | | | version 2.1.0 +| | |__ | | | | | | version 2.1.1 |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License . diff --git a/test/src/unit-pointer_access.cpp b/test/src/unit-pointer_access.cpp index 5611a750..5f70780d 100644 --- a/test/src/unit-pointer_access.cpp +++ b/test/src/unit-pointer_access.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (test suite) -| | |__ | | | | | | version 2.1.0 +| | |__ | | | | | | version 2.1.1 |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License . diff --git a/test/src/unit-readme.cpp b/test/src/unit-readme.cpp index 954b7440..1b22f1b3 100644 --- a/test/src/unit-readme.cpp +++ b/test/src/unit-readme.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (test suite) -| | |__ | | | | | | version 2.1.0 +| | |__ | | | | | | version 2.1.1 |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License . diff --git a/test/src/unit-reference_access.cpp b/test/src/unit-reference_access.cpp index 6281572a..e73ec07c 100644 --- a/test/src/unit-reference_access.cpp +++ b/test/src/unit-reference_access.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (test suite) -| | |__ | | | | | | version 2.1.0 +| | |__ | | | | | | version 2.1.1 |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License . diff --git a/test/src/unit-regression.cpp b/test/src/unit-regression.cpp index bfa4d497..83bb371a 100644 --- a/test/src/unit-regression.cpp +++ b/test/src/unit-regression.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (test suite) -| | |__ | | | | | | version 2.1.0 +| | |__ | | | | | | version 2.1.1 |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License . diff --git a/test/src/unit-serialization.cpp b/test/src/unit-serialization.cpp index b8bb6455..3df56cdc 100644 --- a/test/src/unit-serialization.cpp +++ b/test/src/unit-serialization.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (test suite) -| | |__ | | | | | | version 2.1.0 +| | |__ | | | | | | version 2.1.1 |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License . diff --git a/test/src/unit-testsuites.cpp b/test/src/unit-testsuites.cpp index ab1f689c..e83d5b74 100644 --- a/test/src/unit-testsuites.cpp +++ b/test/src/unit-testsuites.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (test suite) -| | |__ | | | | | | version 2.1.0 +| | |__ | | | | | | version 2.1.1 |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License . diff --git a/test/src/unit-udt.cpp b/test/src/unit-udt.cpp index ba56532d..a8103082 100644 --- a/test/src/unit-udt.cpp +++ b/test/src/unit-udt.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (test suite) -| | |__ | | | | | | version 2.1.0 +| | |__ | | | | | | version 2.1.1 |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License . diff --git a/test/src/unit-unicode.cpp b/test/src/unit-unicode.cpp index 89e828f4..c429b91c 100644 --- a/test/src/unit-unicode.cpp +++ b/test/src/unit-unicode.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (test suite) -| | |__ | | | | | | version 2.1.0 +| | |__ | | | | | | version 2.1.1 |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License . diff --git a/test/src/unit.cpp b/test/src/unit.cpp index c89a0e83..38f2d5b4 100644 --- a/test/src/unit.cpp +++ b/test/src/unit.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (test suite) -| | |__ | | | | | | version 2.1.0 +| | |__ | | | | | | version 2.1.1 |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License .

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 Date: Wed, 8 Feb 2017 19:22:19 +0100 Subject: [PATCH 45/80] :memo: added screenshots --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index f8f75644..178bac0f 100644 --- a/README.md +++ b/README.md @@ -831,6 +831,10 @@ Thanks a lot for helping out! Please [let me know](mailto:mail@nlohmann.me) if I The library is currently used in Apple macOS Sierra and iOS 10. I am not sure what they are using the library for, but I am happy that it runs on so many devices. +macOS Sierra + +iOS 10 + ## Notes From c485d46ceaf938598773c7c7d325a5522f1302ac Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Wed, 8 Feb 2017 20:00:46 +0100 Subject: [PATCH 46/80] :memo: screenshoots look ugly --- README.md | 4 ---- 1 file changed, 4 deletions(-) diff --git a/README.md b/README.md index 178bac0f..f8f75644 100644 --- a/README.md +++ b/README.md @@ -831,10 +831,6 @@ Thanks a lot for helping out! Please [let me know](mailto:mail@nlohmann.me) if I The library is currently used in Apple macOS Sierra and iOS 10. I am not sure what they are using the library for, but I am happy that it runs on so many devices. -macOS Sierra - -iOS 10 - ## Notes From ed8516dc39bdc6016b204c57baef26ffb629bece Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Thu, 9 Feb 2017 17:38:02 +0100 Subject: [PATCH 47/80] :construction_worker: added Codacy badge --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index f8f75644..9732a0fa 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,7 @@ [![Build Status](https://ci.appveyor.com/api/projects/status/1acb366xfyg3qybk/branch/develop?svg=true)](https://ci.appveyor.com/project/nlohmann/json) [![Coverage Status](https://img.shields.io/coveralls/nlohmann/json.svg)](https://coveralls.io/r/nlohmann/json) [![Coverity Scan Build Status](https://scan.coverity.com/projects/5550/badge.svg)](https://scan.coverity.com/projects/nlohmann-json) +[![Codacy Badge](https://api.codacy.com/project/badge/Grade/f3732b3327e34358a0e9d1fe9f661f08)](https://www.codacy.com/app/nlohmann/json?utm_source=github.com&utm_medium=referral&utm_content=nlohmann/json&utm_campaign=Badge_Grade) [![Try online](https://img.shields.io/badge/try-online-blue.svg)](http://melpon.org/wandbox/permlink/4NEU6ZZMoM9lpIex) [![Documentation](https://img.shields.io/badge/docs-doxygen-blue.svg)](http://nlohmann.github.io/json) [![GitHub license](https://img.shields.io/badge/license-MIT-blue.svg)](https://raw.githubusercontent.com/nlohmann/json/master/LICENSE.MIT) From 9f5dccbab5765638632b5b380fdecd4533dc5c3e Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Sat, 11 Feb 2017 15:55:53 +0100 Subject: [PATCH 48/80] :lipstick: cleanup --- src/json.hpp | 146 ++++++++++++++++++++-------------------------- src/json.hpp.re2c | 146 ++++++++++++++++++++-------------------------- 2 files changed, 128 insertions(+), 164 deletions(-) diff --git a/src/json.hpp b/src/json.hpp index 143ae0b8..2d98db8c 100644 --- a/src/json.hpp +++ b/src/json.hpp @@ -10840,13 +10840,13 @@ basic_json_parser_66: /*! - @brief parse string into a built-in arithmetic type as if - the current locale is POSIX. + @brief parse string into a built-in arithmetic type as if the current + locale is POSIX. - note: in floating-point case strtod may parse - past the token's end - this is not an error. + @note in floating-point case strtod may parse past the token's end - + this is not an error - any leading blanks are not handled. + @note any leading blanks are not handled */ struct strtonum { @@ -10855,36 +10855,37 @@ basic_json_parser_66: : m_start(start), m_end(end) {} - /// return true iff parsed successfully as - /// number of type T. - /// - /// @val shall contain parsed value, or - /// undefined value if could not parse. - template::value>::type > + /*! + @return true iff parsed successfully as number of type T + + @param[in,out] val shall contain parsed value, or undefined value + if could not parse + */ + template::value>::type> bool to(T& val) const { return parse(val, std::is_integral()); } - /// return true iff token matches ^[+-]\d+$ - /// - /// this is a helper to determine whether to - /// parse the token into floating-point or - /// integral type. We wouldn't need it if - /// we had separate token types for integral - /// and floating-point cases. + /*! + This is a helper to determine whether to parse the token into + floating-point or integral type. + + @note We wouldn't need it if we had separate token types for + integral and floating-point cases. + + @return true iff token matches `^[+-]\d+$` + */ bool is_integral() const { const char* p = m_start; - if (!p) + if (p == nullptr) { return false; // LCOV_EXCL_LINE } - if (*p == '-' or * p == '+') + if ((*p == '-') or (*p == '+')) { ++p; } @@ -10894,39 +10895,31 @@ basic_json_parser_66: return false; // LCOV_EXCL_LINE } - while (p < m_end and* p >= '0' - and * p <= '9') + while ((p < m_end) and (*p >= '0') and (*p <= '9')) { ++p; } - return p == m_end; + return (p == m_end); } private: const char* const m_start = nullptr; - const char* const m_end = nullptr; + const char* const m_end = nullptr; // overloaded wrappers for strtod/strtof/strtold // that will be called from parse - - static void strtof(float& f, - const char* str, - char** endptr) + static void strtof(float& f, const char* str, char** endptr) { f = std::strtof(str, endptr); } - static void strtof(double& f, - const char* str, - char** endptr) + static void strtof(double& f, const char* str, char** endptr) { f = std::strtod(str, endptr); } - static void strtof(long double& f, - const char* str, - char** endptr) + static void strtof(long double& f, const char* str, char** endptr) { f = std::strtold(str, endptr); } @@ -10934,37 +10927,32 @@ basic_json_parser_66: template bool parse(T& value, /*is_integral=*/std::false_type) const { - // replace decimal separator with locale-specific - // version, when necessary; data will point to - // either the original string, or buf, or tempstr - // containing the fixed string. + // replace decimal separator with locale-specific version, + // when necessary; data will point to either the original + // string, or buf, or tempstr containing the fixed string. std::string tempstr; std::array buf; const size_t len = static_cast(m_end - m_start); - // Since dealing with strtod family of functions, - // we're getting the decimal point char from the - // C locale facilities instead of C++'s numpunct - // facet of the current std::locale; + // since dealing with strtod family of functions, we're + // getting the decimal point char from the C locale facilities + // instead of C++'s numpunct facet of the current std::locale const auto loc = localeconv(); assert(loc != nullptr); - const char decimal_point_char = !loc->decimal_point ? '.' - : loc->decimal_point[0]; + const char decimal_point_char = (loc->decimal_point == nullptr) ? '.' : loc->decimal_point[0]; const char* data = m_start; if (decimal_point_char != '.') { - const size_t ds_pos = static_cast( - std::find(m_start, m_end, '.') - m_start ); + const size_t ds_pos = static_cast(std::find(m_start, m_end, '.') - m_start); if (ds_pos != len) { - // copy the data into the local buffer or - // tempstr, if buffer is too small; - // replace decimal separator, and update - // data to point to the modified bytes - if (len + 1 < buf.size()) + // copy the data into the local buffer or tempstr, if + // buffer is too small; replace decimal separator, and + // update data to point to the modified bytes + if ((len + 1) < buf.size()) { std::copy(m_start, m_end, buf.data()); buf[len] = 0; @@ -10985,13 +10973,12 @@ basic_json_parser_66: // this calls appropriate overload depending on T strtof(value, data, &endptr); - // note that reading past the end is OK, the data may be, - // for example, "123.", where the parsed token only - // contains "123", but strtod will read the dot as well. - const bool ok = endptr >= data + len - and len > 0; + // note that reading past the end is OK, the data may be, for + // example, "123.", where the parsed token only contains + // "123", but strtod will read the dot as well. + const bool ok = (endptr >= (data + len)) and (len > 0); - if (ok and value == 0.0 and * data == '-') + if (ok and (value == 0.0) and (*data == '-')) { // some implementations forget to negate the zero value = -0.0; @@ -11000,16 +10987,12 @@ basic_json_parser_66: return ok; } - signed long long parse_integral( - char** endptr, - /*is_signed*/std::true_type) const + signed long long parse_integral(char** endptr, /*is_signed*/std::true_type) const { return std::strtoll(m_start, endptr, 10); } - unsigned long long parse_integral( - char** endptr, - /*is_signed*/std::false_type) const + unsigned long long parse_integral(char** endptr, /*is_signed*/std::false_type) const { return std::strtoull(m_start, endptr, 10); } @@ -11018,20 +11001,20 @@ basic_json_parser_66: bool parse(T& value, /*is_integral=*/std::true_type) const { char* endptr = nullptr; - errno = 0; // these are thread-local + errno = 0; // these are thread-local const auto x = parse_integral(&endptr, std::is_signed()); - static_assert(std::is_signed() // called right overload? - == std::is_signed(), ""); + // called right overload? + static_assert(std::is_signed() == std::is_signed(), ""); value = static_cast(x); - return x == static_cast(value) // x fits into destination T - and (x < 0) == (value < 0) // preserved sign - and (x != 0 or is_integral()) // strto[u]ll did nto fail - and errno == 0 // strto[u]ll did not overflow - and m_start < m_end // token was not empty - and endptr == m_end; // parsed entire token exactly + return (x == static_cast(value)) // x fits into destination T + and (x < 0) == (value < 0) // preserved sign + and ((x != 0) or is_integral()) // strto[u]ll did nto fail + and (errno == 0) // strto[u]ll did not overflow + and (m_start < m_end) // token was not empty + and (endptr == m_end); // parsed entire token exactly } }; @@ -11061,20 +11044,20 @@ basic_json_parser_66: strtonum num(reinterpret_cast(m_start), reinterpret_cast(m_cursor)); - const bool is_negative = *m_start == '-'; + const bool is_negative = (*m_start == '-'); result.m_type = value_t::discarded; if (not num.is_integral()) { - ; // will parse as float below + // will parse as float below } else if (is_negative) { number_integer_t val{0}; if (num.to(val)) { - result.m_type = value_t::number_integer; + result.m_type = value_t::number_integer; result.m_value = val; } } @@ -11089,14 +11072,13 @@ basic_json_parser_66: } number_float_t val{0}; - if (result.m_type != value_t::discarded - or !num.to(val)) + if (result.m_type != value_t::discarded or (not num.to(val))) { - return; // already have a value from above - // or couldn't parse as float_t + // already have a value from above or couldn't parse as float_t + return; } - result.m_type = value_t::number_float; + result.m_type = value_t::number_float; result.m_value = val; // replace infinity and NAN by null diff --git a/src/json.hpp.re2c b/src/json.hpp.re2c index 698fbb3b..b3f7af8d 100644 --- a/src/json.hpp.re2c +++ b/src/json.hpp.re2c @@ -9990,13 +9990,13 @@ class basic_json /*! - @brief parse string into a built-in arithmetic type as if - the current locale is POSIX. + @brief parse string into a built-in arithmetic type as if the current + locale is POSIX. - note: in floating-point case strtod may parse - past the token's end - this is not an error. + @note in floating-point case strtod may parse past the token's end - + this is not an error - any leading blanks are not handled. + @note any leading blanks are not handled */ struct strtonum { @@ -10005,36 +10005,37 @@ class basic_json : m_start(start), m_end(end) {} - /// return true iff parsed successfully as - /// number of type T. - /// - /// @val shall contain parsed value, or - /// undefined value if could not parse. - template::value>::type > + /*! + @return true iff parsed successfully as number of type T + + @param[in,out] val shall contain parsed value, or undefined value + if could not parse + */ + template::value>::type> bool to(T& val) const { return parse(val, std::is_integral()); } - /// return true iff token matches ^[+-]\d+$ - /// - /// this is a helper to determine whether to - /// parse the token into floating-point or - /// integral type. We wouldn't need it if - /// we had separate token types for integral - /// and floating-point cases. + /*! + This is a helper to determine whether to parse the token into + floating-point or integral type. + + @note We wouldn't need it if we had separate token types for + integral and floating-point cases. + + @return true iff token matches `^[+-]\d+$` + */ bool is_integral() const { const char* p = m_start; - if (!p) + if (p == nullptr) { return false; // LCOV_EXCL_LINE } - if (*p == '-' or * p == '+') + if ((*p == '-') or (*p == '+')) { ++p; } @@ -10044,39 +10045,31 @@ class basic_json return false; // LCOV_EXCL_LINE } - while (p < m_end and* p >= '0' - and * p <= '9') + while ((p < m_end) and (*p >= '0') and (*p <= '9')) { ++p; } - return p == m_end; + return (p == m_end); } private: const char* const m_start = nullptr; - const char* const m_end = nullptr; + const char* const m_end = nullptr; // overloaded wrappers for strtod/strtof/strtold // that will be called from parse - - static void strtof(float& f, - const char* str, - char** endptr) + static void strtof(float& f, const char* str, char** endptr) { f = std::strtof(str, endptr); } - static void strtof(double& f, - const char* str, - char** endptr) + static void strtof(double& f, const char* str, char** endptr) { f = std::strtod(str, endptr); } - static void strtof(long double& f, - const char* str, - char** endptr) + static void strtof(long double& f, const char* str, char** endptr) { f = std::strtold(str, endptr); } @@ -10084,37 +10077,32 @@ class basic_json template bool parse(T& value, /*is_integral=*/std::false_type) const { - // replace decimal separator with locale-specific - // version, when necessary; data will point to - // either the original string, or buf, or tempstr - // containing the fixed string. + // replace decimal separator with locale-specific version, + // when necessary; data will point to either the original + // string, or buf, or tempstr containing the fixed string. std::string tempstr; std::array buf; const size_t len = static_cast(m_end - m_start); - // Since dealing with strtod family of functions, - // we're getting the decimal point char from the - // C locale facilities instead of C++'s numpunct - // facet of the current std::locale; + // since dealing with strtod family of functions, we're + // getting the decimal point char from the C locale facilities + // instead of C++'s numpunct facet of the current std::locale const auto loc = localeconv(); assert(loc != nullptr); - const char decimal_point_char = !loc->decimal_point ? '.' - : loc->decimal_point[0]; + const char decimal_point_char = (loc->decimal_point == nullptr) ? '.' : loc->decimal_point[0]; const char* data = m_start; if (decimal_point_char != '.') { - const size_t ds_pos = static_cast( - std::find(m_start, m_end, '.') - m_start ); + const size_t ds_pos = static_cast(std::find(m_start, m_end, '.') - m_start); if (ds_pos != len) { - // copy the data into the local buffer or - // tempstr, if buffer is too small; - // replace decimal separator, and update - // data to point to the modified bytes - if (len + 1 < buf.size()) + // copy the data into the local buffer or tempstr, if + // buffer is too small; replace decimal separator, and + // update data to point to the modified bytes + if ((len + 1) < buf.size()) { std::copy(m_start, m_end, buf.data()); buf[len] = 0; @@ -10135,13 +10123,12 @@ class basic_json // this calls appropriate overload depending on T strtof(value, data, &endptr); - // note that reading past the end is OK, the data may be, - // for example, "123.", where the parsed token only - // contains "123", but strtod will read the dot as well. - const bool ok = endptr >= data + len - and len > 0; + // note that reading past the end is OK, the data may be, for + // example, "123.", where the parsed token only contains + // "123", but strtod will read the dot as well. + const bool ok = (endptr >= (data + len)) and (len > 0); - if (ok and value == 0.0 and * data == '-') + if (ok and (value == 0.0) and (*data == '-')) { // some implementations forget to negate the zero value = -0.0; @@ -10150,16 +10137,12 @@ class basic_json return ok; } - signed long long parse_integral( - char** endptr, - /*is_signed*/std::true_type) const + signed long long parse_integral(char** endptr, /*is_signed*/std::true_type) const { return std::strtoll(m_start, endptr, 10); } - unsigned long long parse_integral( - char** endptr, - /*is_signed*/std::false_type) const + unsigned long long parse_integral(char** endptr, /*is_signed*/std::false_type) const { return std::strtoull(m_start, endptr, 10); } @@ -10168,20 +10151,20 @@ class basic_json bool parse(T& value, /*is_integral=*/std::true_type) const { char* endptr = nullptr; - errno = 0; // these are thread-local + errno = 0; // these are thread-local const auto x = parse_integral(&endptr, std::is_signed()); - static_assert(std::is_signed() // called right overload? - == std::is_signed(), ""); + // called right overload? + static_assert(std::is_signed() == std::is_signed(), ""); value = static_cast(x); - return x == static_cast(value) // x fits into destination T - and (x < 0) == (value < 0) // preserved sign - and (x != 0 or is_integral()) // strto[u]ll did nto fail - and errno == 0 // strto[u]ll did not overflow - and m_start < m_end // token was not empty - and endptr == m_end; // parsed entire token exactly + return (x == static_cast(value)) // x fits into destination T + and (x < 0) == (value < 0) // preserved sign + and ((x != 0) or is_integral()) // strto[u]ll did nto fail + and (errno == 0) // strto[u]ll did not overflow + and (m_start < m_end) // token was not empty + and (endptr == m_end); // parsed entire token exactly } }; @@ -10211,20 +10194,20 @@ class basic_json strtonum num(reinterpret_cast(m_start), reinterpret_cast(m_cursor)); - const bool is_negative = *m_start == '-'; + const bool is_negative = (*m_start == '-'); result.m_type = value_t::discarded; if (not num.is_integral()) { - ; // will parse as float below + // will parse as float below } else if (is_negative) { number_integer_t val{0}; if (num.to(val)) { - result.m_type = value_t::number_integer; + result.m_type = value_t::number_integer; result.m_value = val; } } @@ -10239,14 +10222,13 @@ class basic_json } number_float_t val{0}; - if (result.m_type != value_t::discarded - or !num.to(val)) + if (result.m_type != value_t::discarded or (not num.to(val))) { - return; // already have a value from above - // or couldn't parse as float_t + // already have a value from above or couldn't parse as float_t + return; } - result.m_type = value_t::number_float; + result.m_type = value_t::number_float; result.m_value = val; // replace infinity and NAN by null From c2d55109c1f6b5b39902f52291dee28263b90fa1 Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Sat, 11 Feb 2017 16:54:25 +0100 Subject: [PATCH 49/80] :hammer: make lexer distinguishes number types --- src/json.hpp | 318 ++++++++++++++++++++-------------- src/json.hpp.re2c | 136 +++++++-------- test/src/unit-class_lexer.cpp | 36 ++-- 3 files changed, 275 insertions(+), 215 deletions(-) diff --git a/src/json.hpp b/src/json.hpp index 2d98db8c..b8cdc480 100644 --- a/src/json.hpp +++ b/src/json.hpp @@ -9444,7 +9444,9 @@ class basic_json literal_false, ///< the `false` literal literal_null, ///< the `null` literal value_string, ///< a string -- use get_string() for actual value - value_number, ///< a number -- use get_number() for actual value + value_unsigned_integer, ///< an unsigned integer -- use get_number() for actual value + value_signed_integer, ///< a signed integer -- use get_number() for actual value + value_float, ///< an floating point number -- use get_number() for actual value begin_array, ///< the character for array begin `[` begin_object, ///< the character for object begin `{` end_array, ///< the character for array end `]` @@ -9596,7 +9598,9 @@ class basic_json return "null literal"; case token_type::value_string: return "string literal"; - case token_type::value_number: + case lexer::token_type::value_unsigned_integer: + case lexer::token_type::value_signed_integer: + case lexer::token_type::value_float: return "number literal"; case token_type::begin_array: return "'['"; @@ -9869,11 +9873,11 @@ basic_json_parser_12: } if (yych <= '0') { - goto basic_json_parser_13; + goto basic_json_parser_43; } if (yych <= '9') { - goto basic_json_parser_15; + goto basic_json_parser_45; } goto basic_json_parser_5; basic_json_parser_13: @@ -9883,23 +9887,23 @@ basic_json_parser_13: { if (yych == '.') { - goto basic_json_parser_43; + goto basic_json_parser_47; } } else { if (yych <= 'E') { - goto basic_json_parser_44; + goto basic_json_parser_48; } if (yych == 'e') { - goto basic_json_parser_44; + goto basic_json_parser_48; } } basic_json_parser_14: { - last_token_type = token_type::value_number; + last_token_type = token_type::value_unsigned_integer; break; } basic_json_parser_15: @@ -9918,7 +9922,7 @@ basic_json_parser_15: { if (yych == '.') { - goto basic_json_parser_43; + goto basic_json_parser_47; } goto basic_json_parser_14; } @@ -9926,11 +9930,11 @@ basic_json_parser_15: { if (yych <= 'E') { - goto basic_json_parser_44; + goto basic_json_parser_48; } if (yych == 'e') { - goto basic_json_parser_44; + goto basic_json_parser_48; } goto basic_json_parser_14; } @@ -9957,7 +9961,7 @@ basic_json_parser_23: yych = *(m_marker = ++m_cursor); if (yych == 'a') { - goto basic_json_parser_45; + goto basic_json_parser_49; } goto basic_json_parser_5; basic_json_parser_24: @@ -9965,7 +9969,7 @@ basic_json_parser_24: yych = *(m_marker = ++m_cursor); if (yych == 'u') { - goto basic_json_parser_46; + goto basic_json_parser_50; } goto basic_json_parser_5; basic_json_parser_25: @@ -9973,7 +9977,7 @@ basic_json_parser_25: yych = *(m_marker = ++m_cursor); if (yych == 'r') { - goto basic_json_parser_47; + goto basic_json_parser_51; } goto basic_json_parser_5; basic_json_parser_26: @@ -10055,13 +10059,27 @@ basic_json_parser_31: } basic_json_parser_32: m_cursor = m_marker; - if (yyaccept == 0) + if (yyaccept <= 1) { - goto basic_json_parser_5; + if (yyaccept == 0) + { + goto basic_json_parser_5; + } + else + { + goto basic_json_parser_14; + } } else { - goto basic_json_parser_14; + if (yyaccept == 2) + { + goto basic_json_parser_44; + } + else + { + goto basic_json_parser_55; + } } basic_json_parser_33: ++m_cursor; @@ -10142,7 +10160,7 @@ basic_json_parser_35: } if (yych <= 'u') { - goto basic_json_parser_48; + goto basic_json_parser_52; } goto basic_json_parser_32; } @@ -10261,6 +10279,71 @@ basic_json_parser_42: } goto basic_json_parser_32; basic_json_parser_43: + yyaccept = 2; + yych = *(m_marker = ++m_cursor); + if (yych <= 'D') + { + if (yych == '.') + { + goto basic_json_parser_47; + } + } + else + { + if (yych <= 'E') + { + goto basic_json_parser_48; + } + if (yych == 'e') + { + goto basic_json_parser_48; + } + } +basic_json_parser_44: + { + last_token_type = token_type::value_signed_integer; + break; + } +basic_json_parser_45: + yyaccept = 2; + m_marker = ++m_cursor; + if ((m_limit - m_cursor) < 3) + { + fill_line_buffer(3); // LCOV_EXCL_LINE + } + yych = *m_cursor; + if (yych <= '9') + { + if (yych == '.') + { + goto basic_json_parser_47; + } + if (yych <= '/') + { + goto basic_json_parser_44; + } + goto basic_json_parser_45; + } + else + { + if (yych <= 'E') + { + if (yych <= 'D') + { + goto basic_json_parser_44; + } + goto basic_json_parser_48; + } + else + { + if (yych == 'e') + { + goto basic_json_parser_48; + } + goto basic_json_parser_44; + } + } +basic_json_parser_47: yych = *++m_cursor; if (yych <= '/') { @@ -10268,16 +10351,16 @@ basic_json_parser_43: } if (yych <= '9') { - goto basic_json_parser_49; + goto basic_json_parser_53; } goto basic_json_parser_32; -basic_json_parser_44: +basic_json_parser_48: yych = *++m_cursor; if (yych <= ',') { if (yych == '+') { - goto basic_json_parser_51; + goto basic_json_parser_56; } goto basic_json_parser_32; } @@ -10285,7 +10368,7 @@ basic_json_parser_44: { if (yych <= '-') { - goto basic_json_parser_51; + goto basic_json_parser_56; } if (yych <= '/') { @@ -10293,32 +10376,32 @@ basic_json_parser_44: } if (yych <= '9') { - goto basic_json_parser_52; + goto basic_json_parser_57; } goto basic_json_parser_32; } -basic_json_parser_45: +basic_json_parser_49: yych = *++m_cursor; if (yych == 'l') { - goto basic_json_parser_54; + goto basic_json_parser_59; } goto basic_json_parser_32; -basic_json_parser_46: +basic_json_parser_50: yych = *++m_cursor; if (yych == 'l') { - goto basic_json_parser_55; + goto basic_json_parser_60; } goto basic_json_parser_32; -basic_json_parser_47: +basic_json_parser_51: yych = *++m_cursor; if (yych == 'u') { - goto basic_json_parser_56; + goto basic_json_parser_61; } goto basic_json_parser_32; -basic_json_parser_48: +basic_json_parser_52: ++m_cursor; if (m_limit <= m_cursor) { @@ -10333,7 +10416,7 @@ basic_json_parser_48: } if (yych <= '9') { - goto basic_json_parser_57; + goto basic_json_parser_62; } goto basic_json_parser_32; } @@ -10341,7 +10424,7 @@ basic_json_parser_48: { if (yych <= 'F') { - goto basic_json_parser_57; + goto basic_json_parser_62; } if (yych <= '`') { @@ -10349,12 +10432,12 @@ basic_json_parser_48: } if (yych <= 'f') { - goto basic_json_parser_57; + goto basic_json_parser_62; } goto basic_json_parser_32; } -basic_json_parser_49: - yyaccept = 1; +basic_json_parser_53: + yyaccept = 3; m_marker = ++m_cursor; if ((m_limit - m_cursor) < 3) { @@ -10365,27 +10448,30 @@ basic_json_parser_49: { if (yych <= '/') { - goto basic_json_parser_14; + goto basic_json_parser_55; } if (yych <= '9') { - goto basic_json_parser_49; + goto basic_json_parser_53; } - goto basic_json_parser_14; } else { if (yych <= 'E') { - goto basic_json_parser_44; + goto basic_json_parser_48; } if (yych == 'e') { - goto basic_json_parser_44; + goto basic_json_parser_48; } - goto basic_json_parser_14; } -basic_json_parser_51: +basic_json_parser_55: + { + last_token_type = token_type::value_float; + break; + } +basic_json_parser_56: yych = *++m_cursor; if (yych <= '/') { @@ -10395,7 +10481,7 @@ basic_json_parser_51: { goto basic_json_parser_32; } -basic_json_parser_52: +basic_json_parser_57: ++m_cursor; if (m_limit <= m_cursor) { @@ -10404,35 +10490,35 @@ basic_json_parser_52: yych = *m_cursor; if (yych <= '/') { - goto basic_json_parser_14; + goto basic_json_parser_55; } if (yych <= '9') { - goto basic_json_parser_52; + goto basic_json_parser_57; } - goto basic_json_parser_14; -basic_json_parser_54: + goto basic_json_parser_55; +basic_json_parser_59: yych = *++m_cursor; if (yych == 's') { - goto basic_json_parser_58; + goto basic_json_parser_63; } goto basic_json_parser_32; -basic_json_parser_55: +basic_json_parser_60: yych = *++m_cursor; if (yych == 'l') { - goto basic_json_parser_59; + goto basic_json_parser_64; } goto basic_json_parser_32; -basic_json_parser_56: +basic_json_parser_61: yych = *++m_cursor; if (yych == 'e') { - goto basic_json_parser_61; + goto basic_json_parser_66; } goto basic_json_parser_32; -basic_json_parser_57: +basic_json_parser_62: ++m_cursor; if (m_limit <= m_cursor) { @@ -10447,7 +10533,7 @@ basic_json_parser_57: } if (yych <= '9') { - goto basic_json_parser_63; + goto basic_json_parser_68; } goto basic_json_parser_32; } @@ -10455,7 +10541,7 @@ basic_json_parser_57: { if (yych <= 'F') { - goto basic_json_parser_63; + goto basic_json_parser_68; } if (yych <= '`') { @@ -10463,30 +10549,30 @@ basic_json_parser_57: } if (yych <= 'f') { - goto basic_json_parser_63; + goto basic_json_parser_68; } goto basic_json_parser_32; } -basic_json_parser_58: +basic_json_parser_63: yych = *++m_cursor; if (yych == 'e') { - goto basic_json_parser_64; + goto basic_json_parser_69; } goto basic_json_parser_32; -basic_json_parser_59: +basic_json_parser_64: ++m_cursor; { last_token_type = token_type::literal_null; break; } -basic_json_parser_61: +basic_json_parser_66: ++m_cursor; { last_token_type = token_type::literal_true; break; } -basic_json_parser_63: +basic_json_parser_68: ++m_cursor; if (m_limit <= m_cursor) { @@ -10501,7 +10587,7 @@ basic_json_parser_63: } if (yych <= '9') { - goto basic_json_parser_66; + goto basic_json_parser_71; } goto basic_json_parser_32; } @@ -10509,7 +10595,7 @@ basic_json_parser_63: { if (yych <= 'F') { - goto basic_json_parser_66; + goto basic_json_parser_71; } if (yych <= '`') { @@ -10517,17 +10603,17 @@ basic_json_parser_63: } if (yych <= 'f') { - goto basic_json_parser_66; + goto basic_json_parser_71; } goto basic_json_parser_32; } -basic_json_parser_64: +basic_json_parser_69: ++m_cursor; { last_token_type = token_type::literal_false; break; } -basic_json_parser_66: +basic_json_parser_71: ++m_cursor; if (m_limit <= m_cursor) { @@ -10867,42 +10953,6 @@ basic_json_parser_66: return parse(val, std::is_integral()); } - /*! - This is a helper to determine whether to parse the token into - floating-point or integral type. - - @note We wouldn't need it if we had separate token types for - integral and floating-point cases. - - @return true iff token matches `^[+-]\d+$` - */ - bool is_integral() const - { - const char* p = m_start; - - if (p == nullptr) - { - return false; // LCOV_EXCL_LINE - } - - if ((*p == '-') or (*p == '+')) - { - ++p; - } - - if (p == m_end) - { - return false; // LCOV_EXCL_LINE - } - - while ((p < m_end) and (*p >= '0') and (*p <= '9')) - { - ++p; - } - - return (p == m_end); - } - private: const char* const m_start = nullptr; const char* const m_end = nullptr; @@ -11011,7 +11061,7 @@ basic_json_parser_66: return (x == static_cast(value)) // x fits into destination T and (x < 0) == (value < 0) // preserved sign - and ((x != 0) or is_integral()) // strto[u]ll did nto fail + //and ((x != 0) or is_integral()) // strto[u]ll did nto fail and (errno == 0) // strto[u]ll did not overflow and (m_start < m_end) // token was not empty and (endptr == m_end); // parsed entire token exactly @@ -11035,46 +11085,56 @@ basic_json_parser_66: interpreted as a number @param[out] result @ref basic_json object to receive the number. + @param[in] token the type of the number token */ - void get_number(basic_json& result) const + void get_number(basic_json& result, const token_type token) const { assert(m_start != nullptr); assert(m_start < m_cursor); + assert((token == token_type::value_unsigned_integer) or + (token == token_type::value_signed_integer) or + (token == token_type::value_float)); strtonum num(reinterpret_cast(m_start), reinterpret_cast(m_cursor)); - const bool is_negative = (*m_start == '-'); - - result.m_type = value_t::discarded; - - if (not num.is_integral()) + switch (token) { - // will parse as float below - } - else if (is_negative) - { - number_integer_t val{0}; - if (num.to(val)) + case lexer::token_type::value_unsigned_integer: { - result.m_type = value_t::number_integer; - result.m_value = val; + number_unsigned_t val{0}; + if (num.to(val)) + { + result.m_type = value_t::number_unsigned; + result.m_value = val; + return; + } + break; } - } - else - { - number_unsigned_t val{0}; - if (num.to(val)) + + case lexer::token_type::value_signed_integer: { - result.m_type = value_t::number_unsigned; - result.m_value = val; + number_integer_t val{0}; + if (num.to(val)) + { + result.m_type = value_t::number_integer; + result.m_value = val; + return; + } + break; + } + + default: + { + break; } } number_float_t val{0}; - if (result.m_type != value_t::discarded or (not num.to(val))) + if (not num.to(val)) { - // already have a value from above or couldn't parse as float_t + // couldn't parse as float_t + result.m_type = value_t::discarded; return; } @@ -11330,9 +11390,11 @@ basic_json_parser_66: break; } - case lexer::token_type::value_number: + case lexer::token_type::value_unsigned_integer: + case lexer::token_type::value_signed_integer: + case lexer::token_type::value_float: { - m_lexer.get_number(result); + m_lexer.get_number(result, last_token); get_token(); break; } diff --git a/src/json.hpp.re2c b/src/json.hpp.re2c index b3f7af8d..51760eef 100644 --- a/src/json.hpp.re2c +++ b/src/json.hpp.re2c @@ -9444,7 +9444,9 @@ class basic_json literal_false, ///< the `false` literal literal_null, ///< the `null` literal value_string, ///< a string -- use get_string() for actual value - value_number, ///< a number -- use get_number() for actual value + value_unsigned_integer, ///< an unsigned integer -- use get_number() for actual value + value_signed_integer, ///< a signed integer -- use get_number() for actual value + value_float, ///< an floating point number -- use get_number() for actual value begin_array, ///< the character for array begin `[` begin_object, ///< the character for object begin `{` end_array, ///< the character for array end `]` @@ -9596,7 +9598,9 @@ class basic_json return "null literal"; case token_type::value_string: return "string literal"; - case token_type::value_number: + case lexer::token_type::value_unsigned_integer: + case lexer::token_type::value_signed_integer: + case lexer::token_type::value_float: return "number literal"; case token_type::begin_array: return "'['"; @@ -9684,18 +9688,22 @@ class basic_json "false" { last_token_type = token_type::literal_false; break; } // number - decimal_point = "."; - digit = [0-9]; - digit_1_9 = [1-9]; - e = "e" | "E"; - minus = "-"; - plus = "+"; - zero = "0"; - exp = e (minus | plus)? digit+; - frac = decimal_point digit+; - int = (zero | digit_1_9 digit*); - number = minus? int frac? exp?; - number { last_token_type = token_type::value_number; break; } + decimal_point = "."; + digit = [0-9]; + digit_1_9 = [1-9]; + e = "e" | "E"; + minus = "-"; + plus = "+"; + zero = "0"; + exp = e (minus | plus)? digit+; + frac = decimal_point digit+; + int = (zero | digit_1_9 digit*); + number_unsigned = int; + number_unsigned { last_token_type = token_type::value_unsigned_integer; break; } + number_signed = minus int; + number_signed { last_token_type = token_type::value_signed_integer; break; } + number_float = minus? int frac? exp?; + number_float { last_token_type = token_type::value_float; break; } // string quotation_mark = "\""; @@ -10017,42 +10025,6 @@ class basic_json return parse(val, std::is_integral()); } - /*! - This is a helper to determine whether to parse the token into - floating-point or integral type. - - @note We wouldn't need it if we had separate token types for - integral and floating-point cases. - - @return true iff token matches `^[+-]\d+$` - */ - bool is_integral() const - { - const char* p = m_start; - - if (p == nullptr) - { - return false; // LCOV_EXCL_LINE - } - - if ((*p == '-') or (*p == '+')) - { - ++p; - } - - if (p == m_end) - { - return false; // LCOV_EXCL_LINE - } - - while ((p < m_end) and (*p >= '0') and (*p <= '9')) - { - ++p; - } - - return (p == m_end); - } - private: const char* const m_start = nullptr; const char* const m_end = nullptr; @@ -10161,7 +10133,7 @@ class basic_json return (x == static_cast(value)) // x fits into destination T and (x < 0) == (value < 0) // preserved sign - and ((x != 0) or is_integral()) // strto[u]ll did nto fail + //and ((x != 0) or is_integral()) // strto[u]ll did nto fail and (errno == 0) // strto[u]ll did not overflow and (m_start < m_end) // token was not empty and (endptr == m_end); // parsed entire token exactly @@ -10185,46 +10157,56 @@ class basic_json interpreted as a number @param[out] result @ref basic_json object to receive the number. + @param[in] token the type of the number token */ - void get_number(basic_json& result) const + void get_number(basic_json& result, const token_type token) const { assert(m_start != nullptr); assert(m_start < m_cursor); + assert((token == token_type::value_unsigned_integer) or + (token == token_type::value_signed_integer) or + (token == token_type::value_float)); strtonum num(reinterpret_cast(m_start), reinterpret_cast(m_cursor)); - const bool is_negative = (*m_start == '-'); - - result.m_type = value_t::discarded; - - if (not num.is_integral()) + switch (token) { - // will parse as float below - } - else if (is_negative) - { - number_integer_t val{0}; - if (num.to(val)) + case lexer::token_type::value_unsigned_integer: { - result.m_type = value_t::number_integer; - result.m_value = val; + number_unsigned_t val{0}; + if (num.to(val)) + { + result.m_type = value_t::number_unsigned; + result.m_value = val; + return; + } + break; } - } - else - { - number_unsigned_t val{0}; - if (num.to(val)) + + case lexer::token_type::value_signed_integer: { - result.m_type = value_t::number_unsigned; - result.m_value = val; + number_integer_t val{0}; + if (num.to(val)) + { + result.m_type = value_t::number_integer; + result.m_value = val; + return; + } + break; + } + + default: + { + break; } } number_float_t val{0}; - if (result.m_type != value_t::discarded or (not num.to(val))) + if (not num.to(val)) { - // already have a value from above or couldn't parse as float_t + // couldn't parse as float_t + result.m_type = value_t::discarded; return; } @@ -10480,9 +10462,11 @@ class basic_json break; } - case lexer::token_type::value_number: + case lexer::token_type::value_unsigned_integer: + case lexer::token_type::value_signed_integer: + case lexer::token_type::value_float: { - m_lexer.get_number(result); + m_lexer.get_number(result, last_token); get_token(); break; } diff --git a/test/src/unit-class_lexer.cpp b/test/src/unit-class_lexer.cpp index ac43de8a..268f503a 100644 --- a/test/src/unit-class_lexer.cpp +++ b/test/src/unit-class_lexer.cpp @@ -65,25 +65,37 @@ TEST_CASE("lexer class") SECTION("numbers") { CHECK((json::lexer(reinterpret_cast("0"), - 1).scan() == json::lexer::token_type::value_number)); + 1).scan() == json::lexer::token_type::value_unsigned_integer)); CHECK((json::lexer(reinterpret_cast("1"), - 1).scan() == json::lexer::token_type::value_number)); + 1).scan() == json::lexer::token_type::value_unsigned_integer)); CHECK((json::lexer(reinterpret_cast("2"), - 1).scan() == json::lexer::token_type::value_number)); + 1).scan() == json::lexer::token_type::value_unsigned_integer)); CHECK((json::lexer(reinterpret_cast("3"), - 1).scan() == json::lexer::token_type::value_number)); + 1).scan() == json::lexer::token_type::value_unsigned_integer)); CHECK((json::lexer(reinterpret_cast("4"), - 1).scan() == json::lexer::token_type::value_number)); + 1).scan() == json::lexer::token_type::value_unsigned_integer)); CHECK((json::lexer(reinterpret_cast("5"), - 1).scan() == json::lexer::token_type::value_number)); + 1).scan() == json::lexer::token_type::value_unsigned_integer)); CHECK((json::lexer(reinterpret_cast("6"), - 1).scan() == json::lexer::token_type::value_number)); + 1).scan() == json::lexer::token_type::value_unsigned_integer)); CHECK((json::lexer(reinterpret_cast("7"), - 1).scan() == json::lexer::token_type::value_number)); + 1).scan() == json::lexer::token_type::value_unsigned_integer)); CHECK((json::lexer(reinterpret_cast("8"), - 1).scan() == json::lexer::token_type::value_number)); + 1).scan() == json::lexer::token_type::value_unsigned_integer)); CHECK((json::lexer(reinterpret_cast("9"), - 1).scan() == json::lexer::token_type::value_number)); + 1).scan() == json::lexer::token_type::value_unsigned_integer)); + + CHECK((json::lexer(reinterpret_cast("-0"), + 2).scan() == json::lexer::token_type::value_signed_integer)); + CHECK((json::lexer(reinterpret_cast("-1"), + 2).scan() == json::lexer::token_type::value_signed_integer)); + + CHECK((json::lexer(reinterpret_cast("1.1"), + 3).scan() == json::lexer::token_type::value_float)); + CHECK((json::lexer(reinterpret_cast("-1.1"), + 4).scan() == json::lexer::token_type::value_float)); + CHECK((json::lexer(reinterpret_cast("1E10"), + 4).scan() == json::lexer::token_type::value_float)); } SECTION("whitespace") @@ -109,7 +121,9 @@ TEST_CASE("lexer class") CHECK((json::lexer::token_type_name(json::lexer::token_type::literal_false) == "false literal")); CHECK((json::lexer::token_type_name(json::lexer::token_type::literal_null) == "null literal")); CHECK((json::lexer::token_type_name(json::lexer::token_type::value_string) == "string literal")); - CHECK((json::lexer::token_type_name(json::lexer::token_type::value_number) == "number literal")); + CHECK((json::lexer::token_type_name(json::lexer::token_type::value_unsigned_integer) == "number literal")); + CHECK((json::lexer::token_type_name(json::lexer::token_type::value_signed_integer) == "number literal")); + CHECK((json::lexer::token_type_name(json::lexer::token_type::value_float) == "number literal")); CHECK((json::lexer::token_type_name(json::lexer::token_type::begin_array) == "'['")); CHECK((json::lexer::token_type_name(json::lexer::token_type::begin_object) == "'{'")); CHECK((json::lexer::token_type_name(json::lexer::token_type::end_array) == "']'")); From c8191c81728a389cc8869935575eae9cca8117dd Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Sun, 12 Feb 2017 18:50:17 +0100 Subject: [PATCH 50/80] :hammer: further cleanup --- Makefile | 2 +- src/json.hpp | 42 +++++++++++++++++---------------- src/json.hpp.re2c | 44 ++++++++++++++++++----------------- test/src/unit-class_lexer.cpp | 28 +++++++++++----------- test/src/unit-regression.cpp | 2 +- 5 files changed, 61 insertions(+), 57 deletions(-) diff --git a/Makefile b/Makefile index 56cbdb0c..8bd7a2dd 100644 --- a/Makefile +++ b/Makefile @@ -94,7 +94,7 @@ cppcheck: # run clang sanitize (we are overrding the CXXFLAGS provided by travis in order to use gcc's libstdc++) clang_sanitize: clean - CXX=clang++ CXXFLAGS="-g -O2 -fsanitize=address -fsanitize=undefined -fno-omit-frame-pointer" $(MAKE) + CXX=clang++ CXXFLAGS="-g -O2 -fsanitize=address -fsanitize=undefined -fno-omit-frame-pointer" $(MAKE) check ########################################################################## diff --git a/src/json.hpp b/src/json.hpp index b8cdc480..873b8252 100644 --- a/src/json.hpp +++ b/src/json.hpp @@ -9444,8 +9444,8 @@ class basic_json literal_false, ///< the `false` literal literal_null, ///< the `null` literal value_string, ///< a string -- use get_string() for actual value - value_unsigned_integer, ///< an unsigned integer -- use get_number() for actual value - value_signed_integer, ///< a signed integer -- use get_number() for actual value + value_unsigned, ///< an unsigned integer -- use get_number() for actual value + value_integer, ///< a signed integer -- use get_number() for actual value value_float, ///< an floating point number -- use get_number() for actual value begin_array, ///< the character for array begin `[` begin_object, ///< the character for object begin `{` @@ -9598,8 +9598,8 @@ class basic_json return "null literal"; case token_type::value_string: return "string literal"; - case lexer::token_type::value_unsigned_integer: - case lexer::token_type::value_signed_integer: + case lexer::token_type::value_unsigned: + case lexer::token_type::value_integer: case lexer::token_type::value_float: return "number literal"; case token_type::begin_array: @@ -9903,7 +9903,7 @@ basic_json_parser_13: } basic_json_parser_14: { - last_token_type = token_type::value_unsigned_integer; + last_token_type = token_type::value_unsigned; break; } basic_json_parser_15: @@ -10301,7 +10301,7 @@ basic_json_parser_43: } basic_json_parser_44: { - last_token_type = token_type::value_signed_integer; + last_token_type = token_type::value_integer; break; } basic_json_parser_45: @@ -11091,19 +11091,19 @@ basic_json_parser_71: { assert(m_start != nullptr); assert(m_start < m_cursor); - assert((token == token_type::value_unsigned_integer) or - (token == token_type::value_signed_integer) or + assert((token == token_type::value_unsigned) or + (token == token_type::value_integer) or (token == token_type::value_float)); - strtonum num(reinterpret_cast(m_start), - reinterpret_cast(m_cursor)); + strtonum num_converter(reinterpret_cast(m_start), + reinterpret_cast(m_cursor)); switch (token) { - case lexer::token_type::value_unsigned_integer: + case lexer::token_type::value_unsigned: { - number_unsigned_t val{0}; - if (num.to(val)) + number_unsigned_t val; + if (num_converter.to(val)) { result.m_type = value_t::number_unsigned; result.m_value = val; @@ -11112,10 +11112,10 @@ basic_json_parser_71: break; } - case lexer::token_type::value_signed_integer: + case lexer::token_type::value_integer: { - number_integer_t val{0}; - if (num.to(val)) + number_integer_t val; + if (num_converter.to(val)) { result.m_type = value_t::number_integer; result.m_value = val; @@ -11130,8 +11130,10 @@ basic_json_parser_71: } } - number_float_t val{0}; - if (not num.to(val)) + // parse float (either explicitly or because a previous conversion + // failed) + number_float_t val; + if (not num_converter.to(val)) { // couldn't parse as float_t result.m_type = value_t::discarded; @@ -11390,8 +11392,8 @@ basic_json_parser_71: break; } - case lexer::token_type::value_unsigned_integer: - case lexer::token_type::value_signed_integer: + case lexer::token_type::value_unsigned: + case lexer::token_type::value_integer: case lexer::token_type::value_float: { m_lexer.get_number(result, last_token); diff --git a/src/json.hpp.re2c b/src/json.hpp.re2c index 51760eef..cf6ed432 100644 --- a/src/json.hpp.re2c +++ b/src/json.hpp.re2c @@ -9444,8 +9444,8 @@ class basic_json literal_false, ///< the `false` literal literal_null, ///< the `null` literal value_string, ///< a string -- use get_string() for actual value - value_unsigned_integer, ///< an unsigned integer -- use get_number() for actual value - value_signed_integer, ///< a signed integer -- use get_number() for actual value + value_unsigned, ///< an unsigned integer -- use get_number() for actual value + value_integer, ///< a signed integer -- use get_number() for actual value value_float, ///< an floating point number -- use get_number() for actual value begin_array, ///< the character for array begin `[` begin_object, ///< the character for object begin `{` @@ -9598,8 +9598,8 @@ class basic_json return "null literal"; case token_type::value_string: return "string literal"; - case lexer::token_type::value_unsigned_integer: - case lexer::token_type::value_signed_integer: + case lexer::token_type::value_unsigned: + case lexer::token_type::value_integer: case lexer::token_type::value_float: return "number literal"; case token_type::begin_array: @@ -9699,9 +9699,9 @@ class basic_json frac = decimal_point digit+; int = (zero | digit_1_9 digit*); number_unsigned = int; - number_unsigned { last_token_type = token_type::value_unsigned_integer; break; } - number_signed = minus int; - number_signed { last_token_type = token_type::value_signed_integer; break; } + number_unsigned { last_token_type = token_type::value_unsigned; break; } + number_integer = minus int; + number_integer { last_token_type = token_type::value_integer; break; } number_float = minus? int frac? exp?; number_float { last_token_type = token_type::value_float; break; } @@ -10163,19 +10163,19 @@ class basic_json { assert(m_start != nullptr); assert(m_start < m_cursor); - assert((token == token_type::value_unsigned_integer) or - (token == token_type::value_signed_integer) or + assert((token == token_type::value_unsigned) or + (token == token_type::value_integer) or (token == token_type::value_float)); - strtonum num(reinterpret_cast(m_start), - reinterpret_cast(m_cursor)); + strtonum num_converter(reinterpret_cast(m_start), + reinterpret_cast(m_cursor)); switch (token) { - case lexer::token_type::value_unsigned_integer: + case lexer::token_type::value_unsigned: { - number_unsigned_t val{0}; - if (num.to(val)) + number_unsigned_t val; + if (num_converter.to(val)) { result.m_type = value_t::number_unsigned; result.m_value = val; @@ -10184,10 +10184,10 @@ class basic_json break; } - case lexer::token_type::value_signed_integer: + case lexer::token_type::value_integer: { - number_integer_t val{0}; - if (num.to(val)) + number_integer_t val; + if (num_converter.to(val)) { result.m_type = value_t::number_integer; result.m_value = val; @@ -10202,8 +10202,10 @@ class basic_json } } - number_float_t val{0}; - if (not num.to(val)) + // parse float (either explicitly or because a previous conversion + // failed) + number_float_t val; + if (not num_converter.to(val)) { // couldn't parse as float_t result.m_type = value_t::discarded; @@ -10462,8 +10464,8 @@ class basic_json break; } - case lexer::token_type::value_unsigned_integer: - case lexer::token_type::value_signed_integer: + case lexer::token_type::value_unsigned: + case lexer::token_type::value_integer: case lexer::token_type::value_float: { m_lexer.get_number(result, last_token); diff --git a/test/src/unit-class_lexer.cpp b/test/src/unit-class_lexer.cpp index 268f503a..79dbb766 100644 --- a/test/src/unit-class_lexer.cpp +++ b/test/src/unit-class_lexer.cpp @@ -65,30 +65,30 @@ TEST_CASE("lexer class") SECTION("numbers") { CHECK((json::lexer(reinterpret_cast("0"), - 1).scan() == json::lexer::token_type::value_unsigned_integer)); + 1).scan() == json::lexer::token_type::value_unsigned)); CHECK((json::lexer(reinterpret_cast("1"), - 1).scan() == json::lexer::token_type::value_unsigned_integer)); + 1).scan() == json::lexer::token_type::value_unsigned)); CHECK((json::lexer(reinterpret_cast("2"), - 1).scan() == json::lexer::token_type::value_unsigned_integer)); + 1).scan() == json::lexer::token_type::value_unsigned)); CHECK((json::lexer(reinterpret_cast("3"), - 1).scan() == json::lexer::token_type::value_unsigned_integer)); + 1).scan() == json::lexer::token_type::value_unsigned)); CHECK((json::lexer(reinterpret_cast("4"), - 1).scan() == json::lexer::token_type::value_unsigned_integer)); + 1).scan() == json::lexer::token_type::value_unsigned)); CHECK((json::lexer(reinterpret_cast("5"), - 1).scan() == json::lexer::token_type::value_unsigned_integer)); + 1).scan() == json::lexer::token_type::value_unsigned)); CHECK((json::lexer(reinterpret_cast("6"), - 1).scan() == json::lexer::token_type::value_unsigned_integer)); + 1).scan() == json::lexer::token_type::value_unsigned)); CHECK((json::lexer(reinterpret_cast("7"), - 1).scan() == json::lexer::token_type::value_unsigned_integer)); + 1).scan() == json::lexer::token_type::value_unsigned)); CHECK((json::lexer(reinterpret_cast("8"), - 1).scan() == json::lexer::token_type::value_unsigned_integer)); + 1).scan() == json::lexer::token_type::value_unsigned)); CHECK((json::lexer(reinterpret_cast("9"), - 1).scan() == json::lexer::token_type::value_unsigned_integer)); + 1).scan() == json::lexer::token_type::value_unsigned)); CHECK((json::lexer(reinterpret_cast("-0"), - 2).scan() == json::lexer::token_type::value_signed_integer)); + 2).scan() == json::lexer::token_type::value_integer)); CHECK((json::lexer(reinterpret_cast("-1"), - 2).scan() == json::lexer::token_type::value_signed_integer)); + 2).scan() == json::lexer::token_type::value_integer)); CHECK((json::lexer(reinterpret_cast("1.1"), 3).scan() == json::lexer::token_type::value_float)); @@ -121,8 +121,8 @@ TEST_CASE("lexer class") CHECK((json::lexer::token_type_name(json::lexer::token_type::literal_false) == "false literal")); CHECK((json::lexer::token_type_name(json::lexer::token_type::literal_null) == "null literal")); CHECK((json::lexer::token_type_name(json::lexer::token_type::value_string) == "string literal")); - CHECK((json::lexer::token_type_name(json::lexer::token_type::value_unsigned_integer) == "number literal")); - CHECK((json::lexer::token_type_name(json::lexer::token_type::value_signed_integer) == "number literal")); + CHECK((json::lexer::token_type_name(json::lexer::token_type::value_unsigned) == "number literal")); + CHECK((json::lexer::token_type_name(json::lexer::token_type::value_integer) == "number literal")); CHECK((json::lexer::token_type_name(json::lexer::token_type::value_float) == "number literal")); CHECK((json::lexer::token_type_name(json::lexer::token_type::begin_array) == "'['")); CHECK((json::lexer::token_type_name(json::lexer::token_type::begin_object) == "'{'")); diff --git a/test/src/unit-regression.cpp b/test/src/unit-regression.cpp index 251c4cb8..dcfcf62b 100644 --- a/test/src/unit-regression.cpp +++ b/test/src/unit-regression.cpp @@ -417,7 +417,7 @@ TEST_CASE("regression tests") // disabled, because locale-specific beharivor is not // triggered in AppVeyor for some reason -#if 0 +#ifndef _MSC_VER { // verify that strtod now uses commas as decimal-separator CHECK(std::strtod("3,14", nullptr) == 3.14); From b84705d5577c8e44bbb9e3fde81886ade19fcb81 Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Sun, 12 Feb 2017 20:14:43 +0100 Subject: [PATCH 51/80] :white_check_mark: improved test coverage --- test/src/unit-class_parser.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/test/src/unit-class_parser.cpp b/test/src/unit-class_parser.cpp index 59ea3cef..caa672a1 100644 --- a/test/src/unit-class_parser.cpp +++ b/test/src/unit-class_parser.cpp @@ -101,6 +101,7 @@ TEST_CASE("parser class") CHECK_THROWS_WITH(json::parser("\"\b\"").parse(), "parse error - unexpected '\"'"); // improve code coverage CHECK_THROWS_AS(json::parser("\uFF01").parse(), std::invalid_argument); + CHECK_THROWS_AS(json::parser("[-4:1,]").parse(), std::invalid_argument); // unescaped control characters CHECK_THROWS_AS(json::parser("\"\x00\"").parse(), std::invalid_argument); CHECK_THROWS_AS(json::parser("\"\x01\"").parse(), std::invalid_argument); From 265c5b5207cec0327c9e4844a56bcecaaa1f9a8d Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Mon, 13 Feb 2017 18:51:23 +0100 Subject: [PATCH 52/80] :hammer: more work on the number parser --- src/json.hpp | 60 ++++++++++++++++++++++------------ src/json.hpp.re2c | 60 ++++++++++++++++++++++------------ test/src/unit-class_parser.cpp | 7 +++- 3 files changed, 84 insertions(+), 43 deletions(-) diff --git a/src/json.hpp b/src/json.hpp index 873b8252..bf9386b3 100644 --- a/src/json.hpp +++ b/src/json.hpp @@ -10957,6 +10957,8 @@ basic_json_parser_71: const char* const m_start = nullptr; const char* const m_end = nullptr; + // floating-point conversion + // overloaded wrappers for strtod/strtof/strtold // that will be called from parse static void strtof(float& f, const char* str, char** endptr) @@ -10984,6 +10986,9 @@ basic_json_parser_71: std::array buf; const size_t len = static_cast(m_end - m_start); + // lexer will reject empty numbers + assert(len > 0); + // since dealing with strtod family of functions, we're // getting the decimal point char from the C locale facilities // instead of C++'s numpunct facet of the current std::locale @@ -11023,10 +11028,9 @@ basic_json_parser_71: // this calls appropriate overload depending on T strtof(value, data, &endptr); - // note that reading past the end is OK, the data may be, for - // example, "123.", where the parsed token only contains - // "123", but strtod will read the dot as well. - const bool ok = (endptr >= (data + len)) and (len > 0); + // parsing was successful iff strtof parsed exactly the number + // of characters determined by the lexer (len) + const bool ok = (endptr == (data + len)); if (ok and (value == 0.0) and (*data == '-')) { @@ -11037,6 +11041,8 @@ basic_json_parser_71: return ok; } + // integral conversion + signed long long parse_integral(char** endptr, /*is_signed*/std::true_type) const { return std::strtoll(m_start, endptr, 10); @@ -11087,7 +11093,7 @@ basic_json_parser_71: @param[out] result @ref basic_json object to receive the number. @param[in] token the type of the number token */ - void get_number(basic_json& result, const token_type token) const + bool get_number(basic_json& result, const token_type token) const { assert(m_start != nullptr); assert(m_start < m_cursor); @@ -11105,9 +11111,10 @@ basic_json_parser_71: number_unsigned_t val; if (num_converter.to(val)) { + // parsing successful result.m_type = value_t::number_unsigned; result.m_value = val; - return; + return true; } break; } @@ -11117,9 +11124,10 @@ basic_json_parser_71: number_integer_t val; if (num_converter.to(val)) { + // parsing successful result.m_type = value_t::number_integer; result.m_value = val; - return; + return true; } break; } @@ -11133,22 +11141,24 @@ basic_json_parser_71: // parse float (either explicitly or because a previous conversion // failed) number_float_t val; - if (not num_converter.to(val)) + if (num_converter.to(val)) { - // couldn't parse as float_t - result.m_type = value_t::discarded; - return; + // parsing successful + result.m_type = value_t::number_float; + result.m_value = val; + + // replace infinity and NAN by null + if (not std::isfinite(result.m_value.number_float)) + { + result.m_type = value_t::null; + result.m_value = basic_json::json_value(); + } + + return true; } - result.m_type = value_t::number_float; - result.m_value = val; - - // replace infinity and NAN by null - if (not std::isfinite(result.m_value.number_float)) - { - result.m_type = value_t::null; - result.m_value = basic_json::json_value(); - } + // couldn't parse number in any format + return false; } private: @@ -11396,8 +11406,16 @@ basic_json_parser_71: case lexer::token_type::value_integer: case lexer::token_type::value_float: { - m_lexer.get_number(result, last_token); + const bool ok = m_lexer.get_number(result, last_token); get_token(); + + // if number conversion was unsuccessful, then is is + // because the number was directly followed by an + // unexpected character (e.g. "01" where "1" is unexpected) + if (not ok) + { + unexpect(last_token); + } break; } diff --git a/src/json.hpp.re2c b/src/json.hpp.re2c index cf6ed432..e15f7b1f 100644 --- a/src/json.hpp.re2c +++ b/src/json.hpp.re2c @@ -10029,6 +10029,8 @@ class basic_json const char* const m_start = nullptr; const char* const m_end = nullptr; + // floating-point conversion + // overloaded wrappers for strtod/strtof/strtold // that will be called from parse static void strtof(float& f, const char* str, char** endptr) @@ -10056,6 +10058,9 @@ class basic_json std::array buf; const size_t len = static_cast(m_end - m_start); + // lexer will reject empty numbers + assert(len > 0); + // since dealing with strtod family of functions, we're // getting the decimal point char from the C locale facilities // instead of C++'s numpunct facet of the current std::locale @@ -10095,10 +10100,9 @@ class basic_json // this calls appropriate overload depending on T strtof(value, data, &endptr); - // note that reading past the end is OK, the data may be, for - // example, "123.", where the parsed token only contains - // "123", but strtod will read the dot as well. - const bool ok = (endptr >= (data + len)) and (len > 0); + // parsing was successful iff strtof parsed exactly the number + // of characters determined by the lexer (len) + const bool ok = (endptr == (data + len)); if (ok and (value == 0.0) and (*data == '-')) { @@ -10109,6 +10113,8 @@ class basic_json return ok; } + // integral conversion + signed long long parse_integral(char** endptr, /*is_signed*/std::true_type) const { return std::strtoll(m_start, endptr, 10); @@ -10159,7 +10165,7 @@ class basic_json @param[out] result @ref basic_json object to receive the number. @param[in] token the type of the number token */ - void get_number(basic_json& result, const token_type token) const + bool get_number(basic_json& result, const token_type token) const { assert(m_start != nullptr); assert(m_start < m_cursor); @@ -10177,9 +10183,10 @@ class basic_json number_unsigned_t val; if (num_converter.to(val)) { + // parsing successful result.m_type = value_t::number_unsigned; result.m_value = val; - return; + return true; } break; } @@ -10189,9 +10196,10 @@ class basic_json number_integer_t val; if (num_converter.to(val)) { + // parsing successful result.m_type = value_t::number_integer; result.m_value = val; - return; + return true; } break; } @@ -10205,22 +10213,24 @@ class basic_json // parse float (either explicitly or because a previous conversion // failed) number_float_t val; - if (not num_converter.to(val)) + if (num_converter.to(val)) { - // couldn't parse as float_t - result.m_type = value_t::discarded; - return; + // parsing successful + result.m_type = value_t::number_float; + result.m_value = val; + + // replace infinity and NAN by null + if (not std::isfinite(result.m_value.number_float)) + { + result.m_type = value_t::null; + result.m_value = basic_json::json_value(); + } + + return true; } - result.m_type = value_t::number_float; - result.m_value = val; - - // replace infinity and NAN by null - if (not std::isfinite(result.m_value.number_float)) - { - result.m_type = value_t::null; - result.m_value = basic_json::json_value(); - } + // couldn't parse number in any format + return false; } private: @@ -10468,8 +10478,16 @@ class basic_json case lexer::token_type::value_integer: case lexer::token_type::value_float: { - m_lexer.get_number(result, last_token); + const bool ok = m_lexer.get_number(result, last_token); get_token(); + + // if number conversion was unsuccessful, then is is + // because the number was directly followed by an + // unexpected character (e.g. "01" where "1" is unexpected) + if (not ok) + { + unexpect(last_token); + } break; } diff --git a/test/src/unit-class_parser.cpp b/test/src/unit-class_parser.cpp index caa672a1..2fb0da2b 100644 --- a/test/src/unit-class_parser.cpp +++ b/test/src/unit-class_parser.cpp @@ -270,6 +270,11 @@ TEST_CASE("parser class") } } + SECTION("overflow") + { + CHECK(json::parser("1.18973e+4932").parse() == json()); + } + SECTION("invalid numbers") { CHECK_THROWS_AS(json::parser("01").parse(), std::invalid_argument); @@ -294,7 +299,7 @@ TEST_CASE("parser class") CHECK_THROWS_AS(json::parser("+0").parse(), std::invalid_argument); CHECK_THROWS_WITH(json::parser("01").parse(), - "parse error - unexpected number literal; expected end of input"); + "parse error - unexpected number literal"); CHECK_THROWS_WITH(json::parser("--1").parse(), "parse error - unexpected '-'"); CHECK_THROWS_WITH(json::parser("1.").parse(), "parse error - unexpected '.'; expected end of input"); From c95ff863bfcd08325ad3d8e6023b1264b070fdca Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Mon, 13 Feb 2017 18:55:11 +0100 Subject: [PATCH 53/80] :arrow_up: updated Catch to v1.7.2 --- test/thirdparty/catch/catch.hpp | 22073 +++++++++++++++--------------- 1 file changed, 11069 insertions(+), 11004 deletions(-) diff --git a/test/thirdparty/catch/catch.hpp b/test/thirdparty/catch/catch.hpp index c1ef3ed6..2a09fd19 100644 --- a/test/thirdparty/catch/catch.hpp +++ b/test/thirdparty/catch/catch.hpp @@ -1,11004 +1,11069 @@ -/* - * Catch v1.7.0 - * Generated: 2017-02-01 21:32:13.239291 - * ---------------------------------------------------------- - * This file has been merged from multiple headers. Please don't edit it directly - * Copyright (c) 2012 Two Blue Cubes Ltd. All rights reserved. - * - * Distributed under the Boost Software License, Version 1.0. (See accompanying - * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) - */ -#ifndef TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED -#define TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED - -#define TWOBLUECUBES_CATCH_HPP_INCLUDED - -#ifdef __clang__ -# pragma clang system_header -#elif defined __GNUC__ -# pragma GCC system_header -#endif - -// #included from: internal/catch_suppress_warnings.h - -#ifdef __clang__ -# ifdef __ICC // icpc defines the __clang__ macro -# pragma warning(push) -# pragma warning(disable: 161 1682) -# else // __ICC -# pragma clang diagnostic ignored "-Wglobal-constructors" -# pragma clang diagnostic ignored "-Wvariadic-macros" -# pragma clang diagnostic ignored "-Wc99-extensions" -# pragma clang diagnostic ignored "-Wunused-variable" -# pragma clang diagnostic push -# pragma clang diagnostic ignored "-Wpadded" -# pragma clang diagnostic ignored "-Wc++98-compat" -# pragma clang diagnostic ignored "-Wc++98-compat-pedantic" -# pragma clang diagnostic ignored "-Wswitch-enum" -# pragma clang diagnostic ignored "-Wcovered-switch-default" -# endif -#elif defined __GNUC__ -# pragma GCC diagnostic ignored "-Wvariadic-macros" -# pragma GCC diagnostic ignored "-Wunused-variable" -# pragma GCC diagnostic push -# pragma GCC diagnostic ignored "-Wpadded" -#endif -#if defined(CATCH_CONFIG_MAIN) || defined(CATCH_CONFIG_RUNNER) -# define CATCH_IMPL -#endif - -#ifdef CATCH_IMPL -# ifndef CLARA_CONFIG_MAIN -# define CLARA_CONFIG_MAIN_NOT_DEFINED -# define CLARA_CONFIG_MAIN -# endif -#endif - -// #included from: internal/catch_notimplemented_exception.h -#define TWOBLUECUBES_CATCH_NOTIMPLEMENTED_EXCEPTION_H_INCLUDED - -// #included from: catch_common.h -#define TWOBLUECUBES_CATCH_COMMON_H_INCLUDED - -// #included from: catch_compiler_capabilities.h -#define TWOBLUECUBES_CATCH_COMPILER_CAPABILITIES_HPP_INCLUDED - -// Detect a number of compiler features - mostly C++11/14 conformance - by compiler -// The following features are defined: -// -// CATCH_CONFIG_CPP11_NULLPTR : is nullptr supported? -// CATCH_CONFIG_CPP11_NOEXCEPT : is noexcept supported? -// CATCH_CONFIG_CPP11_GENERATED_METHODS : The delete and default keywords for compiler generated methods -// CATCH_CONFIG_CPP11_IS_ENUM : std::is_enum is supported? -// CATCH_CONFIG_CPP11_TUPLE : std::tuple is supported -// CATCH_CONFIG_CPP11_LONG_LONG : is long long supported? -// CATCH_CONFIG_CPP11_OVERRIDE : is override supported? -// CATCH_CONFIG_CPP11_UNIQUE_PTR : is unique_ptr supported (otherwise use auto_ptr) -// CATCH_CONFIG_CPP11_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? -// **************** -// Note to maintainers: if new toggles are added please document them -// in configuration.md, too -// **************** - -// In general each macro has a _NO_ form -// (e.g. CATCH_CONFIG_CPP11_NO_NULLPTR) which disables the feature. -// Many features, at point of detection, define an _INTERNAL_ macro, so they -// can be combined, en-mass, with the _NO_ forms later. - -// All the C++11 features can be disabled with CATCH_CONFIG_NO_CPP11 - -#ifdef __cplusplus - -# if __cplusplus >= 201103L -# define CATCH_CPP11_OR_GREATER -# endif - -# if __cplusplus >= 201402L -# define CATCH_CPP14_OR_GREATER -# endif - -#endif - -#ifdef __clang__ - -# if __has_feature(cxx_nullptr) -# define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR -# endif - -# if __has_feature(cxx_noexcept) -# define CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT -# endif - -# if defined(CATCH_CPP11_OR_GREATER) -# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS _Pragma( "clang diagnostic ignored \"-Wparentheses\"" ) -# endif - -#endif // __clang__ - -//////////////////////////////////////////////////////////////////////////////// -// Borland -#ifdef __BORLANDC__ - -#endif // __BORLANDC__ - -//////////////////////////////////////////////////////////////////////////////// -// EDG -#ifdef __EDG_VERSION__ - -#endif // __EDG_VERSION__ - -//////////////////////////////////////////////////////////////////////////////// -// Digital Mars -#ifdef __DMC__ - -#endif // __DMC__ - -//////////////////////////////////////////////////////////////////////////////// -// GCC -#ifdef __GNUC__ - -# if __GNUC__ == 4 && __GNUC_MINOR__ >= 6 && defined(__GXX_EXPERIMENTAL_CXX0X__) -# define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR -# endif - -# if !defined(CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS) && defined(CATCH_CPP11_OR_GREATER) -# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS _Pragma( "GCC diagnostic ignored \"-Wparentheses\"" ) -# endif - -// - otherwise more recent versions define __cplusplus >= 201103L -// and will get picked up below - -#endif // __GNUC__ - -//////////////////////////////////////////////////////////////////////////////// -// Visual C++ -#ifdef _MSC_VER - -#if (_MSC_VER >= 1600) -# define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR -# define CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR -#endif - -#if (_MSC_VER >= 1900 ) // (VC++ 13 (VS2015)) -#define CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT -#define CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS -#define CATCH_INTERNAL_CONFIG_CPP11_SHUFFLE -#define CATCH_INTERNAL_CONFIG_CPP11_TYPE_TRAITS -#endif - -#endif // _MSC_VER - -//////////////////////////////////////////////////////////////////////////////// - -// Use variadic macros if the compiler supports them -#if ( defined _MSC_VER && _MSC_VER > 1400 && !defined __EDGE__) || \ - ( defined __WAVE__ && __WAVE_HAS_VARIADICS ) || \ - ( defined __GNUC__ && __GNUC__ >= 3 ) || \ - ( !defined __cplusplus && __STDC_VERSION__ >= 199901L || __cplusplus >= 201103L ) - -#define CATCH_INTERNAL_CONFIG_VARIADIC_MACROS - -#endif - -// Use __COUNTER__ if the compiler supports it -#if ( defined _MSC_VER && _MSC_VER >= 1300 ) || \ - ( defined __GNUC__ && __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_SUPPRESS_PARENTHESES_WARNINGS) -# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS -#endif - -// noexcept support: -#if defined(CATCH_CONFIG_CPP11_NOEXCEPT) && !defined(CATCH_NOEXCEPT) -# define CATCH_NOEXCEPT noexcept -# define CATCH_NOEXCEPT_IS(x) noexcept(x) -#else -# define CATCH_NOEXCEPT throw() -# define CATCH_NOEXCEPT_IS(x) -#endif - -// nullptr support -#ifdef CATCH_CONFIG_CPP11_NULLPTR -# define CATCH_NULL nullptr -#else -# define CATCH_NULL NULL -#endif - -// override support -#ifdef CATCH_CONFIG_CPP11_OVERRIDE -# define CATCH_OVERRIDE override -#else -# define CATCH_OVERRIDE -#endif - -// unique_ptr support -#ifdef CATCH_CONFIG_CPP11_UNIQUE_PTR -# define CATCH_AUTO_PTR( T ) std::unique_ptr -#else -# define CATCH_AUTO_PTR( T ) std::auto_ptr -#endif - -#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 -# define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __COUNTER__ ) -#else -# 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 - -namespace Catch { - - struct IConfig; - - struct CaseSensitive { enum Choice { - Yes, - No - }; }; - - class NonCopyable { -#ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS - NonCopyable( NonCopyable const& ) = delete; - NonCopyable( NonCopyable && ) = delete; - NonCopyable& operator = ( NonCopyable const& ) = delete; - NonCopyable& operator = ( NonCopyable && ) = delete; -#else - NonCopyable( NonCopyable const& info ); - NonCopyable& operator = ( NonCopyable const& ); -#endif - - protected: - NonCopyable() {} - virtual ~NonCopyable(); - }; - - class SafeBool { - public: - typedef void (SafeBool::*type)() const; - - static type makeSafe( bool value ) { - return value ? &SafeBool::trueValue : 0; - } - private: - void trueValue() const {} - }; - - template - inline void deleteAll( ContainerT& container ) { - typename ContainerT::const_iterator it = container.begin(); - typename ContainerT::const_iterator itEnd = container.end(); - for(; it != itEnd; ++it ) - delete *it; - } - template - inline void deleteAllValues( AssociativeContainerT& container ) { - typename AssociativeContainerT::const_iterator it = container.begin(); - typename AssociativeContainerT::const_iterator itEnd = container.end(); - for(; it != itEnd; ++it ) - delete it->second; - } - - 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 ); - 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( 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; - - char const* file; - std::size_t line; - }; - - std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info ); - - // This is just here to avoid compiler warnings with macro constants and boolean literals - inline bool isTrue( bool value ){ return value; } - inline bool alwaysTrue() { return true; } - inline bool alwaysFalse() { return false; } - - void throwLogicError( std::string const& message, SourceLineInfo const& locationInfo ); - - void seedRng( IConfig const& config ); - unsigned int rngSeed(); - - // Use this in variadic streaming macros to allow - // >> +StreamEndStop - // as well as - // >> stuff +StreamEndStop - struct StreamEndStop { - std::string operator+() { - return std::string(); - } - }; - template - T const& operator + ( T const& value, StreamEndStop ) { - return value; - } -} - -#define CATCH_INTERNAL_LINEINFO ::Catch::SourceLineInfo( __FILE__, static_cast( __LINE__ ) ) -#define CATCH_INTERNAL_ERROR( msg ) ::Catch::throwLogicError( msg, CATCH_INTERNAL_LINEINFO ); - -#include - -namespace Catch { - - class NotImplementedException : public std::exception - { - public: - NotImplementedException( SourceLineInfo const& lineInfo ); - NotImplementedException( NotImplementedException const& ) {} - - virtual ~NotImplementedException() CATCH_NOEXCEPT {} - - virtual const char* what() const CATCH_NOEXCEPT; - - private: - std::string m_what; - SourceLineInfo m_lineInfo; - }; - -} // end namespace Catch - -/////////////////////////////////////////////////////////////////////////////// -#define CATCH_NOT_IMPLEMENTED throw Catch::NotImplementedException( CATCH_INTERNAL_LINEINFO ) - -// #included from: internal/catch_context.h -#define TWOBLUECUBES_CATCH_CONTEXT_H_INCLUDED - -// #included from: catch_interfaces_generators.h -#define TWOBLUECUBES_CATCH_INTERFACES_GENERATORS_H_INCLUDED - -#include - -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 - -#include -#include -#include - -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 - -namespace Catch { - - class TestSpec; - - struct ITestCase : IShared { - virtual void invoke () const = 0; - protected: - virtual ~ITestCase(); - }; - - class TestCase; - struct IConfig; - - struct ITestCaseRegistry { - virtual ~ITestCaseRegistry(); - virtual std::vector const& getAllTests() const = 0; - virtual std::vector const& getAllTestsSorted( IConfig const& config ) const = 0; - }; - - bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config ); - std::vector filterTests( std::vector const& testCases, TestSpec const& testSpec, IConfig const& config ); - std::vector const& getAllTestCasesSorted( IConfig const& config ); - -} - -namespace Catch { - -template -class MethodTestCase : public SharedImpl { - -public: - MethodTestCase( void (C::*method)() ) : m_method( method ) {} - - virtual void invoke() const { - C obj; - (obj.*m_method)(); - } - -private: - virtual ~MethodTestCase() {} - - void (C::*m_method)(); -}; - -typedef void(*TestFunction)(); - -struct NameAndDesc { - NameAndDesc( const char* _name = "", const char* _description= "" ) - : name( _name ), description( _description ) - {} - - const char* name; - const char* description; -}; - -void registerTestCase - ( ITestCase* testCase, - char const* className, - NameAndDesc const& nameAndDesc, - SourceLineInfo const& lineInfo ); - -struct AutoReg { - - AutoReg - ( TestFunction function, - SourceLineInfo const& lineInfo, - NameAndDesc const& nameAndDesc ); - - template - 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 - -#ifdef CATCH_CONFIG_VARIADIC_MACROS - /////////////////////////////////////////////////////////////////////////////// - #define INTERNAL_CATCH_TESTCASE2( TestName, ... ) \ - static void TestName(); \ - namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &TestName, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( __VA_ARGS__ ) ); }\ - 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, ... ) \ - namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &QualifiedMethod, "&" #QualifiedMethod, Catch::NameAndDesc( __VA_ARGS__ ), CATCH_INTERNAL_LINEINFO ); } - - /////////////////////////////////////////////////////////////////////////////// - #define INTERNAL_CATCH_TEST_CASE_METHOD2( TestName, ClassName, ... )\ - namespace{ \ - struct TestName : ClassName{ \ - void test(); \ - }; \ - Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( &TestName::test, #ClassName, Catch::NameAndDesc( __VA_ARGS__ ), CATCH_INTERNAL_LINEINFO ); \ - } \ - 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::AutoReg( Function, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( __VA_ARGS__ ) ); - -#else - /////////////////////////////////////////////////////////////////////////////// - #define INTERNAL_CATCH_TESTCASE2( TestName, Name, Desc ) \ - static void TestName(); \ - namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &TestName, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( Name, Desc ) ); }\ - 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 ) - - /////////////////////////////////////////////////////////////////////////////// - #define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, Name, Desc ) \ - namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &QualifiedMethod, "&" #QualifiedMethod, Catch::NameAndDesc( Name, Desc ), CATCH_INTERNAL_LINEINFO ); } - - /////////////////////////////////////////////////////////////////////////////// - #define INTERNAL_CATCH_TEST_CASE_METHOD2( TestCaseName, ClassName, TestName, Desc )\ - namespace{ \ - struct TestCaseName : ClassName{ \ - void test(); \ - }; \ - Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( &TestCaseName::test, #ClassName, Catch::NameAndDesc( TestName, Desc ), CATCH_INTERNAL_LINEINFO ); \ - } \ - 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 ) - - /////////////////////////////////////////////////////////////////////////////// - #define INTERNAL_CATCH_REGISTER_TESTCASE( Function, Name, Desc ) \ - Catch::AutoReg( Function, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( Name, Desc ) ); -#endif - -// #included from: internal/catch_capture.hpp -#define TWOBLUECUBES_CATCH_CAPTURE_HPP_INCLUDED - -// #included from: catch_result_builder.h -#define TWOBLUECUBES_CATCH_RESULT_BUILDER_H_INCLUDED - -// #included from: catch_result_type.h -#define TWOBLUECUBES_CATCH_RESULT_TYPE_H_INCLUDED - -namespace Catch { - - // ResultWas::OfType enum - struct ResultWas { enum OfType { - Unknown = -1, - Ok = 0, - Info = 1, - Warning = 2, - - FailureBit = 0x10, - - ExpressionFailed = FailureBit | 1, - ExplicitFailure = FailureBit | 2, - - Exception = 0x100 | FailureBit, - - ThrewException = Exception | 1, - DidntThrowException = Exception | 2, - - FatalErrorCondition = 0x200 | FailureBit - - }; }; - - inline bool isOk( ResultWas::OfType resultType ) { - return ( resultType & ResultWas::FailureBit ) == 0; - } - inline bool isJustInfo( int flags ) { - return flags == ResultWas::Info; - } - - // ResultDisposition::Flags enum - struct ResultDisposition { enum Flags { - Normal = 0x01, - - ContinueOnFailure = 0x02, // Failures fail test, but execution continues - FalseTest = 0x04, // Prefix expression with ! - SuppressFail = 0x08 // Failures are reported but do not fail the test - }; }; - - inline ResultDisposition::Flags operator | ( ResultDisposition::Flags lhs, ResultDisposition::Flags rhs ) { - return static_cast( 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& ); - }; - - struct AssertionInfo - { - AssertionInfo() {} - AssertionInfo( std::string const& _macroName, - SourceLineInfo const& _lineInfo, - std::string const& _capturedExpression, - ResultDisposition::Flags _resultDisposition ); - - std::string macroName; - SourceLineInfo lineInfo; - std::string capturedExpression; - ResultDisposition::Flags resultDisposition; - }; - - struct AssertionResultData - { - AssertionResultData() : 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 { - - namespace Generic { - template class AllOf; - template class AnyOf; - template class Not; - } - - template - struct Matcher : SharedImpl - { - typedef ExpressionT ExpressionType; - - virtual ~Matcher() {} - virtual Ptr clone() const = 0; - virtual bool match( ExpressionT const& expr ) const = 0; - virtual std::string toString() const = 0; - - Generic::AllOf operator && ( Matcher const& other ) const; - Generic::AnyOf operator || ( Matcher const& other ) const; - Generic::Not operator ! () const; - }; - - template - struct MatcherImpl : Matcher { - - virtual Ptr > clone() const { - return Ptr >( new DerivedT( static_cast( *this ) ) ); - } - }; - - namespace Generic { - template - class Not : public MatcherImpl, ExpressionT> { - public: - explicit Not( Matcher const& matcher ) : m_matcher(matcher.clone()) {} - Not( Not const& other ) : m_matcher( other.m_matcher ) {} - - virtual bool match( ExpressionT const& expr ) const CATCH_OVERRIDE { - return !m_matcher->match( expr ); - } - - virtual std::string toString() const CATCH_OVERRIDE { - return "not " + m_matcher->toString(); - } - private: - Ptr< Matcher > m_matcher; - }; - - template - class AllOf : public MatcherImpl, ExpressionT> { - public: - - AllOf() {} - AllOf( AllOf const& other ) : m_matchers( other.m_matchers ) {} - - AllOf& add( Matcher const& matcher ) { - m_matchers.push_back( matcher.clone() ); - return *this; - } - virtual bool match( ExpressionT const& expr ) const - { - for( std::size_t i = 0; i < m_matchers.size(); ++i ) - if( !m_matchers[i]->match( expr ) ) - return false; - return true; - } - virtual std::string toString() const { - std::ostringstream oss; - oss << "( "; - for( std::size_t i = 0; i < m_matchers.size(); ++i ) { - if( i != 0 ) - oss << " and "; - oss << m_matchers[i]->toString(); - } - oss << " )"; - return oss.str(); - } - - AllOf operator && ( Matcher const& other ) const { - AllOf allOfExpr( *this ); - allOfExpr.add( other ); - return allOfExpr; - } - - private: - std::vector > > m_matchers; - }; - - template - class AnyOf : public MatcherImpl, ExpressionT> { - public: - - AnyOf() {} - AnyOf( AnyOf const& other ) : m_matchers( other.m_matchers ) {} - - AnyOf& add( Matcher const& matcher ) { - m_matchers.push_back( matcher.clone() ); - return *this; - } - virtual bool match( ExpressionT const& expr ) const - { - for( std::size_t i = 0; i < m_matchers.size(); ++i ) - if( m_matchers[i]->match( expr ) ) - return true; - return false; - } - virtual std::string toString() const { - std::ostringstream oss; - oss << "( "; - for( std::size_t i = 0; i < m_matchers.size(); ++i ) { - if( i != 0 ) - oss << " or "; - oss << m_matchers[i]->toString(); - } - oss << " )"; - return oss.str(); - } - - AnyOf operator || ( Matcher const& other ) const { - AnyOf anyOfExpr( *this ); - anyOfExpr.add( other ); - return anyOfExpr; - } - - private: - std::vector > > m_matchers; - }; - - } // namespace Generic - - template - Generic::AllOf Matcher::operator && ( Matcher const& other ) const { - Generic::AllOf allOfExpr; - allOfExpr.add( *this ); - allOfExpr.add( other ); - return allOfExpr; - } - - template - Generic::AnyOf Matcher::operator || ( Matcher const& other ) const { - Generic::AnyOf anyOfExpr; - anyOfExpr.add( *this ); - anyOfExpr.add( other ); - return anyOfExpr; - } - - template - Generic::Not Matcher::operator ! () const { - return Generic::Not( *this ); - } - - namespace StdString { - - inline std::string makeString( std::string const& str ) { return str; } - inline std::string makeString( const char* str ) { return str ? std::string( str ) : std::string(); } - - struct CasedString - { - CasedString( std::string const& str, CaseSensitive::Choice caseSensitivity ) - : m_caseSensitivity( caseSensitivity ), - m_str( adjustString( str ) ) - {} - std::string adjustString( std::string const& str ) const { - return m_caseSensitivity == CaseSensitive::No - ? toLower( str ) - : str; - - } - std::string toStringSuffix() const - { - return m_caseSensitivity == CaseSensitive::No - ? " (case insensitive)" - : std::string(); - } - CaseSensitive::Choice m_caseSensitivity; - std::string m_str; - }; - - struct Equals : MatcherImpl { - Equals( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) - : m_data( str, caseSensitivity ) - {} - Equals( Equals const& other ) : m_data( other.m_data ){} - - virtual ~Equals(); - - virtual bool match( std::string const& expr ) const { - return m_data.m_str == m_data.adjustString( expr );; - } - virtual std::string toString() const { - return "equals: \"" + m_data.m_str + '"' + m_data.toStringSuffix(); - } - - CasedString m_data; - }; - - struct Contains : MatcherImpl { - Contains( std::string const& substr, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) - : m_data( substr, caseSensitivity ){} - Contains( Contains const& other ) : m_data( other.m_data ){} - - virtual ~Contains(); - - virtual bool match( std::string const& expr ) const { - return m_data.adjustString( expr ).find( m_data.m_str ) != std::string::npos; - } - virtual std::string toString() const { - return "contains: \"" + m_data.m_str + '"' + m_data.toStringSuffix(); - } - - CasedString m_data; - }; - - struct StartsWith : MatcherImpl { - StartsWith( std::string const& substr, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) - : m_data( substr, caseSensitivity ){} - - StartsWith( StartsWith const& other ) : m_data( other.m_data ){} - - virtual ~StartsWith(); - - virtual bool match( std::string const& expr ) const { - return startsWith( m_data.adjustString( expr ), m_data.m_str ); - } - virtual std::string toString() const { - return "starts with: \"" + m_data.m_str + '"' + m_data.toStringSuffix(); - } - - CasedString m_data; - }; - - struct EndsWith : MatcherImpl { - EndsWith( std::string const& substr, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) - : m_data( substr, caseSensitivity ){} - EndsWith( EndsWith const& other ) : m_data( other.m_data ){} - - virtual ~EndsWith(); - - virtual bool match( std::string const& expr ) const { - return endsWith( m_data.adjustString( expr ), m_data.m_str ); - } - virtual std::string toString() const { - return "ends with: \"" + m_data.m_str + '"' + m_data.toStringSuffix(); - } - - CasedString m_data; - }; - } // namespace StdString - } // namespace Impl - - // The following functions create the actual matcher objects. - // This allows the types to be inferred - template - inline Impl::Generic::Not Not( Impl::Matcher const& m ) { - return Impl::Generic::Not( m ); - } - - template - inline Impl::Generic::AllOf AllOf( Impl::Matcher const& m1, - Impl::Matcher const& m2 ) { - return Impl::Generic::AllOf().add( m1 ).add( m2 ); - } - template - inline Impl::Generic::AllOf AllOf( Impl::Matcher const& m1, - Impl::Matcher const& m2, - Impl::Matcher const& m3 ) { - return Impl::Generic::AllOf().add( m1 ).add( m2 ).add( m3 ); - } - template - inline Impl::Generic::AnyOf AnyOf( Impl::Matcher const& m1, - Impl::Matcher const& m2 ) { - return Impl::Generic::AnyOf().add( m1 ).add( m2 ); - } - template - inline Impl::Generic::AnyOf AnyOf( Impl::Matcher const& m1, - Impl::Matcher const& m2, - Impl::Matcher const& m3 ) { - return Impl::Generic::AnyOf().add( m1 ).add( m2 ).add( m3 ); - } - - inline Impl::StdString::Equals Equals( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) { - return Impl::StdString::Equals( str, caseSensitivity ); - } - inline Impl::StdString::Equals Equals( const char* str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) { - return Impl::StdString::Equals( Impl::StdString::makeString( str ), caseSensitivity ); - } - inline Impl::StdString::Contains Contains( std::string const& substr, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) { - return Impl::StdString::Contains( substr, caseSensitivity ); - } - inline Impl::StdString::Contains Contains( const char* substr, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) { - return Impl::StdString::Contains( Impl::StdString::makeString( substr ), caseSensitivity ); - } - inline Impl::StdString::StartsWith StartsWith( std::string const& substr ) { - return Impl::StdString::StartsWith( substr ); - } - inline Impl::StdString::StartsWith StartsWith( const char* substr ) { - return Impl::StdString::StartsWith( Impl::StdString::makeString( substr ) ); - } - inline Impl::StdString::EndsWith EndsWith( std::string const& substr ) { - return Impl::StdString::EndsWith( substr ); - } - inline Impl::StdString::EndsWith EndsWith( const char* substr ) { - return Impl::StdString::EndsWith( Impl::StdString::makeString( substr ) ); - } - -} // namespace Matchers - -using namespace Matchers; - -} // namespace Catch - -namespace Catch { - - struct TestFailureException{}; - - template 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 = "" ); - - template - ExpressionLhs operator <= ( T const& operand ); - ExpressionLhs operator <= ( bool value ); - - template - ResultBuilder& operator << ( T const& value ) { - m_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::Matcher 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 ); - - private: - AssertionInfo m_assertionInfo; - AssertionResultData m_data; - CopyableStream m_stream; - - bool m_shouldDebugBreak; - bool m_shouldThrow; - }; - -} // namespace Catch - -// Include after due to circular dependency: -// #included from: catch_expression_lhs.hpp -#define TWOBLUECUBES_CATCH_EXPRESSION_LHS_HPP_INCLUDED - -// #included from: catch_evaluate.hpp -#define TWOBLUECUBES_CATCH_EVALUATE_HPP_INCLUDED - -#ifdef _MSC_VER -#pragma warning(push) -#pragma warning(disable:4389) // '==' : signed/unsigned mismatch -#endif - -#include - -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 - inline T& opCast(T const& t) { return const_cast(t); } - -// nullptr_t support based on pull request #154 from Konstantin Baumann -#ifdef CATCH_CONFIG_CPP11_NULLPTR - inline std::nullptr_t opCast(std::nullptr_t) { return nullptr; } -#endif // CATCH_CONFIG_CPP11_NULLPTR - - // So the compare overloads can be operator agnostic we convey the operator as a template - // enum, which is used to specialise an Evaluator for doing the comparison. - template - class Evaluator{}; - - 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__ -// #included from: catch_objc_arc.hpp -#define TWOBLUECUBES_CATCH_OBJC_ARC_HPP_INCLUDED - -#import - -#ifdef __has_feature -#define CATCH_ARC_ENABLED __has_feature(objc_arc) -#else -#define CATCH_ARC_ENABLED 0 -#endif - -void arcSafeRelease( NSObject* obj ); -id performOptionalSelector( id obj, SEL sel ); - -#if !CATCH_ARC_ENABLED -inline void arcSafeRelease( NSObject* obj ) { - [obj release]; -} -inline id performOptionalSelector( id obj, SEL sel ) { - if( [obj respondsToSelector: sel] ) - return [obj performSelector: sel]; - return nil; -} -#define CATCH_UNSAFE_UNRETAINED -#define CATCH_ARC_STRONG -#else -inline void arcSafeRelease( NSObject* ){} -inline id performOptionalSelector( id obj, SEL sel ) { -#ifdef __clang__ -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Warc-performSelector-leaks" -#endif - if( [obj respondsToSelector: sel] ) - return [obj performSelector: sel]; -#ifdef __clang__ -#pragma clang diagnostic pop -#endif - return nil; -} -#define CATCH_UNSAFE_UNRETAINED __unsafe_unretained -#define CATCH_ARC_STRONG __strong -#endif - -#endif - -#ifdef CATCH_CONFIG_CPP11_TUPLE -#include -#endif - -#ifdef CATCH_CONFIG_CPP11_IS_ENUM -#include -#endif - -namespace Catch { - -// Why we're here. -template -std::string toString( T const& value ); - -// Built in overloads - -std::string toString( std::string const& value ); -std::string toString( std::wstring const& value ); -std::string toString( const char* const value ); -std::string toString( char* const value ); -std::string toString( const wchar_t* const value ); -std::string toString( wchar_t* const value ); -std::string toString( int value ); -std::string toString( unsigned long value ); -std::string toString( unsigned int value ); -std::string toString( const double value ); -std::string toString( const float value ); -std::string toString( bool value ); -std::string toString( char value ); -std::string toString( signed char value ); -std::string toString( unsigned char value ); - -#ifdef CATCH_CONFIG_CPP11_LONG_LONG -std::string toString( long long value ); -std::string toString( unsigned long long value ); -#endif - -#ifdef CATCH_CONFIG_CPP11_NULLPTR -std::string toString( std::nullptr_t ); -#endif - -#ifdef __OBJC__ - std::string toString( NSString const * const& nsstring ); - std::string toString( NSString * CATCH_ARC_STRONG const& nsstring ); - std::string toString( NSObject* const& nsObject ); -#endif - -namespace Detail { - - extern const std::string unprintableString; - - struct BorgType { - template BorgType( T const& ); - }; - - struct TrueType { char sizer[1]; }; - struct FalseType { char sizer[2]; }; - - TrueType& testStreamable( std::ostream& ); - FalseType testStreamable( FalseType ); - - FalseType operator<<( std::ostream const&, BorgType const& ); - - template - struct IsStreamInsertable { - static std::ostream &s; - static T const&t; - enum { value = sizeof( testStreamable(s << t) ) == sizeof( TrueType ) }; - }; - -#if defined(CATCH_CONFIG_CPP11_IS_ENUM) - template::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) - ); - } - }; -#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 - inline 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 - -namespace Catch { - -template -class BinaryExpression; - -template -class MatchExpression; - -// 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) {} - - template - BinaryExpression - operator == ( RhsT const& rhs ) const { - return captureExpression( rhs ); - } - - template - BinaryExpression - operator != ( RhsT const& rhs ) const { - return captureExpression( rhs ); - } - - template - BinaryExpression - operator < ( RhsT const& rhs ) const { - return captureExpression( rhs ); - } - - template - BinaryExpression - operator > ( RhsT const& rhs ) const { - return captureExpression( rhs ); - } - - template - BinaryExpression - operator <= ( RhsT const& rhs ) const { - return captureExpression( rhs ); - } - - template - BinaryExpression - operator >= ( RhsT const& rhs ) const { - return captureExpression( rhs ); - } - - BinaryExpression operator == ( bool rhs ) const { - return captureExpression( rhs ); - } - - BinaryExpression operator != ( bool rhs ) const { - 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_truthy ); - } - -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 ) {} - - 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 - inline ExpressionLhs ResultBuilder::operator <= ( T const& operand ) { - return ExpressionLhs( *this, operand ); - } - - inline ExpressionLhs ResultBuilder::operator <= ( bool value ) { - return ExpressionLhs( *this, value ); - } - - template - inline 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 - -// #included from: catch_message.h -#define TWOBLUECUBES_CATCH_MESSAGE_H_INCLUDED - -#include - -namespace Catch { - - struct MessageInfo { - MessageInfo( std::string const& _macroName, - SourceLineInfo const& _lineInfo, - ResultWas::OfType _type ); - - std::string macroName; - SourceLineInfo lineInfo; - ResultWas::OfType type; - std::string message; - unsigned int sequence; - - bool operator == ( MessageInfo const& other ) const { - return sequence == other.sequence; - } - bool operator < ( MessageInfo const& other ) const { - return sequence < other.sequence; - } - private: - static unsigned int globalCount; - }; - - struct MessageBuilder { - MessageBuilder( std::string const& macroName, - SourceLineInfo const& lineInfo, - ResultWas::OfType type ) - : m_info( macroName, lineInfo, type ) - {} - - template - MessageBuilder& operator << ( T const& value ) { - m_stream << value; - return *this; - } - - MessageInfo m_info; - std::ostringstream m_stream; - }; - - class ScopedMessage { - public: - ScopedMessage( MessageBuilder const& builder ); - ScopedMessage( ScopedMessage const& other ); - ~ScopedMessage(); - - MessageInfo m_info; - }; - -} // end namespace Catch - -// #included from: catch_interfaces_capture.h -#define TWOBLUECUBES_CATCH_INTERFACES_CAPTURE_H_INCLUDED - -#include - -namespace Catch { - - class TestCase; - class AssertionResult; - struct AssertionInfo; - struct SectionInfo; - struct SectionEndInfo; - struct MessageInfo; - class ScopedMessageBuilder; - struct Counts; - - struct IResultCapture { - - virtual ~IResultCapture(); - - virtual void assertionEnded( AssertionResult const& result ) = 0; - virtual bool sectionStarted( SectionInfo const& sectionInfo, - Counts& assertions ) = 0; - virtual void sectionEnded( SectionEndInfo const& endInfo ) = 0; - virtual void sectionEndedEarly( SectionEndInfo const& endInfo ) = 0; - virtual void pushScopedMessage( MessageInfo const& message ) = 0; - virtual void popScopedMessage( MessageInfo const& message ) = 0; - - virtual std::string getCurrentTestName() const = 0; - virtual const AssertionResult* getLastResult() const = 0; - - virtual void handleFatalErrorCondition( std::string const& message ) = 0; - }; - - IResultCapture& getResultCapture(); -} - -// #included from: catch_debugger.h -#define TWOBLUECUBES_CATCH_DEBUGGER_H_INCLUDED - -// #included from: catch_platform.h -#define TWOBLUECUBES_CATCH_PLATFORM_H_INCLUDED - -#if defined(__MAC_OS_X_VERSION_MIN_REQUIRED) -# define CATCH_PLATFORM_MAC -#elif defined(__IPHONE_OS_VERSION_MIN_REQUIRED) -# define CATCH_PLATFORM_IPHONE -#elif defined(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{ - - 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" ) - #else - #define CATCH_TRAP() __asm__("int $3\n" : : ) - #endif - -#elif defined(CATCH_PLATFORM_LINUX) - // If we can use inline assembler, do it because this allows us to break - // directly at the location of the failing check instead of breaking inside - // raise() called from it, i.e. one stack frame below. - #if defined(__GNUC__) && (defined(__i386) || defined(__x86_64)) - #define CATCH_TRAP() asm volatile ("int $3") - #else // Fall back to the generic way. - #include - - #define CATCH_TRAP() raise(SIGTRAP) - #endif -#elif defined(_MSC_VER) - #define CATCH_TRAP() __debugbreak() -#elif defined(__MINGW32__) - extern "C" __declspec(dllimport) void __stdcall DebugBreak(); - #define CATCH_TRAP() DebugBreak() -#endif - -#ifdef CATCH_TRAP - #define CATCH_BREAK_INTO_DEBUGGER() if( Catch::isDebuggerActive() ) { CATCH_TRAP(); } -#else - #define CATCH_BREAK_INTO_DEBUGGER() Catch::alwaysTrue(); -#endif - -// #included from: catch_interfaces_runner.h -#define TWOBLUECUBES_CATCH_INTERFACES_RUNNER_H_INCLUDED - -namespace Catch { - class TestCase; - - struct IRunner { - virtual ~IRunner(); - virtual bool aborting() const = 0; - }; -} - -/////////////////////////////////////////////////////////////////////////////// -// In the event of a failure works out if the debugger needs to be invoked -// and/or an exception thrown and takes appropriate action. -// This needs to be done as a macro so the debugger will stop in the user -// source code rather than in Catch library code -#define INTERNAL_CATCH_REACT( resultBuilder ) \ - if( resultBuilder.shouldDebugBreak() ) CATCH_BREAK_INTO_DEBUGGER(); \ - resultBuilder.react(); - -/////////////////////////////////////////////////////////////////////////////// -#define INTERNAL_CATCH_TEST( expr, resultDisposition, macroName ) \ - do { \ - Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \ - try { \ - CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \ - ( __catchResult <= expr ).endExpression(); \ - } \ - catch( ... ) { \ - __catchResult.useActiveException( 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( expr, resultDisposition, macroName ) \ - INTERNAL_CATCH_TEST( expr, resultDisposition, macroName ); \ - if( Catch::getResultCapture().getLastResult()->succeeded() ) - -/////////////////////////////////////////////////////////////////////////////// -#define INTERNAL_CATCH_ELSE( expr, resultDisposition, macroName ) \ - INTERNAL_CATCH_TEST( expr, resultDisposition, macroName ); \ - if( !Catch::getResultCapture().getLastResult()->succeeded() ) - -/////////////////////////////////////////////////////////////////////////////// -#define INTERNAL_CATCH_NO_THROW( expr, resultDisposition, macroName ) \ - do { \ - Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \ - try { \ - static_cast(expr); \ - __catchResult.captureResult( Catch::ResultWas::Ok ); \ - } \ - catch( ... ) { \ - __catchResult.useActiveException( resultDisposition ); \ - } \ - INTERNAL_CATCH_REACT( __catchResult ) \ - } while( Catch::alwaysFalse() ) - -/////////////////////////////////////////////////////////////////////////////// -#define INTERNAL_CATCH_THROWS( expr, resultDisposition, matcher, macroName ) \ - do { \ - Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition, #matcher ); \ - if( __catchResult.allowThrows() ) \ - try { \ - static_cast(expr); \ - __catchResult.captureResult( Catch::ResultWas::DidntThrowException ); \ - } \ - catch( ... ) { \ - __catchResult.captureExpectedException( matcher ); \ - } \ - else \ - __catchResult.captureResult( Catch::ResultWas::Ok ); \ - INTERNAL_CATCH_REACT( __catchResult ) \ - } while( Catch::alwaysFalse() ) - -/////////////////////////////////////////////////////////////////////////////// -#define INTERNAL_CATCH_THROWS_AS( expr, exceptionType, resultDisposition, macroName ) \ - do { \ - Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \ - if( __catchResult.allowThrows() ) \ - try { \ - static_cast(expr); \ - __catchResult.captureResult( Catch::ResultWas::DidntThrowException ); \ - } \ - catch( exceptionType ) { \ - __catchResult.captureResult( Catch::ResultWas::Ok ); \ - } \ - catch( ... ) { \ - __catchResult.useActiveException( resultDisposition ); \ - } \ - else \ - __catchResult.captureResult( Catch::ResultWas::Ok ); \ - INTERNAL_CATCH_REACT( __catchResult ) \ - } while( Catch::alwaysFalse() ) - -/////////////////////////////////////////////////////////////////////////////// -#ifdef CATCH_CONFIG_VARIADIC_MACROS - #define INTERNAL_CATCH_MSG( messageType, resultDisposition, macroName, ... ) \ - do { \ - Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, "", resultDisposition ); \ - __catchResult << __VA_ARGS__ + ::Catch::StreamEndStop(); \ - __catchResult.captureResult( messageType ); \ - INTERNAL_CATCH_REACT( __catchResult ) \ - } while( Catch::alwaysFalse() ) -#else - #define INTERNAL_CATCH_MSG( messageType, resultDisposition, macroName, log ) \ - do { \ - Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, "", resultDisposition ); \ - __catchResult << log + ::Catch::StreamEndStop(); \ - __catchResult.captureResult( messageType ); \ - INTERNAL_CATCH_REACT( __catchResult ) \ - } while( Catch::alwaysFalse() ) -#endif - -/////////////////////////////////////////////////////////////////////////////// -#define INTERNAL_CATCH_INFO( log, macroName ) \ - Catch::ScopedMessage INTERNAL_CATCH_UNIQUE_NAME( scopedMessage ) = Catch::MessageBuilder( macroName, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info ) << log; - -/////////////////////////////////////////////////////////////////////////////// -#define INTERNAL_CHECK_THAT( arg, matcher, resultDisposition, macroName ) \ - do { \ - Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #arg ", " #matcher, resultDisposition ); \ - try { \ - __catchResult.captureMatch( arg, matcher, #matcher ); \ - } catch( ... ) { \ - __catchResult.useActiveException( resultDisposition | Catch::ResultDisposition::ContinueOnFailure ); \ - } \ - INTERNAL_CATCH_REACT( __catchResult ) \ - } while( Catch::alwaysFalse() ) - -// #included from: internal/catch_section.h -#define TWOBLUECUBES_CATCH_SECTION_H_INCLUDED - -// #included from: catch_section_info.h -#define TWOBLUECUBES_CATCH_SECTION_INFO_H_INCLUDED - -// #included from: catch_totals.hpp -#define TWOBLUECUBES_CATCH_TOTALS_HPP_INCLUDED - -#include - -namespace Catch { - - struct Counts { - Counts() : passed( 0 ), failed( 0 ), failedButOk( 0 ) {} - - Counts operator - ( Counts const& other ) const { - Counts diff; - diff.passed = passed - other.passed; - diff.failed = failed - other.failed; - diff.failedButOk = failedButOk - other.failedButOk; - return diff; - } - Counts& operator += ( Counts const& other ) { - passed += other.passed; - failed += other.failed; - failedButOk += other.failedButOk; - return *this; - } - - std::size_t total() const { - return passed + failed + failedButOk; - } - bool allPassed() const { - return failed == 0 && failedButOk == 0; - } - bool allOk() const { - return failed == 0; - } - - std::size_t passed; - std::size_t failed; - std::size_t failedButOk; - }; - - struct Totals { - - Totals operator - ( Totals const& other ) const { - Totals diff; - diff.assertions = assertions - other.assertions; - diff.testCases = testCases - other.testCases; - return diff; - } - - Totals delta( Totals const& prevTotals ) const { - Totals diff = *this - prevTotals; - if( diff.assertions.failed > 0 ) - ++diff.testCases.failed; - else if( diff.assertions.failedButOk > 0 ) - ++diff.testCases.failedButOk; - else - ++diff.testCases.passed; - return diff; - } - - Totals& operator += ( Totals const& other ) { - assertions += other.assertions; - testCases += other.testCases; - return *this; - } - - Counts assertions; - Counts testCases; - }; -} - -namespace Catch { - - struct SectionInfo { - SectionInfo - ( SourceLineInfo const& _lineInfo, - std::string const& _name, - std::string const& _description = std::string() ); - - std::string name; - std::string description; - SourceLineInfo lineInfo; - }; - - struct SectionEndInfo { - SectionEndInfo( SectionInfo const& _sectionInfo, Counts const& _prevAssertions, double _durationInSeconds ) - : sectionInfo( _sectionInfo ), prevAssertions( _prevAssertions ), durationInSeconds( _durationInSeconds ) - {} - - SectionInfo sectionInfo; - Counts prevAssertions; - double durationInSeconds; - }; - -} // end namespace Catch - -// #included from: catch_timer.h -#define TWOBLUECUBES_CATCH_TIMER_H_INCLUDED - -#ifdef CATCH_PLATFORM_WINDOWS -typedef unsigned long long uint64_t; -#else -#include -#endif - -namespace Catch { - - class Timer { - public: - Timer() : m_ticks( 0 ) {} - void start(); - unsigned int getElapsedMicroseconds() const; - unsigned int getElapsedMilliseconds() const; - double getElapsedSeconds() const; - - private: - uint64_t m_ticks; - }; - -} // namespace Catch - -#include - -namespace Catch { - - class Section : NonCopyable { - public: - Section( SectionInfo const& info ); - ~Section(); - - // This indicates whether the section should be executed or not - operator bool() const; - - private: - SectionInfo m_info; - - std::string m_name; - Counts m_assertions; - bool m_sectionIncluded; - Timer m_timer; - }; - -} // end namespace Catch - -#ifdef CATCH_CONFIG_VARIADIC_MACROS - #define INTERNAL_CATCH_SECTION( ... ) \ - if( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::SectionInfo( CATCH_INTERNAL_LINEINFO, __VA_ARGS__ ) ) -#else - #define INTERNAL_CATCH_SECTION( name, desc ) \ - if( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::SectionInfo( CATCH_INTERNAL_LINEINFO, name, desc ) ) -#endif - -// #included from: internal/catch_generators.hpp -#define TWOBLUECUBES_CATCH_GENERATORS_HPP_INCLUDED - -#include -#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; -}; - -template -class BetweenGenerator : public IGenerator { -public: - BetweenGenerator( T from, T to ) : m_from( from ), m_to( to ){} - - virtual T getValue( std::size_t index ) const { - return m_from+static_cast( index ); - } - - virtual 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 ) - { - 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 - } - - void add( const IGenerator* generator ) { - m_totalSize += generator->size(); - m_composed.push_back( generator ); - } - - CompositeGenerator& then( CompositeGenerator& other ) { - move( other ); - return *this; - } - - CompositeGenerator& then( T value ) { - ValuesGenerator* valuesGen = new ValuesGenerator(); - valuesGen->add( value ); - add( valuesGen ); - return *this; - } - -private: - - void move( CompositeGenerator& other ) { - std::copy( other.m_composed.begin(), other.m_composed.end(), std::back_inserter( m_composed ) ); - m_totalSize += other.m_totalSize; - other.m_composed.clear(); - } - - std::vector*> 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 INTERNAL_CATCH_LINESTR2( line ) #line -#define INTERNAL_CATCH_LINESTR( line ) INTERNAL_CATCH_LINESTR2( line ) - -#define INTERNAL_CATCH_GENERATE( expr ) expr.setFileInfo( __FILE__ "(" INTERNAL_CATCH_LINESTR( __LINE__ ) ")" ) - -// #included from: internal/catch_interfaces_exception.h -#define TWOBLUECUBES_CATCH_INTERFACES_EXCEPTION_H_INCLUDED - -#include -#include - -// #included from: catch_interfaces_registry_hub.h -#define TWOBLUECUBES_CATCH_INTERFACES_REGISTRY_HUB_H_INCLUDED - -#include - -namespace Catch { - - class TestCase; - struct ITestCaseRegistry; - struct IExceptionTranslatorRegistry; - struct IExceptionTranslator; - struct IReporterRegistry; - struct IReporterFactory; - - struct IRegistryHub { - virtual ~IRegistryHub(); - - virtual IReporterRegistry const& getReporterRegistry() const = 0; - virtual ITestCaseRegistry const& getTestCaseRegistry() const = 0; - virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() = 0; - }; - - struct IMutableRegistryHub { - virtual ~IMutableRegistryHub(); - virtual void registerReporter( std::string const& name, Ptr const& factory ) = 0; - virtual void registerListener( Ptr const& factory ) = 0; - virtual void registerTest( TestCase const& testInfo ) = 0; - virtual void registerTranslator( const IExceptionTranslator* translator ) = 0; - }; - - IRegistryHub& getRegistryHub(); - IMutableRegistryHub& getMutableRegistryHub(); - void cleanUp(); - std::string translateActiveException(); - -} - -namespace Catch { - - typedef std::string(*exceptionTranslateFunction)(); - - struct IExceptionTranslator; - typedef std::vector ExceptionTranslators; - - struct IExceptionTranslator { - virtual ~IExceptionTranslator(); - virtual std::string translate( ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd ) const = 0; - }; - - struct IExceptionTranslatorRegistry { - virtual ~IExceptionTranslatorRegistry(); - - virtual std::string translateActiveException() const = 0; - }; - - class ExceptionTranslatorRegistrar { - template - class ExceptionTranslator : public IExceptionTranslator { - public: - - ExceptionTranslator( std::string(*translateFunction)( T& ) ) - : m_translateFunction( translateFunction ) - {} - - virtual std::string translate( ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd ) const CATCH_OVERRIDE { - try { - if( it == itEnd ) - throw; - else - return (*it)->translate( it+1, itEnd ); - } - catch( T& ex ) { - return m_translateFunction( ex ); - } - } - - protected: - std::string(*m_translateFunction)( T& ); - }; - - public: - template - ExceptionTranslatorRegistrar( std::string(*translateFunction)( T& ) ) { - getMutableRegistryHub().registerTranslator - ( new ExceptionTranslator( translateFunction ) ); - } - }; -} - -/////////////////////////////////////////////////////////////////////////////// -#define INTERNAL_CATCH_TRANSLATE_EXCEPTION2( translatorName, signature ) \ - static std::string translatorName( signature ); \ - namespace{ Catch::ExceptionTranslatorRegistrar INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionRegistrar )( &translatorName ); }\ - static std::string translatorName( signature ) - -#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 - -#include -#include - -#if defined(CATCH_CONFIG_CPP11_TYPE_TRAITS) -#include -#endif - -namespace Catch { -namespace Detail { - - class Approx { - public: - explicit Approx ( double value ) - : m_epsilon( std::numeric_limits::epsilon()*100 ), - m_scale( 1.0 ), - m_value( value ) - {} - - Approx( Approx const& other ) - : m_epsilon( other.m_epsilon ), - m_scale( other.m_scale ), - m_value( other.m_value ) - {} - - static Approx custom() { - return Approx( 0 ); - } - - Approx operator()( double value ) { - Approx approx( value ); - approx.epsilon( m_epsilon ); - approx.scale( m_scale ); - return approx; - } - -#if defined(CATCH_CONFIG_CPP11_TYPE_TRAITS) - 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); - return fabs( lhs_v - rhs.m_value ) < rhs.m_epsilon * (rhs.m_scale + (std::max)( fabs(lhs_v), fabs(rhs.m_value) ) ); - } - - template ::value>::type> - friend bool operator == ( Approx const& lhs, const T& rhs ) { - return operator==( rhs, lhs ); - } - - template ::value>::type> - friend bool operator != ( T lhs, Approx const& rhs ) { - return !operator==( lhs, rhs ); - } - - template ::value>::type> - friend bool operator != ( Approx const& lhs, T rhs ) { - return !operator==( rhs, lhs ); - } - - template ::value>::type> - 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 rhs ) - { - return lhs.m_value < double(rhs) || lhs == rhs; - } - - template ::value>::type> - 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 rhs ) - { - return lhs.m_value > double(rhs) || lhs == rhs; - } -#else - friend bool operator == ( double lhs, Approx const& rhs ) { - // Thanks to Richard Harris for his help refining this formula - return fabs( lhs - rhs.m_value ) < rhs.m_epsilon * (rhs.m_scale + (std::max)( fabs(lhs), fabs(rhs.m_value) ) ); - } - - friend bool operator == ( Approx const& lhs, double rhs ) { - return operator==( rhs, lhs ); - } - - friend bool operator != ( double lhs, Approx const& rhs ) { - return !operator==( lhs, rhs ); - } - - friend bool operator != ( Approx const& lhs, double rhs ) { - return !operator==( rhs, lhs ); - } - - 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; - } -#endif - - Approx& epsilon( double newEpsilon ) { - m_epsilon = newEpsilon; - return *this; - } - - Approx& scale( double newScale ) { - m_scale = newScale; - return *this; - } - - std::string toString() const { - std::ostringstream oss; - oss << "Approx( " << Catch::toString( m_value ) << " )"; - return oss.str(); - } - - private: - double m_epsilon; - double m_scale; - double m_value; - }; -} - -template<> -inline std::string toString( Detail::Approx const& value ) { - return value.toString(); -} - -} // end namespace Catch - -// #included from: internal/catch_interfaces_tag_alias_registry.h -#define TWOBLUECUBES_CATCH_INTERFACES_TAG_ALIAS_REGISTRY_H_INCLUDED - -// #included from: catch_tag_alias.h -#define TWOBLUECUBES_CATCH_TAG_ALIAS_H_INCLUDED - -#include - -namespace Catch { - - struct TagAlias { - TagAlias( std::string _tag, SourceLineInfo _lineInfo ) : tag( _tag ), lineInfo( _lineInfo ) {} - - std::string tag; - SourceLineInfo lineInfo; - }; - - struct RegistrarForTagAliases { - RegistrarForTagAliases( char const* alias, char const* tag, SourceLineInfo const& lineInfo ); - }; - -} // end namespace Catch - -#define CATCH_REGISTER_TAG_ALIAS( alias, spec ) namespace{ Catch::RegistrarForTagAliases INTERNAL_CATCH_UNIQUE_NAME( AutoRegisterTagAlias )( alias, spec, CATCH_INTERNAL_LINEINFO ); } -// #included from: catch_option.hpp -#define TWOBLUECUBES_CATCH_OPTION_HPP_INCLUDED - -namespace Catch { - - // An optional type - template - class Option { - public: - Option() : nullableValue( CATCH_NULL ) {} - Option( T const& _value ) - : nullableValue( new( storage ) T( _value ) ) - {} - Option( Option const& _other ) - : nullableValue( _other ? new( storage ) T( *_other ) : CATCH_NULL ) - {} - - ~Option() { - reset(); - } - - Option& operator= ( Option const& _other ) { - if( &_other != this ) { - reset(); - if( _other ) - nullableValue = new( storage ) T( *_other ); - } - return *this; - } - Option& operator = ( T const& _value ) { - reset(); - nullableValue = new( storage ) T( _value ); - return *this; - } - - void reset() { - if( nullableValue ) - nullableValue->~T(); - nullableValue = CATCH_NULL; - } - - T& operator*() { return *nullableValue; } - T const& operator*() const { return *nullableValue; } - T* operator->() { return nullableValue; } - const T* operator->() const { return nullableValue; } - - T valueOr( T const& defaultValue ) const { - return nullableValue ? *nullableValue : defaultValue; - } - - bool some() const { return nullableValue != CATCH_NULL; } - bool none() const { return nullableValue == CATCH_NULL; } - - bool operator !() const { return nullableValue == CATCH_NULL; } - operator SafeBool::type() const { - return SafeBool::makeSafe( some() ); - } - - private: - T* nullableValue; - char storage[sizeof(T)]; - }; - -} // end namespace Catch - -namespace Catch { - - struct ITagAliasRegistry { - virtual ~ITagAliasRegistry(); - virtual Option find( std::string const& alias ) const = 0; - virtual std::string expandAliases( std::string const& unexpandedTestSpec ) const = 0; - - static ITagAliasRegistry const& get(); - }; - -} // end namespace Catch - -// These files are included here so the single_include script doesn't put them -// in the conditionally compiled sections -// #included from: internal/catch_test_case_info.h -#define TWOBLUECUBES_CATCH_TEST_CASE_INFO_H_INCLUDED - -#include -#include - -#ifdef __clang__ -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wpadded" -#endif - -namespace Catch { - - struct ITestCase; - - struct TestCaseInfo { - enum SpecialProperties{ - None = 0, - IsHidden = 1 << 1, - ShouldFail = 1 << 2, - MayFail = 1 << 3, - Throws = 1 << 4, - NonPortable = 1 << 5 - }; - - TestCaseInfo( std::string const& _name, - std::string const& _className, - std::string const& _description, - std::set const& _tags, - SourceLineInfo const& _lineInfo ); - - 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 name; - std::string className; - std::string description; - std::set tags; - std::set lcaseTags; - std::string tagsAsString; - SourceLineInfo lineInfo; - SpecialProperties properties; - }; - - class TestCase : public TestCaseInfo { - public: - - TestCase( ITestCase* testCase, TestCaseInfo const& info ); - TestCase( TestCase const& other ); - - TestCase withName( std::string const& _newName ) const; - - void invoke() const; - - TestCaseInfo const& getTestCaseInfo() const; - - void swap( TestCase& other ); - bool operator == ( TestCase const& other ) const; - bool operator < ( TestCase const& other ) const; - TestCase& operator = ( TestCase const& other ); - - private: - Ptr test; - }; - - TestCase makeTestCase( ITestCase* testCase, - std::string const& className, - std::string const& name, - std::string const& description, - SourceLineInfo const& lineInfo ); -} - -#ifdef __clang__ -#pragma clang diagnostic pop -#endif - - -#ifdef __OBJC__ -// #included from: internal/catch_objc.hpp -#define TWOBLUECUBES_CATCH_OBJC_HPP_INCLUDED - -#import - -#include - -// NB. Any general catch headers included here must be included -// in catch.hpp first to make sure they are included by the single -// header for non obj-usage - -/////////////////////////////////////////////////////////////////////////////// -// This protocol is really only here for (self) documenting purposes, since -// all its methods are optional. -@protocol OcFixture - -@optional - --(void) setUp; --(void) tearDown; - -@end - -namespace Catch { - - class OcMethod : public SharedImpl { - - public: - OcMethod( Class cls, SEL sel ) : m_cls( cls ), m_sel( sel ) {} - - virtual void invoke() const { - id obj = [[m_cls alloc] init]; - - performOptionalSelector( obj, @selector(setUp) ); - performOptionalSelector( obj, m_sel ); - performOptionalSelector( obj, @selector(tearDown) ); - - arcSafeRelease( obj ); - } - private: - virtual ~OcMethod() {} - - Class m_cls; - SEL m_sel; - }; - - namespace Detail{ - - inline std::string getAnnotation( Class cls, - std::string const& annotationName, - std::string const& testCaseName ) { - NSString* selStr = [[NSString alloc] initWithFormat:@"Catch_%s_%s", annotationName.c_str(), testCaseName.c_str()]; - SEL sel = NSSelectorFromString( selStr ); - arcSafeRelease( selStr ); - id value = performOptionalSelector( cls, sel ); - if( value ) - return [(NSString*)value UTF8String]; - return ""; - } - } - - inline size_t registerTestMethods() { - size_t noTestMethods = 0; - int noClasses = objc_getClassList( CATCH_NULL, 0 ); - - Class* classes = (CATCH_UNSAFE_UNRETAINED Class *)malloc( sizeof(Class) * noClasses); - objc_getClassList( classes, noClasses ); - - for( int c = 0; c < noClasses; c++ ) { - Class cls = classes[c]; - { - u_int count; - Method* methods = class_copyMethodList( cls, &count ); - for( u_int m = 0; m < count ; m++ ) { - SEL selector = method_getName(methods[m]); - std::string methodName = sel_getName(selector); - if( startsWith( methodName, "Catch_TestCase_" ) ) { - std::string testCaseName = methodName.substr( 15 ); - std::string name = Detail::getAnnotation( cls, "Name", testCaseName ); - std::string desc = Detail::getAnnotation( cls, "Description", testCaseName ); - const char* className = class_getName( cls ); - - getMutableRegistryHub().registerTest( makeTestCase( new OcMethod( cls, selector ), className, name.c_str(), desc.c_str(), SourceLineInfo() ) ); - noTestMethods++; - } - } - free(methods); - } - } - return noTestMethods; - } - - namespace Matchers { - namespace Impl { - namespace NSStringMatchers { - - template - struct StringHolder : MatcherImpl{ - StringHolder( NSString* substr ) : m_substr( [substr copy] ){} - StringHolder( StringHolder const& other ) : m_substr( [other.m_substr copy] ){} - StringHolder() { - arcSafeRelease( m_substr ); - } - - NSString* m_substr; - }; - - struct Equals : StringHolder { - Equals( NSString* substr ) : StringHolder( substr ){} - - virtual bool match( ExpressionType const& str ) const { - return (str != nil || m_substr == nil ) && - [str isEqualToString:m_substr]; - } - - virtual std::string toString() const { - return "equals string: " + Catch::toString( m_substr ); - } - }; - - struct Contains : StringHolder { - Contains( NSString* substr ) : StringHolder( substr ){} - - virtual bool match( ExpressionType const& str ) const { - return (str != nil || m_substr == nil ) && - [str rangeOfString:m_substr].location != NSNotFound; - } - - virtual std::string toString() const { - return "contains string: " + Catch::toString( m_substr ); - } - }; - - struct StartsWith : StringHolder { - StartsWith( NSString* substr ) : StringHolder( substr ){} - - virtual bool match( ExpressionType const& str ) const { - return (str != nil || m_substr == nil ) && - [str rangeOfString:m_substr].location == 0; - } - - virtual std::string toString() const { - return "starts with: " + Catch::toString( m_substr ); - } - }; - struct EndsWith : StringHolder { - EndsWith( NSString* substr ) : StringHolder( substr ){} - - virtual bool match( ExpressionType const& str ) const { - return (str != nil || m_substr == nil ) && - [str rangeOfString:m_substr].location == [str length] - [m_substr length]; - } - - virtual std::string toString() const { - return "ends with: " + Catch::toString( m_substr ); - } - }; - - } // namespace NSStringMatchers - } // namespace Impl - - inline Impl::NSStringMatchers::Equals - Equals( NSString* substr ){ return Impl::NSStringMatchers::Equals( substr ); } - - inline Impl::NSStringMatchers::Contains - Contains( NSString* substr ){ return Impl::NSStringMatchers::Contains( substr ); } - - inline Impl::NSStringMatchers::StartsWith - StartsWith( NSString* substr ){ return Impl::NSStringMatchers::StartsWith( substr ); } - - inline Impl::NSStringMatchers::EndsWith - EndsWith( NSString* substr ){ return Impl::NSStringMatchers::EndsWith( substr ); } - - } // namespace Matchers - - using namespace Matchers; - -} // namespace Catch - -/////////////////////////////////////////////////////////////////////////////// -#define OC_TEST_CASE( name, desc )\ -+(NSString*) INTERNAL_CATCH_UNIQUE_NAME( Catch_Name_test ) \ -{\ -return @ name; \ -}\ -+(NSString*) INTERNAL_CATCH_UNIQUE_NAME( Catch_Description_test ) \ -{ \ -return @ desc; \ -} \ --(void) INTERNAL_CATCH_UNIQUE_NAME( Catch_TestCase_test ) - -#endif - -#ifdef CATCH_IMPL -// #included from: internal/catch_impl.hpp -#define TWOBLUECUBES_CATCH_IMPL_HPP_INCLUDED - -// Collect all the implementation files together here -// These are the equivalent of what would usually be cpp files - -#ifdef __clang__ -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wweak-vtables" -#endif - -// #included from: ../catch_session.hpp -#define TWOBLUECUBES_CATCH_RUNNER_HPP_INCLUDED - -// #included from: internal/catch_commandline.hpp -#define TWOBLUECUBES_CATCH_COMMANDLINE_HPP_INCLUDED - -// #included from: catch_config.hpp -#define TWOBLUECUBES_CATCH_CONFIG_HPP_INCLUDED - -// #included from: catch_test_spec_parser.hpp -#define TWOBLUECUBES_CATCH_TEST_SPEC_PARSER_HPP_INCLUDED - -#ifdef __clang__ -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wpadded" -#endif - -// #included from: catch_test_spec.hpp -#define TWOBLUECUBES_CATCH_TEST_SPEC_HPP_INCLUDED - -#ifdef __clang__ -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wpadded" -#endif - -// #included from: catch_wildcard_pattern.hpp -#define TWOBLUECUBES_CATCH_WILDCARD_PATTERN_HPP_INCLUDED - -namespace Catch -{ - class WildcardPattern { - enum WildcardPosition { - NoWildcard = 0, - WildcardAtStart = 1, - WildcardAtEnd = 2, - WildcardAtBothEnds = WildcardAtStart | WildcardAtEnd - }; - - public: - - WildcardPattern( std::string const& pattern, CaseSensitive::Choice caseSensitivity ) - : m_caseSensitivity( caseSensitivity ), - m_wildcard( NoWildcard ), - m_pattern( adjustCase( pattern ) ) - { - if( startsWith( m_pattern, '*' ) ) { - m_pattern = m_pattern.substr( 1 ); - m_wildcard = WildcardAtStart; - } - if( endsWith( m_pattern, '*' ) ) { - m_pattern = m_pattern.substr( 0, m_pattern.size()-1 ); - m_wildcard = static_cast( m_wildcard | WildcardAtEnd ); - } - } - virtual ~WildcardPattern(); - virtual bool matches( std::string const& str ) const { - switch( m_wildcard ) { - case NoWildcard: - return m_pattern == adjustCase( str ); - case WildcardAtStart: - return endsWith( adjustCase( str ), m_pattern ); - case WildcardAtEnd: - return startsWith( adjustCase( str ), m_pattern ); - case WildcardAtBothEnds: - return contains( adjustCase( str ), m_pattern ); - } - -#ifdef __clang__ -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wunreachable-code" -#endif - throw std::logic_error( "Unknown enum" ); -#ifdef __clang__ -#pragma clang diagnostic pop -#endif - } - private: - std::string adjustCase( std::string const& str ) const { - return m_caseSensitivity == CaseSensitive::No ? toLower( str ) : str; - } - CaseSensitive::Choice m_caseSensitivity; - WildcardPosition m_wildcard; - std::string m_pattern; - }; -} - -#include -#include - -namespace Catch { - - class TestSpec { - struct Pattern : SharedImpl<> { - virtual ~Pattern(); - virtual bool matches( TestCaseInfo const& testCase ) const = 0; - }; - class NamePattern : public Pattern { - public: - NamePattern( std::string const& name ) - : m_wildcardPattern( toLower( name ), CaseSensitive::No ) - {} - virtual ~NamePattern(); - virtual bool matches( TestCaseInfo const& testCase ) const { - return m_wildcardPattern.matches( toLower( testCase.name ) ); - } - private: - WildcardPattern m_wildcardPattern; - }; - - class TagPattern : public Pattern { - public: - TagPattern( std::string const& tag ) : m_tag( toLower( tag ) ) {} - virtual ~TagPattern(); - virtual bool matches( TestCaseInfo const& testCase ) const { - return testCase.lcaseTags.find( m_tag ) != testCase.lcaseTags.end(); - } - private: - std::string m_tag; - }; - - class ExcludedPattern : public Pattern { - public: - ExcludedPattern( Ptr const& underlyingPattern ) : m_underlyingPattern( underlyingPattern ) {} - virtual ~ExcludedPattern(); - virtual bool matches( TestCaseInfo const& testCase ) const { return !m_underlyingPattern->matches( testCase ); } - private: - Ptr m_underlyingPattern; - }; - - struct Filter { - std::vector > m_patterns; - - bool matches( TestCaseInfo const& testCase ) const { - // All patterns in a filter must match for the filter to be a match - for( std::vector >::const_iterator it = m_patterns.begin(), itEnd = m_patterns.end(); it != itEnd; ++it ) { - if( !(*it)->matches( testCase ) ) - return false; - } - return true; - } - }; - - public: - bool hasFilters() const { - return !m_filters.empty(); - } - bool matches( TestCaseInfo const& testCase ) const { - // A TestSpec matches if any filter matches - for( std::vector::const_iterator it = m_filters.begin(), itEnd = m_filters.end(); it != itEnd; ++it ) - if( it->matches( testCase ) ) - return true; - return false; - } - - private: - std::vector m_filters; - - friend class TestSpecParser; - }; -} - -#ifdef __clang__ -#pragma clang diagnostic pop -#endif - -namespace Catch { - - class TestSpecParser { - enum Mode{ None, Name, QuotedName, Tag, EscapedName }; - 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; - - public: - TestSpecParser( ITagAliasRegistry const& tagAliases ) : m_tagAliases( &tagAliases ) {} - - TestSpecParser& parse( std::string const& arg ) { - m_mode = None; - m_exclusion = false; - m_start = std::string::npos; - m_arg = m_tagAliases->expandAliases( arg ); - 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 ); } - template - void addPattern() { - std::string token = subString(); - for( size_t i = 0; i < m_escapeChars.size(); ++i ) - token = token.substr( 0, m_escapeChars[i]-i ) + token.substr( m_escapeChars[i]+1-i ); - m_escapeChars.clear(); - if( startsWith( token, "exclude:" ) ) { - m_exclusion = true; - token = token.substr( 8 ); - } - if( !token.empty() ) { - Ptr pattern = new T( token ); - if( m_exclusion ) - pattern = new TestSpec::ExcludedPattern( pattern ); - m_currentFilter.m_patterns.push_back( pattern ); - } - m_exclusion = false; - m_mode = None; - } - void addFilter() { - if( !m_currentFilter.m_patterns.empty() ) { - m_testSpec.m_filters.push_back( m_currentFilter ); - m_currentFilter = TestSpec::Filter(); - } - } - }; - inline TestSpec parseTestSpec( std::string const& arg ) { - return TestSpecParser( ITagAliasRegistry::get() ).parse( arg ).testSpec(); - } - -} // namespace Catch - -#ifdef __clang__ -#pragma clang diagnostic pop -#endif - -// #included from: catch_interfaces_config.h -#define TWOBLUECUBES_CATCH_INTERFACES_CONFIG_H_INCLUDED - -#include -#include -#include - -namespace Catch { - - struct Verbosity { enum Level { - NoOutput = 0, - Quiet, - Normal - }; }; - - struct WarnAbout { enum What { - Nothing = 0x00, - NoAssertions = 0x01 - }; }; - - struct ShowDurations { enum OrNot { - DefaultForReporter, - Always, - Never - }; }; - struct RunTests { enum InWhatOrder { - InDeclarationOrder, - InLexicographicalOrder, - InRandomOrder - }; }; - struct UseColour { enum YesOrNo { - Auto, - Yes, - No - }; }; - - class TestSpec; - - struct IConfig : IShared { - - virtual ~IConfig(); - - virtual bool allowThrows() const = 0; - virtual std::ostream& stream() const = 0; - virtual std::string name() const = 0; - virtual bool includeSuccessfulResults() const = 0; - virtual bool shouldDebugBreak() const = 0; - virtual bool warnAboutMissingAssertions() const = 0; - virtual int abortAfter() const = 0; - virtual bool showInvisibles() const = 0; - virtual ShowDurations::OrNot showDurations() const = 0; - virtual TestSpec const& testSpec() const = 0; - virtual RunTests::InWhatOrder runOrder() const = 0; - virtual unsigned int rngSeed() const = 0; - virtual UseColour::YesOrNo useColour() const = 0; - virtual std::vector const& getSectionsToRun() const = 0; - - }; -} - -// #included from: catch_stream.h -#define TWOBLUECUBES_CATCH_STREAM_H_INCLUDED - -// #included from: catch_streambuf.h -#define TWOBLUECUBES_CATCH_STREAMBUF_H_INCLUDED - -#include - -namespace Catch { - - class StreamBufBase : public std::streambuf { - public: - virtual ~StreamBufBase() CATCH_NOEXCEPT; - }; -} - -#include -#include -#include -#include - -namespace Catch { - - std::ostream& cout(); - std::ostream& cerr(); - - struct IStream { - virtual ~IStream() CATCH_NOEXCEPT; - virtual std::ostream& stream() const = 0; - }; - - class FileStream : public IStream { - mutable std::ofstream m_ofs; - public: - FileStream( std::string const& filename ); - virtual ~FileStream() CATCH_NOEXCEPT; - public: // IStream - virtual std::ostream& stream() const CATCH_OVERRIDE; - }; - - class CoutStream : public IStream { - mutable std::ostream m_os; - public: - CoutStream(); - virtual ~CoutStream() CATCH_NOEXCEPT; - - public: // IStream - virtual std::ostream& stream() const CATCH_OVERRIDE; - }; - - class DebugOutStream : public IStream { - CATCH_AUTO_PTR( StreamBufBase ) m_streamBuf; - mutable std::ostream m_os; - public: - DebugOutStream(); - virtual ~DebugOutStream() CATCH_NOEXCEPT; - - public: // IStream - virtual std::ostream& stream() const CATCH_OVERRIDE; - }; -} - -#include -#include -#include -#include -#include - -#ifndef CATCH_CONFIG_CONSOLE_WIDTH -#define CATCH_CONFIG_CONSOLE_WIDTH 80 -#endif - -namespace Catch { - - struct ConfigData { - - ConfigData() - : listTests( false ), - listTags( false ), - listReporters( false ), - listTestNamesOnly( false ), - showSuccessfulTests( false ), - shouldDebugBreak( false ), - noThrow( false ), - showHelp( false ), - showInvisibles( false ), - filenamesAsTags( false ), - abortAfter( -1 ), - rngSeed( 0 ), - verbosity( Verbosity::Normal ), - warnings( WarnAbout::Nothing ), - showDurations( ShowDurations::DefaultForReporter ), - runOrder( RunTests::InDeclarationOrder ), - useColour( UseColour::Auto ) - {} - - bool listTests; - bool listTags; - bool listReporters; - bool listTestNamesOnly; - - bool showSuccessfulTests; - bool shouldDebugBreak; - bool noThrow; - bool showHelp; - bool showInvisibles; - bool filenamesAsTags; - - int abortAfter; - unsigned int rngSeed; - - Verbosity::Level verbosity; - WarnAbout::What warnings; - ShowDurations::OrNot showDurations; - RunTests::InWhatOrder runOrder; - UseColour::YesOrNo useColour; - - std::string outputFilename; - std::string name; - std::string processName; - - std::vector reporterNames; - std::vector testsOrTags; - std::vector sectionsToRun; - }; - - class Config : public SharedImpl { - private: - Config( Config const& other ); - Config& operator = ( Config const& other ); - virtual void dummy(); - public: - - Config() - {} - - Config( ConfigData const& data ) - : m_data( data ), - m_stream( openStream() ) - { - if( !data.testsOrTags.empty() ) { - TestSpecParser parser( ITagAliasRegistry::get() ); - for( std::size_t i = 0; i < data.testsOrTags.size(); ++i ) - parser.parse( data.testsOrTags[i] ); - m_testSpec = parser.testSpec(); - } - } - - virtual ~Config() { - } - - std::string const& getFilename() const { - return m_data.outputFilename ; - } - - bool listTests() const { return m_data.listTests; } - bool listTestNamesOnly() const { return m_data.listTestNamesOnly; } - bool listTags() const { return m_data.listTags; } - bool listReporters() const { return m_data.listReporters; } - - std::string getProcessName() const { return m_data.processName; } - - bool shouldDebugBreak() const { return m_data.shouldDebugBreak; } - - std::vector const& getReporterNames() const { return m_data.reporterNames; } - std::vector const& getSectionsToRun() const CATCH_OVERRIDE { return m_data.sectionsToRun; } - - int abortAfter() const { return m_data.abortAfter; } - - TestSpec const& testSpec() const { return m_testSpec; } - - bool showHelp() const { return m_data.showHelp; } - bool showInvisibles() const { return m_data.showInvisibles; } - - // IConfig interface - virtual bool allowThrows() const { return !m_data.noThrow; } - virtual std::ostream& stream() const { return m_stream->stream(); } - virtual std::string name() const { return m_data.name.empty() ? m_data.processName : m_data.name; } - virtual bool includeSuccessfulResults() const { return m_data.showSuccessfulTests; } - virtual bool warnAboutMissingAssertions() const { return m_data.warnings & WarnAbout::NoAssertions; } - virtual ShowDurations::OrNot showDurations() const { return m_data.showDurations; } - virtual RunTests::InWhatOrder runOrder() const { return m_data.runOrder; } - virtual unsigned int rngSeed() const { return m_data.rngSeed; } - virtual UseColour::YesOrNo useColour() const { return m_data.useColour; } - - private: - - IStream const* openStream() { - if( m_data.outputFilename.empty() ) - return new CoutStream(); - else if( m_data.outputFilename[0] == '%' ) { - if( m_data.outputFilename == "%debug" ) - return new DebugOutStream(); - else - throw std::domain_error( "Unrecognised stream: " + m_data.outputFilename ); - } - else - return new FileStream( m_data.outputFilename ); - } - ConfigData m_data; - - CATCH_AUTO_PTR( IStream const ) m_stream; - TestSpec m_testSpec; - }; - -} // end namespace Catch - -// #included from: catch_clara.h -#define TWOBLUECUBES_CATCH_CLARA_H_INCLUDED - -// Use Catch's value for console width (store Clara's off to the side, if present) -#ifdef CLARA_CONFIG_CONSOLE_WIDTH -#define CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH CLARA_CONFIG_CONSOLE_WIDTH -#undef CLARA_CONFIG_CONSOLE_WIDTH -#endif -#define CLARA_CONFIG_CONSOLE_WIDTH CATCH_CONFIG_CONSOLE_WIDTH - -// Declare Clara inside the Catch namespace -#define STITCH_CLARA_OPEN_NAMESPACE namespace Catch { -// #included from: ../external/clara.h - -// Version 0.0.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 -#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(); - } - - 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 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( ::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( 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[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 - -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( "Argment to --rng-seed should be the word 'time' or a number" ); - } - } - inline void setVerbosity( ConfigData& config, int level ) { - // !TBD: accept strings? - config.verbosity = static_cast( 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-reporters"] - .describe( "list all reporters" ) - .bind( &ConfigData::listReporters ); - - cli["--order"] - .describe( "test case order (defaults to decl)" ) - .bind( &setOrder, "decl|lex|rand" ); - - cli["--rng-seed"] - .describe( "set a specific seed for random numbers" ) - .bind( &setRngSeed, "'time'|number" ); - - cli["--force-colour"] - .describe( "force colourised output (deprecated)" ) - .bind( &forceColour ); - - cli["--use-colour"] - .describe( "should output be colourised" ) - .bind( &setUseColour, "yes|no" ); - - return cli; - } - -} // end namespace Catch - -// #included from: internal/catch_list.hpp -#define TWOBLUECUBES_CATCH_LIST_HPP_INCLUDED - -// #included from: catch_text.h -#define TWOBLUECUBES_CATCH_TEXT_H_INCLUDED - -#define TBC_TEXT_FORMAT_CONSOLE_WIDTH CATCH_CONFIG_CONSOLE_WIDTH - -#define CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE Catch -// #included from: ../external/tbc_text_format.h -// Only use header guard if we are not using an outer namespace -#ifndef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE -# ifdef TWOBLUECUBES_TEXT_FORMAT_H_INCLUDED -# ifndef TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED -# define TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED -# endif -# else -# define TWOBLUECUBES_TEXT_FORMAT_H_INCLUDED -# endif -#endif -#ifndef TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED -#include -#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 { - - struct Colour { - enum Code { - None = 0, - - White, - Red, - Green, - Blue, - Cyan, - Yellow, - Grey, - - Bright = 0x10, - - BrightRed = Bright | Red, - BrightGreen = Bright | Green, - LightGrey = Bright | Grey, - BrightWhite = Bright | White, - - // By intention - FileName = LightGrey, - Warning = Yellow, - ResultError = BrightRed, - ResultSuccess = BrightGreen, - ResultExpectedFailure = Warning, - - Error = BrightRed, - Success = Green, - - OriginalExpression = Cyan, - ReconstructedExpression = Yellow, - - SecondaryText = LightGrey, - Headers = White - }; - - // Use constructed object for RAII guard - Colour( Code _colourCode ); - Colour( Colour const& other ); - ~Colour(); - - // Use static method for one-shot changes - static void use( Code _colourCode ); - - private: - bool m_moved; - }; - - inline std::ostream& operator << ( std::ostream& os, Colour const& ) { return os; } - -} // end namespace Catch - -// #included from: catch_interfaces_reporter.h -#define TWOBLUECUBES_CATCH_INTERFACES_REPORTER_H_INCLUDED - -#include -#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 ) { - - TestSpec testSpec = config.testSpec(); - if( config.testSpec().hasFilters() ) - Catch::cout() << "Matching test cases:\n"; - else { - Catch::cout() << "All available test cases:\n"; - testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "*" ).testSpec(); - } - - std::size_t matchedTests = 0; - TextAttributes nameAttr, tagsAttr; - nameAttr.setInitialIndent( 2 ).setIndent( 4 ); - tagsAttr.setIndent( 6 ); - - std::vector 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( !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 << '"' << std::endl; - else - Catch::cout() << testCaseInfo.name << std::endl; - } - return matchedTests; - } - - struct TagInfo { - TagInfo() : count ( 0 ) {} - void add( std::string const& spelling ) { - ++count; - spellings.insert( spelling ); - } - std::string all() const { - std::string out; - for( std::set::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(); - } - - std::map tagCounts; - - 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 ); - } - } - - 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(); - } - - inline std::size_t listReporters( Config const& /*config*/ ) { - Catch::cout() << "Available reporters:\n"; - IReporterRegistry::FactoryMap const& factories = getRegistryHub().getReporterRegistry().getFactories(); - IReporterRegistry::FactoryMap::const_iterator itBegin = factories.begin(), itEnd = factories.end(), it; - std::size_t maxNameLen = 0; - for(it = itBegin; it != itEnd; ++it ) - maxNameLen = (std::max)( maxNameLen, it->first.size() ); - - for(it = itBegin; it != itEnd; ++it ) { - Text wrapper( it->second->getDescription(), TextAttributes() - .setInitialIndent( 0 ) - .setIndent( 7+maxNameLen ) - .setWidth( CATCH_CONFIG_CONSOLE_WIDTH - maxNameLen-8 ) ); - Catch::cout() << " " - << it->first - << ':' - << std::string( maxNameLen - it->first.size() + 2, ' ' ) - << wrapper << '\n'; - } - Catch::cout() << std::endl; - return factories.size(); - } - - inline Option 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 - -// #included from: internal/catch_run_context.hpp -#define TWOBLUECUBES_CATCH_RUNNER_IMPL_HPP_INCLUDED - -// #included from: catch_test_case_tracker.hpp -#define TWOBLUECUBES_CATCH_TEST_CASE_TRACKER_HPP_INCLUDED - -#include -#include -#include -#include -#include - -namespace Catch { -namespace TestCaseTracking { - - struct NameAndLocation { - std::string name; - SourceLineInfo location; - - NameAndLocation( std::string const& _name, SourceLineInfo const& _location ) - : name( _name ), - location( _location ) - {} - }; - - struct ITracker : SharedImpl<> { - virtual ~ITracker(); - - // static queries - virtual NameAndLocation const& nameAndLocation() const = 0; - - // dynamic queries - virtual bool isComplete() const = 0; // Successfully completed or failed - virtual bool isSuccessfullyCompleted() const = 0; - virtual bool isOpen() const = 0; // Started but not complete - virtual bool hasChildren() const = 0; - - virtual ITracker& parent() = 0; - - // actions - virtual void close() = 0; // Successfully complete - virtual void fail() = 0; - virtual void markAsNeedingAnotherRun() = 0; - - virtual void addChild( Ptr const& child ) = 0; - virtual ITracker* findChild( NameAndLocation const& nameAndLocation ) = 0; - virtual void openChild() = 0; - - // Debug/ checking - virtual bool isSectionTracker() const = 0; - virtual bool isIndexTracker() const = 0; - }; - - class TrackerContext { - - enum RunState { - NotStarted, - Executing, - CompletedCycle - }; - - Ptr m_rootTracker; - ITracker* m_currentTracker; - RunState m_runState; - - public: - - static TrackerContext& instance() { - static TrackerContext s_instance; - return s_instance; - } - - TrackerContext() - : m_currentTracker( CATCH_NULL ), - m_runState( NotStarted ) - {} - - ITracker& startRun(); - - void endRun() { - m_rootTracker.reset(); - m_currentTracker = CATCH_NULL; - m_runState = NotStarted; - } - - void startCycle() { - m_currentTracker = m_rootTracker.get(); - m_runState = Executing; - } - void completeCycle() { - m_runState = CompletedCycle; - } - - bool completedCycle() const { - return m_runState == CompletedCycle; - } - ITracker& currentTracker() { - return *m_currentTracker; - } - void setCurrentTracker( ITracker* tracker ) { - m_currentTracker = tracker; - } - }; - - class TrackerBase : public ITracker { - protected: - enum CycleState { - NotStarted, - Executing, - ExecutingChildren, - NeedsAnotherRun, - CompletedSuccessfully, - Failed - }; - class TrackerHasName { - 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; - } - }; - typedef std::vector > Children; - NameAndLocation m_nameAndLocation; - TrackerContext& m_ctx; - ITracker* m_parent; - Children m_children; - CycleState m_runState; - public: - TrackerBase( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent ) - : m_nameAndLocation( nameAndLocation ), - m_ctx( ctx ), - m_parent( parent ), - m_runState( NotStarted ) - {} - virtual ~TrackerBase(); - - 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(); - } - - virtual void addChild( Ptr const& child ) CATCH_OVERRIDE { - m_children.push_back( child ); - } - - 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; - } - - virtual void openChild() CATCH_OVERRIDE { - if( m_runState != ExecutingChildren ) { - m_runState = ExecutingChildren; - if( m_parent ) - m_parent->openChild(); - } - } - - virtual bool isSectionTracker() const CATCH_OVERRIDE { return false; } - virtual bool isIndexTracker() const CATCH_OVERRIDE { return false; } - - void open() { - m_runState = Executing; - moveToThis(); - if( m_parent ) - m_parent->openChild(); - } - - virtual void close() CATCH_OVERRIDE { - - // Close any still open children (e.g. generators) - while( &m_ctx.currentTracker() != this ) - m_ctx.currentTracker().close(); - - switch( m_runState ) { - case NotStarted: - case CompletedSuccessfully: - case Failed: - throw std::logic_error( "Illogical state" ); - - case NeedsAnotherRun: - break;; - - case Executing: - m_runState = CompletedSuccessfully; - break; - case ExecutingChildren: - if( m_children.empty() || m_children.back()->isComplete() ) - m_runState = CompletedSuccessfully; - break; - - default: - throw std::logic_error( "Unexpected state" ); - } - moveToParent(); - m_ctx.completeCycle(); - } - virtual void fail() CATCH_OVERRIDE { - m_runState = Failed; - if( m_parent ) - m_parent->markAsNeedingAnotherRun(); - moveToParent(); - m_ctx.completeCycle(); - } - virtual void markAsNeedingAnotherRun() CATCH_OVERRIDE { - m_runState = NeedsAnotherRun; - } - private: - void moveToParent() { - assert( m_parent ); - m_ctx.setCurrentTracker( m_parent ); - } - void moveToThis() { - m_ctx.setCurrentTracker( this ); - } - }; - - class SectionTracker : public TrackerBase { - 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& parentSection = static_cast( *parent ); - addNextFilters( parentSection.m_filters ); - } - } - virtual ~SectionTracker(); - - virtual bool isSectionTracker() const CATCH_OVERRIDE { return true; } - - static SectionTracker& acquire( TrackerContext& ctx, NameAndLocation const& nameAndLocation ) { - SectionTracker* section = CATCH_NULL; - - 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 - std::copy( filters.begin(), filters.end(), std::back_inserter( m_filters ) ); - } - } - void addNextFilters( std::vector const& filters ) { - if( filters.size() > 1 ) - std::copy( filters.begin()+1, filters.end(), std::back_inserter( m_filters ) ); - } - }; - - class IndexTracker : public TrackerBase { - int m_size; - int m_index; - public: - IndexTracker( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent, int size ) - : TrackerBase( nameAndLocation, ctx, parent ), - m_size( size ), - m_index( -1 ) - {} - virtual ~IndexTracker(); - - virtual bool isIndexTracker() const CATCH_OVERRIDE { return true; } - - static IndexTracker& acquire( TrackerContext& ctx, NameAndLocation const& nameAndLocation, int size ) { - IndexTracker* tracker = CATCH_NULL; - - 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 ); - } - - 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; -using TestCaseTracking::TrackerContext; -using TestCaseTracking::SectionTracker; -using TestCaseTracking::IndexTracker; - -} // namespace Catch - -// #included from: catch_fatal_condition.hpp -#define TWOBLUECUBES_CATCH_FATAL_CONDITION_H_INCLUDED - -namespace Catch { - - // Report the error condition - inline void reportFatal( std::string const& message ) { - IContext& context = Catch::getCurrentContext(); - IResultCapture* resultCapture = context.getResultCapture(); - resultCapture->handleFatalErrorCondition( message ); - } - -} // namespace Catch - -#if defined ( CATCH_PLATFORM_WINDOWS ) ///////////////////////////////////////// - -#define NOMINMAX -#define WIN32_LEAN_AND_MEAN -#include -#undef WIN32_LEAN_AND_MEAN -#undef NOMINMAX - -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; - } - - // 32k seems enough for Catch to handle stack overflow, - // but the value was found experimentally, so there is no strong guarantee - FatalConditionHandler():m_isSet(true), m_guaranteeSize(32 * 1024), m_exceptionHandlerHandle(CATCH_NULL) { - // Register as first handler in current chain - m_exceptionHandlerHandle = AddVectoredExceptionHandler(1, handleVectoredException); - // Pass in guarantee size to be filled - SetThreadStackGuarantee(&m_guaranteeSize); - } - - void reset() { - if (m_isSet) { - // Unregister handler and restore the old guarantee - RemoveVectoredExceptionHandler(m_exceptionHandlerHandle); - SetThreadStackGuarantee(&m_guaranteeSize); - m_exceptionHandlerHandle = CATCH_NULL; - m_isSet = false; - } - } - - ~FatalConditionHandler() { - reset(); - } - private: - bool m_isSet; - ULONG m_guaranteeSize; - PVOID m_exceptionHandlerHandle; - }; - -} // namespace Catch - -#else // Not Windows - assumed to be POSIX compatible ////////////////////////// - -#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 // 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; - }; - - /////////////////////////////////////////////////////////////////////////// - - 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_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(); - dynamic_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++; - } - - if( m_reporter->assertionEnded( AssertionStats( result, m_messages, m_totals ) ) ) - m_messages.clear(); - - // Reset working state - m_lastAssertionInfo = AssertionInfo( std::string(), m_lastAssertionInfo.lineInfo, "{Unknown expression after the reported line}" , m_lastAssertionInfo.resultDisposition ); - m_lastResult = result; - } - - 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 handleFatalErrorCondition( std::string const& message ) { - ResultBuilder resultBuilder = makeUnexpectedResultBuilder(); - resultBuilder.setResultType( ResultWas::FatalErrorCondition ); - resultBuilder << message; - resultBuilder.captureExpression(); - - handleUnfinishedSections(); - - // Recreate section for test case (as we will lose the one that was in scope) - TestCaseInfo const& testCaseInfo = m_activeTestCase->getTestCaseInfo(); - SectionInfo testCaseSection( testCaseInfo.lineInfo, testCaseInfo.name, testCaseInfo.description ); - - Counts assertions; - assertions.failed = 1; - SectionStats testCaseSectionStats( testCaseSection, assertions, 0, false ); - m_reporter->sectionEnded( testCaseSectionStats ); - - TestCaseInfo testInfo = m_activeTestCase->getTestCaseInfo(); - - Totals deltaTotals; - deltaTotals.testCases.failed = 1; - m_reporter->testCaseEnded( TestCaseStats( testInfo, - deltaTotals, - 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; - try { - m_lastAssertionInfo = AssertionInfo( "TEST_CASE", testCaseInfo.lineInfo, std::string(), ResultDisposition::Normal ); - - seedRng( *m_config ); - - Timer timer; - timer.start(); - if( m_reporter->getPreferences().shouldRedirectStdOut ) { - StreamRedirect coutRedir( Catch::cout(), redirectedCout ); - StreamRedirect cerrRedir( Catch::cerr(), redirectedCerr ); - invokeActiveTestCase(); - } - else { - invokeActiveTestCase(); - } - duration = timer.getElapsedSeconds(); - } - catch( TestFailureException& ) { - // This just means the test was aborted due to failure - } - catch(...) { - makeUnexpectedResultBuilder().useActiveException(); - } - m_testCaseTracker->close(); - handleUnfinishedSections(); - m_messages.clear(); - - Counts assertions = m_totals.assertions - prevAssertions; - bool missingAssertions = testForMissingAssertions( assertions ); - - if( testCaseInfo.okToFail() ) { - std::swap( assertions.failedButOk, assertions.failed ); - m_totals.assertions.failed -= assertions.failedButOk; - m_totals.assertions.failedButOk += assertions.failedButOk; - } - - SectionStats testCaseSectionStats( testCaseSection, assertions, duration, missingAssertions ); - m_reporter->sectionEnded( testCaseSectionStats ); - } - - void invokeActiveTestCase() { - FatalConditionHandler fatalConditionHandler; // Handle signals - m_activeTestCase->invoke(); - fatalConditionHandler.reset(); - } - - private: - - ResultBuilder makeUnexpectedResultBuilder() const { - return ResultBuilder( m_lastAssertionInfo.macroName.c_str(), - m_lastAssertionInfo.lineInfo, - m_lastAssertionInfo.capturedExpression.c_str(), - m_lastAssertionInfo.resultDisposition ); - } - - void handleUnfinishedSections() { - // If sections ended prematurely due to an exception we stored their - // infos here so we can tear them down outside the unwind process. - for( std::vector::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; - }; - - IResultCapture& getResultCapture() { - if( IResultCapture* capture = getCurrentContext().getResultCapture() ) - return *capture; - else - throw std::logic_error( "No result capture instance" ); - } - -} // end namespace Catch - -// #included from: internal/catch_version.h -#define TWOBLUECUBES_CATCH_VERSION_H_INCLUDED - -namespace Catch { - - // Versioning information - struct Version { - Version( unsigned int _majorVersion, - unsigned int _minorVersion, - unsigned int _patchNumber, - std::string const& _branchName, - unsigned int _buildNumber ); - - unsigned int const majorVersion; - unsigned int const minorVersion; - unsigned int const patchNumber; - - // buildNumber is only used if branchName is not null - std::string const branchName; - unsigned int const buildNumber; - - friend std::ostream& operator << ( std::ostream& os, Version const& version ); - - private: - void operator=( Version const& ); - }; - - extern Version libraryVersion; -} - -#include -#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; - } - - Ptr makeReporter( Ptr const& config ) { - std::vector reporters = config->getReporterNames(); - if( reporters.empty() ) - reporters.push_back( "console" ); - - 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; - } - - 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 -#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; - }; -} - -namespace Catch { - - namespace { - - class RegistryHub : public IRegistryHub, public IMutableRegistryHub { - - RegistryHub( RegistryHub const& ); - void operator=( RegistryHub const& ); - - public: // IRegistryHub - RegistryHub() { - } - virtual IReporterRegistry const& getReporterRegistry() const CATCH_OVERRIDE { - return m_reporterRegistry; - } - virtual ITestCaseRegistry const& getTestCaseRegistry() const CATCH_OVERRIDE { - return m_testCaseRegistry; - } - virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() CATCH_OVERRIDE { - return m_exceptionTranslatorRegistry; - } - - public: // IMutableRegistryHub - virtual void registerReporter( std::string const& name, Ptr 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 ); - } - - private: - TestRegistry m_testCaseRegistry; - ReporterRegistry m_reporterRegistry; - ExceptionTranslatorRegistry m_exceptionTranslatorRegistry; - }; - - // Single, global, instance - inline RegistryHub*& getTheRegistryHub() { - static RegistryHub* theRegistryHub = CATCH_NULL; - if( !theRegistryHub ) - theRegistryHub = new RegistryHub(); - return theRegistryHub; - } - } - - IRegistryHub& getRegistryHub() { - return *getTheRegistryHub(); - } - IMutableRegistryHub& getMutableRegistryHub() { - return *getTheRegistryHub(); - } - void cleanUp() { - delete getTheRegistryHub(); - getTheRegistryHub() = CATCH_NULL; - cleanUpContext(); - } - std::string translateActiveException() { - return getRegistryHub().getExceptionTranslatorRegistry().translateActiveException(); - } - -} // end namespace Catch - -// #included from: catch_notimplemented_exception.hpp -#define TWOBLUECUBES_CATCH_NOTIMPLEMENTED_EXCEPTION_HPP_INCLUDED - -#include - -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; - } -#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 - -namespace Catch { - namespace { - - struct IColourImpl { - virtual ~IColourImpl() {} - virtual void use( Colour::Code _colourCode ) = 0; - }; - - struct NoColourImpl : IColourImpl { - void use( Colour::Code ) {} - - static IColourImpl* instance() { - static NoColourImpl s_instance; - return &s_instance; - } - }; - - } // anon namespace -} // namespace Catch - -#if !defined( CATCH_CONFIG_COLOUR_NONE ) && !defined( CATCH_CONFIG_COLOUR_WINDOWS ) && !defined( CATCH_CONFIG_COLOUR_ANSI ) -# ifdef CATCH_PLATFORM_WINDOWS -# define CATCH_CONFIG_COLOUR_WINDOWS -# else -# define CATCH_CONFIG_COLOUR_ANSI -# endif -#endif - -#if defined ( CATCH_CONFIG_COLOUR_WINDOWS ) ///////////////////////////////////////// - -// #included from: catch_windows_h_proxy.h - -#define TWOBLUECUBES_CATCH_WINDOWS_H_PROXY_H_INCLUDED - -#ifdef CATCH_DEFINES_NOMINMAX -# define NOMINMAX -#endif -#ifdef CATCH_DEFINES_WIN32_LEAN_AND_MEAN -# define WIN32_LEAN_AND_MEAN -#endif - -#ifdef __AFXDLL -#include -#else -#include -#endif - -#ifdef CATCH_DEFINES_NOMINMAX -# undef NOMINMAX -#endif -#ifdef CATCH_DEFINES_WIN32_LEAN_AND_MEAN -# undef WIN32_LEAN_AND_MEAN -#endif - -namespace Catch { -namespace { - - class Win32ColourImpl : public IColourImpl { - public: - Win32ColourImpl() : stdoutHandle( GetStdHandle(STD_OUTPUT_HANDLE) ) - { - CONSOLE_SCREEN_BUFFER_INFO csbiInfo; - GetConsoleScreenBufferInfo( stdoutHandle, &csbiInfo ); - originalForegroundAttributes = csbiInfo.wAttributes & ~( BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_BLUE | BACKGROUND_INTENSITY ); - originalBackgroundAttributes = csbiInfo.wAttributes & ~( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY ); - } - - virtual void use( Colour::Code _colourCode ) { - switch( _colourCode ) { - case Colour::None: return setTextAttribute( originalForegroundAttributes ); - case Colour::White: return setTextAttribute( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE ); - case Colour::Red: return setTextAttribute( FOREGROUND_RED ); - case Colour::Green: return setTextAttribute( FOREGROUND_GREEN ); - case Colour::Blue: return setTextAttribute( FOREGROUND_BLUE ); - case Colour::Cyan: return setTextAttribute( FOREGROUND_BLUE | FOREGROUND_GREEN ); - case Colour::Yellow: return setTextAttribute( FOREGROUND_RED | FOREGROUND_GREEN ); - case Colour::Grey: return setTextAttribute( 0 ); - - case Colour::LightGrey: return setTextAttribute( FOREGROUND_INTENSITY ); - case Colour::BrightRed: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_RED ); - case Colour::BrightGreen: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN ); - case Colour::BrightWhite: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE ); - - case Colour::Bright: throw std::logic_error( "not a colour" ); - } - } - - private: - void setTextAttribute( WORD _textAttribute ) { - SetConsoleTextAttribute( stdoutHandle, _textAttribute | originalBackgroundAttributes ); - } - HANDLE stdoutHandle; - WORD originalForegroundAttributes; - WORD originalBackgroundAttributes; - }; - - IColourImpl* platformColourInstance() { - static Win32ColourImpl s_instance; - - Ptr config = getCurrentContext().getConfig(); - UseColour::YesOrNo colourMode = config - ? config->useColour() - : UseColour::Auto; - if( colourMode == UseColour::Auto ) - colourMode = !isDebuggerActive() - ? UseColour::Yes - : UseColour::No; - return colourMode == UseColour::Yes - ? &s_instance - : NoColourImpl::instance(); - } - -} // end anon namespace -} // end namespace Catch - -#elif defined( CATCH_CONFIG_COLOUR_ANSI ) ////////////////////////////////////// - -#include - -namespace Catch { -namespace { - - // use POSIX/ ANSI console terminal codes - // Thanks to Adam Strzelecki for original contribution - // (http://github.com/nanoant) - // https://github.com/philsquared/Catch/pull/131 - class PosixColourImpl : public IColourImpl { - public: - virtual void use( Colour::Code _colourCode ) { - switch( _colourCode ) { - case Colour::None: - case Colour::White: return setColour( "[0m" ); - case Colour::Red: return setColour( "[0;31m" ); - case Colour::Green: return setColour( "[0;32m" ); - case Colour::Blue: return setColour( "[0;34m" ); - case Colour::Cyan: return setColour( "[0;36m" ); - case Colour::Yellow: return setColour( "[0;33m" ); - case Colour::Grey: return setColour( "[1;30m" ); - - case Colour::LightGrey: return setColour( "[0;37m" ); - case Colour::BrightRed: return setColour( "[1;31m" ); - case Colour::BrightGreen: return setColour( "[1;32m" ); - case Colour::BrightWhite: return setColour( "[1;37m" ); - - case Colour::Bright: throw std::logic_error( "not a colour" ); - } - } - static IColourImpl* instance() { - static PosixColourImpl s_instance; - return &s_instance; - } - - private: - void setColour( const char* _escapeCode ) { - Catch::cout() << '\033' << _escapeCode; - } - }; - - IColourImpl* platformColourInstance() { - Ptr config = getCurrentContext().getConfig(); - UseColour::YesOrNo colourMode = config - ? config->useColour() - : UseColour::Auto; - if( colourMode == UseColour::Auto ) - colourMode = (!isDebuggerActive() && isatty(STDOUT_FILENO) ) - ? UseColour::Yes - : UseColour::No; - return colourMode == UseColour::Yes - ? PosixColourImpl::instance() - : NoColourImpl::instance(); - } - -} // end anon namespace -} // end namespace Catch - -#else // not Windows or ANSI /////////////////////////////////////////////// - -namespace Catch { - - static IColourImpl* platformColourInstance() { return NoColourImpl::instance(); } - -} // end namespace Catch - -#endif // Windows/ ANSI/ None - -namespace Catch { - - Colour::Colour( Code _colourCode ) : m_moved( false ) { use( _colourCode ); } - Colour::Colour( Colour const& _other ) : m_moved( false ) { const_cast( _other ).m_moved = true; } - Colour::~Colour(){ if( !m_moved ) use( None ); } - - void Colour::use( Code _colourCode ) { - static IColourImpl* impl = platformColourInstance(); - impl->use( _colourCode ); - } - -} // end namespace Catch - -// #included from: catch_generators_impl.hpp -#define TWOBLUECUBES_CATCH_GENERATORS_IMPL_HPP_INCLUDED - -#include -#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( std::string const& _macroName, - SourceLineInfo const& _lineInfo, - std::string const& _capturedExpression, - ResultDisposition::Flags _resultDisposition ) - : macroName( _macroName ), - lineInfo( _lineInfo ), - capturedExpression( _capturedExpression ), - resultDisposition( _resultDisposition ) - {} - - AssertionResult::AssertionResult() {} - - AssertionResult::AssertionResult( AssertionInfo const& info, AssertionResultData const& data ) - : m_info( info ), - m_resultData( data ) - {} - - AssertionResult::~AssertionResult() {} - - // Result was a success - bool AssertionResult::succeeded() const { - return Catch::isOk( m_resultData.resultType ); - } - - // Result was a success, or failure is suppressed - bool AssertionResult::isOk() const { - return Catch::isOk( m_resultData.resultType ) || shouldSuppressFailure( m_info.resultDisposition ); - } - - ResultWas::OfType AssertionResult::getResultType() const { - return m_resultData.resultType; - } - - bool AssertionResult::hasExpression() const { - return !m_info.capturedExpression.empty(); - } - - bool AssertionResult::hasMessage() const { - return !m_resultData.message.empty(); - } - - std::string AssertionResult::getExpression() const { - if( isFalseTest( m_info.resultDisposition ) ) - return '!' + m_info.capturedExpression; - else - return m_info.capturedExpression; - } - std::string AssertionResult::getExpressionInMacro() const { - if( m_info.macroName.empty() ) - return m_info.capturedExpression; - else - return m_info.macroName + "( " + m_info.capturedExpression + " )"; - } - - bool AssertionResult::hasExpandedExpression() const { - return hasExpression() && getExpandedExpression() != getExpression(); - } - - std::string AssertionResult::getExpandedExpression() const { - return m_resultData.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 - -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 && !isalnum( tag[0] ); - } - inline void enforceNotReservedTag( std::string const& tag, SourceLineInfo const& _lineInfo ) { - if( isReservedTag( tag ) ) { - { - Colour colourGuard( Colour::Red ); - Catch::cerr() - << "Tag name [" << tag << "] not allowed.\n" - << "Tag names starting with non alpha-numeric characters are reserved\n"; - } - { - Colour colourGuard( Colour::FileName ); - Catch::cerr() << _lineInfo << std::endl; - } - exit(1); - } - } - - TestCase makeTestCase( ITestCase* _testCase, - std::string const& _className, - std::string const& _name, - std::string const& _descOrTags, - SourceLineInfo const& _lineInfo ) - { - bool isHidden( startsWith( _name, "./" ) ); // Legacy support - - // Parse out tags - std::set 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, - std::string const& _branchName, - unsigned int _buildNumber ) - : majorVersion( _majorVersion ), - minorVersion( _minorVersion ), - patchNumber( _patchNumber ), - branchName( _branchName ), - buildNumber( _buildNumber ) - {} - - std::ostream& operator << ( std::ostream& os, Version const& version ) { - os << version.majorVersion << '.' - << version.minorVersion << '.' - << version.patchNumber; - - if( !version.branchName.empty() ) { - os << '-' << version.branchName - << '.' << version.buildNumber; - } - return os; - } - - Version libraryVersion( 1, 7, 0, "", 0 ); - -} - -// #included from: catch_message.hpp -#define TWOBLUECUBES_CATCH_MESSAGE_HPP_INCLUDED - -namespace Catch { - - MessageInfo::MessageInfo( std::string const& _macroName, - SourceLineInfo const& _lineInfo, - ResultWas::OfType _type ) - : macroName( _macroName ), - lineInfo( _lineInfo ), - type( _type ), - sequence( ++globalCount ) - {} - - // This may need protecting if threading support is added - unsigned int MessageInfo::globalCount = 0; - - //////////////////////////////////////////////////////////////////////////// - - ScopedMessage::ScopedMessage( MessageBuilder const& builder ) - : m_info( builder.m_info ) - { - m_info.message = builder.m_stream.str(); - getResultCapture().pushScopedMessage( m_info ); - } - ScopedMessage::ScopedMessage( ScopedMessage const& other ) - : m_info( other.m_info ) - {} - - ScopedMessage::~ScopedMessage() { - getResultCapture().popScopedMessage( m_info ); - } - -} // end namespace Catch - -// #included from: catch_legacy_reporter_adapter.hpp -#define TWOBLUECUBES_CATCH_LEGACY_REPORTER_ADAPTER_HPP_INCLUDED - -// #included from: catch_legacy_reporter_adapter.h -#define TWOBLUECUBES_CATCH_LEGACY_REPORTER_ADAPTER_H_INCLUDED - -namespace Catch -{ - // Deprecated - struct IReporter : IShared { - virtual ~IReporter(); - - virtual bool shouldRedirectStdout() const = 0; - - virtual void StartTesting() = 0; - virtual void EndTesting( Totals const& totals ) = 0; - virtual void StartGroup( std::string const& groupName ) = 0; - virtual void EndGroup( std::string const& groupName, Totals const& totals ) = 0; - virtual void StartTestCase( TestCaseInfo const& testInfo ) = 0; - virtual void EndTestCase( TestCaseInfo const& testInfo, Totals const& totals, std::string const& stdOut, std::string const& stdErr ) = 0; - virtual void StartSection( std::string const& sectionName, std::string const& description ) = 0; - virtual void EndSection( std::string const& sectionName, Counts const& assertions ) = 0; - virtual void NoAssertionsInSection( std::string const& sectionName ) = 0; - virtual void NoAssertionsInTestCase( std::string const& testName ) = 0; - virtual void Aborted() = 0; - virtual void Result( AssertionResult const& result ) = 0; - }; - - class LegacyReporterAdapter : public SharedImpl - { - 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" -#endif - -#ifdef CATCH_PLATFORM_WINDOWS -#else -#include -#endif - -namespace Catch { - - namespace { -#ifdef CATCH_PLATFORM_WINDOWS - uint64_t getCurrentTicks() { - static uint64_t hz=0, hzo=0; - if (!hz) { - QueryPerformanceFrequency( reinterpret_cast( &hz ) ); - QueryPerformanceCounter( reinterpret_cast( &hzo ) ); - } - uint64_t t; - QueryPerformanceCounter( reinterpret_cast( &t ) ); - return ((t-hzo)*1000000)/hz; - } -#else - uint64_t 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 - -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; - } - bool contains( std::string const& s, char infix ) { - return s.find(infix) != std::string::npos; - } - char toLowerCh(char c) { - return static_cast( ::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(); - } - - Section::~Section() { - if( m_sectionIncluded ) { - SectionEndInfo endInfo( m_info, m_assertions, m_timer.getElapsedSeconds() ); - if( std::uncaught_exception() ) - getResultCapture().sectionEndedEarly( endInfo ); - else - getResultCapture().sectionEnded( endInfo ); - } - } - - // This indicates whether the section should be executed or not - Section::operator bool() const { - return m_sectionIncluded; - } - -} // end namespace Catch - -// #included from: catch_debugger.hpp -#define TWOBLUECUBES_CATCH_DEBUGGER_HPP_INCLUDED - -#include - -#ifdef CATCH_PLATFORM_MAC - - #include - #include - #include - #include - #include - - namespace Catch{ - - // The following function is taken directly from the following technical note: - // http://developer.apple.com/library/mac/#qa/qa2004/qa1361.html - - // Returns true if the current process is being debugged (either - // running under the debugger or has a debugger attached post facto). - bool isDebuggerActive(){ - - int mib[4]; - struct kinfo_proc info; - size_t size; - - // Initialize the flags so that, if sysctl fails for some bizarre - // reason, we get a predictable result. - - info.kp_proc.p_flag = 0; - - // Initialize mib, which tells sysctl the info we want, in this case - // we're looking for information about a specific process ID. - - mib[0] = CTL_KERN; - mib[1] = KERN_PROC; - mib[2] = KERN_PROC_PID; - mib[3] = getpid(); - - // Call sysctl. - - size = sizeof(info); - if( sysctl(mib, sizeof(mib) / sizeof(*mib), &info, &size, CATCH_NULL, 0) != 0 ) { - Catch::cerr() << "\n** Call to sysctl failed - unable to determine if debugger is active **\n" << std::endl; - return false; - } - - // We're being debugged if the P_TRACED flag is set. - - return ( (info.kp_proc.p_flag & P_TRACED) != 0 ); - } - } // namespace Catch - -#elif defined(CATCH_PLATFORM_LINUX) - #include - #include - - namespace Catch{ - // The standard POSIX way of detecting a debugger is to attempt to - // ptrace() the process, but this needs to be done from a child and not - // this process itself to still allow attaching to this process later - // if wanted, so is rather heavy. Under Linux we have the PID of the - // "debugger" (which doesn't need to be gdb, of course, it could also - // be strace, for example) in /proc/$PID/status, so just get it from - // there instead. - bool isDebuggerActive(){ - std::ifstream in("/proc/self/status"); - for( std::string line; std::getline(in, line); ) { - static const int PREFIX_LEN = 11; - if( line.compare(0, PREFIX_LEN, "TracerPid:\t") == 0 ) { - // We're traced if the PID is not 0 and no other PID starts - // with 0 digit, so it's enough to check for just a single - // character. - return line.length() > PREFIX_LEN && line[PREFIX_LEN] != '0'; - } - } - - return false; - } - } // namespace Catch -#elif defined(_MSC_VER) - extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent(); - namespace Catch { - bool isDebuggerActive() { - return IsDebuggerPresent() != 0; - } - } -#elif defined(__MINGW32__) - extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent(); - namespace Catch { - bool isDebuggerActive() { - return IsDebuggerPresent() != 0; - } - } -#else - namespace Catch { - inline bool isDebuggerActive() { return false; } - } -#endif // Platform - -#ifdef CATCH_PLATFORM_WINDOWS - extern "C" __declspec(dllimport) void __stdcall OutputDebugStringA( const char* ); - namespace Catch { - void writeToDebugConsole( std::string const& text ) { - ::OutputDebugStringA( text.c_str() ); - } - } -#else - namespace Catch { - void writeToDebugConsole( std::string const& text ) { - // !TBD: Need a version for Mac/ XCode and other IDEs - Catch::cout() << text; - } - } -#endif // Platform - -// #included from: catch_tostring.hpp -#define TWOBLUECUBES_CATCH_TOSTRING_HPP_INCLUDED - -namespace Catch { - -namespace Detail { - - const std::string unprintableString = "{?}"; - - namespace { - const int hexThreshold = 255; - - struct Endianness { - enum Arch { Big, Little }; - - static Arch which() { - union _{ - int asInt; - char asChar[sizeof (int)]; - } u; - - u.asInt = 1; - return ( u.asChar[sizeof(int)-1] == 1 ) ? Big : Little; - } - }; - } - - std::string rawMemoryToString( const void *object, std::size_t size ) - { - // Reverse order for little endian architectures - int i = 0, end = static_cast( size ), inc = 1; - if( Endianness::which() == Endianness::Little ) { - i = end-1; - end = inc = -1; - } - - unsigned char const *bytes = static_cast(object); - std::ostringstream os; - os << "0x" << std::setfill('0') << std::hex; - for( ; i != end; i += inc ) - os << std::setw(2) << static_cast(bytes[i]); - return os.str(); - } -} - -std::string toString( std::string const& value ) { - std::string s = value; - if( getCurrentContext().getConfig()->showInvisibles() ) { - for(size_t i = 0; i < s.size(); ++i ) { - std::string subs; - switch( s[i] ) { - case '\n': subs = "\\n"; break; - case '\t': subs = "\\t"; break; - default: break; - } - if( !subs.empty() ) { - s = s.substr( 0, i ) + subs + s.substr( i+1 ); - ++i; - } - } - } - return '"' + s + '"'; -} -std::string toString( std::wstring const& value ) { - - std::string 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 ); -} - -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 - -#ifdef __OBJC__ - std::string toString( NSString const * const& nsstring ) { - if( !nsstring ) - return "nil"; - return "@" + toString([nsstring UTF8String]); - } - std::string toString( NSString * CATCH_ARC_STRONG const& nsstring ) { - if( !nsstring ) - return "nil"; - return "@" + toString([nsstring UTF8String]); - } - std::string toString( NSObject* const& nsObject ) { - return toString( [nsObject description] ); - } -#endif - -} // end namespace Catch - -// #included from: catch_result_builder.hpp -#define TWOBLUECUBES_CATCH_RESULT_BUILDER_HPP_INCLUDED - -namespace Catch { - - std::string capturedExpressionWithSecondArgument( std::string const& capturedExpression, std::string const& secondArg ) { - return secondArg.empty() || secondArg == "\"\"" - ? capturedExpression - : capturedExpression + ", " + secondArg; - } - ResultBuilder::ResultBuilder( char const* macroName, - SourceLineInfo const& lineInfo, - char const* capturedExpression, - ResultDisposition::Flags resultDisposition, - char const* secondArg ) - : m_assertionInfo( macroName, lineInfo, capturedExpressionWithSecondArgument( capturedExpression, secondArg ), resultDisposition ), - m_shouldDebugBreak( false ), - m_shouldThrow( false ) - {} - - ResultBuilder& ResultBuilder::setResultType( ResultWas::OfType result ) { - m_data.resultType = result; - return *this; - } - ResultBuilder& ResultBuilder::setResultType( bool result ) { - m_data.resultType = result ? ResultWas::Ok : ResultWas::ExpressionFailed; - return *this; - } - - void ResultBuilder::endExpression( DecomposedExpression const& expr ) { - AssertionResult result = build( expr ); - handleResult( result ); - } - - void ResultBuilder::useActiveException( ResultDisposition::Flags resultDisposition ) { - m_assertionInfo.resultDisposition = resultDisposition; - m_stream.oss << Catch::translateActiveException(); - captureResult( ResultWas::ThrewException ); - } - - void ResultBuilder::captureResult( ResultWas::OfType resultType ) { - setResultType( resultType ); - captureExpression(); - } - - void ResultBuilder::captureExpectedException( std::string const& expectedMessage ) { - if( expectedMessage.empty() ) - captureExpectedException( Matchers::Impl::Generic::AllOf() ); - else - captureExpectedException( Matchers::Equals( expectedMessage ) ); - } - - void ResultBuilder::captureExpectedException( Matchers::Impl::Matcher const& matcher ) { - - assert( !isFalseTest( m_assertionInfo.resultDisposition ) ); - AssertionResultData data = m_data; - data.resultType = ResultWas::Ok; - data.reconstructedExpression = m_assertionInfo.capturedExpression; - - std::string actualMessage = Catch::translateActiveException(); - if( !matcher.match( actualMessage ) ) { - data.resultType = ResultWas::ExpressionFailed; - data.reconstructedExpression = actualMessage; - } - AssertionResult result( m_assertionInfo, data ); - handleResult( result ); - } - - void ResultBuilder::captureExpression() { - AssertionResult result = build(); - handleResult( result ); - } - - void ResultBuilder::handleResult( AssertionResult const& result ) - { - getResultCapture().assertionEnded( result ); - - if( !result.isOk() ) { - if( getCurrentContext().getConfig()->shouldDebugBreak() ) - m_shouldDebugBreak = true; - if( getCurrentContext().getRunner()->aborting() || (m_assertionInfo.resultDisposition & ResultDisposition::Normal) ) - m_shouldThrow = true; - } - } - - void ResultBuilder::react() { - if( m_shouldThrow ) - throw Catch::TestFailureException(); - } - - bool ResultBuilder::shouldDebugBreak() const { return m_shouldDebugBreak; } - bool ResultBuilder::allowThrows() const { return getCurrentContext().getConfig()->allowThrows(); } - - AssertionResult ResultBuilder::build() const - { - 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; - - // Flip bool results if FalseTest flag is set - if( isFalseTest( m_assertionInfo.resultDisposition ) ) { - data.negate( expr.isBinaryExpression() ); - } - - 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 = m_assertionInfo.capturedExpression; - } - -} // end namespace Catch - -// #included from: catch_tag_alias_registry.hpp -#define TWOBLUECUBES_CATCH_TAG_ALIAS_REGISTRY_HPP_INCLUDED - -// #included from: catch_tag_alias_registry.h -#define TWOBLUECUBES_CATCH_TAG_ALIAS_REGISTRY_H_INCLUDED - -#include - -namespace Catch { - - class TagAliasRegistry : public ITagAliasRegistry { - public: - virtual ~TagAliasRegistry(); - virtual Option find( std::string const& alias ) const; - virtual std::string expandAliases( std::string const& unexpandedTestSpec ) const; - void add( char const* alias, char const* tag, SourceLineInfo const& lineInfo ); - static TagAliasRegistry& get(); - - private: - std::map m_registry; - }; - -} // end namespace Catch - -#include -#include - -namespace Catch { - - 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; - } - - void TagAliasRegistry::add( char const* alias, char const* tag, SourceLineInfo const& lineInfo ) { - - if( !startsWith( alias, "[@" ) || !endsWith( alias, ']' ) ) { - std::ostringstream oss; - oss << "error: tag alias, \"" << alias << "\" is not of the form [@alias name].\n" << lineInfo; - throw std::domain_error( oss.str().c_str() ); - } - if( !m_registry.insert( std::make_pair( alias, TagAlias( tag, lineInfo ) ) ).second ) { - std::ostringstream oss; - oss << "error: tag alias, \"" << alias << "\" already registered.\n" - << "\tFirst seen at " << find(alias)->lineInfo << '\n' - << "\tRedefined at " << lineInfo; - throw std::domain_error( oss.str().c_str() ); - } - } - - TagAliasRegistry& TagAliasRegistry::get() { - static TagAliasRegistry instance; - return instance; - - } - - ITagAliasRegistry::~ITagAliasRegistry() {} - ITagAliasRegistry const& ITagAliasRegistry::get() { return TagAliasRegistry::get(); } - - RegistrarForTagAliases::RegistrarForTagAliases( char const* alias, char const* tag, SourceLineInfo const& lineInfo ) { - try { - TagAliasRegistry::get().add( alias, tag, lineInfo ); - } - catch( std::exception& ex ) { - Colour colourGuard( Colour::Red ); - Catch::cerr() << ex.what() << std::endl; - exit(1); - } - } - -} // end namespace Catch - -// #included from: ../reporters/catch_reporter_multi.hpp -#define TWOBLUECUBES_CATCH_REPORTER_MULTI_HPP_INCLUDED - -namespace Catch { - -class MultipleReporters : public SharedImpl { - typedef std::vector > Reporters; - Reporters m_reporters; - -public: - void add( Ptr const& reporter ) { - m_reporters.push_back( reporter ); - } - -public: // IStreamingReporter - - virtual ReporterPreferences getPreferences() const CATCH_OVERRIDE { - return m_reporters[0]->getPreferences(); - } - - virtual void noMatchingTestCases( std::string const& spec ) CATCH_OVERRIDE { - for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); - it != itEnd; - ++it ) - (*it)->noMatchingTestCases( spec ); - } - - virtual void testRunStarting( TestRunInfo const& testRunInfo ) CATCH_OVERRIDE { - for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); - it != itEnd; - ++it ) - (*it)->testRunStarting( testRunInfo ); - } - - virtual void testGroupStarting( GroupInfo const& groupInfo ) CATCH_OVERRIDE { - for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); - it != itEnd; - ++it ) - (*it)->testGroupStarting( groupInfo ); - } - - virtual void testCaseStarting( TestCaseInfo const& testInfo ) CATCH_OVERRIDE { - for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); - it != itEnd; - ++it ) - (*it)->testCaseStarting( testInfo ); - } - - virtual void sectionStarting( SectionInfo const& sectionInfo ) CATCH_OVERRIDE { - for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); - it != itEnd; - ++it ) - (*it)->sectionStarting( sectionInfo ); - } - - virtual void assertionStarting( AssertionInfo const& assertionInfo ) CATCH_OVERRIDE { - for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); - it != itEnd; - ++it ) - (*it)->assertionStarting( assertionInfo ); - } - - // The return value indicates if the messages buffer should be cleared: - virtual bool assertionEnded( AssertionStats const& assertionStats ) CATCH_OVERRIDE { - bool clearBuffer = false; - for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); - it != itEnd; - ++it ) - clearBuffer |= (*it)->assertionEnded( assertionStats ); - return clearBuffer; - } - - virtual void sectionEnded( SectionStats const& sectionStats ) CATCH_OVERRIDE { - for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); - it != itEnd; - ++it ) - (*it)->sectionEnded( sectionStats ); - } - - virtual void testCaseEnded( TestCaseStats const& testCaseStats ) CATCH_OVERRIDE { - for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); - it != itEnd; - ++it ) - (*it)->testCaseEnded( testCaseStats ); - } - - virtual void testGroupEnded( TestGroupStats const& testGroupStats ) CATCH_OVERRIDE { - for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); - it != itEnd; - ++it ) - (*it)->testGroupEnded( testGroupStats ); - } - - virtual void testRunEnded( TestRunStats const& testRunStats ) CATCH_OVERRIDE { - for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); - it != itEnd; - ++it ) - (*it)->testRunEnded( testRunStats ); - } - - virtual void skipTest( TestCaseInfo const& testInfo ) CATCH_OVERRIDE { - for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); - it != itEnd; - ++it ) - (*it)->skipTest( testInfo ); - } - - 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; - - return resultingReporter; -} - -} // end namespace Catch - -// #included from: ../reporters/catch_reporter_xml.hpp -#define TWOBLUECUBES_CATCH_REPORTER_XML_HPP_INCLUDED - -// #included from: catch_reporter_bases.hpp -#define TWOBLUECUBES_CATCH_REPORTER_BASES_HPP_INCLUDED - -#include - -namespace Catch { - - 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; - } - bool operator == ( Ptr const& other ) const { - return operator==( *other ); - } - - SectionStats stats; - typedef std::vector > ChildSections; - typedef std::vector Assertions; - ChildSections childSections; - Assertions assertions; - std::string stdOut; - std::string stdErr; - }; - - struct BySectionInfo { - BySectionInfo( SectionInfo const& other ) : m_other( other ) {} - BySectionInfo( BySectionInfo const& other ) : m_other( other.m_other ) {} - bool operator() ( Ptr const& node ) const { - return node->stats.sectionInfo.lineInfo == m_other.lineInfo; - } - private: - void operator=( BySectionInfo const& ); - SectionInfo const& m_other; - }; - - typedef Node TestCaseNode; - typedef Node TestGroupNode; - typedef Node TestRunNode; - - CumulativeReporterBase( ReporterConfig const& _config ) - : m_config( _config.fullConfig() ), - stream( _config.stream() ) - { - m_reporterPrefs.shouldRedirectStdOut = false; - } - ~CumulativeReporterBase(); - - virtual ReporterPreferences getPreferences() const CATCH_OVERRIDE { - return m_reporterPrefs; - } - - virtual void testRunStarting( TestRunInfo const& ) CATCH_OVERRIDE {} - virtual void testGroupStarting( GroupInfo const& ) CATCH_OVERRIDE {} - - virtual void testCaseStarting( TestCaseInfo const& ) CATCH_OVERRIDE {} - - virtual void sectionStarting( SectionInfo const& sectionInfo ) CATCH_OVERRIDE { - SectionStats incompleteStats( sectionInfo, Counts(), 0, false ); - Ptr 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 ) { - memset( line, C, CATCH_CONFIG_CONSOLE_WIDTH-1 ); - line[CATCH_CONFIG_CONSOLE_WIDTH-1] = 0; - } - return line; - } - - struct TestEventListenerBase : StreamingReporterBase { - TestEventListenerBase( ReporterConfig const& _config ) - : StreamingReporterBase( _config ) - {} - - virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE {} - virtual bool assertionEnded( AssertionStats const& ) CATCH_OVERRIDE { - return false; - } - }; - -} // end namespace Catch - -// #included from: ../internal/catch_reporter_registrars.hpp -#define TWOBLUECUBES_CATCH_REPORTER_REGISTRARS_HPP_INCLUDED - -namespace Catch { - - template - class LegacyReporterRegistrar { - - class ReporterFactory : public IReporterFactory { - virtual IStreamingReporter* create( ReporterConfig const& config ) const { - return new LegacyReporterAdapter( new T( config ) ); - } - - virtual std::string getDescription() const { - return T::getDescription(); - } - }; - - public: - - LegacyReporterRegistrar( std::string const& name ) { - getMutableRegistryHub().registerReporter( name, new ReporterFactory() ); - } - }; - - template - 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() ); - } - }; -} - -#define INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) \ - namespace{ Catch::LegacyReporterRegistrar catch_internal_RegistrarFor##reporterType( name ); } - -#define INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType ) \ - namespace{ Catch::ReporterRegistrar catch_internal_RegistrarFor##reporterType( name ); } - -#define INTERNAL_CATCH_REGISTER_LISTENER( listenerType ) \ - namespace{ Catch::ListenerRegistrar catch_internal_RegistrarFor##listenerType; } - -// #included from: ../internal/catch_xmlwriter.hpp -#define TWOBLUECUBES_CATCH_XMLWRITER_HPP_INCLUDED - -#include -#include -#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 ) - {} - - 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' ) - 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; - ForWhat m_forWhat; - }; - - class XmlWriter { - public: - - class ScopedElement { - public: - ScopedElement( XmlWriter* writer ) - : m_writer( writer ) - {} - - ScopedElement( ScopedElement const& other ) - : m_writer( other.m_writer ){ - other.m_writer = CATCH_NULL; - } - - ~ScopedElement() { - if( m_writer ) - m_writer->endElement(); - } - - ScopedElement& writeText( std::string const& text, bool indent = true ) { - m_writer->writeText( text, indent ); - return *this; - } - - template - ScopedElement& writeAttribute( std::string const& name, T const& attribute ) { - m_writer->writeAttribute( name, attribute ); - return *this; - } - - private: - mutable XmlWriter* m_writer; - }; - - XmlWriter() - : m_tagIsOpen( false ), - m_needsNewline( false ), - m_os( &Catch::cout() ) - { - // We encode control characters, which requires - // XML 1.1 - // see http://stackoverflow.com/questions/404107/why-are-control-characters-illegal-in-xml-1-0 - *m_os << "\n"; - } - - XmlWriter( std::ostream& os ) - : m_tagIsOpen( false ), - m_needsNewline( false ), - m_os( &os ) - { - *m_os << "\n"; - } - - ~XmlWriter() { - while( !m_tags.empty() ) - endElement(); - } - - XmlWriter& startElement( std::string const& name ) { - ensureTagClosed(); - newlineIfNecessary(); - stream() << m_indent << '<' << name; - m_tags.push_back( name ); - m_indent += " "; - m_tagIsOpen = true; - return *this; - } - - ScopedElement scopedElement( std::string const& name ) { - ScopedElement scoped( this ); - startElement( name ); - return scoped; - } - - XmlWriter& endElement() { - newlineIfNecessary(); - m_indent = m_indent.substr( 0, m_indent.size()-2 ); - if( m_tagIsOpen ) { - stream() << "/>\n"; - m_tagIsOpen = false; - } - else { - stream() << m_indent << "\n"; - } - m_tags.pop_back(); - return *this; - } - - XmlWriter& writeAttribute( std::string const& name, std::string const& attribute ) { - if( !name.empty() && !attribute.empty() ) - stream() << ' ' << name << "=\"" << XmlEncode( attribute, XmlEncode::ForAttributes ) << '"'; - return *this; - } - - XmlWriter& writeAttribute( std::string const& name, bool attribute ) { - stream() << ' ' << name << "=\"" << ( attribute ? "true" : "false" ) << '"'; - return *this; - } - - template - XmlWriter& writeAttribute( std::string const& name, T const& attribute ) { - std::ostringstream oss; - oss << attribute; - return writeAttribute( name, oss.str() ); - } - - XmlWriter& writeText( std::string const& text, bool indent = true ) { - if( !text.empty() ){ - bool tagWasOpen = m_tagIsOpen; - ensureTagClosed(); - if( tagWasOpen && indent ) - stream() << m_indent; - stream() << XmlEncode( text ); - m_needsNewline = true; - } - return *this; - } - - XmlWriter& writeComment( std::string const& text ) { - ensureTagClosed(); - stream() << m_indent << ""; - m_needsNewline = true; - return *this; - } - - XmlWriter& writeBlankLine() { - ensureTagClosed(); - stream() << '\n'; - return *this; - } - - void setStream( std::ostream& os ) { - m_os = &os; - } - - private: - XmlWriter( XmlWriter const& ); - void operator=( XmlWriter const& ); - - std::ostream& stream() { - return *m_os; - } - - void ensureTagClosed() { - if( m_tagIsOpen ) { - stream() << ">\n"; - m_tagIsOpen = false; - } - } - - void newlineIfNecessary() { - if( m_needsNewline ) { - stream() << '\n'; - m_needsNewline = false; - } - } - - bool m_tagIsOpen; - bool m_needsNewline; - std::vector m_tags; - std::string m_indent; - std::ostream* m_os; - }; - -} -// #included from: catch_reenable_warnings.h - -#define TWOBLUECUBES_CATCH_REENABLE_WARNINGS_H_INCLUDED - -#ifdef __clang__ -# ifdef __ICC // icpc defines the __clang__ macro -# pragma warning(pop) -# else -# pragma clang diagnostic pop -# endif -#elif defined __GNUC__ -# pragma GCC diagnostic pop -#endif - - -namespace Catch { - class XmlReporter : public StreamingReporterBase { - public: - XmlReporter( ReporterConfig const& _config ) - : StreamingReporterBase( _config ), - m_xml(_config.stream()), - m_sectionDepth( 0 ) - { - m_reporterPrefs.shouldRedirectStdOut = true; - } - - virtual ~XmlReporter() CATCH_OVERRIDE; - - static std::string getDescription() { - return "Reports test results as an XML document"; - } - - public: // StreamingReporterBase - - virtual void noMatchingTestCases( std::string const& s ) CATCH_OVERRIDE { - StreamingReporterBase::noMatchingTestCases( s ); - } - - virtual void testRunStarting( TestRunInfo const& testInfo ) CATCH_OVERRIDE { - StreamingReporterBase::testRunStarting( testInfo ); - m_xml.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", testInfo.name ); - - if ( m_config->showDurations() == ShowDurations::Always ) - m_testCaseTimer.start(); - } - - virtual void sectionStarting( SectionInfo const& sectionInfo ) CATCH_OVERRIDE { - StreamingReporterBase::sectionStarting( sectionInfo ); - if( m_sectionDepth++ > 0 ) { - m_xml.startElement( "Section" ) - .writeAttribute( "name", trim( sectionInfo.name ) ) - .writeAttribute( "description", sectionInfo.description ); - } - } - - virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE { } - - virtual bool assertionEnded( AssertionStats const& assertionStats ) CATCH_OVERRIDE { - const AssertionResult& assertionResult = assertionStats.assertionResult; - - // Print any info messages in tags. - 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 ) { - m_xml.scopedElement( "Info" ) - .writeText( it->message ); - } else if ( it->type == ResultWas::Warning ) { - m_xml.scopedElement( "Warning" ) - .writeText( it->message ); - } - } - } - - // Drop out if result was successful but we're not printing them. - if( !m_config->includeSuccessfulResults() && isOk(assertionResult.getResultType()) ) - return true; - - // Print the expression if there is one. - if( assertionResult.hasExpression() ) { - m_xml.startElement( "Expression" ) - .writeAttribute( "success", assertionResult.succeeded() ) - .writeAttribute( "type", assertionResult.getTestMacroName() ) - .writeAttribute( "filename", assertionResult.getSourceInfo().file ) - .writeAttribute( "line", assertionResult.getSourceInfo().line ); - - m_xml.scopedElement( "Original" ) - .writeText( assertionResult.getExpression() ); - m_xml.scopedElement( "Expanded" ) - .writeText( assertionResult.getExpandedExpression() ); - } - - // And... Print a result applicable to each result type. - switch( assertionResult.getResultType() ) { - case ResultWas::ThrewException: - m_xml.scopedElement( "Exception" ) - .writeAttribute( "filename", assertionResult.getSourceInfo().file ) - .writeAttribute( "line", assertionResult.getSourceInfo().line ) - .writeText( assertionResult.getMessage() ); - break; - case ResultWas::FatalErrorCondition: - m_xml.scopedElement( "FatalErrorCondition" ) - .writeAttribute( "filename", assertionResult.getSourceInfo().file ) - .writeAttribute( "line", assertionResult.getSourceInfo().line ) - .writeText( assertionResult.getMessage() ); - break; - case ResultWas::Info: - m_xml.scopedElement( "Info" ) - .writeText( assertionResult.getMessage() ); - break; - case ResultWas::Warning: - // Warning will already have been written - break; - case ResultWas::ExplicitFailure: - m_xml.scopedElement( "Failure" ) - .writeText( assertionResult.getMessage() ); - break; - default: - break; - } - - if( assertionResult.hasExpression() ) - m_xml.endElement(); - - return true; - } - - virtual void sectionEnded( SectionStats const& sectionStats ) CATCH_OVERRIDE { - StreamingReporterBase::sectionEnded( sectionStats ); - if( --m_sectionDepth > 0 ) { - XmlWriter::ScopedElement e = m_xml.scopedElement( "OverallResults" ); - e.writeAttribute( "successes", sectionStats.assertions.passed ); - e.writeAttribute( "failures", sectionStats.assertions.failed ); - e.writeAttribute( "expectedFailures", sectionStats.assertions.failedButOk ); - - if ( m_config->showDurations() == ShowDurations::Always ) - e.writeAttribute( "durationInSeconds", sectionStats.durationInSeconds ); - - m_xml.endElement(); - } - } - - virtual void testCaseEnded( TestCaseStats const& testCaseStats ) CATCH_OVERRIDE { - StreamingReporterBase::testCaseEnded( testCaseStats ); - XmlWriter::ScopedElement e = m_xml.scopedElement( "OverallResult" ); - e.writeAttribute( "success", testCaseStats.totals.assertions.allOk() ); - - if ( m_config->showDurations() == ShowDurations::Always ) - e.writeAttribute( "durationInSeconds", m_testCaseTimer.getElapsedSeconds() ); - - m_xml.endElement(); - } - - virtual void testGroupEnded( TestGroupStats const& testGroupStats ) CATCH_OVERRIDE { - StreamingReporterBase::testGroupEnded( testGroupStats ); - // TODO: Check testGroupStats.aborting and act accordingly. - m_xml.scopedElement( "OverallResults" ) - .writeAttribute( "successes", testGroupStats.totals.assertions.passed ) - .writeAttribute( "failures", testGroupStats.totals.assertions.failed ) - .writeAttribute( "expectedFailures", testGroupStats.totals.assertions.failedButOk ); - m_xml.endElement(); - } - - virtual void testRunEnded( TestRunStats const& testRunStats ) CATCH_OVERRIDE { - StreamingReporterBase::testRunEnded( testRunStats ); - m_xml.scopedElement( "OverallResults" ) - .writeAttribute( "successes", testRunStats.totals.assertions.passed ) - .writeAttribute( "failures", testRunStats.totals.assertions.failed ) - .writeAttribute( "expectedFailures", testRunStats.totals.assertions.failedButOk ); - m_xml.endElement(); - } - - private: - Timer m_testCaseTimer; - XmlWriter m_xml; - int m_sectionDepth; - }; - - INTERNAL_CATCH_REGISTER_REPORTER( "xml", XmlReporter ) - -} // end namespace Catch - -// #included from: ../reporters/catch_reporter_junit.hpp -#define TWOBLUECUBES_CATCH_REPORTER_JUNIT_HPP_INCLUDED - -#include - -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 CATCH_PLATFORM_WINDOWS - 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 CATCH_PLATFORM_WINDOWS - 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() ) - { - m_reporterPrefs.shouldRedirectStdOut = true; - } - - virtual ~JunitReporter() CATCH_OVERRIDE; - - static std::string getDescription() { - return "Reports test results in an XML format that looks like Ant's junitreport target"; - } - - virtual void noMatchingTestCases( std::string const& /*spec*/ ) CATCH_OVERRIDE {} - - virtual void testRunStarting( TestRunInfo const& runInfo ) CATCH_OVERRIDE { - CumulativeReporterBase::testRunStarting( runInfo ); - xml.startElement( "testsuites" ); - } - - virtual void testGroupStarting( GroupInfo const& groupInfo ) CATCH_OVERRIDE { - suiteTimer.start(); - stdOutForSuite.str(""); - stdErrForSuite.str(""); - unexpectedExceptions = 0; - CumulativeReporterBase::testGroupStarting( groupInfo ); - } - - virtual bool assertionEnded( AssertionStats const& assertionStats ) CATCH_OVERRIDE { - if( assertionStats.assertionResult.getResultType() == ResultWas::ThrewException ) - unexpectedExceptions++; - return CumulativeReporterBase::assertionEnded( assertionStats ); - } - - virtual void testCaseEnded( TestCaseStats const& testCaseStats ) CATCH_OVERRIDE { - stdOutForSuite << testCaseStats.stdOut; - stdErrForSuite << testCaseStats.stdErr; - CumulativeReporterBase::testCaseEnded( testCaseStats ); - } - - virtual void testGroupEnded( TestGroupStats const& testGroupStats ) CATCH_OVERRIDE { - double suiteTime = suiteTimer.getElapsedSeconds(); - CumulativeReporterBase::testGroupEnded( testGroupStats ); - writeGroup( *m_testGroups.back(), suiteTime ); - } - - virtual void testRunEndedCumulative() CATCH_OVERRIDE { - xml.endElement(); - } - - void writeGroup( TestGroupNode const& groupNode, double suiteTime ) { - XmlWriter::ScopedElement e = xml.scopedElement( "testsuite" ); - TestGroupStats const& stats = groupNode.value; - xml.writeAttribute( "name", stats.groupInfo.name ); - xml.writeAttribute( "errors", unexpectedExceptions ); - xml.writeAttribute( "failures", stats.totals.assertions.failed-unexpectedExceptions ); - xml.writeAttribute( "tests", stats.totals.assertions.total() ); - xml.writeAttribute( "hostname", "tbd" ); // !TBD - if( m_config->showDurations() == ShowDurations::Never ) - xml.writeAttribute( "time", "" ); - else - xml.writeAttribute( "time", suiteTime ); - xml.writeAttribute( "timestamp", 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; - }; - - INTERNAL_CATCH_REGISTER_REPORTER( "junit", JunitReporter ) - -} // end namespace Catch - -// #included from: ../reporters/catch_reporter_console.hpp -#define TWOBLUECUBES_CATCH_REPORTER_CONSOLE_HPP_INCLUDED - -namespace Catch { - - struct ConsoleReporter : StreamingReporterBase { - ConsoleReporter( ReporterConfig const& _config ) - : StreamingReporterBase( _config ), - m_headerPrinted( false ) - {} - - virtual ~ConsoleReporter() CATCH_OVERRIDE; - static std::string getDescription() { - return "Reports test results as plain lines of text"; - } - - virtual void noMatchingTestCases( std::string const& spec ) CATCH_OVERRIDE { - stream << "No test cases matched '" << spec << '\'' << std::endl; - } - - virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE { - } - - virtual bool assertionEnded( AssertionStats const& _assertionStats ) CATCH_OVERRIDE { - AssertionResult const& result = _assertionStats.assertionResult; - - bool printInfoMessages = true; - - // Drop out if result was successful and we're not printing those - if( !m_config->includeSuccessfulResults() && result.isOk() ) { - if( result.getResultType() != ResultWas::Warning ) - return false; - printInfoMessages = false; - } - - lazyPrint(); - - AssertionPrinter printer( stream, _assertionStats, printInfoMessages ); - printer.print(); - stream << std::endl; - return true; - } - - virtual void sectionStarting( SectionInfo const& _sectionInfo ) CATCH_OVERRIDE { - m_headerPrinted = false; - StreamingReporterBase::sectionStarting( _sectionInfo ); - } - virtual void sectionEnded( SectionStats const& _sectionStats ) CATCH_OVERRIDE { - if( _sectionStats.missingAssertions ) { - lazyPrint(); - Colour colour( Colour::ResultError ); - if( m_sectionStack.size() > 1 ) - stream << "\nNo assertions in section"; - else - stream << "\nNo assertions in test case"; - stream << " '" << _sectionStats.sectionInfo.name << "'\n" << std::endl; - } - if( m_headerPrinted ) { - if( m_config->showDurations() == ShowDurations::Always ) - stream << "Completed in " << _sectionStats.durationInSeconds << 's' << std::endl; - m_headerPrinted = false; - } - else { - if( m_config->showDurations() == ShowDurations::Always ) - stream << _sectionStats.sectionInfo.name << " completed in " << _sectionStats.durationInSeconds << 's' << std::endl; - } - StreamingReporterBase::sectionEnded( _sectionStats ); - } - - virtual void testCaseEnded( TestCaseStats const& _testCaseStats ) CATCH_OVERRIDE { - StreamingReporterBase::testCaseEnded( _testCaseStats ); - m_headerPrinted = false; - } - virtual void testGroupEnded( TestGroupStats const& _testGroupStats ) CATCH_OVERRIDE { - if( currentGroupInfo.used ) { - printSummaryDivider(); - stream << "Summary for group '" << _testGroupStats.groupInfo.name << "':\n"; - printTotals( _testGroupStats.totals ); - stream << '\n' << std::endl; - } - StreamingReporterBase::testGroupEnded( _testGroupStats ); - } - virtual void testRunEnded( TestRunStats const& _testRunStats ) CATCH_OVERRIDE { - printTotalsDivider( _testRunStats.totals ); - printTotals( _testRunStats.totals ); - stream << std::endl; - StreamingReporterBase::testRunEnded( _testRunStats ); - } - - private: - - class AssertionPrinter { - void operator= ( AssertionPrinter const& ); - public: - AssertionPrinter( std::ostream& _stream, AssertionStats const& _stats, bool _printInfoMessages ) - : stream( _stream ), - stats( _stats ), - result( _stats.assertionResult ), - colour( Colour::None ), - message( result.getMessage() ), - messages( _stats.infoMessages ), - printInfoMessages( _printInfoMessages ) - { - switch( result.getResultType() ) { - case ResultWas::Ok: - colour = Colour::Success; - passOrFail = "PASSED"; - //if( result.hasMessage() ) - if( _stats.infoMessages.size() == 1 ) - messageLabel = "with message"; - if( _stats.infoMessages.size() > 1 ) - messageLabel = "with messages"; - break; - case ResultWas::ExpressionFailed: - if( result.isOk() ) { - colour = Colour::Success; - passOrFail = "FAILED - but was ok"; - } - else { - colour = Colour::Error; - passOrFail = "FAILED"; - } - if( _stats.infoMessages.size() == 1 ) - messageLabel = "with message"; - if( _stats.infoMessages.size() > 1 ) - messageLabel = "with messages"; - break; - case ResultWas::ThrewException: - colour = Colour::Error; - passOrFail = "FAILED"; - messageLabel = "due to unexpected exception with message"; - break; - case ResultWas::FatalErrorCondition: - colour = Colour::Error; - passOrFail = "FAILED"; - messageLabel = "due to a fatal error condition"; - break; - case ResultWas::DidntThrowException: - colour = Colour::Error; - passOrFail = "FAILED"; - messageLabel = "because no exception was thrown where one was expected"; - break; - case ResultWas::Info: - messageLabel = "info"; - break; - case ResultWas::Warning: - messageLabel = "warning"; - break; - case ResultWas::ExplicitFailure: - passOrFail = "FAILED"; - colour = Colour::Error; - if( _stats.infoMessages.size() == 1 ) - messageLabel = "explicitly with message"; - if( _stats.infoMessages.size() > 1 ) - messageLabel = "explicitly with messages"; - break; - // These cases are here to prevent compiler warnings - case ResultWas::Unknown: - case ResultWas::FailureBit: - case ResultWas::Exception: - passOrFail = "** internal error **"; - colour = Colour::Error; - break; - } - } - - void print() const { - printSourceInfo(); - if( stats.totals.assertions.total() > 0 ) { - if( result.isOk() ) - stream << '\n'; - printResultType(); - printOriginalExpression(); - printReconstructedExpression(); - } - else { - stream << '\n'; - } - printMessage(); - } - - private: - void printResultType() const { - if( !passOrFail.empty() ) { - Colour colourGuard( colour ); - stream << passOrFail << ":\n"; - } - } - void printOriginalExpression() const { - if( result.hasExpression() ) { - Colour colourGuard( Colour::OriginalExpression ); - stream << " "; - stream << result.getExpressionInMacro(); - stream << '\n'; - } - } - void printReconstructedExpression() const { - if( result.hasExpandedExpression() ) { - stream << "with expansion:\n"; - Colour colourGuard( Colour::ReconstructedExpression ); - stream << Text( result.getExpandedExpression(), TextAttributes().setIndent(2) ) << '\n'; - } - } - void printMessage() const { - if( !messageLabel.empty() ) - stream << messageLabel << ':' << '\n'; - for( std::vector::const_iterator it = messages.begin(), itEnd = messages.end(); - it != itEnd; - ++it ) { - // If this assertion is a warning ignore any INFO messages - if( printInfoMessages || it->type != ResultWas::Info ) - stream << Text( it->message, TextAttributes().setIndent(2) ) << '\n'; - } - } - void printSourceInfo() const { - Colour colourGuard( Colour::FileName ); - stream << result.getSourceInfo() << ": "; - } - - std::ostream& stream; - AssertionStats const& stats; - AssertionResult const& result; - Colour::Code colour; - std::string passOrFail; - std::string messageLabel; - std::string message; - std::vector messages; - bool printInfoMessages; - }; - - void lazyPrint() { - - if( !currentTestRunInfo.used ) - lazyPrintRunInfo(); - if( !currentGroupInfo.used ) - lazyPrintGroupInfo(); - - if( !m_headerPrinted ) { - printTestCaseAndSectionHeader(); - m_headerPrinted = true; - } - } - void lazyPrintRunInfo() { - stream << '\n' << getLineOfChars<'~'>() << '\n'; - Colour colour( Colour::SecondaryText ); - stream << currentTestRunInfo->name - << " is a Catch v" << libraryVersion << " host application.\n" - << "Run with -? for options\n\n"; - - if( m_config->rngSeed() != 0 ) - stream << "Randomness seeded to: " << m_config->rngSeed() << "\n\n"; - - currentTestRunInfo.used = true; - } - void lazyPrintGroupInfo() { - if( !currentGroupInfo->name.empty() && currentGroupInfo->groupsCounts > 1 ) { - printClosedHeader( "Group: " + currentGroupInfo->name ); - currentGroupInfo.used = true; - } - } - void printTestCaseAndSectionHeader() { - assert( !m_sectionStack.empty() ); - printOpenHeader( currentTestCaseInfo->name ); - - if( m_sectionStack.size() > 1 ) { - Colour colourGuard( Colour::Headers ); - - std::vector::const_iterator - it = m_sectionStack.begin()+1, // Skip first section (test case) - itEnd = m_sectionStack.end(); - for( ; it != itEnd; ++it ) - printHeaderString( it->name, 2 ); - } - - SourceLineInfo lineInfo = m_sectionStack.front().lineInfo; - - if( !lineInfo.empty() ){ - stream << getLineOfChars<'-'>() << '\n'; - Colour colourGuard( Colour::FileName ); - stream << lineInfo << '\n'; - } - stream << getLineOfChars<'.'>() << '\n' << std::endl; - } - - void printClosedHeader( std::string const& _name ) { - printOpenHeader( _name ); - stream << getLineOfChars<'.'>() << '\n'; - } - void printOpenHeader( std::string const& _name ) { - stream << getLineOfChars<'-'>() << '\n'; - { - Colour colourGuard( Colour::Headers ); - printHeaderString( _name ); - } - } - - // if string has a : in first line will set indent to follow it on - // subsequent lines - void printHeaderString( std::string const& _string, std::size_t indent = 0 ) { - std::size_t i = _string.find( ": " ); - if( i != std::string::npos ) - i+=2; - else - i = 0; - stream << Text( _string, TextAttributes() - .setIndent( indent+i) - .setInitialIndent( indent ) ) << '\n'; - } - - struct SummaryColumn { - - SummaryColumn( std::string const& _label, Colour::Code _colour ) - : label( _label ), - colour( _colour ) - {} - SummaryColumn addRow( std::size_t count ) { - std::ostringstream oss; - oss << count; - std::string row = oss.str(); - for( std::vector::iterator it = rows.begin(); it != rows.end(); ++it ) { - while( it->size() < row.size() ) - *it = ' ' + *it; - while( it->size() > row.size() ) - row = ' ' + row; - } - rows.push_back( row ); - return *this; - } - - std::string label; - Colour::Code colour; - std::vector rows; - - }; - - void printTotals( Totals const& totals ) { - if( totals.testCases.total() == 0 ) { - stream << Colour( Colour::Warning ) << "No tests ran\n"; - } - else if( totals.assertions.total() > 0 && totals.testCases.allPassed() ) { - stream << Colour( Colour::ResultSuccess ) << "All tests passed"; - stream << " (" - << pluralise( totals.assertions.passed, "assertion" ) << " in " - << pluralise( totals.testCases.passed, "test case" ) << ')' - << '\n'; - } - else { - - std::vector columns; - columns.push_back( SummaryColumn( "", Colour::None ) - .addRow( totals.testCases.total() ) - .addRow( totals.assertions.total() ) ); - columns.push_back( SummaryColumn( "passed", Colour::Success ) - .addRow( totals.testCases.passed ) - .addRow( totals.assertions.passed ) ); - columns.push_back( SummaryColumn( "failed", Colour::ResultError ) - .addRow( totals.testCases.failed ) - .addRow( totals.assertions.failed ) ); - columns.push_back( SummaryColumn( "failed as expected", Colour::ResultExpectedFailure ) - .addRow( totals.testCases.failedButOk ) - .addRow( totals.assertions.failedButOk ) ); - - printSummaryRow( "test cases", columns, 0 ); - printSummaryRow( "assertions", columns, 1 ); - } - } - void printSummaryRow( std::string const& label, std::vector const& cols, std::size_t row ) { - for( std::vector::const_iterator it = cols.begin(); it != cols.end(); ++it ) { - std::string value = it->rows[row]; - if( it->label.empty() ) { - stream << label << ": "; - if( value != "0" ) - stream << value; - else - stream << Colour( Colour::Warning ) << "- none -"; - } - else if( value != "0" ) { - stream << Colour( Colour::LightGrey ) << " | "; - stream << Colour( it->colour ) - << value << ' ' << it->label; - } - } - stream << '\n'; - } - - static std::size_t makeRatio( std::size_t number, std::size_t total ) { - std::size_t ratio = total > 0 ? CATCH_CONFIG_CONSOLE_WIDTH * number/ total : 0; - return ( ratio == 0 && number > 0 ) ? 1 : ratio; - } - static std::size_t& findMax( std::size_t& i, std::size_t& j, std::size_t& k ) { - if( i > j && i > k ) - return i; - else if( j > k ) - return j; - else - return k; - } - - void printTotalsDivider( Totals const& totals ) { - if( totals.testCases.total() > 0 ) { - std::size_t failedRatio = makeRatio( totals.testCases.failed, totals.testCases.total() ); - std::size_t failedButOkRatio = makeRatio( totals.testCases.failedButOk, totals.testCases.total() ); - std::size_t passedRatio = makeRatio( totals.testCases.passed, totals.testCases.total() ); - while( failedRatio + failedButOkRatio + passedRatio < CATCH_CONFIG_CONSOLE_WIDTH-1 ) - findMax( failedRatio, failedButOkRatio, passedRatio )++; - while( failedRatio + failedButOkRatio + passedRatio > CATCH_CONFIG_CONSOLE_WIDTH-1 ) - findMax( failedRatio, failedButOkRatio, passedRatio )--; - - stream << Colour( Colour::Error ) << std::string( failedRatio, '=' ); - stream << Colour( Colour::ResultExpectedFailure ) << std::string( failedButOkRatio, '=' ); - if( totals.testCases.allPassed() ) - stream << Colour( Colour::ResultSuccess ) << std::string( passedRatio, '=' ); - else - stream << Colour( Colour::Success ) << std::string( passedRatio, '=' ); - } - else { - stream << Colour( Colour::Warning ) << std::string( CATCH_CONFIG_CONSOLE_WIDTH-1, '=' ); - } - stream << '\n'; - } - void printSummaryDivider() { - stream << getLineOfChars<'-'>() << '\n'; - } - - private: - bool m_headerPrinted; - }; - - INTERNAL_CATCH_REGISTER_REPORTER( "console", ConsoleReporter ) - -} // end namespace Catch - -// #included from: ../reporters/catch_reporter_compact.hpp -#define TWOBLUECUBES_CATCH_REPORTER_COMPACT_HPP_INCLUDED - -namespace Catch { - - struct CompactReporter : StreamingReporterBase { - - CompactReporter( ReporterConfig const& _config ) - : StreamingReporterBase( _config ) - {} - - virtual ~CompactReporter(); - - static std::string getDescription() { - return "Reports test results on a single line, suitable for IDEs"; - } - - virtual ReporterPreferences getPreferences() const { - ReporterPreferences prefs; - prefs.shouldRedirectStdOut = false; - return prefs; - } - - virtual void noMatchingTestCases( std::string const& spec ) { - stream << "No test cases matched '" << spec << '\'' << std::endl; - } - - virtual void assertionStarting( AssertionInfo const& ) { - } - - virtual bool assertionEnded( AssertionStats const& _assertionStats ) { - AssertionResult const& result = _assertionStats.assertionResult; - - bool printInfoMessages = true; - - // Drop out if result was successful and we're not printing those - if( !m_config->includeSuccessfulResults() && result.isOk() ) { - if( result.getResultType() != ResultWas::Warning ) - return false; - printInfoMessages = false; - } - - AssertionPrinter printer( stream, _assertionStats, printInfoMessages ); - printer.print(); - - stream << std::endl; - return true; - } - - virtual void testRunEnded( TestRunStats const& _testRunStats ) { - printTotals( _testRunStats.totals ); - stream << '\n' << std::endl; - StreamingReporterBase::testRunEnded( _testRunStats ); - } - - private: - class AssertionPrinter { - void operator= ( AssertionPrinter const& ); - public: - AssertionPrinter( std::ostream& _stream, AssertionStats const& _stats, bool _printInfoMessages ) - : stream( _stream ) - , stats( _stats ) - , result( _stats.assertionResult ) - , messages( _stats.infoMessages ) - , itMessage( _stats.infoMessages.begin() ) - , printInfoMessages( _printInfoMessages ) - {} - - void print() { - printSourceInfo(); - - itMessage = messages.begin(); - - switch( result.getResultType() ) { - case ResultWas::Ok: - printResultType( Colour::ResultSuccess, passedString() ); - printOriginalExpression(); - printReconstructedExpression(); - if ( ! result.hasExpression() ) - printRemainingMessages( Colour::None ); - else - printRemainingMessages(); - break; - case ResultWas::ExpressionFailed: - if( result.isOk() ) - printResultType( Colour::ResultSuccess, failedString() + std::string( " - but was ok" ) ); - else - printResultType( Colour::Error, failedString() ); - printOriginalExpression(); - printReconstructedExpression(); - printRemainingMessages(); - break; - case ResultWas::ThrewException: - printResultType( Colour::Error, failedString() ); - printIssue( "unexpected exception with message:" ); - printMessage(); - printExpressionWas(); - printRemainingMessages(); - break; - case ResultWas::FatalErrorCondition: - printResultType( Colour::Error, failedString() ); - printIssue( "fatal error condition with message:" ); - printMessage(); - printExpressionWas(); - printRemainingMessages(); - break; - case ResultWas::DidntThrowException: - printResultType( Colour::Error, failedString() ); - printIssue( "expected exception, got none" ); - printExpressionWas(); - printRemainingMessages(); - break; - case ResultWas::Info: - printResultType( Colour::None, "info" ); - printMessage(); - printRemainingMessages(); - break; - case ResultWas::Warning: - printResultType( Colour::None, "warning" ); - printMessage(); - printRemainingMessages(); - break; - case ResultWas::ExplicitFailure: - printResultType( Colour::Error, failedString() ); - printIssue( "explicitly" ); - printRemainingMessages( Colour::None ); - break; - // These cases are here to prevent compiler warnings - case ResultWas::Unknown: - case ResultWas::FailureBit: - case ResultWas::Exception: - printResultType( Colour::Error, "** internal error **" ); - break; - } - } - - private: - // Colour::LightGrey - - static Colour::Code dimColour() { return Colour::FileName; } - -#ifdef CATCH_PLATFORM_MAC - static const char* failedString() { return "FAILED"; } - static const char* passedString() { return "PASSED"; } -#else - static const char* failedString() { return "failed"; } - static const char* passedString() { return "passed"; } -#endif - - void printSourceInfo() const { - Colour colourGuard( Colour::FileName ); - stream << result.getSourceInfo() << ':'; - } - - void printResultType( Colour::Code colour, std::string passOrFail ) const { - if( !passOrFail.empty() ) { - { - Colour colourGuard( colour ); - stream << ' ' << passOrFail; - } - stream << ':'; - } - } - - void printIssue( std::string issue ) const { - stream << ' ' << issue; - } - - void printExpressionWas() { - if( result.hasExpression() ) { - stream << ';'; - { - Colour colour( dimColour() ); - stream << " expression was:"; - } - printOriginalExpression(); - } - } - - void printOriginalExpression() const { - if( result.hasExpression() ) { - stream << ' ' << result.getExpression(); - } - } - - void printReconstructedExpression() const { - if( result.hasExpandedExpression() ) { - { - Colour colour( dimColour() ); - stream << " for: "; - } - stream << result.getExpandedExpression(); - } - } - - void printMessage() { - if ( itMessage != messages.end() ) { - stream << " '" << itMessage->message << '\''; - ++itMessage; - } - } - - void printRemainingMessages( Colour::Code colour = dimColour() ) { - if ( itMessage == messages.end() ) - return; - - // using messages.end() directly yields compilation error: - std::vector::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" ) << '.'; - } - } - }; - - INTERNAL_CATCH_REGISTER_REPORTER( "compact", CompactReporter ) - -} // end namespace Catch - -namespace Catch { - // These are all here to avoid warnings about not having any out of line - // virtual methods - NonCopyable::~NonCopyable() {} - IShared::~IShared() {} - IStream::~IStream() CATCH_NOEXCEPT {} - FileStream::~FileStream() CATCH_NOEXCEPT {} - CoutStream::~CoutStream() CATCH_NOEXCEPT {} - DebugOutStream::~DebugOutStream() CATCH_NOEXCEPT {} - StreamBufBase::~StreamBufBase() CATCH_NOEXCEPT {} - IContext::~IContext() {} - IResultCapture::~IResultCapture() {} - ITestCase::~ITestCase() {} - ITestCaseRegistry::~ITestCaseRegistry() {} - IRegistryHub::~IRegistryHub() {} - IMutableRegistryHub::~IMutableRegistryHub() {} - IExceptionTranslator::~IExceptionTranslator() {} - IExceptionTranslatorRegistry::~IExceptionTranslatorRegistry() {} - IReporter::~IReporter() {} - IReporterFactory::~IReporterFactory() {} - IReporterRegistry::~IReporterRegistry() {} - IStreamingReporter::~IStreamingReporter() {} - AssertionStats::~AssertionStats() {} - SectionStats::~SectionStats() {} - TestCaseStats::~TestCaseStats() {} - TestGroupStats::~TestGroupStats() {} - TestRunStats::~TestRunStats() {} - CumulativeReporterBase::SectionNode::~SectionNode() {} - CumulativeReporterBase::~CumulativeReporterBase() {} - - StreamingReporterBase::~StreamingReporterBase() {} - ConsoleReporter::~ConsoleReporter() {} - CompactReporter::~CompactReporter() {} - IRunner::~IRunner() {} - IMutableContext::~IMutableContext() {} - IConfig::~IConfig() {} - XmlReporter::~XmlReporter() {} - JunitReporter::~JunitReporter() {} - TestRegistry::~TestRegistry() {} - FreeFunctionTestCase::~FreeFunctionTestCase() {} - IGeneratorInfo::~IGeneratorInfo() {} - IGeneratorsForTest::~IGeneratorsForTest() {} - WildcardPattern::~WildcardPattern() {} - TestSpec::Pattern::~Pattern() {} - TestSpec::NamePattern::~NamePattern() {} - TestSpec::TagPattern::~TagPattern() {} - TestSpec::ExcludedPattern::~ExcludedPattern() {} - - Matchers::Impl::StdString::Equals::~Equals() {} - Matchers::Impl::StdString::Contains::~Contains() {} - Matchers::Impl::StdString::StartsWith::~StartsWith() {} - Matchers::Impl::StdString::EndsWith::~EndsWith() {} - - void Config::dummy() {} - - namespace TestCaseTracking { - ITracker::~ITracker() {} - TrackerBase::~TrackerBase() {} - SectionTracker::~SectionTracker() {} - IndexTracker::~IndexTracker() {} - } -} - -#ifdef __clang__ -#pragma clang diagnostic pop -#endif - -#endif - -#ifdef CATCH_CONFIG_MAIN -// #included from: internal/catch_default_main.hpp -#define TWOBLUECUBES_CATCH_DEFAULT_MAIN_HPP_INCLUDED - -#ifndef __OBJC__ - -// Standard C/C++ main entry point -int main (int argc, char * argv[]) { - int result = Catch::Session().run( argc, argv ); - return ( result < 0xff ? result : 0xff ); -} - -#else // __OBJC__ - -// Objective-C entry point -int main (int argc, char * const argv[]) { -#if !CATCH_ARC_ENABLED - NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; -#endif - - Catch::registerTestMethods(); - int result = Catch::Session().run( argc, (char* const*)argv ); - -#if !CATCH_ARC_ENABLED - [pool drain]; -#endif - - return ( result < 0xff ? result : 0xff ); -} - -#endif // __OBJC__ - -#endif - -#ifdef CLARA_CONFIG_MAIN_NOT_DEFINED -# undef CLARA_CONFIG_MAIN -#endif - -////// - -// If this config identifier is defined then all CATCH macros are prefixed with CATCH_ -#ifdef CATCH_CONFIG_PREFIX_ALL - -#define CATCH_REQUIRE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal, "CATCH_REQUIRE" ) -#define CATCH_REQUIRE_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, "CATCH_REQUIRE_FALSE" ) - -#define CATCH_REQUIRE_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::Normal, "", "CATCH_REQUIRE_THROWS" ) -#define CATCH_REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_THROWS_AS" ) -#define CATCH_REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::Normal, matcher, "CATCH_REQUIRE_THROWS_WITH" ) -#define CATCH_REQUIRE_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_NOTHROW" ) - -#define CATCH_CHECK( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK" ) -#define CATCH_CHECK_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::FalseTest, "CATCH_CHECK_FALSE" ) -#define CATCH_CHECKED_IF( expr ) INTERNAL_CATCH_IF( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECKED_IF" ) -#define CATCH_CHECKED_ELSE( expr ) INTERNAL_CATCH_ELSE( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECKED_ELSE" ) -#define CATCH_CHECK_NOFAIL( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, "CATCH_CHECK_NOFAIL" ) - -#define CATCH_CHECK_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::ContinueOnFailure, "", "CATCH_CHECK_THROWS" ) -#define CATCH_CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_THROWS_AS" ) -#define CATCH_CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::ContinueOnFailure, matcher, "CATCH_CHECK_THROWS_WITH" ) -#define CATCH_CHECK_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_NOTHROW" ) - -#define CATCH_CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_THAT" ) -#define CATCH_REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_THAT" ) - -#define CATCH_INFO( msg ) INTERNAL_CATCH_INFO( msg, "CATCH_INFO" ) -#define CATCH_WARN( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, "CATCH_WARN", msg ) -#define CATCH_SCOPED_INFO( msg ) INTERNAL_CATCH_INFO( msg, "CATCH_INFO" ) -#define CATCH_CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CATCH_CAPTURE" ) -#define CATCH_SCOPED_CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CATCH_CAPTURE" ) - -#ifdef CATCH_CONFIG_VARIADIC_MACROS - #define CATCH_TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ ) - #define CATCH_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ ) - #define CATCH_METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ ) - #define CATCH_REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ ) - #define CATCH_SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ ) - #define CATCH_FAIL( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "CATCH_FAIL", __VA_ARGS__ ) - #define CATCH_SUCCEED( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "CATCH_SUCCEED", __VA_ARGS__ ) -#else - #define CATCH_TEST_CASE( name, description ) INTERNAL_CATCH_TESTCASE( name, description ) - #define CATCH_TEST_CASE_METHOD( className, name, description ) INTERNAL_CATCH_TEST_CASE_METHOD( className, name, description ) - #define CATCH_METHOD_AS_TEST_CASE( method, name, description ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, name, description ) - #define CATCH_REGISTER_TEST_CASE( function, name, description ) INTERNAL_CATCH_REGISTER_TESTCASE( function, name, description ) - #define CATCH_SECTION( name, description ) INTERNAL_CATCH_SECTION( name, description ) - #define CATCH_FAIL( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "CATCH_FAIL", msg ) - #define CATCH_SUCCEED( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "CATCH_SUCCEED", msg ) -#endif -#define CATCH_ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE( "", "" ) - -#define CATCH_REGISTER_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType ) -#define CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) - -#define CATCH_GENERATE( expr) INTERNAL_CATCH_GENERATE( expr ) - -// "BDD-style" convenience wrappers -#ifdef CATCH_CONFIG_VARIADIC_MACROS -#define CATCH_SCENARIO( ... ) CATCH_TEST_CASE( "Scenario: " __VA_ARGS__ ) -#define CATCH_SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ ) -#else -#define CATCH_SCENARIO( name, tags ) CATCH_TEST_CASE( "Scenario: " name, tags ) -#define CATCH_SCENARIO_METHOD( className, name, tags ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " name, tags ) -#endif -#define CATCH_GIVEN( desc ) CATCH_SECTION( std::string( "Given: ") + desc, "" ) -#define CATCH_WHEN( desc ) CATCH_SECTION( std::string( " When: ") + desc, "" ) -#define CATCH_AND_WHEN( desc ) CATCH_SECTION( std::string( " And: ") + desc, "" ) -#define CATCH_THEN( desc ) CATCH_SECTION( std::string( " Then: ") + desc, "" ) -#define CATCH_AND_THEN( desc ) CATCH_SECTION( std::string( " And: ") + desc, "" ) - -// If CATCH_CONFIG_PREFIX_ALL is not defined then the CATCH_ prefix is not required -#else - -#define REQUIRE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal, "REQUIRE" ) -#define REQUIRE_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, "REQUIRE_FALSE" ) - -#define REQUIRE_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::Normal, "", "REQUIRE_THROWS" ) -#define REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::Normal, "REQUIRE_THROWS_AS" ) -#define REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::Normal, matcher, "REQUIRE_THROWS_WITH" ) -#define REQUIRE_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::Normal, "REQUIRE_NOTHROW" ) - -#define CHECK( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECK" ) -#define CHECK_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::FalseTest, "CHECK_FALSE" ) -#define CHECKED_IF( expr ) INTERNAL_CATCH_IF( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECKED_IF" ) -#define CHECKED_ELSE( expr ) INTERNAL_CATCH_ELSE( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECKED_ELSE" ) -#define CHECK_NOFAIL( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, "CHECK_NOFAIL" ) - -#define CHECK_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::ContinueOnFailure, "", "CHECK_THROWS" ) -#define CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::ContinueOnFailure, "CHECK_THROWS_AS" ) -#define CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::ContinueOnFailure, matcher, "CHECK_THROWS_WITH" ) -#define CHECK_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECK_NOTHROW" ) - -#define CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::ContinueOnFailure, "CHECK_THAT" ) -#define REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::Normal, "REQUIRE_THAT" ) - -#define INFO( msg ) INTERNAL_CATCH_INFO( msg, "INFO" ) -#define WARN( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, "WARN", msg ) -#define SCOPED_INFO( msg ) INTERNAL_CATCH_INFO( msg, "INFO" ) -#define CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CAPTURE" ) -#define SCOPED_CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CAPTURE" ) - -#ifdef CATCH_CONFIG_VARIADIC_MACROS - #define TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ ) - #define TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ ) - #define METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ ) - #define REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ ) - #define SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ ) - #define FAIL( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "FAIL", __VA_ARGS__ ) - #define SUCCEED( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "SUCCEED", __VA_ARGS__ ) -#else - #define TEST_CASE( name, description ) INTERNAL_CATCH_TESTCASE( name, description ) - #define TEST_CASE_METHOD( className, name, description ) INTERNAL_CATCH_TEST_CASE_METHOD( className, name, description ) - #define METHOD_AS_TEST_CASE( method, name, description ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, name, description ) - #define REGISTER_TEST_CASE( method, name, description ) INTERNAL_CATCH_REGISTER_TESTCASE( method, name, description ) - #define SECTION( name, description ) INTERNAL_CATCH_SECTION( name, description ) - #define FAIL( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "FAIL", msg ) - #define SUCCEED( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "SUCCEED", msg ) -#endif -#define ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE( "", "" ) - -#define REGISTER_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType ) -#define REGISTER_LEGACY_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) - -#define GENERATE( expr) INTERNAL_CATCH_GENERATE( expr ) - -#endif - -#define CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) - -// "BDD-style" convenience wrappers -#ifdef CATCH_CONFIG_VARIADIC_MACROS -#define SCENARIO( ... ) TEST_CASE( "Scenario: " __VA_ARGS__ ) -#define SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ ) -#else -#define SCENARIO( name, tags ) TEST_CASE( "Scenario: " name, tags ) -#define SCENARIO_METHOD( className, name, tags ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " name, tags ) -#endif -#define GIVEN( desc ) SECTION( std::string(" Given: ") + desc, "" ) -#define WHEN( desc ) SECTION( std::string(" When: ") + desc, "" ) -#define AND_WHEN( desc ) SECTION( std::string("And when: ") + desc, "" ) -#define THEN( desc ) SECTION( std::string(" Then: ") + desc, "" ) -#define AND_THEN( desc ) SECTION( std::string(" And: ") + desc, "" ) - -using Catch::Detail::Approx; - -#endif // TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED - +/* + * Catch v1.7.2 + * Generated: 2017-02-13 15:57:33.350226 + * ---------------------------------------------------------- + * This file has been merged from multiple headers. Please don't edit it directly + * Copyright (c) 2012 Two Blue Cubes Ltd. All rights reserved. + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + */ +#ifndef TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED +#define TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED + +#define TWOBLUECUBES_CATCH_HPP_INCLUDED + +#ifdef __clang__ +# pragma clang system_header +#elif defined __GNUC__ +# pragma GCC system_header +#endif + +// #included from: internal/catch_suppress_warnings.h + +#ifdef __clang__ +# ifdef __ICC // icpc defines the __clang__ macro +# pragma warning(push) +# pragma warning(disable: 161 1682) +# else // __ICC +# pragma clang diagnostic ignored "-Wglobal-constructors" +# pragma clang diagnostic ignored "-Wvariadic-macros" +# pragma clang diagnostic ignored "-Wc99-extensions" +# pragma clang diagnostic ignored "-Wunused-variable" +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wpadded" +# pragma clang diagnostic ignored "-Wc++98-compat" +# pragma clang diagnostic ignored "-Wc++98-compat-pedantic" +# pragma clang diagnostic ignored "-Wswitch-enum" +# pragma clang diagnostic ignored "-Wcovered-switch-default" +# endif +#elif defined __GNUC__ +# pragma GCC diagnostic ignored "-Wvariadic-macros" +# pragma GCC diagnostic ignored "-Wunused-variable" +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wpadded" +#endif +#if defined(CATCH_CONFIG_MAIN) || defined(CATCH_CONFIG_RUNNER) +# define CATCH_IMPL +#endif + +#ifdef CATCH_IMPL +# ifndef CLARA_CONFIG_MAIN +# define CLARA_CONFIG_MAIN_NOT_DEFINED +# define CLARA_CONFIG_MAIN +# endif +#endif + +// #included from: internal/catch_notimplemented_exception.h +#define TWOBLUECUBES_CATCH_NOTIMPLEMENTED_EXCEPTION_H_INCLUDED + +// #included from: catch_common.h +#define TWOBLUECUBES_CATCH_COMMON_H_INCLUDED + +// #included from: catch_compiler_capabilities.h +#define TWOBLUECUBES_CATCH_COMPILER_CAPABILITIES_HPP_INCLUDED + +// Detect a number of compiler features - mostly C++11/14 conformance - by compiler +// The following features are defined: +// +// CATCH_CONFIG_CPP11_NULLPTR : is nullptr supported? +// CATCH_CONFIG_CPP11_NOEXCEPT : is noexcept supported? +// CATCH_CONFIG_CPP11_GENERATED_METHODS : The delete and default keywords for compiler generated methods +// CATCH_CONFIG_CPP11_IS_ENUM : std::is_enum is supported? +// CATCH_CONFIG_CPP11_TUPLE : std::tuple is supported +// CATCH_CONFIG_CPP11_LONG_LONG : is long long supported? +// CATCH_CONFIG_CPP11_OVERRIDE : is override supported? +// CATCH_CONFIG_CPP11_UNIQUE_PTR : is unique_ptr supported (otherwise use auto_ptr) +// CATCH_CONFIG_CPP11_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? +// **************** +// Note to maintainers: if new toggles are added please document them +// in configuration.md, too +// **************** + +// In general each macro has a _NO_ form +// (e.g. CATCH_CONFIG_CPP11_NO_NULLPTR) which disables the feature. +// Many features, at point of detection, define an _INTERNAL_ macro, so they +// can be combined, en-mass, with the _NO_ forms later. + +// All the C++11 features can be disabled with CATCH_CONFIG_NO_CPP11 + +#ifdef __cplusplus + +# if __cplusplus >= 201103L +# define CATCH_CPP11_OR_GREATER +# endif + +# if __cplusplus >= 201402L +# define CATCH_CPP14_OR_GREATER +# endif + +#endif + +#ifdef __clang__ + +# if __has_feature(cxx_nullptr) +# define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR +# endif + +# if __has_feature(cxx_noexcept) +# define CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT +# endif + +# if defined(CATCH_CPP11_OR_GREATER) +# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS _Pragma( "clang diagnostic ignored \"-Wparentheses\"" ) +# endif + +#endif // __clang__ + +//////////////////////////////////////////////////////////////////////////////// +// Borland +#ifdef __BORLANDC__ + +#endif // __BORLANDC__ + +//////////////////////////////////////////////////////////////////////////////// +// EDG +#ifdef __EDG_VERSION__ + +#endif // __EDG_VERSION__ + +//////////////////////////////////////////////////////////////////////////////// +// Digital Mars +#ifdef __DMC__ + +#endif // __DMC__ + +//////////////////////////////////////////////////////////////////////////////// +// GCC +#ifdef __GNUC__ + +# if __GNUC__ == 4 && __GNUC_MINOR__ >= 6 && defined(__GXX_EXPERIMENTAL_CXX0X__) +# define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR +# endif + +# if !defined(CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS) && defined(CATCH_CPP11_OR_GREATER) +# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS _Pragma( "GCC diagnostic ignored \"-Wparentheses\"" ) +# endif + +// - otherwise more recent versions define __cplusplus >= 201103L +// and will get picked up below + +#endif // __GNUC__ + +//////////////////////////////////////////////////////////////////////////////// +// Visual C++ +#ifdef _MSC_VER + +#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 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 + +// Use __COUNTER__ if the compiler supports it +#if ( defined _MSC_VER && _MSC_VER >= 1300 ) || \ + ( defined __GNUC__ && __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 + +#if !defined(CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS) +# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS +#endif + +// noexcept support: +#if defined(CATCH_CONFIG_CPP11_NOEXCEPT) && !defined(CATCH_NOEXCEPT) +# define CATCH_NOEXCEPT noexcept +# define CATCH_NOEXCEPT_IS(x) noexcept(x) +#else +# define CATCH_NOEXCEPT throw() +# define CATCH_NOEXCEPT_IS(x) +#endif + +// nullptr support +#ifdef CATCH_CONFIG_CPP11_NULLPTR +# define CATCH_NULL nullptr +#else +# define CATCH_NULL NULL +#endif + +// override support +#ifdef CATCH_CONFIG_CPP11_OVERRIDE +# define CATCH_OVERRIDE override +#else +# define CATCH_OVERRIDE +#endif + +// unique_ptr support +#ifdef CATCH_CONFIG_CPP11_UNIQUE_PTR +# define CATCH_AUTO_PTR( T ) std::unique_ptr +#else +# define CATCH_AUTO_PTR( T ) std::auto_ptr +#endif + +#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 +# define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __COUNTER__ ) +#else +# 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 + +namespace Catch { + + struct IConfig; + + struct CaseSensitive { enum Choice { + Yes, + No + }; }; + + class NonCopyable { +#ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS + NonCopyable( NonCopyable const& ) = delete; + NonCopyable( NonCopyable && ) = delete; + NonCopyable& operator = ( NonCopyable const& ) = delete; + NonCopyable& operator = ( NonCopyable && ) = delete; +#else + NonCopyable( NonCopyable const& info ); + NonCopyable& operator = ( NonCopyable const& ); +#endif + + protected: + NonCopyable() {} + virtual ~NonCopyable(); + }; + + class SafeBool { + public: + typedef void (SafeBool::*type)() const; + + static type makeSafe( bool value ) { + return value ? &SafeBool::trueValue : 0; + } + private: + void trueValue() const {} + }; + + template + inline void deleteAll( ContainerT& container ) { + typename ContainerT::const_iterator it = container.begin(); + typename ContainerT::const_iterator itEnd = container.end(); + for(; it != itEnd; ++it ) + delete *it; + } + template + inline void deleteAllValues( AssociativeContainerT& container ) { + typename AssociativeContainerT::const_iterator it = container.begin(); + typename AssociativeContainerT::const_iterator itEnd = container.end(); + for(; it != itEnd; ++it ) + delete it->second; + } + + 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( 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; + + char const* file; + std::size_t line; + }; + + std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info ); + + // This is just here to avoid compiler warnings with macro constants and boolean literals + inline bool isTrue( bool value ){ return value; } + inline bool alwaysTrue() { return true; } + inline bool alwaysFalse() { return false; } + + void throwLogicError( std::string const& message, SourceLineInfo const& locationInfo ); + + void seedRng( IConfig const& config ); + unsigned int rngSeed(); + + // Use this in variadic streaming macros to allow + // >> +StreamEndStop + // as well as + // >> stuff +StreamEndStop + struct StreamEndStop { + std::string operator+() { + return std::string(); + } + }; + template + T const& operator + ( T const& value, StreamEndStop ) { + return value; + } +} + +#define CATCH_INTERNAL_LINEINFO ::Catch::SourceLineInfo( __FILE__, static_cast( __LINE__ ) ) +#define CATCH_INTERNAL_ERROR( msg ) ::Catch::throwLogicError( msg, CATCH_INTERNAL_LINEINFO ); + +namespace Catch { + + class NotImplementedException : public std::exception + { + public: + NotImplementedException( SourceLineInfo const& lineInfo ); + NotImplementedException( NotImplementedException const& ) {} + + virtual ~NotImplementedException() CATCH_NOEXCEPT {} + + virtual const char* what() const CATCH_NOEXCEPT; + + private: + std::string m_what; + SourceLineInfo m_lineInfo; + }; + +} // end namespace Catch + +/////////////////////////////////////////////////////////////////////////////// +#define CATCH_NOT_IMPLEMENTED throw Catch::NotImplementedException( CATCH_INTERNAL_LINEINFO ) + +// #included from: internal/catch_context.h +#define TWOBLUECUBES_CATCH_CONTEXT_H_INCLUDED + +// #included from: catch_interfaces_generators.h +#define TWOBLUECUBES_CATCH_INTERFACES_GENERATORS_H_INCLUDED + +#include + +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 + +namespace Catch { + + class TestSpec; + + struct ITestCase : IShared { + virtual void invoke () const = 0; + protected: + virtual ~ITestCase(); + }; + + class TestCase; + struct IConfig; + + struct ITestCaseRegistry { + virtual ~ITestCaseRegistry(); + virtual std::vector const& getAllTests() const = 0; + virtual std::vector const& getAllTestsSorted( IConfig const& config ) const = 0; + }; + + bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config ); + std::vector filterTests( std::vector const& testCases, TestSpec const& testSpec, IConfig const& config ); + std::vector const& getAllTestCasesSorted( IConfig const& config ); + +} + +namespace Catch { + +template +class MethodTestCase : public SharedImpl { + +public: + MethodTestCase( void (C::*method)() ) : m_method( method ) {} + + virtual void invoke() const { + C obj; + (obj.*m_method)(); + } + +private: + virtual ~MethodTestCase() {} + + void (C::*m_method)(); +}; + +typedef void(*TestFunction)(); + +struct NameAndDesc { + NameAndDesc( const char* _name = "", const char* _description= "" ) + : name( _name ), description( _description ) + {} + + const char* name; + const char* description; +}; + +void registerTestCase + ( ITestCase* testCase, + char const* className, + NameAndDesc const& nameAndDesc, + SourceLineInfo const& lineInfo ); + +struct AutoReg { + + AutoReg + ( TestFunction function, + SourceLineInfo const& lineInfo, + NameAndDesc const& nameAndDesc ); + + template + 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 + +#ifdef CATCH_CONFIG_VARIADIC_MACROS + /////////////////////////////////////////////////////////////////////////////// + #define INTERNAL_CATCH_TESTCASE2( TestName, ... ) \ + static void TestName(); \ + namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &TestName, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( __VA_ARGS__ ) ); }\ + 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, ... ) \ + namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &QualifiedMethod, "&" #QualifiedMethod, Catch::NameAndDesc( __VA_ARGS__ ), CATCH_INTERNAL_LINEINFO ); } + + /////////////////////////////////////////////////////////////////////////////// + #define INTERNAL_CATCH_TEST_CASE_METHOD2( TestName, ClassName, ... )\ + namespace{ \ + struct TestName : ClassName{ \ + void test(); \ + }; \ + Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( &TestName::test, #ClassName, Catch::NameAndDesc( __VA_ARGS__ ), CATCH_INTERNAL_LINEINFO ); \ + } \ + 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::AutoReg( Function, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( __VA_ARGS__ ) ); + +#else + /////////////////////////////////////////////////////////////////////////////// + #define INTERNAL_CATCH_TESTCASE2( TestName, Name, Desc ) \ + static void TestName(); \ + namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &TestName, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( Name, Desc ) ); }\ + 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 ) + + /////////////////////////////////////////////////////////////////////////////// + #define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, Name, Desc ) \ + namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &QualifiedMethod, "&" #QualifiedMethod, Catch::NameAndDesc( Name, Desc ), CATCH_INTERNAL_LINEINFO ); } + + /////////////////////////////////////////////////////////////////////////////// + #define INTERNAL_CATCH_TEST_CASE_METHOD2( TestCaseName, ClassName, TestName, Desc )\ + namespace{ \ + struct TestCaseName : ClassName{ \ + void test(); \ + }; \ + Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( &TestCaseName::test, #ClassName, Catch::NameAndDesc( TestName, Desc ), CATCH_INTERNAL_LINEINFO ); \ + } \ + 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 ) + + /////////////////////////////////////////////////////////////////////////////// + #define INTERNAL_CATCH_REGISTER_TESTCASE( Function, Name, Desc ) \ + Catch::AutoReg( Function, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( Name, Desc ) ); +#endif + +// #included from: internal/catch_capture.hpp +#define TWOBLUECUBES_CATCH_CAPTURE_HPP_INCLUDED + +// #included from: catch_result_builder.h +#define TWOBLUECUBES_CATCH_RESULT_BUILDER_H_INCLUDED + +// #included from: catch_result_type.h +#define TWOBLUECUBES_CATCH_RESULT_TYPE_H_INCLUDED + +namespace Catch { + + // ResultWas::OfType enum + struct ResultWas { enum OfType { + Unknown = -1, + Ok = 0, + Info = 1, + Warning = 2, + + FailureBit = 0x10, + + ExpressionFailed = FailureBit | 1, + ExplicitFailure = FailureBit | 2, + + Exception = 0x100 | FailureBit, + + ThrewException = Exception | 1, + DidntThrowException = Exception | 2, + + FatalErrorCondition = 0x200 | FailureBit + + }; }; + + inline bool isOk( ResultWas::OfType resultType ) { + return ( resultType & ResultWas::FailureBit ) == 0; + } + inline bool isJustInfo( int flags ) { + return flags == ResultWas::Info; + } + + // ResultDisposition::Flags enum + struct ResultDisposition { enum Flags { + Normal = 0x01, + + ContinueOnFailure = 0x02, // Failures fail test, but execution continues + FalseTest = 0x04, // Prefix expression with ! + SuppressFail = 0x08 // Failures are reported but do not fail the test + }; }; + + inline ResultDisposition::Flags operator | ( ResultDisposition::Flags lhs, ResultDisposition::Flags rhs ) { + return static_cast( 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& ); + }; + + struct AssertionInfo + { + AssertionInfo() {} + AssertionInfo( std::string const& _macroName, + SourceLineInfo const& _lineInfo, + std::string const& _capturedExpression, + ResultDisposition::Flags _resultDisposition ); + + std::string macroName; + SourceLineInfo lineInfo; + std::string capturedExpression; + ResultDisposition::Flags resultDisposition; + }; + + struct AssertionResultData + { + AssertionResultData() : 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 { + + namespace Generic { + template class AllOf; + template class AnyOf; + template class Not; + } + + template + struct Matcher : SharedImpl + { + typedef ExpressionT ExpressionType; + + virtual ~Matcher() {} + virtual Ptr clone() const = 0; + virtual bool match( ExpressionT const& expr ) const = 0; + virtual std::string toString() const = 0; + + Generic::AllOf operator && ( Matcher const& other ) const; + Generic::AnyOf operator || ( Matcher const& other ) const; + Generic::Not operator ! () const; + }; + + template + struct MatcherImpl : Matcher { + + virtual Ptr > clone() const { + return Ptr >( new DerivedT( static_cast( *this ) ) ); + } + }; + + namespace Generic { + template + class Not : public MatcherImpl, ExpressionT> { + public: + explicit Not( Matcher const& matcher ) : m_matcher(matcher.clone()) {} + Not( Not const& other ) : m_matcher( other.m_matcher ) {} + + virtual bool match( ExpressionT const& expr ) const CATCH_OVERRIDE { + return !m_matcher->match( expr ); + } + + virtual std::string toString() const CATCH_OVERRIDE { + return "not " + m_matcher->toString(); + } + private: + Ptr< Matcher > m_matcher; + }; + + template + class AllOf : public MatcherImpl, ExpressionT> { + public: + + AllOf() {} + AllOf( AllOf const& other ) : m_matchers( other.m_matchers ) {} + + AllOf& add( Matcher const& matcher ) { + m_matchers.push_back( matcher.clone() ); + return *this; + } + virtual bool match( ExpressionT const& expr ) const + { + for( std::size_t i = 0; i < m_matchers.size(); ++i ) + if( !m_matchers[i]->match( expr ) ) + return false; + return true; + } + virtual std::string toString() const { + std::ostringstream oss; + oss << "( "; + for( std::size_t i = 0; i < m_matchers.size(); ++i ) { + if( i != 0 ) + oss << " and "; + oss << m_matchers[i]->toString(); + } + oss << " )"; + return oss.str(); + } + + AllOf operator && ( Matcher const& other ) const { + AllOf allOfExpr( *this ); + allOfExpr.add( other ); + return allOfExpr; + } + + private: + std::vector > > m_matchers; + }; + + template + class AnyOf : public MatcherImpl, ExpressionT> { + public: + + AnyOf() {} + AnyOf( AnyOf const& other ) : m_matchers( other.m_matchers ) {} + + AnyOf& add( Matcher const& matcher ) { + m_matchers.push_back( matcher.clone() ); + return *this; + } + virtual bool match( ExpressionT const& expr ) const + { + for( std::size_t i = 0; i < m_matchers.size(); ++i ) + if( m_matchers[i]->match( expr ) ) + return true; + return false; + } + virtual std::string toString() const { + std::ostringstream oss; + oss << "( "; + for( std::size_t i = 0; i < m_matchers.size(); ++i ) { + if( i != 0 ) + oss << " or "; + oss << m_matchers[i]->toString(); + } + oss << " )"; + return oss.str(); + } + + AnyOf operator || ( Matcher const& other ) const { + AnyOf anyOfExpr( *this ); + anyOfExpr.add( other ); + return anyOfExpr; + } + + private: + std::vector > > m_matchers; + }; + + } // namespace Generic + + template + Generic::AllOf Matcher::operator && ( Matcher const& other ) const { + Generic::AllOf allOfExpr; + allOfExpr.add( *this ); + allOfExpr.add( other ); + return allOfExpr; + } + + template + Generic::AnyOf Matcher::operator || ( Matcher const& other ) const { + Generic::AnyOf anyOfExpr; + anyOfExpr.add( *this ); + anyOfExpr.add( other ); + return anyOfExpr; + } + + template + Generic::Not Matcher::operator ! () const { + return Generic::Not( *this ); + } + + namespace StdString { + + inline std::string makeString( std::string const& str ) { return str; } + inline std::string makeString( const char* str ) { return str ? std::string( str ) : std::string(); } + + struct CasedString + { + CasedString( std::string const& str, CaseSensitive::Choice caseSensitivity ) + : m_caseSensitivity( caseSensitivity ), + m_str( adjustString( str ) ) + {} + std::string adjustString( std::string const& str ) const { + return m_caseSensitivity == CaseSensitive::No + ? toLower( str ) + : str; + + } + std::string toStringSuffix() const + { + return m_caseSensitivity == CaseSensitive::No + ? " (case insensitive)" + : std::string(); + } + CaseSensitive::Choice m_caseSensitivity; + std::string m_str; + }; + + struct Equals : MatcherImpl { + Equals( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) + : m_data( str, caseSensitivity ) + {} + Equals( Equals const& other ) : m_data( other.m_data ){} + + virtual ~Equals(); + + virtual bool match( std::string const& expr ) const { + return m_data.m_str == m_data.adjustString( expr );; + } + virtual std::string toString() const { + return "equals: \"" + m_data.m_str + '"' + m_data.toStringSuffix(); + } + + CasedString m_data; + }; + + struct Contains : MatcherImpl { + Contains( std::string const& substr, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) + : m_data( substr, caseSensitivity ){} + Contains( Contains const& other ) : m_data( other.m_data ){} + + virtual ~Contains(); + + virtual bool match( std::string const& expr ) const { + return m_data.adjustString( expr ).find( m_data.m_str ) != std::string::npos; + } + virtual std::string toString() const { + return "contains: \"" + m_data.m_str + '"' + m_data.toStringSuffix(); + } + + CasedString m_data; + }; + + struct StartsWith : MatcherImpl { + StartsWith( std::string const& substr, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) + : m_data( substr, caseSensitivity ){} + + StartsWith( StartsWith const& other ) : m_data( other.m_data ){} + + virtual ~StartsWith(); + + virtual bool match( std::string const& expr ) const { + return startsWith( m_data.adjustString( expr ), m_data.m_str ); + } + virtual std::string toString() const { + return "starts with: \"" + m_data.m_str + '"' + m_data.toStringSuffix(); + } + + CasedString m_data; + }; + + struct EndsWith : MatcherImpl { + EndsWith( std::string const& substr, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) + : m_data( substr, caseSensitivity ){} + EndsWith( EndsWith const& other ) : m_data( other.m_data ){} + + virtual ~EndsWith(); + + virtual bool match( std::string const& expr ) const { + return endsWith( m_data.adjustString( expr ), m_data.m_str ); + } + virtual std::string toString() const { + return "ends with: \"" + m_data.m_str + '"' + m_data.toStringSuffix(); + } + + CasedString m_data; + }; + } // namespace StdString + } // namespace Impl + + // The following functions create the actual matcher objects. + // This allows the types to be inferred + template + inline Impl::Generic::Not Not( Impl::Matcher const& m ) { + return Impl::Generic::Not( m ); + } + + template + inline Impl::Generic::AllOf AllOf( Impl::Matcher const& m1, + Impl::Matcher const& m2 ) { + return Impl::Generic::AllOf().add( m1 ).add( m2 ); + } + template + inline Impl::Generic::AllOf AllOf( Impl::Matcher const& m1, + Impl::Matcher const& m2, + Impl::Matcher const& m3 ) { + return Impl::Generic::AllOf().add( m1 ).add( m2 ).add( m3 ); + } + template + inline Impl::Generic::AnyOf AnyOf( Impl::Matcher const& m1, + Impl::Matcher const& m2 ) { + return Impl::Generic::AnyOf().add( m1 ).add( m2 ); + } + template + inline Impl::Generic::AnyOf AnyOf( Impl::Matcher const& m1, + Impl::Matcher const& m2, + Impl::Matcher const& m3 ) { + return Impl::Generic::AnyOf().add( m1 ).add( m2 ).add( m3 ); + } + + inline Impl::StdString::Equals Equals( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) { + return Impl::StdString::Equals( str, caseSensitivity ); + } + inline Impl::StdString::Equals Equals( const char* str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) { + return Impl::StdString::Equals( Impl::StdString::makeString( str ), caseSensitivity ); + } + inline Impl::StdString::Contains Contains( std::string const& substr, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) { + return Impl::StdString::Contains( substr, caseSensitivity ); + } + inline Impl::StdString::Contains Contains( const char* substr, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) { + return Impl::StdString::Contains( Impl::StdString::makeString( substr ), caseSensitivity ); + } + inline Impl::StdString::StartsWith StartsWith( std::string const& substr ) { + return Impl::StdString::StartsWith( substr ); + } + inline Impl::StdString::StartsWith StartsWith( const char* substr ) { + return Impl::StdString::StartsWith( Impl::StdString::makeString( substr ) ); + } + inline Impl::StdString::EndsWith EndsWith( std::string const& substr ) { + return Impl::StdString::EndsWith( substr ); + } + inline Impl::StdString::EndsWith EndsWith( const char* substr ) { + return Impl::StdString::EndsWith( Impl::StdString::makeString( substr ) ); + } + +} // namespace Matchers + +using namespace Matchers; + +} // namespace Catch + +namespace Catch { + + struct TestFailureException{}; + + template 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 = "" ); + + template + ExpressionLhs operator <= ( T const& operand ); + ExpressionLhs operator <= ( bool value ); + + template + ResultBuilder& operator << ( T const& value ) { + m_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::Matcher 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 ); + + private: + AssertionInfo m_assertionInfo; + AssertionResultData m_data; + CopyableStream m_stream; + + bool m_shouldDebugBreak; + bool m_shouldThrow; + }; + +} // namespace Catch + +// Include after due to circular dependency: +// #included from: catch_expression_lhs.hpp +#define TWOBLUECUBES_CATCH_EXPRESSION_LHS_HPP_INCLUDED + +// #included from: catch_evaluate.hpp +#define TWOBLUECUBES_CATCH_EVALUATE_HPP_INCLUDED + +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable:4389) // '==' : signed/unsigned mismatch +#endif + +#include + +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 + inline T& opCast(T const& t) { return const_cast(t); } + +// nullptr_t support based on pull request #154 from Konstantin Baumann +#ifdef CATCH_CONFIG_CPP11_NULLPTR + inline std::nullptr_t opCast(std::nullptr_t) { return nullptr; } +#endif // CATCH_CONFIG_CPP11_NULLPTR + + // So the compare overloads can be operator agnostic we convey the operator as a template + // enum, which is used to specialise an Evaluator for doing the comparison. + template + class Evaluator{}; + + 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__ +// #included from: catch_objc_arc.hpp +#define TWOBLUECUBES_CATCH_OBJC_ARC_HPP_INCLUDED + +#import + +#ifdef __has_feature +#define CATCH_ARC_ENABLED __has_feature(objc_arc) +#else +#define CATCH_ARC_ENABLED 0 +#endif + +void arcSafeRelease( NSObject* obj ); +id performOptionalSelector( id obj, SEL sel ); + +#if !CATCH_ARC_ENABLED +inline void arcSafeRelease( NSObject* obj ) { + [obj release]; +} +inline id performOptionalSelector( id obj, SEL sel ) { + if( [obj respondsToSelector: sel] ) + return [obj performSelector: sel]; + return nil; +} +#define CATCH_UNSAFE_UNRETAINED +#define CATCH_ARC_STRONG +#else +inline void arcSafeRelease( NSObject* ){} +inline id performOptionalSelector( id obj, SEL sel ) { +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Warc-performSelector-leaks" +#endif + if( [obj respondsToSelector: sel] ) + return [obj performSelector: sel]; +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + return nil; +} +#define CATCH_UNSAFE_UNRETAINED __unsafe_unretained +#define CATCH_ARC_STRONG __strong +#endif + +#endif + +#ifdef CATCH_CONFIG_CPP11_TUPLE +#include +#endif + +#ifdef CATCH_CONFIG_CPP11_IS_ENUM +#include +#endif + +namespace Catch { + +// Why we're here. +template +std::string toString( T const& value ); + +// Built in overloads + +std::string toString( std::string const& value ); +std::string toString( std::wstring const& value ); +std::string toString( const char* const value ); +std::string toString( char* const value ); +std::string toString( const wchar_t* const value ); +std::string toString( wchar_t* const value ); +std::string toString( int value ); +std::string toString( unsigned long value ); +std::string toString( unsigned int value ); +std::string toString( const double value ); +std::string toString( const float value ); +std::string toString( bool value ); +std::string toString( char value ); +std::string toString( signed char value ); +std::string toString( unsigned char value ); + +#ifdef CATCH_CONFIG_CPP11_LONG_LONG +std::string toString( long long value ); +std::string toString( unsigned long long value ); +#endif + +#ifdef CATCH_CONFIG_CPP11_NULLPTR +std::string toString( std::nullptr_t ); +#endif + +#ifdef __OBJC__ + std::string toString( NSString const * const& nsstring ); + std::string toString( NSString * CATCH_ARC_STRONG const& nsstring ); + std::string toString( NSObject* const& nsObject ); +#endif + +namespace Detail { + + extern const std::string unprintableString; + + struct BorgType { + template BorgType( T const& ); + }; + + struct TrueType { char sizer[1]; }; + struct FalseType { char sizer[2]; }; + + TrueType& testStreamable( std::ostream& ); + FalseType testStreamable( FalseType ); + + FalseType operator<<( std::ostream const&, BorgType const& ); + + template + struct IsStreamInsertable { + static std::ostream &s; + static T const&t; + enum { value = sizeof( testStreamable(s << t) ) == sizeof( TrueType ) }; + }; + +#if defined(CATCH_CONFIG_CPP11_IS_ENUM) + template::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) + ); + } + }; +#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 + inline 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 + +namespace Catch { + +template +class BinaryExpression; + +template +class MatchExpression; + +// 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) {} + + template + BinaryExpression + operator == ( RhsT const& rhs ) { + return captureExpression( rhs ); + } + + template + BinaryExpression + operator != ( RhsT const& rhs ) { + return captureExpression( rhs ); + } + + template + BinaryExpression + operator < ( RhsT const& rhs ) { + return captureExpression( rhs ); + } + + template + BinaryExpression + operator > ( RhsT const& rhs ) { + return captureExpression( rhs ); + } + + template + BinaryExpression + operator <= ( RhsT const& rhs ) { + return captureExpression( rhs ); + } + + template + BinaryExpression + operator >= ( RhsT const& rhs ) { + return captureExpression( rhs ); + } + + 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_truthy ); + } + +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 ) {} + + 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 + inline ExpressionLhs ResultBuilder::operator <= ( T const& operand ) { + return ExpressionLhs( *this, operand ); + } + + inline ExpressionLhs ResultBuilder::operator <= ( bool value ) { + return ExpressionLhs( *this, value ); + } + + template + inline 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 + +// #included from: catch_message.h +#define TWOBLUECUBES_CATCH_MESSAGE_H_INCLUDED + +#include + +namespace Catch { + + struct MessageInfo { + MessageInfo( std::string const& _macroName, + SourceLineInfo const& _lineInfo, + ResultWas::OfType _type ); + + std::string macroName; + SourceLineInfo lineInfo; + ResultWas::OfType type; + std::string message; + unsigned int sequence; + + bool operator == ( MessageInfo const& other ) const { + return sequence == other.sequence; + } + bool operator < ( MessageInfo const& other ) const { + return sequence < other.sequence; + } + private: + static unsigned int globalCount; + }; + + struct MessageBuilder { + MessageBuilder( std::string const& macroName, + SourceLineInfo const& lineInfo, + ResultWas::OfType type ) + : m_info( macroName, lineInfo, type ) + {} + + template + MessageBuilder& operator << ( T const& value ) { + m_stream << value; + return *this; + } + + MessageInfo m_info; + std::ostringstream m_stream; + }; + + class ScopedMessage { + public: + ScopedMessage( MessageBuilder const& builder ); + ScopedMessage( ScopedMessage const& other ); + ~ScopedMessage(); + + MessageInfo m_info; + }; + +} // end namespace Catch + +// #included from: catch_interfaces_capture.h +#define TWOBLUECUBES_CATCH_INTERFACES_CAPTURE_H_INCLUDED + +#include + +namespace Catch { + + class TestCase; + class AssertionResult; + struct AssertionInfo; + struct SectionInfo; + struct SectionEndInfo; + struct MessageInfo; + class ScopedMessageBuilder; + struct Counts; + + struct IResultCapture { + + virtual ~IResultCapture(); + + virtual void assertionEnded( AssertionResult const& result ) = 0; + virtual bool sectionStarted( SectionInfo const& sectionInfo, + Counts& assertions ) = 0; + virtual void sectionEnded( SectionEndInfo const& endInfo ) = 0; + virtual void sectionEndedEarly( SectionEndInfo const& endInfo ) = 0; + virtual void pushScopedMessage( MessageInfo const& message ) = 0; + virtual void popScopedMessage( MessageInfo const& message ) = 0; + + virtual std::string getCurrentTestName() const = 0; + virtual const AssertionResult* getLastResult() const = 0; + + virtual void handleFatalErrorCondition( std::string const& message ) = 0; + }; + + IResultCapture& getResultCapture(); +} + +// #included from: catch_debugger.h +#define TWOBLUECUBES_CATCH_DEBUGGER_H_INCLUDED + +// #included from: catch_platform.h +#define TWOBLUECUBES_CATCH_PLATFORM_H_INCLUDED + +#if defined(__MAC_OS_X_VERSION_MIN_REQUIRED) +# define CATCH_PLATFORM_MAC +#elif defined(__IPHONE_OS_VERSION_MIN_REQUIRED) +# define CATCH_PLATFORM_IPHONE +#elif defined(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{ + + 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" ) + #else + #define CATCH_TRAP() __asm__("int $3\n" : : ) + #endif + +#elif defined(CATCH_PLATFORM_LINUX) + // If we can use inline assembler, do it because this allows us to break + // directly at the location of the failing check instead of breaking inside + // raise() called from it, i.e. one stack frame below. + #if defined(__GNUC__) && (defined(__i386) || defined(__x86_64)) + #define CATCH_TRAP() asm volatile ("int $3") + #else // Fall back to the generic way. + #include + + #define CATCH_TRAP() raise(SIGTRAP) + #endif +#elif defined(_MSC_VER) + #define CATCH_TRAP() __debugbreak() +#elif defined(__MINGW32__) + extern "C" __declspec(dllimport) void __stdcall DebugBreak(); + #define CATCH_TRAP() DebugBreak() +#endif + +#ifdef CATCH_TRAP + #define CATCH_BREAK_INTO_DEBUGGER() if( Catch::isDebuggerActive() ) { CATCH_TRAP(); } +#else + #define CATCH_BREAK_INTO_DEBUGGER() Catch::alwaysTrue(); +#endif + +// #included from: catch_interfaces_runner.h +#define TWOBLUECUBES_CATCH_INTERFACES_RUNNER_H_INCLUDED + +namespace Catch { + class TestCase; + + struct IRunner { + virtual ~IRunner(); + virtual bool aborting() const = 0; + }; +} + +// #included from: catch_type_traits.hpp +#define TWOBLUECUBES_CATCH_TYPE_TRAITS_HPP_INCLUDED + +#if defined(CATCH_CONFIG_CPP11_TYPE_TRAITS) +#include +#endif + +namespace Catch { + +#if defined(CATCH_CONFIG_CPP11_TYPE_TRAITS) + + template + using add_lvalue_reference = std::add_lvalue_reference; + + template + using add_const = std::add_const; + +#else + + template + struct add_const { + typedef const T type; + }; + + template + struct add_lvalue_reference { + typedef T& type; + }; + template + struct add_lvalue_reference { + typedef T& type; + }; + // No && overload, because that is C++11, in which case we have + // proper type_traits implementation from the standard library + +#endif + +} + +/////////////////////////////////////////////////////////////////////////////// +// In the event of a failure works out if the debugger needs to be invoked +// and/or an exception thrown and takes appropriate action. +// This needs to be done as a macro so the debugger will stop in the user +// source code rather than in Catch library code +#define INTERNAL_CATCH_REACT( resultBuilder ) \ + if( resultBuilder.shouldDebugBreak() ) CATCH_BREAK_INTO_DEBUGGER(); \ + resultBuilder.react(); + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_TEST( expr, resultDisposition, macroName ) \ + do { \ + Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \ + try { \ + CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \ + ( __catchResult <= expr ).endExpression(); \ + } \ + catch( ... ) { \ + __catchResult.useActiveException( 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( expr, resultDisposition, macroName ) \ + INTERNAL_CATCH_TEST( expr, resultDisposition, macroName ); \ + if( Catch::getResultCapture().getLastResult()->succeeded() ) + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_ELSE( expr, resultDisposition, macroName ) \ + INTERNAL_CATCH_TEST( expr, resultDisposition, macroName ); \ + if( !Catch::getResultCapture().getLastResult()->succeeded() ) + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_NO_THROW( expr, resultDisposition, macroName ) \ + do { \ + Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \ + try { \ + static_cast(expr); \ + __catchResult.captureResult( Catch::ResultWas::Ok ); \ + } \ + catch( ... ) { \ + __catchResult.useActiveException( resultDisposition ); \ + } \ + INTERNAL_CATCH_REACT( __catchResult ) \ + } while( Catch::alwaysFalse() ) + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_THROWS( expr, resultDisposition, matcher, macroName ) \ + do { \ + Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition, #matcher ); \ + if( __catchResult.allowThrows() ) \ + try { \ + static_cast(expr); \ + __catchResult.captureResult( Catch::ResultWas::DidntThrowException ); \ + } \ + catch( ... ) { \ + __catchResult.captureExpectedException( matcher ); \ + } \ + else \ + __catchResult.captureResult( Catch::ResultWas::Ok ); \ + INTERNAL_CATCH_REACT( __catchResult ) \ + } while( Catch::alwaysFalse() ) + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_THROWS_AS( expr, exceptionType, resultDisposition, macroName ) \ + do { \ + Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr ", " #exceptionType, resultDisposition ); \ + if( __catchResult.allowThrows() ) \ + try { \ + static_cast(expr); \ + __catchResult.captureResult( Catch::ResultWas::DidntThrowException ); \ + } \ + catch( Catch::add_const::type>::type ) { \ + __catchResult.captureResult( Catch::ResultWas::Ok ); \ + } \ + catch( ... ) { \ + __catchResult.useActiveException( resultDisposition ); \ + } \ + else \ + __catchResult.captureResult( Catch::ResultWas::Ok ); \ + INTERNAL_CATCH_REACT( __catchResult ) \ + } while( Catch::alwaysFalse() ) + +/////////////////////////////////////////////////////////////////////////////// +#ifdef CATCH_CONFIG_VARIADIC_MACROS + #define INTERNAL_CATCH_MSG( messageType, resultDisposition, macroName, ... ) \ + do { \ + Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, "", resultDisposition ); \ + __catchResult << __VA_ARGS__ + ::Catch::StreamEndStop(); \ + __catchResult.captureResult( messageType ); \ + INTERNAL_CATCH_REACT( __catchResult ) \ + } while( Catch::alwaysFalse() ) +#else + #define INTERNAL_CATCH_MSG( messageType, resultDisposition, macroName, log ) \ + do { \ + Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, "", resultDisposition ); \ + __catchResult << log + ::Catch::StreamEndStop(); \ + __catchResult.captureResult( messageType ); \ + INTERNAL_CATCH_REACT( __catchResult ) \ + } while( Catch::alwaysFalse() ) +#endif + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_INFO( log, macroName ) \ + Catch::ScopedMessage INTERNAL_CATCH_UNIQUE_NAME( scopedMessage ) = Catch::MessageBuilder( macroName, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info ) << log; + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CHECK_THAT( arg, matcher, resultDisposition, macroName ) \ + do { \ + Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #arg ", " #matcher, resultDisposition ); \ + try { \ + __catchResult.captureMatch( arg, matcher, #matcher ); \ + } catch( ... ) { \ + __catchResult.useActiveException( resultDisposition | Catch::ResultDisposition::ContinueOnFailure ); \ + } \ + INTERNAL_CATCH_REACT( __catchResult ) \ + } while( Catch::alwaysFalse() ) + +// #included from: internal/catch_section.h +#define TWOBLUECUBES_CATCH_SECTION_H_INCLUDED + +// #included from: catch_section_info.h +#define TWOBLUECUBES_CATCH_SECTION_INFO_H_INCLUDED + +// #included from: catch_totals.hpp +#define TWOBLUECUBES_CATCH_TOTALS_HPP_INCLUDED + +#include + +namespace Catch { + + struct Counts { + Counts() : passed( 0 ), failed( 0 ), failedButOk( 0 ) {} + + Counts operator - ( Counts const& other ) const { + Counts diff; + diff.passed = passed - other.passed; + diff.failed = failed - other.failed; + diff.failedButOk = failedButOk - other.failedButOk; + return diff; + } + Counts& operator += ( Counts const& other ) { + passed += other.passed; + failed += other.failed; + failedButOk += other.failedButOk; + return *this; + } + + std::size_t total() const { + return passed + failed + failedButOk; + } + bool allPassed() const { + return failed == 0 && failedButOk == 0; + } + bool allOk() const { + return failed == 0; + } + + std::size_t passed; + std::size_t failed; + std::size_t failedButOk; + }; + + struct Totals { + + Totals operator - ( Totals const& other ) const { + Totals diff; + diff.assertions = assertions - other.assertions; + diff.testCases = testCases - other.testCases; + return diff; + } + + Totals delta( Totals const& prevTotals ) const { + Totals diff = *this - prevTotals; + if( diff.assertions.failed > 0 ) + ++diff.testCases.failed; + else if( diff.assertions.failedButOk > 0 ) + ++diff.testCases.failedButOk; + else + ++diff.testCases.passed; + return diff; + } + + Totals& operator += ( Totals const& other ) { + assertions += other.assertions; + testCases += other.testCases; + return *this; + } + + Counts assertions; + Counts testCases; + }; +} + +#include + +namespace Catch { + + struct SectionInfo { + SectionInfo + ( SourceLineInfo const& _lineInfo, + std::string const& _name, + std::string const& _description = std::string() ); + + std::string name; + std::string description; + SourceLineInfo lineInfo; + }; + + struct SectionEndInfo { + SectionEndInfo( SectionInfo const& _sectionInfo, Counts const& _prevAssertions, double _durationInSeconds ) + : sectionInfo( _sectionInfo ), prevAssertions( _prevAssertions ), durationInSeconds( _durationInSeconds ) + {} + + SectionInfo sectionInfo; + Counts prevAssertions; + double durationInSeconds; + }; + +} // end namespace Catch + +// #included from: catch_timer.h +#define TWOBLUECUBES_CATCH_TIMER_H_INCLUDED + +#ifdef CATCH_PLATFORM_WINDOWS +typedef unsigned long long uint64_t; +#else +#include +#endif + +namespace Catch { + + class Timer { + public: + Timer() : m_ticks( 0 ) {} + void start(); + unsigned int getElapsedMicroseconds() const; + unsigned int getElapsedMilliseconds() const; + double getElapsedSeconds() const; + + private: + uint64_t m_ticks; + }; + +} // namespace Catch + +#include + +namespace Catch { + + class Section : NonCopyable { + public: + Section( SectionInfo const& info ); + ~Section(); + + // This indicates whether the section should be executed or not + operator bool() const; + + private: + SectionInfo m_info; + + std::string m_name; + Counts m_assertions; + bool m_sectionIncluded; + Timer m_timer; + }; + +} // end namespace Catch + +#ifdef CATCH_CONFIG_VARIADIC_MACROS + #define INTERNAL_CATCH_SECTION( ... ) \ + if( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::SectionInfo( CATCH_INTERNAL_LINEINFO, __VA_ARGS__ ) ) +#else + #define INTERNAL_CATCH_SECTION( name, desc ) \ + if( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::SectionInfo( CATCH_INTERNAL_LINEINFO, name, desc ) ) +#endif + +// #included from: internal/catch_generators.hpp +#define TWOBLUECUBES_CATCH_GENERATORS_HPP_INCLUDED + +#include +#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; +}; + +template +class BetweenGenerator : public IGenerator { +public: + BetweenGenerator( T from, T to ) : m_from( from ), m_to( to ){} + + virtual T getValue( std::size_t index ) const { + return m_from+static_cast( index ); + } + + virtual 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 ) + { + 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 + } + + void add( const IGenerator* generator ) { + m_totalSize += generator->size(); + m_composed.push_back( generator ); + } + + CompositeGenerator& then( CompositeGenerator& other ) { + move( other ); + return *this; + } + + CompositeGenerator& then( T value ) { + ValuesGenerator* valuesGen = new ValuesGenerator(); + valuesGen->add( value ); + add( valuesGen ); + return *this; + } + +private: + + void move( CompositeGenerator& other ) { + std::copy( other.m_composed.begin(), other.m_composed.end(), std::back_inserter( m_composed ) ); + m_totalSize += other.m_totalSize; + other.m_composed.clear(); + } + + std::vector*> 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 INTERNAL_CATCH_LINESTR2( line ) #line +#define INTERNAL_CATCH_LINESTR( line ) INTERNAL_CATCH_LINESTR2( line ) + +#define INTERNAL_CATCH_GENERATE( expr ) expr.setFileInfo( __FILE__ "(" INTERNAL_CATCH_LINESTR( __LINE__ ) ")" ) + +// #included from: internal/catch_interfaces_exception.h +#define TWOBLUECUBES_CATCH_INTERFACES_EXCEPTION_H_INCLUDED + +#include +#include + +// #included from: catch_interfaces_registry_hub.h +#define TWOBLUECUBES_CATCH_INTERFACES_REGISTRY_HUB_H_INCLUDED + +#include + +namespace Catch { + + class TestCase; + struct ITestCaseRegistry; + struct IExceptionTranslatorRegistry; + struct IExceptionTranslator; + struct IReporterRegistry; + struct IReporterFactory; + + struct IRegistryHub { + virtual ~IRegistryHub(); + + virtual IReporterRegistry const& getReporterRegistry() const = 0; + virtual ITestCaseRegistry const& getTestCaseRegistry() const = 0; + virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() = 0; + }; + + struct IMutableRegistryHub { + virtual ~IMutableRegistryHub(); + virtual void registerReporter( std::string const& name, Ptr const& factory ) = 0; + virtual void registerListener( Ptr const& factory ) = 0; + virtual void registerTest( TestCase const& testInfo ) = 0; + virtual void registerTranslator( const IExceptionTranslator* translator ) = 0; + }; + + IRegistryHub& getRegistryHub(); + IMutableRegistryHub& getMutableRegistryHub(); + void cleanUp(); + std::string translateActiveException(); + +} + +namespace Catch { + + typedef std::string(*exceptionTranslateFunction)(); + + struct IExceptionTranslator; + typedef std::vector ExceptionTranslators; + + struct IExceptionTranslator { + virtual ~IExceptionTranslator(); + virtual std::string translate( ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd ) const = 0; + }; + + struct IExceptionTranslatorRegistry { + virtual ~IExceptionTranslatorRegistry(); + + virtual std::string translateActiveException() const = 0; + }; + + class ExceptionTranslatorRegistrar { + template + class ExceptionTranslator : public IExceptionTranslator { + public: + + ExceptionTranslator( std::string(*translateFunction)( T& ) ) + : m_translateFunction( translateFunction ) + {} + + virtual std::string translate( ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd ) const CATCH_OVERRIDE { + try { + if( it == itEnd ) + throw; + else + return (*it)->translate( it+1, itEnd ); + } + catch( T& ex ) { + return m_translateFunction( ex ); + } + } + + protected: + std::string(*m_translateFunction)( T& ); + }; + + public: + template + ExceptionTranslatorRegistrar( std::string(*translateFunction)( T& ) ) { + getMutableRegistryHub().registerTranslator + ( new ExceptionTranslator( translateFunction ) ); + } + }; +} + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_TRANSLATE_EXCEPTION2( translatorName, signature ) \ + static std::string translatorName( signature ); \ + namespace{ Catch::ExceptionTranslatorRegistrar INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionRegistrar )( &translatorName ); }\ + static std::string translatorName( signature ) + +#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 + +#include +#include + +#if defined(CATCH_CONFIG_CPP11_TYPE_TRAITS) +#include +#endif + +namespace Catch { +namespace Detail { + + class Approx { + public: + explicit Approx ( double value ) + : m_epsilon( std::numeric_limits::epsilon()*100 ), + m_scale( 1.0 ), + m_value( value ) + {} + + Approx( Approx const& other ) + : m_epsilon( other.m_epsilon ), + m_scale( other.m_scale ), + m_value( other.m_value ) + {} + + static Approx custom() { + return Approx( 0 ); + } + + Approx operator()( double value ) { + Approx approx( value ); + approx.epsilon( m_epsilon ); + approx.scale( m_scale ); + return approx; + } + +#if defined(CATCH_CONFIG_CPP11_TYPE_TRAITS) + 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); + return std::fabs( lhs_v - rhs.m_value ) < rhs.m_epsilon * (rhs.m_scale + (std::max)( std::fabs(lhs_v), std::fabs(rhs.m_value) ) ); + } + + template ::value>::type> + friend bool operator == ( Approx const& lhs, const T& rhs ) { + return operator==( rhs, lhs ); + } + + template ::value>::type> + friend bool operator != ( T lhs, Approx const& rhs ) { + return !operator==( lhs, rhs ); + } + + template ::value>::type> + friend bool operator != ( Approx const& lhs, T rhs ) { + return !operator==( rhs, lhs ); + } + + template ::value>::type> + 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 rhs ) + { + return lhs.m_value < double(rhs) || lhs == rhs; + } + + template ::value>::type> + 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 rhs ) + { + return lhs.m_value > double(rhs) || lhs == rhs; + } +#else + friend bool operator == ( double lhs, Approx const& rhs ) { + // Thanks to Richard Harris for his help refining this formula + return std::fabs( lhs - rhs.m_value ) < rhs.m_epsilon * (rhs.m_scale + (std::max)( std::fabs(lhs), std::fabs(rhs.m_value) ) ); + } + + friend bool operator == ( Approx const& lhs, double rhs ) { + return operator==( rhs, lhs ); + } + + friend bool operator != ( double lhs, Approx const& rhs ) { + return !operator==( lhs, rhs ); + } + + friend bool operator != ( Approx const& lhs, double rhs ) { + return !operator==( rhs, lhs ); + } + + 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; + } +#endif + + Approx& epsilon( double newEpsilon ) { + m_epsilon = newEpsilon; + return *this; + } + + Approx& scale( double newScale ) { + m_scale = newScale; + return *this; + } + + std::string toString() const { + std::ostringstream oss; + oss << "Approx( " << Catch::toString( m_value ) << " )"; + return oss.str(); + } + + private: + double m_epsilon; + double m_scale; + double m_value; + }; +} + +template<> +inline std::string toString( Detail::Approx const& value ) { + return value.toString(); +} + +} // end namespace Catch + +// #included from: internal/catch_interfaces_tag_alias_registry.h +#define TWOBLUECUBES_CATCH_INTERFACES_TAG_ALIAS_REGISTRY_H_INCLUDED + +// #included from: catch_tag_alias.h +#define TWOBLUECUBES_CATCH_TAG_ALIAS_H_INCLUDED + +#include + +namespace Catch { + + struct TagAlias { + TagAlias( std::string _tag, SourceLineInfo _lineInfo ) : tag( _tag ), lineInfo( _lineInfo ) {} + + std::string tag; + SourceLineInfo lineInfo; + }; + + struct RegistrarForTagAliases { + RegistrarForTagAliases( char const* alias, char const* tag, SourceLineInfo const& lineInfo ); + }; + +} // end namespace Catch + +#define CATCH_REGISTER_TAG_ALIAS( alias, spec ) namespace{ Catch::RegistrarForTagAliases INTERNAL_CATCH_UNIQUE_NAME( AutoRegisterTagAlias )( alias, spec, CATCH_INTERNAL_LINEINFO ); } +// #included from: catch_option.hpp +#define TWOBLUECUBES_CATCH_OPTION_HPP_INCLUDED + +namespace Catch { + + // An optional type + template + class Option { + public: + Option() : nullableValue( CATCH_NULL ) {} + Option( T const& _value ) + : nullableValue( new( storage ) T( _value ) ) + {} + Option( Option const& _other ) + : nullableValue( _other ? new( storage ) T( *_other ) : CATCH_NULL ) + {} + + ~Option() { + reset(); + } + + Option& operator= ( Option const& _other ) { + if( &_other != this ) { + reset(); + if( _other ) + nullableValue = new( storage ) T( *_other ); + } + return *this; + } + Option& operator = ( T const& _value ) { + reset(); + nullableValue = new( storage ) T( _value ); + return *this; + } + + void reset() { + if( nullableValue ) + nullableValue->~T(); + nullableValue = CATCH_NULL; + } + + T& operator*() { return *nullableValue; } + T const& operator*() const { return *nullableValue; } + T* operator->() { return nullableValue; } + const T* operator->() const { return nullableValue; } + + T valueOr( T const& defaultValue ) const { + return nullableValue ? *nullableValue : defaultValue; + } + + bool some() const { return nullableValue != CATCH_NULL; } + bool none() const { return nullableValue == CATCH_NULL; } + + bool operator !() const { return nullableValue == CATCH_NULL; } + operator SafeBool::type() const { + return SafeBool::makeSafe( some() ); + } + + private: + T* nullableValue; + char storage[sizeof(T)]; + }; + +} // end namespace Catch + +namespace Catch { + + struct ITagAliasRegistry { + virtual ~ITagAliasRegistry(); + virtual Option find( std::string const& alias ) const = 0; + virtual std::string expandAliases( std::string const& unexpandedTestSpec ) const = 0; + + static ITagAliasRegistry const& get(); + }; + +} // end namespace Catch + +// These files are included here so the single_include script doesn't put them +// in the conditionally compiled sections +// #included from: internal/catch_test_case_info.h +#define TWOBLUECUBES_CATCH_TEST_CASE_INFO_H_INCLUDED + +#include +#include + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wpadded" +#endif + +namespace Catch { + + struct ITestCase; + + struct TestCaseInfo { + enum SpecialProperties{ + None = 0, + IsHidden = 1 << 1, + ShouldFail = 1 << 2, + MayFail = 1 << 3, + Throws = 1 << 4, + NonPortable = 1 << 5 + }; + + TestCaseInfo( std::string const& _name, + std::string const& _className, + std::string const& _description, + std::set const& _tags, + SourceLineInfo const& _lineInfo ); + + 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 name; + std::string className; + std::string description; + std::set tags; + std::set lcaseTags; + std::string tagsAsString; + SourceLineInfo lineInfo; + SpecialProperties properties; + }; + + class TestCase : public TestCaseInfo { + public: + + TestCase( ITestCase* testCase, TestCaseInfo const& info ); + TestCase( TestCase const& other ); + + TestCase withName( std::string const& _newName ) const; + + void invoke() const; + + TestCaseInfo const& getTestCaseInfo() const; + + void swap( TestCase& other ); + bool operator == ( TestCase const& other ) const; + bool operator < ( TestCase const& other ) const; + TestCase& operator = ( TestCase const& other ); + + private: + Ptr test; + }; + + TestCase makeTestCase( ITestCase* testCase, + std::string const& className, + std::string const& name, + std::string const& description, + SourceLineInfo const& lineInfo ); +} + +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + + +#ifdef __OBJC__ +// #included from: internal/catch_objc.hpp +#define TWOBLUECUBES_CATCH_OBJC_HPP_INCLUDED + +#import + +#include + +// NB. Any general catch headers included here must be included +// in catch.hpp first to make sure they are included by the single +// header for non obj-usage + +/////////////////////////////////////////////////////////////////////////////// +// This protocol is really only here for (self) documenting purposes, since +// all its methods are optional. +@protocol OcFixture + +@optional + +-(void) setUp; +-(void) tearDown; + +@end + +namespace Catch { + + class OcMethod : public SharedImpl { + + public: + OcMethod( Class cls, SEL sel ) : m_cls( cls ), m_sel( sel ) {} + + virtual void invoke() const { + id obj = [[m_cls alloc] init]; + + performOptionalSelector( obj, @selector(setUp) ); + performOptionalSelector( obj, m_sel ); + performOptionalSelector( obj, @selector(tearDown) ); + + arcSafeRelease( obj ); + } + private: + virtual ~OcMethod() {} + + Class m_cls; + SEL m_sel; + }; + + namespace Detail{ + + inline std::string getAnnotation( Class cls, + std::string const& annotationName, + std::string const& testCaseName ) { + NSString* selStr = [[NSString alloc] initWithFormat:@"Catch_%s_%s", annotationName.c_str(), testCaseName.c_str()]; + SEL sel = NSSelectorFromString( selStr ); + arcSafeRelease( selStr ); + id value = performOptionalSelector( cls, sel ); + if( value ) + return [(NSString*)value UTF8String]; + return ""; + } + } + + inline size_t registerTestMethods() { + size_t noTestMethods = 0; + int noClasses = objc_getClassList( CATCH_NULL, 0 ); + + Class* classes = (CATCH_UNSAFE_UNRETAINED Class *)malloc( sizeof(Class) * noClasses); + objc_getClassList( classes, noClasses ); + + for( int c = 0; c < noClasses; c++ ) { + Class cls = classes[c]; + { + u_int count; + Method* methods = class_copyMethodList( cls, &count ); + for( u_int m = 0; m < count ; m++ ) { + SEL selector = method_getName(methods[m]); + std::string methodName = sel_getName(selector); + if( startsWith( methodName, "Catch_TestCase_" ) ) { + std::string testCaseName = methodName.substr( 15 ); + std::string name = Detail::getAnnotation( cls, "Name", testCaseName ); + std::string desc = Detail::getAnnotation( cls, "Description", testCaseName ); + const char* className = class_getName( cls ); + + getMutableRegistryHub().registerTest( makeTestCase( new OcMethod( cls, selector ), className, name.c_str(), desc.c_str(), SourceLineInfo() ) ); + noTestMethods++; + } + } + free(methods); + } + } + return noTestMethods; + } + + namespace Matchers { + namespace Impl { + namespace NSStringMatchers { + + template + struct StringHolder : MatcherImpl{ + StringHolder( NSString* substr ) : m_substr( [substr copy] ){} + StringHolder( StringHolder const& other ) : m_substr( [other.m_substr copy] ){} + StringHolder() { + arcSafeRelease( m_substr ); + } + + NSString* m_substr; + }; + + struct Equals : StringHolder { + Equals( NSString* substr ) : StringHolder( substr ){} + + virtual bool match( ExpressionType const& str ) const { + return (str != nil || m_substr == nil ) && + [str isEqualToString:m_substr]; + } + + virtual std::string toString() const { + return "equals string: " + Catch::toString( m_substr ); + } + }; + + struct Contains : StringHolder { + Contains( NSString* substr ) : StringHolder( substr ){} + + virtual bool match( ExpressionType const& str ) const { + return (str != nil || m_substr == nil ) && + [str rangeOfString:m_substr].location != NSNotFound; + } + + virtual std::string toString() const { + return "contains string: " + Catch::toString( m_substr ); + } + }; + + struct StartsWith : StringHolder { + StartsWith( NSString* substr ) : StringHolder( substr ){} + + virtual bool match( ExpressionType const& str ) const { + return (str != nil || m_substr == nil ) && + [str rangeOfString:m_substr].location == 0; + } + + virtual std::string toString() const { + return "starts with: " + Catch::toString( m_substr ); + } + }; + struct EndsWith : StringHolder { + EndsWith( NSString* substr ) : StringHolder( substr ){} + + virtual bool match( ExpressionType const& str ) const { + return (str != nil || m_substr == nil ) && + [str rangeOfString:m_substr].location == [str length] - [m_substr length]; + } + + virtual std::string toString() const { + return "ends with: " + Catch::toString( m_substr ); + } + }; + + } // namespace NSStringMatchers + } // namespace Impl + + inline Impl::NSStringMatchers::Equals + Equals( NSString* substr ){ return Impl::NSStringMatchers::Equals( substr ); } + + inline Impl::NSStringMatchers::Contains + Contains( NSString* substr ){ return Impl::NSStringMatchers::Contains( substr ); } + + inline Impl::NSStringMatchers::StartsWith + StartsWith( NSString* substr ){ return Impl::NSStringMatchers::StartsWith( substr ); } + + inline Impl::NSStringMatchers::EndsWith + EndsWith( NSString* substr ){ return Impl::NSStringMatchers::EndsWith( substr ); } + + } // namespace Matchers + + using namespace Matchers; + +} // namespace Catch + +/////////////////////////////////////////////////////////////////////////////// +#define OC_TEST_CASE( name, desc )\ ++(NSString*) INTERNAL_CATCH_UNIQUE_NAME( Catch_Name_test ) \ +{\ +return @ name; \ +}\ ++(NSString*) INTERNAL_CATCH_UNIQUE_NAME( Catch_Description_test ) \ +{ \ +return @ desc; \ +} \ +-(void) INTERNAL_CATCH_UNIQUE_NAME( Catch_TestCase_test ) + +#endif + +#ifdef CATCH_IMPL +// #included from: internal/catch_impl.hpp +#define TWOBLUECUBES_CATCH_IMPL_HPP_INCLUDED + +// Collect all the implementation files together here +// These are the equivalent of what would usually be cpp files + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wweak-vtables" +#endif + +// #included from: ../catch_session.hpp +#define TWOBLUECUBES_CATCH_RUNNER_HPP_INCLUDED + +// #included from: internal/catch_commandline.hpp +#define TWOBLUECUBES_CATCH_COMMANDLINE_HPP_INCLUDED + +// #included from: catch_config.hpp +#define TWOBLUECUBES_CATCH_CONFIG_HPP_INCLUDED + +// #included from: catch_test_spec_parser.hpp +#define TWOBLUECUBES_CATCH_TEST_SPEC_PARSER_HPP_INCLUDED + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wpadded" +#endif + +// #included from: catch_test_spec.hpp +#define TWOBLUECUBES_CATCH_TEST_SPEC_HPP_INCLUDED + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wpadded" +#endif + +// #included from: catch_wildcard_pattern.hpp +#define TWOBLUECUBES_CATCH_WILDCARD_PATTERN_HPP_INCLUDED + +#include + +namespace Catch +{ + class WildcardPattern { + enum WildcardPosition { + NoWildcard = 0, + WildcardAtStart = 1, + WildcardAtEnd = 2, + WildcardAtBothEnds = WildcardAtStart | WildcardAtEnd + }; + + public: + + WildcardPattern( std::string const& pattern, CaseSensitive::Choice caseSensitivity ) + : m_caseSensitivity( caseSensitivity ), + m_wildcard( NoWildcard ), + m_pattern( adjustCase( pattern ) ) + { + if( startsWith( m_pattern, '*' ) ) { + m_pattern = m_pattern.substr( 1 ); + m_wildcard = WildcardAtStart; + } + if( endsWith( m_pattern, '*' ) ) { + m_pattern = m_pattern.substr( 0, m_pattern.size()-1 ); + m_wildcard = static_cast( m_wildcard | WildcardAtEnd ); + } + } + virtual ~WildcardPattern(); + virtual bool matches( std::string const& str ) const { + switch( m_wildcard ) { + case NoWildcard: + return m_pattern == adjustCase( str ); + case WildcardAtStart: + return endsWith( adjustCase( str ), m_pattern ); + case WildcardAtEnd: + return startsWith( adjustCase( str ), m_pattern ); + case WildcardAtBothEnds: + return contains( adjustCase( str ), m_pattern ); + } + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunreachable-code" +#endif + throw std::logic_error( "Unknown enum" ); +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + } + private: + std::string adjustCase( std::string const& str ) const { + return m_caseSensitivity == CaseSensitive::No ? toLower( str ) : str; + } + CaseSensitive::Choice m_caseSensitivity; + WildcardPosition m_wildcard; + std::string m_pattern; + }; +} + +#include +#include + +namespace Catch { + + class TestSpec { + struct Pattern : SharedImpl<> { + virtual ~Pattern(); + virtual bool matches( TestCaseInfo const& testCase ) const = 0; + }; + class NamePattern : public Pattern { + public: + NamePattern( std::string const& name ) + : m_wildcardPattern( toLower( name ), CaseSensitive::No ) + {} + virtual ~NamePattern(); + virtual bool matches( TestCaseInfo const& testCase ) const { + return m_wildcardPattern.matches( toLower( testCase.name ) ); + } + private: + WildcardPattern m_wildcardPattern; + }; + + class TagPattern : public Pattern { + public: + TagPattern( std::string const& tag ) : m_tag( toLower( tag ) ) {} + virtual ~TagPattern(); + virtual bool matches( TestCaseInfo const& testCase ) const { + return testCase.lcaseTags.find( m_tag ) != testCase.lcaseTags.end(); + } + private: + std::string m_tag; + }; + + class ExcludedPattern : public Pattern { + public: + ExcludedPattern( Ptr const& underlyingPattern ) : m_underlyingPattern( underlyingPattern ) {} + virtual ~ExcludedPattern(); + virtual bool matches( TestCaseInfo const& testCase ) const { return !m_underlyingPattern->matches( testCase ); } + private: + Ptr m_underlyingPattern; + }; + + struct Filter { + std::vector > m_patterns; + + bool matches( TestCaseInfo const& testCase ) const { + // All patterns in a filter must match for the filter to be a match + for( std::vector >::const_iterator it = m_patterns.begin(), itEnd = m_patterns.end(); it != itEnd; ++it ) { + if( !(*it)->matches( testCase ) ) + return false; + } + return true; + } + }; + + public: + bool hasFilters() const { + return !m_filters.empty(); + } + bool matches( TestCaseInfo const& testCase ) const { + // A TestSpec matches if any filter matches + for( std::vector::const_iterator it = m_filters.begin(), itEnd = m_filters.end(); it != itEnd; ++it ) + if( it->matches( testCase ) ) + return true; + return false; + } + + private: + std::vector m_filters; + + friend class TestSpecParser; + }; +} + +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + +namespace Catch { + + class TestSpecParser { + enum Mode{ None, Name, QuotedName, Tag, EscapedName }; + 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; + + public: + TestSpecParser( ITagAliasRegistry const& tagAliases ) : m_tagAliases( &tagAliases ) {} + + TestSpecParser& parse( std::string const& arg ) { + m_mode = None; + m_exclusion = false; + m_start = std::string::npos; + m_arg = m_tagAliases->expandAliases( arg ); + 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 ); } + template + void addPattern() { + std::string token = subString(); + for( size_t i = 0; i < m_escapeChars.size(); ++i ) + token = token.substr( 0, m_escapeChars[i]-i ) + token.substr( m_escapeChars[i]+1-i ); + m_escapeChars.clear(); + if( startsWith( token, "exclude:" ) ) { + m_exclusion = true; + token = token.substr( 8 ); + } + if( !token.empty() ) { + Ptr pattern = new T( token ); + if( m_exclusion ) + pattern = new TestSpec::ExcludedPattern( pattern ); + m_currentFilter.m_patterns.push_back( pattern ); + } + m_exclusion = false; + m_mode = None; + } + void addFilter() { + if( !m_currentFilter.m_patterns.empty() ) { + m_testSpec.m_filters.push_back( m_currentFilter ); + m_currentFilter = TestSpec::Filter(); + } + } + }; + inline TestSpec parseTestSpec( std::string const& arg ) { + return TestSpecParser( ITagAliasRegistry::get() ).parse( arg ).testSpec(); + } + +} // namespace Catch + +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + +// #included from: catch_interfaces_config.h +#define TWOBLUECUBES_CATCH_INTERFACES_CONFIG_H_INCLUDED + +#include +#include +#include + +namespace Catch { + + struct Verbosity { enum Level { + NoOutput = 0, + Quiet, + Normal + }; }; + + struct WarnAbout { enum What { + Nothing = 0x00, + NoAssertions = 0x01 + }; }; + + struct ShowDurations { enum OrNot { + DefaultForReporter, + Always, + Never + }; }; + struct RunTests { enum InWhatOrder { + InDeclarationOrder, + InLexicographicalOrder, + InRandomOrder + }; }; + struct UseColour { enum YesOrNo { + Auto, + Yes, + No + }; }; + + class TestSpec; + + struct IConfig : IShared { + + virtual ~IConfig(); + + virtual bool allowThrows() const = 0; + virtual std::ostream& stream() const = 0; + virtual std::string name() const = 0; + virtual bool includeSuccessfulResults() const = 0; + virtual bool shouldDebugBreak() const = 0; + virtual bool warnAboutMissingAssertions() const = 0; + virtual int abortAfter() const = 0; + virtual bool showInvisibles() const = 0; + virtual ShowDurations::OrNot showDurations() const = 0; + virtual TestSpec const& testSpec() const = 0; + virtual RunTests::InWhatOrder runOrder() const = 0; + virtual unsigned int rngSeed() const = 0; + virtual UseColour::YesOrNo useColour() const = 0; + virtual std::vector const& getSectionsToRun() const = 0; + + }; +} + +// #included from: catch_stream.h +#define TWOBLUECUBES_CATCH_STREAM_H_INCLUDED + +// #included from: catch_streambuf.h +#define TWOBLUECUBES_CATCH_STREAMBUF_H_INCLUDED + +#include + +namespace Catch { + + class StreamBufBase : public std::streambuf { + public: + virtual ~StreamBufBase() CATCH_NOEXCEPT; + }; +} + +#include +#include +#include +#include + +namespace Catch { + + std::ostream& cout(); + std::ostream& cerr(); + + struct IStream { + virtual ~IStream() CATCH_NOEXCEPT; + virtual std::ostream& stream() const = 0; + }; + + class FileStream : public IStream { + mutable std::ofstream m_ofs; + public: + FileStream( std::string const& filename ); + virtual ~FileStream() CATCH_NOEXCEPT; + public: // IStream + virtual std::ostream& stream() const CATCH_OVERRIDE; + }; + + class CoutStream : public IStream { + mutable std::ostream m_os; + public: + CoutStream(); + virtual ~CoutStream() CATCH_NOEXCEPT; + + public: // IStream + virtual std::ostream& stream() const CATCH_OVERRIDE; + }; + + class DebugOutStream : public IStream { + CATCH_AUTO_PTR( StreamBufBase ) m_streamBuf; + mutable std::ostream m_os; + public: + DebugOutStream(); + virtual ~DebugOutStream() CATCH_NOEXCEPT; + + public: // IStream + virtual std::ostream& stream() const CATCH_OVERRIDE; + }; +} + +#include +#include +#include +#include + +#ifndef CATCH_CONFIG_CONSOLE_WIDTH +#define CATCH_CONFIG_CONSOLE_WIDTH 80 +#endif + +namespace Catch { + + struct ConfigData { + + ConfigData() + : listTests( false ), + listTags( false ), + listReporters( false ), + listTestNamesOnly( false ), + showSuccessfulTests( false ), + shouldDebugBreak( false ), + noThrow( false ), + showHelp( false ), + showInvisibles( false ), + filenamesAsTags( false ), + abortAfter( -1 ), + rngSeed( 0 ), + verbosity( Verbosity::Normal ), + warnings( WarnAbout::Nothing ), + showDurations( ShowDurations::DefaultForReporter ), + runOrder( RunTests::InDeclarationOrder ), + useColour( UseColour::Auto ) + {} + + bool listTests; + bool listTags; + bool listReporters; + bool listTestNamesOnly; + + bool showSuccessfulTests; + bool shouldDebugBreak; + bool noThrow; + bool showHelp; + bool showInvisibles; + bool filenamesAsTags; + + int abortAfter; + unsigned int rngSeed; + + Verbosity::Level verbosity; + WarnAbout::What warnings; + ShowDurations::OrNot showDurations; + RunTests::InWhatOrder runOrder; + UseColour::YesOrNo useColour; + + std::string outputFilename; + std::string name; + std::string processName; + + std::vector reporterNames; + std::vector testsOrTags; + std::vector sectionsToRun; + }; + + class Config : public SharedImpl { + private: + Config( Config const& other ); + Config& operator = ( Config const& other ); + virtual void dummy(); + public: + + Config() + {} + + Config( ConfigData const& data ) + : m_data( data ), + m_stream( openStream() ) + { + if( !data.testsOrTags.empty() ) { + TestSpecParser parser( ITagAliasRegistry::get() ); + for( std::size_t i = 0; i < data.testsOrTags.size(); ++i ) + parser.parse( data.testsOrTags[i] ); + m_testSpec = parser.testSpec(); + } + } + + virtual ~Config() {} + + std::string const& getFilename() const { + return m_data.outputFilename ; + } + + bool listTests() const { return m_data.listTests; } + bool listTestNamesOnly() const { return m_data.listTestNamesOnly; } + bool listTags() const { return m_data.listTags; } + bool listReporters() const { return m_data.listReporters; } + + std::string getProcessName() const { return m_data.processName; } + + 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 + 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() { + 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; + + CATCH_AUTO_PTR( IStream const ) m_stream; + TestSpec m_testSpec; + }; + +} // end namespace Catch + +// #included from: catch_clara.h +#define TWOBLUECUBES_CATCH_CLARA_H_INCLUDED + +// Use Catch's value for console width (store Clara's off to the side, if present) +#ifdef CLARA_CONFIG_CONSOLE_WIDTH +#define CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH CLARA_CONFIG_CONSOLE_WIDTH +#undef CLARA_CONFIG_CONSOLE_WIDTH +#endif +#define CLARA_CONFIG_CONSOLE_WIDTH CATCH_CONFIG_CONSOLE_WIDTH + +// Declare Clara inside the Catch namespace +#define STITCH_CLARA_OPEN_NAMESPACE namespace Catch { +// #included from: ../external/clara.h + +// Version 0.0.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 +#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(); + } + + 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 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( ::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( 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[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-reporters"] + .describe( "list all reporters" ) + .bind( &ConfigData::listReporters ); + + cli["--order"] + .describe( "test case order (defaults to decl)" ) + .bind( &setOrder, "decl|lex|rand" ); + + cli["--rng-seed"] + .describe( "set a specific seed for random numbers" ) + .bind( &setRngSeed, "'time'|number" ); + + cli["--force-colour"] + .describe( "force colourised output (deprecated)" ) + .bind( &forceColour ); + + cli["--use-colour"] + .describe( "should output be colourised" ) + .bind( &setUseColour, "yes|no" ); + + return cli; + } + +} // end namespace Catch + +// #included from: internal/catch_list.hpp +#define TWOBLUECUBES_CATCH_LIST_HPP_INCLUDED + +// #included from: catch_text.h +#define TWOBLUECUBES_CATCH_TEXT_H_INCLUDED + +#define TBC_TEXT_FORMAT_CONSOLE_WIDTH CATCH_CONFIG_CONSOLE_WIDTH + +#define CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE Catch +// #included from: ../external/tbc_text_format.h +// Only use header guard if we are not using an outer namespace +#ifndef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE +# ifdef TWOBLUECUBES_TEXT_FORMAT_H_INCLUDED +# ifndef TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED +# define TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED +# endif +# else +# define TWOBLUECUBES_TEXT_FORMAT_H_INCLUDED +# endif +#endif +#ifndef TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED +#include +#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 { + + struct Colour { + enum Code { + None = 0, + + White, + Red, + Green, + Blue, + Cyan, + Yellow, + Grey, + + Bright = 0x10, + + BrightRed = Bright | Red, + BrightGreen = Bright | Green, + LightGrey = Bright | Grey, + BrightWhite = Bright | White, + + // By intention + FileName = LightGrey, + Warning = Yellow, + ResultError = BrightRed, + ResultSuccess = BrightGreen, + ResultExpectedFailure = Warning, + + Error = BrightRed, + Success = Green, + + OriginalExpression = Cyan, + ReconstructedExpression = Yellow, + + SecondaryText = LightGrey, + Headers = White + }; + + // Use constructed object for RAII guard + Colour( Code _colourCode ); + Colour( Colour const& other ); + ~Colour(); + + // Use static method for one-shot changes + static void use( Code _colourCode ); + + private: + bool m_moved; + }; + + inline std::ostream& operator << ( std::ostream& os, Colour const& ) { return os; } + +} // end namespace Catch + +// #included from: catch_interfaces_reporter.h +#define TWOBLUECUBES_CATCH_INTERFACES_REPORTER_H_INCLUDED + +#include +#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 ) { + + TestSpec testSpec = config.testSpec(); + if( config.testSpec().hasFilters() ) + Catch::cout() << "Matching test cases:\n"; + else { + Catch::cout() << "All available test cases:\n"; + testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "*" ).testSpec(); + } + + std::size_t matchedTests = 0; + TextAttributes nameAttr, tagsAttr; + nameAttr.setInitialIndent( 2 ).setIndent( 4 ); + tagsAttr.setIndent( 6 ); + + std::vector 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( !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 << '"' << std::endl; + else + Catch::cout() << testCaseInfo.name << std::endl; + } + return matchedTests; + } + + struct TagInfo { + TagInfo() : count ( 0 ) {} + void add( std::string const& spelling ) { + ++count; + spellings.insert( spelling ); + } + std::string all() const { + std::string out; + for( std::set::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(); + } + + std::map tagCounts; + + 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 ); + } + } + + 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(); + } + + inline std::size_t listReporters( Config const& /*config*/ ) { + Catch::cout() << "Available reporters:\n"; + IReporterRegistry::FactoryMap const& factories = getRegistryHub().getReporterRegistry().getFactories(); + IReporterRegistry::FactoryMap::const_iterator itBegin = factories.begin(), itEnd = factories.end(), it; + std::size_t maxNameLen = 0; + for(it = itBegin; it != itEnd; ++it ) + maxNameLen = (std::max)( maxNameLen, it->first.size() ); + + for(it = itBegin; it != itEnd; ++it ) { + Text wrapper( it->second->getDescription(), TextAttributes() + .setInitialIndent( 0 ) + .setIndent( 7+maxNameLen ) + .setWidth( CATCH_CONFIG_CONSOLE_WIDTH - maxNameLen-8 ) ); + Catch::cout() << " " + << it->first + << ':' + << std::string( maxNameLen - it->first.size() + 2, ' ' ) + << wrapper << '\n'; + } + Catch::cout() << std::endl; + return factories.size(); + } + + inline Option 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 + +// #included from: internal/catch_run_context.hpp +#define TWOBLUECUBES_CATCH_RUNNER_IMPL_HPP_INCLUDED + +// #included from: catch_test_case_tracker.hpp +#define TWOBLUECUBES_CATCH_TEST_CASE_TRACKER_HPP_INCLUDED + +#include +#include +#include +#include +#include +#include + +namespace Catch { +namespace TestCaseTracking { + + struct NameAndLocation { + std::string name; + SourceLineInfo location; + + NameAndLocation( std::string const& _name, SourceLineInfo const& _location ) + : name( _name ), + location( _location ) + {} + }; + + struct ITracker : SharedImpl<> { + virtual ~ITracker(); + + // static queries + virtual NameAndLocation const& nameAndLocation() const = 0; + + // dynamic queries + virtual bool isComplete() const = 0; // Successfully completed or failed + virtual bool isSuccessfullyCompleted() const = 0; + virtual bool isOpen() const = 0; // Started but not complete + virtual bool hasChildren() const = 0; + + virtual ITracker& parent() = 0; + + // actions + virtual void close() = 0; // Successfully complete + virtual void fail() = 0; + virtual void markAsNeedingAnotherRun() = 0; + + virtual void addChild( Ptr const& child ) = 0; + virtual ITracker* findChild( NameAndLocation const& nameAndLocation ) = 0; + virtual void openChild() = 0; + + // Debug/ checking + virtual bool isSectionTracker() const = 0; + virtual bool isIndexTracker() const = 0; + }; + + class TrackerContext { + + enum RunState { + NotStarted, + Executing, + CompletedCycle + }; + + Ptr m_rootTracker; + ITracker* m_currentTracker; + RunState m_runState; + + public: + + static TrackerContext& instance() { + static TrackerContext s_instance; + return s_instance; + } + + TrackerContext() + : m_currentTracker( CATCH_NULL ), + m_runState( NotStarted ) + {} + + ITracker& startRun(); + + void endRun() { + m_rootTracker.reset(); + m_currentTracker = CATCH_NULL; + m_runState = NotStarted; + } + + void startCycle() { + m_currentTracker = m_rootTracker.get(); + m_runState = Executing; + } + void completeCycle() { + m_runState = CompletedCycle; + } + + bool completedCycle() const { + return m_runState == CompletedCycle; + } + ITracker& currentTracker() { + return *m_currentTracker; + } + void setCurrentTracker( ITracker* tracker ) { + m_currentTracker = tracker; + } + }; + + class TrackerBase : public ITracker { + protected: + enum CycleState { + NotStarted, + Executing, + ExecutingChildren, + NeedsAnotherRun, + CompletedSuccessfully, + Failed + }; + class TrackerHasName { + 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; + } + }; + typedef std::vector > Children; + NameAndLocation m_nameAndLocation; + TrackerContext& m_ctx; + ITracker* m_parent; + Children m_children; + CycleState m_runState; + public: + TrackerBase( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent ) + : m_nameAndLocation( nameAndLocation ), + m_ctx( ctx ), + m_parent( parent ), + m_runState( NotStarted ) + {} + virtual ~TrackerBase(); + + 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(); + } + + virtual void addChild( Ptr const& child ) CATCH_OVERRIDE { + m_children.push_back( child ); + } + + 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; + } + + virtual void openChild() CATCH_OVERRIDE { + if( m_runState != ExecutingChildren ) { + m_runState = ExecutingChildren; + if( m_parent ) + m_parent->openChild(); + } + } + + virtual bool isSectionTracker() const CATCH_OVERRIDE { return false; } + virtual bool isIndexTracker() const CATCH_OVERRIDE { return false; } + + void open() { + m_runState = Executing; + moveToThis(); + if( m_parent ) + m_parent->openChild(); + } + + virtual void close() CATCH_OVERRIDE { + + // Close any still open children (e.g. generators) + while( &m_ctx.currentTracker() != this ) + m_ctx.currentTracker().close(); + + switch( m_runState ) { + case NotStarted: + case CompletedSuccessfully: + case Failed: + throw std::logic_error( "Illogical state" ); + + case NeedsAnotherRun: + break;; + + case Executing: + m_runState = CompletedSuccessfully; + break; + case ExecutingChildren: + if( m_children.empty() || m_children.back()->isComplete() ) + m_runState = CompletedSuccessfully; + break; + + default: + throw std::logic_error( "Unexpected state" ); + } + moveToParent(); + m_ctx.completeCycle(); + } + virtual void fail() CATCH_OVERRIDE { + m_runState = Failed; + if( m_parent ) + m_parent->markAsNeedingAnotherRun(); + moveToParent(); + m_ctx.completeCycle(); + } + virtual void markAsNeedingAnotherRun() CATCH_OVERRIDE { + m_runState = NeedsAnotherRun; + } + private: + void moveToParent() { + assert( m_parent ); + m_ctx.setCurrentTracker( m_parent ); + } + void moveToThis() { + m_ctx.setCurrentTracker( this ); + } + }; + + class SectionTracker : public TrackerBase { + 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& parentSection = static_cast( *parent ); + addNextFilters( parentSection.m_filters ); + } + } + virtual ~SectionTracker(); + + virtual bool isSectionTracker() const CATCH_OVERRIDE { return true; } + + static SectionTracker& acquire( TrackerContext& ctx, NameAndLocation const& nameAndLocation ) { + SectionTracker* section = CATCH_NULL; + + 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 + std::copy( filters.begin(), filters.end(), std::back_inserter( m_filters ) ); + } + } + void addNextFilters( std::vector const& filters ) { + if( filters.size() > 1 ) + std::copy( filters.begin()+1, filters.end(), std::back_inserter( m_filters ) ); + } + }; + + class IndexTracker : public TrackerBase { + int m_size; + int m_index; + public: + IndexTracker( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent, int size ) + : TrackerBase( nameAndLocation, ctx, parent ), + m_size( size ), + m_index( -1 ) + {} + virtual ~IndexTracker(); + + virtual bool isIndexTracker() const CATCH_OVERRIDE { return true; } + + static IndexTracker& acquire( TrackerContext& ctx, NameAndLocation const& nameAndLocation, int size ) { + IndexTracker* tracker = CATCH_NULL; + + 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 ); + } + + 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; +using TestCaseTracking::TrackerContext; +using TestCaseTracking::SectionTracker; +using TestCaseTracking::IndexTracker; + +} // namespace Catch + +// #included from: catch_fatal_condition.hpp +#define TWOBLUECUBES_CATCH_FATAL_CONDITION_H_INCLUDED + +namespace Catch { + + // Report the error condition + inline void reportFatal( std::string const& message ) { + IContext& context = Catch::getCurrentContext(); + IResultCapture* resultCapture = context.getResultCapture(); + resultCapture->handleFatalErrorCondition( message ); + } + +} // namespace Catch + +#if defined ( CATCH_PLATFORM_WINDOWS ) ///////////////////////////////////////// +// #included from: catch_windows_h_proxy.h + +#define TWOBLUECUBES_CATCH_WINDOWS_H_PROXY_H_INCLUDED + +#ifdef CATCH_DEFINES_NOMINMAX +# define NOMINMAX +#endif +#ifdef CATCH_DEFINES_WIN32_LEAN_AND_MEAN +# define WIN32_LEAN_AND_MEAN +#endif + +#ifdef __AFXDLL +#include +#else +#include +#endif + +#ifdef CATCH_DEFINES_NOMINMAX +# undef NOMINMAX +#endif +#ifdef CATCH_DEFINES_WIN32_LEAN_AND_MEAN +# undef WIN32_LEAN_AND_MEAN +#endif + + +# 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) { + reset(); + 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 ////////////////////////// + +#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 // 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; + }; + + /////////////////////////////////////////////////////////////////////////// + + 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_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++; + } + + if( m_reporter->assertionEnded( AssertionStats( result, m_messages, m_totals ) ) ) + m_messages.clear(); + + // Reset working state + m_lastAssertionInfo = AssertionInfo( std::string(), m_lastAssertionInfo.lineInfo, "{Unknown expression after the reported line}" , m_lastAssertionInfo.resultDisposition ); + m_lastResult = result; + } + + 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 handleFatalErrorCondition( std::string const& message ) { + ResultBuilder resultBuilder = makeUnexpectedResultBuilder(); + resultBuilder.setResultType( ResultWas::FatalErrorCondition ); + resultBuilder << message; + resultBuilder.captureExpression(); + + handleUnfinishedSections(); + + // Recreate section for test case (as we will lose the one that was in scope) + TestCaseInfo const& testCaseInfo = m_activeTestCase->getTestCaseInfo(); + SectionInfo testCaseSection( testCaseInfo.lineInfo, testCaseInfo.name, testCaseInfo.description ); + + Counts assertions; + assertions.failed = 1; + SectionStats testCaseSectionStats( testCaseSection, assertions, 0, false ); + m_reporter->sectionEnded( testCaseSectionStats ); + + TestCaseInfo testInfo = m_activeTestCase->getTestCaseInfo(); + + Totals deltaTotals; + deltaTotals.testCases.failed = 1; + m_reporter->testCaseEnded( TestCaseStats( testInfo, + deltaTotals, + 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; + try { + m_lastAssertionInfo = AssertionInfo( "TEST_CASE", testCaseInfo.lineInfo, std::string(), ResultDisposition::Normal ); + + seedRng( *m_config ); + + Timer timer; + timer.start(); + if( m_reporter->getPreferences().shouldRedirectStdOut ) { + StreamRedirect coutRedir( Catch::cout(), redirectedCout ); + StreamRedirect cerrRedir( Catch::cerr(), redirectedCerr ); + invokeActiveTestCase(); + } + else { + invokeActiveTestCase(); + } + duration = timer.getElapsedSeconds(); + } + catch( TestFailureException& ) { + // This just means the test was aborted due to failure + } + catch(...) { + makeUnexpectedResultBuilder().useActiveException(); + } + m_testCaseTracker->close(); + handleUnfinishedSections(); + m_messages.clear(); + + Counts assertions = m_totals.assertions - prevAssertions; + bool missingAssertions = testForMissingAssertions( assertions ); + + if( testCaseInfo.okToFail() ) { + std::swap( assertions.failedButOk, assertions.failed ); + m_totals.assertions.failed -= assertions.failedButOk; + m_totals.assertions.failedButOk += assertions.failedButOk; + } + + SectionStats testCaseSectionStats( testCaseSection, assertions, duration, missingAssertions ); + m_reporter->sectionEnded( testCaseSectionStats ); + } + + void invokeActiveTestCase() { + FatalConditionHandler fatalConditionHandler; // Handle signals + m_activeTestCase->invoke(); + fatalConditionHandler.reset(); + } + + private: + + ResultBuilder makeUnexpectedResultBuilder() const { + return ResultBuilder( m_lastAssertionInfo.macroName.c_str(), + m_lastAssertionInfo.lineInfo, + m_lastAssertionInfo.capturedExpression.c_str(), + m_lastAssertionInfo.resultDisposition ); + } + + void handleUnfinishedSections() { + // If sections ended prematurely due to an exception we stored their + // infos here so we can tear them down outside the unwind process. + for( std::vector::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; + }; + + IResultCapture& getResultCapture() { + if( IResultCapture* capture = getCurrentContext().getResultCapture() ) + return *capture; + else + throw std::logic_error( "No result capture instance" ); + } + +} // end namespace Catch + +// #included from: internal/catch_version.h +#define TWOBLUECUBES_CATCH_VERSION_H_INCLUDED + +namespace Catch { + + // Versioning information + struct Version { + Version( unsigned int _majorVersion, + unsigned int _minorVersion, + unsigned int _patchNumber, + std::string const& _branchName, + unsigned int _buildNumber ); + + unsigned int const majorVersion; + unsigned int const minorVersion; + unsigned int const patchNumber; + + // buildNumber is only used if branchName is not null + std::string const branchName; + unsigned int const buildNumber; + + friend std::ostream& operator << ( std::ostream& os, Version const& version ); + + private: + void operator=( Version const& ); + }; + + extern Version libraryVersion; +} + +#include +#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; + } + + Ptr makeReporter( Ptr const& config ) { + std::vector reporters = config->getReporterNames(); + if( reporters.empty() ) + reporters.push_back( "console" ); + + 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; + } + + 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; + }; +} + +namespace Catch { + + namespace { + + class RegistryHub : public IRegistryHub, public IMutableRegistryHub { + + RegistryHub( RegistryHub const& ); + void operator=( RegistryHub const& ); + + public: // IRegistryHub + RegistryHub() { + } + virtual IReporterRegistry const& getReporterRegistry() const CATCH_OVERRIDE { + return m_reporterRegistry; + } + virtual ITestCaseRegistry const& getTestCaseRegistry() const CATCH_OVERRIDE { + return m_testCaseRegistry; + } + virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() CATCH_OVERRIDE { + return m_exceptionTranslatorRegistry; + } + + public: // IMutableRegistryHub + virtual void registerReporter( std::string const& name, Ptr 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 ); + } + + private: + TestRegistry m_testCaseRegistry; + ReporterRegistry m_reporterRegistry; + ExceptionTranslatorRegistry m_exceptionTranslatorRegistry; + }; + + // Single, global, instance + inline RegistryHub*& getTheRegistryHub() { + static RegistryHub* theRegistryHub = CATCH_NULL; + if( !theRegistryHub ) + theRegistryHub = new RegistryHub(); + return theRegistryHub; + } + } + + IRegistryHub& getRegistryHub() { + return *getTheRegistryHub(); + } + IMutableRegistryHub& getMutableRegistryHub() { + return *getTheRegistryHub(); + } + void cleanUp() { + delete getTheRegistryHub(); + getTheRegistryHub() = CATCH_NULL; + cleanUpContext(); + } + std::string translateActiveException() { + return getRegistryHub().getExceptionTranslatorRegistry().translateActiveException(); + } + +} // end namespace Catch + +// #included from: catch_notimplemented_exception.hpp +#define TWOBLUECUBES_CATCH_NOTIMPLEMENTED_EXCEPTION_HPP_INCLUDED + +#include + +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; + } +#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 + +namespace Catch { + namespace { + + struct IColourImpl { + virtual ~IColourImpl() {} + virtual void use( Colour::Code _colourCode ) = 0; + }; + + struct NoColourImpl : IColourImpl { + void use( Colour::Code ) {} + + static IColourImpl* instance() { + static NoColourImpl s_instance; + return &s_instance; + } + }; + + } // anon namespace +} // namespace Catch + +#if !defined( CATCH_CONFIG_COLOUR_NONE ) && !defined( CATCH_CONFIG_COLOUR_WINDOWS ) && !defined( CATCH_CONFIG_COLOUR_ANSI ) +# ifdef CATCH_PLATFORM_WINDOWS +# define CATCH_CONFIG_COLOUR_WINDOWS +# else +# define CATCH_CONFIG_COLOUR_ANSI +# endif +#endif + +#if defined ( CATCH_CONFIG_COLOUR_WINDOWS ) ///////////////////////////////////////// + +namespace Catch { +namespace { + + class Win32ColourImpl : public IColourImpl { + public: + Win32ColourImpl() : stdoutHandle( GetStdHandle(STD_OUTPUT_HANDLE) ) + { + CONSOLE_SCREEN_BUFFER_INFO csbiInfo; + GetConsoleScreenBufferInfo( stdoutHandle, &csbiInfo ); + originalForegroundAttributes = csbiInfo.wAttributes & ~( BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_BLUE | BACKGROUND_INTENSITY ); + originalBackgroundAttributes = csbiInfo.wAttributes & ~( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY ); + } + + virtual void use( Colour::Code _colourCode ) { + switch( _colourCode ) { + case Colour::None: return setTextAttribute( originalForegroundAttributes ); + case Colour::White: return setTextAttribute( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE ); + case Colour::Red: return setTextAttribute( FOREGROUND_RED ); + case Colour::Green: return setTextAttribute( FOREGROUND_GREEN ); + case Colour::Blue: return setTextAttribute( FOREGROUND_BLUE ); + case Colour::Cyan: return setTextAttribute( FOREGROUND_BLUE | FOREGROUND_GREEN ); + case Colour::Yellow: return setTextAttribute( FOREGROUND_RED | FOREGROUND_GREEN ); + case Colour::Grey: return setTextAttribute( 0 ); + + case Colour::LightGrey: return setTextAttribute( FOREGROUND_INTENSITY ); + case Colour::BrightRed: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_RED ); + case Colour::BrightGreen: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN ); + case Colour::BrightWhite: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE ); + + case Colour::Bright: throw std::logic_error( "not a colour" ); + } + } + + private: + void setTextAttribute( WORD _textAttribute ) { + SetConsoleTextAttribute( stdoutHandle, _textAttribute | originalBackgroundAttributes ); + } + HANDLE stdoutHandle; + WORD originalForegroundAttributes; + WORD originalBackgroundAttributes; + }; + + IColourImpl* platformColourInstance() { + static Win32ColourImpl s_instance; + + Ptr config = getCurrentContext().getConfig(); + UseColour::YesOrNo colourMode = config + ? config->useColour() + : UseColour::Auto; + if( colourMode == UseColour::Auto ) + colourMode = !isDebuggerActive() + ? UseColour::Yes + : UseColour::No; + return colourMode == UseColour::Yes + ? &s_instance + : NoColourImpl::instance(); + } + +} // end anon namespace +} // end namespace Catch + +#elif defined( CATCH_CONFIG_COLOUR_ANSI ) ////////////////////////////////////// + +#include + +namespace Catch { +namespace { + + // use POSIX/ ANSI console terminal codes + // Thanks to Adam Strzelecki for original contribution + // (http://github.com/nanoant) + // https://github.com/philsquared/Catch/pull/131 + class PosixColourImpl : public IColourImpl { + public: + virtual void use( Colour::Code _colourCode ) { + switch( _colourCode ) { + case Colour::None: + case Colour::White: return setColour( "[0m" ); + case Colour::Red: return setColour( "[0;31m" ); + case Colour::Green: return setColour( "[0;32m" ); + case Colour::Blue: return setColour( "[0;34m" ); + case Colour::Cyan: return setColour( "[0;36m" ); + case Colour::Yellow: return setColour( "[0;33m" ); + case Colour::Grey: return setColour( "[1;30m" ); + + case Colour::LightGrey: return setColour( "[0;37m" ); + case Colour::BrightRed: return setColour( "[1;31m" ); + case Colour::BrightGreen: return setColour( "[1;32m" ); + case Colour::BrightWhite: return setColour( "[1;37m" ); + + case Colour::Bright: throw std::logic_error( "not a colour" ); + } + } + static IColourImpl* instance() { + static PosixColourImpl s_instance; + return &s_instance; + } + + private: + void setColour( const char* _escapeCode ) { + Catch::cout() << '\033' << _escapeCode; + } + }; + + IColourImpl* platformColourInstance() { + Ptr config = getCurrentContext().getConfig(); + UseColour::YesOrNo colourMode = config + ? config->useColour() + : UseColour::Auto; + if( colourMode == UseColour::Auto ) + colourMode = (!isDebuggerActive() && isatty(STDOUT_FILENO) ) + ? UseColour::Yes + : UseColour::No; + return colourMode == UseColour::Yes + ? PosixColourImpl::instance() + : NoColourImpl::instance(); + } + +} // end anon namespace +} // end namespace Catch + +#else // not Windows or ANSI /////////////////////////////////////////////// + +namespace Catch { + + static IColourImpl* platformColourInstance() { return NoColourImpl::instance(); } + +} // end namespace Catch + +#endif // Windows/ ANSI/ None + +namespace Catch { + + Colour::Colour( Code _colourCode ) : m_moved( false ) { use( _colourCode ); } + Colour::Colour( Colour const& _other ) : m_moved( false ) { const_cast( _other ).m_moved = true; } + Colour::~Colour(){ if( !m_moved ) use( None ); } + + void Colour::use( Code _colourCode ) { + static IColourImpl* impl = platformColourInstance(); + impl->use( _colourCode ); + } + +} // end namespace Catch + +// #included from: catch_generators_impl.hpp +#define TWOBLUECUBES_CATCH_GENERATORS_IMPL_HPP_INCLUDED + +#include +#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( std::string const& _macroName, + SourceLineInfo const& _lineInfo, + std::string const& _capturedExpression, + ResultDisposition::Flags _resultDisposition ) + : macroName( _macroName ), + lineInfo( _lineInfo ), + capturedExpression( _capturedExpression ), + resultDisposition( _resultDisposition ) + {} + + AssertionResult::AssertionResult() {} + + AssertionResult::AssertionResult( AssertionInfo const& info, AssertionResultData const& data ) + : m_info( info ), + m_resultData( data ) + {} + + AssertionResult::~AssertionResult() {} + + // Result was a success + bool AssertionResult::succeeded() const { + return Catch::isOk( m_resultData.resultType ); + } + + // Result was a success, or failure is suppressed + bool AssertionResult::isOk() const { + return Catch::isOk( m_resultData.resultType ) || shouldSuppressFailure( m_info.resultDisposition ); + } + + ResultWas::OfType AssertionResult::getResultType() const { + return m_resultData.resultType; + } + + bool AssertionResult::hasExpression() const { + return !m_info.capturedExpression.empty(); + } + + bool AssertionResult::hasMessage() const { + return !m_resultData.message.empty(); + } + + std::string AssertionResult::getExpression() const { + if( isFalseTest( m_info.resultDisposition ) ) + return '!' + m_info.capturedExpression; + else + return m_info.capturedExpression; + } + std::string AssertionResult::getExpressionInMacro() const { + if( m_info.macroName.empty() ) + return m_info.capturedExpression; + else + return m_info.macroName + "( " + m_info.capturedExpression + " )"; + } + + bool AssertionResult::hasExpandedExpression() const { + return hasExpression() && getExpandedExpression() != getExpression(); + } + + std::string AssertionResult::getExpandedExpression() const { + return m_resultData.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 ) ) { + { + Colour colourGuard( Colour::Red ); + Catch::cerr() + << "Tag name [" << tag << "] not allowed.\n" + << "Tag names starting with non alpha-numeric characters are reserved\n"; + } + { + Colour colourGuard( Colour::FileName ); + Catch::cerr() << _lineInfo << std::endl; + } + exit(1); + } + } + + TestCase makeTestCase( ITestCase* _testCase, + std::string const& _className, + std::string const& _name, + std::string const& _descOrTags, + SourceLineInfo const& _lineInfo ) + { + bool isHidden( startsWith( _name, "./" ) ); // Legacy support + + // Parse out tags + std::set 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, + std::string const& _branchName, + unsigned int _buildNumber ) + : majorVersion( _majorVersion ), + minorVersion( _minorVersion ), + patchNumber( _patchNumber ), + branchName( _branchName ), + buildNumber( _buildNumber ) + {} + + std::ostream& operator << ( std::ostream& os, Version const& version ) { + os << version.majorVersion << '.' + << version.minorVersion << '.' + << version.patchNumber; + + if( !version.branchName.empty() ) { + os << '-' << version.branchName + << '.' << version.buildNumber; + } + return os; + } + + Version libraryVersion( 1, 7, 2, "", 0 ); + +} + +// #included from: catch_message.hpp +#define TWOBLUECUBES_CATCH_MESSAGE_HPP_INCLUDED + +namespace Catch { + + MessageInfo::MessageInfo( std::string const& _macroName, + SourceLineInfo const& _lineInfo, + ResultWas::OfType _type ) + : macroName( _macroName ), + lineInfo( _lineInfo ), + type( _type ), + sequence( ++globalCount ) + {} + + // This may need protecting if threading support is added + unsigned int MessageInfo::globalCount = 0; + + //////////////////////////////////////////////////////////////////////////// + + ScopedMessage::ScopedMessage( MessageBuilder const& builder ) + : m_info( builder.m_info ) + { + m_info.message = builder.m_stream.str(); + getResultCapture().pushScopedMessage( m_info ); + } + ScopedMessage::ScopedMessage( ScopedMessage const& other ) + : m_info( other.m_info ) + {} + + ScopedMessage::~ScopedMessage() { + getResultCapture().popScopedMessage( m_info ); + } + +} // end namespace Catch + +// #included from: catch_legacy_reporter_adapter.hpp +#define TWOBLUECUBES_CATCH_LEGACY_REPORTER_ADAPTER_HPP_INCLUDED + +// #included from: catch_legacy_reporter_adapter.h +#define TWOBLUECUBES_CATCH_LEGACY_REPORTER_ADAPTER_H_INCLUDED + +namespace Catch +{ + // Deprecated + struct IReporter : IShared { + virtual ~IReporter(); + + virtual bool shouldRedirectStdout() const = 0; + + virtual void StartTesting() = 0; + virtual void EndTesting( Totals const& totals ) = 0; + virtual void StartGroup( std::string const& groupName ) = 0; + virtual void EndGroup( std::string const& groupName, Totals const& totals ) = 0; + virtual void StartTestCase( TestCaseInfo const& testInfo ) = 0; + virtual void EndTestCase( TestCaseInfo const& testInfo, Totals const& totals, std::string const& stdOut, std::string const& stdErr ) = 0; + virtual void StartSection( std::string const& sectionName, std::string const& description ) = 0; + virtual void EndSection( std::string const& sectionName, Counts const& assertions ) = 0; + virtual void NoAssertionsInSection( std::string const& sectionName ) = 0; + virtual void NoAssertionsInTestCase( std::string const& testName ) = 0; + virtual void Aborted() = 0; + virtual void Result( AssertionResult const& result ) = 0; + }; + + class LegacyReporterAdapter : public SharedImpl + { + 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" +#endif + +#ifdef CATCH_PLATFORM_WINDOWS +#else +#include +#endif + +namespace Catch { + + namespace { +#ifdef CATCH_PLATFORM_WINDOWS + uint64_t getCurrentTicks() { + static uint64_t hz=0, hzo=0; + if (!hz) { + QueryPerformanceFrequency( reinterpret_cast( &hz ) ); + QueryPerformanceCounter( reinterpret_cast( &hzo ) ); + } + uint64_t t; + QueryPerformanceCounter( reinterpret_cast( &t ) ); + return ((t-hzo)*1000000)/hz; + } +#else + uint64_t 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(); + } + + Section::~Section() { + if( m_sectionIncluded ) { + SectionEndInfo endInfo( m_info, m_assertions, m_timer.getElapsedSeconds() ); + if( std::uncaught_exception() ) + getResultCapture().sectionEndedEarly( endInfo ); + else + getResultCapture().sectionEnded( endInfo ); + } + } + + // This indicates whether the section should be executed or not + Section::operator bool() const { + return m_sectionIncluded; + } + +} // end namespace Catch + +// #included from: catch_debugger.hpp +#define TWOBLUECUBES_CATCH_DEBUGGER_HPP_INCLUDED + +#ifdef CATCH_PLATFORM_MAC + + #include + #include + #include + #include + #include + + namespace Catch{ + + // The following function is taken directly from the following technical note: + // http://developer.apple.com/library/mac/#qa/qa2004/qa1361.html + + // Returns true if the current process is being debugged (either + // running under the debugger or has a debugger attached post facto). + bool isDebuggerActive(){ + + int mib[4]; + struct kinfo_proc info; + size_t size; + + // Initialize the flags so that, if sysctl fails for some bizarre + // reason, we get a predictable result. + + info.kp_proc.p_flag = 0; + + // Initialize mib, which tells sysctl the info we want, in this case + // we're looking for information about a specific process ID. + + mib[0] = CTL_KERN; + mib[1] = KERN_PROC; + mib[2] = KERN_PROC_PID; + mib[3] = getpid(); + + // Call sysctl. + + size = sizeof(info); + if( sysctl(mib, sizeof(mib) / sizeof(*mib), &info, &size, CATCH_NULL, 0) != 0 ) { + Catch::cerr() << "\n** Call to sysctl failed - unable to determine if debugger is active **\n" << std::endl; + return false; + } + + // We're being debugged if the P_TRACED flag is set. + + return ( (info.kp_proc.p_flag & P_TRACED) != 0 ); + } + } // namespace Catch + +#elif defined(CATCH_PLATFORM_LINUX) + #include + #include + + namespace Catch{ + // The standard POSIX way of detecting a debugger is to attempt to + // ptrace() the process, but this needs to be done from a child and not + // this process itself to still allow attaching to this process later + // if wanted, so is rather heavy. Under Linux we have the PID of the + // "debugger" (which doesn't need to be gdb, of course, it could also + // be strace, for example) in /proc/$PID/status, so just get it from + // there instead. + bool isDebuggerActive(){ + std::ifstream in("/proc/self/status"); + for( std::string line; std::getline(in, line); ) { + static const int PREFIX_LEN = 11; + if( line.compare(0, PREFIX_LEN, "TracerPid:\t") == 0 ) { + // We're traced if the PID is not 0 and no other PID starts + // with 0 digit, so it's enough to check for just a single + // character. + return line.length() > PREFIX_LEN && line[PREFIX_LEN] != '0'; + } + } + + return false; + } + } // namespace Catch +#elif defined(_MSC_VER) + extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent(); + namespace Catch { + bool isDebuggerActive() { + return IsDebuggerPresent() != 0; + } + } +#elif defined(__MINGW32__) + extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent(); + namespace Catch { + bool isDebuggerActive() { + return IsDebuggerPresent() != 0; + } + } +#else + namespace Catch { + inline bool isDebuggerActive() { return false; } + } +#endif // Platform + +#ifdef CATCH_PLATFORM_WINDOWS + + namespace Catch { + void writeToDebugConsole( std::string const& text ) { + ::OutputDebugStringA( text.c_str() ); + } + } +#else + namespace Catch { + void writeToDebugConsole( std::string const& text ) { + // !TBD: Need a version for Mac/ XCode and other IDEs + Catch::cout() << text; + } + } +#endif // Platform + +// #included from: catch_tostring.hpp +#define TWOBLUECUBES_CATCH_TOSTRING_HPP_INCLUDED + +namespace Catch { + +namespace Detail { + + const std::string unprintableString = "{?}"; + + namespace { + const int hexThreshold = 255; + + struct Endianness { + enum Arch { Big, Little }; + + static Arch which() { + union _{ + int asInt; + char asChar[sizeof (int)]; + } u; + + u.asInt = 1; + return ( u.asChar[sizeof(int)-1] == 1 ) ? Big : Little; + } + }; + } + + std::string rawMemoryToString( const void *object, std::size_t size ) + { + // Reverse order for little endian architectures + int i = 0, end = static_cast( size ), inc = 1; + if( Endianness::which() == Endianness::Little ) { + i = end-1; + end = inc = -1; + } + + unsigned char const *bytes = static_cast(object); + std::ostringstream os; + os << "0x" << std::setfill('0') << std::hex; + for( ; i != end; i += inc ) + os << std::setw(2) << static_cast(bytes[i]); + return os.str(); + } +} + +std::string toString( std::string const& value ) { + std::string s = value; + if( getCurrentContext().getConfig()->showInvisibles() ) { + for(size_t i = 0; i < s.size(); ++i ) { + std::string subs; + switch( s[i] ) { + case '\n': subs = "\\n"; break; + case '\t': subs = "\\t"; break; + default: break; + } + if( !subs.empty() ) { + s = s.substr( 0, i ) + subs + s.substr( i+1 ); + ++i; + } + } + } + return '"' + s + '"'; +} +std::string toString( std::wstring const& value ) { + + std::string 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 ); +} + +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 + +#ifdef __OBJC__ + std::string toString( NSString const * const& nsstring ) { + if( !nsstring ) + return "nil"; + return "@" + toString([nsstring UTF8String]); + } + std::string toString( NSString * CATCH_ARC_STRONG const& nsstring ) { + if( !nsstring ) + return "nil"; + return "@" + toString([nsstring UTF8String]); + } + std::string toString( NSObject* const& nsObject ) { + return toString( [nsObject description] ); + } +#endif + +} // end namespace Catch + +// #included from: catch_result_builder.hpp +#define TWOBLUECUBES_CATCH_RESULT_BUILDER_HPP_INCLUDED + +namespace Catch { + + std::string capturedExpressionWithSecondArgument( std::string const& capturedExpression, std::string const& secondArg ) { + return secondArg.empty() || secondArg == "\"\"" + ? capturedExpression + : capturedExpression + ", " + secondArg; + } + ResultBuilder::ResultBuilder( char const* macroName, + SourceLineInfo const& lineInfo, + char const* capturedExpression, + ResultDisposition::Flags resultDisposition, + char const* secondArg ) + : m_assertionInfo( macroName, lineInfo, capturedExpressionWithSecondArgument( capturedExpression, secondArg ), resultDisposition ), + m_shouldDebugBreak( false ), + m_shouldThrow( false ) + {} + + ResultBuilder& ResultBuilder::setResultType( ResultWas::OfType result ) { + m_data.resultType = result; + return *this; + } + ResultBuilder& ResultBuilder::setResultType( bool result ) { + m_data.resultType = result ? ResultWas::Ok : ResultWas::ExpressionFailed; + return *this; + } + + void ResultBuilder::endExpression( DecomposedExpression const& expr ) { + AssertionResult result = build( expr ); + handleResult( result ); + } + + void ResultBuilder::useActiveException( ResultDisposition::Flags resultDisposition ) { + m_assertionInfo.resultDisposition = resultDisposition; + m_stream.oss << Catch::translateActiveException(); + captureResult( ResultWas::ThrewException ); + } + + void ResultBuilder::captureResult( ResultWas::OfType resultType ) { + setResultType( resultType ); + captureExpression(); + } + + void ResultBuilder::captureExpectedException( std::string const& expectedMessage ) { + if( expectedMessage.empty() ) + captureExpectedException( Matchers::Impl::Generic::AllOf() ); + else + captureExpectedException( Matchers::Equals( expectedMessage ) ); + } + + void ResultBuilder::captureExpectedException( Matchers::Impl::Matcher const& matcher ) { + + assert( !isFalseTest( m_assertionInfo.resultDisposition ) ); + AssertionResultData data = m_data; + data.resultType = ResultWas::Ok; + data.reconstructedExpression = m_assertionInfo.capturedExpression; + + std::string actualMessage = Catch::translateActiveException(); + if( !matcher.match( actualMessage ) ) { + data.resultType = ResultWas::ExpressionFailed; + data.reconstructedExpression = actualMessage; + } + AssertionResult result( m_assertionInfo, data ); + handleResult( result ); + } + + void ResultBuilder::captureExpression() { + AssertionResult result = build(); + handleResult( result ); + } + + void ResultBuilder::handleResult( AssertionResult const& result ) + { + getResultCapture().assertionEnded( result ); + + if( !result.isOk() ) { + if( getCurrentContext().getConfig()->shouldDebugBreak() ) + m_shouldDebugBreak = true; + if( getCurrentContext().getRunner()->aborting() || (m_assertionInfo.resultDisposition & ResultDisposition::Normal) ) + m_shouldThrow = true; + } + } + + void ResultBuilder::react() { + if( m_shouldThrow ) + throw Catch::TestFailureException(); + } + + bool ResultBuilder::shouldDebugBreak() const { return m_shouldDebugBreak; } + bool ResultBuilder::allowThrows() const { return getCurrentContext().getConfig()->allowThrows(); } + + AssertionResult ResultBuilder::build() const + { + 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; + + // Flip bool results if FalseTest flag is set + if( isFalseTest( m_assertionInfo.resultDisposition ) ) { + data.negate( expr.isBinaryExpression() ); + } + + 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 = m_assertionInfo.capturedExpression; + } + +} // end namespace Catch + +// #included from: catch_tag_alias_registry.hpp +#define TWOBLUECUBES_CATCH_TAG_ALIAS_REGISTRY_HPP_INCLUDED + +// #included from: catch_tag_alias_registry.h +#define TWOBLUECUBES_CATCH_TAG_ALIAS_REGISTRY_H_INCLUDED + +#include + +namespace Catch { + + class TagAliasRegistry : public ITagAliasRegistry { + public: + virtual ~TagAliasRegistry(); + virtual Option find( std::string const& alias ) const; + virtual std::string expandAliases( std::string const& unexpandedTestSpec ) const; + void add( char const* alias, char const* tag, SourceLineInfo const& lineInfo ); + static TagAliasRegistry& get(); + + private: + std::map m_registry; + }; + +} // end namespace Catch + +namespace Catch { + + 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; + } + + void TagAliasRegistry::add( char const* alias, char const* tag, SourceLineInfo const& lineInfo ) { + + if( !startsWith( alias, "[@" ) || !endsWith( alias, ']' ) ) { + std::ostringstream oss; + oss << "error: tag alias, \"" << alias << "\" is not of the form [@alias name].\n" << lineInfo; + throw std::domain_error( oss.str().c_str() ); + } + if( !m_registry.insert( std::make_pair( alias, TagAlias( tag, lineInfo ) ) ).second ) { + std::ostringstream oss; + oss << "error: tag alias, \"" << alias << "\" already registered.\n" + << "\tFirst seen at " << find(alias)->lineInfo << '\n' + << "\tRedefined at " << lineInfo; + throw std::domain_error( oss.str().c_str() ); + } + } + + TagAliasRegistry& TagAliasRegistry::get() { + static TagAliasRegistry instance; + return instance; + + } + + ITagAliasRegistry::~ITagAliasRegistry() {} + ITagAliasRegistry const& ITagAliasRegistry::get() { return TagAliasRegistry::get(); } + + RegistrarForTagAliases::RegistrarForTagAliases( char const* alias, char const* tag, SourceLineInfo const& lineInfo ) { + try { + TagAliasRegistry::get().add( alias, tag, lineInfo ); + } + catch( std::exception& ex ) { + Colour colourGuard( Colour::Red ); + Catch::cerr() << ex.what() << std::endl; + exit(1); + } + } + +} // end namespace Catch + +// #included from: ../reporters/catch_reporter_multi.hpp +#define TWOBLUECUBES_CATCH_REPORTER_MULTI_HPP_INCLUDED + +namespace Catch { + +class MultipleReporters : public SharedImpl { + typedef std::vector > Reporters; + Reporters m_reporters; + +public: + void add( Ptr const& reporter ) { + m_reporters.push_back( reporter ); + } + +public: // IStreamingReporter + + virtual ReporterPreferences getPreferences() const CATCH_OVERRIDE { + return m_reporters[0]->getPreferences(); + } + + virtual void noMatchingTestCases( std::string const& spec ) CATCH_OVERRIDE { + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + (*it)->noMatchingTestCases( spec ); + } + + virtual void testRunStarting( TestRunInfo const& testRunInfo ) CATCH_OVERRIDE { + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + (*it)->testRunStarting( testRunInfo ); + } + + virtual void testGroupStarting( GroupInfo const& groupInfo ) CATCH_OVERRIDE { + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + (*it)->testGroupStarting( groupInfo ); + } + + virtual void testCaseStarting( TestCaseInfo const& testInfo ) CATCH_OVERRIDE { + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + (*it)->testCaseStarting( testInfo ); + } + + virtual void sectionStarting( SectionInfo const& sectionInfo ) CATCH_OVERRIDE { + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + (*it)->sectionStarting( sectionInfo ); + } + + virtual void assertionStarting( AssertionInfo const& assertionInfo ) CATCH_OVERRIDE { + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + (*it)->assertionStarting( assertionInfo ); + } + + // The return value indicates if the messages buffer should be cleared: + virtual bool assertionEnded( AssertionStats const& assertionStats ) CATCH_OVERRIDE { + bool clearBuffer = false; + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + clearBuffer |= (*it)->assertionEnded( assertionStats ); + return clearBuffer; + } + + virtual void sectionEnded( SectionStats const& sectionStats ) CATCH_OVERRIDE { + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + (*it)->sectionEnded( sectionStats ); + } + + virtual void testCaseEnded( TestCaseStats const& testCaseStats ) CATCH_OVERRIDE { + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + (*it)->testCaseEnded( testCaseStats ); + } + + virtual void testGroupEnded( TestGroupStats const& testGroupStats ) CATCH_OVERRIDE { + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + (*it)->testGroupEnded( testGroupStats ); + } + + virtual void testRunEnded( TestRunStats const& testRunStats ) CATCH_OVERRIDE { + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + (*it)->testRunEnded( testRunStats ); + } + + virtual void skipTest( TestCaseInfo const& testInfo ) CATCH_OVERRIDE { + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + (*it)->skipTest( testInfo ); + } + + 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; + + return resultingReporter; +} + +} // end namespace Catch + +// #included from: ../reporters/catch_reporter_xml.hpp +#define TWOBLUECUBES_CATCH_REPORTER_XML_HPP_INCLUDED + +// #included from: catch_reporter_bases.hpp +#define TWOBLUECUBES_CATCH_REPORTER_BASES_HPP_INCLUDED + +#include + +namespace Catch { + + 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; + } + bool operator == ( Ptr const& other ) const { + return operator==( *other ); + } + + SectionStats stats; + typedef std::vector > ChildSections; + typedef std::vector Assertions; + ChildSections childSections; + Assertions assertions; + std::string stdOut; + std::string stdErr; + }; + + struct BySectionInfo { + BySectionInfo( SectionInfo const& other ) : m_other( other ) {} + BySectionInfo( BySectionInfo const& other ) : m_other( other.m_other ) {} + bool operator() ( Ptr const& node ) const { + return node->stats.sectionInfo.lineInfo == m_other.lineInfo; + } + private: + void operator=( BySectionInfo const& ); + SectionInfo const& m_other; + }; + + typedef Node TestCaseNode; + typedef Node TestGroupNode; + typedef Node TestRunNode; + + CumulativeReporterBase( ReporterConfig const& _config ) + : m_config( _config.fullConfig() ), + stream( _config.stream() ) + { + m_reporterPrefs.shouldRedirectStdOut = false; + } + ~CumulativeReporterBase(); + + virtual ReporterPreferences getPreferences() const CATCH_OVERRIDE { + return m_reporterPrefs; + } + + virtual void testRunStarting( TestRunInfo const& ) CATCH_OVERRIDE {} + virtual void testGroupStarting( GroupInfo const& ) CATCH_OVERRIDE {} + + virtual void testCaseStarting( TestCaseInfo const& ) CATCH_OVERRIDE {} + + virtual void sectionStarting( SectionInfo const& sectionInfo ) CATCH_OVERRIDE { + SectionStats incompleteStats( sectionInfo, Counts(), 0, false ); + Ptr 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 ) + {} + + virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE {} + virtual bool assertionEnded( AssertionStats const& ) CATCH_OVERRIDE { + return false; + } + }; + +} // end namespace Catch + +// #included from: ../internal/catch_reporter_registrars.hpp +#define TWOBLUECUBES_CATCH_REPORTER_REGISTRARS_HPP_INCLUDED + +namespace Catch { + + template + class LegacyReporterRegistrar { + + class ReporterFactory : public IReporterFactory { + virtual IStreamingReporter* create( ReporterConfig const& config ) const { + return new LegacyReporterAdapter( new T( config ) ); + } + + virtual std::string getDescription() const { + return T::getDescription(); + } + }; + + public: + + LegacyReporterRegistrar( std::string const& name ) { + getMutableRegistryHub().registerReporter( name, new ReporterFactory() ); + } + }; + + template + 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() ); + } + }; +} + +#define INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) \ + namespace{ Catch::LegacyReporterRegistrar catch_internal_RegistrarFor##reporterType( name ); } + +#define INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType ) \ + namespace{ Catch::ReporterRegistrar catch_internal_RegistrarFor##reporterType( name ); } + +#define INTERNAL_CATCH_REGISTER_LISTENER( listenerType ) \ + namespace{ Catch::ListenerRegistrar catch_internal_RegistrarFor##listenerType; } + +// #included from: ../internal/catch_xmlwriter.hpp +#define TWOBLUECUBES_CATCH_XMLWRITER_HPP_INCLUDED + +#include +#include +#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 ) + {} + + 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; + } + + private: + std::string m_str; + ForWhat m_forWhat; + }; + + class XmlWriter { + public: + + class ScopedElement { + public: + ScopedElement( XmlWriter* writer ) + : m_writer( writer ) + {} + + ScopedElement( ScopedElement const& other ) + : m_writer( other.m_writer ){ + other.m_writer = CATCH_NULL; + } + + ~ScopedElement() { + if( m_writer ) + m_writer->endElement(); + } + + ScopedElement& writeText( std::string const& text, bool indent = true ) { + m_writer->writeText( text, indent ); + return *this; + } + + template + ScopedElement& writeAttribute( std::string const& name, T const& attribute ) { + m_writer->writeAttribute( name, attribute ); + return *this; + } + + private: + mutable XmlWriter* m_writer; + }; + + XmlWriter() + : m_tagIsOpen( false ), + m_needsNewline( false ), + m_os( Catch::cout() ) + { + writeDeclaration(); + } + + XmlWriter( std::ostream& os ) + : m_tagIsOpen( false ), + m_needsNewline( false ), + m_os( os ) + { + writeDeclaration(); + } + + ~XmlWriter() { + while( !m_tags.empty() ) + endElement(); + } + + 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 scoped( this ); + startElement( name ); + return scoped; + } + + 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 ) { + 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 ) { + std::ostringstream oss; + oss << attribute; + return writeAttribute( name, oss.str() ); + } + + XmlWriter& writeText( std::string const& text, bool indent = true ) { + if( !text.empty() ){ + bool tagWasOpen = m_tagIsOpen; + ensureTagClosed(); + if( tagWasOpen && indent ) + m_os << m_indent; + m_os << XmlEncode( text ); + m_needsNewline = true; + } + return *this; + } + + XmlWriter& writeComment( std::string const& text ) { + ensureTagClosed(); + m_os << m_indent << ""; + m_needsNewline = true; + return *this; + } + + void writeStylesheetRef( std::string const& url ) { + m_os << "\n"; + } + + XmlWriter& writeBlankLine() { + ensureTagClosed(); + m_os << '\n'; + return *this; + } + + void ensureTagClosed() { + if( m_tagIsOpen ) { + m_os << ">" << std::endl; + m_tagIsOpen = false; + } + } + + private: + XmlWriter( XmlWriter const& ); + void operator=( XmlWriter const& ); + + void writeDeclaration() { + m_os << "\n"; + } + + void newlineIfNecessary() { + if( m_needsNewline ) { + m_os << std::endl; + m_needsNewline = false; + } + } + + bool m_tagIsOpen; + bool m_needsNewline; + std::vector m_tags; + std::string m_indent; + std::ostream& m_os; + }; + +} +// #included from: catch_reenable_warnings.h + +#define TWOBLUECUBES_CATCH_REENABLE_WARNINGS_H_INCLUDED + +#ifdef __clang__ +# ifdef __ICC // icpc defines the __clang__ macro +# pragma warning(pop) +# else +# pragma clang diagnostic pop +# endif +#elif defined __GNUC__ +# pragma GCC diagnostic pop +#endif + + +namespace Catch { + class XmlReporter : public StreamingReporterBase { + public: + XmlReporter( ReporterConfig const& _config ) + : StreamingReporterBase( _config ), + m_xml(_config.stream()), + m_sectionDepth( 0 ) + { + m_reporterPrefs.shouldRedirectStdOut = true; + } + + virtual ~XmlReporter() CATCH_OVERRIDE; + + static std::string getDescription() { + return "Reports test results as an XML document"; + } + + virtual std::string getStylesheetRef() const { + return std::string(); + } + + public: // StreamingReporterBase + + virtual void noMatchingTestCases( std::string const& s ) CATCH_OVERRIDE { + StreamingReporterBase::noMatchingTestCases( s ); + } + + virtual void testRunStarting( TestRunInfo const& testInfo ) CATCH_OVERRIDE { + StreamingReporterBase::testRunStarting( testInfo ); + 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 ); + + 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 ); + m_xml.ensureTagClosed(); + } + } + + virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE { } + + virtual bool assertionEnded( AssertionStats const& assertionStats ) CATCH_OVERRIDE { + const AssertionResult& assertionResult = assertionStats.assertionResult; + + // Print any info messages in tags. + 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 ) { + m_xml.scopedElement( "Info" ) + .writeText( it->message ); + } else if ( it->type == ResultWas::Warning ) { + m_xml.scopedElement( "Warning" ) + .writeText( it->message ); + } + } + } + + // Drop out if result was successful but we're not printing them. + if( !m_config->includeSuccessfulResults() && isOk(assertionResult.getResultType()) ) + return true; + + // Print the expression if there is one. + if( assertionResult.hasExpression() ) { + m_xml.startElement( "Expression" ) + .writeAttribute( "success", assertionResult.succeeded() ) + .writeAttribute( "type", assertionResult.getTestMacroName() ) + .writeAttribute( "filename", assertionResult.getSourceInfo().file ) + .writeAttribute( "line", assertionResult.getSourceInfo().line ); + + m_xml.scopedElement( "Original" ) + .writeText( assertionResult.getExpression() ); + m_xml.scopedElement( "Expanded" ) + .writeText( assertionResult.getExpandedExpression() ); + } + + // And... Print a result applicable to each result type. + switch( assertionResult.getResultType() ) { + case ResultWas::ThrewException: + m_xml.scopedElement( "Exception" ) + .writeAttribute( "filename", assertionResult.getSourceInfo().file ) + .writeAttribute( "line", assertionResult.getSourceInfo().line ) + .writeText( assertionResult.getMessage() ); + break; + case ResultWas::FatalErrorCondition: + m_xml.scopedElement( "FatalErrorCondition" ) + .writeAttribute( "filename", assertionResult.getSourceInfo().file ) + .writeAttribute( "line", assertionResult.getSourceInfo().line ) + .writeText( assertionResult.getMessage() ); + break; + case ResultWas::Info: + m_xml.scopedElement( "Info" ) + .writeText( assertionResult.getMessage() ); + break; + case ResultWas::Warning: + // Warning will already have been written + break; + case ResultWas::ExplicitFailure: + m_xml.scopedElement( "Failure" ) + .writeText( assertionResult.getMessage() ); + break; + default: + break; + } + + if( assertionResult.hasExpression() ) + m_xml.endElement(); + + return true; + } + + virtual void sectionEnded( SectionStats const& sectionStats ) CATCH_OVERRIDE { + StreamingReporterBase::sectionEnded( sectionStats ); + if( --m_sectionDepth > 0 ) { + XmlWriter::ScopedElement e = m_xml.scopedElement( "OverallResults" ); + e.writeAttribute( "successes", sectionStats.assertions.passed ); + e.writeAttribute( "failures", sectionStats.assertions.failed ); + e.writeAttribute( "expectedFailures", sectionStats.assertions.failedButOk ); + + if ( m_config->showDurations() == ShowDurations::Always ) + e.writeAttribute( "durationInSeconds", sectionStats.durationInSeconds ); + + m_xml.endElement(); + } + } + + virtual void testCaseEnded( TestCaseStats const& testCaseStats ) CATCH_OVERRIDE { + StreamingReporterBase::testCaseEnded( testCaseStats ); + XmlWriter::ScopedElement e = m_xml.scopedElement( "OverallResult" ); + e.writeAttribute( "success", testCaseStats.totals.assertions.allOk() ); + + if ( m_config->showDurations() == ShowDurations::Always ) + e.writeAttribute( "durationInSeconds", m_testCaseTimer.getElapsedSeconds() ); + + 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 ) + +} // 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() ) + { + m_reporterPrefs.shouldRedirectStdOut = true; + } + + virtual ~JunitReporter() CATCH_OVERRIDE; + + static std::string getDescription() { + return "Reports test results in an XML format that looks like Ant's junitreport target"; + } + + virtual void noMatchingTestCases( std::string const& /*spec*/ ) CATCH_OVERRIDE {} + + virtual void testRunStarting( TestRunInfo const& runInfo ) CATCH_OVERRIDE { + CumulativeReporterBase::testRunStarting( runInfo ); + xml.startElement( "testsuites" ); + } + + virtual void testGroupStarting( GroupInfo const& groupInfo ) CATCH_OVERRIDE { + suiteTimer.start(); + stdOutForSuite.str(""); + stdErrForSuite.str(""); + unexpectedExceptions = 0; + CumulativeReporterBase::testGroupStarting( groupInfo ); + } + + virtual bool assertionEnded( AssertionStats const& assertionStats ) CATCH_OVERRIDE { + if( assertionStats.assertionResult.getResultType() == ResultWas::ThrewException ) + unexpectedExceptions++; + return CumulativeReporterBase::assertionEnded( assertionStats ); + } + + virtual void testCaseEnded( TestCaseStats const& testCaseStats ) CATCH_OVERRIDE { + stdOutForSuite << testCaseStats.stdOut; + stdErrForSuite << testCaseStats.stdErr; + CumulativeReporterBase::testCaseEnded( testCaseStats ); + } + + virtual void testGroupEnded( TestGroupStats const& testGroupStats ) CATCH_OVERRIDE { + double suiteTime = suiteTimer.getElapsedSeconds(); + CumulativeReporterBase::testGroupEnded( testGroupStats ); + writeGroup( *m_testGroups.back(), suiteTime ); + } + + virtual void testRunEndedCumulative() CATCH_OVERRIDE { + xml.endElement(); + } + + void writeGroup( TestGroupNode const& groupNode, double suiteTime ) { + XmlWriter::ScopedElement e = xml.scopedElement( "testsuite" ); + TestGroupStats const& stats = groupNode.value; + xml.writeAttribute( "name", stats.groupInfo.name ); + xml.writeAttribute( "errors", unexpectedExceptions ); + xml.writeAttribute( "failures", stats.totals.assertions.failed-unexpectedExceptions ); + xml.writeAttribute( "tests", stats.totals.assertions.total() ); + xml.writeAttribute( "hostname", "tbd" ); // !TBD + if( m_config->showDurations() == ShowDurations::Never ) + xml.writeAttribute( "time", "" ); + else + xml.writeAttribute( "time", suiteTime ); + xml.writeAttribute( "timestamp", 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; + }; + + INTERNAL_CATCH_REGISTER_REPORTER( "junit", JunitReporter ) + +} // end namespace Catch + +// #included from: ../reporters/catch_reporter_console.hpp +#define TWOBLUECUBES_CATCH_REPORTER_CONSOLE_HPP_INCLUDED + +namespace Catch { + + struct ConsoleReporter : StreamingReporterBase { + ConsoleReporter( ReporterConfig const& _config ) + : StreamingReporterBase( _config ), + m_headerPrinted( false ) + {} + + virtual ~ConsoleReporter() CATCH_OVERRIDE; + static std::string getDescription() { + return "Reports test results as plain lines of text"; + } + + virtual void noMatchingTestCases( std::string const& spec ) CATCH_OVERRIDE { + stream << "No test cases matched '" << spec << '\'' << std::endl; + } + + virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE { + } + + virtual bool assertionEnded( AssertionStats const& _assertionStats ) CATCH_OVERRIDE { + AssertionResult const& result = _assertionStats.assertionResult; + + bool printInfoMessages = true; + + // Drop out if result was successful and we're not printing those + if( !m_config->includeSuccessfulResults() && result.isOk() ) { + if( result.getResultType() != ResultWas::Warning ) + return false; + printInfoMessages = false; + } + + lazyPrint(); + + AssertionPrinter printer( stream, _assertionStats, printInfoMessages ); + printer.print(); + stream << std::endl; + return true; + } + + virtual void sectionStarting( SectionInfo const& _sectionInfo ) CATCH_OVERRIDE { + m_headerPrinted = false; + StreamingReporterBase::sectionStarting( _sectionInfo ); + } + virtual void sectionEnded( SectionStats const& _sectionStats ) CATCH_OVERRIDE { + if( _sectionStats.missingAssertions ) { + lazyPrint(); + Colour colour( Colour::ResultError ); + if( m_sectionStack.size() > 1 ) + stream << "\nNo assertions in section"; + else + stream << "\nNo assertions in test case"; + stream << " '" << _sectionStats.sectionInfo.name << "'\n" << std::endl; + } + if( m_headerPrinted ) { + if( m_config->showDurations() == ShowDurations::Always ) + stream << "Completed in " << _sectionStats.durationInSeconds << 's' << std::endl; + m_headerPrinted = false; + } + else { + if( m_config->showDurations() == ShowDurations::Always ) + stream << _sectionStats.sectionInfo.name << " completed in " << _sectionStats.durationInSeconds << 's' << std::endl; + } + StreamingReporterBase::sectionEnded( _sectionStats ); + } + + virtual void testCaseEnded( TestCaseStats const& _testCaseStats ) CATCH_OVERRIDE { + StreamingReporterBase::testCaseEnded( _testCaseStats ); + m_headerPrinted = false; + } + virtual void testGroupEnded( TestGroupStats const& _testGroupStats ) CATCH_OVERRIDE { + if( currentGroupInfo.used ) { + printSummaryDivider(); + stream << "Summary for group '" << _testGroupStats.groupInfo.name << "':\n"; + printTotals( _testGroupStats.totals ); + stream << '\n' << std::endl; + } + StreamingReporterBase::testGroupEnded( _testGroupStats ); + } + virtual void testRunEnded( TestRunStats const& _testRunStats ) CATCH_OVERRIDE { + printTotalsDivider( _testRunStats.totals ); + printTotals( _testRunStats.totals ); + stream << std::endl; + StreamingReporterBase::testRunEnded( _testRunStats ); + } + + private: + + class AssertionPrinter { + void operator= ( AssertionPrinter const& ); + public: + AssertionPrinter( std::ostream& _stream, AssertionStats const& _stats, bool _printInfoMessages ) + : stream( _stream ), + stats( _stats ), + result( _stats.assertionResult ), + colour( Colour::None ), + message( result.getMessage() ), + messages( _stats.infoMessages ), + printInfoMessages( _printInfoMessages ) + { + switch( result.getResultType() ) { + case ResultWas::Ok: + colour = Colour::Success; + passOrFail = "PASSED"; + //if( result.hasMessage() ) + if( _stats.infoMessages.size() == 1 ) + messageLabel = "with message"; + if( _stats.infoMessages.size() > 1 ) + messageLabel = "with messages"; + break; + case ResultWas::ExpressionFailed: + if( result.isOk() ) { + colour = Colour::Success; + passOrFail = "FAILED - but was ok"; + } + else { + colour = Colour::Error; + passOrFail = "FAILED"; + } + if( _stats.infoMessages.size() == 1 ) + messageLabel = "with message"; + if( _stats.infoMessages.size() > 1 ) + messageLabel = "with messages"; + break; + case ResultWas::ThrewException: + colour = Colour::Error; + passOrFail = "FAILED"; + messageLabel = "due to unexpected exception with message"; + break; + case ResultWas::FatalErrorCondition: + colour = Colour::Error; + passOrFail = "FAILED"; + messageLabel = "due to a fatal error condition"; + break; + case ResultWas::DidntThrowException: + colour = Colour::Error; + passOrFail = "FAILED"; + messageLabel = "because no exception was thrown where one was expected"; + break; + case ResultWas::Info: + messageLabel = "info"; + break; + case ResultWas::Warning: + messageLabel = "warning"; + break; + case ResultWas::ExplicitFailure: + passOrFail = "FAILED"; + colour = Colour::Error; + if( _stats.infoMessages.size() == 1 ) + messageLabel = "explicitly with message"; + if( _stats.infoMessages.size() > 1 ) + messageLabel = "explicitly with messages"; + break; + // These cases are here to prevent compiler warnings + case ResultWas::Unknown: + case ResultWas::FailureBit: + case ResultWas::Exception: + passOrFail = "** internal error **"; + colour = Colour::Error; + break; + } + } + + void print() const { + printSourceInfo(); + if( stats.totals.assertions.total() > 0 ) { + if( result.isOk() ) + stream << '\n'; + printResultType(); + printOriginalExpression(); + printReconstructedExpression(); + } + else { + stream << '\n'; + } + printMessage(); + } + + private: + void printResultType() const { + if( !passOrFail.empty() ) { + Colour colourGuard( colour ); + stream << passOrFail << ":\n"; + } + } + void printOriginalExpression() const { + if( result.hasExpression() ) { + Colour colourGuard( Colour::OriginalExpression ); + stream << " "; + stream << result.getExpressionInMacro(); + stream << '\n'; + } + } + void printReconstructedExpression() const { + if( result.hasExpandedExpression() ) { + stream << "with expansion:\n"; + Colour colourGuard( Colour::ReconstructedExpression ); + stream << Text( result.getExpandedExpression(), TextAttributes().setIndent(2) ) << '\n'; + } + } + void printMessage() const { + if( !messageLabel.empty() ) + stream << messageLabel << ':' << '\n'; + for( std::vector::const_iterator it = messages.begin(), itEnd = messages.end(); + it != itEnd; + ++it ) { + // If this assertion is a warning ignore any INFO messages + if( printInfoMessages || it->type != ResultWas::Info ) + stream << Text( it->message, TextAttributes().setIndent(2) ) << '\n'; + } + } + void printSourceInfo() const { + Colour colourGuard( Colour::FileName ); + stream << result.getSourceInfo() << ": "; + } + + std::ostream& stream; + AssertionStats const& stats; + AssertionResult const& result; + Colour::Code colour; + std::string passOrFail; + std::string messageLabel; + std::string message; + std::vector messages; + bool printInfoMessages; + }; + + void lazyPrint() { + + if( !currentTestRunInfo.used ) + lazyPrintRunInfo(); + if( !currentGroupInfo.used ) + lazyPrintGroupInfo(); + + if( !m_headerPrinted ) { + printTestCaseAndSectionHeader(); + m_headerPrinted = true; + } + } + void lazyPrintRunInfo() { + stream << '\n' << getLineOfChars<'~'>() << '\n'; + Colour colour( Colour::SecondaryText ); + stream << currentTestRunInfo->name + << " is a Catch v" << libraryVersion << " host application.\n" + << "Run with -? for options\n\n"; + + if( m_config->rngSeed() != 0 ) + stream << "Randomness seeded to: " << m_config->rngSeed() << "\n\n"; + + currentTestRunInfo.used = true; + } + void lazyPrintGroupInfo() { + if( !currentGroupInfo->name.empty() && currentGroupInfo->groupsCounts > 1 ) { + printClosedHeader( "Group: " + currentGroupInfo->name ); + currentGroupInfo.used = true; + } + } + void printTestCaseAndSectionHeader() { + assert( !m_sectionStack.empty() ); + printOpenHeader( currentTestCaseInfo->name ); + + if( m_sectionStack.size() > 1 ) { + Colour colourGuard( Colour::Headers ); + + std::vector::const_iterator + it = m_sectionStack.begin()+1, // Skip first section (test case) + itEnd = m_sectionStack.end(); + for( ; it != itEnd; ++it ) + printHeaderString( it->name, 2 ); + } + + SourceLineInfo lineInfo = m_sectionStack.back().lineInfo; + + if( !lineInfo.empty() ){ + stream << getLineOfChars<'-'>() << '\n'; + Colour colourGuard( Colour::FileName ); + stream << lineInfo << '\n'; + } + stream << getLineOfChars<'.'>() << '\n' << std::endl; + } + + void printClosedHeader( std::string const& _name ) { + printOpenHeader( _name ); + stream << getLineOfChars<'.'>() << '\n'; + } + void printOpenHeader( std::string const& _name ) { + stream << getLineOfChars<'-'>() << '\n'; + { + Colour colourGuard( Colour::Headers ); + printHeaderString( _name ); + } + } + + // if string has a : in first line will set indent to follow it on + // subsequent lines + void printHeaderString( std::string const& _string, std::size_t indent = 0 ) { + std::size_t i = _string.find( ": " ); + if( i != std::string::npos ) + i+=2; + else + i = 0; + stream << Text( _string, TextAttributes() + .setIndent( indent+i) + .setInitialIndent( indent ) ) << '\n'; + } + + struct SummaryColumn { + + SummaryColumn( std::string const& _label, Colour::Code _colour ) + : label( _label ), + colour( _colour ) + {} + SummaryColumn addRow( std::size_t count ) { + std::ostringstream oss; + oss << count; + std::string row = oss.str(); + for( std::vector::iterator it = rows.begin(); it != rows.end(); ++it ) { + while( it->size() < row.size() ) + *it = ' ' + *it; + while( it->size() > row.size() ) + row = ' ' + row; + } + rows.push_back( row ); + return *this; + } + + std::string label; + Colour::Code colour; + std::vector rows; + + }; + + void printTotals( Totals const& totals ) { + if( totals.testCases.total() == 0 ) { + stream << Colour( Colour::Warning ) << "No tests ran\n"; + } + else if( totals.assertions.total() > 0 && totals.testCases.allPassed() ) { + stream << Colour( Colour::ResultSuccess ) << "All tests passed"; + stream << " (" + << pluralise( totals.assertions.passed, "assertion" ) << " in " + << pluralise( totals.testCases.passed, "test case" ) << ')' + << '\n'; + } + else { + + std::vector columns; + columns.push_back( SummaryColumn( "", Colour::None ) + .addRow( totals.testCases.total() ) + .addRow( totals.assertions.total() ) ); + columns.push_back( SummaryColumn( "passed", Colour::Success ) + .addRow( totals.testCases.passed ) + .addRow( totals.assertions.passed ) ); + columns.push_back( SummaryColumn( "failed", Colour::ResultError ) + .addRow( totals.testCases.failed ) + .addRow( totals.assertions.failed ) ); + columns.push_back( SummaryColumn( "failed as expected", Colour::ResultExpectedFailure ) + .addRow( totals.testCases.failedButOk ) + .addRow( totals.assertions.failedButOk ) ); + + printSummaryRow( "test cases", columns, 0 ); + printSummaryRow( "assertions", columns, 1 ); + } + } + void printSummaryRow( std::string const& label, std::vector const& cols, std::size_t row ) { + for( std::vector::const_iterator it = cols.begin(); it != cols.end(); ++it ) { + std::string value = it->rows[row]; + if( it->label.empty() ) { + stream << label << ": "; + if( value != "0" ) + stream << value; + else + stream << Colour( Colour::Warning ) << "- none -"; + } + else if( value != "0" ) { + stream << Colour( Colour::LightGrey ) << " | "; + stream << Colour( it->colour ) + << value << ' ' << it->label; + } + } + stream << '\n'; + } + + static std::size_t makeRatio( std::size_t number, std::size_t total ) { + std::size_t ratio = total > 0 ? CATCH_CONFIG_CONSOLE_WIDTH * number/ total : 0; + return ( ratio == 0 && number > 0 ) ? 1 : ratio; + } + static std::size_t& findMax( std::size_t& i, std::size_t& j, std::size_t& k ) { + if( i > j && i > k ) + return i; + else if( j > k ) + return j; + else + return k; + } + + void printTotalsDivider( Totals const& totals ) { + if( totals.testCases.total() > 0 ) { + std::size_t failedRatio = makeRatio( totals.testCases.failed, totals.testCases.total() ); + std::size_t failedButOkRatio = makeRatio( totals.testCases.failedButOk, totals.testCases.total() ); + std::size_t passedRatio = makeRatio( totals.testCases.passed, totals.testCases.total() ); + while( failedRatio + failedButOkRatio + passedRatio < CATCH_CONFIG_CONSOLE_WIDTH-1 ) + findMax( failedRatio, failedButOkRatio, passedRatio )++; + while( failedRatio + failedButOkRatio + passedRatio > CATCH_CONFIG_CONSOLE_WIDTH-1 ) + findMax( failedRatio, failedButOkRatio, passedRatio )--; + + stream << Colour( Colour::Error ) << std::string( failedRatio, '=' ); + stream << Colour( Colour::ResultExpectedFailure ) << std::string( failedButOkRatio, '=' ); + if( totals.testCases.allPassed() ) + stream << Colour( Colour::ResultSuccess ) << std::string( passedRatio, '=' ); + else + stream << Colour( Colour::Success ) << std::string( passedRatio, '=' ); + } + else { + stream << Colour( Colour::Warning ) << std::string( CATCH_CONFIG_CONSOLE_WIDTH-1, '=' ); + } + stream << '\n'; + } + void printSummaryDivider() { + stream << getLineOfChars<'-'>() << '\n'; + } + + private: + bool m_headerPrinted; + }; + + INTERNAL_CATCH_REGISTER_REPORTER( "console", ConsoleReporter ) + +} // end namespace Catch + +// #included from: ../reporters/catch_reporter_compact.hpp +#define TWOBLUECUBES_CATCH_REPORTER_COMPACT_HPP_INCLUDED + +namespace Catch { + + struct CompactReporter : StreamingReporterBase { + + CompactReporter( ReporterConfig const& _config ) + : StreamingReporterBase( _config ) + {} + + virtual ~CompactReporter(); + + static std::string getDescription() { + return "Reports test results on a single line, suitable for IDEs"; + } + + virtual ReporterPreferences getPreferences() const { + ReporterPreferences prefs; + prefs.shouldRedirectStdOut = false; + return prefs; + } + + virtual void noMatchingTestCases( std::string const& spec ) { + stream << "No test cases matched '" << spec << '\'' << std::endl; + } + + virtual void assertionStarting( AssertionInfo const& ) { + } + + virtual bool assertionEnded( AssertionStats const& _assertionStats ) { + AssertionResult const& result = _assertionStats.assertionResult; + + bool printInfoMessages = true; + + // Drop out if result was successful and we're not printing those + if( !m_config->includeSuccessfulResults() && result.isOk() ) { + if( result.getResultType() != ResultWas::Warning ) + return false; + printInfoMessages = false; + } + + AssertionPrinter printer( stream, _assertionStats, printInfoMessages ); + printer.print(); + + stream << std::endl; + return true; + } + + virtual void testRunEnded( TestRunStats const& _testRunStats ) { + printTotals( _testRunStats.totals ); + stream << '\n' << std::endl; + StreamingReporterBase::testRunEnded( _testRunStats ); + } + + private: + class AssertionPrinter { + void operator= ( AssertionPrinter const& ); + public: + AssertionPrinter( std::ostream& _stream, AssertionStats const& _stats, bool _printInfoMessages ) + : stream( _stream ) + , stats( _stats ) + , result( _stats.assertionResult ) + , messages( _stats.infoMessages ) + , itMessage( _stats.infoMessages.begin() ) + , printInfoMessages( _printInfoMessages ) + {} + + void print() { + printSourceInfo(); + + itMessage = messages.begin(); + + switch( result.getResultType() ) { + case ResultWas::Ok: + printResultType( Colour::ResultSuccess, passedString() ); + printOriginalExpression(); + printReconstructedExpression(); + if ( ! result.hasExpression() ) + printRemainingMessages( Colour::None ); + else + printRemainingMessages(); + break; + case ResultWas::ExpressionFailed: + if( result.isOk() ) + printResultType( Colour::ResultSuccess, failedString() + std::string( " - but was ok" ) ); + else + printResultType( Colour::Error, failedString() ); + printOriginalExpression(); + printReconstructedExpression(); + printRemainingMessages(); + break; + case ResultWas::ThrewException: + printResultType( Colour::Error, failedString() ); + printIssue( "unexpected exception with message:" ); + printMessage(); + printExpressionWas(); + printRemainingMessages(); + break; + case ResultWas::FatalErrorCondition: + printResultType( Colour::Error, failedString() ); + printIssue( "fatal error condition with message:" ); + printMessage(); + printExpressionWas(); + printRemainingMessages(); + break; + case ResultWas::DidntThrowException: + printResultType( Colour::Error, failedString() ); + printIssue( "expected exception, got none" ); + printExpressionWas(); + printRemainingMessages(); + break; + case ResultWas::Info: + printResultType( Colour::None, "info" ); + printMessage(); + printRemainingMessages(); + break; + case ResultWas::Warning: + printResultType( Colour::None, "warning" ); + printMessage(); + printRemainingMessages(); + break; + case ResultWas::ExplicitFailure: + printResultType( Colour::Error, failedString() ); + printIssue( "explicitly" ); + printRemainingMessages( Colour::None ); + break; + // These cases are here to prevent compiler warnings + case ResultWas::Unknown: + case ResultWas::FailureBit: + case ResultWas::Exception: + printResultType( Colour::Error, "** internal error **" ); + break; + } + } + + private: + // Colour::LightGrey + + static Colour::Code dimColour() { return Colour::FileName; } + +#ifdef CATCH_PLATFORM_MAC + static const char* failedString() { return "FAILED"; } + static const char* passedString() { return "PASSED"; } +#else + static const char* failedString() { return "failed"; } + static const char* passedString() { return "passed"; } +#endif + + void printSourceInfo() const { + Colour colourGuard( Colour::FileName ); + stream << result.getSourceInfo() << ':'; + } + + void printResultType( Colour::Code colour, std::string passOrFail ) const { + if( !passOrFail.empty() ) { + { + Colour colourGuard( colour ); + stream << ' ' << passOrFail; + } + stream << ':'; + } + } + + void printIssue( std::string issue ) const { + stream << ' ' << issue; + } + + void printExpressionWas() { + if( result.hasExpression() ) { + stream << ';'; + { + Colour colour( dimColour() ); + stream << " expression was:"; + } + printOriginalExpression(); + } + } + + void printOriginalExpression() const { + if( result.hasExpression() ) { + stream << ' ' << result.getExpression(); + } + } + + void printReconstructedExpression() const { + if( result.hasExpandedExpression() ) { + { + Colour colour( dimColour() ); + stream << " for: "; + } + stream << result.getExpandedExpression(); + } + } + + void printMessage() { + if ( itMessage != messages.end() ) { + stream << " '" << itMessage->message << '\''; + ++itMessage; + } + } + + void printRemainingMessages( Colour::Code colour = dimColour() ) { + if ( itMessage == messages.end() ) + return; + + // using messages.end() directly yields compilation error: + std::vector::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" ) << '.'; + } + } + }; + + INTERNAL_CATCH_REGISTER_REPORTER( "compact", CompactReporter ) + +} // end namespace Catch + +namespace Catch { + // These are all here to avoid warnings about not having any out of line + // virtual methods + NonCopyable::~NonCopyable() {} + IShared::~IShared() {} + IStream::~IStream() CATCH_NOEXCEPT {} + FileStream::~FileStream() CATCH_NOEXCEPT {} + CoutStream::~CoutStream() CATCH_NOEXCEPT {} + DebugOutStream::~DebugOutStream() CATCH_NOEXCEPT {} + StreamBufBase::~StreamBufBase() CATCH_NOEXCEPT {} + IContext::~IContext() {} + IResultCapture::~IResultCapture() {} + ITestCase::~ITestCase() {} + ITestCaseRegistry::~ITestCaseRegistry() {} + IRegistryHub::~IRegistryHub() {} + IMutableRegistryHub::~IMutableRegistryHub() {} + IExceptionTranslator::~IExceptionTranslator() {} + IExceptionTranslatorRegistry::~IExceptionTranslatorRegistry() {} + IReporter::~IReporter() {} + IReporterFactory::~IReporterFactory() {} + IReporterRegistry::~IReporterRegistry() {} + IStreamingReporter::~IStreamingReporter() {} + AssertionStats::~AssertionStats() {} + SectionStats::~SectionStats() {} + TestCaseStats::~TestCaseStats() {} + TestGroupStats::~TestGroupStats() {} + TestRunStats::~TestRunStats() {} + CumulativeReporterBase::SectionNode::~SectionNode() {} + CumulativeReporterBase::~CumulativeReporterBase() {} + + StreamingReporterBase::~StreamingReporterBase() {} + ConsoleReporter::~ConsoleReporter() {} + CompactReporter::~CompactReporter() {} + IRunner::~IRunner() {} + IMutableContext::~IMutableContext() {} + IConfig::~IConfig() {} + XmlReporter::~XmlReporter() {} + JunitReporter::~JunitReporter() {} + TestRegistry::~TestRegistry() {} + FreeFunctionTestCase::~FreeFunctionTestCase() {} + IGeneratorInfo::~IGeneratorInfo() {} + IGeneratorsForTest::~IGeneratorsForTest() {} + WildcardPattern::~WildcardPattern() {} + TestSpec::Pattern::~Pattern() {} + TestSpec::NamePattern::~NamePattern() {} + TestSpec::TagPattern::~TagPattern() {} + TestSpec::ExcludedPattern::~ExcludedPattern() {} + + Matchers::Impl::StdString::Equals::~Equals() {} + Matchers::Impl::StdString::Contains::~Contains() {} + Matchers::Impl::StdString::StartsWith::~StartsWith() {} + Matchers::Impl::StdString::EndsWith::~EndsWith() {} + + void Config::dummy() {} + + namespace TestCaseTracking { + ITracker::~ITracker() {} + TrackerBase::~TrackerBase() {} + SectionTracker::~SectionTracker() {} + IndexTracker::~IndexTracker() {} + } +} + +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + +#endif + +#ifdef CATCH_CONFIG_MAIN +// #included from: internal/catch_default_main.hpp +#define TWOBLUECUBES_CATCH_DEFAULT_MAIN_HPP_INCLUDED + +#ifndef __OBJC__ + +// Standard C/C++ main entry point +int main (int argc, char * argv[]) { + int result = Catch::Session().run( argc, argv ); + return ( result < 0xff ? result : 0xff ); +} + +#else // __OBJC__ + +// Objective-C entry point +int main (int argc, char * const argv[]) { +#if !CATCH_ARC_ENABLED + NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; +#endif + + Catch::registerTestMethods(); + int result = Catch::Session().run( argc, (char* const*)argv ); + +#if !CATCH_ARC_ENABLED + [pool drain]; +#endif + + return ( result < 0xff ? result : 0xff ); +} + +#endif // __OBJC__ + +#endif + +#ifdef CLARA_CONFIG_MAIN_NOT_DEFINED +# undef CLARA_CONFIG_MAIN +#endif + +////// + +// If this config identifier is defined then all CATCH macros are prefixed with CATCH_ +#ifdef CATCH_CONFIG_PREFIX_ALL + +#define CATCH_REQUIRE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal, "CATCH_REQUIRE" ) +#define CATCH_REQUIRE_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, "CATCH_REQUIRE_FALSE" ) + +#define CATCH_REQUIRE_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::Normal, "", "CATCH_REQUIRE_THROWS" ) +#define CATCH_REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_THROWS_AS" ) +#define CATCH_REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::Normal, matcher, "CATCH_REQUIRE_THROWS_WITH" ) +#define CATCH_REQUIRE_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_NOTHROW" ) + +#define CATCH_CHECK( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK" ) +#define CATCH_CHECK_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::FalseTest, "CATCH_CHECK_FALSE" ) +#define CATCH_CHECKED_IF( expr ) INTERNAL_CATCH_IF( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECKED_IF" ) +#define CATCH_CHECKED_ELSE( expr ) INTERNAL_CATCH_ELSE( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECKED_ELSE" ) +#define CATCH_CHECK_NOFAIL( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, "CATCH_CHECK_NOFAIL" ) + +#define CATCH_CHECK_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::ContinueOnFailure, "", "CATCH_CHECK_THROWS" ) +#define CATCH_CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_THROWS_AS" ) +#define CATCH_CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::ContinueOnFailure, matcher, "CATCH_CHECK_THROWS_WITH" ) +#define CATCH_CHECK_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_NOTHROW" ) + +#define CATCH_CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_THAT" ) +#define CATCH_REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_THAT" ) + +#define CATCH_INFO( msg ) INTERNAL_CATCH_INFO( msg, "CATCH_INFO" ) +#define CATCH_WARN( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, "CATCH_WARN", msg ) +#define CATCH_SCOPED_INFO( msg ) INTERNAL_CATCH_INFO( msg, "CATCH_INFO" ) +#define CATCH_CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CATCH_CAPTURE" ) +#define CATCH_SCOPED_CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CATCH_CAPTURE" ) + +#ifdef CATCH_CONFIG_VARIADIC_MACROS + #define CATCH_TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ ) + #define CATCH_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ ) + #define CATCH_METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ ) + #define CATCH_REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ ) + #define CATCH_SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ ) + #define CATCH_FAIL( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "CATCH_FAIL", __VA_ARGS__ ) + #define CATCH_SUCCEED( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "CATCH_SUCCEED", __VA_ARGS__ ) +#else + #define CATCH_TEST_CASE( name, description ) INTERNAL_CATCH_TESTCASE( name, description ) + #define CATCH_TEST_CASE_METHOD( className, name, description ) INTERNAL_CATCH_TEST_CASE_METHOD( className, name, description ) + #define CATCH_METHOD_AS_TEST_CASE( method, name, description ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, name, description ) + #define CATCH_REGISTER_TEST_CASE( function, name, description ) INTERNAL_CATCH_REGISTER_TESTCASE( function, name, description ) + #define CATCH_SECTION( name, description ) INTERNAL_CATCH_SECTION( name, description ) + #define CATCH_FAIL( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "CATCH_FAIL", msg ) + #define CATCH_SUCCEED( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "CATCH_SUCCEED", msg ) +#endif +#define CATCH_ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE( "", "" ) + +#define CATCH_REGISTER_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType ) +#define CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) + +#define CATCH_GENERATE( expr) INTERNAL_CATCH_GENERATE( expr ) + +// "BDD-style" convenience wrappers +#ifdef CATCH_CONFIG_VARIADIC_MACROS +#define CATCH_SCENARIO( ... ) CATCH_TEST_CASE( "Scenario: " __VA_ARGS__ ) +#define CATCH_SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ ) +#else +#define CATCH_SCENARIO( name, tags ) CATCH_TEST_CASE( "Scenario: " name, tags ) +#define CATCH_SCENARIO_METHOD( className, name, tags ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " name, tags ) +#endif +#define CATCH_GIVEN( desc ) CATCH_SECTION( std::string( "Given: ") + desc, "" ) +#define CATCH_WHEN( desc ) CATCH_SECTION( std::string( " When: ") + desc, "" ) +#define CATCH_AND_WHEN( desc ) CATCH_SECTION( std::string( " And: ") + desc, "" ) +#define CATCH_THEN( desc ) CATCH_SECTION( std::string( " Then: ") + desc, "" ) +#define CATCH_AND_THEN( desc ) CATCH_SECTION( std::string( " And: ") + desc, "" ) + +// If CATCH_CONFIG_PREFIX_ALL is not defined then the CATCH_ prefix is not required +#else + +#define REQUIRE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal, "REQUIRE" ) +#define REQUIRE_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, "REQUIRE_FALSE" ) + +#define REQUIRE_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::Normal, "", "REQUIRE_THROWS" ) +#define REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::Normal, "REQUIRE_THROWS_AS" ) +#define REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::Normal, matcher, "REQUIRE_THROWS_WITH" ) +#define REQUIRE_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::Normal, "REQUIRE_NOTHROW" ) + +#define CHECK( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECK" ) +#define CHECK_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::FalseTest, "CHECK_FALSE" ) +#define CHECKED_IF( expr ) INTERNAL_CATCH_IF( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECKED_IF" ) +#define CHECKED_ELSE( expr ) INTERNAL_CATCH_ELSE( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECKED_ELSE" ) +#define CHECK_NOFAIL( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, "CHECK_NOFAIL" ) + +#define CHECK_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::ContinueOnFailure, "", "CHECK_THROWS" ) +#define CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::ContinueOnFailure, "CHECK_THROWS_AS" ) +#define CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::ContinueOnFailure, matcher, "CHECK_THROWS_WITH" ) +#define CHECK_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECK_NOTHROW" ) + +#define CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::ContinueOnFailure, "CHECK_THAT" ) +#define REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::Normal, "REQUIRE_THAT" ) + +#define INFO( msg ) INTERNAL_CATCH_INFO( msg, "INFO" ) +#define WARN( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, "WARN", msg ) +#define SCOPED_INFO( msg ) INTERNAL_CATCH_INFO( msg, "INFO" ) +#define CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CAPTURE" ) +#define SCOPED_CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CAPTURE" ) + +#ifdef CATCH_CONFIG_VARIADIC_MACROS + #define TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ ) + #define TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ ) + #define METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ ) + #define REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ ) + #define SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ ) + #define FAIL( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "FAIL", __VA_ARGS__ ) + #define SUCCEED( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "SUCCEED", __VA_ARGS__ ) +#else + #define TEST_CASE( name, description ) INTERNAL_CATCH_TESTCASE( name, description ) + #define TEST_CASE_METHOD( className, name, description ) INTERNAL_CATCH_TEST_CASE_METHOD( className, name, description ) + #define METHOD_AS_TEST_CASE( method, name, description ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, name, description ) + #define REGISTER_TEST_CASE( method, name, description ) INTERNAL_CATCH_REGISTER_TESTCASE( method, name, description ) + #define SECTION( name, description ) INTERNAL_CATCH_SECTION( name, description ) + #define FAIL( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "FAIL", msg ) + #define SUCCEED( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "SUCCEED", msg ) +#endif +#define ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE( "", "" ) + +#define REGISTER_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType ) +#define REGISTER_LEGACY_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) + +#define GENERATE( expr) INTERNAL_CATCH_GENERATE( expr ) + +#endif + +#define CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) + +// "BDD-style" convenience wrappers +#ifdef CATCH_CONFIG_VARIADIC_MACROS +#define SCENARIO( ... ) TEST_CASE( "Scenario: " __VA_ARGS__ ) +#define SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ ) +#else +#define SCENARIO( name, tags ) TEST_CASE( "Scenario: " name, tags ) +#define SCENARIO_METHOD( className, name, tags ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " name, tags ) +#endif +#define GIVEN( desc ) SECTION( std::string(" Given: ") + desc, "" ) +#define WHEN( desc ) SECTION( std::string(" When: ") + desc, "" ) +#define AND_WHEN( desc ) SECTION( std::string("And when: ") + desc, "" ) +#define THEN( desc ) SECTION( std::string(" Then: ") + desc, "" ) +#define AND_THEN( desc ) SECTION( std::string(" And: ") + desc, "" ) + +using Catch::Detail::Approx; + +#endif // TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED + From 82fb6137633e630a7c5ab0de3aebdde831ef61af Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Tue, 14 Feb 2017 07:28:30 +0100 Subject: [PATCH 54/80] :memo: update after #302 --- README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 9732a0fa..ab44c969 100644 --- a/README.md +++ b/README.md @@ -809,7 +809,7 @@ I deeply appreciate the help of the following people. - [Vladimir Petrigo](https://github.com/vpetrigo) made a SFINAE hack more readable. - [Denis Andrejew](https://github.com/seeekr) fixed a grammar issue in the README file. - [Pierre-Antoine Lacaze](https://github.com/palacaze) found a subtle bug in the `dump()` function. -- [TurpentineDistillery](https://github.com/TurpentineDistillery) pointed to [`std::locale::classic()`](http://en.cppreference.com/w/cpp/locale/locale/classic) to avoid too much locale joggling, found some nice performance improvements in the parser and improved the benchmarking code. +- [TurpentineDistillery](https://github.com/TurpentineDistillery) pointed to [`std::locale::classic()`](http://en.cppreference.com/w/cpp/locale/locale/classic) to avoid too much locale joggling, found some nice performance improvements in the parser, improved the benchmarking code, and realized locale-independent number parsing. - [cgzones](https://github.com/cgzones) had an idea how to fix the Coverity scan. - [Jared Grubb](https://github.com/jaredgrubb) silenced a nasty documentation warning. - [Yixin Zhang](https://github.com/qwename) fixed an integer overflow check. @@ -823,6 +823,7 @@ I deeply appreciate the help of the following people. - [Martin HoÅ™eňovský](https://github.com/horenmar) found a way for a 2x speedup for the compilation time of the test suite. - [ukhegg](https://github.com/ukhegg) found proposed an improvement for the examples section. - [rswanson-ihi](https://github.com/rswanson-ihi) noted a type in the README. +- Thanks a lot for helping out! Please [let me know](mailto:mail@nlohmann.me) if I forgot someone. @@ -856,7 +857,7 @@ $ make json_unit -Ctest $ ./test/json_unit "*"" =============================================================================== -All tests passed (11202549 assertions in 47 test cases) +All tests passed (11202562 assertions in 47 test cases) ``` Alternatively, you can use [CMake](https://cmake.org) and run From b9f314945140afb427f424b8f2de568b92bc03c3 Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Wed, 15 Feb 2017 21:30:28 +0100 Subject: [PATCH 55/80] :ambulance: fix for #452 --- src/json.hpp | 252 +++++++++++++++++++-------------- src/json.hpp.re2c | 2 + test/src/unit-class_parser.cpp | 4 +- test/src/unit-regression.cpp | 12 ++ 4 files changed, 163 insertions(+), 107 deletions(-) diff --git a/src/json.hpp b/src/json.hpp index bf9386b3..cc593200 100644 --- a/src/json.hpp +++ b/src/json.hpp @@ -9883,22 +9883,32 @@ basic_json_parser_12: basic_json_parser_13: yyaccept = 1; yych = *(m_marker = ++m_cursor); - if (yych <= 'D') + if (yych <= '9') { if (yych == '.') { goto basic_json_parser_47; } + if (yych >= '0') + { + goto basic_json_parser_48; + } } else { if (yych <= 'E') { - goto basic_json_parser_48; + if (yych >= 'E') + { + goto basic_json_parser_51; + } } - if (yych == 'e') + else { - goto basic_json_parser_48; + if (yych == 'e') + { + goto basic_json_parser_51; + } } } basic_json_parser_14: @@ -9930,11 +9940,11 @@ basic_json_parser_15: { if (yych <= 'E') { - goto basic_json_parser_48; + goto basic_json_parser_51; } if (yych == 'e') { - goto basic_json_parser_48; + goto basic_json_parser_51; } goto basic_json_parser_14; } @@ -9961,7 +9971,7 @@ basic_json_parser_23: yych = *(m_marker = ++m_cursor); if (yych == 'a') { - goto basic_json_parser_49; + goto basic_json_parser_52; } goto basic_json_parser_5; basic_json_parser_24: @@ -9969,7 +9979,7 @@ basic_json_parser_24: yych = *(m_marker = ++m_cursor); if (yych == 'u') { - goto basic_json_parser_50; + goto basic_json_parser_53; } goto basic_json_parser_5; basic_json_parser_25: @@ -9977,7 +9987,7 @@ basic_json_parser_25: yych = *(m_marker = ++m_cursor); if (yych == 'r') { - goto basic_json_parser_51; + goto basic_json_parser_54; } goto basic_json_parser_5; basic_json_parser_26: @@ -10078,7 +10088,7 @@ basic_json_parser_32: } else { - goto basic_json_parser_55; + goto basic_json_parser_58; } } basic_json_parser_33: @@ -10160,7 +10170,7 @@ basic_json_parser_35: } if (yych <= 'u') { - goto basic_json_parser_52; + goto basic_json_parser_55; } goto basic_json_parser_32; } @@ -10281,22 +10291,32 @@ basic_json_parser_42: basic_json_parser_43: yyaccept = 2; yych = *(m_marker = ++m_cursor); - if (yych <= 'D') + if (yych <= '9') { if (yych == '.') { goto basic_json_parser_47; } + if (yych >= '0') + { + goto basic_json_parser_48; + } } else { if (yych <= 'E') { - goto basic_json_parser_48; + if (yych >= 'E') + { + goto basic_json_parser_51; + } } - if (yych == 'e') + else { - goto basic_json_parser_48; + if (yych == 'e') + { + goto basic_json_parser_51; + } } } basic_json_parser_44: @@ -10332,13 +10352,13 @@ basic_json_parser_45: { goto basic_json_parser_44; } - goto basic_json_parser_48; + goto basic_json_parser_51; } else { if (yych == 'e') { - goto basic_json_parser_48; + goto basic_json_parser_51; } goto basic_json_parser_44; } @@ -10351,16 +10371,36 @@ basic_json_parser_47: } if (yych <= '9') { - goto basic_json_parser_53; + goto basic_json_parser_56; } goto basic_json_parser_32; basic_json_parser_48: + ++m_cursor; + if (m_limit <= m_cursor) + { + fill_line_buffer(1); // LCOV_EXCL_LINE + } + yych = *m_cursor; + if (yych <= '/') + { + goto basic_json_parser_50; + } + if (yych <= '9') + { + goto basic_json_parser_48; + } +basic_json_parser_50: + { + last_token_type = token_type::parse_error; + break; + } +basic_json_parser_51: yych = *++m_cursor; if (yych <= ',') { if (yych == '+') { - goto basic_json_parser_56; + goto basic_json_parser_59; } goto basic_json_parser_32; } @@ -10368,7 +10408,7 @@ basic_json_parser_48: { if (yych <= '-') { - goto basic_json_parser_56; + goto basic_json_parser_59; } if (yych <= '/') { @@ -10376,32 +10416,32 @@ basic_json_parser_48: } if (yych <= '9') { - goto basic_json_parser_57; + goto basic_json_parser_60; } goto basic_json_parser_32; } -basic_json_parser_49: +basic_json_parser_52: yych = *++m_cursor; if (yych == 'l') { - goto basic_json_parser_59; + goto basic_json_parser_62; } goto basic_json_parser_32; -basic_json_parser_50: +basic_json_parser_53: yych = *++m_cursor; if (yych == 'l') { - goto basic_json_parser_60; + goto basic_json_parser_63; } goto basic_json_parser_32; -basic_json_parser_51: +basic_json_parser_54: yych = *++m_cursor; if (yych == 'u') { - goto basic_json_parser_61; + goto basic_json_parser_64; } goto basic_json_parser_32; -basic_json_parser_52: +basic_json_parser_55: ++m_cursor; if (m_limit <= m_cursor) { @@ -10416,7 +10456,7 @@ basic_json_parser_52: } if (yych <= '9') { - goto basic_json_parser_62; + goto basic_json_parser_65; } goto basic_json_parser_32; } @@ -10424,7 +10464,7 @@ basic_json_parser_52: { if (yych <= 'F') { - goto basic_json_parser_62; + goto basic_json_parser_65; } if (yych <= '`') { @@ -10432,11 +10472,11 @@ basic_json_parser_52: } if (yych <= 'f') { - goto basic_json_parser_62; + goto basic_json_parser_65; } goto basic_json_parser_32; } -basic_json_parser_53: +basic_json_parser_56: yyaccept = 3; m_marker = ++m_cursor; if ((m_limit - m_cursor) < 3) @@ -10448,30 +10488,30 @@ basic_json_parser_53: { if (yych <= '/') { - goto basic_json_parser_55; + goto basic_json_parser_58; } if (yych <= '9') { - goto basic_json_parser_53; + goto basic_json_parser_56; } } else { if (yych <= 'E') { - goto basic_json_parser_48; + goto basic_json_parser_51; } if (yych == 'e') { - goto basic_json_parser_48; + goto basic_json_parser_51; } } -basic_json_parser_55: +basic_json_parser_58: { last_token_type = token_type::value_float; break; } -basic_json_parser_56: +basic_json_parser_59: yych = *++m_cursor; if (yych <= '/') { @@ -10481,7 +10521,7 @@ basic_json_parser_56: { goto basic_json_parser_32; } -basic_json_parser_57: +basic_json_parser_60: ++m_cursor; if (m_limit <= m_cursor) { @@ -10490,89 +10530,35 @@ basic_json_parser_57: yych = *m_cursor; if (yych <= '/') { - goto basic_json_parser_55; + goto basic_json_parser_58; } if (yych <= '9') { - goto basic_json_parser_57; + goto basic_json_parser_60; } - goto basic_json_parser_55; -basic_json_parser_59: + goto basic_json_parser_58; +basic_json_parser_62: yych = *++m_cursor; if (yych == 's') - { - goto basic_json_parser_63; - } - goto basic_json_parser_32; -basic_json_parser_60: - yych = *++m_cursor; - if (yych == 'l') - { - goto basic_json_parser_64; - } - goto basic_json_parser_32; -basic_json_parser_61: - yych = *++m_cursor; - if (yych == 'e') { goto basic_json_parser_66; } goto basic_json_parser_32; -basic_json_parser_62: - ++m_cursor; - if (m_limit <= m_cursor) - { - fill_line_buffer(1); // LCOV_EXCL_LINE - } - yych = *m_cursor; - if (yych <= '@') - { - if (yych <= '/') - { - goto basic_json_parser_32; - } - if (yych <= '9') - { - goto basic_json_parser_68; - } - goto basic_json_parser_32; - } - else - { - if (yych <= 'F') - { - goto basic_json_parser_68; - } - if (yych <= '`') - { - goto basic_json_parser_32; - } - if (yych <= 'f') - { - goto basic_json_parser_68; - } - goto basic_json_parser_32; - } basic_json_parser_63: + yych = *++m_cursor; + if (yych == 'l') + { + goto basic_json_parser_67; + } + goto basic_json_parser_32; +basic_json_parser_64: yych = *++m_cursor; if (yych == 'e') { goto basic_json_parser_69; } goto basic_json_parser_32; -basic_json_parser_64: - ++m_cursor; - { - last_token_type = token_type::literal_null; - break; - } -basic_json_parser_66: - ++m_cursor; - { - last_token_type = token_type::literal_true; - break; - } -basic_json_parser_68: +basic_json_parser_65: ++m_cursor; if (m_limit <= m_cursor) { @@ -10607,13 +10593,67 @@ basic_json_parser_68: } goto basic_json_parser_32; } +basic_json_parser_66: + yych = *++m_cursor; + if (yych == 'e') + { + goto basic_json_parser_72; + } + goto basic_json_parser_32; +basic_json_parser_67: + ++m_cursor; + { + last_token_type = token_type::literal_null; + break; + } basic_json_parser_69: + ++m_cursor; + { + last_token_type = token_type::literal_true; + break; + } +basic_json_parser_71: + ++m_cursor; + if (m_limit <= m_cursor) + { + fill_line_buffer(1); // LCOV_EXCL_LINE + } + yych = *m_cursor; + if (yych <= '@') + { + if (yych <= '/') + { + goto basic_json_parser_32; + } + if (yych <= '9') + { + goto basic_json_parser_74; + } + goto basic_json_parser_32; + } + else + { + if (yych <= 'F') + { + goto basic_json_parser_74; + } + if (yych <= '`') + { + goto basic_json_parser_32; + } + if (yych <= 'f') + { + goto basic_json_parser_74; + } + goto basic_json_parser_32; + } +basic_json_parser_72: ++m_cursor; { last_token_type = token_type::literal_false; break; } -basic_json_parser_71: +basic_json_parser_74: ++m_cursor; if (m_limit <= m_cursor) { diff --git a/src/json.hpp.re2c b/src/json.hpp.re2c index e15f7b1f..bfb3c958 100644 --- a/src/json.hpp.re2c +++ b/src/json.hpp.re2c @@ -9698,6 +9698,8 @@ class basic_json exp = e (minus | plus)? digit+; frac = decimal_point digit+; int = (zero | digit_1_9 digit*); + invalid_int = minus? "0" digit+; + invalid_int { last_token_type = token_type::parse_error; break; } number_unsigned = int; number_unsigned { last_token_type = token_type::value_unsigned; break; } number_integer = minus int; diff --git a/test/src/unit-class_parser.cpp b/test/src/unit-class_parser.cpp index 2fb0da2b..09c5a160 100644 --- a/test/src/unit-class_parser.cpp +++ b/test/src/unit-class_parser.cpp @@ -299,7 +299,9 @@ TEST_CASE("parser class") CHECK_THROWS_AS(json::parser("+0").parse(), std::invalid_argument); CHECK_THROWS_WITH(json::parser("01").parse(), - "parse error - unexpected number literal"); + "parse error - unexpected '01'"); + CHECK_THROWS_WITH(json::parser("-01").parse(), + "parse error - unexpected '-01'"); CHECK_THROWS_WITH(json::parser("--1").parse(), "parse error - unexpected '-'"); CHECK_THROWS_WITH(json::parser("1.").parse(), "parse error - unexpected '.'; expected end of input"); diff --git a/test/src/unit-regression.cpp b/test/src/unit-regression.cpp index dcfcf62b..3bd50747 100644 --- a/test/src/unit-regression.cpp +++ b/test/src/unit-regression.cpp @@ -724,4 +724,16 @@ TEST_CASE("regression tests") }; CHECK_THROWS_AS(json::from_cbor(vec2), std::out_of_range); } + + 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), std::invalid_argument); + } + + //SECTION("issue #454 - doubles are printed as integers") + //{ + // json j = R"({"bool_value":true,"double_value":2.0,"int_value":10,"level1":{"list_value":[3,"hi",false],"tmp":5.0},"string_value":"hello"})"_json; + // CHECK(j["double_value"].is_number_integer()); + //} } From 973402c11ed423e23860d1bf292d53f13accded2 Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Wed, 15 Feb 2017 22:44:18 +0100 Subject: [PATCH 56/80] :construction: replaced throws (#440) and _MAX/_MIN macros (#451) --- src/json.hpp | 58 +++++++++++++++++++++++------------------------ src/json.hpp.re2c | 58 +++++++++++++++++++++++------------------------ 2 files changed, 58 insertions(+), 58 deletions(-) diff --git a/src/json.hpp b/src/json.hpp index cc593200..fdb58bfb 100644 --- a/src/json.hpp +++ b/src/json.hpp @@ -3149,8 +3149,8 @@ class basic_json return *ptr; } - throw std::domain_error("incompatible ReferenceType for get_ref, actual type is " + - obj.type_name()); + JSON_THROW(std::domain_error("incompatible ReferenceType for get_ref, actual type is " + + obj.type_name())); } public: @@ -6712,25 +6712,25 @@ class basic_json // positive fixnum add_to_vector(v, 1, j.m_value.number_unsigned); } - else if (j.m_value.number_unsigned <= UINT8_MAX) + else if (j.m_value.number_unsigned <= std::numeric_limits::max()) { // uint 8 v.push_back(0xcc); add_to_vector(v, 1, j.m_value.number_unsigned); } - else if (j.m_value.number_unsigned <= UINT16_MAX) + else if (j.m_value.number_unsigned <= std::numeric_limits::max()) { // uint 16 v.push_back(0xcd); add_to_vector(v, 2, j.m_value.number_unsigned); } - else if (j.m_value.number_unsigned <= UINT32_MAX) + else if (j.m_value.number_unsigned <= std::numeric_limits::max()) { // uint 32 v.push_back(0xce); add_to_vector(v, 4, j.m_value.number_unsigned); } - else if (j.m_value.number_unsigned <= UINT64_MAX) + else if (j.m_value.number_unsigned <= std::numeric_limits::max()) { // uint 64 v.push_back(0xcf); @@ -6744,25 +6744,25 @@ class basic_json // negative fixnum add_to_vector(v, 1, j.m_value.number_integer); } - else if (j.m_value.number_integer >= INT8_MIN and j.m_value.number_integer <= INT8_MAX) + else if (j.m_value.number_integer >= std::numeric_limits::min() and j.m_value.number_integer <= std::numeric_limits::max()) { // int 8 v.push_back(0xd0); add_to_vector(v, 1, j.m_value.number_integer); } - else if (j.m_value.number_integer >= INT16_MIN and j.m_value.number_integer <= INT16_MAX) + else if (j.m_value.number_integer >= std::numeric_limits::min() and j.m_value.number_integer <= std::numeric_limits::max()) { // int 16 v.push_back(0xd1); add_to_vector(v, 2, j.m_value.number_integer); } - else if (j.m_value.number_integer >= INT32_MIN and j.m_value.number_integer <= INT32_MAX) + else if (j.m_value.number_integer >= std::numeric_limits::min() and j.m_value.number_integer <= std::numeric_limits::max()) { // int 32 v.push_back(0xd2); add_to_vector(v, 4, j.m_value.number_integer); } - else if (j.m_value.number_integer >= INT64_MIN and j.m_value.number_integer <= INT64_MAX) + else if (j.m_value.number_integer >= std::numeric_limits::min() and j.m_value.number_integer <= std::numeric_limits::max()) { // int 64 v.push_back(0xd3); @@ -6779,25 +6779,25 @@ class basic_json // positive fixnum add_to_vector(v, 1, j.m_value.number_unsigned); } - else if (j.m_value.number_unsigned <= UINT8_MAX) + else if (j.m_value.number_unsigned <= std::numeric_limits::max()) { // uint 8 v.push_back(0xcc); add_to_vector(v, 1, j.m_value.number_unsigned); } - else if (j.m_value.number_unsigned <= UINT16_MAX) + else if (j.m_value.number_unsigned <= std::numeric_limits::max()) { // uint 16 v.push_back(0xcd); add_to_vector(v, 2, j.m_value.number_unsigned); } - else if (j.m_value.number_unsigned <= UINT32_MAX) + else if (j.m_value.number_unsigned <= std::numeric_limits::max()) { // uint 32 v.push_back(0xce); add_to_vector(v, 4, j.m_value.number_unsigned); } - else if (j.m_value.number_unsigned <= UINT64_MAX) + else if (j.m_value.number_unsigned <= std::numeric_limits::max()) { // uint 64 v.push_back(0xcf); @@ -6954,19 +6954,19 @@ class basic_json { add_to_vector(v, 1, j.m_value.number_integer); } - else if (j.m_value.number_integer <= UINT8_MAX) + else if (j.m_value.number_integer <= std::numeric_limits::max()) { v.push_back(0x18); // one-byte uint8_t add_to_vector(v, 1, j.m_value.number_integer); } - else if (j.m_value.number_integer <= UINT16_MAX) + else if (j.m_value.number_integer <= std::numeric_limits::max()) { v.push_back(0x19); // two-byte uint16_t add_to_vector(v, 2, j.m_value.number_integer); } - else if (j.m_value.number_integer <= UINT32_MAX) + else if (j.m_value.number_integer <= std::numeric_limits::max()) { v.push_back(0x1a); // four-byte uint32_t @@ -6988,19 +6988,19 @@ class basic_json { v.push_back(static_cast(0x20 + positive_number)); } - else if (positive_number <= UINT8_MAX) + else if (positive_number <= std::numeric_limits::max()) { // int 8 v.push_back(0x38); add_to_vector(v, 1, positive_number); } - else if (positive_number <= UINT16_MAX) + else if (positive_number <= std::numeric_limits::max()) { // int 16 v.push_back(0x39); add_to_vector(v, 2, positive_number); } - else if (positive_number <= UINT32_MAX) + else if (positive_number <= std::numeric_limits::max()) { // int 32 v.push_back(0x3a); @@ -11788,9 +11788,9 @@ basic_json_parser_74: if (reference_token == "-") { // "-" always fails the range check - throw std::out_of_range("array index '-' (" + - std::to_string(ptr->m_value.array->size()) + - ") is out of range"); + JSON_THROW(std::out_of_range("array index '-' (" + + std::to_string(ptr->m_value.array->size()) + + ") is out of range")); } // error condition (cf. RFC 6901, Sect. 4) @@ -11840,9 +11840,9 @@ basic_json_parser_74: if (reference_token == "-") { // "-" cannot be used for const access - throw std::out_of_range("array index '-' (" + - std::to_string(ptr->m_value.array->size()) + - ") is out of range"); + JSON_THROW(std::out_of_range("array index '-' (" + + std::to_string(ptr->m_value.array->size()) + + ") is out of range")); } // error condition (cf. RFC 6901, Sect. 4) @@ -11884,9 +11884,9 @@ basic_json_parser_74: if (reference_token == "-") { // "-" always fails the range check - throw std::out_of_range("array index '-' (" + - std::to_string(ptr->m_value.array->size()) + - ") is out of range"); + JSON_THROW(std::out_of_range("array index '-' (" + + std::to_string(ptr->m_value.array->size()) + + ") is out of range")); } // error condition (cf. RFC 6901, Sect. 4) diff --git a/src/json.hpp.re2c b/src/json.hpp.re2c index bfb3c958..dbed606c 100644 --- a/src/json.hpp.re2c +++ b/src/json.hpp.re2c @@ -3149,8 +3149,8 @@ class basic_json return *ptr; } - throw std::domain_error("incompatible ReferenceType for get_ref, actual type is " + - obj.type_name()); + JSON_THROW(std::domain_error("incompatible ReferenceType for get_ref, actual type is " + + obj.type_name())); } public: @@ -6712,25 +6712,25 @@ class basic_json // positive fixnum add_to_vector(v, 1, j.m_value.number_unsigned); } - else if (j.m_value.number_unsigned <= UINT8_MAX) + else if (j.m_value.number_unsigned <= std::numeric_limits::max()) { // uint 8 v.push_back(0xcc); add_to_vector(v, 1, j.m_value.number_unsigned); } - else if (j.m_value.number_unsigned <= UINT16_MAX) + else if (j.m_value.number_unsigned <= std::numeric_limits::max()) { // uint 16 v.push_back(0xcd); add_to_vector(v, 2, j.m_value.number_unsigned); } - else if (j.m_value.number_unsigned <= UINT32_MAX) + else if (j.m_value.number_unsigned <= std::numeric_limits::max()) { // uint 32 v.push_back(0xce); add_to_vector(v, 4, j.m_value.number_unsigned); } - else if (j.m_value.number_unsigned <= UINT64_MAX) + else if (j.m_value.number_unsigned <= std::numeric_limits::max()) { // uint 64 v.push_back(0xcf); @@ -6744,25 +6744,25 @@ class basic_json // negative fixnum add_to_vector(v, 1, j.m_value.number_integer); } - else if (j.m_value.number_integer >= INT8_MIN and j.m_value.number_integer <= INT8_MAX) + else if (j.m_value.number_integer >= std::numeric_limits::min() and j.m_value.number_integer <= std::numeric_limits::max()) { // int 8 v.push_back(0xd0); add_to_vector(v, 1, j.m_value.number_integer); } - else if (j.m_value.number_integer >= INT16_MIN and j.m_value.number_integer <= INT16_MAX) + else if (j.m_value.number_integer >= std::numeric_limits::min() and j.m_value.number_integer <= std::numeric_limits::max()) { // int 16 v.push_back(0xd1); add_to_vector(v, 2, j.m_value.number_integer); } - else if (j.m_value.number_integer >= INT32_MIN and j.m_value.number_integer <= INT32_MAX) + else if (j.m_value.number_integer >= std::numeric_limits::min() and j.m_value.number_integer <= std::numeric_limits::max()) { // int 32 v.push_back(0xd2); add_to_vector(v, 4, j.m_value.number_integer); } - else if (j.m_value.number_integer >= INT64_MIN and j.m_value.number_integer <= INT64_MAX) + else if (j.m_value.number_integer >= std::numeric_limits::min() and j.m_value.number_integer <= std::numeric_limits::max()) { // int 64 v.push_back(0xd3); @@ -6779,25 +6779,25 @@ class basic_json // positive fixnum add_to_vector(v, 1, j.m_value.number_unsigned); } - else if (j.m_value.number_unsigned <= UINT8_MAX) + else if (j.m_value.number_unsigned <= std::numeric_limits::max()) { // uint 8 v.push_back(0xcc); add_to_vector(v, 1, j.m_value.number_unsigned); } - else if (j.m_value.number_unsigned <= UINT16_MAX) + else if (j.m_value.number_unsigned <= std::numeric_limits::max()) { // uint 16 v.push_back(0xcd); add_to_vector(v, 2, j.m_value.number_unsigned); } - else if (j.m_value.number_unsigned <= UINT32_MAX) + else if (j.m_value.number_unsigned <= std::numeric_limits::max()) { // uint 32 v.push_back(0xce); add_to_vector(v, 4, j.m_value.number_unsigned); } - else if (j.m_value.number_unsigned <= UINT64_MAX) + else if (j.m_value.number_unsigned <= std::numeric_limits::max()) { // uint 64 v.push_back(0xcf); @@ -6954,19 +6954,19 @@ class basic_json { add_to_vector(v, 1, j.m_value.number_integer); } - else if (j.m_value.number_integer <= UINT8_MAX) + else if (j.m_value.number_integer <= std::numeric_limits::max()) { v.push_back(0x18); // one-byte uint8_t add_to_vector(v, 1, j.m_value.number_integer); } - else if (j.m_value.number_integer <= UINT16_MAX) + else if (j.m_value.number_integer <= std::numeric_limits::max()) { v.push_back(0x19); // two-byte uint16_t add_to_vector(v, 2, j.m_value.number_integer); } - else if (j.m_value.number_integer <= UINT32_MAX) + else if (j.m_value.number_integer <= std::numeric_limits::max()) { v.push_back(0x1a); // four-byte uint32_t @@ -6988,19 +6988,19 @@ class basic_json { v.push_back(static_cast(0x20 + positive_number)); } - else if (positive_number <= UINT8_MAX) + else if (positive_number <= std::numeric_limits::max()) { // int 8 v.push_back(0x38); add_to_vector(v, 1, positive_number); } - else if (positive_number <= UINT16_MAX) + else if (positive_number <= std::numeric_limits::max()) { // int 16 v.push_back(0x39); add_to_vector(v, 2, positive_number); } - else if (positive_number <= UINT32_MAX) + else if (positive_number <= std::numeric_limits::max()) { // int 32 v.push_back(0x3a); @@ -10822,9 +10822,9 @@ class basic_json if (reference_token == "-") { // "-" always fails the range check - throw std::out_of_range("array index '-' (" + - std::to_string(ptr->m_value.array->size()) + - ") is out of range"); + JSON_THROW(std::out_of_range("array index '-' (" + + std::to_string(ptr->m_value.array->size()) + + ") is out of range")); } // error condition (cf. RFC 6901, Sect. 4) @@ -10874,9 +10874,9 @@ class basic_json if (reference_token == "-") { // "-" cannot be used for const access - throw std::out_of_range("array index '-' (" + - std::to_string(ptr->m_value.array->size()) + - ") is out of range"); + JSON_THROW(std::out_of_range("array index '-' (" + + std::to_string(ptr->m_value.array->size()) + + ") is out of range")); } // error condition (cf. RFC 6901, Sect. 4) @@ -10918,9 +10918,9 @@ class basic_json if (reference_token == "-") { // "-" always fails the range check - throw std::out_of_range("array index '-' (" + - std::to_string(ptr->m_value.array->size()) + - ") is out of range"); + JSON_THROW(std::out_of_range("array index '-' (" + + std::to_string(ptr->m_value.array->size()) + + ") is out of range")); } // error condition (cf. RFC 6901, Sect. 4) From 2c17c1b1b2f7a33abf520b2cf8c53fdf0d6c77c2 Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Thu, 16 Feb 2017 08:01:01 +0100 Subject: [PATCH 57/80] :lipstick: cleanup --- src/json.hpp | 10 +--------- src/json.hpp.re2c | 10 +--------- 2 files changed, 2 insertions(+), 18 deletions(-) diff --git a/src/json.hpp b/src/json.hpp index fdb58bfb..f823d435 100644 --- a/src/json.hpp +++ b/src/json.hpp @@ -11446,16 +11446,8 @@ basic_json_parser_74: case lexer::token_type::value_integer: case lexer::token_type::value_float: { - const bool ok = m_lexer.get_number(result, last_token); + m_lexer.get_number(result, last_token); get_token(); - - // if number conversion was unsuccessful, then is is - // because the number was directly followed by an - // unexpected character (e.g. "01" where "1" is unexpected) - if (not ok) - { - unexpect(last_token); - } break; } diff --git a/src/json.hpp.re2c b/src/json.hpp.re2c index dbed606c..d58e80fc 100644 --- a/src/json.hpp.re2c +++ b/src/json.hpp.re2c @@ -10480,16 +10480,8 @@ class basic_json case lexer::token_type::value_integer: case lexer::token_type::value_float: { - const bool ok = m_lexer.get_number(result, last_token); + m_lexer.get_number(result, last_token); get_token(); - - // if number conversion was unsuccessful, then is is - // because the number was directly followed by an - // unexpected character (e.g. "01" where "1" is unexpected) - if (not ok) - { - unexpect(last_token); - } break; } From 0200f2dc6280c474d4298b490ce54cc254e2eb3b Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Fri, 17 Feb 2017 19:14:21 +0100 Subject: [PATCH 58/80] :construction: fixing warning C4267 (#453) --- src/json.hpp | 6 +++--- src/json.hpp.re2c | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/json.hpp b/src/json.hpp index 6e49b4d9..5ad77f9d 100644 --- a/src/json.hpp +++ b/src/json.hpp @@ -7046,7 +7046,7 @@ class basic_json const auto N = j.m_value.string->size(); if (N <= 0x17) { - v.push_back(0x60 + N); // 1 byte for string + size + v.push_back(0x60 + static_cast(N)); // 1 byte for string + size } else if (N <= 0xff) { @@ -7082,7 +7082,7 @@ class basic_json const auto N = j.m_value.array->size(); if (N <= 0x17) { - v.push_back(0x80 + N); // 1 byte for array + size + v.push_back(0x80 + static_cast(N)); // 1 byte for array + size } else if (N <= 0xff) { @@ -7120,7 +7120,7 @@ class basic_json const auto N = j.m_value.object->size(); if (N <= 0x17) { - v.push_back(0xa0 + N); // 1 byte for object + size + v.push_back(0xa0 + static_cast(N)); // 1 byte for object + size } else if (N <= 0xff) { diff --git a/src/json.hpp.re2c b/src/json.hpp.re2c index dae2e958..84c0e893 100644 --- a/src/json.hpp.re2c +++ b/src/json.hpp.re2c @@ -7046,7 +7046,7 @@ class basic_json const auto N = j.m_value.string->size(); if (N <= 0x17) { - v.push_back(0x60 + N); // 1 byte for string + size + v.push_back(0x60 + static_cast(N)); // 1 byte for string + size } else if (N <= 0xff) { @@ -7082,7 +7082,7 @@ class basic_json const auto N = j.m_value.array->size(); if (N <= 0x17) { - v.push_back(0x80 + N); // 1 byte for array + size + v.push_back(0x80 + static_cast(N)); // 1 byte for array + size } else if (N <= 0xff) { @@ -7120,7 +7120,7 @@ class basic_json const auto N = j.m_value.object->size(); if (N <= 0x17) { - v.push_back(0xa0 + N); // 1 byte for object + size + v.push_back(0xa0 + static_cast(N)); // 1 byte for object + size } else if (N <= 0xff) { From 513eb3ab5f064bd24f5e24ca5ccc79c017a16367 Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Sat, 18 Feb 2017 11:00:18 +0100 Subject: [PATCH 59/80] :construction: clean up --- src/json.hpp | 71 +++++++++++++------------------- src/json.hpp.re2c | 75 +++++++++++++++------------------- test/src/unit-class_parser.cpp | 2 +- 3 files changed, 62 insertions(+), 86 deletions(-) diff --git a/src/json.hpp b/src/json.hpp index 6d7eb050..05ed2068 100644 --- a/src/json.hpp +++ b/src/json.hpp @@ -8226,15 +8226,10 @@ class basic_json struct numtostr { public: - template - numtostr(T value) + template + numtostr(NumberType value) { - x_write(value, std::is_integral()); - } - - operator const char* () const - { - return m_buf.data(); + x_write(value, std::is_integral()); } const char* c_str() const @@ -8244,17 +8239,24 @@ class basic_json private: static constexpr size_t s_capacity = 30; - std::array < char, s_capacity + 2 > m_buf{{}}; // +2 for leading '-' - // and trailing '\0' - template - void x_write(T x, std::true_type) + /// added capacity for leading '-' and trailing '\0' + std::array < char, s_capacity + 2 > m_buf{{}}; + + template + void x_write(NumberType x, /*is_integral=*/std::true_type) { - static_assert(std::numeric_limits::digits10 <= s_capacity, ""); + if (x == 0) + { + m_buf[0] = '0'; + return; + } + + static_assert(std::numeric_limits::digits10 <= s_capacity, ""); const bool is_neg = x < 0; size_t i = 0; - while (x and i < s_capacity) + while (x != 0 and i < s_capacity) { const auto digit = std::labs(static_cast(x % 10)); m_buf[i++] = static_cast('0' + digit); @@ -8263,11 +8265,6 @@ class basic_json assert(i < s_capacity); - if (i == 0) - { - m_buf[i++] = '0'; - } - if (is_neg) { m_buf[i++] = '-'; @@ -8276,18 +8273,16 @@ class basic_json std::reverse(m_buf.begin(), m_buf.begin() + i); } - template - void x_write(T x, std::false_type) + template + void x_write(NumberType x, /*is_integral=*/std::false_type) { if (x == 0) { - std::strcpy(m_buf.data(), - std::signbit(x) ? "-0.0" : "0.0"); + std::strcpy(m_buf.data(), std::signbit(x) ? "-0.0" : "0.0"); return; } - static constexpr auto d = - std::numeric_limits::digits10; + static constexpr auto d = std::numeric_limits::digits10; static_assert(d == 6 or d == 15 or d == 16 or d == 17, ""); static constexpr auto fmt = d == 6 ? "%.7g" @@ -8330,17 +8325,14 @@ class basic_json #endif // erase thousands separator - if (thousands_sep) + if (thousands_sep != '\0') { - auto end = std::remove(m_buf.begin(), - m_buf.end(), - thousands_sep); - + const auto end = std::remove(m_buf.begin(), m_buf.end(), thousands_sep); std::fill(end, m_buf.end(), '\0'); } // convert decimal point to '.' - if (decimal_point and decimal_point != '.') + if (decimal_point != '\0' and decimal_point != '.') { for (auto& c : m_buf) { @@ -8352,20 +8344,16 @@ class basic_json } } - // determine if need to apperd ".0" - auto data_end = m_buf.begin() + strlen(m_buf.data()); + // determine if need to append ".0" + const auto data_end = m_buf.begin() + strlen(m_buf.data()); const bool value_is_int_like = - std::find_if(m_buf.begin(), data_end, - [](const char c) + std::none_of(m_buf.begin(), data_end, [](const char c) { - return c == '.' - or c == 'e' - or c == 'E'; - }) - == data_end; - + return (c == '.' or c == 'e' or c == 'E'); + }); assert(data_end + 2 < m_buf.end()); + if (value_is_int_like) { strcat(m_buf.data(), ".0"); @@ -8374,7 +8362,6 @@ class basic_json }; - /*! @brief internal implementation of the serialization function diff --git a/src/json.hpp.re2c b/src/json.hpp.re2c index dc1d8207..eaee6157 100644 --- a/src/json.hpp.re2c +++ b/src/json.hpp.re2c @@ -8226,15 +8226,10 @@ class basic_json struct numtostr { public: - template - numtostr(T value) + template + numtostr(NumberType value) { - x_write(value, std::is_integral()); - } - - operator const char* () const - { - return m_buf.data(); + x_write(value, std::is_integral()); } const char* c_str() const @@ -8244,17 +8239,25 @@ class basic_json private: static constexpr size_t s_capacity = 30; - std::array < char, s_capacity + 2 > m_buf{{}}; // +2 for leading '-' - // and trailing '\0' - template - void x_write(T x, std::true_type) + /// added capacity for leading '-' and trailing '\0' + std::array < char, s_capacity + 2 > m_buf{{}}; + + template + void x_write(NumberType x, /*is_integral=*/std::true_type) { - static_assert(std::numeric_limits::digits10 <= s_capacity, ""); + if (x == 0) + { + m_buf[0] = '0'; + return; + } + + static_assert(std::numeric_limits::digits10 <= s_capacity, + "unexpected NumberType"); const bool is_neg = x < 0; size_t i = 0; - while (x and i < s_capacity) + while (x != 0 and i < s_capacity) { const auto digit = std::labs(static_cast(x % 10)); m_buf[i++] = static_cast('0' + digit); @@ -8263,11 +8266,6 @@ class basic_json assert(i < s_capacity); - if (i == 0) - { - m_buf[i++] = '0'; - } - if (is_neg) { m_buf[i++] = '-'; @@ -8276,19 +8274,18 @@ class basic_json std::reverse(m_buf.begin(), m_buf.begin() + i); } - template - void x_write(T x, std::false_type) + template + void x_write(NumberType x, /*is_integral=*/std::false_type) { if (x == 0) { - std::strcpy(m_buf.data(), - std::signbit(x) ? "-0.0" : "0.0"); + std::strcpy(m_buf.data(), std::signbit(x) ? "-0.0" : "0.0"); return; } - static constexpr auto d = - std::numeric_limits::digits10; - static_assert(d == 6 or d == 15 or d == 16 or d == 17, ""); + static constexpr auto d = std::numeric_limits::digits10; + static_assert(d == 6 or d == 15 or d == 16 or d == 17, + "unexpected NumberType"); static constexpr auto fmt = d == 6 ? "%.7g" : d == 15 ? "%.16g" @@ -8330,17 +8327,14 @@ class basic_json #endif // erase thousands separator - if (thousands_sep) + if (thousands_sep != '\0') { - auto end = std::remove(m_buf.begin(), - m_buf.end(), - thousands_sep); - + const auto end = std::remove(m_buf.begin(), m_buf.end(), thousands_sep); std::fill(end, m_buf.end(), '\0'); } // convert decimal point to '.' - if (decimal_point and decimal_point != '.') + if (decimal_point != '\0' and decimal_point != '.') { for (auto& c : m_buf) { @@ -8352,20 +8346,16 @@ class basic_json } } - // determine if need to apperd ".0" - auto data_end = m_buf.begin() + strlen(m_buf.data()); + // determine if need to append ".0" + const auto data_end = m_buf.begin() + strlen(m_buf.data()); const bool value_is_int_like = - std::find_if(m_buf.begin(), data_end, - [](const char c) + std::none_of(m_buf.begin(), data_end, [](const char c) { - return c == '.' - or c == 'e' - or c == 'E'; - }) - == data_end; - + return (c == '.' or c == 'e' or c == 'E'); + }); assert(data_end + 2 < m_buf.end()); + if (value_is_int_like) { strcat(m_buf.data(), ".0"); @@ -8374,7 +8364,6 @@ class basic_json }; - /*! @brief internal implementation of the serialization function diff --git a/test/src/unit-class_parser.cpp b/test/src/unit-class_parser.cpp index 09c5a160..27eef5ce 100644 --- a/test/src/unit-class_parser.cpp +++ b/test/src/unit-class_parser.cpp @@ -613,7 +613,7 @@ TEST_CASE("parser class") // test case to make sure the callback is properly evaluated after reading a key { - json::parser_callback_t cb = [](int depth, json::parse_event_t event, json & parsed) + json::parser_callback_t cb = [](int, json::parse_event_t event, json&) { if (event == json::parse_event_t::key) { From d1479e47bb0123d0e4def6c31b99ba14b344b009 Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Sat, 18 Feb 2017 11:01:03 +0100 Subject: [PATCH 60/80] :lipstick: added assertion message --- src/json.hpp | 6 ++++-- src/json.hpp.re2c | 4 ++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/json.hpp b/src/json.hpp index 05ed2068..7385768e 100644 --- a/src/json.hpp +++ b/src/json.hpp @@ -8251,7 +8251,8 @@ class basic_json return; } - static_assert(std::numeric_limits::digits10 <= s_capacity, ""); + static_assert(std::numeric_limits::digits10 <= s_capacity, + "unexpected NumberType"); const bool is_neg = x < 0; size_t i = 0; @@ -8283,7 +8284,8 @@ class basic_json } static constexpr auto d = std::numeric_limits::digits10; - static_assert(d == 6 or d == 15 or d == 16 or d == 17, ""); + static_assert(d == 6 or d == 15 or d == 16 or d == 17, + "unexpected NumberType"); static constexpr auto fmt = d == 6 ? "%.7g" : d == 15 ? "%.16g" diff --git a/src/json.hpp.re2c b/src/json.hpp.re2c index eaee6157..99ce5c89 100644 --- a/src/json.hpp.re2c +++ b/src/json.hpp.re2c @@ -8252,7 +8252,7 @@ class basic_json } static_assert(std::numeric_limits::digits10 <= s_capacity, - "unexpected NumberType"); + "unexpected NumberType"); const bool is_neg = x < 0; size_t i = 0; @@ -8285,7 +8285,7 @@ class basic_json static constexpr auto d = std::numeric_limits::digits10; static_assert(d == 6 or d == 15 or d == 16 or d == 17, - "unexpected NumberType"); + "unexpected NumberType"); static constexpr auto fmt = d == 6 ? "%.7g" : d == 15 ? "%.16g" From 85ce4d7b535409a8a9ac9753906b4be73ab1ce52 Mon Sep 17 00:00:00 2001 From: Tushar Maheshwari Date: Sun, 12 Feb 2017 17:16:54 +0530 Subject: [PATCH 61/80] :zap: cmake compile time reduce using cotire - Add prefix header - Include catch.hpp - Include json.hpp - Replace private with public for all json_unit files - Move `unit.cpp` to an object library - cotire issue: strip whitespace from CMAKE_INCLUDE_SYSTEM_FLAG_CXX --- CMakeLists.txt | 2 + cmake/cotire.cmake | 4008 +++++++++++++++++++++++++++++++++++++++++ test/CMakeLists.txt | 36 +- test/src/prefix.hpp | 7 + test/src/unit-udt.cpp | 9 +- 5 files changed, 4054 insertions(+), 8 deletions(-) create mode 100644 cmake/cotire.cmake create mode 100644 test/src/prefix.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index f1ccf47e..4bce30ee 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -16,6 +16,8 @@ set(JSON_CONFIGVERSION_FILENAME "${JSON_PACKAGE_NAME}ConfigVersion.cmake") set(JSON_CONFIG_DESTINATION "cmake") set(JSON_INCLUDE_DESTINATION "include/nlohmann") +set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake") + # create and configure the library target add_library(${JSON_TARGET_NAME} INTERFACE) target_include_directories(${JSON_TARGET_NAME} INTERFACE diff --git a/cmake/cotire.cmake b/cmake/cotire.cmake new file mode 100644 index 00000000..ab611007 --- /dev/null +++ b/cmake/cotire.cmake @@ -0,0 +1,4008 @@ +# - cotire (compile time reducer) +# +# See the cotire manual for usage hints. +# +#============================================================================= +# Copyright 2012-2016 Sascha Kratky +# +# Permission is hereby granted, free of charge, to any person +# obtaining a copy of this software and associated documentation +# files (the "Software"), to deal in the Software without +# restriction, including without limitation the rights to use, +# copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the +# Software is furnished to do so, subject to the following +# conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +# OTHER DEALINGS IN THE SOFTWARE. +#============================================================================= + +if(__COTIRE_INCLUDED) + return() +endif() +set(__COTIRE_INCLUDED TRUE) + +# call cmake_minimum_required, but prevent modification of the CMake policy stack in include mode +# cmake_minimum_required also sets the policy version as a side effect, which we have to avoid +if (NOT CMAKE_SCRIPT_MODE_FILE) + cmake_policy(PUSH) +endif() +cmake_minimum_required(VERSION 2.8.12) +if (NOT CMAKE_SCRIPT_MODE_FILE) + cmake_policy(POP) +endif() + +set (COTIRE_CMAKE_MODULE_FILE "${CMAKE_CURRENT_LIST_FILE}") +set (COTIRE_CMAKE_MODULE_VERSION "1.7.9") + +# activate select policies +if (POLICY CMP0025) + # Compiler id for Apple Clang is now AppleClang + cmake_policy(SET CMP0025 NEW) +endif() + +if (POLICY CMP0026) + # disallow use of the LOCATION target property + cmake_policy(SET CMP0026 NEW) +endif() + +if (POLICY CMP0038) + # targets may not link directly to themselves + cmake_policy(SET CMP0038 NEW) +endif() + +if (POLICY CMP0039) + # utility targets may not have link dependencies + cmake_policy(SET CMP0039 NEW) +endif() + +if (POLICY CMP0040) + # target in the TARGET signature of add_custom_command() must exist + cmake_policy(SET CMP0040 NEW) +endif() + +if (POLICY CMP0045) + # error on non-existent target in get_target_property + cmake_policy(SET CMP0045 NEW) +endif() + +if (POLICY CMP0046) + # error on non-existent dependency in add_dependencies + cmake_policy(SET CMP0046 NEW) +endif() + +if (POLICY CMP0049) + # do not expand variables in target source entries + cmake_policy(SET CMP0049 NEW) +endif() + +if (POLICY CMP0050) + # disallow add_custom_command SOURCE signatures + cmake_policy(SET CMP0050 NEW) +endif() + +if (POLICY CMP0051) + # include TARGET_OBJECTS expressions in a target's SOURCES property + cmake_policy(SET CMP0051 NEW) +endif() + +if (POLICY CMP0053) + # simplify variable reference and escape sequence evaluation + cmake_policy(SET CMP0053 NEW) +endif() + +if (POLICY CMP0054) + # only interpret if() arguments as variables or keywords when unquoted + cmake_policy(SET CMP0054 NEW) +endif() + +include(CMakeParseArguments) +include(ProcessorCount) + +function (cotire_get_configuration_types _configsVar) + set (_configs "") + if (CMAKE_CONFIGURATION_TYPES) + list (APPEND _configs ${CMAKE_CONFIGURATION_TYPES}) + endif() + if (CMAKE_BUILD_TYPE) + list (APPEND _configs "${CMAKE_BUILD_TYPE}") + endif() + if (_configs) + list (REMOVE_DUPLICATES _configs) + set (${_configsVar} ${_configs} PARENT_SCOPE) + else() + set (${_configsVar} "None" PARENT_SCOPE) + endif() +endfunction() + +function (cotire_get_source_file_extension _sourceFile _extVar) + # get_filename_component returns extension from first occurrence of . in file name + # this function computes the extension from last occurrence of . in file name + string (FIND "${_sourceFile}" "." _index REVERSE) + if (_index GREATER -1) + math (EXPR _index "${_index} + 1") + string (SUBSTRING "${_sourceFile}" ${_index} -1 _sourceExt) + else() + set (_sourceExt "") + endif() + set (${_extVar} "${_sourceExt}" PARENT_SCOPE) +endfunction() + +macro (cotire_check_is_path_relative_to _path _isRelativeVar) + set (${_isRelativeVar} FALSE) + if (IS_ABSOLUTE "${_path}") + foreach (_dir ${ARGN}) + file (RELATIVE_PATH _relPath "${_dir}" "${_path}") + if (NOT _relPath OR (NOT IS_ABSOLUTE "${_relPath}" AND NOT "${_relPath}" MATCHES "^\\.\\.")) + set (${_isRelativeVar} TRUE) + break() + endif() + endforeach() + endif() +endmacro() + +function (cotire_filter_language_source_files _language _target _sourceFilesVar _excludedSourceFilesVar _cotiredSourceFilesVar) + if (CMAKE_${_language}_SOURCE_FILE_EXTENSIONS) + set (_languageExtensions "${CMAKE_${_language}_SOURCE_FILE_EXTENSIONS}") + else() + set (_languageExtensions "") + endif() + if (CMAKE_${_language}_IGNORE_EXTENSIONS) + set (_ignoreExtensions "${CMAKE_${_language}_IGNORE_EXTENSIONS}") + else() + set (_ignoreExtensions "") + endif() + if (COTIRE_UNITY_SOURCE_EXCLUDE_EXTENSIONS) + set (_excludeExtensions "${COTIRE_UNITY_SOURCE_EXCLUDE_EXTENSIONS}") + else() + set (_excludeExtensions "") + endif() + if (COTIRE_DEBUG AND _languageExtensions) + message (STATUS "${_language} source file extensions: ${_languageExtensions}") + endif() + if (COTIRE_DEBUG AND _ignoreExtensions) + message (STATUS "${_language} ignore extensions: ${_ignoreExtensions}") + endif() + if (COTIRE_DEBUG AND _excludeExtensions) + message (STATUS "${_language} exclude extensions: ${_excludeExtensions}") + endif() + if (CMAKE_VERSION VERSION_LESS "3.1.0") + set (_allSourceFiles ${ARGN}) + else() + # as of CMake 3.1 target sources may contain generator expressions + # since we cannot obtain required property information about source files added + # through generator expressions at configure time, we filter them out + string (GENEX_STRIP "${ARGN}" _allSourceFiles) + endif() + set (_filteredSourceFiles "") + set (_excludedSourceFiles "") + foreach (_sourceFile ${_allSourceFiles}) + get_source_file_property(_sourceIsHeaderOnly "${_sourceFile}" HEADER_FILE_ONLY) + get_source_file_property(_sourceIsExternal "${_sourceFile}" EXTERNAL_OBJECT) + get_source_file_property(_sourceIsSymbolic "${_sourceFile}" SYMBOLIC) + if (NOT _sourceIsHeaderOnly AND NOT _sourceIsExternal AND NOT _sourceIsSymbolic) + cotire_get_source_file_extension("${_sourceFile}" _sourceExt) + if (_sourceExt) + list (FIND _ignoreExtensions "${_sourceExt}" _ignoreIndex) + if (_ignoreIndex LESS 0) + list (FIND _excludeExtensions "${_sourceExt}" _excludeIndex) + if (_excludeIndex GREATER -1) + list (APPEND _excludedSourceFiles "${_sourceFile}") + else() + list (FIND _languageExtensions "${_sourceExt}" _sourceIndex) + if (_sourceIndex GREATER -1) + # consider source file unless it is excluded explicitly + get_source_file_property(_sourceIsExcluded "${_sourceFile}" COTIRE_EXCLUDED) + if (_sourceIsExcluded) + list (APPEND _excludedSourceFiles "${_sourceFile}") + else() + list (APPEND _filteredSourceFiles "${_sourceFile}") + endif() + else() + get_source_file_property(_sourceLanguage "${_sourceFile}" LANGUAGE) + if ("${_sourceLanguage}" STREQUAL "${_language}") + # add to excluded sources, if file is not ignored and has correct language without having the correct extension + list (APPEND _excludedSourceFiles "${_sourceFile}") + endif() + endif() + endif() + endif() + endif() + endif() + endforeach() + # separate filtered source files from already cotired ones + # the COTIRE_TARGET property of a source file may be set while a target is being processed by cotire + set (_sourceFiles "") + set (_cotiredSourceFiles "") + foreach (_sourceFile ${_filteredSourceFiles}) + get_source_file_property(_sourceIsCotired "${_sourceFile}" COTIRE_TARGET) + if (_sourceIsCotired) + list (APPEND _cotiredSourceFiles "${_sourceFile}") + else() + get_source_file_property(_sourceCompileFlags "${_sourceFile}" COMPILE_FLAGS) + if (_sourceCompileFlags) + # add to excluded sources, if file has custom compile flags + list (APPEND _excludedSourceFiles "${_sourceFile}") + else() + list (APPEND _sourceFiles "${_sourceFile}") + endif() + endif() + endforeach() + if (COTIRE_DEBUG) + if (_sourceFiles) + message (STATUS "Filtered ${_target} ${_language} sources: ${_sourceFiles}") + endif() + if (_excludedSourceFiles) + message (STATUS "Excluded ${_target} ${_language} sources: ${_excludedSourceFiles}") + endif() + if (_cotiredSourceFiles) + message (STATUS "Cotired ${_target} ${_language} sources: ${_cotiredSourceFiles}") + endif() + endif() + set (${_sourceFilesVar} ${_sourceFiles} PARENT_SCOPE) + set (${_excludedSourceFilesVar} ${_excludedSourceFiles} PARENT_SCOPE) + set (${_cotiredSourceFilesVar} ${_cotiredSourceFiles} PARENT_SCOPE) +endfunction() + +function (cotire_get_objects_with_property_on _filteredObjectsVar _property _type) + set (_filteredObjects "") + foreach (_object ${ARGN}) + get_property(_isSet ${_type} "${_object}" PROPERTY ${_property} SET) + if (_isSet) + get_property(_propertyValue ${_type} "${_object}" PROPERTY ${_property}) + if (_propertyValue) + list (APPEND _filteredObjects "${_object}") + endif() + endif() + endforeach() + set (${_filteredObjectsVar} ${_filteredObjects} PARENT_SCOPE) +endfunction() + +function (cotire_get_objects_with_property_off _filteredObjectsVar _property _type) + set (_filteredObjects "") + foreach (_object ${ARGN}) + get_property(_isSet ${_type} "${_object}" PROPERTY ${_property} SET) + if (_isSet) + get_property(_propertyValue ${_type} "${_object}" PROPERTY ${_property}) + if (NOT _propertyValue) + list (APPEND _filteredObjects "${_object}") + endif() + endif() + endforeach() + set (${_filteredObjectsVar} ${_filteredObjects} PARENT_SCOPE) +endfunction() + +function (cotire_get_source_file_property_values _valuesVar _property) + set (_values "") + foreach (_sourceFile ${ARGN}) + get_source_file_property(_propertyValue "${_sourceFile}" ${_property}) + if (_propertyValue) + list (APPEND _values "${_propertyValue}") + endif() + endforeach() + set (${_valuesVar} ${_values} PARENT_SCOPE) +endfunction() + +function (cotire_resolve_config_properites _configurations _propertiesVar) + set (_properties "") + foreach (_property ${ARGN}) + if ("${_property}" MATCHES "") + foreach (_config ${_configurations}) + string (TOUPPER "${_config}" _upperConfig) + string (REPLACE "" "${_upperConfig}" _configProperty "${_property}") + list (APPEND _properties ${_configProperty}) + endforeach() + else() + list (APPEND _properties ${_property}) + endif() + endforeach() + set (${_propertiesVar} ${_properties} PARENT_SCOPE) +endfunction() + +function (cotire_copy_set_properites _configurations _type _source _target) + cotire_resolve_config_properites("${_configurations}" _properties ${ARGN}) + foreach (_property ${_properties}) + get_property(_isSet ${_type} ${_source} PROPERTY ${_property} SET) + if (_isSet) + get_property(_propertyValue ${_type} ${_source} PROPERTY ${_property}) + set_property(${_type} ${_target} PROPERTY ${_property} "${_propertyValue}") + endif() + endforeach() +endfunction() + +function (cotire_get_target_usage_requirements _target _targetRequirementsVar) + set (_targetRequirements "") + get_target_property(_librariesToProcess ${_target} LINK_LIBRARIES) + while (_librariesToProcess) + # remove from head + list (GET _librariesToProcess 0 _library) + list (REMOVE_AT _librariesToProcess 0) + if (TARGET ${_library}) + list (FIND _targetRequirements ${_library} _index) + if (_index LESS 0) + list (APPEND _targetRequirements ${_library}) + # BFS traversal of transitive libraries + get_target_property(_libraries ${_library} INTERFACE_LINK_LIBRARIES) + if (_libraries) + list (APPEND _librariesToProcess ${_libraries}) + list (REMOVE_DUPLICATES _librariesToProcess) + endif() + endif() + endif() + endwhile() + set (${_targetRequirementsVar} ${_targetRequirements} PARENT_SCOPE) +endfunction() + +function (cotire_filter_compile_flags _language _flagFilter _matchedOptionsVar _unmatchedOptionsVar) + if (WIN32 AND CMAKE_${_language}_COMPILER_ID MATCHES "MSVC|Intel") + set (_flagPrefix "[/-]") + else() + set (_flagPrefix "--?") + endif() + set (_optionFlag "") + set (_matchedOptions "") + set (_unmatchedOptions "") + foreach (_compileFlag ${ARGN}) + if (_compileFlag) + if (_optionFlag AND NOT "${_compileFlag}" MATCHES "^${_flagPrefix}") + # option with separate argument + list (APPEND _matchedOptions "${_compileFlag}") + set (_optionFlag "") + elseif ("${_compileFlag}" MATCHES "^(${_flagPrefix})(${_flagFilter})$") + # remember option + set (_optionFlag "${CMAKE_MATCH_2}") + elseif ("${_compileFlag}" MATCHES "^(${_flagPrefix})(${_flagFilter})(.+)$") + # option with joined argument + list (APPEND _matchedOptions "${CMAKE_MATCH_3}") + set (_optionFlag "") + else() + # flush remembered option + if (_optionFlag) + list (APPEND _matchedOptions "${_optionFlag}") + set (_optionFlag "") + endif() + # add to unfiltered options + list (APPEND _unmatchedOptions "${_compileFlag}") + endif() + endif() + endforeach() + if (_optionFlag) + list (APPEND _matchedOptions "${_optionFlag}") + endif() + if (COTIRE_DEBUG AND _matchedOptions) + message (STATUS "Filter ${_flagFilter} matched: ${_matchedOptions}") + endif() + if (COTIRE_DEBUG AND _unmatchedOptions) + message (STATUS "Filter ${_flagFilter} unmatched: ${_unmatchedOptions}") + endif() + set (${_matchedOptionsVar} ${_matchedOptions} PARENT_SCOPE) + set (${_unmatchedOptionsVar} ${_unmatchedOptions} PARENT_SCOPE) +endfunction() + +function (cotire_is_target_supported _target _isSupportedVar) + if (NOT TARGET "${_target}") + set (${_isSupportedVar} FALSE PARENT_SCOPE) + return() + endif() + get_target_property(_imported ${_target} IMPORTED) + if (_imported) + set (${_isSupportedVar} FALSE PARENT_SCOPE) + return() + endif() + get_target_property(_targetType ${_target} TYPE) + if (NOT _targetType MATCHES "EXECUTABLE|(STATIC|SHARED|MODULE|OBJECT)_LIBRARY") + set (${_isSupportedVar} FALSE PARENT_SCOPE) + return() + endif() + set (${_isSupportedVar} TRUE PARENT_SCOPE) +endfunction() + +function (cotire_get_target_compile_flags _config _language _target _flagsVar) + string (TOUPPER "${_config}" _upperConfig) + # collect options from CMake language variables + set (_compileFlags "") + if (CMAKE_${_language}_FLAGS) + set (_compileFlags "${_compileFlags} ${CMAKE_${_language}_FLAGS}") + endif() + if (CMAKE_${_language}_FLAGS_${_upperConfig}) + set (_compileFlags "${_compileFlags} ${CMAKE_${_language}_FLAGS_${_upperConfig}}") + endif() + if (_target) + # add target compile flags + get_target_property(_targetflags ${_target} COMPILE_FLAGS) + if (_targetflags) + set (_compileFlags "${_compileFlags} ${_targetflags}") + endif() + endif() + if (UNIX) + separate_arguments(_compileFlags UNIX_COMMAND "${_compileFlags}") + elseif(WIN32) + separate_arguments(_compileFlags WINDOWS_COMMAND "${_compileFlags}") + else() + separate_arguments(_compileFlags) + endif() + # target compile options + if (_target) + get_target_property(_targetOptions ${_target} COMPILE_OPTIONS) + if (_targetOptions) + list (APPEND _compileFlags ${_targetOptions}) + endif() + endif() + # interface compile options from linked library targets + if (_target) + set (_linkedTargets "") + cotire_get_target_usage_requirements(${_target} _linkedTargets) + foreach (_linkedTarget ${_linkedTargets}) + get_target_property(_targetOptions ${_linkedTarget} INTERFACE_COMPILE_OPTIONS) + if (_targetOptions) + list (APPEND _compileFlags ${_targetOptions}) + endif() + endforeach() + endif() + # handle language standard properties + if (CMAKE_${_language}_STANDARD_DEFAULT) + # used compiler supports language standard levels + if (_target) + get_target_property(_targetLanguageStandard ${_target} ${_language}_STANDARD) + if (_targetLanguageStandard) + set (_type "EXTENSION") + get_property(_isSet TARGET ${_target} PROPERTY ${_language}_EXTENSIONS SET) + if (_isSet) + get_target_property(_targetUseLanguageExtensions ${_target} ${_language}_EXTENSIONS) + if (NOT _targetUseLanguageExtensions) + set (_type "STANDARD") + endif() + endif() + if (CMAKE_${_language}${_targetLanguageStandard}_${_type}_COMPILE_OPTION) + list (APPEND _compileFlags "${CMAKE_${_language}${_targetLanguageStandard}_${_type}_COMPILE_OPTION}") + endif() + endif() + endif() + endif() + # handle the POSITION_INDEPENDENT_CODE target property + if (_target) + get_target_property(_targetPIC ${_target} POSITION_INDEPENDENT_CODE) + if (_targetPIC) + get_target_property(_targetType ${_target} TYPE) + if (_targetType STREQUAL "EXECUTABLE" AND CMAKE_${_language}_COMPILE_OPTIONS_PIE) + list (APPEND _compileFlags "${CMAKE_${_language}_COMPILE_OPTIONS_PIE}") + elseif (CMAKE_${_language}_COMPILE_OPTIONS_PIC) + list (APPEND _compileFlags "${CMAKE_${_language}_COMPILE_OPTIONS_PIC}") + endif() + endif() + endif() + # handle visibility target properties + if (_target) + get_target_property(_targetVisibility ${_target} ${_language}_VISIBILITY_PRESET) + if (_targetVisibility AND CMAKE_${_language}_COMPILE_OPTIONS_VISIBILITY) + list (APPEND _compileFlags "${CMAKE_${_language}_COMPILE_OPTIONS_VISIBILITY}${_targetVisibility}") + endif() + get_target_property(_targetVisibilityInlines ${_target} VISIBILITY_INLINES_HIDDEN) + if (_targetVisibilityInlines AND CMAKE_${_language}_COMPILE_OPTIONS_VISIBILITY_INLINES_HIDDEN) + list (APPEND _compileFlags "${CMAKE_${_language}_COMPILE_OPTIONS_VISIBILITY_INLINES_HIDDEN}") + endif() + endif() + # platform specific flags + if (APPLE) + get_target_property(_architectures ${_target} OSX_ARCHITECTURES_${_upperConfig}) + if (NOT _architectures) + get_target_property(_architectures ${_target} OSX_ARCHITECTURES) + endif() + if (_architectures) + foreach (_arch ${_architectures}) + list (APPEND _compileFlags "-arch" "${_arch}") + endforeach() + endif() + if (CMAKE_OSX_SYSROOT) + if (CMAKE_${_language}_SYSROOT_FLAG) + list (APPEND _compileFlags "${CMAKE_${_language}_SYSROOT_FLAG}" "${CMAKE_OSX_SYSROOT}") + else() + list (APPEND _compileFlags "-isysroot" "${CMAKE_OSX_SYSROOT}") + endif() + endif() + if (CMAKE_OSX_DEPLOYMENT_TARGET) + if (CMAKE_${_language}_OSX_DEPLOYMENT_TARGET_FLAG) + list (APPEND _compileFlags "${CMAKE_${_language}_OSX_DEPLOYMENT_TARGET_FLAG}${CMAKE_OSX_DEPLOYMENT_TARGET}") + else() + list (APPEND _compileFlags "-mmacosx-version-min=${CMAKE_OSX_DEPLOYMENT_TARGET}") + endif() + endif() + endif() + if (COTIRE_DEBUG AND _compileFlags) + message (STATUS "Target ${_target} compile flags: ${_compileFlags}") + endif() + set (${_flagsVar} ${_compileFlags} PARENT_SCOPE) +endfunction() + +function (cotire_get_target_include_directories _config _language _target _includeDirsVar _systemIncludeDirsVar) + set (_includeDirs "") + set (_systemIncludeDirs "") + # default include dirs + if (CMAKE_INCLUDE_CURRENT_DIR) + list (APPEND _includeDirs "${CMAKE_CURRENT_BINARY_DIR}") + list (APPEND _includeDirs "${CMAKE_CURRENT_SOURCE_DIR}") + endif() + set (_targetFlags "") + cotire_get_target_compile_flags("${_config}" "${_language}" "${_target}" _targetFlags) + # parse additional include directories from target compile flags + if (CMAKE_INCLUDE_FLAG_${_language}) + string (STRIP "${CMAKE_INCLUDE_FLAG_${_language}}" _includeFlag) + string (REGEX REPLACE "^[-/]+" "" _includeFlag "${_includeFlag}") + if (_includeFlag) + set (_dirs "") + cotire_filter_compile_flags("${_language}" "${_includeFlag}" _dirs _ignore ${_targetFlags}) + if (_dirs) + list (APPEND _includeDirs ${_dirs}) + endif() + endif() + endif() + # parse additional system include directories from target compile flags + if (CMAKE_INCLUDE_SYSTEM_FLAG_${_language}) + string (STRIP "${CMAKE_INCLUDE_SYSTEM_FLAG_${_language}}" _includeFlag) + string (REGEX REPLACE "^[-/]+" "" _includeFlag "${_includeFlag}") + if (_includeFlag) + set (_dirs "") + cotire_filter_compile_flags("${_language}" "${_includeFlag}" _dirs _ignore ${_targetFlags}) + if (_dirs) + list (APPEND _systemIncludeDirs ${_dirs}) + endif() + endif() + endif() + # target include directories + get_directory_property(_dirs DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" INCLUDE_DIRECTORIES) + if (_target) + get_target_property(_targetDirs ${_target} INCLUDE_DIRECTORIES) + if (_targetDirs) + list (APPEND _dirs ${_targetDirs}) + endif() + get_target_property(_targetDirs ${_target} INTERFACE_SYSTEM_INCLUDE_DIRECTORIES) + if (_targetDirs) + list (APPEND _systemIncludeDirs ${_targetDirs}) + endif() + endif() + # interface include directories from linked library targets + if (_target) + set (_linkedTargets "") + cotire_get_target_usage_requirements(${_target} _linkedTargets) + foreach (_linkedTarget ${_linkedTargets}) + get_target_property(_linkedTargetType ${_linkedTarget} TYPE) + if (CMAKE_INCLUDE_CURRENT_DIR_IN_INTERFACE AND NOT CMAKE_VERSION VERSION_LESS "3.4.0" AND + _linkedTargetType MATCHES "(STATIC|SHARED|MODULE|OBJECT)_LIBRARY") + # CMAKE_INCLUDE_CURRENT_DIR_IN_INTERFACE refers to CMAKE_CURRENT_BINARY_DIR and CMAKE_CURRENT_SOURCE_DIR + # at the time, when the target was created. These correspond to the target properties BINARY_DIR and SOURCE_DIR + # which are only available with CMake 3.4 or later. + get_target_property(_targetDirs ${_linkedTarget} BINARY_DIR) + if (_targetDirs) + list (APPEND _dirs ${_targetDirs}) + endif() + get_target_property(_targetDirs ${_linkedTarget} SOURCE_DIR) + if (_targetDirs) + list (APPEND _dirs ${_targetDirs}) + endif() + endif() + get_target_property(_targetDirs ${_linkedTarget} INTERFACE_INCLUDE_DIRECTORIES) + if (_targetDirs) + list (APPEND _dirs ${_targetDirs}) + endif() + get_target_property(_targetDirs ${_linkedTarget} INTERFACE_SYSTEM_INCLUDE_DIRECTORIES) + if (_targetDirs) + list (APPEND _systemIncludeDirs ${_targetDirs}) + endif() + endforeach() + endif() + if (dirs) + list (REMOVE_DUPLICATES _dirs) + endif() + list (LENGTH _includeDirs _projectInsertIndex) + foreach (_dir ${_dirs}) + if (CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE) + cotire_check_is_path_relative_to("${_dir}" _isRelative "${CMAKE_SOURCE_DIR}" "${CMAKE_BINARY_DIR}") + if (_isRelative) + list (LENGTH _includeDirs _len) + if (_len EQUAL _projectInsertIndex) + list (APPEND _includeDirs "${_dir}") + else() + list (INSERT _includeDirs _projectInsertIndex "${_dir}") + endif() + math (EXPR _projectInsertIndex "${_projectInsertIndex} + 1") + else() + list (APPEND _includeDirs "${_dir}") + endif() + else() + list (APPEND _includeDirs "${_dir}") + endif() + endforeach() + list (REMOVE_DUPLICATES _includeDirs) + list (REMOVE_DUPLICATES _systemIncludeDirs) + if (CMAKE_${_language}_IMPLICIT_INCLUDE_DIRECTORIES) + list (REMOVE_ITEM _includeDirs ${CMAKE_${_language}_IMPLICIT_INCLUDE_DIRECTORIES}) + endif() + if (WIN32) + # convert Windows paths in include directories to CMake paths + if (_includeDirs) + set (_paths "") + foreach (_dir ${_includeDirs}) + file (TO_CMAKE_PATH "${_dir}" _path) + list (APPEND _paths "${_path}") + endforeach() + set (_includeDirs ${_paths}) + endif() + if (_systemIncludeDirs) + set (_paths "") + foreach (_dir ${_systemIncludeDirs}) + file (TO_CMAKE_PATH "${_dir}" _path) + list (APPEND _paths "${_path}") + endforeach() + set (_systemIncludeDirs ${_paths}) + endif() + endif() + if (COTIRE_DEBUG AND _includeDirs) + message (STATUS "Target ${_target} include dirs: ${_includeDirs}") + endif() + set (${_includeDirsVar} ${_includeDirs} PARENT_SCOPE) + if (COTIRE_DEBUG AND _systemIncludeDirs) + message (STATUS "Target ${_target} system include dirs: ${_systemIncludeDirs}") + endif() + set (${_systemIncludeDirsVar} ${_systemIncludeDirs} PARENT_SCOPE) +endfunction() + +function (cotire_get_target_export_symbol _target _exportSymbolVar) + set (_exportSymbol "") + get_target_property(_targetType ${_target} TYPE) + get_target_property(_enableExports ${_target} ENABLE_EXPORTS) + if (_targetType MATCHES "(SHARED|MODULE)_LIBRARY" OR + (_targetType STREQUAL "EXECUTABLE" AND _enableExports)) + get_target_property(_exportSymbol ${_target} DEFINE_SYMBOL) + if (NOT _exportSymbol) + set (_exportSymbol "${_target}_EXPORTS") + endif() + string (MAKE_C_IDENTIFIER "${_exportSymbol}" _exportSymbol) + endif() + set (${_exportSymbolVar} ${_exportSymbol} PARENT_SCOPE) +endfunction() + +function (cotire_get_target_compile_definitions _config _language _target _definitionsVar) + string (TOUPPER "${_config}" _upperConfig) + set (_configDefinitions "") + # CMAKE_INTDIR for multi-configuration build systems + if (NOT "${CMAKE_CFG_INTDIR}" STREQUAL ".") + list (APPEND _configDefinitions "CMAKE_INTDIR=\"${_config}\"") + endif() + # target export define symbol + cotire_get_target_export_symbol("${_target}" _defineSymbol) + if (_defineSymbol) + list (APPEND _configDefinitions "${_defineSymbol}") + endif() + # directory compile definitions + get_directory_property(_definitions DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" COMPILE_DEFINITIONS) + if (_definitions) + list (APPEND _configDefinitions ${_definitions}) + endif() + get_directory_property(_definitions DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" COMPILE_DEFINITIONS_${_upperConfig}) + if (_definitions) + list (APPEND _configDefinitions ${_definitions}) + endif() + # target compile definitions + get_target_property(_definitions ${_target} COMPILE_DEFINITIONS) + if (_definitions) + list (APPEND _configDefinitions ${_definitions}) + endif() + get_target_property(_definitions ${_target} COMPILE_DEFINITIONS_${_upperConfig}) + if (_definitions) + list (APPEND _configDefinitions ${_definitions}) + endif() + # interface compile definitions from linked library targets + set (_linkedTargets "") + cotire_get_target_usage_requirements(${_target} _linkedTargets) + foreach (_linkedTarget ${_linkedTargets}) + get_target_property(_definitions ${_linkedTarget} INTERFACE_COMPILE_DEFINITIONS) + if (_definitions) + list (APPEND _configDefinitions ${_definitions}) + endif() + endforeach() + # parse additional compile definitions from target compile flags + # and don't look at directory compile definitions, which we already handled + set (_targetFlags "") + cotire_get_target_compile_flags("${_config}" "${_language}" "${_target}" _targetFlags) + cotire_filter_compile_flags("${_language}" "D" _definitions _ignore ${_targetFlags}) + if (_definitions) + list (APPEND _configDefinitions ${_definitions}) + endif() + list (REMOVE_DUPLICATES _configDefinitions) + if (COTIRE_DEBUG AND _configDefinitions) + message (STATUS "Target ${_target} compile definitions: ${_configDefinitions}") + endif() + set (${_definitionsVar} ${_configDefinitions} PARENT_SCOPE) +endfunction() + +function (cotire_get_target_compiler_flags _config _language _target _compilerFlagsVar) + # parse target compile flags omitting compile definitions and include directives + set (_targetFlags "") + cotire_get_target_compile_flags("${_config}" "${_language}" "${_target}" _targetFlags) + set (_flagFilter "D") + if (CMAKE_INCLUDE_FLAG_${_language}) + string (STRIP "${CMAKE_INCLUDE_FLAG_${_language}}" _includeFlag) + string (REGEX REPLACE "^[-/]+" "" _includeFlag "${_includeFlag}") + if (_includeFlag) + set (_flagFilter "${_flagFilter}|${_includeFlag}") + endif() + endif() + if (CMAKE_INCLUDE_SYSTEM_FLAG_${_language}) + string (STRIP "${CMAKE_INCLUDE_SYSTEM_FLAG_${_language}}" _includeFlag) + string (REGEX REPLACE "^[-/]+" "" _includeFlag "${_includeFlag}") + if (_includeFlag) + set (_flagFilter "${_flagFilter}|${_includeFlag}") + endif() + endif() + set (_compilerFlags "") + cotire_filter_compile_flags("${_language}" "${_flagFilter}" _ignore _compilerFlags ${_targetFlags}) + if (COTIRE_DEBUG AND _compilerFlags) + message (STATUS "Target ${_target} compiler flags: ${_compilerFlags}") + endif() + set (${_compilerFlagsVar} ${_compilerFlags} PARENT_SCOPE) +endfunction() + +function (cotire_add_sys_root_paths _pathsVar) + if (APPLE) + if (CMAKE_OSX_SYSROOT AND CMAKE_${_language}_HAS_ISYSROOT) + foreach (_path IN LISTS ${_pathsVar}) + if (IS_ABSOLUTE "${_path}") + get_filename_component(_path "${CMAKE_OSX_SYSROOT}/${_path}" ABSOLUTE) + if (EXISTS "${_path}") + list (APPEND ${_pathsVar} "${_path}") + endif() + endif() + endforeach() + endif() + endif() + set (${_pathsVar} ${${_pathsVar}} PARENT_SCOPE) +endfunction() + +function (cotire_get_source_extra_properties _sourceFile _pattern _resultVar) + set (_extraProperties ${ARGN}) + set (_result "") + if (_extraProperties) + list (FIND _extraProperties "${_sourceFile}" _index) + if (_index GREATER -1) + math (EXPR _index "${_index} + 1") + list (LENGTH _extraProperties _len) + math (EXPR _len "${_len} - 1") + foreach (_index RANGE ${_index} ${_len}) + list (GET _extraProperties ${_index} _value) + if (_value MATCHES "${_pattern}") + list (APPEND _result "${_value}") + else() + break() + endif() + endforeach() + endif() + endif() + set (${_resultVar} ${_result} PARENT_SCOPE) +endfunction() + +function (cotire_get_source_compile_definitions _config _language _sourceFile _definitionsVar) + set (_compileDefinitions "") + if (NOT CMAKE_SCRIPT_MODE_FILE) + string (TOUPPER "${_config}" _upperConfig) + get_source_file_property(_definitions "${_sourceFile}" COMPILE_DEFINITIONS) + if (_definitions) + list (APPEND _compileDefinitions ${_definitions}) + endif() + get_source_file_property(_definitions "${_sourceFile}" COMPILE_DEFINITIONS_${_upperConfig}) + if (_definitions) + list (APPEND _compileDefinitions ${_definitions}) + endif() + endif() + cotire_get_source_extra_properties("${_sourceFile}" "^[a-zA-Z0-9_]+(=.*)?$" _definitions ${ARGN}) + if (_definitions) + list (APPEND _compileDefinitions ${_definitions}) + endif() + if (COTIRE_DEBUG AND _compileDefinitions) + message (STATUS "Source ${_sourceFile} compile definitions: ${_compileDefinitions}") + endif() + set (${_definitionsVar} ${_compileDefinitions} PARENT_SCOPE) +endfunction() + +function (cotire_get_source_files_compile_definitions _config _language _definitionsVar) + set (_configDefinitions "") + foreach (_sourceFile ${ARGN}) + cotire_get_source_compile_definitions("${_config}" "${_language}" "${_sourceFile}" _sourceDefinitions) + if (_sourceDefinitions) + list (APPEND _configDefinitions "${_sourceFile}" ${_sourceDefinitions} "-") + endif() + endforeach() + set (${_definitionsVar} ${_configDefinitions} PARENT_SCOPE) +endfunction() + +function (cotire_get_source_undefs _sourceFile _property _sourceUndefsVar) + set (_sourceUndefs "") + if (NOT CMAKE_SCRIPT_MODE_FILE) + get_source_file_property(_undefs "${_sourceFile}" ${_property}) + if (_undefs) + list (APPEND _sourceUndefs ${_undefs}) + endif() + endif() + cotire_get_source_extra_properties("${_sourceFile}" "^[a-zA-Z0-9_]+$" _undefs ${ARGN}) + if (_undefs) + list (APPEND _sourceUndefs ${_undefs}) + endif() + if (COTIRE_DEBUG AND _sourceUndefs) + message (STATUS "Source ${_sourceFile} ${_property} undefs: ${_sourceUndefs}") + endif() + set (${_sourceUndefsVar} ${_sourceUndefs} PARENT_SCOPE) +endfunction() + +function (cotire_get_source_files_undefs _property _sourceUndefsVar) + set (_sourceUndefs "") + foreach (_sourceFile ${ARGN}) + cotire_get_source_undefs("${_sourceFile}" ${_property} _undefs) + if (_undefs) + list (APPEND _sourceUndefs "${_sourceFile}" ${_undefs} "-") + endif() + endforeach() + set (${_sourceUndefsVar} ${_sourceUndefs} PARENT_SCOPE) +endfunction() + +macro (cotire_set_cmd_to_prologue _cmdVar) + set (${_cmdVar} "${CMAKE_COMMAND}") + if (COTIRE_DEBUG) + list (APPEND ${_cmdVar} "--warn-uninitialized") + endif() + list (APPEND ${_cmdVar} "-DCOTIRE_BUILD_TYPE:STRING=$") + if (COTIRE_VERBOSE) + list (APPEND ${_cmdVar} "-DCOTIRE_VERBOSE:BOOL=ON") + elseif("${CMAKE_GENERATOR}" MATCHES "Makefiles") + list (APPEND ${_cmdVar} "-DCOTIRE_VERBOSE:BOOL=$(VERBOSE)") + endif() +endmacro() + +function (cotire_init_compile_cmd _cmdVar _language _compilerLauncher _compilerExe _compilerArg1) + if (NOT _compilerLauncher) + set (_compilerLauncher ${CMAKE_${_language}_COMPILER_LAUNCHER}) + endif() + if (NOT _compilerExe) + set (_compilerExe "${CMAKE_${_language}_COMPILER}") + endif() + if (NOT _compilerArg1) + set (_compilerArg1 ${CMAKE_${_language}_COMPILER_ARG1}) + endif() + string (STRIP "${_compilerArg1}" _compilerArg1) + if ("${CMAKE_GENERATOR}" MATCHES "Make|Ninja") + # compiler launcher is only supported for Makefile and Ninja + set (${_cmdVar} ${_compilerLauncher} "${_compilerExe}" ${_compilerArg1} PARENT_SCOPE) + else() + set (${_cmdVar} "${_compilerExe}" ${_compilerArg1} PARENT_SCOPE) + endif() +endfunction() + +macro (cotire_add_definitions_to_cmd _cmdVar _language) + foreach (_definition ${ARGN}) + if (WIN32 AND CMAKE_${_language}_COMPILER_ID MATCHES "MSVC|Intel") + list (APPEND ${_cmdVar} "/D${_definition}") + else() + list (APPEND ${_cmdVar} "-D${_definition}") + endif() + endforeach() +endmacro() + +function (cotire_add_includes_to_cmd _cmdVar _language _includesVar _systemIncludesVar) + set (_includeDirs ${${_includesVar}} ${${_systemIncludesVar}}) + if (_includeDirs) + list (REMOVE_DUPLICATES _includeDirs) + foreach (_include ${_includeDirs}) + if (WIN32 AND CMAKE_${_language}_COMPILER_ID MATCHES "MSVC|Intel") + file (TO_NATIVE_PATH "${_include}" _include) + list (APPEND ${_cmdVar} "${CMAKE_INCLUDE_FLAG_${_language}}${CMAKE_INCLUDE_FLAG_${_language}_SEP}${_include}") + else() + set (_index -1) + if ("${CMAKE_INCLUDE_SYSTEM_FLAG_${_language}}" MATCHES ".+") + list (FIND ${_systemIncludesVar} "${_include}" _index) + endif() + if (_index GREATER -1) + list (APPEND ${_cmdVar} "${CMAKE_INCLUDE_SYSTEM_FLAG_${_language}}${_include}") + else() + list (APPEND ${_cmdVar} "${CMAKE_INCLUDE_FLAG_${_language}}${CMAKE_INCLUDE_FLAG_${_language}_SEP}${_include}") + endif() + endif() + endforeach() + endif() + set (${_cmdVar} ${${_cmdVar}} PARENT_SCOPE) +endfunction() + +function (cotire_add_frameworks_to_cmd _cmdVar _language _includesVar _systemIncludesVar) + if (APPLE) + set (_frameworkDirs "") + foreach (_include ${${_includesVar}}) + if (IS_ABSOLUTE "${_include}" AND _include MATCHES "\\.framework$") + get_filename_component(_frameworkDir "${_include}" DIRECTORY) + list (APPEND _frameworkDirs "${_frameworkDir}") + endif() + endforeach() + set (_systemFrameworkDirs "") + foreach (_include ${${_systemIncludesVar}}) + if (IS_ABSOLUTE "${_include}" AND _include MATCHES "\\.framework$") + get_filename_component(_frameworkDir "${_include}" DIRECTORY) + list (APPEND _systemFrameworkDirs "${_frameworkDir}") + endif() + endforeach() + if (_systemFrameworkDirs) + list (APPEND _frameworkDirs ${_systemFrameworkDirs}) + endif() + if (_frameworkDirs) + list (REMOVE_DUPLICATES _frameworkDirs) + foreach (_frameworkDir ${_frameworkDirs}) + set (_index -1) + if ("${CMAKE_${_language}_SYSTEM_FRAMEWORK_SEARCH_FLAG}" MATCHES ".+") + list (FIND _systemFrameworkDirs "${_frameworkDir}" _index) + endif() + if (_index GREATER -1) + list (APPEND ${_cmdVar} "${CMAKE_${_language}_SYSTEM_FRAMEWORK_SEARCH_FLAG}${_frameworkDir}") + else() + list (APPEND ${_cmdVar} "${CMAKE_${_language}_FRAMEWORK_SEARCH_FLAG}${_frameworkDir}") + endif() + endforeach() + endif() + endif() + set (${_cmdVar} ${${_cmdVar}} PARENT_SCOPE) +endfunction() + +macro (cotire_add_compile_flags_to_cmd _cmdVar) + foreach (_flag ${ARGN}) + list (APPEND ${_cmdVar} "${_flag}") + endforeach() +endmacro() + +function (cotire_check_file_up_to_date _fileIsUpToDateVar _file) + if (EXISTS "${_file}") + set (_triggerFile "") + foreach (_dependencyFile ${ARGN}) + if (EXISTS "${_dependencyFile}") + # IS_NEWER_THAN returns TRUE if both files have the same timestamp + # thus we do the comparison in both directions to exclude ties + if ("${_dependencyFile}" IS_NEWER_THAN "${_file}" AND + NOT "${_file}" IS_NEWER_THAN "${_dependencyFile}") + set (_triggerFile "${_dependencyFile}") + break() + endif() + endif() + endforeach() + if (_triggerFile) + if (COTIRE_VERBOSE) + get_filename_component(_fileName "${_file}" NAME) + message (STATUS "${_fileName} update triggered by ${_triggerFile} change.") + endif() + set (${_fileIsUpToDateVar} FALSE PARENT_SCOPE) + else() + if (COTIRE_VERBOSE) + get_filename_component(_fileName "${_file}" NAME) + message (STATUS "${_fileName} is up-to-date.") + endif() + set (${_fileIsUpToDateVar} TRUE PARENT_SCOPE) + endif() + else() + if (COTIRE_VERBOSE) + get_filename_component(_fileName "${_file}" NAME) + message (STATUS "${_fileName} does not exist yet.") + endif() + set (${_fileIsUpToDateVar} FALSE PARENT_SCOPE) + endif() +endfunction() + +macro (cotire_find_closest_relative_path _headerFile _includeDirs _relPathVar) + set (${_relPathVar} "") + foreach (_includeDir ${_includeDirs}) + if (IS_DIRECTORY "${_includeDir}") + file (RELATIVE_PATH _relPath "${_includeDir}" "${_headerFile}") + if (NOT IS_ABSOLUTE "${_relPath}" AND NOT "${_relPath}" MATCHES "^\\.\\.") + string (LENGTH "${${_relPathVar}}" _closestLen) + string (LENGTH "${_relPath}" _relLen) + if (_closestLen EQUAL 0 OR _relLen LESS _closestLen) + set (${_relPathVar} "${_relPath}") + endif() + endif() + elseif ("${_includeDir}" STREQUAL "${_headerFile}") + # if path matches exactly, return short non-empty string + set (${_relPathVar} "1") + break() + endif() + endforeach() +endmacro() + +macro (cotire_check_header_file_location _headerFile _insideIncludeDirs _outsideIncludeDirs _headerIsInside) + # check header path against ignored and honored include directories + cotire_find_closest_relative_path("${_headerFile}" "${_insideIncludeDirs}" _insideRelPath) + if (_insideRelPath) + # header is inside, but could be become outside if there is a shorter outside match + cotire_find_closest_relative_path("${_headerFile}" "${_outsideIncludeDirs}" _outsideRelPath) + if (_outsideRelPath) + string (LENGTH "${_insideRelPath}" _insideRelPathLen) + string (LENGTH "${_outsideRelPath}" _outsideRelPathLen) + if (_outsideRelPathLen LESS _insideRelPathLen) + set (${_headerIsInside} FALSE) + else() + set (${_headerIsInside} TRUE) + endif() + else() + set (${_headerIsInside} TRUE) + endif() + else() + # header is outside + set (${_headerIsInside} FALSE) + endif() +endmacro() + +macro (cotire_check_ignore_header_file_path _headerFile _headerIsIgnoredVar) + if (NOT EXISTS "${_headerFile}") + set (${_headerIsIgnoredVar} TRUE) + elseif (IS_DIRECTORY "${_headerFile}") + set (${_headerIsIgnoredVar} TRUE) + elseif ("${_headerFile}" MATCHES "\\.\\.|[_-]fixed" AND "${_headerFile}" MATCHES "\\.h$") + # heuristic: ignore C headers with embedded parent directory references or "-fixed" or "_fixed" in path + # these often stem from using GCC #include_next tricks, which may break the precompiled header compilation + # with the error message "error: no include path in which to search for header.h" + set (${_headerIsIgnoredVar} TRUE) + else() + set (${_headerIsIgnoredVar} FALSE) + endif() +endmacro() + +macro (cotire_check_ignore_header_file_ext _headerFile _ignoreExtensionsVar _headerIsIgnoredVar) + # check header file extension + cotire_get_source_file_extension("${_headerFile}" _headerFileExt) + set (${_headerIsIgnoredVar} FALSE) + if (_headerFileExt) + list (FIND ${_ignoreExtensionsVar} "${_headerFileExt}" _index) + if (_index GREATER -1) + set (${_headerIsIgnoredVar} TRUE) + endif() + endif() +endmacro() + +macro (cotire_parse_line _line _headerFileVar _headerDepthVar) + if (MSVC) + # cl.exe /showIncludes output looks different depending on the language pack used, e.g.: + # English: "Note: including file: C:\directory\file" + # German: "Hinweis: Einlesen der Datei: C:\directory\file" + # We use a very general regular expression, relying on the presence of the : characters + if (_line MATCHES "( +)([a-zA-Z]:[^:]+)$") + # Visual Studio compiler output + string (LENGTH "${CMAKE_MATCH_1}" ${_headerDepthVar}) + get_filename_component(${_headerFileVar} "${CMAKE_MATCH_2}" ABSOLUTE) + else() + set (${_headerFileVar} "") + set (${_headerDepthVar} 0) + endif() + else() + if (_line MATCHES "^(\\.+) (.*)$") + # GCC like output + string (LENGTH "${CMAKE_MATCH_1}" ${_headerDepthVar}) + if (IS_ABSOLUTE "${CMAKE_MATCH_2}") + set (${_headerFileVar} "${CMAKE_MATCH_2}") + else() + get_filename_component(${_headerFileVar} "${CMAKE_MATCH_2}" REALPATH) + endif() + else() + set (${_headerFileVar} "") + set (${_headerDepthVar} 0) + endif() + endif() +endmacro() + +function (cotire_parse_includes _language _scanOutput _ignoredIncludeDirs _honoredIncludeDirs _ignoredExtensions _selectedIncludesVar _unparsedLinesVar) + if (WIN32) + # prevent CMake macro invocation errors due to backslash characters in Windows paths + string (REPLACE "\\" "/" _scanOutput "${_scanOutput}") + endif() + # canonize slashes + string (REPLACE "//" "/" _scanOutput "${_scanOutput}") + # prevent semicolon from being interpreted as a line separator + string (REPLACE ";" "\\;" _scanOutput "${_scanOutput}") + # then separate lines + string (REGEX REPLACE "\n" ";" _scanOutput "${_scanOutput}") + list (LENGTH _scanOutput _len) + # remove duplicate lines to speed up parsing + list (REMOVE_DUPLICATES _scanOutput) + list (LENGTH _scanOutput _uniqueLen) + if (COTIRE_VERBOSE OR COTIRE_DEBUG) + message (STATUS "Scanning ${_uniqueLen} unique lines of ${_len} for includes") + if (_ignoredExtensions) + message (STATUS "Ignored extensions: ${_ignoredExtensions}") + endif() + if (_ignoredIncludeDirs) + message (STATUS "Ignored paths: ${_ignoredIncludeDirs}") + endif() + if (_honoredIncludeDirs) + message (STATUS "Included paths: ${_honoredIncludeDirs}") + endif() + endif() + set (_sourceFiles ${ARGN}) + set (_selectedIncludes "") + set (_unparsedLines "") + # stack keeps track of inside/outside project status of processed header files + set (_headerIsInsideStack "") + foreach (_line IN LISTS _scanOutput) + if (_line) + cotire_parse_line("${_line}" _headerFile _headerDepth) + if (_headerFile) + cotire_check_header_file_location("${_headerFile}" "${_ignoredIncludeDirs}" "${_honoredIncludeDirs}" _headerIsInside) + if (COTIRE_DEBUG) + message (STATUS "${_headerDepth}: ${_headerFile} ${_headerIsInside}") + endif() + # update stack + list (LENGTH _headerIsInsideStack _stackLen) + if (_headerDepth GREATER _stackLen) + math (EXPR _stackLen "${_stackLen} + 1") + foreach (_index RANGE ${_stackLen} ${_headerDepth}) + list (APPEND _headerIsInsideStack ${_headerIsInside}) + endforeach() + else() + foreach (_index RANGE ${_headerDepth} ${_stackLen}) + list (REMOVE_AT _headerIsInsideStack -1) + endforeach() + list (APPEND _headerIsInsideStack ${_headerIsInside}) + endif() + if (COTIRE_DEBUG) + message (STATUS "${_headerIsInsideStack}") + endif() + # header is a candidate if it is outside project + if (NOT _headerIsInside) + # get parent header file's inside/outside status + if (_headerDepth GREATER 1) + math (EXPR _index "${_headerDepth} - 2") + list (GET _headerIsInsideStack ${_index} _parentHeaderIsInside) + else() + set (_parentHeaderIsInside TRUE) + endif() + # select header file if parent header file is inside project + # (e.g., a project header file that includes a standard header file) + if (_parentHeaderIsInside) + cotire_check_ignore_header_file_path("${_headerFile}" _headerIsIgnored) + if (NOT _headerIsIgnored) + cotire_check_ignore_header_file_ext("${_headerFile}" _ignoredExtensions _headerIsIgnored) + if (NOT _headerIsIgnored) + list (APPEND _selectedIncludes "${_headerFile}") + else() + # fix header's inside status on stack, it is ignored by extension now + list (REMOVE_AT _headerIsInsideStack -1) + list (APPEND _headerIsInsideStack TRUE) + endif() + endif() + if (COTIRE_DEBUG) + message (STATUS "${_headerFile} ${_ignoredExtensions} ${_headerIsIgnored}") + endif() + endif() + endif() + else() + if (MSVC) + # for cl.exe do not keep unparsed lines which solely consist of a source file name + string (FIND "${_sourceFiles}" "${_line}" _index) + if (_index LESS 0) + list (APPEND _unparsedLines "${_line}") + endif() + else() + list (APPEND _unparsedLines "${_line}") + endif() + endif() + endif() + endforeach() + list (REMOVE_DUPLICATES _selectedIncludes) + set (${_selectedIncludesVar} ${_selectedIncludes} PARENT_SCOPE) + set (${_unparsedLinesVar} ${_unparsedLines} PARENT_SCOPE) +endfunction() + +function (cotire_scan_includes _includesVar) + set(_options "") + set(_oneValueArgs COMPILER_ID COMPILER_EXECUTABLE COMPILER_ARG1 COMPILER_VERSION LANGUAGE UNPARSED_LINES SCAN_RESULT) + set(_multiValueArgs COMPILE_DEFINITIONS COMPILE_FLAGS INCLUDE_DIRECTORIES SYSTEM_INCLUDE_DIRECTORIES + IGNORE_PATH INCLUDE_PATH IGNORE_EXTENSIONS INCLUDE_PRIORITY_PATH COMPILER_LAUNCHER) + cmake_parse_arguments(_option "${_options}" "${_oneValueArgs}" "${_multiValueArgs}" ${ARGN}) + set (_sourceFiles ${_option_UNPARSED_ARGUMENTS}) + if (NOT _option_LANGUAGE) + set (_option_LANGUAGE "CXX") + endif() + if (NOT _option_COMPILER_ID) + set (_option_COMPILER_ID "${CMAKE_${_option_LANGUAGE}_ID}") + endif() + if (NOT _option_COMPILER_VERSION) + set (_option_COMPILER_VERSION "${CMAKE_${_option_LANGUAGE}_COMPILER_VERSION}") + endif() + cotire_init_compile_cmd(_cmd "${_option_LANGUAGE}" "${_option_COMPILER_LAUNCHER}" "${_option_COMPILER_EXECUTABLE}" "${_option_COMPILER_ARG1}") + cotire_add_definitions_to_cmd(_cmd "${_option_LANGUAGE}" ${_option_COMPILE_DEFINITIONS}) + cotire_add_compile_flags_to_cmd(_cmd ${_option_COMPILE_FLAGS}) + cotire_add_includes_to_cmd(_cmd "${_option_LANGUAGE}" _option_INCLUDE_DIRECTORIES _option_SYSTEM_INCLUDE_DIRECTORIES) + cotire_add_frameworks_to_cmd(_cmd "${_option_LANGUAGE}" _option_INCLUDE_DIRECTORIES _option_SYSTEM_INCLUDE_DIRECTORIES) + cotire_add_makedep_flags("${_option_LANGUAGE}" "${_option_COMPILER_ID}" "${_option_COMPILER_VERSION}" _cmd) + # only consider existing source files for scanning + set (_existingSourceFiles "") + foreach (_sourceFile ${_sourceFiles}) + if (EXISTS "${_sourceFile}") + list (APPEND _existingSourceFiles "${_sourceFile}") + endif() + endforeach() + if (NOT _existingSourceFiles) + set (${_includesVar} "" PARENT_SCOPE) + return() + endif() + list (APPEND _cmd ${_existingSourceFiles}) + if (COTIRE_VERBOSE) + message (STATUS "execute_process: ${_cmd}") + endif() + if (_option_COMPILER_ID MATCHES "MSVC") + # cl.exe messes with the output streams unless the environment variable VS_UNICODE_OUTPUT is cleared + unset (ENV{VS_UNICODE_OUTPUT}) + endif() + execute_process( + COMMAND ${_cmd} + WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" + RESULT_VARIABLE _result + OUTPUT_QUIET + ERROR_VARIABLE _output) + if (_result) + message (STATUS "Result ${_result} scanning includes of ${_existingSourceFiles}.") + endif() + cotire_parse_includes( + "${_option_LANGUAGE}" "${_output}" + "${_option_IGNORE_PATH}" "${_option_INCLUDE_PATH}" + "${_option_IGNORE_EXTENSIONS}" + _includes _unparsedLines + ${_sourceFiles}) + if (_option_INCLUDE_PRIORITY_PATH) + set (_sortedIncludes "") + foreach (_priorityPath ${_option_INCLUDE_PRIORITY_PATH}) + foreach (_include ${_includes}) + string (FIND ${_include} ${_priorityPath} _position) + if (_position GREATER -1) + list (APPEND _sortedIncludes ${_include}) + endif() + endforeach() + endforeach() + if (_sortedIncludes) + list (INSERT _includes 0 ${_sortedIncludes}) + list (REMOVE_DUPLICATES _includes) + endif() + endif() + set (${_includesVar} ${_includes} PARENT_SCOPE) + if (_option_UNPARSED_LINES) + set (${_option_UNPARSED_LINES} ${_unparsedLines} PARENT_SCOPE) + endif() + if (_option_SCAN_RESULT) + set (${_option_SCAN_RESULT} ${_result} PARENT_SCOPE) + endif() +endfunction() + +macro (cotire_append_undefs _contentsVar) + set (_undefs ${ARGN}) + if (_undefs) + list (REMOVE_DUPLICATES _undefs) + foreach (_definition ${_undefs}) + list (APPEND ${_contentsVar} "#undef ${_definition}") + endforeach() + endif() +endmacro() + +macro (cotire_comment_str _language _commentText _commentVar) + if ("${_language}" STREQUAL "CMAKE") + set (${_commentVar} "# ${_commentText}") + else() + set (${_commentVar} "/* ${_commentText} */") + endif() +endmacro() + +function (cotire_write_file _language _file _contents _force) + get_filename_component(_moduleName "${COTIRE_CMAKE_MODULE_FILE}" NAME) + cotire_comment_str("${_language}" "${_moduleName} ${COTIRE_CMAKE_MODULE_VERSION} generated file" _header1) + cotire_comment_str("${_language}" "${_file}" _header2) + set (_contents "${_header1}\n${_header2}\n${_contents}") + if (COTIRE_DEBUG) + message (STATUS "${_contents}") + endif() + if (_force OR NOT EXISTS "${_file}") + file (WRITE "${_file}" "${_contents}") + else() + file (READ "${_file}" _oldContents) + if (NOT "${_oldContents}" STREQUAL "${_contents}") + file (WRITE "${_file}" "${_contents}") + else() + if (COTIRE_DEBUG) + message (STATUS "${_file} unchanged") + endif() + endif() + endif() +endfunction() + +function (cotire_generate_unity_source _unityFile) + set(_options "") + set(_oneValueArgs LANGUAGE) + set(_multiValueArgs + DEPENDS SOURCES_COMPILE_DEFINITIONS + PRE_UNDEFS SOURCES_PRE_UNDEFS POST_UNDEFS SOURCES_POST_UNDEFS PROLOGUE EPILOGUE) + cmake_parse_arguments(_option "${_options}" "${_oneValueArgs}" "${_multiValueArgs}" ${ARGN}) + if (_option_DEPENDS) + cotire_check_file_up_to_date(_unityFileIsUpToDate "${_unityFile}" ${_option_DEPENDS}) + if (_unityFileIsUpToDate) + return() + endif() + endif() + set (_sourceFiles ${_option_UNPARSED_ARGUMENTS}) + if (NOT _option_PRE_UNDEFS) + set (_option_PRE_UNDEFS "") + endif() + if (NOT _option_SOURCES_PRE_UNDEFS) + set (_option_SOURCES_PRE_UNDEFS "") + endif() + if (NOT _option_POST_UNDEFS) + set (_option_POST_UNDEFS "") + endif() + if (NOT _option_SOURCES_POST_UNDEFS) + set (_option_SOURCES_POST_UNDEFS "") + endif() + set (_contents "") + if (_option_PROLOGUE) + list (APPEND _contents ${_option_PROLOGUE}) + endif() + if (_option_LANGUAGE AND _sourceFiles) + if ("${_option_LANGUAGE}" STREQUAL "CXX") + list (APPEND _contents "#ifdef __cplusplus") + elseif ("${_option_LANGUAGE}" STREQUAL "C") + list (APPEND _contents "#ifndef __cplusplus") + endif() + endif() + set (_compileUndefinitions "") + foreach (_sourceFile ${_sourceFiles}) + cotire_get_source_compile_definitions( + "${_option_CONFIGURATION}" "${_option_LANGUAGE}" "${_sourceFile}" _compileDefinitions + ${_option_SOURCES_COMPILE_DEFINITIONS}) + cotire_get_source_undefs("${_sourceFile}" COTIRE_UNITY_SOURCE_PRE_UNDEFS _sourcePreUndefs ${_option_SOURCES_PRE_UNDEFS}) + cotire_get_source_undefs("${_sourceFile}" COTIRE_UNITY_SOURCE_POST_UNDEFS _sourcePostUndefs ${_option_SOURCES_POST_UNDEFS}) + if (_option_PRE_UNDEFS) + list (APPEND _compileUndefinitions ${_option_PRE_UNDEFS}) + endif() + if (_sourcePreUndefs) + list (APPEND _compileUndefinitions ${_sourcePreUndefs}) + endif() + if (_compileUndefinitions) + cotire_append_undefs(_contents ${_compileUndefinitions}) + set (_compileUndefinitions "") + endif() + if (_sourcePostUndefs) + list (APPEND _compileUndefinitions ${_sourcePostUndefs}) + endif() + if (_option_POST_UNDEFS) + list (APPEND _compileUndefinitions ${_option_POST_UNDEFS}) + endif() + foreach (_definition ${_compileDefinitions}) + if (_definition MATCHES "^([a-zA-Z0-9_]+)=(.+)$") + list (APPEND _contents "#define ${CMAKE_MATCH_1} ${CMAKE_MATCH_2}") + list (INSERT _compileUndefinitions 0 "${CMAKE_MATCH_1}") + else() + list (APPEND _contents "#define ${_definition}") + list (INSERT _compileUndefinitions 0 "${_definition}") + endif() + endforeach() + # use absolute path as source file location + get_filename_component(_sourceFileLocation "${_sourceFile}" ABSOLUTE) + if (WIN32) + file (TO_NATIVE_PATH "${_sourceFileLocation}" _sourceFileLocation) + endif() + list (APPEND _contents "#include \"${_sourceFileLocation}\"") + endforeach() + if (_compileUndefinitions) + cotire_append_undefs(_contents ${_compileUndefinitions}) + set (_compileUndefinitions "") + endif() + if (_option_LANGUAGE AND _sourceFiles) + list (APPEND _contents "#endif") + endif() + if (_option_EPILOGUE) + list (APPEND _contents ${_option_EPILOGUE}) + endif() + list (APPEND _contents "") + string (REPLACE ";" "\n" _contents "${_contents}") + if (COTIRE_VERBOSE) + message ("${_contents}") + endif() + cotire_write_file("${_option_LANGUAGE}" "${_unityFile}" "${_contents}" TRUE) +endfunction() + +function (cotire_generate_prefix_header _prefixFile) + set(_options "") + set(_oneValueArgs LANGUAGE COMPILER_EXECUTABLE COMPILER_ARG1 COMPILER_ID COMPILER_VERSION) + set(_multiValueArgs DEPENDS COMPILE_DEFINITIONS COMPILE_FLAGS + INCLUDE_DIRECTORIES SYSTEM_INCLUDE_DIRECTORIES IGNORE_PATH INCLUDE_PATH + IGNORE_EXTENSIONS INCLUDE_PRIORITY_PATH COMPILER_LAUNCHER) + cmake_parse_arguments(_option "${_options}" "${_oneValueArgs}" "${_multiValueArgs}" ${ARGN}) + if (NOT _option_COMPILER_ID) + set (_option_COMPILER_ID "${CMAKE_${_option_LANGUAGE}_ID}") + endif() + if (NOT _option_COMPILER_VERSION) + set (_option_COMPILER_VERSION "${CMAKE_${_option_LANGUAGE}_COMPILER_VERSION}") + endif() + if (_option_DEPENDS) + cotire_check_file_up_to_date(_prefixFileIsUpToDate "${_prefixFile}" ${_option_DEPENDS}) + if (_prefixFileIsUpToDate) + # create empty log file + set (_unparsedLinesFile "${_prefixFile}.log") + file (WRITE "${_unparsedLinesFile}" "") + return() + endif() + endif() + set (_prologue "") + set (_epilogue "") + if (_option_COMPILER_ID MATCHES "Clang") + set (_prologue "#pragma clang system_header") + elseif (_option_COMPILER_ID MATCHES "GNU") + set (_prologue "#pragma GCC system_header") + elseif (_option_COMPILER_ID MATCHES "MSVC") + set (_prologue "#pragma warning(push, 0)") + set (_epilogue "#pragma warning(pop)") + elseif (_option_COMPILER_ID MATCHES "Intel") + # Intel compiler requires hdrstop pragma to stop generating PCH file + set (_epilogue "#pragma hdrstop") + endif() + set (_sourceFiles ${_option_UNPARSED_ARGUMENTS}) + cotire_scan_includes(_selectedHeaders ${_sourceFiles} + LANGUAGE "${_option_LANGUAGE}" + COMPILER_LAUNCHER "${_option_COMPILER_LAUNCHER}" + COMPILER_EXECUTABLE "${_option_COMPILER_EXECUTABLE}" + COMPILER_ARG1 "${_option_COMPILER_ARG1}" + COMPILER_ID "${_option_COMPILER_ID}" + COMPILER_VERSION "${_option_COMPILER_VERSION}" + COMPILE_DEFINITIONS ${_option_COMPILE_DEFINITIONS} + COMPILE_FLAGS ${_option_COMPILE_FLAGS} + INCLUDE_DIRECTORIES ${_option_INCLUDE_DIRECTORIES} + SYSTEM_INCLUDE_DIRECTORIES ${_option_SYSTEM_INCLUDE_DIRECTORIES} + IGNORE_PATH ${_option_IGNORE_PATH} + INCLUDE_PATH ${_option_INCLUDE_PATH} + IGNORE_EXTENSIONS ${_option_IGNORE_EXTENSIONS} + INCLUDE_PRIORITY_PATH ${_option_INCLUDE_PRIORITY_PATH} + UNPARSED_LINES _unparsedLines + SCAN_RESULT _scanResult) + cotire_generate_unity_source("${_prefixFile}" + PROLOGUE ${_prologue} EPILOGUE ${_epilogue} LANGUAGE "${_option_LANGUAGE}" ${_selectedHeaders}) + set (_unparsedLinesFile "${_prefixFile}.log") + if (_unparsedLines) + if (COTIRE_VERBOSE OR _scanResult OR NOT _selectedHeaders) + list (LENGTH _unparsedLines _skippedLineCount) + message (STATUS "${_skippedLineCount} line(s) skipped, see ${_unparsedLinesFile}") + endif() + string (REPLACE ";" "\n" _unparsedLines "${_unparsedLines}") + endif() + file (WRITE "${_unparsedLinesFile}" "${_unparsedLines}") +endfunction() + +function (cotire_add_makedep_flags _language _compilerID _compilerVersion _flagsVar) + set (_flags ${${_flagsVar}}) + if (_compilerID MATCHES "MSVC") + # cl.exe options used + # /nologo suppresses display of sign-on banner + # /TC treat all files named on the command line as C source files + # /TP treat all files named on the command line as C++ source files + # /EP preprocess to stdout without #line directives + # /showIncludes list include files + set (_sourceFileTypeC "/TC") + set (_sourceFileTypeCXX "/TP") + if (_flags) + # append to list + list (APPEND _flags /nologo "${_sourceFileType${_language}}" /EP /showIncludes) + else() + # return as a flag string + set (_flags "${_sourceFileType${_language}} /EP /showIncludes") + endif() + elseif (_compilerID MATCHES "GNU") + # GCC options used + # -H print the name of each header file used + # -E invoke preprocessor + # -fdirectives-only do not expand macros, requires GCC >= 4.3 + if (_flags) + # append to list + list (APPEND _flags -H -E) + if (NOT "${_compilerVersion}" VERSION_LESS "4.3.0") + list (APPEND _flags "-fdirectives-only") + endif() + else() + # return as a flag string + set (_flags "-H -E") + if (NOT "${_compilerVersion}" VERSION_LESS "4.3.0") + set (_flags "${_flags} -fdirectives-only") + endif() + endif() + elseif (_compilerID MATCHES "Clang") + # Clang options used + # -H print the name of each header file used + # -E invoke preprocessor + # -fno-color-diagnostics don't prints diagnostics in color + if (_flags) + # append to list + list (APPEND _flags -H -E -fno-color-diagnostics) + else() + # return as a flag string + set (_flags "-H -E -fno-color-diagnostics") + endif() + elseif (_compilerID MATCHES "Intel") + if (WIN32) + # Windows Intel options used + # /nologo do not display compiler version information + # /QH display the include file order + # /EP preprocess to stdout, omitting #line directives + # /TC process all source or unrecognized file types as C source files + # /TP process all source or unrecognized file types as C++ source files + set (_sourceFileTypeC "/TC") + set (_sourceFileTypeCXX "/TP") + if (_flags) + # append to list + list (APPEND _flags /nologo "${_sourceFileType${_language}}" /EP /QH) + else() + # return as a flag string + set (_flags "${_sourceFileType${_language}} /EP /QH") + endif() + else() + # Linux / Mac OS X Intel options used + # -H print the name of each header file used + # -EP preprocess to stdout, omitting #line directives + # -Kc++ process all source or unrecognized file types as C++ source files + if (_flags) + # append to list + if ("${_language}" STREQUAL "CXX") + list (APPEND _flags -Kc++) + endif() + list (APPEND _flags -H -EP) + else() + # return as a flag string + if ("${_language}" STREQUAL "CXX") + set (_flags "-Kc++ ") + endif() + set (_flags "${_flags}-H -EP") + endif() + endif() + else() + message (FATAL_ERROR "cotire: unsupported ${_language} compiler ${_compilerID} version ${_compilerVersion}.") + endif() + set (${_flagsVar} ${_flags} PARENT_SCOPE) +endfunction() + +function (cotire_add_pch_compilation_flags _language _compilerID _compilerVersion _prefixFile _pchFile _hostFile _flagsVar) + set (_flags ${${_flagsVar}}) + if (_compilerID MATCHES "MSVC") + file (TO_NATIVE_PATH "${_prefixFile}" _prefixFileNative) + file (TO_NATIVE_PATH "${_pchFile}" _pchFileNative) + file (TO_NATIVE_PATH "${_hostFile}" _hostFileNative) + # cl.exe options used + # /Yc creates a precompiled header file + # /Fp specifies precompiled header binary file name + # /FI forces inclusion of file + # /TC treat all files named on the command line as C source files + # /TP treat all files named on the command line as C++ source files + # /Zs syntax check only + # /Zm precompiled header memory allocation scaling factor + set (_sourceFileTypeC "/TC") + set (_sourceFileTypeCXX "/TP") + if (_flags) + # append to list + list (APPEND _flags /nologo "${_sourceFileType${_language}}" + "/Yc${_prefixFileNative}" "/Fp${_pchFileNative}" "/FI${_prefixFileNative}" /Zs "${_hostFileNative}") + if (COTIRE_PCH_MEMORY_SCALING_FACTOR) + list (APPEND _flags "/Zm${COTIRE_PCH_MEMORY_SCALING_FACTOR}") + endif() + else() + # return as a flag string + set (_flags "/Yc\"${_prefixFileNative}\" /Fp\"${_pchFileNative}\" /FI\"${_prefixFileNative}\"") + if (COTIRE_PCH_MEMORY_SCALING_FACTOR) + set (_flags "${_flags} /Zm${COTIRE_PCH_MEMORY_SCALING_FACTOR}") + endif() + endif() + elseif (_compilerID MATCHES "GNU|Clang") + # GCC / Clang options used + # -x specify the source language + # -c compile but do not link + # -o place output in file + # note that we cannot use -w to suppress all warnings upon pre-compiling, because turning off a warning may + # alter compile flags as a side effect (e.g., -Wwrite-string implies -fconst-strings) + set (_xLanguage_C "c-header") + set (_xLanguage_CXX "c++-header") + if (_flags) + # append to list + list (APPEND _flags "-x" "${_xLanguage_${_language}}" "-c" "${_prefixFile}" -o "${_pchFile}") + else() + # return as a flag string + set (_flags "-x ${_xLanguage_${_language}} -c \"${_prefixFile}\" -o \"${_pchFile}\"") + endif() + elseif (_compilerID MATCHES "Intel") + if (WIN32) + file (TO_NATIVE_PATH "${_prefixFile}" _prefixFileNative) + file (TO_NATIVE_PATH "${_pchFile}" _pchFileNative) + file (TO_NATIVE_PATH "${_hostFile}" _hostFileNative) + # Windows Intel options used + # /nologo do not display compiler version information + # /Yc create a precompiled header (PCH) file + # /Fp specify a path or file name for precompiled header files + # /FI tells the preprocessor to include a specified file name as the header file + # /TC process all source or unrecognized file types as C source files + # /TP process all source or unrecognized file types as C++ source files + # /Zs syntax check only + # /Wpch-messages enable diagnostics related to pre-compiled headers (requires Intel XE 2013 Update 2) + set (_sourceFileTypeC "/TC") + set (_sourceFileTypeCXX "/TP") + if (_flags) + # append to list + list (APPEND _flags /nologo "${_sourceFileType${_language}}" + "/Yc" "/Fp${_pchFileNative}" "/FI${_prefixFileNative}" /Zs "${_hostFileNative}") + if (NOT "${_compilerVersion}" VERSION_LESS "13.1.0") + list (APPEND _flags "/Wpch-messages") + endif() + else() + # return as a flag string + set (_flags "/Yc /Fp\"${_pchFileNative}\" /FI\"${_prefixFileNative}\"") + if (NOT "${_compilerVersion}" VERSION_LESS "13.1.0") + set (_flags "${_flags} /Wpch-messages") + endif() + endif() + else() + # Linux / Mac OS X Intel options used + # -pch-dir location for precompiled header files + # -pch-create name of the precompiled header (PCH) to create + # -Kc++ process all source or unrecognized file types as C++ source files + # -fsyntax-only check only for correct syntax + # -Wpch-messages enable diagnostics related to pre-compiled headers (requires Intel XE 2013 Update 2) + get_filename_component(_pchDir "${_pchFile}" DIRECTORY) + get_filename_component(_pchName "${_pchFile}" NAME) + set (_xLanguage_C "c-header") + set (_xLanguage_CXX "c++-header") + if (_flags) + # append to list + if ("${_language}" STREQUAL "CXX") + list (APPEND _flags -Kc++) + endif() + list (APPEND _flags "-include" "${_prefixFile}" "-pch-dir" "${_pchDir}" "-pch-create" "${_pchName}" "-fsyntax-only" "${_hostFile}") + if (NOT "${_compilerVersion}" VERSION_LESS "13.1.0") + list (APPEND _flags "-Wpch-messages") + endif() + else() + # return as a flag string + set (_flags "-include \"${_prefixFile}\" -pch-dir \"${_pchDir}\" -pch-create \"${_pchName}\"") + if (NOT "${_compilerVersion}" VERSION_LESS "13.1.0") + set (_flags "${_flags} -Wpch-messages") + endif() + endif() + endif() + else() + message (FATAL_ERROR "cotire: unsupported ${_language} compiler ${_compilerID} version ${_compilerVersion}.") + endif() + set (${_flagsVar} ${_flags} PARENT_SCOPE) +endfunction() + +function (cotire_add_prefix_pch_inclusion_flags _language _compilerID _compilerVersion _prefixFile _pchFile _flagsVar) + set (_flags ${${_flagsVar}}) + if (_compilerID MATCHES "MSVC") + file (TO_NATIVE_PATH "${_prefixFile}" _prefixFileNative) + # cl.exe options used + # /Yu uses a precompiled header file during build + # /Fp specifies precompiled header binary file name + # /FI forces inclusion of file + # /Zm precompiled header memory allocation scaling factor + if (_pchFile) + file (TO_NATIVE_PATH "${_pchFile}" _pchFileNative) + if (_flags) + # append to list + list (APPEND _flags "/Yu${_prefixFileNative}" "/Fp${_pchFileNative}" "/FI${_prefixFileNative}") + if (COTIRE_PCH_MEMORY_SCALING_FACTOR) + list (APPEND _flags "/Zm${COTIRE_PCH_MEMORY_SCALING_FACTOR}") + endif() + else() + # return as a flag string + set (_flags "/Yu\"${_prefixFileNative}\" /Fp\"${_pchFileNative}\" /FI\"${_prefixFileNative}\"") + if (COTIRE_PCH_MEMORY_SCALING_FACTOR) + set (_flags "${_flags} /Zm${COTIRE_PCH_MEMORY_SCALING_FACTOR}") + endif() + endif() + else() + # no precompiled header, force inclusion of prefix header + if (_flags) + # append to list + list (APPEND _flags "/FI${_prefixFileNative}") + else() + # return as a flag string + set (_flags "/FI\"${_prefixFileNative}\"") + endif() + endif() + elseif (_compilerID MATCHES "GNU") + # GCC options used + # -include process include file as the first line of the primary source file + # -Winvalid-pch warns if precompiled header is found but cannot be used + # note: ccache requires the -include flag to be used in order to process precompiled header correctly + if (_flags) + # append to list + list (APPEND _flags "-Winvalid-pch" "-include" "${_prefixFile}") + else() + # return as a flag string + set (_flags "-Winvalid-pch -include \"${_prefixFile}\"") + endif() + elseif (_compilerID MATCHES "Clang") + # Clang options used + # -include process include file as the first line of the primary source file + # -include-pch include precompiled header file + # -Qunused-arguments don't emit warning for unused driver arguments + # note: ccache requires the -include flag to be used in order to process precompiled header correctly + if (_flags) + # append to list + list (APPEND _flags "-Qunused-arguments" "-include" "${_prefixFile}") + else() + # return as a flag string + set (_flags "-Qunused-arguments -include \"${_prefixFile}\"") + endif() + elseif (_compilerID MATCHES "Intel") + if (WIN32) + file (TO_NATIVE_PATH "${_prefixFile}" _prefixFileNative) + # Windows Intel options used + # /Yu use a precompiled header (PCH) file + # /Fp specify a path or file name for precompiled header files + # /FI tells the preprocessor to include a specified file name as the header file + # /Wpch-messages enable diagnostics related to pre-compiled headers (requires Intel XE 2013 Update 2) + if (_pchFile) + file (TO_NATIVE_PATH "${_pchFile}" _pchFileNative) + if (_flags) + # append to list + list (APPEND _flags "/Yu" "/Fp${_pchFileNative}" "/FI${_prefixFileNative}") + if (NOT "${_compilerVersion}" VERSION_LESS "13.1.0") + list (APPEND _flags "/Wpch-messages") + endif() + else() + # return as a flag string + set (_flags "/Yu /Fp\"${_pchFileNative}\" /FI\"${_prefixFileNative}\"") + if (NOT "${_compilerVersion}" VERSION_LESS "13.1.0") + set (_flags "${_flags} /Wpch-messages") + endif() + endif() + else() + # no precompiled header, force inclusion of prefix header + if (_flags) + # append to list + list (APPEND _flags "/FI${_prefixFileNative}") + else() + # return as a flag string + set (_flags "/FI\"${_prefixFileNative}\"") + endif() + endif() + else() + # Linux / Mac OS X Intel options used + # -pch-dir location for precompiled header files + # -pch-use name of the precompiled header (PCH) to use + # -include process include file as the first line of the primary source file + # -Wpch-messages enable diagnostics related to pre-compiled headers (requires Intel XE 2013 Update 2) + if (_pchFile) + get_filename_component(_pchDir "${_pchFile}" DIRECTORY) + get_filename_component(_pchName "${_pchFile}" NAME) + if (_flags) + # append to list + list (APPEND _flags "-include" "${_prefixFile}" "-pch-dir" "${_pchDir}" "-pch-use" "${_pchName}") + if (NOT "${_compilerVersion}" VERSION_LESS "13.1.0") + list (APPEND _flags "-Wpch-messages") + endif() + else() + # return as a flag string + set (_flags "-include \"${_prefixFile}\" -pch-dir \"${_pchDir}\" -pch-use \"${_pchName}\"") + if (NOT "${_compilerVersion}" VERSION_LESS "13.1.0") + set (_flags "${_flags} -Wpch-messages") + endif() + endif() + else() + # no precompiled header, force inclusion of prefix header + if (_flags) + # append to list + list (APPEND _flags "-include" "${_prefixFile}") + else() + # return as a flag string + set (_flags "-include \"${_prefixFile}\"") + endif() + endif() + endif() + else() + message (FATAL_ERROR "cotire: unsupported ${_language} compiler ${_compilerID} version ${_compilerVersion}.") + endif() + set (${_flagsVar} ${_flags} PARENT_SCOPE) +endfunction() + +function (cotire_precompile_prefix_header _prefixFile _pchFile _hostFile) + set(_options "") + set(_oneValueArgs COMPILER_EXECUTABLE COMPILER_ARG1 COMPILER_ID COMPILER_VERSION LANGUAGE) + set(_multiValueArgs COMPILE_DEFINITIONS COMPILE_FLAGS INCLUDE_DIRECTORIES SYSTEM_INCLUDE_DIRECTORIES SYS COMPILER_LAUNCHER) + cmake_parse_arguments(_option "${_options}" "${_oneValueArgs}" "${_multiValueArgs}" ${ARGN}) + if (NOT _option_LANGUAGE) + set (_option_LANGUAGE "CXX") + endif() + if (NOT _option_COMPILER_ID) + set (_option_COMPILER_ID "${CMAKE_${_option_LANGUAGE}_ID}") + endif() + if (NOT _option_COMPILER_VERSION) + set (_option_COMPILER_VERSION "${CMAKE_${_option_LANGUAGE}_COMPILER_VERSION}") + endif() + cotire_init_compile_cmd(_cmd "${_option_LANGUAGE}" "${_option_COMPILER_LAUNCHER}" "${_option_COMPILER_EXECUTABLE}" "${_option_COMPILER_ARG1}") + cotire_add_definitions_to_cmd(_cmd "${_option_LANGUAGE}" ${_option_COMPILE_DEFINITIONS}) + cotire_add_compile_flags_to_cmd(_cmd ${_option_COMPILE_FLAGS}) + cotire_add_includes_to_cmd(_cmd "${_option_LANGUAGE}" _option_INCLUDE_DIRECTORIES _option_SYSTEM_INCLUDE_DIRECTORIES) + cotire_add_frameworks_to_cmd(_cmd "${_option_LANGUAGE}" _option_INCLUDE_DIRECTORIES _option_SYSTEM_INCLUDE_DIRECTORIES) + cotire_add_pch_compilation_flags( + "${_option_LANGUAGE}" "${_option_COMPILER_ID}" "${_option_COMPILER_VERSION}" + "${_prefixFile}" "${_pchFile}" "${_hostFile}" _cmd) + if (COTIRE_VERBOSE) + message (STATUS "execute_process: ${_cmd}") + endif() + if (_option_COMPILER_ID MATCHES "MSVC") + # cl.exe messes with the output streams unless the environment variable VS_UNICODE_OUTPUT is cleared + unset (ENV{VS_UNICODE_OUTPUT}) + endif() + execute_process( + COMMAND ${_cmd} + WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" + RESULT_VARIABLE _result) + if (_result) + message (FATAL_ERROR "cotire: error ${_result} precompiling ${_prefixFile}.") + endif() +endfunction() + +function (cotire_check_precompiled_header_support _language _target _msgVar) + set (_unsupportedCompiler + "Precompiled headers not supported for ${_language} compiler ${CMAKE_${_language}_COMPILER_ID}") + if (CMAKE_${_language}_COMPILER_ID MATCHES "MSVC") + # supported since Visual Studio C++ 6.0 + # and CMake does not support an earlier version + set (${_msgVar} "" PARENT_SCOPE) + elseif (CMAKE_${_language}_COMPILER_ID MATCHES "GNU") + # GCC PCH support requires version >= 3.4 + if ("${CMAKE_${_language}_COMPILER_VERSION}" VERSION_LESS "3.4.0") + set (${_msgVar} "${_unsupportedCompiler} version ${CMAKE_${_language}_COMPILER_VERSION}." PARENT_SCOPE) + else() + set (${_msgVar} "" PARENT_SCOPE) + endif() + elseif (CMAKE_${_language}_COMPILER_ID MATCHES "Clang") + # all Clang versions have PCH support + set (${_msgVar} "" PARENT_SCOPE) + elseif (CMAKE_${_language}_COMPILER_ID MATCHES "Intel") + # Intel PCH support requires version >= 8.0.0 + if ("${CMAKE_${_language}_COMPILER_VERSION}" VERSION_LESS "8.0.0") + set (${_msgVar} "${_unsupportedCompiler} version ${CMAKE_${_language}_COMPILER_VERSION}." PARENT_SCOPE) + else() + set (${_msgVar} "" PARENT_SCOPE) + endif() + else() + set (${_msgVar} "${_unsupportedCompiler}." PARENT_SCOPE) + endif() + get_target_property(_launcher ${_target} ${_language}_COMPILER_LAUNCHER) + if (CMAKE_${_language}_COMPILER MATCHES "ccache" OR _launcher MATCHES "ccache") + if (DEFINED ENV{CCACHE_SLOPPINESS}) + if (NOT "$ENV{CCACHE_SLOPPINESS}" MATCHES "pch_defines" OR NOT "$ENV{CCACHE_SLOPPINESS}" MATCHES "time_macros") + set (${_msgVar} + "ccache requires the environment variable CCACHE_SLOPPINESS to be set to \"pch_defines,time_macros\"." + PARENT_SCOPE) + endif() + else() + if (_launcher MATCHES "ccache") + get_filename_component(_ccacheExe "${_launcher}" REALPATH) + else() + get_filename_component(_ccacheExe "${CMAKE_${_language}_COMPILER}" REALPATH) + endif() + execute_process( + COMMAND "${_ccacheExe}" "--print-config" + WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}" + RESULT_VARIABLE _result + OUTPUT_VARIABLE _ccacheConfig OUTPUT_STRIP_TRAILING_WHITESPACE + ERROR_QUIET) + if (_result OR NOT + _ccacheConfig MATCHES "sloppiness.*=.*time_macros" OR NOT + _ccacheConfig MATCHES "sloppiness.*=.*pch_defines") + set (${_msgVar} + "ccache requires configuration setting \"sloppiness\" to be set to \"pch_defines,time_macros\"." + PARENT_SCOPE) + endif() + endif() + endif() + if (APPLE) + # PCH compilation not supported by GCC / Clang for multi-architecture builds (e.g., i386, x86_64) + cotire_get_configuration_types(_configs) + foreach (_config ${_configs}) + set (_targetFlags "") + cotire_get_target_compile_flags("${_config}" "${_language}" "${_target}" _targetFlags) + cotire_filter_compile_flags("${_language}" "arch" _architectures _ignore ${_targetFlags}) + list (LENGTH _architectures _numberOfArchitectures) + if (_numberOfArchitectures GREATER 1) + string (REPLACE ";" ", " _architectureStr "${_architectures}") + set (${_msgVar} + "Precompiled headers not supported on Darwin for multi-architecture builds (${_architectureStr})." + PARENT_SCOPE) + break() + endif() + endforeach() + endif() +endfunction() + +macro (cotire_get_intermediate_dir _cotireDir) + # ${CMAKE_CFG_INTDIR} may reference a build-time variable when using a generator which supports configuration types + get_filename_component(${_cotireDir} "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${COTIRE_INTDIR}" ABSOLUTE) +endmacro() + +macro (cotire_setup_file_extension_variables) + set (_unityFileExt_C ".c") + set (_unityFileExt_CXX ".cxx") + set (_prefixFileExt_C ".h") + set (_prefixFileExt_CXX ".hxx") + set (_prefixSourceFileExt_C ".c") + set (_prefixSourceFileExt_CXX ".cxx") +endmacro() + +function (cotire_make_single_unity_source_file_path _language _target _unityFileVar) + cotire_setup_file_extension_variables() + if (NOT DEFINED _unityFileExt_${_language}) + set (${_unityFileVar} "" PARENT_SCOPE) + return() + endif() + set (_unityFileBaseName "${_target}_${_language}${COTIRE_UNITY_SOURCE_FILENAME_SUFFIX}") + set (_unityFileName "${_unityFileBaseName}${_unityFileExt_${_language}}") + cotire_get_intermediate_dir(_baseDir) + set (_unityFile "${_baseDir}/${_unityFileName}") + set (${_unityFileVar} "${_unityFile}" PARENT_SCOPE) +endfunction() + +function (cotire_make_unity_source_file_paths _language _target _maxIncludes _unityFilesVar) + cotire_setup_file_extension_variables() + if (NOT DEFINED _unityFileExt_${_language}) + set (${_unityFileVar} "" PARENT_SCOPE) + return() + endif() + set (_unityFileBaseName "${_target}_${_language}${COTIRE_UNITY_SOURCE_FILENAME_SUFFIX}") + cotire_get_intermediate_dir(_baseDir) + set (_startIndex 0) + set (_index 0) + set (_unityFiles "") + set (_sourceFiles ${ARGN}) + foreach (_sourceFile ${_sourceFiles}) + get_source_file_property(_startNew "${_sourceFile}" COTIRE_START_NEW_UNITY_SOURCE) + math (EXPR _unityFileCount "${_index} - ${_startIndex}") + if (_startNew OR (_maxIncludes GREATER 0 AND NOT _unityFileCount LESS _maxIncludes)) + if (_index GREATER 0) + # start new unity file segment + math (EXPR _endIndex "${_index} - 1") + set (_unityFileName "${_unityFileBaseName}_${_startIndex}_${_endIndex}${_unityFileExt_${_language}}") + list (APPEND _unityFiles "${_baseDir}/${_unityFileName}") + endif() + set (_startIndex ${_index}) + endif() + math (EXPR _index "${_index} + 1") + endforeach() + list (LENGTH _sourceFiles _numberOfSources) + if (_startIndex EQUAL 0) + # there is only a single unity file + cotire_make_single_unity_source_file_path(${_language} ${_target} _unityFiles) + elseif (_startIndex LESS _numberOfSources) + # end with final unity file segment + math (EXPR _endIndex "${_index} - 1") + set (_unityFileName "${_unityFileBaseName}_${_startIndex}_${_endIndex}${_unityFileExt_${_language}}") + list (APPEND _unityFiles "${_baseDir}/${_unityFileName}") + endif() + set (${_unityFilesVar} ${_unityFiles} PARENT_SCOPE) + if (COTIRE_DEBUG AND _unityFiles) + message (STATUS "unity files: ${_unityFiles}") + endif() +endfunction() + +function (cotire_unity_to_prefix_file_path _language _target _unityFile _prefixFileVar) + cotire_setup_file_extension_variables() + if (NOT DEFINED _unityFileExt_${_language}) + set (${_prefixFileVar} "" PARENT_SCOPE) + return() + endif() + set (_unityFileBaseName "${_target}_${_language}${COTIRE_UNITY_SOURCE_FILENAME_SUFFIX}") + set (_prefixFileBaseName "${_target}_${_language}${COTIRE_PREFIX_HEADER_FILENAME_SUFFIX}") + string (REPLACE "${_unityFileBaseName}" "${_prefixFileBaseName}" _prefixFile "${_unityFile}") + string (REGEX REPLACE "${_unityFileExt_${_language}}$" "${_prefixFileExt_${_language}}" _prefixFile "${_prefixFile}") + set (${_prefixFileVar} "${_prefixFile}" PARENT_SCOPE) +endfunction() + +function (cotire_prefix_header_to_source_file_path _language _prefixHeaderFile _prefixSourceFileVar) + cotire_setup_file_extension_variables() + if (NOT DEFINED _prefixSourceFileExt_${_language}) + set (${_prefixSourceFileVar} "" PARENT_SCOPE) + return() + endif() + string (REGEX REPLACE "${_prefixFileExt_${_language}}$" "${_prefixSourceFileExt_${_language}}" _prefixSourceFile "${_prefixHeaderFile}") + set (${_prefixSourceFileVar} "${_prefixSourceFile}" PARENT_SCOPE) +endfunction() + +function (cotire_make_prefix_file_name _language _target _prefixFileBaseNameVar _prefixFileNameVar) + cotire_setup_file_extension_variables() + if (NOT _language) + set (_prefixFileBaseName "${_target}${COTIRE_PREFIX_HEADER_FILENAME_SUFFIX}") + set (_prefixFileName "${_prefixFileBaseName}${_prefixFileExt_C}") + elseif (DEFINED _prefixFileExt_${_language}) + set (_prefixFileBaseName "${_target}_${_language}${COTIRE_PREFIX_HEADER_FILENAME_SUFFIX}") + set (_prefixFileName "${_prefixFileBaseName}${_prefixFileExt_${_language}}") + else() + set (_prefixFileBaseName "") + set (_prefixFileName "") + endif() + set (${_prefixFileBaseNameVar} "${_prefixFileBaseName}" PARENT_SCOPE) + set (${_prefixFileNameVar} "${_prefixFileName}" PARENT_SCOPE) +endfunction() + +function (cotire_make_prefix_file_path _language _target _prefixFileVar) + cotire_make_prefix_file_name("${_language}" "${_target}" _prefixFileBaseName _prefixFileName) + set (${_prefixFileVar} "" PARENT_SCOPE) + if (_prefixFileName) + if (NOT _language) + set (_language "C") + endif() + if (CMAKE_${_language}_COMPILER_ID MATCHES "GNU|Clang|Intel|MSVC") + cotire_get_intermediate_dir(_baseDir) + set (${_prefixFileVar} "${_baseDir}/${_prefixFileName}" PARENT_SCOPE) + endif() + endif() +endfunction() + +function (cotire_make_pch_file_path _language _target _pchFileVar) + cotire_make_prefix_file_name("${_language}" "${_target}" _prefixFileBaseName _prefixFileName) + set (${_pchFileVar} "" PARENT_SCOPE) + if (_prefixFileBaseName AND _prefixFileName) + cotire_check_precompiled_header_support("${_language}" "${_target}" _msg) + if (NOT _msg) + if (XCODE) + # For Xcode, we completely hand off the compilation of the prefix header to the IDE + return() + endif() + cotire_get_intermediate_dir(_baseDir) + if (CMAKE_${_language}_COMPILER_ID MATCHES "MSVC") + # MSVC uses the extension .pch added to the prefix header base name + set (${_pchFileVar} "${_baseDir}/${_prefixFileBaseName}.pch" PARENT_SCOPE) + elseif (CMAKE_${_language}_COMPILER_ID MATCHES "Clang") + # Clang looks for a precompiled header corresponding to the prefix header with the extension .pch appended + set (${_pchFileVar} "${_baseDir}/${_prefixFileName}.pch" PARENT_SCOPE) + elseif (CMAKE_${_language}_COMPILER_ID MATCHES "GNU") + # GCC looks for a precompiled header corresponding to the prefix header with the extension .gch appended + set (${_pchFileVar} "${_baseDir}/${_prefixFileName}.gch" PARENT_SCOPE) + elseif (CMAKE_${_language}_COMPILER_ID MATCHES "Intel") + # Intel uses the extension .pchi added to the prefix header base name + set (${_pchFileVar} "${_baseDir}/${_prefixFileBaseName}.pchi" PARENT_SCOPE) + endif() + endif() + endif() +endfunction() + +function (cotire_select_unity_source_files _unityFile _sourcesVar) + set (_sourceFiles ${ARGN}) + if (_sourceFiles AND "${_unityFile}" MATCHES "${COTIRE_UNITY_SOURCE_FILENAME_SUFFIX}_([0-9]+)_([0-9]+)") + set (_startIndex ${CMAKE_MATCH_1}) + set (_endIndex ${CMAKE_MATCH_2}) + list (LENGTH _sourceFiles _numberOfSources) + if (NOT _startIndex LESS _numberOfSources) + math (EXPR _startIndex "${_numberOfSources} - 1") + endif() + if (NOT _endIndex LESS _numberOfSources) + math (EXPR _endIndex "${_numberOfSources} - 1") + endif() + set (_files "") + foreach (_index RANGE ${_startIndex} ${_endIndex}) + list (GET _sourceFiles ${_index} _file) + list (APPEND _files "${_file}") + endforeach() + else() + set (_files ${_sourceFiles}) + endif() + set (${_sourcesVar} ${_files} PARENT_SCOPE) +endfunction() + +function (cotire_get_unity_source_dependencies _language _target _dependencySourcesVar) + set (_dependencySources "") + # depend on target's generated source files + get_target_property(_targetSourceFiles ${_target} SOURCES) + cotire_get_objects_with_property_on(_generatedSources GENERATED SOURCE ${_targetSourceFiles}) + if (_generatedSources) + # but omit all generated source files that have the COTIRE_EXCLUDED property set to true + cotire_get_objects_with_property_on(_excludedGeneratedSources COTIRE_EXCLUDED SOURCE ${_generatedSources}) + if (_excludedGeneratedSources) + list (REMOVE_ITEM _generatedSources ${_excludedGeneratedSources}) + endif() + # and omit all generated source files that have the COTIRE_DEPENDENCY property set to false explicitly + cotire_get_objects_with_property_off(_excludedNonDependencySources COTIRE_DEPENDENCY SOURCE ${_generatedSources}) + if (_excludedNonDependencySources) + list (REMOVE_ITEM _generatedSources ${_excludedNonDependencySources}) + endif() + if (_generatedSources) + list (APPEND _dependencySources ${_generatedSources}) + endif() + endif() + if (COTIRE_DEBUG AND _dependencySources) + message (STATUS "${_language} ${_target} unity source dependencies: ${_dependencySources}") + endif() + set (${_dependencySourcesVar} ${_dependencySources} PARENT_SCOPE) +endfunction() + +function (cotire_get_prefix_header_dependencies _language _target _dependencySourcesVar) + set (_dependencySources "") + # depend on target source files marked with custom COTIRE_DEPENDENCY property + get_target_property(_targetSourceFiles ${_target} SOURCES) + cotire_get_objects_with_property_on(_dependencySources COTIRE_DEPENDENCY SOURCE ${_targetSourceFiles}) + if (COTIRE_DEBUG AND _dependencySources) + message (STATUS "${_language} ${_target} prefix header dependencies: ${_dependencySources}") + endif() + set (${_dependencySourcesVar} ${_dependencySources} PARENT_SCOPE) +endfunction() + +function (cotire_generate_target_script _language _configurations _target _targetScriptVar _targetConfigScriptVar) + set (_targetSources ${ARGN}) + cotire_get_prefix_header_dependencies(${_language} ${_target} COTIRE_TARGET_PREFIX_DEPENDS ${_targetSources}) + cotire_get_unity_source_dependencies(${_language} ${_target} COTIRE_TARGET_UNITY_DEPENDS ${_targetSources}) + # set up variables to be configured + set (COTIRE_TARGET_LANGUAGE "${_language}") + get_target_property(COTIRE_TARGET_IGNORE_PATH ${_target} COTIRE_PREFIX_HEADER_IGNORE_PATH) + cotire_add_sys_root_paths(COTIRE_TARGET_IGNORE_PATH) + get_target_property(COTIRE_TARGET_INCLUDE_PATH ${_target} COTIRE_PREFIX_HEADER_INCLUDE_PATH) + cotire_add_sys_root_paths(COTIRE_TARGET_INCLUDE_PATH) + get_target_property(COTIRE_TARGET_PRE_UNDEFS ${_target} COTIRE_UNITY_SOURCE_PRE_UNDEFS) + get_target_property(COTIRE_TARGET_POST_UNDEFS ${_target} COTIRE_UNITY_SOURCE_POST_UNDEFS) + get_target_property(COTIRE_TARGET_MAXIMUM_NUMBER_OF_INCLUDES ${_target} COTIRE_UNITY_SOURCE_MAXIMUM_NUMBER_OF_INCLUDES) + get_target_property(COTIRE_TARGET_INCLUDE_PRIORITY_PATH ${_target} COTIRE_PREFIX_HEADER_INCLUDE_PRIORITY_PATH) + cotire_get_source_files_undefs(COTIRE_UNITY_SOURCE_PRE_UNDEFS COTIRE_TARGET_SOURCES_PRE_UNDEFS ${_targetSources}) + cotire_get_source_files_undefs(COTIRE_UNITY_SOURCE_POST_UNDEFS COTIRE_TARGET_SOURCES_POST_UNDEFS ${_targetSources}) + set (COTIRE_TARGET_CONFIGURATION_TYPES "${_configurations}") + foreach (_config ${_configurations}) + string (TOUPPER "${_config}" _upperConfig) + cotire_get_target_include_directories( + "${_config}" "${_language}" "${_target}" COTIRE_TARGET_INCLUDE_DIRECTORIES_${_upperConfig} COTIRE_TARGET_SYSTEM_INCLUDE_DIRECTORIES_${_upperConfig}) + cotire_get_target_compile_definitions( + "${_config}" "${_language}" "${_target}" COTIRE_TARGET_COMPILE_DEFINITIONS_${_upperConfig}) + cotire_get_target_compiler_flags( + "${_config}" "${_language}" "${_target}" COTIRE_TARGET_COMPILE_FLAGS_${_upperConfig}) + cotire_get_source_files_compile_definitions( + "${_config}" "${_language}" COTIRE_TARGET_SOURCES_COMPILE_DEFINITIONS_${_upperConfig} ${_targetSources}) + endforeach() + get_target_property(COTIRE_TARGET_${_language}_COMPILER_LAUNCHER ${_target} ${_language}_COMPILER_LAUNCHER) + # set up COTIRE_TARGET_SOURCES + set (COTIRE_TARGET_SOURCES "") + foreach (_sourceFile ${_targetSources}) + get_source_file_property(_generated "${_sourceFile}" GENERATED) + if (_generated) + # use absolute paths for generated files only, retrieving the LOCATION property is an expensive operation + get_source_file_property(_sourceLocation "${_sourceFile}" LOCATION) + list (APPEND COTIRE_TARGET_SOURCES "${_sourceLocation}") + else() + list (APPEND COTIRE_TARGET_SOURCES "${_sourceFile}") + endif() + endforeach() + # copy variable definitions to cotire target script + get_cmake_property(_vars VARIABLES) + string (REGEX MATCHALL "COTIRE_[A-Za-z0-9_]+" _matchVars "${_vars}") + # omit COTIRE_*_INIT variables + string (REGEX MATCHALL "COTIRE_[A-Za-z0-9_]+_INIT" _initVars "${_matchVars}") + if (_initVars) + list (REMOVE_ITEM _matchVars ${_initVars}) + endif() + # omit COTIRE_VERBOSE which is passed as a CMake define on command line + list (REMOVE_ITEM _matchVars COTIRE_VERBOSE) + set (_contents "") + set (_contentsHasGeneratorExpressions FALSE) + foreach (_var IN LISTS _matchVars ITEMS + XCODE MSVC CMAKE_GENERATOR CMAKE_BUILD_TYPE CMAKE_CONFIGURATION_TYPES + CMAKE_${_language}_COMPILER_ID CMAKE_${_language}_COMPILER_VERSION + CMAKE_${_language}_COMPILER_LAUNCHER CMAKE_${_language}_COMPILER CMAKE_${_language}_COMPILER_ARG1 + CMAKE_INCLUDE_FLAG_${_language} CMAKE_INCLUDE_FLAG_${_language}_SEP + CMAKE_INCLUDE_SYSTEM_FLAG_${_language} + CMAKE_${_language}_FRAMEWORK_SEARCH_FLAG + CMAKE_${_language}_SYSTEM_FRAMEWORK_SEARCH_FLAG + CMAKE_${_language}_SOURCE_FILE_EXTENSIONS) + if (DEFINED ${_var}) + string (REPLACE "\"" "\\\"" _value "${${_var}}") + set (_contents "${_contents}set (${_var} \"${_value}\")\n") + if (NOT _contentsHasGeneratorExpressions) + if ("${_value}" MATCHES "\\$<.*>") + set (_contentsHasGeneratorExpressions TRUE) + endif() + endif() + endif() + endforeach() + # generate target script file + get_filename_component(_moduleName "${COTIRE_CMAKE_MODULE_FILE}" NAME) + set (_targetCotireScript "${CMAKE_CURRENT_BINARY_DIR}/${_target}_${_language}_${_moduleName}") + cotire_write_file("CMAKE" "${_targetCotireScript}" "${_contents}" FALSE) + if (_contentsHasGeneratorExpressions) + # use file(GENERATE ...) to expand generator expressions in the target script at CMake generate-time + set (_configNameOrNoneGeneratorExpression "$<$:None>$<$>:$>") + set (_targetCotireConfigScript "${CMAKE_CURRENT_BINARY_DIR}/${_target}_${_language}_${_configNameOrNoneGeneratorExpression}_${_moduleName}") + file (GENERATE OUTPUT "${_targetCotireConfigScript}" INPUT "${_targetCotireScript}") + else() + set (_targetCotireConfigScript "${_targetCotireScript}") + endif() + set (${_targetScriptVar} "${_targetCotireScript}" PARENT_SCOPE) + set (${_targetConfigScriptVar} "${_targetCotireConfigScript}" PARENT_SCOPE) +endfunction() + +function (cotire_setup_pch_file_compilation _language _target _targetScript _prefixFile _pchFile _hostFile) + set (_sourceFiles ${ARGN}) + if (CMAKE_${_language}_COMPILER_ID MATCHES "MSVC|Intel") + # for Visual Studio and Intel, we attach the precompiled header compilation to the host file + # the remaining files include the precompiled header, see cotire_setup_pch_file_inclusion + if (_sourceFiles) + set (_flags "") + cotire_add_pch_compilation_flags( + "${_language}" "${CMAKE_${_language}_COMPILER_ID}" "${CMAKE_${_language}_COMPILER_VERSION}" + "${_prefixFile}" "${_pchFile}" "${_hostFile}" _flags) + set_property (SOURCE ${_hostFile} APPEND_STRING PROPERTY COMPILE_FLAGS " ${_flags} ") + set_property (SOURCE ${_hostFile} APPEND PROPERTY OBJECT_OUTPUTS "${_pchFile}") + # make object file generated from host file depend on prefix header + set_property (SOURCE ${_hostFile} APPEND PROPERTY OBJECT_DEPENDS "${_prefixFile}") + # mark host file as cotired to prevent it from being used in another cotired target + set_property (SOURCE ${_hostFile} PROPERTY COTIRE_TARGET "${_target}") + endif() + elseif ("${CMAKE_GENERATOR}" MATCHES "Make|Ninja") + # for makefile based generator, we add a custom command to precompile the prefix header + if (_targetScript) + cotire_set_cmd_to_prologue(_cmds) + list (APPEND _cmds -P "${COTIRE_CMAKE_MODULE_FILE}" "precompile" "${_targetScript}" "${_prefixFile}" "${_pchFile}" "${_hostFile}") + if (MSVC_IDE) + file (TO_NATIVE_PATH "${_pchFile}" _pchFileLogPath) + else() + file (RELATIVE_PATH _pchFileLogPath "${CMAKE_BINARY_DIR}" "${_pchFile}") + endif() + # make precompiled header compilation depend on the actual compiler executable used to force + # re-compilation when the compiler executable is updated. This prevents "created by a different GCC executable" + # warnings when the precompiled header is included. + get_filename_component(_realCompilerExe "${CMAKE_${_language}_COMPILER}" ABSOLUTE) + if (COTIRE_DEBUG) + message (STATUS "add_custom_command: OUTPUT ${_pchFile} ${_cmds} DEPENDS ${_prefixFile} ${_realCompilerExe} IMPLICIT_DEPENDS ${_language} ${_prefixFile}") + endif() + set_property (SOURCE "${_pchFile}" PROPERTY GENERATED TRUE) + add_custom_command( + OUTPUT "${_pchFile}" + COMMAND ${_cmds} + DEPENDS "${_prefixFile}" "${_realCompilerExe}" + IMPLICIT_DEPENDS ${_language} "${_prefixFile}" + WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" + COMMENT "Building ${_language} precompiled header ${_pchFileLogPath}" + VERBATIM) + endif() + endif() +endfunction() + +function (cotire_setup_pch_file_inclusion _language _target _wholeTarget _prefixFile _pchFile _hostFile) + if (CMAKE_${_language}_COMPILER_ID MATCHES "MSVC|Intel") + # for Visual Studio and Intel, we include the precompiled header in all but the host file + # the host file does the precompiled header compilation, see cotire_setup_pch_file_compilation + set (_sourceFiles ${ARGN}) + list (LENGTH _sourceFiles _numberOfSourceFiles) + if (_numberOfSourceFiles GREATER 0) + # mark sources as cotired to prevent them from being used in another cotired target + set_source_files_properties(${_sourceFiles} PROPERTIES COTIRE_TARGET "${_target}") + set (_flags "") + cotire_add_prefix_pch_inclusion_flags( + "${_language}" "${CMAKE_${_language}_COMPILER_ID}" "${CMAKE_${_language}_COMPILER_VERSION}" + "${_prefixFile}" "${_pchFile}" _flags) + set_property (SOURCE ${_sourceFiles} APPEND_STRING PROPERTY COMPILE_FLAGS " ${_flags} ") + # make object files generated from source files depend on precompiled header + set_property (SOURCE ${_sourceFiles} APPEND PROPERTY OBJECT_DEPENDS "${_pchFile}") + endif() + elseif ("${CMAKE_GENERATOR}" MATCHES "Make|Ninja") + set (_sourceFiles ${_hostFile} ${ARGN}) + if (NOT _wholeTarget) + # for makefile based generator, we force the inclusion of the prefix header for a subset + # of the source files, if this is a multi-language target or has excluded files + set (_flags "") + cotire_add_prefix_pch_inclusion_flags( + "${_language}" "${CMAKE_${_language}_COMPILER_ID}" "${CMAKE_${_language}_COMPILER_VERSION}" + "${_prefixFile}" "${_pchFile}" _flags) + set_property (SOURCE ${_sourceFiles} APPEND_STRING PROPERTY COMPILE_FLAGS " ${_flags} ") + # mark sources as cotired to prevent them from being used in another cotired target + set_source_files_properties(${_sourceFiles} PROPERTIES COTIRE_TARGET "${_target}") + endif() + # make object files generated from source files depend on precompiled header + set_property (SOURCE ${_sourceFiles} APPEND PROPERTY OBJECT_DEPENDS "${_pchFile}") + endif() +endfunction() + +function (cotire_setup_prefix_file_inclusion _language _target _prefixFile) + set (_sourceFiles ${ARGN}) + # force the inclusion of the prefix header for the given source files + set (_flags "") + set (_pchFile "") + cotire_add_prefix_pch_inclusion_flags( + "${_language}" "${CMAKE_${_language}_COMPILER_ID}" "${CMAKE_${_language}_COMPILER_VERSION}" + "${_prefixFile}" "${_pchFile}" _flags) + set_property (SOURCE ${_sourceFiles} APPEND_STRING PROPERTY COMPILE_FLAGS " ${_flags} ") + # mark sources as cotired to prevent them from being used in another cotired target + set_source_files_properties(${_sourceFiles} PROPERTIES COTIRE_TARGET "${_target}") + # make object files generated from source files depend on prefix header + set_property (SOURCE ${_sourceFiles} APPEND PROPERTY OBJECT_DEPENDS "${_prefixFile}") +endfunction() + +function (cotire_get_first_set_property_value _propertyValueVar _type _object) + set (_properties ${ARGN}) + foreach (_property ${_properties}) + get_property(_propertyValue ${_type} "${_object}" PROPERTY ${_property}) + if (_propertyValue) + set (${_propertyValueVar} ${_propertyValue} PARENT_SCOPE) + return() + endif() + endforeach() + set (${_propertyValueVar} "" PARENT_SCOPE) +endfunction() + +function (cotire_setup_combine_command _language _targetScript _joinedFile _cmdsVar) + set (_files ${ARGN}) + set (_filesPaths "") + foreach (_file ${_files}) + get_filename_component(_filePath "${_file}" ABSOLUTE) + list (APPEND _filesPaths "${_filePath}") + endforeach() + cotire_set_cmd_to_prologue(_prefixCmd) + list (APPEND _prefixCmd -P "${COTIRE_CMAKE_MODULE_FILE}" "combine") + if (_targetScript) + list (APPEND _prefixCmd "${_targetScript}") + endif() + list (APPEND _prefixCmd "${_joinedFile}" ${_filesPaths}) + if (COTIRE_DEBUG) + message (STATUS "add_custom_command: OUTPUT ${_joinedFile} COMMAND ${_prefixCmd} DEPENDS ${_files}") + endif() + set_property (SOURCE "${_joinedFile}" PROPERTY GENERATED TRUE) + if (MSVC_IDE) + file (TO_NATIVE_PATH "${_joinedFile}" _joinedFileLogPath) + else() + file (RELATIVE_PATH _joinedFileLogPath "${CMAKE_BINARY_DIR}" "${_joinedFile}") + endif() + get_filename_component(_joinedFileBaseName "${_joinedFile}" NAME_WE) + get_filename_component(_joinedFileExt "${_joinedFile}" EXT) + if (_language AND _joinedFileBaseName MATCHES "${COTIRE_UNITY_SOURCE_FILENAME_SUFFIX}$") + set (_comment "Generating ${_language} unity source ${_joinedFileLogPath}") + elseif (_language AND _joinedFileBaseName MATCHES "${COTIRE_PREFIX_HEADER_FILENAME_SUFFIX}$") + if (_joinedFileExt MATCHES "^\\.c") + set (_comment "Generating ${_language} prefix source ${_joinedFileLogPath}") + else() + set (_comment "Generating ${_language} prefix header ${_joinedFileLogPath}") + endif() + else() + set (_comment "Generating ${_joinedFileLogPath}") + endif() + add_custom_command( + OUTPUT "${_joinedFile}" + COMMAND ${_prefixCmd} + DEPENDS ${_files} + COMMENT "${_comment}" + WORKING_DIRECTORY "${CMAKE_BINARY_DIR}" + VERBATIM) + list (APPEND ${_cmdsVar} COMMAND ${_prefixCmd}) + set (${_cmdsVar} ${${_cmdsVar}} PARENT_SCOPE) +endfunction() + +function (cotire_setup_target_pch_usage _languages _target _wholeTarget) + if (XCODE) + # for Xcode, we attach a pre-build action to generate the unity sources and prefix headers + set (_prefixFiles "") + foreach (_language ${_languages}) + get_property(_prefixFile TARGET ${_target} PROPERTY COTIRE_${_language}_PREFIX_HEADER) + if (_prefixFile) + list (APPEND _prefixFiles "${_prefixFile}") + endif() + endforeach() + set (_cmds ${ARGN}) + list (LENGTH _prefixFiles _numberOfPrefixFiles) + if (_numberOfPrefixFiles GREATER 1) + # we also generate a generic, single prefix header which includes all language specific prefix headers + set (_language "") + set (_targetScript "") + cotire_make_prefix_file_path("${_language}" ${_target} _prefixHeader) + cotire_setup_combine_command("${_language}" "${_targetScript}" "${_prefixHeader}" _cmds ${_prefixFiles}) + else() + set (_prefixHeader "${_prefixFiles}") + endif() + if (COTIRE_DEBUG) + message (STATUS "add_custom_command: TARGET ${_target} PRE_BUILD ${_cmds}") + endif() + # because CMake PRE_BUILD command does not support dependencies, + # we check dependencies explicity in cotire script mode when the pre-build action is run + add_custom_command( + TARGET "${_target}" + PRE_BUILD ${_cmds} + WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" + COMMENT "Updating target ${_target} prefix headers" + VERBATIM) + # make Xcode precompile the generated prefix header with ProcessPCH and ProcessPCH++ + set_target_properties(${_target} PROPERTIES XCODE_ATTRIBUTE_GCC_PRECOMPILE_PREFIX_HEADER "YES") + set_target_properties(${_target} PROPERTIES XCODE_ATTRIBUTE_GCC_PREFIX_HEADER "${_prefixHeader}") + elseif ("${CMAKE_GENERATOR}" MATCHES "Make|Ninja") + # for makefile based generator, we force inclusion of the prefix header for all target source files + # if this is a single-language target without any excluded files + if (_wholeTarget) + set (_language "${_languages}") + # for Visual Studio and Intel, precompiled header inclusion is always done on the source file level + # see cotire_setup_pch_file_inclusion + if (NOT CMAKE_${_language}_COMPILER_ID MATCHES "MSVC|Intel") + get_property(_prefixFile TARGET ${_target} PROPERTY COTIRE_${_language}_PREFIX_HEADER) + if (_prefixFile) + get_property(_pchFile TARGET ${_target} PROPERTY COTIRE_${_language}_PRECOMPILED_HEADER) + set (_options COMPILE_OPTIONS) + cotire_add_prefix_pch_inclusion_flags( + "${_language}" "${CMAKE_${_language}_COMPILER_ID}" "${CMAKE_${_language}_COMPILER_VERSION}" + "${_prefixFile}" "${_pchFile}" _options) + set_property(TARGET ${_target} APPEND PROPERTY ${_options}) + endif() + endif() + endif() + endif() +endfunction() + +function (cotire_setup_unity_generation_commands _language _target _targetScript _targetConfigScript _unityFiles _cmdsVar) + set (_dependencySources "") + cotire_get_unity_source_dependencies(${_language} ${_target} _dependencySources ${ARGN}) + foreach (_unityFile ${_unityFiles}) + set_property (SOURCE "${_unityFile}" PROPERTY GENERATED TRUE) + # set up compiled unity source dependencies via OBJECT_DEPENDS + # this ensures that missing source files are generated before the unity file is compiled + if (COTIRE_DEBUG AND _dependencySources) + message (STATUS "${_unityFile} OBJECT_DEPENDS ${_dependencySources}") + endif() + if (_dependencySources) + # the OBJECT_DEPENDS property requires a list of full paths + set (_objectDependsPaths "") + foreach (_sourceFile ${_dependencySources}) + get_source_file_property(_sourceLocation "${_sourceFile}" LOCATION) + list (APPEND _objectDependsPaths "${_sourceLocation}") + endforeach() + set_property (SOURCE "${_unityFile}" PROPERTY OBJECT_DEPENDS ${_objectDependsPaths}) + endif() + if (WIN32 AND CMAKE_${_language}_COMPILER_ID MATCHES "MSVC|Intel") + # unity file compilation results in potentially huge object file, thus use /bigobj by default unter MSVC and Windows Intel + set_property (SOURCE "${_unityFile}" APPEND_STRING PROPERTY COMPILE_FLAGS "/bigobj") + endif() + cotire_set_cmd_to_prologue(_unityCmd) + list (APPEND _unityCmd -P "${COTIRE_CMAKE_MODULE_FILE}" "unity" "${_targetConfigScript}" "${_unityFile}") + if (CMAKE_VERSION VERSION_LESS "3.1.0") + set (_unityCmdDepends "${_targetScript}") + else() + # CMake 3.1.0 supports generator expressions in arguments to DEPENDS + set (_unityCmdDepends "${_targetConfigScript}") + endif() + if (MSVC_IDE) + file (TO_NATIVE_PATH "${_unityFile}" _unityFileLogPath) + else() + file (RELATIVE_PATH _unityFileLogPath "${CMAKE_BINARY_DIR}" "${_unityFile}") + endif() + if (COTIRE_DEBUG) + message (STATUS "add_custom_command: OUTPUT ${_unityFile} COMMAND ${_unityCmd} DEPENDS ${_unityCmdDepends}") + endif() + add_custom_command( + OUTPUT "${_unityFile}" + COMMAND ${_unityCmd} + DEPENDS ${_unityCmdDepends} + COMMENT "Generating ${_language} unity source ${_unityFileLogPath}" + WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" + VERBATIM) + list (APPEND ${_cmdsVar} COMMAND ${_unityCmd}) + endforeach() + set (${_cmdsVar} ${${_cmdsVar}} PARENT_SCOPE) +endfunction() + +function (cotire_setup_prefix_generation_command _language _target _targetScript _prefixFile _unityFiles _cmdsVar) + set (_sourceFiles ${ARGN}) + set (_dependencySources "") + cotire_get_prefix_header_dependencies(${_language} ${_target} _dependencySources ${_sourceFiles}) + cotire_set_cmd_to_prologue(_prefixCmd) + list (APPEND _prefixCmd -P "${COTIRE_CMAKE_MODULE_FILE}" "prefix" "${_targetScript}" "${_prefixFile}" ${_unityFiles}) + set_property (SOURCE "${_prefixFile}" PROPERTY GENERATED TRUE) + # make prefix header generation depend on the actual compiler executable used to force + # re-generation when the compiler executable is updated. This prevents "file not found" + # errors for compiler version specific system header files. + get_filename_component(_realCompilerExe "${CMAKE_${_language}_COMPILER}" ABSOLUTE) + if (COTIRE_DEBUG) + message (STATUS "add_custom_command: OUTPUT ${_prefixFile} COMMAND ${_prefixCmd} DEPENDS ${_unityFile} ${_dependencySources} ${_realCompilerExe}") + endif() + if (MSVC_IDE) + file (TO_NATIVE_PATH "${_prefixFile}" _prefixFileLogPath) + else() + file (RELATIVE_PATH _prefixFileLogPath "${CMAKE_BINARY_DIR}" "${_prefixFile}") + endif() + get_filename_component(_prefixFileExt "${_prefixFile}" EXT) + if (_prefixFileExt MATCHES "^\\.c") + set (_comment "Generating ${_language} prefix source ${_prefixFileLogPath}") + else() + set (_comment "Generating ${_language} prefix header ${_prefixFileLogPath}") + endif() + # prevent pre-processing errors upon generating the prefix header when a target's generated include file does not yet exist + # we do not add a file-level dependency for the target's generated files though, because we only want to depend on their existence + # thus we make the prefix header generation depend on a custom helper target which triggers the generation of the files + set (_preTargetName "${_target}${COTIRE_PCH_TARGET_SUFFIX}_pre") + if (TARGET ${_preTargetName}) + # custom helper target has already been generated while processing a different language + list (APPEND _dependencySources ${_preTargetName}) + else() + get_target_property(_targetSourceFiles ${_target} SOURCES) + cotire_get_objects_with_property_on(_generatedSources GENERATED SOURCE ${_targetSourceFiles}) + if (_generatedSources) + add_custom_target("${_preTargetName}" DEPENDS ${_generatedSources}) + cotire_init_target("${_preTargetName}") + list (APPEND _dependencySources ${_preTargetName}) + endif() + endif() + add_custom_command( + OUTPUT "${_prefixFile}" "${_prefixFile}.log" + COMMAND ${_prefixCmd} + DEPENDS ${_unityFiles} ${_dependencySources} "${_realCompilerExe}" + COMMENT "${_comment}" + WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" + VERBATIM) + list (APPEND ${_cmdsVar} COMMAND ${_prefixCmd}) + set (${_cmdsVar} ${${_cmdsVar}} PARENT_SCOPE) +endfunction() + +function (cotire_setup_prefix_generation_from_unity_command _language _target _targetScript _prefixFile _unityFiles _cmdsVar) + set (_sourceFiles ${ARGN}) + if (CMAKE_${_language}_COMPILER_ID MATCHES "GNU|Clang") + # GNU and Clang require indirect compilation of the prefix header to make them honor the system_header pragma + cotire_prefix_header_to_source_file_path(${_language} "${_prefixFile}" _prefixSourceFile) + else() + set (_prefixSourceFile "${_prefixFile}") + endif() + cotire_setup_prefix_generation_command( + ${_language} ${_target} "${_targetScript}" + "${_prefixSourceFile}" "${_unityFiles}" ${_cmdsVar} ${_sourceFiles}) + if (CMAKE_${_language}_COMPILER_ID MATCHES "GNU|Clang") + # set up generation of a prefix source file which includes the prefix header + cotire_setup_combine_command(${_language} "${_targetScript}" "${_prefixFile}" _cmds ${_prefixSourceFile}) + endif() + set (${_cmdsVar} ${${_cmdsVar}} PARENT_SCOPE) +endfunction() + +function (cotire_setup_prefix_generation_from_provided_command _language _target _targetScript _prefixFile _cmdsVar) + set (_prefixHeaderFiles ${ARGN}) + if (CMAKE_${_language}_COMPILER_ID MATCHES "GNU|Clang") + # GNU and Clang require indirect compilation of the prefix header to make them honor the system_header pragma + cotire_prefix_header_to_source_file_path(${_language} "${_prefixFile}" _prefixSourceFile) + else() + set (_prefixSourceFile "${_prefixFile}") + endif() + cotire_setup_combine_command(${_language} "${_targetScript}" "${_prefixSourceFile}" _cmds ${_prefixHeaderFiles}) + if (CMAKE_${_language}_COMPILER_ID MATCHES "GNU|Clang") + # set up generation of a prefix source file which includes the prefix header + cotire_setup_combine_command(${_language} "${_targetScript}" "${_prefixFile}" _cmds ${_prefixSourceFile}) + endif() + set (${_cmdsVar} ${${_cmdsVar}} PARENT_SCOPE) +endfunction() + +function (cotire_init_cotire_target_properties _target) + get_property(_isSet TARGET ${_target} PROPERTY COTIRE_ENABLE_PRECOMPILED_HEADER SET) + if (NOT _isSet) + set_property(TARGET ${_target} PROPERTY COTIRE_ENABLE_PRECOMPILED_HEADER TRUE) + endif() + get_property(_isSet TARGET ${_target} PROPERTY COTIRE_ADD_UNITY_BUILD SET) + if (NOT _isSet) + set_property(TARGET ${_target} PROPERTY COTIRE_ADD_UNITY_BUILD TRUE) + endif() + get_property(_isSet TARGET ${_target} PROPERTY COTIRE_ADD_CLEAN SET) + if (NOT _isSet) + set_property(TARGET ${_target} PROPERTY COTIRE_ADD_CLEAN FALSE) + endif() + get_property(_isSet TARGET ${_target} PROPERTY COTIRE_PREFIX_HEADER_IGNORE_PATH SET) + if (NOT _isSet) + set_property(TARGET ${_target} PROPERTY COTIRE_PREFIX_HEADER_IGNORE_PATH "${CMAKE_SOURCE_DIR}") + cotire_check_is_path_relative_to("${CMAKE_BINARY_DIR}" _isRelative "${CMAKE_SOURCE_DIR}") + if (NOT _isRelative) + set_property(TARGET ${_target} APPEND PROPERTY COTIRE_PREFIX_HEADER_IGNORE_PATH "${CMAKE_BINARY_DIR}") + endif() + endif() + get_property(_isSet TARGET ${_target} PROPERTY COTIRE_PREFIX_HEADER_INCLUDE_PATH SET) + if (NOT _isSet) + set_property(TARGET ${_target} PROPERTY COTIRE_PREFIX_HEADER_INCLUDE_PATH "") + endif() + get_property(_isSet TARGET ${_target} PROPERTY COTIRE_PREFIX_HEADER_INCLUDE_PRIORITY_PATH SET) + if (NOT _isSet) + set_property(TARGET ${_target} PROPERTY COTIRE_PREFIX_HEADER_INCLUDE_PRIORITY_PATH "") + endif() + get_property(_isSet TARGET ${_target} PROPERTY COTIRE_UNITY_SOURCE_PRE_UNDEFS SET) + if (NOT _isSet) + set_property(TARGET ${_target} PROPERTY COTIRE_UNITY_SOURCE_PRE_UNDEFS "") + endif() + get_property(_isSet TARGET ${_target} PROPERTY COTIRE_UNITY_SOURCE_POST_UNDEFS SET) + if (NOT _isSet) + set_property(TARGET ${_target} PROPERTY COTIRE_UNITY_SOURCE_POST_UNDEFS "") + endif() + get_property(_isSet TARGET ${_target} PROPERTY COTIRE_UNITY_LINK_LIBRARIES_INIT SET) + if (NOT _isSet) + set_property(TARGET ${_target} PROPERTY COTIRE_UNITY_LINK_LIBRARIES_INIT "COPY_UNITY") + endif() + get_property(_isSet TARGET ${_target} PROPERTY COTIRE_UNITY_SOURCE_MAXIMUM_NUMBER_OF_INCLUDES SET) + if (NOT _isSet) + if (COTIRE_MAXIMUM_NUMBER_OF_UNITY_INCLUDES) + set_property(TARGET ${_target} PROPERTY COTIRE_UNITY_SOURCE_MAXIMUM_NUMBER_OF_INCLUDES "${COTIRE_MAXIMUM_NUMBER_OF_UNITY_INCLUDES}") + else() + set_property(TARGET ${_target} PROPERTY COTIRE_UNITY_SOURCE_MAXIMUM_NUMBER_OF_INCLUDES "") + endif() + endif() +endfunction() + +function (cotire_make_target_message _target _languages _disableMsg _targetMsgVar) + get_target_property(_targetUsePCH ${_target} COTIRE_ENABLE_PRECOMPILED_HEADER) + get_target_property(_targetAddSCU ${_target} COTIRE_ADD_UNITY_BUILD) + string (REPLACE ";" " " _languagesStr "${_languages}") + math (EXPR _numberOfExcludedFiles "${ARGC} - 4") + if (_numberOfExcludedFiles EQUAL 0) + set (_excludedStr "") + elseif (COTIRE_VERBOSE OR _numberOfExcludedFiles LESS 4) + string (REPLACE ";" ", " _excludedStr "excluding ${ARGN}") + else() + set (_excludedStr "excluding ${_numberOfExcludedFiles} files") + endif() + set (_targetMsg "") + if (NOT _languages) + set (_targetMsg "Target ${_target} cannot be cotired.") + if (_disableMsg) + set (_targetMsg "${_targetMsg} ${_disableMsg}") + endif() + elseif (NOT _targetUsePCH AND NOT _targetAddSCU) + set (_targetMsg "${_languagesStr} target ${_target} cotired without unity build and precompiled header.") + if (_disableMsg) + set (_targetMsg "${_targetMsg} ${_disableMsg}") + endif() + elseif (NOT _targetUsePCH) + if (_excludedStr) + set (_targetMsg "${_languagesStr} target ${_target} cotired without precompiled header ${_excludedStr}.") + else() + set (_targetMsg "${_languagesStr} target ${_target} cotired without precompiled header.") + endif() + if (_disableMsg) + set (_targetMsg "${_targetMsg} ${_disableMsg}") + endif() + elseif (NOT _targetAddSCU) + if (_excludedStr) + set (_targetMsg "${_languagesStr} target ${_target} cotired without unity build ${_excludedStr}.") + else() + set (_targetMsg "${_languagesStr} target ${_target} cotired without unity build.") + endif() + else() + if (_excludedStr) + set (_targetMsg "${_languagesStr} target ${_target} cotired ${_excludedStr}.") + else() + set (_targetMsg "${_languagesStr} target ${_target} cotired.") + endif() + endif() + set (${_targetMsgVar} "${_targetMsg}" PARENT_SCOPE) +endfunction() + +function (cotire_choose_target_languages _target _targetLanguagesVar _wholeTargetVar) + set (_languages ${ARGN}) + set (_allSourceFiles "") + set (_allExcludedSourceFiles "") + set (_allCotiredSourceFiles "") + set (_targetLanguages "") + set (_pchEligibleTargetLanguages "") + get_target_property(_targetType ${_target} TYPE) + get_target_property(_targetSourceFiles ${_target} SOURCES) + get_target_property(_targetUsePCH ${_target} COTIRE_ENABLE_PRECOMPILED_HEADER) + get_target_property(_targetAddSCU ${_target} COTIRE_ADD_UNITY_BUILD) + set (_disableMsg "") + foreach (_language ${_languages}) + get_target_property(_prefixHeader ${_target} COTIRE_${_language}_PREFIX_HEADER) + get_target_property(_unityBuildFile ${_target} COTIRE_${_language}_UNITY_SOURCE) + if (_prefixHeader OR _unityBuildFile) + message (STATUS "cotire: target ${_target} has already been cotired.") + set (${_targetLanguagesVar} "" PARENT_SCOPE) + return() + endif() + if (_targetUsePCH AND "${_language}" MATCHES "^C|CXX$" AND DEFINED CMAKE_${_language}_COMPILER_ID) + if (CMAKE_${_language}_COMPILER_ID) + cotire_check_precompiled_header_support("${_language}" "${_target}" _disableMsg) + if (_disableMsg) + set (_targetUsePCH FALSE) + endif() + endif() + endif() + set (_sourceFiles "") + set (_excludedSources "") + set (_cotiredSources "") + cotire_filter_language_source_files(${_language} ${_target} _sourceFiles _excludedSources _cotiredSources ${_targetSourceFiles}) + if (_sourceFiles OR _excludedSources OR _cotiredSources) + list (APPEND _targetLanguages ${_language}) + endif() + if (_sourceFiles) + list (APPEND _allSourceFiles ${_sourceFiles}) + endif() + list (LENGTH _sourceFiles _numberOfSources) + if (NOT _numberOfSources LESS ${COTIRE_MINIMUM_NUMBER_OF_TARGET_SOURCES}) + list (APPEND _pchEligibleTargetLanguages ${_language}) + endif() + if (_excludedSources) + list (APPEND _allExcludedSourceFiles ${_excludedSources}) + endif() + if (_cotiredSources) + list (APPEND _allCotiredSourceFiles ${_cotiredSources}) + endif() + endforeach() + set (_targetMsgLevel STATUS) + if (NOT _targetLanguages) + string (REPLACE ";" " or " _languagesStr "${_languages}") + set (_disableMsg "No ${_languagesStr} source files.") + set (_targetUsePCH FALSE) + set (_targetAddSCU FALSE) + endif() + if (_targetUsePCH) + if (_allCotiredSourceFiles) + cotire_get_source_file_property_values(_cotireTargets COTIRE_TARGET ${_allCotiredSourceFiles}) + list (REMOVE_DUPLICATES _cotireTargets) + string (REPLACE ";" ", " _cotireTargetsStr "${_cotireTargets}") + set (_disableMsg "Target sources already include a precompiled header for target(s) ${_cotireTargets}.") + set (_disableMsg "${_disableMsg} Set target property COTIRE_ENABLE_PRECOMPILED_HEADER to FALSE for targets ${_target},") + set (_disableMsg "${_disableMsg} ${_cotireTargetsStr} to get a workable build system.") + set (_targetMsgLevel SEND_ERROR) + set (_targetUsePCH FALSE) + elseif (NOT _pchEligibleTargetLanguages) + set (_disableMsg "Too few applicable sources.") + set (_targetUsePCH FALSE) + elseif (XCODE AND _allExcludedSourceFiles) + # for Xcode, we cannot apply the precompiled header to individual sources, only to the whole target + set (_disableMsg "Exclusion of source files not supported for generator Xcode.") + set (_targetUsePCH FALSE) + elseif (XCODE AND "${_targetType}" STREQUAL "OBJECT_LIBRARY") + # for Xcode, we cannot apply the required PRE_BUILD action to generate the prefix header to an OBJECT_LIBRARY target + set (_disableMsg "Required PRE_BUILD action not supported for OBJECT_LIBRARY targets for generator Xcode.") + set (_targetUsePCH FALSE) + endif() + endif() + set_property(TARGET ${_target} PROPERTY COTIRE_ENABLE_PRECOMPILED_HEADER ${_targetUsePCH}) + set_property(TARGET ${_target} PROPERTY COTIRE_ADD_UNITY_BUILD ${_targetAddSCU}) + cotire_make_target_message(${_target} "${_targetLanguages}" "${_disableMsg}" _targetMsg ${_allExcludedSourceFiles}) + if (_targetMsg) + if (NOT DEFINED COTIREMSG_${_target}) + set (COTIREMSG_${_target} "") + endif() + if (COTIRE_VERBOSE OR NOT "${_targetMsgLevel}" STREQUAL "STATUS" OR + NOT "${COTIREMSG_${_target}}" STREQUAL "${_targetMsg}") + # cache message to avoid redundant messages on re-configure + set (COTIREMSG_${_target} "${_targetMsg}" CACHE INTERNAL "${_target} cotire message.") + message (${_targetMsgLevel} "${_targetMsg}") + endif() + endif() + list (LENGTH _targetLanguages _numberOfLanguages) + if (_numberOfLanguages GREATER 1 OR _allExcludedSourceFiles) + set (${_wholeTargetVar} FALSE PARENT_SCOPE) + else() + set (${_wholeTargetVar} TRUE PARENT_SCOPE) + endif() + set (${_targetLanguagesVar} ${_targetLanguages} PARENT_SCOPE) +endfunction() + +function (cotire_compute_unity_max_number_of_includes _target _maxIncludesVar) + set (_sourceFiles ${ARGN}) + get_target_property(_maxIncludes ${_target} COTIRE_UNITY_SOURCE_MAXIMUM_NUMBER_OF_INCLUDES) + if (_maxIncludes MATCHES "(-j|--parallel|--jobs) ?([0-9]*)") + set (_numberOfThreads "${CMAKE_MATCH_2}") + if (NOT _numberOfThreads) + # use all available cores + ProcessorCount(_numberOfThreads) + endif() + list (LENGTH _sourceFiles _numberOfSources) + math (EXPR _maxIncludes "(${_numberOfSources} + ${_numberOfThreads} - 1) / ${_numberOfThreads}") + elseif (NOT _maxIncludes MATCHES "[0-9]+") + set (_maxIncludes 0) + endif() + if (COTIRE_DEBUG) + message (STATUS "${_target} unity source max includes: ${_maxIncludes}") + endif() + set (${_maxIncludesVar} ${_maxIncludes} PARENT_SCOPE) +endfunction() + +function (cotire_process_target_language _language _configurations _target _wholeTarget _cmdsVar) + set (${_cmdsVar} "" PARENT_SCOPE) + get_target_property(_targetSourceFiles ${_target} SOURCES) + set (_sourceFiles "") + set (_excludedSources "") + set (_cotiredSources "") + cotire_filter_language_source_files(${_language} ${_target} _sourceFiles _excludedSources _cotiredSources ${_targetSourceFiles}) + if (NOT _sourceFiles AND NOT _cotiredSources) + return() + endif() + set (_cmds "") + # check for user provided unity source file list + get_property(_unitySourceFiles TARGET ${_target} PROPERTY COTIRE_${_language}_UNITY_SOURCE_INIT) + if (NOT _unitySourceFiles) + set (_unitySourceFiles ${_sourceFiles} ${_cotiredSources}) + endif() + cotire_generate_target_script( + ${_language} "${_configurations}" ${_target} _targetScript _targetConfigScript ${_unitySourceFiles}) + # set up unity files for parallel compilation + cotire_compute_unity_max_number_of_includes(${_target} _maxIncludes ${_unitySourceFiles}) + cotire_make_unity_source_file_paths(${_language} ${_target} ${_maxIncludes} _unityFiles ${_unitySourceFiles}) + list (LENGTH _unityFiles _numberOfUnityFiles) + if (_numberOfUnityFiles EQUAL 0) + return() + elseif (_numberOfUnityFiles GREATER 1) + cotire_setup_unity_generation_commands( + ${_language} ${_target} "${_targetScript}" "${_targetConfigScript}" "${_unityFiles}" _cmds ${_unitySourceFiles}) + endif() + # set up single unity file for prefix header generation + cotire_make_single_unity_source_file_path(${_language} ${_target} _unityFile) + cotire_setup_unity_generation_commands( + ${_language} ${_target} "${_targetScript}" "${_targetConfigScript}" "${_unityFile}" _cmds ${_unitySourceFiles}) + cotire_make_prefix_file_path(${_language} ${_target} _prefixFile) + # set up prefix header + if (_prefixFile) + # check for user provided prefix header files + get_property(_prefixHeaderFiles TARGET ${_target} PROPERTY COTIRE_${_language}_PREFIX_HEADER_INIT) + if (_prefixHeaderFiles) + cotire_setup_prefix_generation_from_provided_command( + ${_language} ${_target} "${_targetConfigScript}" "${_prefixFile}" _cmds ${_prefixHeaderFiles}) + else() + cotire_setup_prefix_generation_from_unity_command( + ${_language} ${_target} "${_targetConfigScript}" "${_prefixFile}" "${_unityFile}" _cmds ${_unitySourceFiles}) + endif() + # check if selected language has enough sources at all + list (LENGTH _sourceFiles _numberOfSources) + if (_numberOfSources LESS ${COTIRE_MINIMUM_NUMBER_OF_TARGET_SOURCES}) + set (_targetUsePCH FALSE) + else() + get_target_property(_targetUsePCH ${_target} COTIRE_ENABLE_PRECOMPILED_HEADER) + endif() + if (_targetUsePCH) + cotire_make_pch_file_path(${_language} ${_target} _pchFile) + if (_pchFile) + # first file in _sourceFiles is passed as the host file + cotire_setup_pch_file_compilation( + ${_language} ${_target} "${_targetConfigScript}" "${_prefixFile}" "${_pchFile}" ${_sourceFiles}) + cotire_setup_pch_file_inclusion( + ${_language} ${_target} ${_wholeTarget} "${_prefixFile}" "${_pchFile}" ${_sourceFiles}) + endif() + elseif (_prefixHeaderFiles) + # user provided prefix header must be included unconditionally + cotire_setup_prefix_file_inclusion(${_language} ${_target} "${_prefixFile}" ${_sourceFiles}) + endif() + endif() + # mark target as cotired for language + set_property(TARGET ${_target} PROPERTY COTIRE_${_language}_UNITY_SOURCE "${_unityFiles}") + if (_prefixFile) + set_property(TARGET ${_target} PROPERTY COTIRE_${_language}_PREFIX_HEADER "${_prefixFile}") + if (_targetUsePCH AND _pchFile) + set_property(TARGET ${_target} PROPERTY COTIRE_${_language}_PRECOMPILED_HEADER "${_pchFile}") + endif() + endif() + set (${_cmdsVar} ${_cmds} PARENT_SCOPE) +endfunction() + +function (cotire_setup_clean_target _target) + set (_cleanTargetName "${_target}${COTIRE_CLEAN_TARGET_SUFFIX}") + if (NOT TARGET "${_cleanTargetName}") + cotire_set_cmd_to_prologue(_cmds) + get_filename_component(_outputDir "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}" ABSOLUTE) + list (APPEND _cmds -P "${COTIRE_CMAKE_MODULE_FILE}" "cleanup" "${_outputDir}" "${COTIRE_INTDIR}" "${_target}") + add_custom_target(${_cleanTargetName} + COMMAND ${_cmds} + WORKING_DIRECTORY "${CMAKE_BINARY_DIR}" + COMMENT "Cleaning up target ${_target} cotire generated files" + VERBATIM) + cotire_init_target("${_cleanTargetName}") + endif() +endfunction() + +function (cotire_setup_pch_target _languages _configurations _target) + if ("${CMAKE_GENERATOR}" MATCHES "Make|Ninja") + # for makefile based generators, we add a custom target to trigger the generation of the cotire related files + set (_dependsFiles "") + foreach (_language ${_languages}) + set (_props COTIRE_${_language}_PREFIX_HEADER COTIRE_${_language}_UNITY_SOURCE) + if (NOT CMAKE_${_language}_COMPILER_ID MATCHES "MSVC|Intel") + # Visual Studio and Intel only create precompiled header as a side effect + list (INSERT _props 0 COTIRE_${_language}_PRECOMPILED_HEADER) + endif() + cotire_get_first_set_property_value(_dependsFile TARGET ${_target} ${_props}) + if (_dependsFile) + list (APPEND _dependsFiles "${_dependsFile}") + endif() + endforeach() + if (_dependsFiles) + set (_pchTargetName "${_target}${COTIRE_PCH_TARGET_SUFFIX}") + add_custom_target("${_pchTargetName}" DEPENDS ${_dependsFiles}) + cotire_init_target("${_pchTargetName}") + cotire_add_to_pch_all_target(${_pchTargetName}) + endif() + else() + # for other generators, we add the "clean all" target to clean up the precompiled header + cotire_setup_clean_all_target() + endif() +endfunction() + +function (cotire_filter_object_libraries _target _objectLibrariesVar) + set (_objectLibraries "") + foreach (_source ${ARGN}) + if (_source MATCHES "^\\$$") + list (APPEND _objectLibraries "${_source}") + endif() + endforeach() + set (${_objectLibrariesVar} ${_objectLibraries} PARENT_SCOPE) +endfunction() + +function (cotire_collect_unity_target_sources _target _languages _unityTargetSourcesVar) + get_target_property(_targetSourceFiles ${_target} SOURCES) + set (_unityTargetSources ${_targetSourceFiles}) + foreach (_language ${_languages}) + get_property(_unityFiles TARGET ${_target} PROPERTY COTIRE_${_language}_UNITY_SOURCE) + if (_unityFiles) + # remove source files that are included in the unity source + set (_sourceFiles "") + set (_excludedSources "") + set (_cotiredSources "") + cotire_filter_language_source_files(${_language} ${_target} _sourceFiles _excludedSources _cotiredSources ${_targetSourceFiles}) + if (_sourceFiles OR _cotiredSources) + list (REMOVE_ITEM _unityTargetSources ${_sourceFiles} ${_cotiredSources}) + endif() + # add unity source files instead + list (APPEND _unityTargetSources ${_unityFiles}) + endif() + endforeach() + get_target_property(_linkLibrariesStrategy ${_target} COTIRE_UNITY_LINK_LIBRARIES_INIT) + if ("${_linkLibrariesStrategy}" MATCHES "^COPY_UNITY$") + cotire_filter_object_libraries(${_target} _objectLibraries ${_targetSourceFiles}) + if (_objectLibraries) + cotire_map_libraries("${_linkLibrariesStrategy}" _unityObjectLibraries ${_objectLibraries}) + list (REMOVE_ITEM _unityTargetSources ${_objectLibraries}) + list (APPEND _unityTargetSources ${_unityObjectLibraries}) + endif() + endif() + set (${_unityTargetSourcesVar} ${_unityTargetSources} PARENT_SCOPE) +endfunction() + +function (cotire_setup_unity_target_pch_usage _languages _target) + foreach (_language ${_languages}) + get_property(_unityFiles TARGET ${_target} PROPERTY COTIRE_${_language}_UNITY_SOURCE) + if (_unityFiles) + get_property(_userPrefixFile TARGET ${_target} PROPERTY COTIRE_${_language}_PREFIX_HEADER_INIT) + get_property(_prefixFile TARGET ${_target} PROPERTY COTIRE_${_language}_PREFIX_HEADER) + if (_userPrefixFile AND _prefixFile) + # user provided prefix header must be included unconditionally by unity sources + cotire_setup_prefix_file_inclusion(${_language} ${_target} "${_prefixFile}" ${_unityFiles}) + endif() + endif() + endforeach() +endfunction() + +function (cotire_setup_unity_build_target _languages _configurations _target) + get_target_property(_unityTargetName ${_target} COTIRE_UNITY_TARGET_NAME) + if (NOT _unityTargetName) + set (_unityTargetName "${_target}${COTIRE_UNITY_BUILD_TARGET_SUFFIX}") + endif() + # determine unity target sub type + get_target_property(_targetType ${_target} TYPE) + if ("${_targetType}" STREQUAL "EXECUTABLE") + set (_unityTargetSubType "") + elseif (_targetType MATCHES "(STATIC|SHARED|MODULE|OBJECT)_LIBRARY") + set (_unityTargetSubType "${CMAKE_MATCH_1}") + else() + message (WARNING "cotire: target ${_target} has unknown target type ${_targetType}.") + return() + endif() + # determine unity target sources + set (_unityTargetSources "") + cotire_collect_unity_target_sources(${_target} "${_languages}" _unityTargetSources) + # handle automatic Qt processing + get_target_property(_targetAutoMoc ${_target} AUTOMOC) + get_target_property(_targetAutoUic ${_target} AUTOUIC) + get_target_property(_targetAutoRcc ${_target} AUTORCC) + if (_targetAutoMoc OR _targetAutoUic OR _targetAutoRcc) + # if the original target sources are subject to CMake's automatic Qt processing, + # also include implicitly generated _automoc.cpp file + list (APPEND _unityTargetSources "${_target}_automoc.cpp") + set_property (SOURCE "${_target}_automoc.cpp" PROPERTY GENERATED TRUE) + endif() + # prevent AUTOMOC, AUTOUIC and AUTORCC properties from being set when the unity target is created + set (CMAKE_AUTOMOC OFF) + set (CMAKE_AUTOUIC OFF) + set (CMAKE_AUTORCC OFF) + if (COTIRE_DEBUG) + message (STATUS "add target ${_targetType} ${_unityTargetName} ${_unityTargetSubType} EXCLUDE_FROM_ALL ${_unityTargetSources}") + endif() + # generate unity target + if ("${_targetType}" STREQUAL "EXECUTABLE") + add_executable(${_unityTargetName} ${_unityTargetSubType} EXCLUDE_FROM_ALL ${_unityTargetSources}) + else() + add_library(${_unityTargetName} ${_unityTargetSubType} EXCLUDE_FROM_ALL ${_unityTargetSources}) + endif() + if ("${CMAKE_GENERATOR}" MATCHES "Visual Studio") + # depend on original target's automoc target, if it exists + if (TARGET ${_target}_automoc) + add_dependencies(${_unityTargetName} ${_target}_automoc) + endif() + else() + if (_targetAutoMoc OR _targetAutoUic OR _targetAutoRcc) + # depend on the original target's implicity generated _automoc target + add_dependencies(${_unityTargetName} ${_target}_automoc) + endif() + endif() + # copy output location properties + set (_outputDirProperties + ARCHIVE_OUTPUT_DIRECTORY ARCHIVE_OUTPUT_DIRECTORY_ + LIBRARY_OUTPUT_DIRECTORY LIBRARY_OUTPUT_DIRECTORY_ + RUNTIME_OUTPUT_DIRECTORY RUNTIME_OUTPUT_DIRECTORY_) + if (COTIRE_UNITY_OUTPUT_DIRECTORY) + set (_setDefaultOutputDir TRUE) + if (IS_ABSOLUTE "${COTIRE_UNITY_OUTPUT_DIRECTORY}") + set (_outputDir "${COTIRE_UNITY_OUTPUT_DIRECTORY}") + else() + # append relative COTIRE_UNITY_OUTPUT_DIRECTORY to target's actual output directory + cotire_copy_set_properites("${_configurations}" TARGET ${_target} ${_unityTargetName} ${_outputDirProperties}) + cotire_resolve_config_properites("${_configurations}" _properties ${_outputDirProperties}) + foreach (_property ${_properties}) + get_property(_outputDir TARGET ${_target} PROPERTY ${_property}) + if (_outputDir) + get_filename_component(_outputDir "${_outputDir}/${COTIRE_UNITY_OUTPUT_DIRECTORY}" ABSOLUTE) + set_property(TARGET ${_unityTargetName} PROPERTY ${_property} "${_outputDir}") + set (_setDefaultOutputDir FALSE) + endif() + endforeach() + if (_setDefaultOutputDir) + get_filename_component(_outputDir "${CMAKE_CURRENT_BINARY_DIR}/${COTIRE_UNITY_OUTPUT_DIRECTORY}" ABSOLUTE) + endif() + endif() + if (_setDefaultOutputDir) + set_target_properties(${_unityTargetName} PROPERTIES + ARCHIVE_OUTPUT_DIRECTORY "${_outputDir}" + LIBRARY_OUTPUT_DIRECTORY "${_outputDir}" + RUNTIME_OUTPUT_DIRECTORY "${_outputDir}") + endif() + else() + cotire_copy_set_properites("${_configurations}" TARGET ${_target} ${_unityTargetName} + ${_outputDirProperties}) + endif() + # copy output name + cotire_copy_set_properites("${_configurations}" TARGET ${_target} ${_unityTargetName} + ARCHIVE_OUTPUT_NAME ARCHIVE_OUTPUT_NAME_ + LIBRARY_OUTPUT_NAME LIBRARY_OUTPUT_NAME_ + OUTPUT_NAME OUTPUT_NAME_ + RUNTIME_OUTPUT_NAME RUNTIME_OUTPUT_NAME_ + PREFIX _POSTFIX SUFFIX + IMPORT_PREFIX IMPORT_SUFFIX) + # copy compile stuff + cotire_copy_set_properites("${_configurations}" TARGET ${_target} ${_unityTargetName} + COMPILE_DEFINITIONS COMPILE_DEFINITIONS_ + COMPILE_FLAGS COMPILE_OPTIONS + Fortran_FORMAT Fortran_MODULE_DIRECTORY + INCLUDE_DIRECTORIES + INTERPROCEDURAL_OPTIMIZATION INTERPROCEDURAL_OPTIMIZATION_ + POSITION_INDEPENDENT_CODE + C_COMPILER_LAUNCHER CXX_COMPILER_LAUNCHER + C_INCLUDE_WHAT_YOU_USE CXX_INCLUDE_WHAT_YOU_USE + C_VISIBILITY_PRESET CXX_VISIBILITY_PRESET VISIBILITY_INLINES_HIDDEN + C_CLANG_TIDY CXX_CLANG_TIDY) + # copy compile features + cotire_copy_set_properites("${_configurations}" TARGET ${_target} ${_unityTargetName} + C_EXTENSIONS C_STANDARD C_STANDARD_REQUIRED + CXX_EXTENSIONS CXX_STANDARD CXX_STANDARD_REQUIRED + COMPILE_FEATURES) + # copy interface stuff + cotire_copy_set_properites("${_configurations}" TARGET ${_target} ${_unityTargetName} + COMPATIBLE_INTERFACE_BOOL COMPATIBLE_INTERFACE_NUMBER_MAX COMPATIBLE_INTERFACE_NUMBER_MIN + COMPATIBLE_INTERFACE_STRING + INTERFACE_COMPILE_DEFINITIONS INTERFACE_COMPILE_FEATURES INTERFACE_COMPILE_OPTIONS + INTERFACE_INCLUDE_DIRECTORIES INTERFACE_SOURCES + INTERFACE_POSITION_INDEPENDENT_CODE INTERFACE_SYSTEM_INCLUDE_DIRECTORIES + INTERFACE_AUTOUIC_OPTIONS NO_SYSTEM_FROM_IMPORTED) + # copy link stuff + cotire_copy_set_properites("${_configurations}" TARGET ${_target} ${_unityTargetName} + BUILD_WITH_INSTALL_RPATH INSTALL_RPATH INSTALL_RPATH_USE_LINK_PATH SKIP_BUILD_RPATH + LINKER_LANGUAGE LINK_DEPENDS LINK_DEPENDS_NO_SHARED + LINK_FLAGS LINK_FLAGS_ + LINK_INTERFACE_LIBRARIES LINK_INTERFACE_LIBRARIES_ + LINK_INTERFACE_MULTIPLICITY LINK_INTERFACE_MULTIPLICITY_ + LINK_SEARCH_START_STATIC LINK_SEARCH_END_STATIC + STATIC_LIBRARY_FLAGS STATIC_LIBRARY_FLAGS_ + NO_SONAME SOVERSION VERSION + LINK_WHAT_YOU_USE) + # copy cmake stuff + cotire_copy_set_properites("${_configurations}" TARGET ${_target} ${_unityTargetName} + IMPLICIT_DEPENDS_INCLUDE_TRANSFORM RULE_LAUNCH_COMPILE RULE_LAUNCH_CUSTOM RULE_LAUNCH_LINK) + # copy Apple platform specific stuff + cotire_copy_set_properites("${_configurations}" TARGET ${_target} ${_unityTargetName} + BUNDLE BUNDLE_EXTENSION FRAMEWORK FRAMEWORK_VERSION INSTALL_NAME_DIR + MACOSX_BUNDLE MACOSX_BUNDLE_INFO_PLIST MACOSX_FRAMEWORK_INFO_PLIST MACOSX_RPATH + OSX_ARCHITECTURES OSX_ARCHITECTURES_ PRIVATE_HEADER PUBLIC_HEADER RESOURCE XCTEST + IOS_INSTALL_COMBINED) + # copy Windows platform specific stuff + cotire_copy_set_properites("${_configurations}" TARGET ${_target} ${_unityTargetName} + GNUtoMS + COMPILE_PDB_NAME COMPILE_PDB_NAME_ + COMPILE_PDB_OUTPUT_DIRECTORY COMPILE_PDB_OUTPUT_DIRECTORY_ + PDB_NAME PDB_NAME_ PDB_OUTPUT_DIRECTORY PDB_OUTPUT_DIRECTORY_ + VS_DESKTOP_EXTENSIONS_VERSION VS_DOTNET_REFERENCES VS_DOTNET_TARGET_FRAMEWORK_VERSION + VS_GLOBAL_KEYWORD VS_GLOBAL_PROJECT_TYPES VS_GLOBAL_ROOTNAMESPACE + VS_IOT_EXTENSIONS_VERSION VS_IOT_STARTUP_TASK + VS_KEYWORD VS_MOBILE_EXTENSIONS_VERSION + VS_SCC_AUXPATH VS_SCC_LOCALPATH VS_SCC_PROJECTNAME VS_SCC_PROVIDER + VS_WINDOWS_TARGET_PLATFORM_MIN_VERSION + VS_WINRT_COMPONENT VS_WINRT_EXTENSIONS VS_WINRT_REFERENCES + WIN32_EXECUTABLE WINDOWS_EXPORT_ALL_SYMBOLS + DEPLOYMENT_REMOTE_DIRECTORY VS_CONFIGURATION_TYPE + VS_SDK_REFERENCES) + # copy Android platform specific stuff + cotire_copy_set_properites("${_configurations}" TARGET ${_target} ${_unityTargetName} + ANDROID_API ANDROID_API_MIN ANDROID_GUI + ANDROID_ANT_ADDITIONAL_OPTIONS ANDROID_ARCH ANDROID_ASSETS_DIRECTORIES + ANDROID_JAR_DEPENDENCIES ANDROID_JAR_DIRECTORIES ANDROID_JAVA_SOURCE_DIR + ANDROID_NATIVE_LIB_DEPENDENCIES ANDROID_NATIVE_LIB_DIRECTORIES + ANDROID_PROCESS_MAX ANDROID_PROGUARD ANDROID_PROGUARD_CONFIG_PATH + ANDROID_SECURE_PROPS_PATH ANDROID_SKIP_ANT_STEP ANDROID_STL_TYPE) + # use output name from original target + get_target_property(_targetOutputName ${_unityTargetName} OUTPUT_NAME) + if (NOT _targetOutputName) + set_property(TARGET ${_unityTargetName} PROPERTY OUTPUT_NAME "${_target}") + endif() + # use export symbol from original target + cotire_get_target_export_symbol("${_target}" _defineSymbol) + if (_defineSymbol) + set_property(TARGET ${_unityTargetName} PROPERTY DEFINE_SYMBOL "${_defineSymbol}") + if ("${_targetType}" STREQUAL "EXECUTABLE") + set_property(TARGET ${_unityTargetName} PROPERTY ENABLE_EXPORTS TRUE) + endif() + endif() + cotire_init_target(${_unityTargetName}) + cotire_add_to_unity_all_target(${_unityTargetName}) + set_property(TARGET ${_target} PROPERTY COTIRE_UNITY_TARGET_NAME "${_unityTargetName}") +endfunction(cotire_setup_unity_build_target) + +function (cotire_target _target) + set(_options "") + set(_oneValueArgs "") + set(_multiValueArgs LANGUAGES CONFIGURATIONS) + cmake_parse_arguments(_option "${_options}" "${_oneValueArgs}" "${_multiValueArgs}" ${ARGN}) + if (NOT _option_LANGUAGES) + get_property (_option_LANGUAGES GLOBAL PROPERTY ENABLED_LANGUAGES) + endif() + if (NOT _option_CONFIGURATIONS) + cotire_get_configuration_types(_option_CONFIGURATIONS) + endif() + # check if cotire can be applied to target at all + cotire_is_target_supported(${_target} _isSupported) + if (NOT _isSupported) + get_target_property(_imported ${_target} IMPORTED) + get_target_property(_targetType ${_target} TYPE) + if (_imported) + message (WARNING "cotire: imported ${_targetType} target ${_target} cannot be cotired.") + else() + message (STATUS "cotire: ${_targetType} target ${_target} cannot be cotired.") + endif() + return() + endif() + # resolve alias + get_target_property(_aliasName ${_target} ALIASED_TARGET) + if (_aliasName) + if (COTIRE_DEBUG) + message (STATUS "${_target} is an alias. Applying cotire to aliased target ${_aliasName} instead.") + endif() + set (_target ${_aliasName}) + endif() + # check if target needs to be cotired for build type + # when using configuration types, the test is performed at build time + cotire_init_cotire_target_properties(${_target}) + if (NOT CMAKE_CONFIGURATION_TYPES) + if (CMAKE_BUILD_TYPE) + list (FIND _option_CONFIGURATIONS "${CMAKE_BUILD_TYPE}" _index) + else() + list (FIND _option_CONFIGURATIONS "None" _index) + endif() + if (_index EQUAL -1) + if (COTIRE_DEBUG) + message (STATUS "CMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} not cotired (${_option_CONFIGURATIONS})") + endif() + return() + endif() + endif() + # when not using configuration types, immediately create cotire intermediate dir + if (NOT CMAKE_CONFIGURATION_TYPES) + cotire_get_intermediate_dir(_baseDir) + file (MAKE_DIRECTORY "${_baseDir}") + endif() + # choose languages that apply to the target + cotire_choose_target_languages("${_target}" _targetLanguages _wholeTarget ${_option_LANGUAGES}) + if (NOT _targetLanguages) + return() + endif() + set (_cmds "") + foreach (_language ${_targetLanguages}) + cotire_process_target_language("${_language}" "${_option_CONFIGURATIONS}" ${_target} ${_wholeTarget} _cmd) + if (_cmd) + list (APPEND _cmds ${_cmd}) + endif() + endforeach() + get_target_property(_targetAddSCU ${_target} COTIRE_ADD_UNITY_BUILD) + if (_targetAddSCU) + cotire_setup_unity_build_target("${_targetLanguages}" "${_option_CONFIGURATIONS}" ${_target}) + endif() + get_target_property(_targetUsePCH ${_target} COTIRE_ENABLE_PRECOMPILED_HEADER) + if (_targetUsePCH) + cotire_setup_target_pch_usage("${_targetLanguages}" ${_target} ${_wholeTarget} ${_cmds}) + cotire_setup_pch_target("${_targetLanguages}" "${_option_CONFIGURATIONS}" ${_target}) + if (_targetAddSCU) + cotire_setup_unity_target_pch_usage("${_targetLanguages}" ${_target}) + endif() + endif() + get_target_property(_targetAddCleanTarget ${_target} COTIRE_ADD_CLEAN) + if (_targetAddCleanTarget) + cotire_setup_clean_target(${_target}) + endif() +endfunction(cotire_target) + +function (cotire_map_libraries _strategy _mappedLibrariesVar) + set (_mappedLibraries "") + foreach (_library ${ARGN}) + if (_library MATCHES "^\\$$") + set (_libraryName "${CMAKE_MATCH_1}") + set (_linkOnly TRUE) + set (_objectLibrary FALSE) + elseif (_library MATCHES "^\\$$") + set (_libraryName "${CMAKE_MATCH_1}") + set (_linkOnly FALSE) + set (_objectLibrary TRUE) + else() + set (_libraryName "${_library}") + set (_linkOnly FALSE) + set (_objectLibrary FALSE) + endif() + if ("${_strategy}" MATCHES "COPY_UNITY") + cotire_is_target_supported(${_libraryName} _isSupported) + if (_isSupported) + # use target's corresponding unity target, if available + get_target_property(_libraryUnityTargetName ${_libraryName} COTIRE_UNITY_TARGET_NAME) + if (TARGET "${_libraryUnityTargetName}") + if (_linkOnly) + list (APPEND _mappedLibraries "$") + elseif (_objectLibrary) + list (APPEND _mappedLibraries "$") + else() + list (APPEND _mappedLibraries "${_libraryUnityTargetName}") + endif() + else() + list (APPEND _mappedLibraries "${_library}") + endif() + else() + list (APPEND _mappedLibraries "${_library}") + endif() + else() + list (APPEND _mappedLibraries "${_library}") + endif() + endforeach() + list (REMOVE_DUPLICATES _mappedLibraries) + set (${_mappedLibrariesVar} ${_mappedLibraries} PARENT_SCOPE) +endfunction() + +function (cotire_target_link_libraries _target) + cotire_is_target_supported(${_target} _isSupported) + if (NOT _isSupported) + return() + endif() + get_target_property(_unityTargetName ${_target} COTIRE_UNITY_TARGET_NAME) + if (TARGET "${_unityTargetName}") + get_target_property(_linkLibrariesStrategy ${_target} COTIRE_UNITY_LINK_LIBRARIES_INIT) + if (COTIRE_DEBUG) + message (STATUS "unity target ${_unityTargetName} link strategy: ${_linkLibrariesStrategy}") + endif() + if ("${_linkLibrariesStrategy}" MATCHES "^(COPY|COPY_UNITY)$") + get_target_property(_linkLibraries ${_target} LINK_LIBRARIES) + if (_linkLibraries) + cotire_map_libraries("${_linkLibrariesStrategy}" _unityLinkLibraries ${_linkLibraries}) + set_target_properties(${_unityTargetName} PROPERTIES LINK_LIBRARIES "${_unityLinkLibraries}") + if (COTIRE_DEBUG) + message (STATUS "unity target ${_unityTargetName} link libraries: ${_unityLinkLibraries}") + endif() + endif() + get_target_property(_interfaceLinkLibraries ${_target} INTERFACE_LINK_LIBRARIES) + if (_interfaceLinkLibraries) + cotire_map_libraries("${_linkLibrariesStrategy}" _unityLinkInterfaceLibraries ${_interfaceLinkLibraries}) + set_target_properties(${_unityTargetName} PROPERTIES INTERFACE_LINK_LIBRARIES "${_unityLinkInterfaceLibraries}") + if (COTIRE_DEBUG) + message (STATUS "unity target ${_unityTargetName} interface link libraries: ${_unityLinkInterfaceLibraries}") + endif() + endif() + endif() + endif() +endfunction(cotire_target_link_libraries) + +function (cotire_cleanup _binaryDir _cotireIntermediateDirName _targetName) + if (_targetName) + file (GLOB_RECURSE _cotireFiles "${_binaryDir}/${_targetName}*.*") + else() + file (GLOB_RECURSE _cotireFiles "${_binaryDir}/*.*") + endif() + # filter files in intermediate directory + set (_filesToRemove "") + foreach (_file ${_cotireFiles}) + get_filename_component(_dir "${_file}" DIRECTORY) + get_filename_component(_dirName "${_dir}" NAME) + if ("${_dirName}" STREQUAL "${_cotireIntermediateDirName}") + list (APPEND _filesToRemove "${_file}") + endif() + endforeach() + if (_filesToRemove) + if (COTIRE_VERBOSE) + message (STATUS "cleaning up ${_filesToRemove}") + endif() + file (REMOVE ${_filesToRemove}) + endif() +endfunction() + +function (cotire_init_target _targetName) + if (COTIRE_TARGETS_FOLDER) + set_target_properties(${_targetName} PROPERTIES FOLDER "${COTIRE_TARGETS_FOLDER}") + endif() + set_target_properties(${_targetName} PROPERTIES EXCLUDE_FROM_ALL TRUE) + if (MSVC_IDE) + set_target_properties(${_targetName} PROPERTIES EXCLUDE_FROM_DEFAULT_BUILD TRUE) + endif() +endfunction() + +function (cotire_add_to_pch_all_target _pchTargetName) + set (_targetName "${COTIRE_PCH_ALL_TARGET_NAME}") + if (NOT TARGET "${_targetName}") + add_custom_target("${_targetName}" + WORKING_DIRECTORY "${CMAKE_BINARY_DIR}" + VERBATIM) + cotire_init_target("${_targetName}") + endif() + cotire_setup_clean_all_target() + add_dependencies(${_targetName} ${_pchTargetName}) +endfunction() + +function (cotire_add_to_unity_all_target _unityTargetName) + set (_targetName "${COTIRE_UNITY_BUILD_ALL_TARGET_NAME}") + if (NOT TARGET "${_targetName}") + add_custom_target("${_targetName}" + WORKING_DIRECTORY "${CMAKE_BINARY_DIR}" + VERBATIM) + cotire_init_target("${_targetName}") + endif() + cotire_setup_clean_all_target() + add_dependencies(${_targetName} ${_unityTargetName}) +endfunction() + +function (cotire_setup_clean_all_target) + set (_targetName "${COTIRE_CLEAN_ALL_TARGET_NAME}") + if (NOT TARGET "${_targetName}") + cotire_set_cmd_to_prologue(_cmds) + list (APPEND _cmds -P "${COTIRE_CMAKE_MODULE_FILE}" "cleanup" "${CMAKE_BINARY_DIR}" "${COTIRE_INTDIR}") + add_custom_target(${_targetName} + COMMAND ${_cmds} + WORKING_DIRECTORY "${CMAKE_BINARY_DIR}" + COMMENT "Cleaning up all cotire generated files" + VERBATIM) + cotire_init_target("${_targetName}") + endif() +endfunction() + +function (cotire) + set(_options "") + set(_oneValueArgs "") + set(_multiValueArgs LANGUAGES CONFIGURATIONS) + cmake_parse_arguments(_option "${_options}" "${_oneValueArgs}" "${_multiValueArgs}" ${ARGN}) + set (_targets ${_option_UNPARSED_ARGUMENTS}) + foreach (_target ${_targets}) + if (TARGET ${_target}) + cotire_target(${_target} LANGUAGES ${_option_LANGUAGES} CONFIGURATIONS ${_option_CONFIGURATIONS}) + else() + message (WARNING "cotire: ${_target} is not a target.") + endif() + endforeach() + foreach (_target ${_targets}) + if (TARGET ${_target}) + cotire_target_link_libraries(${_target}) + endif() + endforeach() +endfunction() + +if (CMAKE_SCRIPT_MODE_FILE) + + # cotire is being run in script mode + # locate -P on command args + set (COTIRE_ARGC -1) + foreach (_index RANGE ${CMAKE_ARGC}) + if (COTIRE_ARGC GREATER -1) + set (COTIRE_ARGV${COTIRE_ARGC} "${CMAKE_ARGV${_index}}") + math (EXPR COTIRE_ARGC "${COTIRE_ARGC} + 1") + elseif ("${CMAKE_ARGV${_index}}" STREQUAL "-P") + set (COTIRE_ARGC 0) + endif() + endforeach() + + # include target script if available + if ("${COTIRE_ARGV2}" MATCHES "\\.cmake$") + # the included target scripts sets up additional variables relating to the target (e.g., COTIRE_TARGET_SOURCES) + include("${COTIRE_ARGV2}") + endif() + + if (COTIRE_DEBUG) + message (STATUS "${COTIRE_ARGV0} ${COTIRE_ARGV1} ${COTIRE_ARGV2} ${COTIRE_ARGV3} ${COTIRE_ARGV4} ${COTIRE_ARGV5}") + endif() + + if (NOT COTIRE_BUILD_TYPE) + set (COTIRE_BUILD_TYPE "None") + endif() + string (TOUPPER "${COTIRE_BUILD_TYPE}" _upperConfig) + set (_includeDirs ${COTIRE_TARGET_INCLUDE_DIRECTORIES_${_upperConfig}}) + set (_systemIncludeDirs ${COTIRE_TARGET_SYSTEM_INCLUDE_DIRECTORIES_${_upperConfig}}) + set (_compileDefinitions ${COTIRE_TARGET_COMPILE_DEFINITIONS_${_upperConfig}}) + set (_compileFlags ${COTIRE_TARGET_COMPILE_FLAGS_${_upperConfig}}) + # check if target has been cotired for actual build type COTIRE_BUILD_TYPE + list (FIND COTIRE_TARGET_CONFIGURATION_TYPES "${COTIRE_BUILD_TYPE}" _index) + if (_index GREATER -1) + set (_sources ${COTIRE_TARGET_SOURCES}) + set (_sourcesDefinitions ${COTIRE_TARGET_SOURCES_COMPILE_DEFINITIONS_${_upperConfig}}) + else() + if (COTIRE_DEBUG) + message (STATUS "COTIRE_BUILD_TYPE=${COTIRE_BUILD_TYPE} not cotired (${COTIRE_TARGET_CONFIGURATION_TYPES})") + endif() + set (_sources "") + set (_sourcesDefinitions "") + endif() + set (_targetPreUndefs ${COTIRE_TARGET_PRE_UNDEFS}) + set (_targetPostUndefs ${COTIRE_TARGET_POST_UNDEFS}) + set (_sourcesPreUndefs ${COTIRE_TARGET_SOURCES_PRE_UNDEFS}) + set (_sourcesPostUndefs ${COTIRE_TARGET_SOURCES_POST_UNDEFS}) + + if ("${COTIRE_ARGV1}" STREQUAL "unity") + + if (XCODE) + # executing pre-build action under Xcode, check dependency on target script + set (_dependsOption DEPENDS "${COTIRE_ARGV2}") + else() + # executing custom command, no need to re-check for dependencies + set (_dependsOption "") + endif() + + cotire_select_unity_source_files("${COTIRE_ARGV3}" _sources ${_sources}) + + cotire_generate_unity_source( + "${COTIRE_ARGV3}" ${_sources} + LANGUAGE "${COTIRE_TARGET_LANGUAGE}" + SOURCES_COMPILE_DEFINITIONS ${_sourcesDefinitions} + PRE_UNDEFS ${_targetPreUndefs} + POST_UNDEFS ${_targetPostUndefs} + SOURCES_PRE_UNDEFS ${_sourcesPreUndefs} + SOURCES_POST_UNDEFS ${_sourcesPostUndefs} + ${_dependsOption}) + + elseif ("${COTIRE_ARGV1}" STREQUAL "prefix") + + if (XCODE) + # executing pre-build action under Xcode, check dependency on unity file and prefix dependencies + set (_dependsOption DEPENDS "${COTIRE_ARGV4}" ${COTIRE_TARGET_PREFIX_DEPENDS}) + else() + # executing custom command, no need to re-check for dependencies + set (_dependsOption "") + endif() + + set (_files "") + foreach (_index RANGE 4 ${COTIRE_ARGC}) + if (COTIRE_ARGV${_index}) + list (APPEND _files "${COTIRE_ARGV${_index}}") + endif() + endforeach() + + cotire_generate_prefix_header( + "${COTIRE_ARGV3}" ${_files} + COMPILER_LAUNCHER "${COTIRE_TARGET_${COTIRE_TARGET_LANGUAGE}_COMPILER_LAUNCHER}" + COMPILER_EXECUTABLE "${CMAKE_${COTIRE_TARGET_LANGUAGE}_COMPILER}" + COMPILER_ARG1 ${CMAKE_${COTIRE_TARGET_LANGUAGE}_COMPILER_ARG1} + COMPILER_ID "${CMAKE_${COTIRE_TARGET_LANGUAGE}_COMPILER_ID}" + COMPILER_VERSION "${CMAKE_${COTIRE_TARGET_LANGUAGE}_COMPILER_VERSION}" + LANGUAGE "${COTIRE_TARGET_LANGUAGE}" + IGNORE_PATH "${COTIRE_TARGET_IGNORE_PATH};${COTIRE_ADDITIONAL_PREFIX_HEADER_IGNORE_PATH}" + INCLUDE_PATH ${COTIRE_TARGET_INCLUDE_PATH} + IGNORE_EXTENSIONS "${CMAKE_${COTIRE_TARGET_LANGUAGE}_SOURCE_FILE_EXTENSIONS};${COTIRE_ADDITIONAL_PREFIX_HEADER_IGNORE_EXTENSIONS}" + INCLUDE_PRIORITY_PATH ${COTIRE_TARGET_INCLUDE_PRIORITY_PATH} + INCLUDE_DIRECTORIES ${_includeDirs} + SYSTEM_INCLUDE_DIRECTORIES ${_systemIncludeDirs} + COMPILE_DEFINITIONS ${_compileDefinitions} + COMPILE_FLAGS ${_compileFlags} + ${_dependsOption}) + + elseif ("${COTIRE_ARGV1}" STREQUAL "precompile") + + set (_files "") + foreach (_index RANGE 5 ${COTIRE_ARGC}) + if (COTIRE_ARGV${_index}) + list (APPEND _files "${COTIRE_ARGV${_index}}") + endif() + endforeach() + + cotire_precompile_prefix_header( + "${COTIRE_ARGV3}" "${COTIRE_ARGV4}" "${COTIRE_ARGV5}" + COMPILER_LAUNCHER "${COTIRE_TARGET_${COTIRE_TARGET_LANGUAGE}_COMPILER_LAUNCHER}" + COMPILER_EXECUTABLE "${CMAKE_${COTIRE_TARGET_LANGUAGE}_COMPILER}" + COMPILER_ARG1 ${CMAKE_${COTIRE_TARGET_LANGUAGE}_COMPILER_ARG1} + COMPILER_ID "${CMAKE_${COTIRE_TARGET_LANGUAGE}_COMPILER_ID}" + COMPILER_VERSION "${CMAKE_${COTIRE_TARGET_LANGUAGE}_COMPILER_VERSION}" + LANGUAGE "${COTIRE_TARGET_LANGUAGE}" + INCLUDE_DIRECTORIES ${_includeDirs} + SYSTEM_INCLUDE_DIRECTORIES ${_systemIncludeDirs} + COMPILE_DEFINITIONS ${_compileDefinitions} + COMPILE_FLAGS ${_compileFlags}) + + elseif ("${COTIRE_ARGV1}" STREQUAL "combine") + + if (COTIRE_TARGET_LANGUAGE) + set (_combinedFile "${COTIRE_ARGV3}") + set (_startIndex 4) + else() + set (_combinedFile "${COTIRE_ARGV2}") + set (_startIndex 3) + endif() + set (_files "") + foreach (_index RANGE ${_startIndex} ${COTIRE_ARGC}) + if (COTIRE_ARGV${_index}) + list (APPEND _files "${COTIRE_ARGV${_index}}") + endif() + endforeach() + + if (XCODE) + # executing pre-build action under Xcode, check dependency on files to be combined + set (_dependsOption DEPENDS ${_files}) + else() + # executing custom command, no need to re-check for dependencies + set (_dependsOption "") + endif() + + if (COTIRE_TARGET_LANGUAGE) + cotire_generate_unity_source( + "${_combinedFile}" ${_files} + LANGUAGE "${COTIRE_TARGET_LANGUAGE}" + ${_dependsOption}) + else() + cotire_generate_unity_source("${_combinedFile}" ${_files} ${_dependsOption}) + endif() + + elseif ("${COTIRE_ARGV1}" STREQUAL "cleanup") + + cotire_cleanup("${COTIRE_ARGV2}" "${COTIRE_ARGV3}" "${COTIRE_ARGV4}") + + else() + message (FATAL_ERROR "cotire: unknown command \"${COTIRE_ARGV1}\".") + endif() + +else() + + # cotire is being run in include mode + # set up all variable and property definitions + + if (NOT DEFINED COTIRE_DEBUG_INIT) + if (DEFINED COTIRE_DEBUG) + set (COTIRE_DEBUG_INIT ${COTIRE_DEBUG}) + else() + set (COTIRE_DEBUG_INIT FALSE) + endif() + endif() + option (COTIRE_DEBUG "Enable cotire debugging output?" ${COTIRE_DEBUG_INIT}) + + if (NOT DEFINED COTIRE_VERBOSE_INIT) + if (DEFINED COTIRE_VERBOSE) + set (COTIRE_VERBOSE_INIT ${COTIRE_VERBOSE}) + else() + set (COTIRE_VERBOSE_INIT FALSE) + endif() + endif() + option (COTIRE_VERBOSE "Enable cotire verbose output?" ${COTIRE_VERBOSE_INIT}) + + set (COTIRE_ADDITIONAL_PREFIX_HEADER_IGNORE_EXTENSIONS "inc;inl;ipp" CACHE STRING + "Ignore headers with the listed file extensions from the generated prefix header.") + + set (COTIRE_ADDITIONAL_PREFIX_HEADER_IGNORE_PATH "" CACHE STRING + "Ignore headers from these directories when generating the prefix header.") + + set (COTIRE_UNITY_SOURCE_EXCLUDE_EXTENSIONS "m;mm" CACHE STRING + "Ignore sources with the listed file extensions from the generated unity source.") + + set (COTIRE_MINIMUM_NUMBER_OF_TARGET_SOURCES "3" CACHE STRING + "Minimum number of sources in target required to enable use of precompiled header.") + + if (NOT DEFINED COTIRE_MAXIMUM_NUMBER_OF_UNITY_INCLUDES_INIT) + if (DEFINED COTIRE_MAXIMUM_NUMBER_OF_UNITY_INCLUDES) + set (COTIRE_MAXIMUM_NUMBER_OF_UNITY_INCLUDES_INIT ${COTIRE_MAXIMUM_NUMBER_OF_UNITY_INCLUDES}) + elseif ("${CMAKE_GENERATOR}" MATCHES "JOM|Ninja|Visual Studio") + # enable parallelization for generators that run multiple jobs by default + set (COTIRE_MAXIMUM_NUMBER_OF_UNITY_INCLUDES_INIT "-j") + else() + set (COTIRE_MAXIMUM_NUMBER_OF_UNITY_INCLUDES_INIT "0") + endif() + endif() + set (COTIRE_MAXIMUM_NUMBER_OF_UNITY_INCLUDES "${COTIRE_MAXIMUM_NUMBER_OF_UNITY_INCLUDES_INIT}" CACHE STRING + "Maximum number of source files to include in a single unity source file.") + + if (NOT COTIRE_PREFIX_HEADER_FILENAME_SUFFIX) + set (COTIRE_PREFIX_HEADER_FILENAME_SUFFIX "_prefix") + endif() + if (NOT COTIRE_UNITY_SOURCE_FILENAME_SUFFIX) + set (COTIRE_UNITY_SOURCE_FILENAME_SUFFIX "_unity") + endif() + if (NOT COTIRE_INTDIR) + set (COTIRE_INTDIR "cotire") + endif() + if (NOT COTIRE_PCH_ALL_TARGET_NAME) + set (COTIRE_PCH_ALL_TARGET_NAME "all_pch") + endif() + if (NOT COTIRE_UNITY_BUILD_ALL_TARGET_NAME) + set (COTIRE_UNITY_BUILD_ALL_TARGET_NAME "all_unity") + endif() + if (NOT COTIRE_CLEAN_ALL_TARGET_NAME) + set (COTIRE_CLEAN_ALL_TARGET_NAME "clean_cotire") + endif() + if (NOT COTIRE_CLEAN_TARGET_SUFFIX) + set (COTIRE_CLEAN_TARGET_SUFFIX "_clean_cotire") + endif() + if (NOT COTIRE_PCH_TARGET_SUFFIX) + set (COTIRE_PCH_TARGET_SUFFIX "_pch") + endif() + if (MSVC) + # MSVC default PCH memory scaling factor of 100 percent (75 MB) is too small for template heavy C++ code + # use a bigger default factor of 170 percent (128 MB) + if (NOT DEFINED COTIRE_PCH_MEMORY_SCALING_FACTOR) + set (COTIRE_PCH_MEMORY_SCALING_FACTOR "170") + endif() + endif() + if (NOT COTIRE_UNITY_BUILD_TARGET_SUFFIX) + set (COTIRE_UNITY_BUILD_TARGET_SUFFIX "_unity") + endif() + if (NOT DEFINED COTIRE_TARGETS_FOLDER) + set (COTIRE_TARGETS_FOLDER "cotire") + endif() + if (NOT DEFINED COTIRE_UNITY_OUTPUT_DIRECTORY) + if ("${CMAKE_GENERATOR}" MATCHES "Ninja") + # generated Ninja build files do not work if the unity target produces the same output file as the cotired target + set (COTIRE_UNITY_OUTPUT_DIRECTORY "unity") + else() + set (COTIRE_UNITY_OUTPUT_DIRECTORY "") + endif() + endif() + + # define cotire cache variables + + define_property( + CACHED_VARIABLE PROPERTY "COTIRE_ADDITIONAL_PREFIX_HEADER_IGNORE_PATH" + BRIEF_DOCS "Ignore headers from these directories when generating the prefix header." + FULL_DOCS + "The variable can be set to a semicolon separated list of include directories." + "If a header file is found in one of these directories or sub-directories, it will be excluded from the generated prefix header." + "If not defined, defaults to empty list." + ) + + define_property( + CACHED_VARIABLE PROPERTY "COTIRE_ADDITIONAL_PREFIX_HEADER_IGNORE_EXTENSIONS" + BRIEF_DOCS "Ignore includes with the listed file extensions from the generated prefix header." + FULL_DOCS + "The variable can be set to a semicolon separated list of file extensions." + "If a header file extension matches one in the list, it will be excluded from the generated prefix header." + "Includes with an extension in CMAKE__SOURCE_FILE_EXTENSIONS are always ignored." + "If not defined, defaults to inc;inl;ipp." + ) + + define_property( + CACHED_VARIABLE PROPERTY "COTIRE_UNITY_SOURCE_EXCLUDE_EXTENSIONS" + BRIEF_DOCS "Exclude sources with the listed file extensions from the generated unity source." + FULL_DOCS + "The variable can be set to a semicolon separated list of file extensions." + "If a source file extension matches one in the list, it will be excluded from the generated unity source file." + "Source files with an extension in CMAKE__IGNORE_EXTENSIONS are always excluded." + "If not defined, defaults to m;mm." + ) + + define_property( + CACHED_VARIABLE PROPERTY "COTIRE_MINIMUM_NUMBER_OF_TARGET_SOURCES" + BRIEF_DOCS "Minimum number of sources in target required to enable use of precompiled header." + FULL_DOCS + "The variable can be set to an integer > 0." + "If a target contains less than that number of source files, cotire will not enable the use of the precompiled header for the target." + "If not defined, defaults to 3." + ) + + define_property( + CACHED_VARIABLE PROPERTY "COTIRE_MAXIMUM_NUMBER_OF_UNITY_INCLUDES" + BRIEF_DOCS "Maximum number of source files to include in a single unity source file." + FULL_DOCS + "This may be set to an integer >= 0." + "If 0, cotire will only create a single unity source file." + "If a target contains more than that number of source files, cotire will create multiple unity source files for it." + "Can be set to \"-j\" to optimize the count of unity source files for the number of available processor cores." + "Can be set to \"-j jobs\" to optimize the number of unity source files for the given number of simultaneous jobs." + "Is used to initialize the target property COTIRE_UNITY_SOURCE_MAXIMUM_NUMBER_OF_INCLUDES." + "Defaults to \"-j\" for the generators Visual Studio, JOM or Ninja. Defaults to 0 otherwise." + ) + + # define cotire directory properties + + define_property( + DIRECTORY PROPERTY "COTIRE_ENABLE_PRECOMPILED_HEADER" + BRIEF_DOCS "Modify build command of cotired targets added in this directory to make use of the generated precompiled header." + FULL_DOCS + "See target property COTIRE_ENABLE_PRECOMPILED_HEADER." + ) + + define_property( + DIRECTORY PROPERTY "COTIRE_ADD_UNITY_BUILD" + BRIEF_DOCS "Add a new target that performs a unity build for cotired targets added in this directory." + FULL_DOCS + "See target property COTIRE_ADD_UNITY_BUILD." + ) + + define_property( + DIRECTORY PROPERTY "COTIRE_ADD_CLEAN" + BRIEF_DOCS "Add a new target that cleans all cotire generated files for cotired targets added in this directory." + FULL_DOCS + "See target property COTIRE_ADD_CLEAN." + ) + + define_property( + DIRECTORY PROPERTY "COTIRE_PREFIX_HEADER_IGNORE_PATH" + BRIEF_DOCS "Ignore headers from these directories when generating the prefix header." + FULL_DOCS + "See target property COTIRE_PREFIX_HEADER_IGNORE_PATH." + ) + + define_property( + DIRECTORY PROPERTY "COTIRE_PREFIX_HEADER_INCLUDE_PATH" + BRIEF_DOCS "Honor headers from these directories when generating the prefix header." + FULL_DOCS + "See target property COTIRE_PREFIX_HEADER_INCLUDE_PATH." + ) + + define_property( + DIRECTORY PROPERTY "COTIRE_PREFIX_HEADER_INCLUDE_PRIORITY_PATH" + BRIEF_DOCS "Header paths matching one of these directories are put at the top of the prefix header." + FULL_DOCS + "See target property COTIRE_PREFIX_HEADER_INCLUDE_PRIORITY_PATH." + ) + + define_property( + DIRECTORY PROPERTY "COTIRE_UNITY_SOURCE_PRE_UNDEFS" + BRIEF_DOCS "Preprocessor undefs to place in the generated unity source file before the inclusion of each source file." + FULL_DOCS + "See target property COTIRE_UNITY_SOURCE_PRE_UNDEFS." + ) + + define_property( + DIRECTORY PROPERTY "COTIRE_UNITY_SOURCE_POST_UNDEFS" + BRIEF_DOCS "Preprocessor undefs to place in the generated unity source file after the inclusion of each source file." + FULL_DOCS + "See target property COTIRE_UNITY_SOURCE_POST_UNDEFS." + ) + + define_property( + DIRECTORY PROPERTY "COTIRE_UNITY_SOURCE_MAXIMUM_NUMBER_OF_INCLUDES" + BRIEF_DOCS "Maximum number of source files to include in a single unity source file." + FULL_DOCS + "See target property COTIRE_UNITY_SOURCE_MAXIMUM_NUMBER_OF_INCLUDES." + ) + + define_property( + DIRECTORY PROPERTY "COTIRE_UNITY_LINK_LIBRARIES_INIT" + BRIEF_DOCS "Define strategy for setting up the unity target's link libraries." + FULL_DOCS + "See target property COTIRE_UNITY_LINK_LIBRARIES_INIT." + ) + + # define cotire target properties + + define_property( + TARGET PROPERTY "COTIRE_ENABLE_PRECOMPILED_HEADER" INHERITED + BRIEF_DOCS "Modify this target's build command to make use of the generated precompiled header." + FULL_DOCS + "If this property is set to TRUE, cotire will modify the build command to make use of the generated precompiled header." + "Irrespective of the value of this property, cotire will setup custom commands to generate the unity source and prefix header for the target." + "For makefile based generators cotire will also set up a custom target to manually invoke the generation of the precompiled header." + "The target name will be set to this target's name with the suffix _pch appended." + "Inherited from directory." + "Defaults to TRUE." + ) + + define_property( + TARGET PROPERTY "COTIRE_ADD_UNITY_BUILD" INHERITED + BRIEF_DOCS "Add a new target that performs a unity build for this target." + FULL_DOCS + "If this property is set to TRUE, cotire creates a new target of the same type that uses the generated unity source file instead of the target sources." + "Most of the relevant target properties will be copied from this target to the new unity build target." + "Target dependencies and linked libraries have to be manually set up for the new unity build target." + "The unity target name will be set to this target's name with the suffix _unity appended." + "Inherited from directory." + "Defaults to TRUE." + ) + + define_property( + TARGET PROPERTY "COTIRE_ADD_CLEAN" INHERITED + BRIEF_DOCS "Add a new target that cleans all cotire generated files for this target." + FULL_DOCS + "If this property is set to TRUE, cotire creates a new target that clean all files (unity source, prefix header, precompiled header)." + "The clean target name will be set to this target's name with the suffix _clean_cotire appended." + "Inherited from directory." + "Defaults to FALSE." + ) + + define_property( + TARGET PROPERTY "COTIRE_PREFIX_HEADER_IGNORE_PATH" INHERITED + BRIEF_DOCS "Ignore headers from these directories when generating the prefix header." + FULL_DOCS + "The property can be set to a list of directories." + "If a header file is found in one of these directories or sub-directories, it will be excluded from the generated prefix header." + "Inherited from directory." + "If not set, this property is initialized to \${CMAKE_SOURCE_DIR};\${CMAKE_BINARY_DIR}." + ) + + define_property( + TARGET PROPERTY "COTIRE_PREFIX_HEADER_INCLUDE_PATH" INHERITED + BRIEF_DOCS "Honor headers from these directories when generating the prefix header." + FULL_DOCS + "The property can be set to a list of directories." + "If a header file is found in one of these directories or sub-directories, it will be included in the generated prefix header." + "If a header file is both selected by COTIRE_PREFIX_HEADER_IGNORE_PATH and COTIRE_PREFIX_HEADER_INCLUDE_PATH," + "the option which yields the closer relative path match wins." + "Inherited from directory." + "If not set, this property is initialized to the empty list." + ) + + define_property( + TARGET PROPERTY "COTIRE_PREFIX_HEADER_INCLUDE_PRIORITY_PATH" INHERITED + BRIEF_DOCS "Header paths matching one of these directories are put at the top of prefix header." + FULL_DOCS + "The property can be set to a list of directories." + "Header file paths matching one of these directories will be inserted at the beginning of the generated prefix header." + "Header files are sorted according to the order of the directories in the property." + "If not set, this property is initialized to the empty list." + ) + + define_property( + TARGET PROPERTY "COTIRE_UNITY_SOURCE_PRE_UNDEFS" INHERITED + BRIEF_DOCS "Preprocessor undefs to place in the generated unity source file before the inclusion of each target source file." + FULL_DOCS + "This may be set to a semicolon-separated list of preprocessor symbols." + "cotire will add corresponding #undef directives to the generated unit source file before each target source file." + "Inherited from directory." + "Defaults to empty string." + ) + + define_property( + TARGET PROPERTY "COTIRE_UNITY_SOURCE_POST_UNDEFS" INHERITED + BRIEF_DOCS "Preprocessor undefs to place in the generated unity source file after the inclusion of each target source file." + FULL_DOCS + "This may be set to a semicolon-separated list of preprocessor symbols." + "cotire will add corresponding #undef directives to the generated unit source file after each target source file." + "Inherited from directory." + "Defaults to empty string." + ) + + define_property( + TARGET PROPERTY "COTIRE_UNITY_SOURCE_MAXIMUM_NUMBER_OF_INCLUDES" INHERITED + BRIEF_DOCS "Maximum number of source files to include in a single unity source file." + FULL_DOCS + "This may be set to an integer > 0." + "If a target contains more than that number of source files, cotire will create multiple unity build files for it." + "If not set, cotire will only create a single unity source file." + "Inherited from directory." + "Defaults to empty." + ) + + define_property( + TARGET PROPERTY "COTIRE__UNITY_SOURCE_INIT" + BRIEF_DOCS "User provided unity source file to be used instead of the automatically generated one." + FULL_DOCS + "If set, cotire will only add the given file(s) to the generated unity source file." + "If not set, cotire will add all the target source files to the generated unity source file." + "The property can be set to a user provided unity source file." + "Defaults to empty." + ) + + define_property( + TARGET PROPERTY "COTIRE__PREFIX_HEADER_INIT" + BRIEF_DOCS "User provided prefix header file to be used instead of the automatically generated one." + FULL_DOCS + "If set, cotire will add the given header file(s) to the generated prefix header file." + "If not set, cotire will generate a prefix header by tracking the header files included by the unity source file." + "The property can be set to a user provided prefix header file (e.g., stdafx.h)." + "Defaults to empty." + ) + + define_property( + TARGET PROPERTY "COTIRE_UNITY_LINK_LIBRARIES_INIT" INHERITED + BRIEF_DOCS "Define strategy for setting up unity target's link libraries." + FULL_DOCS + "If this property is empty or set to NONE, the generated unity target's link libraries have to be set up manually." + "If this property is set to COPY, the unity target's link libraries will be copied from this target." + "If this property is set to COPY_UNITY, the unity target's link libraries will be copied from this target with considering existing unity targets." + "Inherited from directory." + "Defaults to empty." + ) + + define_property( + TARGET PROPERTY "COTIRE__UNITY_SOURCE" + BRIEF_DOCS "Read-only property. The generated unity source file(s)." + FULL_DOCS + "cotire sets this property to the path of the generated single computation unit source file for the target." + "Defaults to empty string." + ) + + define_property( + TARGET PROPERTY "COTIRE__PREFIX_HEADER" + BRIEF_DOCS "Read-only property. The generated prefix header file." + FULL_DOCS + "cotire sets this property to the full path of the generated language prefix header for the target." + "Defaults to empty string." + ) + + define_property( + TARGET PROPERTY "COTIRE__PRECOMPILED_HEADER" + BRIEF_DOCS "Read-only property. The generated precompiled header file." + FULL_DOCS + "cotire sets this property to the full path of the generated language precompiled header binary for the target." + "Defaults to empty string." + ) + + define_property( + TARGET PROPERTY "COTIRE_UNITY_TARGET_NAME" + BRIEF_DOCS "The name of the generated unity build target corresponding to this target." + FULL_DOCS + "This property can be set to the desired name of the unity target that will be created by cotire." + "If not set, the unity target name will be set to this target's name with the suffix _unity appended." + "After this target has been processed by cotire, the property is set to the actual name of the generated unity target." + "Defaults to empty string." + ) + + # define cotire source properties + + define_property( + SOURCE PROPERTY "COTIRE_EXCLUDED" + BRIEF_DOCS "Do not modify source file's build command." + FULL_DOCS + "If this property is set to TRUE, the source file's build command will not be modified to make use of the precompiled header." + "The source file will also be excluded from the generated unity source file." + "Source files that have their COMPILE_FLAGS property set will be excluded by default." + "Defaults to FALSE." + ) + + define_property( + SOURCE PROPERTY "COTIRE_DEPENDENCY" + BRIEF_DOCS "Add this source file to dependencies of the automatically generated prefix header file." + FULL_DOCS + "If this property is set to TRUE, the source file is added to dependencies of the generated prefix header file." + "If the file is modified, cotire will re-generate the prefix header source upon build." + "Defaults to FALSE." + ) + + define_property( + SOURCE PROPERTY "COTIRE_UNITY_SOURCE_PRE_UNDEFS" + BRIEF_DOCS "Preprocessor undefs to place in the generated unity source file before the inclusion of this source file." + FULL_DOCS + "This may be set to a semicolon-separated list of preprocessor symbols." + "cotire will add corresponding #undef directives to the generated unit source file before this file is included." + "Defaults to empty string." + ) + + define_property( + SOURCE PROPERTY "COTIRE_UNITY_SOURCE_POST_UNDEFS" + BRIEF_DOCS "Preprocessor undefs to place in the generated unity source file after the inclusion of this source file." + FULL_DOCS + "This may be set to a semicolon-separated list of preprocessor symbols." + "cotire will add corresponding #undef directives to the generated unit source file after this file is included." + "Defaults to empty string." + ) + + define_property( + SOURCE PROPERTY "COTIRE_START_NEW_UNITY_SOURCE" + BRIEF_DOCS "Start a new unity source file which includes this source file as the first one." + FULL_DOCS + "If this property is set to TRUE, cotire will complete the current unity file and start a new one." + "The new unity source file will include this source file as the first one." + "This property essentially works as a separator for unity source files." + "Defaults to FALSE." + ) + + define_property( + SOURCE PROPERTY "COTIRE_TARGET" + BRIEF_DOCS "Read-only property. Mark this source file as cotired for the given target." + FULL_DOCS + "cotire sets this property to the name of target, that the source file's build command has been altered for." + "Defaults to empty string." + ) + + message (STATUS "cotire ${COTIRE_CMAKE_MODULE_VERSION} loaded.") + +endif() diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 0ceb6bf6..25e345c2 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -1,8 +1,16 @@ +add_library(catch_main OBJECT + "src/unit.cpp" +) +set_target_properties(catch_main PROPERTIES + CXX_STANDARD 11 + CXX_STANDARD_REQUIRED ON +) +target_include_directories(catch_main PRIVATE "thirdparty/catch") + # The unit test executable. set(JSON_UNITTEST_TARGET_NAME "json_unit") add_executable(${JSON_UNITTEST_TARGET_NAME} - "thirdparty/catch/catch.hpp" - "src/unit.cpp" + $ "src/unit-algorithms.cpp" "src/unit-allocator.cpp" "src/unit-capacity.cpp" @@ -43,13 +51,33 @@ add_executable(${JSON_UNITTEST_TARGET_NAME} set_target_properties(${JSON_UNITTEST_TARGET_NAME} PROPERTIES CXX_STANDARD 11 CXX_STANDARD_REQUIRED ON - COMPILE_DEFINITIONS "$<$:_SCL_SECURE_NO_WARNINGS>" - COMPILE_OPTIONS "$<$:/EHsc;$<$:/Od>>" ) +if(MSVC) + set_target_properties(${JSON_UNITTEST_TARGET_NAME} PROPERTIES + COMPILE_DEFINITIONS "_SCL_SECURE_NO_WARNINGS" + COMPILE_OPTIONS "/EHsc;$<$:/Od>" + ) +endif() + target_include_directories(${JSON_UNITTEST_TARGET_NAME} PRIVATE "src" "thirdparty/catch") target_link_libraries(${JSON_UNITTEST_TARGET_NAME} ${JSON_TARGET_NAME}) +include(cotire OPTIONAL) + +if(COMMAND cotire) + set_target_properties(${JSON_UNITTEST_TARGET_NAME} PROPERTIES + COTIRE_ADD_UNITY_BUILD FALSE + COTIRE_CXX_PREFIX_HEADER_INIT "src/prefix.hpp" + ) + # HACK - CMAKE_INCLUDE_SYSTEM_FLAG_CXX has a trailing space, which Cotire doesn't strip + # Technically, this fix should go in cotire.cmake. TODO - submit a pull request upstream. + if (CMAKE_INCLUDE_SYSTEM_FLAG_CXX) + string (STRIP "${CMAKE_INCLUDE_SYSTEM_FLAG_CXX}" CMAKE_INCLUDE_SYSTEM_FLAG_CXX) + endif() + cotire(${JSON_UNITTEST_TARGET_NAME}) +endif() + add_test(NAME "${JSON_UNITTEST_TARGET_NAME}_default" COMMAND ${JSON_UNITTEST_TARGET_NAME} WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} diff --git a/test/src/prefix.hpp b/test/src/prefix.hpp new file mode 100644 index 00000000..9df98c79 --- /dev/null +++ b/test/src/prefix.hpp @@ -0,0 +1,7 @@ +#pragma once + +#include "catch.hpp" + +#define private public +#include "json.hpp" +using nlohmann::json; diff --git a/test/src/unit-udt.cpp b/test/src/unit-udt.cpp index 347ea377..ba56532d 100644 --- a/test/src/unit-udt.cpp +++ b/test/src/unit-udt.cpp @@ -26,16 +26,17 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#include -#include -#include -#include #include "catch.hpp" #include "json.hpp" using nlohmann::json; +#include +#include +#include +#include + namespace udt { enum class country From 5436407b7e7d1de9381bbabab5c5a88f66f36578 Mon Sep 17 00:00:00 2001 From: Tushar Maheshwari Date: Sun, 12 Feb 2017 19:40:40 +0530 Subject: [PATCH 62/80] :construction_worker: Add cmake logic to Travis config - get CMake for XCode 8.1 image --- .gitignore | 1 + .travis.yml | 13 ++++++++++++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 6e15abc4..69a81cbd 100644 --- a/.gitignore +++ b/.gitignore @@ -7,6 +7,7 @@ fuzz-testing *.gcno *.gcda +build working doc/xml diff --git a/.travis.yml b/.travis.yml index ef5c6143..c3cba69e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -228,6 +228,14 @@ install: # make sure CXX is correctly set - if [[ "${COMPILER}" != "" ]]; then export CXX=${COMPILER}; fi + # get CMake (only for systems with brew - macOS) + - | + if [[ !(-x $(which cmake)) && (-x $(which brew)) ]]; then + brew update + brew install cmake + cmake --version + fi + # install LLVM/clang when LLVM_VERSION is set - | if [[ "${LLVM_VERSION}" != "" ]]; then @@ -266,7 +274,10 @@ script: - $CXX --version # compile and execute unit tests - - make check + - mkdir -p build && cd build + - cmake .. && cmake --build . --config Release -- -j4 + - ctest -C Release -V + - cd .. # check if homebrew works (only checks develop branch) - if [ `which brew` ]; then From 9a9d0ba3df4f9b44582e59bff202d1811d47cad6 Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Sun, 19 Feb 2017 17:47:20 +0100 Subject: [PATCH 63/80] :construction: fixing warning C4293 (#453) --- src/json.hpp | 8 ++++---- src/json.hpp.re2c | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/json.hpp b/src/json.hpp index 5ad77f9d..4891ddfb 100644 --- a/src/json.hpp +++ b/src/json.hpp @@ -6570,10 +6570,10 @@ class basic_json { case 8: { - vec.push_back(static_cast((number >> 070) & 0xff)); - vec.push_back(static_cast((number >> 060) & 0xff)); - vec.push_back(static_cast((number >> 050) & 0xff)); - vec.push_back(static_cast((number >> 040) & 0xff)); + vec.push_back(static_cast((static_cast(number) >> 070) & 0xff)); + vec.push_back(static_cast((static_cast(number) >> 060) & 0xff)); + vec.push_back(static_cast((static_cast(number) >> 050) & 0xff)); + vec.push_back(static_cast((static_cast(number) >> 040) & 0xff)); // intentional fall-through } diff --git a/src/json.hpp.re2c b/src/json.hpp.re2c index 84c0e893..518889e0 100644 --- a/src/json.hpp.re2c +++ b/src/json.hpp.re2c @@ -6570,10 +6570,10 @@ class basic_json { case 8: { - vec.push_back(static_cast((number >> 070) & 0xff)); - vec.push_back(static_cast((number >> 060) & 0xff)); - vec.push_back(static_cast((number >> 050) & 0xff)); - vec.push_back(static_cast((number >> 040) & 0xff)); + vec.push_back(static_cast((static_cast(number) >> 070) & 0xff)); + vec.push_back(static_cast((static_cast(number) >> 060) & 0xff)); + vec.push_back(static_cast((static_cast(number) >> 050) & 0xff)); + vec.push_back(static_cast((static_cast(number) >> 040) & 0xff)); // intentional fall-through } From 4151f2d297f17658ae3fb10f134b99dc4eea79c7 Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Sun, 19 Feb 2017 20:08:01 +0100 Subject: [PATCH 64/80] :white_check_mark: added test with thousands_sep --- src/json.hpp | 21 +-------------------- src/json.hpp.re2c | 21 +-------------------- test/src/unit-regression.cpp | 26 ++++++++++++++++++-------- 3 files changed, 20 insertions(+), 48 deletions(-) diff --git a/src/json.hpp b/src/json.hpp index 03df7426..08b95cdb 100644 --- a/src/json.hpp +++ b/src/json.hpp @@ -8298,25 +8298,7 @@ class basic_json snprintf(m_buf.data(), m_buf.size(), fmt, x); -#if 0 - // C locales and C++ locales are similar but - // different. - // - // If working with C++ streams we'd've used - // these, but for C formatting functions we - // have to use C locales (setlocale / localeconv), - // rather than C++ locales (std::locale installed - // by std::locale::global()). - const std::locale loc; - - const char thousands_sep = - std::use_facet< std::numpunct>( - loc).thousands_sep(); - - const char decimal_point = - std::use_facet< std::numpunct>( - loc).decimal_point(); -#else + // read information from locale const auto loc = localeconv(); assert(loc != nullptr); const char thousands_sep = !loc->thousands_sep ? '\0' @@ -8324,7 +8306,6 @@ class basic_json const char decimal_point = !loc->decimal_point ? '\0' : loc->decimal_point[0]; -#endif // erase thousands separator if (thousands_sep != '\0') diff --git a/src/json.hpp.re2c b/src/json.hpp.re2c index bf7f380a..050b0b6b 100644 --- a/src/json.hpp.re2c +++ b/src/json.hpp.re2c @@ -8298,25 +8298,7 @@ class basic_json snprintf(m_buf.data(), m_buf.size(), fmt, x); -#if 0 - // C locales and C++ locales are similar but - // different. - // - // If working with C++ streams we'd've used - // these, but for C formatting functions we - // have to use C locales (setlocale / localeconv), - // rather than C++ locales (std::locale installed - // by std::locale::global()). - const std::locale loc; - - const char thousands_sep = - std::use_facet< std::numpunct>( - loc).thousands_sep(); - - const char decimal_point = - std::use_facet< std::numpunct>( - loc).decimal_point(); -#else + // read information from locale const auto loc = localeconv(); assert(loc != nullptr); const char thousands_sep = !loc->thousands_sep ? '\0' @@ -8324,7 +8306,6 @@ class basic_json const char decimal_point = !loc->decimal_point ? '\0' : loc->decimal_point[0]; -#endif // erase thousands separator if (thousands_sep != '\0') diff --git a/test/src/unit-regression.cpp b/test/src/unit-regression.cpp index f998fcb9..29ca82ec 100644 --- a/test/src/unit-regression.cpp +++ b/test/src/unit-regression.cpp @@ -361,8 +361,8 @@ TEST_CASE("regression tests") SECTION("issue #228 - double values are serialized with commas as decimal points") { - json j1a = 23.42; - json j1b = json::parse("23.42"); + json j1a = 2312.42; + json j1b = json::parse("2312.42"); json j2a = 2342e-2; //issue #230 @@ -380,23 +380,33 @@ TEST_CASE("regression tests") { return ','; } + + char do_thousands_sep() const + { + return '.'; + } + + std::string do_grouping() const + { + return "\03"; + } }; // change locale to mess with decimal points auto orig_locale = std::locale::global(std::locale(std::locale(), new CommaDecimalSeparator)); - CHECK(j1a.dump() == "23.42"); - CHECK(j1b.dump() == "23.42"); + CHECK(j1a.dump() == "2312.42"); + CHECK(j1b.dump() == "2312.42"); // check if locale is properly reset std::stringstream ss; ss.imbue(std::locale(std::locale(), new CommaDecimalSeparator)); - ss << 47.11; - CHECK(ss.str() == "47,11"); + ss << 4712.11; + CHECK(ss.str() == "4.712,11"); ss << j1a; - CHECK(ss.str() == "47,1123.42"); + CHECK(ss.str() == "4.712,112312.42"); ss << 47.11; - CHECK(ss.str() == "47,1123.4247,11"); + CHECK(ss.str() == "4.712,112312.4247,11"); CHECK(j2a.dump() == "23.42"); //issue #230 From 83f1d2c81b5af42d58b4e52b12a41336d5790ba3 Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Sun, 19 Feb 2017 21:17:05 +0100 Subject: [PATCH 65/80] :sparkles: added start index for from_cbor and from_msgpack (#462) --- src/json.hpp | 35 ++++++++++++++++++++++++----------- src/json.hpp.re2c | 35 ++++++++++++++++++++++++----------- test/src/unit-cbor.cpp | 4 ++++ test/src/unit-msgpack.cpp | 4 ++++ test/src/unit-regression.cpp | 2 +- 5 files changed, 57 insertions(+), 23 deletions(-) diff --git a/src/json.hpp b/src/json.hpp index 08b95cdb..c849f7f4 100644 --- a/src/json.hpp +++ b/src/json.hpp @@ -7917,9 +7917,11 @@ class basic_json vector in MessagePack format.,to_msgpack} @sa http://msgpack.org - @sa @ref from_msgpack(const std::vector&) for the analogous - deserialization + @sa @ref from_msgpack(const std::vector&, const size_t) for the + analogous deserialization @sa @ref to_cbor(const basic_json& for the related CBOR format + + @since version 2.0.9 */ static std::vector to_msgpack(const basic_json& j) { @@ -7935,6 +7937,7 @@ class basic_json serialization format. @param[in] v a byte vector in MessagePack format + @param[in] start_index the index to start reading from @a v (0 by default) @return deserialized JSON value @throw std::invalid_argument if unsupported features from MessagePack were @@ -7948,11 +7951,15 @@ class basic_json @sa http://msgpack.org @sa @ref to_msgpack(const basic_json&) for the analogous serialization - @sa @ref from_cbor(const std::vector&) for the related CBOR format + @sa @ref from_cbor(const std::vector&, const size_t) for the + related CBOR format + + @since version 2.0.9, parameter @a start_index since 2.0.11 */ - static basic_json from_msgpack(const std::vector& v) + static basic_json from_msgpack(const std::vector& v, + const size_t start_index = 0) { - size_t i = 0; + size_t i = start_index; return from_msgpack_internal(v, i); } @@ -7973,9 +7980,11 @@ class basic_json vector in CBOR format.,to_cbor} @sa http://cbor.io - @sa @ref from_cbor(const std::vector&) for the analogous - deserialization + @sa @ref from_cbor(const std::vector&, const size_t) for the + analogous deserialization @sa @ref to_msgpack(const basic_json& for the related MessagePack format + + @since version 2.0.9 */ static std::vector to_cbor(const basic_json& j) { @@ -7991,6 +8000,7 @@ class basic_json (Concise Binary Object Representation) serialization format. @param[in] v a byte vector in CBOR format + @param[in] start_index the index to start reading from @a v (0 by default) @return deserialized JSON value @throw std::invalid_argument if unsupported features from CBOR were used in @@ -8004,12 +8014,15 @@ class basic_json @sa http://cbor.io @sa @ref to_cbor(const basic_json&) for the analogous serialization - @sa @ref from_msgpack(const std::vector&) for the related - MessagePack format + @sa @ref from_msgpack(const std::vector&, const size_t) for the + related MessagePack format + + @since version 2.0.9, parameter @a start_index since 2.0.11 */ - static basic_json from_cbor(const std::vector& v) + static basic_json from_cbor(const std::vector& v, + const size_t start_index = 0) { - size_t i = 0; + size_t i = start_index; return from_cbor_internal(v, i); } diff --git a/src/json.hpp.re2c b/src/json.hpp.re2c index 050b0b6b..2e591919 100644 --- a/src/json.hpp.re2c +++ b/src/json.hpp.re2c @@ -7917,9 +7917,11 @@ class basic_json vector in MessagePack format.,to_msgpack} @sa http://msgpack.org - @sa @ref from_msgpack(const std::vector&) for the analogous - deserialization + @sa @ref from_msgpack(const std::vector&, const size_t) for the + analogous deserialization @sa @ref to_cbor(const basic_json& for the related CBOR format + + @since version 2.0.9 */ static std::vector to_msgpack(const basic_json& j) { @@ -7935,6 +7937,7 @@ class basic_json serialization format. @param[in] v a byte vector in MessagePack format + @param[in] start_index the index to start reading from @a v (0 by default) @return deserialized JSON value @throw std::invalid_argument if unsupported features from MessagePack were @@ -7948,11 +7951,15 @@ class basic_json @sa http://msgpack.org @sa @ref to_msgpack(const basic_json&) for the analogous serialization - @sa @ref from_cbor(const std::vector&) for the related CBOR format + @sa @ref from_cbor(const std::vector&, const size_t) for the + related CBOR format + + @since version 2.0.9, parameter @a start_index since 2.0.11 */ - static basic_json from_msgpack(const std::vector& v) + static basic_json from_msgpack(const std::vector& v, + const size_t start_index = 0) { - size_t i = 0; + size_t i = start_index; return from_msgpack_internal(v, i); } @@ -7973,9 +7980,11 @@ class basic_json vector in CBOR format.,to_cbor} @sa http://cbor.io - @sa @ref from_cbor(const std::vector&) for the analogous - deserialization + @sa @ref from_cbor(const std::vector&, const size_t) for the + analogous deserialization @sa @ref to_msgpack(const basic_json& for the related MessagePack format + + @since version 2.0.9 */ static std::vector to_cbor(const basic_json& j) { @@ -7991,6 +8000,7 @@ class basic_json (Concise Binary Object Representation) serialization format. @param[in] v a byte vector in CBOR format + @param[in] start_index the index to start reading from @a v (0 by default) @return deserialized JSON value @throw std::invalid_argument if unsupported features from CBOR were used in @@ -8004,12 +8014,15 @@ class basic_json @sa http://cbor.io @sa @ref to_cbor(const basic_json&) for the analogous serialization - @sa @ref from_msgpack(const std::vector&) for the related - MessagePack format + @sa @ref from_msgpack(const std::vector&, const size_t) for the + related MessagePack format + + @since version 2.0.9, parameter @a start_index since 2.0.11 */ - static basic_json from_cbor(const std::vector& v) + static basic_json from_cbor(const std::vector& v, + const size_t start_index = 0) { - size_t i = 0; + size_t i = start_index; return from_cbor_internal(v, i); } diff --git a/test/src/unit-cbor.cpp b/test/src/unit-cbor.cpp index 539d408b..a8bbe463 100644 --- a/test/src/unit-cbor.cpp +++ b/test/src/unit-cbor.cpp @@ -1184,6 +1184,10 @@ TEST_CASE("single CBOR roundtrip") // compare parsed JSON values CHECK(j1 == j2); + + // check with different start index + packed.insert(packed.begin(), 5, 0xff); + CHECK(j1 == json::from_cbor(packed, 5)); } } diff --git a/test/src/unit-msgpack.cpp b/test/src/unit-msgpack.cpp index cad78ae8..34befb56 100644 --- a/test/src/unit-msgpack.cpp +++ b/test/src/unit-msgpack.cpp @@ -1039,6 +1039,10 @@ TEST_CASE("single MessagePack roundtrip") // compare parsed JSON values CHECK(j1 == j2); + + // check with different start index + packed.insert(packed.begin(), 5, 0xff); + CHECK(j1 == json::from_msgpack(packed, 5)); } } diff --git a/test/src/unit-regression.cpp b/test/src/unit-regression.cpp index 29ca82ec..8c9c8b92 100644 --- a/test/src/unit-regression.cpp +++ b/test/src/unit-regression.cpp @@ -385,7 +385,7 @@ TEST_CASE("regression tests") { return '.'; } - + std::string do_grouping() const { return "\03"; From 1f72c38861bdd4f0417b4401cd251709c64abef4 Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Sun, 19 Feb 2017 21:26:53 +0100 Subject: [PATCH 66/80] :ambulance: fix for #448 --- src/json.hpp | 6 ++++-- src/json.hpp.re2c | 6 ++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/json.hpp b/src/json.hpp index c849f7f4..b142b3b5 100644 --- a/src/json.hpp +++ b/src/json.hpp @@ -523,8 +523,10 @@ struct has_to_json // to_json // ///////////// -template -void to_json(BasicJsonType& j, typename BasicJsonType::boolean_t b) noexcept +template::type, + typename BasicJsonType::boolean_t>::value, int> = 0> +void to_json(BasicJsonType& j, T b) noexcept { external_constructor::construct(j, b); } diff --git a/src/json.hpp.re2c b/src/json.hpp.re2c index 2e591919..34b6ec30 100644 --- a/src/json.hpp.re2c +++ b/src/json.hpp.re2c @@ -523,8 +523,10 @@ struct has_to_json // to_json // ///////////// -template -void to_json(BasicJsonType& j, typename BasicJsonType::boolean_t b) noexcept +template::type, + typename BasicJsonType::boolean_t>::value, int> = 0> +void to_json(BasicJsonType& j, T b) noexcept { external_constructor::construct(j, b); } From 7a4a16a7db6dd2727770069176bc933bf410c3ba Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Mon, 20 Feb 2017 16:20:45 +0100 Subject: [PATCH 67/80] :lipstick: updated header list --- README.md | 2 +- src/json.hpp | 12 ++++++------ src/json.hpp.re2c | 12 ++++++------ 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index b49942d6..dee3fb7e 100644 --- a/README.md +++ b/README.md @@ -809,7 +809,7 @@ I deeply appreciate the help of the following people. - [Vladimir Petrigo](https://github.com/vpetrigo) made a SFINAE hack more readable. - [Denis Andrejew](https://github.com/seeekr) fixed a grammar issue in the README file. - [Pierre-Antoine Lacaze](https://github.com/palacaze) found a subtle bug in the `dump()` function. -- [TurpentineDistillery](https://github.com/TurpentineDistillery) pointed to [`std::locale::classic()`](http://en.cppreference.com/w/cpp/locale/locale/classic) to avoid too much locale joggling, found some nice performance improvements in the parser, improved the benchmarking code, and realized locale-independent number parsing. +- [TurpentineDistillery](https://github.com/TurpentineDistillery) pointed to [`std::locale::classic()`](http://en.cppreference.com/w/cpp/locale/locale/classic) to avoid too much locale joggling, found some nice performance improvements in the parser, improved the benchmarking code, and realized locale-independent number parsing and printing. - [cgzones](https://github.com/cgzones) had an idea how to fix the Coverity scan. - [Jared Grubb](https://github.com/jaredgrubb) silenced a nasty documentation warning. - [Yixin Zhang](https://github.com/qwename) fixed an integer overflow check. diff --git a/src/json.hpp b/src/json.hpp index b142b3b5..6ea8c249 100644 --- a/src/json.hpp +++ b/src/json.hpp @@ -29,22 +29,22 @@ SOFTWARE. #ifndef NLOHMANN_JSON_HPP #define NLOHMANN_JSON_HPP -#include // all_of, for_each, transform +#include // all_of, copy, fill, find, for_each, none_of, remove, reverse, transform #include // array #include // assert #include // isdigit #include // and, not, or -#include // isfinite, ldexp, signbit +#include // isfinite, labs, ldexp, signbit #include // nullptr_t, ptrdiff_t, size_t #include // int64_t, uint64_t -#include // strtod, strtof, strtold, strtoul -#include // strlen +#include // abort, strtod, strtof, strtold, strtoul, strtoll, strtoull +#include // strcpy, strlen #include // forward_list #include // function, hash, less #include // initializer_list #include // setw #include // istream, ostream -#include // advance, begin, bidirectional_iterator_tag, distance, end, inserter, iterator, iterator_traits, next, random_access_iterator_tag, reverse_iterator +#include // advance, begin, back_inserter, bidirectional_iterator_tag, distance, end, inserter, iterator, iterator_traits, next, random_access_iterator_tag, reverse_iterator #include // numeric_limits #include // locale #include // map @@ -53,7 +53,7 @@ SOFTWARE. #include // stringstream #include // domain_error, invalid_argument, out_of_range #include // getline, stoi, string, to_string -#include // add_pointer, enable_if, is_arithmetic, is_base_of, is_const, is_constructible, is_convertible, is_floating_point, is_integral, is_nothrow_move_assignable, std::is_nothrow_move_constructible, std::is_pointer, std::is_reference, std::is_same, remove_const, remove_pointer, remove_reference +#include // add_pointer, conditional, decay, enable_if, false_type, integral_constant, is_arithmetic, is_base_of, is_const, is_constructible, is_convertible, is_default_constructible, is_enum, is_floating_point, is_integral, is_nothrow_move_assignable, is_nothrow_move_constructible, is_pointer, is_reference, is_same, is_scalar, is_signed, remove_const, remove_cv, remove_pointer, remove_reference, true_type, underlying_type #include // declval, forward, make_pair, move, pair, swap #include // vector diff --git a/src/json.hpp.re2c b/src/json.hpp.re2c index 34b6ec30..72724a35 100644 --- a/src/json.hpp.re2c +++ b/src/json.hpp.re2c @@ -29,22 +29,22 @@ SOFTWARE. #ifndef NLOHMANN_JSON_HPP #define NLOHMANN_JSON_HPP -#include // all_of, for_each, transform +#include // all_of, copy, fill, find, for_each, none_of, remove, reverse, transform #include // array #include // assert #include // isdigit #include // and, not, or -#include // isfinite, ldexp, signbit +#include // isfinite, labs, ldexp, signbit #include // nullptr_t, ptrdiff_t, size_t #include // int64_t, uint64_t -#include // strtod, strtof, strtold, strtoul -#include // strlen +#include // abort, strtod, strtof, strtold, strtoul, strtoll, strtoull +#include // strcpy, strlen #include // forward_list #include // function, hash, less #include // initializer_list #include // setw #include // istream, ostream -#include // advance, begin, bidirectional_iterator_tag, distance, end, inserter, iterator, iterator_traits, next, random_access_iterator_tag, reverse_iterator +#include // advance, begin, back_inserter, bidirectional_iterator_tag, distance, end, inserter, iterator, iterator_traits, next, random_access_iterator_tag, reverse_iterator #include // numeric_limits #include // locale #include // map @@ -53,7 +53,7 @@ SOFTWARE. #include // stringstream #include // domain_error, invalid_argument, out_of_range #include // getline, stoi, string, to_string -#include // add_pointer, enable_if, is_arithmetic, is_base_of, is_const, is_constructible, is_convertible, is_floating_point, is_integral, is_nothrow_move_assignable, std::is_nothrow_move_constructible, std::is_pointer, std::is_reference, std::is_same, remove_const, remove_pointer, remove_reference +#include // add_pointer, conditional, decay, enable_if, false_type, integral_constant, is_arithmetic, is_base_of, is_const, is_constructible, is_convertible, is_default_constructible, is_enum, is_floating_point, is_integral, is_nothrow_move_assignable, is_nothrow_move_constructible, is_pointer, is_reference, is_same, is_scalar, is_signed, remove_const, remove_cv, remove_pointer, remove_reference, true_type, underlying_type #include // declval, forward, make_pair, move, pair, swap #include // vector From 716485a965cc6be49dc651833ec638be4b4f0548 Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Mon, 20 Feb 2017 16:27:16 +0100 Subject: [PATCH 68/80] :construction: removed decay (#448) --- src/json.hpp | 3 +-- src/json.hpp.re2c | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/json.hpp b/src/json.hpp index 6ea8c249..ab9b75d7 100644 --- a/src/json.hpp +++ b/src/json.hpp @@ -524,8 +524,7 @@ struct has_to_json ///////////// template::type, - typename BasicJsonType::boolean_t>::value, int> = 0> + std::is_same::value, int> = 0> void to_json(BasicJsonType& j, T b) noexcept { external_constructor::construct(j, b); diff --git a/src/json.hpp.re2c b/src/json.hpp.re2c index 72724a35..c409d18f 100644 --- a/src/json.hpp.re2c +++ b/src/json.hpp.re2c @@ -524,8 +524,7 @@ struct has_to_json ///////////// template::type, - typename BasicJsonType::boolean_t>::value, int> = 0> + std::is_same::value, int> = 0> void to_json(BasicJsonType& j, T b) noexcept { external_constructor::construct(j, b); From 83a9c60dbda7ab81a34f38cce037440316311eac Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Mon, 20 Feb 2017 17:37:34 +0100 Subject: [PATCH 69/80] :hammer: refactored code to avoid using strcpy/strlen/strcat (#463) --- src/json.hpp | 48 ++++++++++++++++++++++++++++++++++++----------- src/json.hpp.re2c | 48 ++++++++++++++++++++++++++++++++++++----------- 2 files changed, 74 insertions(+), 22 deletions(-) diff --git a/src/json.hpp b/src/json.hpp index ab9b75d7..6be6a6d9 100644 --- a/src/json.hpp +++ b/src/json.hpp @@ -38,7 +38,7 @@ SOFTWARE. #include // nullptr_t, ptrdiff_t, size_t #include // int64_t, uint64_t #include // abort, strtod, strtof, strtold, strtoul, strtoll, strtoull -#include // strcpy, strlen +#include // strlen #include // forward_list #include // function, hash, less #include // initializer_list @@ -8259,6 +8259,7 @@ class basic_json template void x_write(NumberType x, /*is_integral=*/std::true_type) { + // special case for "0" if (x == 0) { m_buf[0] = '0'; @@ -8291,9 +8292,17 @@ class basic_json template void x_write(NumberType x, /*is_integral=*/std::false_type) { + // special case for 0.0 and -0.0 if (x == 0) { - std::strcpy(m_buf.data(), std::signbit(x) ? "-0.0" : "0.0"); + size_t i = 0; + if (std::signbit(x)) + { + m_buf[i++] = '-'; + } + m_buf[i++] = '0'; + m_buf[i++] = '.'; + m_buf[i] = '0'; return; } @@ -8342,18 +8351,35 @@ class basic_json } // determine if need to append ".0" - const auto data_end = m_buf.begin() + strlen(m_buf.data()); - - const bool value_is_int_like = - std::none_of(m_buf.begin(), data_end, [](const char c) + size_t i = 0; + bool value_is_int_like = true; + for (i = 0; i < m_buf.size(); ++i) { - return (c == '.' or c == 'e' or c == 'E'); - }); - assert(data_end + 2 < m_buf.end()); + // break when end of number is reached + if (m_buf[i] == '\0') + { + break; + } + + // check if we find non-int character + value_is_int_like = value_is_int_like and m_buf[i] != '.' and + m_buf[i] != 'e' and m_buf[i] != 'E'; + } if (value_is_int_like) { - strcat(m_buf.data(), ".0"); + // there must be 2 bytes left for ".0" + assert((i + 2) < m_buf.size()); + // we write to the end of the number + assert(m_buf[i] == '\0'); + assert(m_buf[i - 1] != '\0'); + + // add ".0" + m_buf[i] = '.'; + m_buf[i + 1] = '0'; + + // the resulting string is properly terminated + assert(m_buf[i + 2] == '\0'); } } }; @@ -11136,7 +11162,7 @@ basic_json_parser_74: // update data to point to the modified bytes if ((len + 1) < buf.size()) { - std::copy(m_start, m_end, buf.data()); + std::copy(m_start, m_end, buf.begin()); buf[len] = 0; buf[ds_pos] = decimal_point_char; data = buf.data(); diff --git a/src/json.hpp.re2c b/src/json.hpp.re2c index c409d18f..82673171 100644 --- a/src/json.hpp.re2c +++ b/src/json.hpp.re2c @@ -38,7 +38,7 @@ SOFTWARE. #include // nullptr_t, ptrdiff_t, size_t #include // int64_t, uint64_t #include // abort, strtod, strtof, strtold, strtoul, strtoll, strtoull -#include // strcpy, strlen +#include // strlen #include // forward_list #include // function, hash, less #include // initializer_list @@ -8259,6 +8259,7 @@ class basic_json template void x_write(NumberType x, /*is_integral=*/std::true_type) { + // special case for "0" if (x == 0) { m_buf[0] = '0'; @@ -8291,9 +8292,17 @@ class basic_json template void x_write(NumberType x, /*is_integral=*/std::false_type) { + // special case for 0.0 and -0.0 if (x == 0) { - std::strcpy(m_buf.data(), std::signbit(x) ? "-0.0" : "0.0"); + size_t i = 0; + if (std::signbit(x)) + { + m_buf[i++] = '-'; + } + m_buf[i++] = '0'; + m_buf[i++] = '.'; + m_buf[i] = '0'; return; } @@ -8342,18 +8351,35 @@ class basic_json } // determine if need to append ".0" - const auto data_end = m_buf.begin() + strlen(m_buf.data()); - - const bool value_is_int_like = - std::none_of(m_buf.begin(), data_end, [](const char c) + size_t i = 0; + bool value_is_int_like = true; + for (i = 0; i < m_buf.size(); ++i) { - return (c == '.' or c == 'e' or c == 'E'); - }); - assert(data_end + 2 < m_buf.end()); + // break when end of number is reached + if (m_buf[i] == '\0') + { + break; + } + + // check if we find non-int character + value_is_int_like = value_is_int_like and m_buf[i] != '.' and + m_buf[i] != 'e' and m_buf[i] != 'E'; + } if (value_is_int_like) { - strcat(m_buf.data(), ".0"); + // there must be 2 bytes left for ".0" + assert((i + 2) < m_buf.size()); + // we write to the end of the number + assert(m_buf[i] == '\0'); + assert(m_buf[i - 1] != '\0'); + + // add ".0" + m_buf[i] = '.'; + m_buf[i + 1] = '0'; + + // the resulting string is properly terminated + assert(m_buf[i + 2] == '\0'); } } }; @@ -10170,7 +10196,7 @@ class basic_json // update data to point to the modified bytes if ((len + 1) < buf.size()) { - std::copy(m_start, m_end, buf.data()); + std::copy(m_start, m_end, buf.begin()); buf[len] = 0; buf[ds_pos] = decimal_point_char; data = buf.data(); From f2dfa09aecf672a3b9980613bde196a5cb1ef994 Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Mon, 20 Feb 2017 18:05:52 +0100 Subject: [PATCH 70/80] :bug: fix for #464 --- src/json.hpp | 1 + src/json.hpp.re2c | 1 + 2 files changed, 2 insertions(+) diff --git a/src/json.hpp b/src/json.hpp index 6be6a6d9..ae847adc 100644 --- a/src/json.hpp +++ b/src/json.hpp @@ -3487,6 +3487,7 @@ class basic_json not std::is_same::value #ifndef _MSC_VER // fix for issue #167 operator<< ambiguity under VS2015 and not std::is_same>::value + and not std::is_same::value #endif , int >::type = 0 > operator ValueType() const diff --git a/src/json.hpp.re2c b/src/json.hpp.re2c index 82673171..64b1e5dd 100644 --- a/src/json.hpp.re2c +++ b/src/json.hpp.re2c @@ -3487,6 +3487,7 @@ class basic_json not std::is_same::value #ifndef _MSC_VER // fix for issue #167 operator<< ambiguity under VS2015 and not std::is_same>::value + and not std::is_same::value #endif , int >::type = 0 > operator ValueType() const From f7075be93aca14537a80acdeae6b70b5bde01e12 Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Mon, 20 Feb 2017 18:15:50 +0100 Subject: [PATCH 71/80] :bug: reverted change for #464 --- src/json.hpp | 1 - src/json.hpp.re2c | 1 - 2 files changed, 2 deletions(-) diff --git a/src/json.hpp b/src/json.hpp index ae847adc..6be6a6d9 100644 --- a/src/json.hpp +++ b/src/json.hpp @@ -3487,7 +3487,6 @@ class basic_json not std::is_same::value #ifndef _MSC_VER // fix for issue #167 operator<< ambiguity under VS2015 and not std::is_same>::value - and not std::is_same::value #endif , int >::type = 0 > operator ValueType() const diff --git a/src/json.hpp.re2c b/src/json.hpp.re2c index 64b1e5dd..82673171 100644 --- a/src/json.hpp.re2c +++ b/src/json.hpp.re2c @@ -3487,7 +3487,6 @@ class basic_json not std::is_same::value #ifndef _MSC_VER // fix for issue #167 operator<< ambiguity under VS2015 and not std::is_same>::value - and not std::is_same::value #endif , int >::type = 0 > operator ValueType() const From 1a6d7f5bca9baec12fe6065c6009903c24ea533f Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Mon, 20 Feb 2017 18:32:11 +0100 Subject: [PATCH 72/80] :construction: try to fix some warnings in MSVC --- test/src/unit-cbor.cpp | 2 +- test/src/unit-concepts.cpp | 4 ++-- test/src/unit-msgpack.cpp | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/test/src/unit-cbor.cpp b/test/src/unit-cbor.cpp index a8bbe463..b22f744e 100644 --- a/test/src/unit-cbor.cpp +++ b/test/src/unit-cbor.cpp @@ -1271,7 +1271,7 @@ TEST_CASE("CBOR regressions", "[!throws]") SECTION("improve code coverage") { // exotic edge case - CHECK_THROWS_AS(json::check_length(0xffffffffffffffff, 0xfffffffffffffff0, 0xff), std::out_of_range); + CHECK_THROWS_AS(json::check_length(0xffffffffffffffffull, 0xfffffffffffffff0ull, 0xff), std::out_of_range); } } diff --git a/test/src/unit-concepts.cpp b/test/src/unit-concepts.cpp index d65f7401..cdc104b6 100644 --- a/test/src/unit-concepts.cpp +++ b/test/src/unit-concepts.cpp @@ -72,8 +72,8 @@ TEST_CASE("concepts") // X::size_type must return an unsigned integer CHECK((std::is_unsigned::value)); // X::size_type can represent any non-negative value of X::difference_type - CHECK(std::numeric_limits::max() <= - std::numeric_limits::max()); + CHECK(static_cast(std::numeric_limits::max()) <= + static_cast(std::numeric_limits::max())); // the expression "X u" has the post-condition "u.empty()" { diff --git a/test/src/unit-msgpack.cpp b/test/src/unit-msgpack.cpp index 34befb56..cc459fee 100644 --- a/test/src/unit-msgpack.cpp +++ b/test/src/unit-msgpack.cpp @@ -389,7 +389,7 @@ TEST_CASE("MessagePack") numbers.push_back(-65536); numbers.push_back(-77777); numbers.push_back(-1048576); - numbers.push_back(-2147483648); + numbers.push_back(-2147483648ll); for (auto i : numbers) { CAPTURE(i); From b04543ecc58188a593f8729db38c2c87abd90dc3 Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Mon, 20 Feb 2017 21:56:10 +0100 Subject: [PATCH 73/80] :art: fixed newlines --- appveyor.yml | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index a527ef76..3960f4db 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,10 +1,10 @@ -version: '{build}' -os: Visual Studio 2015 -init: [] -install: [] -build_script: -- set PATH=C:\Program Files (x86)\MSBuild\14.0\Bin;%PATH% -- cmake . -G "Visual Studio 14 2015" -- cmake --build . --config Release -test_script: -- ctest -C Release -V +version: '{build}' +os: Visual Studio 2015 +init: [] +install: [] +build_script: +- set PATH=C:\Program Files (x86)\MSBuild\14.0\Bin;%PATH% +- cmake . -G "Visual Studio 14 2015" +- cmake --build . --config Release +test_script: +- ctest -C Release -V From 7d14f167b84bf53b04e92ea08dbea86eaa8aafd8 Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Mon, 20 Feb 2017 22:48:27 +0100 Subject: [PATCH 74/80] :ambulance: fix for #465 --- src/json.hpp | 11 +---------- src/json.hpp.re2c | 11 +---------- test/src/unit-inspection.cpp | 18 ++++++++++++++++-- test/src/unit-regression.cpp | 9 +++++++++ 4 files changed, 27 insertions(+), 22 deletions(-) diff --git a/src/json.hpp b/src/json.hpp index 6be6a6d9..4aedb967 100644 --- a/src/json.hpp +++ b/src/json.hpp @@ -8310,16 +8310,7 @@ class basic_json static_assert(d == 6 or d == 15 or d == 16 or d == 17, "unexpected NumberType"); - static constexpr auto fmt = d == 6 ? "%.7g" - : d == 15 ? "%.16g" - : d == 16 ? "%.17g" - : d == 17 ? "%.18g" - : "%.19g"; - // I'm not sure why we need to +1 the precision, - // but without it there's a unit-test that fails - // that asserts precision of the output - - snprintf(m_buf.data(), m_buf.size(), fmt, x); + snprintf(m_buf.data(), m_buf.size(), "%.*g", d, x); // read information from locale const auto loc = localeconv(); diff --git a/src/json.hpp.re2c b/src/json.hpp.re2c index 82673171..0ceb4793 100644 --- a/src/json.hpp.re2c +++ b/src/json.hpp.re2c @@ -8310,16 +8310,7 @@ class basic_json static_assert(d == 6 or d == 15 or d == 16 or d == 17, "unexpected NumberType"); - static constexpr auto fmt = d == 6 ? "%.7g" - : d == 15 ? "%.16g" - : d == 16 ? "%.17g" - : d == 17 ? "%.18g" - : "%.19g"; - // I'm not sure why we need to +1 the precision, - // but without it there's a unit-test that fails - // that asserts precision of the output - - snprintf(m_buf.data(), m_buf.size(), fmt, x); + snprintf(m_buf.data(), m_buf.size(), "%.*g", d, x); // read information from locale const auto loc = localeconv(); diff --git a/test/src/unit-inspection.cpp b/test/src/unit-inspection.cpp index 2e3d075d..d5a97b7e 100644 --- a/test/src/unit-inspection.cpp +++ b/test/src/unit-inspection.cpp @@ -250,17 +250,31 @@ TEST_CASE("object inspection") ss.str(std::string()); // use stringstream for JSON serialization - json j_number = 3.141592653589793; + json j_number = 3.14159265358979; ss << j_number; // check that precision has been overridden during serialization - CHECK(ss.str() == "3.141592653589793"); + CHECK(ss.str() == "3.14159265358979"); // check that precision has been restored CHECK(ss.precision() == 3); } } + SECTION("round trips") + { + for (const auto& s : + {"3.141592653589793", "1000000000000000010E5" + }) + { + json j1 = json::parse(s); + std::string s1 = j1.dump(); + json j2 = json::parse(s1); + std::string s2 = j2.dump(); + CHECK(s1 == s2); + } + } + SECTION("return the type of the object (explicit)") { SECTION("null") diff --git a/test/src/unit-regression.cpp b/test/src/unit-regression.cpp index 8c9c8b92..e476d933 100644 --- a/test/src/unit-regression.cpp +++ b/test/src/unit-regression.cpp @@ -783,4 +783,13 @@ TEST_CASE("regression tests") json j = R"({"bool_value":true,"double_value":2.0,"int_value":10,"level1":{"list_value":[3,"hi",false],"tmp":5.0},"string_value":"hello"})"_json; CHECK(j["double_value"].is_number_float()); } + + SECTION("issue #465 - roundtrip error while parsing 1000000000000000010E5") + { + json j1 = json::parse("1000000000000000010E5"); + std::string s1 = j1.dump(); + json j2 = json::parse(s1); + std::string s2 = j2.dump(); + CHECK(s1 == s2); + } } From 967f9144d42b116060fd751203e809a5d169e241 Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Tue, 21 Feb 2017 19:11:34 +0100 Subject: [PATCH 75/80] :construction: overworked fix for #465 --- doc/Makefile | 10 +++++----- src/json.hpp | 33 +++++++++++++++++++-------------- src/json.hpp.re2c | 33 +++++++++++++++++++-------------- 3 files changed, 43 insertions(+), 33 deletions(-) diff --git a/doc/Makefile b/doc/Makefile index 04a5cc7b..37a0e19f 100644 --- a/doc/Makefile +++ b/doc/Makefile @@ -53,11 +53,11 @@ clean: # create Doxygen documentation doxygen: create_output create_links doxygen - $(SED) -i 's@< ObjectType, ArrayType, StringType, BooleanType, NumberIntegerType, NumberFloatType, AllocatorType >@@g' html/*.html - $(SED) -i 's@< ObjectType, ArrayType, StringType, BooleanType, NumberIntegerType, NumberFloatType, AllocatorType >@@g' html/*.html - $(SED) -i 's@< ObjectType, ArrayType, StringType, BooleanType, NumberIntegerType, NumberUnsignedType, NumberFloatType, AllocatorType >@@g' html/*.html - $(SED) -i 's@< ObjectType, ArrayType, StringType, BooleanType, NumberIntegerType, NumberUnsignedType, NumberFloatType, AllocatorType >@@g' html/*.html - $(SED) -i 's@< ObjectType, ArrayType, StringType, BooleanType, NumberIntegerType, NumberUnsignedType, NumberFloatType, AllocatorType >@@g' html/*.html + $(SED) -i 's@< ObjectType, ArrayType, StringType, BooleanType, NumberIntegerType, NumberFloatType, AllocatorType, JSONSerializer >@@g' html/*.html + $(SED) -i 's@< ObjectType, ArrayType, StringType, BooleanType, NumberIntegerType, NumberFloatType, AllocatorType JSONSerializer >@@g' html/*.html + $(SED) -i 's@< ObjectType, ArrayType, StringType, BooleanType, NumberIntegerType, NumberUnsignedType, NumberFloatType, AllocatorType, JSONSerializer >@@g' html/*.html + $(SED) -i 's@< ObjectType, ArrayType, StringType, BooleanType, NumberIntegerType, NumberUnsignedType, NumberFloatType, AllocatorType, JSONSerializer >@@g' html/*.html + $(SED) -i 's@< ObjectType, ArrayType, StringType, BooleanType, NumberIntegerType, NumberUnsignedType, NumberFloatType, AllocatorType JSONSerializer >@@g' html/*.html upload: clean doxygen check_output cd html ; ../scripts/git-update-ghpages nlohmann/json diff --git a/src/json.hpp b/src/json.hpp index 4aedb967..ae01cd3a 100644 --- a/src/json.hpp +++ b/src/json.hpp @@ -8252,9 +8252,8 @@ class basic_json } private: - static constexpr size_t s_capacity = 30; - /// added capacity for leading '-' and trailing '\0' - std::array < char, s_capacity + 2 > m_buf{{}}; + /// a (hopefully) large enough character buffer + std::array < char, 64 > m_buf{{}}; template void x_write(NumberType x, /*is_integral=*/std::true_type) @@ -8266,23 +8265,24 @@ class basic_json return; } - static_assert(std::numeric_limits::digits10 <= s_capacity, - "unexpected NumberType"); - - const bool is_neg = x < 0; + const bool is_negative = x < 0; size_t i = 0; - while (x != 0 and i < s_capacity) + // spare 1 byte for '\0' + while (x != 0 and i < m_buf.size() - 1) { const auto digit = std::labs(static_cast(x % 10)); m_buf[i++] = static_cast('0' + digit); x /= 10; } - assert(i < s_capacity); + // make sure the number has been processed completely + assert(x == 0); - if (is_neg) + if (is_negative) { + // make sure there is capacity for the '-' + assert(i < m_buf.size() - 2); m_buf[i++] = '-'; } @@ -8306,11 +8306,16 @@ class basic_json return; } + // get number of digits for a text -> float -> text round-trip static constexpr auto d = std::numeric_limits::digits10; - static_assert(d == 6 or d == 15 or d == 16 or d == 17, - "unexpected NumberType"); - snprintf(m_buf.data(), m_buf.size(), "%.*g", d, x); + // the actual conversion + const auto written_bytes = snprintf(m_buf.data(), m_buf.size(), "%.*g", d, x); + + // negative value indicates an error + assert(written_bytes > 0); + // check if buffer was large enough + assert(written_bytes < m_buf.size()); // read information from locale const auto loc = localeconv(); @@ -8324,7 +8329,7 @@ class basic_json // erase thousands separator if (thousands_sep != '\0') { - const auto end = std::remove(m_buf.begin(), m_buf.end(), thousands_sep); + const auto end = std::remove(m_buf.begin(), m_buf.begin() + written_bytes, thousands_sep); std::fill(end, m_buf.end(), '\0'); } diff --git a/src/json.hpp.re2c b/src/json.hpp.re2c index 0ceb4793..87a50c70 100644 --- a/src/json.hpp.re2c +++ b/src/json.hpp.re2c @@ -8252,9 +8252,8 @@ class basic_json } private: - static constexpr size_t s_capacity = 30; - /// added capacity for leading '-' and trailing '\0' - std::array < char, s_capacity + 2 > m_buf{{}}; + /// a (hopefully) large enough character buffer + std::array < char, 64 > m_buf{{}}; template void x_write(NumberType x, /*is_integral=*/std::true_type) @@ -8266,23 +8265,24 @@ class basic_json return; } - static_assert(std::numeric_limits::digits10 <= s_capacity, - "unexpected NumberType"); - - const bool is_neg = x < 0; + const bool is_negative = x < 0; size_t i = 0; - while (x != 0 and i < s_capacity) + // spare 1 byte for '\0' + while (x != 0 and i < m_buf.size() - 1) { const auto digit = std::labs(static_cast(x % 10)); m_buf[i++] = static_cast('0' + digit); x /= 10; } - assert(i < s_capacity); + // make sure the number has been processed completely + assert(x == 0); - if (is_neg) + if (is_negative) { + // make sure there is capacity for the '-' + assert(i < m_buf.size() - 2); m_buf[i++] = '-'; } @@ -8306,11 +8306,16 @@ class basic_json return; } + // get number of digits for a text -> float -> text round-trip static constexpr auto d = std::numeric_limits::digits10; - static_assert(d == 6 or d == 15 or d == 16 or d == 17, - "unexpected NumberType"); - snprintf(m_buf.data(), m_buf.size(), "%.*g", d, x); + // the actual conversion + const auto written_bytes = snprintf(m_buf.data(), m_buf.size(), "%.*g", d, x); + + // negative value indicates an error + assert(written_bytes > 0); + // check if buffer was large enough + assert(written_bytes < m_buf.size()); // read information from locale const auto loc = localeconv(); @@ -8324,7 +8329,7 @@ class basic_json // erase thousands separator if (thousands_sep != '\0') { - const auto end = std::remove(m_buf.begin(), m_buf.end(), thousands_sep); + const auto end = std::remove(m_buf.begin(), m_buf.begin() + written_bytes, thousands_sep); std::fill(end, m_buf.end(), '\0'); } From 345a106d73762d9954ddad8105e0db3301ad0402 Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Wed, 22 Feb 2017 16:56:56 +0100 Subject: [PATCH 76/80] :lipstick: cleanup --- README.md | 2 +- src/json.hpp | 2 +- src/json.hpp.re2c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index dee3fb7e..4d897a4c 100644 --- a/README.md +++ b/README.md @@ -857,7 +857,7 @@ $ make json_unit -Ctest $ ./test/json_unit "*"" =============================================================================== -All tests passed (11202588 assertions in 47 test cases) +All tests passed (11202596 assertions in 47 test cases) ``` Alternatively, you can use [CMake](https://cmake.org) and run diff --git a/src/json.hpp b/src/json.hpp index ae01cd3a..6fcfc3e1 100644 --- a/src/json.hpp +++ b/src/json.hpp @@ -8315,7 +8315,7 @@ class basic_json // negative value indicates an error assert(written_bytes > 0); // check if buffer was large enough - assert(written_bytes < m_buf.size()); + assert(static_cast(written_bytes) < m_buf.size()); // read information from locale const auto loc = localeconv(); diff --git a/src/json.hpp.re2c b/src/json.hpp.re2c index 87a50c70..a33da4b3 100644 --- a/src/json.hpp.re2c +++ b/src/json.hpp.re2c @@ -8315,7 +8315,7 @@ class basic_json // negative value indicates an error assert(written_bytes > 0); // check if buffer was large enough - assert(written_bytes < m_buf.size()); + assert(static_cast(written_bytes) < m_buf.size()); // read information from locale const auto loc = localeconv(); From 8cec55a271d4aa7db644a0e4180643b24413d31d Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Wed, 22 Feb 2017 18:14:29 +0100 Subject: [PATCH 77/80] :construction: fixed more warnings --- Makefile | 22 ++++++++++++++++++++++ src/json.hpp | 30 ++++++++++++++++++++++-------- src/json.hpp.re2c | 30 ++++++++++++++++++++++-------- test/src/unit-allocator.cpp | 6 +++--- test/src/unit-cbor.cpp | 2 +- test/src/unit-constructor1.cpp | 2 +- test/src/unit-msgpack.cpp | 4 ++-- test/src/unit-readme.cpp | 2 +- test/src/unit-regression.cpp | 12 ++++++------ test/src/unit-testsuites.cpp | 2 ++ 10 files changed, 82 insertions(+), 30 deletions(-) diff --git a/Makefile b/Makefile index 8bd7a2dd..ac75bcaf 100644 --- a/Makefile +++ b/Makefile @@ -41,6 +41,28 @@ doctest: $(MAKE) check_output -C doc +########################################################################## +# warning detector +########################################################################## + +# calling Clang with all warnings, except: +# -Wno-documentation-unknown-command: code uses user-defined commands like @complexity +# -Wno-exit-time-destructors: warning in Catch code +# -Wno-keyword-macro: unit-tests use "#define private public" +# -Wno-deprecated-declarations: some functions are deprecated until 3.0.0 +# -Wno-range-loop-analysis: iterator_wrapper tests tests "for(const auto i...)" +pedantic: + $(MAKE) json_unit CXXFLAGS="\ + -std=c++11 \ + -Werror \ + -Weverything \ + -Wno-documentation-unknown-command \ + -Wno-exit-time-destructors \ + -Wno-keyword-macro \ + -Wno-deprecated-declarations \ + -Wno-range-loop-analysis" + + ########################################################################## # fuzzing ########################################################################## diff --git a/src/json.hpp b/src/json.hpp index 6fcfc3e1..ab07ed90 100644 --- a/src/json.hpp +++ b/src/json.hpp @@ -673,7 +673,7 @@ template::value, int> = 0> void from_json(const BasicJsonType& j, UnscopedEnumType& e) { - typename std::underlying_type::type val = e; + typename std::underlying_type::type val; get_arithmetic_value(j, val); e = static_cast(val); } @@ -917,7 +917,7 @@ struct adl_serializer @ref basic_json class (either explicit or via conversion operators). @param[in] j JSON value to read from - @param[in, out] val value to write to + @param[in,out] val value to write to */ template static void from_json(BasicJsonType&& j, ValueType& val) noexcept( @@ -932,7 +932,7 @@ struct adl_serializer This function is usually called by the constructors of the @ref basic_json class. - @param[in, out] j JSON value to write to + @param[in,out] j JSON value to write to @param[in] val value to read from */ template @@ -6537,6 +6537,11 @@ class basic_json /// @{ private: + /*! + @note Some code in the switch cases has been copied, because otherwise + copilers would complain about implicit fallthrough and there is no + portable attribute to mute such warnings. + */ template static void add_to_vector(std::vector& vec, size_t bytes, const T number) { @@ -6550,20 +6555,27 @@ class basic_json vec.push_back(static_cast((static_cast(number) >> 060) & 0xff)); vec.push_back(static_cast((static_cast(number) >> 050) & 0xff)); vec.push_back(static_cast((static_cast(number) >> 040) & 0xff)); - // intentional fall-through + vec.push_back(static_cast((number >> 030) & 0xff)); + vec.push_back(static_cast((number >> 020) & 0xff)); + vec.push_back(static_cast((number >> 010) & 0xff)); + vec.push_back(static_cast(number & 0xff)); + break; } case 4: { vec.push_back(static_cast((number >> 030) & 0xff)); vec.push_back(static_cast((number >> 020) & 0xff)); - // intentional fall-through + vec.push_back(static_cast((number >> 010) & 0xff)); + vec.push_back(static_cast(number & 0xff)); + break; } case 2: { vec.push_back(static_cast((number >> 010) & 0xff)); - // intentional fall-through + vec.push_back(static_cast(number & 0xff)); + break; } case 1: @@ -7865,7 +7877,9 @@ class basic_json } else { - val = mant == 0 ? INFINITY : NAN; + val = mant == 0 + ? std::numeric_limits::infinity() + : std::numeric_limits::quiet_NaN(); } return (half & 0x8000) != 0 ? -val : val; } @@ -11181,7 +11195,7 @@ basic_json_parser_74: // of characters determined by the lexer (len) const bool ok = (endptr == (data + len)); - if (ok and (value == 0.0) and (*data == '-')) + if (ok and (value == static_cast(0.0)) and (*data == '-')) { // some implementations forget to negate the zero value = -0.0; diff --git a/src/json.hpp.re2c b/src/json.hpp.re2c index a33da4b3..6fda8290 100644 --- a/src/json.hpp.re2c +++ b/src/json.hpp.re2c @@ -673,7 +673,7 @@ template::value, int> = 0> void from_json(const BasicJsonType& j, UnscopedEnumType& e) { - typename std::underlying_type::type val = e; + typename std::underlying_type::type val; get_arithmetic_value(j, val); e = static_cast(val); } @@ -917,7 +917,7 @@ struct adl_serializer @ref basic_json class (either explicit or via conversion operators). @param[in] j JSON value to read from - @param[in, out] val value to write to + @param[in,out] val value to write to */ template static void from_json(BasicJsonType&& j, ValueType& val) noexcept( @@ -932,7 +932,7 @@ struct adl_serializer This function is usually called by the constructors of the @ref basic_json class. - @param[in, out] j JSON value to write to + @param[in,out] j JSON value to write to @param[in] val value to read from */ template @@ -6537,6 +6537,11 @@ class basic_json /// @{ private: + /*! + @note Some code in the switch cases has been copied, because otherwise + copilers would complain about implicit fallthrough and there is no + portable attribute to mute such warnings. + */ template static void add_to_vector(std::vector& vec, size_t bytes, const T number) { @@ -6550,20 +6555,27 @@ class basic_json vec.push_back(static_cast((static_cast(number) >> 060) & 0xff)); vec.push_back(static_cast((static_cast(number) >> 050) & 0xff)); vec.push_back(static_cast((static_cast(number) >> 040) & 0xff)); - // intentional fall-through + vec.push_back(static_cast((number >> 030) & 0xff)); + vec.push_back(static_cast((number >> 020) & 0xff)); + vec.push_back(static_cast((number >> 010) & 0xff)); + vec.push_back(static_cast(number & 0xff)); + break; } case 4: { vec.push_back(static_cast((number >> 030) & 0xff)); vec.push_back(static_cast((number >> 020) & 0xff)); - // intentional fall-through + vec.push_back(static_cast((number >> 010) & 0xff)); + vec.push_back(static_cast(number & 0xff)); + break; } case 2: { vec.push_back(static_cast((number >> 010) & 0xff)); - // intentional fall-through + vec.push_back(static_cast(number & 0xff)); + break; } case 1: @@ -7865,7 +7877,9 @@ class basic_json } else { - val = mant == 0 ? INFINITY : NAN; + val = mant == 0 + ? std::numeric_limits::infinity() + : std::numeric_limits::quiet_NaN(); } return (half & 0x8000) != 0 ? -val : val; } @@ -10215,7 +10229,7 @@ class basic_json // of characters determined by the lexer (len) const bool ok = (endptr == (data + len)); - if (ok and (value == 0.0) and (*data == '-')) + if (ok and (value == static_cast(0.0)) and (*data == '-')) { // some implementations forget to negate the zero value = -0.0; diff --git a/test/src/unit-allocator.cpp b/test/src/unit-allocator.cpp index 9fc2681f..78a48115 100644 --- a/test/src/unit-allocator.cpp +++ b/test/src/unit-allocator.cpp @@ -63,9 +63,9 @@ TEST_CASE("bad_alloc") } } -bool next_construct_fails = false; -bool next_destroy_fails = false; -bool next_deallocate_fails = false; +static bool next_construct_fails = false; +static bool next_destroy_fails = false; +static bool next_deallocate_fails = false; template struct my_allocator : std::allocator diff --git a/test/src/unit-cbor.cpp b/test/src/unit-cbor.cpp index b22f744e..da5603e8 100644 --- a/test/src/unit-cbor.cpp +++ b/test/src/unit-cbor.cpp @@ -237,7 +237,7 @@ TEST_CASE("CBOR") const auto result = json::to_cbor(j); CHECK(result == expected); - int16_t restored = -1 - ((result[1] << 8) + result[2]); + int16_t restored = static_cast(-1 - ((result[1] << 8) + result[2])); CHECK(restored == -9263); // roundtrip diff --git a/test/src/unit-constructor1.cpp b/test/src/unit-constructor1.cpp index 93546c5f..36666746 100644 --- a/test/src/unit-constructor1.cpp +++ b/test/src/unit-constructor1.cpp @@ -725,7 +725,7 @@ TEST_CASE("constructors") SECTION("long double") { - long double n = 42.23; + long double n = 42.23l; json j(n); CHECK(j.type() == json::value_t::number_float); CHECK(j.m_value.number_float == Approx(j_reference.m_value.number_float)); diff --git a/test/src/unit-msgpack.cpp b/test/src/unit-msgpack.cpp index cc459fee..2f79d31b 100644 --- a/test/src/unit-msgpack.cpp +++ b/test/src/unit-msgpack.cpp @@ -342,7 +342,7 @@ TEST_CASE("MessagePack") const auto result = json::to_msgpack(j); CHECK(result == expected); - int16_t restored = (result[1] << 8) + result[2]; + int16_t restored = static_cast((result[1] << 8) + result[2]); CHECK(restored == -9263); // roundtrip @@ -374,7 +374,7 @@ TEST_CASE("MessagePack") // check individual bytes CHECK(result[0] == 0xd1); - int16_t restored = (result[1] << 8) + result[2]; + int16_t restored = static_cast((result[1] << 8) + result[2]); CHECK(restored == i); // roundtrip diff --git a/test/src/unit-readme.cpp b/test/src/unit-readme.cpp index 061aadb4..954b7440 100644 --- a/test/src/unit-readme.cpp +++ b/test/src/unit-readme.cpp @@ -163,7 +163,7 @@ TEST_CASE("README", "[hide]") j.clear(); // the array is empty again // comparison - j == "[\"foo\", 1, true]"_json; // true + bool x = (j == "[\"foo\", 1, true]"_json); // true // create an object json o; diff --git a/test/src/unit-regression.cpp b/test/src/unit-regression.cpp index e476d933..bfa4d497 100644 --- a/test/src/unit-regression.cpp +++ b/test/src/unit-regression.cpp @@ -350,8 +350,8 @@ TEST_CASE("regression tests") // double nlohmann::basic_json j_double = - 1.23e35f; - CHECK(j_double.get() == 1.23e35f); + 1.23e35; + CHECK(j_double.get() == 1.23e35); // long double nlohmann::basic_json @@ -641,7 +641,7 @@ TEST_CASE("regression tests") CHECK_THROWS_AS(json::from_msgpack(vec1), std::out_of_range); // more test cases for MessagePack - for (uint8_t b : + for (auto b : { 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, // fixmap 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, // fixarray @@ -649,12 +649,12 @@ TEST_CASE("regression tests") 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf }) { - std::vector vec(1, b); + std::vector vec(1, static_cast(b)); CHECK_THROWS_AS(json::from_msgpack(vec), std::out_of_range); } // more test cases for CBOR - for (uint8_t b : + for (auto b : { 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, // UTF-8 string @@ -664,7 +664,7 @@ TEST_CASE("regression tests") 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7 // map }) { - std::vector vec(1, b); + std::vector vec(1, static_cast(b)); CHECK_THROWS_AS(json::from_cbor(vec), std::out_of_range); } diff --git a/test/src/unit-testsuites.cpp b/test/src/unit-testsuites.cpp index 62e7e37e..ab1f689c 100644 --- a/test/src/unit-testsuites.cpp +++ b/test/src/unit-testsuites.cpp @@ -816,6 +816,8 @@ TEST_CASE("nst's JSONTestSuite") } } +std::string trim(const std::string& str); + // from http://stackoverflow.com/a/25829178/266378 std::string trim(const std::string& str) { From b49ce351ebc58d6394807e81481c24d8532cc02d Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Wed, 22 Feb 2017 20:48:29 +0100 Subject: [PATCH 78/80] :lipstick: fixed some warnings --- CMakeLists.txt | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 4bce30ee..88c9e62b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -25,7 +25,7 @@ target_include_directories(${JSON_TARGET_NAME} INTERFACE $) # create and configure the unit test target -if (BuildTests) +if(BuildTests) add_subdirectory(test) endif() @@ -41,17 +41,17 @@ write_basic_package_version_file("${CMAKE_CURRENT_BINARY_DIR}/${JSON_CONFIGVERSI # export the library target and store build directory in package registry export(TARGETS ${JSON_TARGET_NAME} - FILE "${CMAKE_CURRENT_BINARY_DIR}/${JSON_TARGETS_FILENAME}") + FILE "${CMAKE_CURRENT_BINARY_DIR}/${JSON_TARGETS_FILENAME}") export(PACKAGE ${JSON_PACKAGE_NAME}) # install library target and config files install(TARGETS ${JSON_TARGET_NAME} - EXPORT ${JSON_PACKAGE_NAME}) + EXPORT ${JSON_PACKAGE_NAME}) install(FILES "src/json.hpp" - DESTINATION ${JSON_INCLUDE_DESTINATION}) + DESTINATION ${JSON_INCLUDE_DESTINATION}) install(EXPORT ${JSON_PACKAGE_NAME} - FILE ${JSON_TARGETS_FILENAME} - DESTINATION ${JSON_CONFIG_DESTINATION}) + FILE ${JSON_TARGETS_FILENAME} + DESTINATION ${JSON_CONFIG_DESTINATION}) install(FILES "${CMAKE_CURRENT_BINARY_DIR}/${JSON_CONFIG_FILENAME}" - "${CMAKE_CURRENT_BINARY_DIR}/${JSON_CONFIGVERSION_FILENAME}" - DESTINATION ${JSON_CONFIG_DESTINATION}) + "${CMAKE_CURRENT_BINARY_DIR}/${JSON_CONFIGVERSION_FILENAME}" + DESTINATION ${JSON_CONFIG_DESTINATION}) From 0234e53e23b87249a4998f60e80308556a9c8946 Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Wed, 22 Feb 2017 20:48:52 +0100 Subject: [PATCH 79/80] :memo: added section on used third-party tools --- README.md | 32 +++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 4d897a4c..76042a09 100644 --- a/README.md +++ b/README.md @@ -26,6 +26,7 @@ - [Supported compilers](#supported-compilers) - [License](#license) - [Thanks](#thanks) +- [Used third-party tools](#used-third-party-tools) - [Projects using JSON for Modern C++](#projects-using-json-for-modern-c) - [Notes](#notes) - [Execute unit tests](#execute-unit-tests) @@ -824,11 +825,40 @@ I deeply appreciate the help of the following people. - [ukhegg](https://github.com/ukhegg) found proposed an improvement for the examples section. - [rswanson-ihi](https://github.com/rswanson-ihi) noted a type in the README. - [Mihai Stan](https://github.com/stanmihai4) fixed a bug in the comparison with `nullptr`s. - +- [Tushar Maheshwari](https://github.com/tusharpm) added [cotire](https://github.com/sakra/cotire) support to speed up the compilation. Thanks a lot for helping out! Please [let me know](mailto:mail@nlohmann.me) if I forgot someone. +## Used third-party tools + +The library itself contains of a single header file licensed under the MIT license. However, it is built, tested, documented, and whatnot using a lot of thirs-party tools and services. Thanks a lot! + +- [**American fuzzy lop**](http://lcamtuf.coredump.cx/afl/) for fuzz testing +- [**AppVeyor**](https://www.appveyor.com) for [continuous integration](https://ci.appveyor.com/project/nlohmann/json) on Windows +- [**Artistic Style**](http://astyle.sourceforge.net) for automatic source code identation +- [**benchpress**](https://github.com/sbs-ableton/benchpress) to benchmark the code +- [**Catch**](https://github.com/philsquared/Catch) for the unit tests +- [**Clang**](http://clang.llvm.org) for compilation with code sanitizers +- [**Cmake**](https://cmake.org) for build automation +- [**Codacity**](https://www.codacy.com) for further [code analysis](https://www.codacy.com/app/nlohmann/json) +- [**cotire**](https://github.com/sakra/cotire) to speed of compilation +- [**Coveralls**](https://coveralls.io) to measure [code coverage](https://coveralls.io/github/nlohmann/json) +- [**Coverity Scan**](https://scan.coverity.com) for [static analysis](https://scan.coverity.com/projects/nlohmann-json) +- [**cppcheck**](http://cppcheck.sourceforge.net) for static analysis +- [**cxxopts**](https://github.com/jarro2783/cxxopts) to let benchpress parse command-line parameters +- [**Doxygen**](http://www.stack.nl/~dimitri/doxygen/) to generate [documentation](https://nlohmann.github.io/json/) +- [**git-update-ghpages**](https://github.com/rstacruz/git-update-ghpages) to upload the documentation to gh-pages +- [**Github Changelog Generator**](https://github.com/skywinder/github-changelog-generator) to generate the [ChangeLog](https://github.com/nlohmann/json/blob/develop/ChangeLog.md) +- [**libFuzzer**](http://llvm.org/docs/LibFuzzer.html) to implement fuzz testing for OSS-Fuzz +- [**OSS-Fuzz**](https://github.com/google/oss-fuzz) for continuous fuzz testing of the library +- [**re2c**](http://re2c.org) to generate an automaton for the lexical analysis +- [**send_to_wandbox**](https://github.com/nlohmann/json/blob/develop/doc/scripts/send_to_wandbox.py) to send code examples to [Wandbox](http://melpon.org/wandbox) +- [**Travis**](https://travis-ci.org) for [continuous integration](https://travis-ci.org/nlohmann/json) on Linux and macOS +- [**Valgrind**](http://valgrind.org) to check for correct memory management +- [**Wandbox**](http://melpon.org/wandbox) for [online examples](http://melpon.org/wandbox/permlink/4NEU6ZZMoM9lpIex) + + ## Projects using JSON for Modern C++ The library is currently used in Apple macOS Sierra and iOS 10. I am not sure what they are using the library for, but I am happy that it runs on so many devices. From 27c65b860bd5dde57dddc1bdc4aa8f64a1b0a645 Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Sat, 25 Feb 2017 16:34:38 +0100 Subject: [PATCH 80/80] :bookmark: version 2.1.1 --- CMakeLists.txt | 2 +- ChangeLog.md | 36 +++++++++++++++++++++++++ README.md | 2 +- doc/Doxyfile | 2 +- doc/examples/meta.output | 4 +-- doc/index.md | 2 +- doc/json.gif | Bin 1457913 -> 1457468 bytes src/json.hpp | 12 ++++----- src/json.hpp.re2c | 12 ++++----- test/src/fuzzer-driver_afl.cpp | 2 +- test/src/fuzzer-parse_cbor.cpp | 2 +- test/src/fuzzer-parse_json.cpp | 2 +- test/src/fuzzer-parse_msgpack.cpp | 2 +- test/src/unit-algorithms.cpp | 2 +- test/src/unit-allocator.cpp | 2 +- test/src/unit-capacity.cpp | 2 +- test/src/unit-cbor.cpp | 2 +- test/src/unit-class_const_iterator.cpp | 2 +- test/src/unit-class_iterator.cpp | 2 +- test/src/unit-class_lexer.cpp | 2 +- test/src/unit-class_parser.cpp | 2 +- test/src/unit-comparison.cpp | 2 +- test/src/unit-concepts.cpp | 2 +- test/src/unit-constructor1.cpp | 2 +- test/src/unit-constructor2.cpp | 2 +- test/src/unit-convenience.cpp | 2 +- test/src/unit-conversions.cpp | 2 +- test/src/unit-deserialization.cpp | 2 +- test/src/unit-element_access1.cpp | 2 +- test/src/unit-element_access2.cpp | 2 +- test/src/unit-inspection.cpp | 2 +- test/src/unit-iterator_wrapper.cpp | 2 +- test/src/unit-iterators1.cpp | 2 +- test/src/unit-iterators2.cpp | 2 +- test/src/unit-json_patch.cpp | 2 +- test/src/unit-json_pointer.cpp | 2 +- test/src/unit-meta.cpp | 9 ++++++- test/src/unit-modifiers.cpp | 2 +- test/src/unit-msgpack.cpp | 2 +- test/src/unit-noexcept.cpp | 2 +- test/src/unit-pointer_access.cpp | 2 +- test/src/unit-readme.cpp | 2 +- test/src/unit-reference_access.cpp | 2 +- test/src/unit-regression.cpp | 2 +- test/src/unit-serialization.cpp | 2 +- test/src/unit-testsuites.cpp | 2 +- test/src/unit-udt.cpp | 2 +- test/src/unit-unicode.cpp | 2 +- test/src/unit.cpp | 2 +- 49 files changed, 101 insertions(+), 58 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 88c9e62b..30e39666 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_minimum_required(VERSION 3.0) # define the project -project(nlohmann_json VERSION 2.1.0 LANGUAGES CXX) +project(nlohmann_json VERSION 2.1.1 LANGUAGES CXX) enable_testing() diff --git a/ChangeLog.md b/ChangeLog.md index 0e2f8dae..76244c5d 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -1,6 +1,40 @@ # Change Log All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/). +## [v2.1.1](https://github.com/nlohmann/json/releases/tag/v2.1.1) (2017-02-25) +[Full Changelog](https://github.com/nlohmann/json/compare/v2.1.0...v2.1.1) + +- warning in the library [\#472](https://github.com/nlohmann/json/issues/472) +- How to create an array of Objects? [\#470](https://github.com/nlohmann/json/issues/470) +- \[Bug?\] Cannot get int pointer, but int64\_t works [\#468](https://github.com/nlohmann/json/issues/468) +- Illegal indirection [\#467](https://github.com/nlohmann/json/issues/467) +- in vs can't find linkageId [\#466](https://github.com/nlohmann/json/issues/466) +- Roundtrip error while parsing "1000000000000000010E5" [\#465](https://github.com/nlohmann/json/issues/465) +- C4996 error and warning with Visual Studio [\#463](https://github.com/nlohmann/json/issues/463) +- Support startIndex for from\_cbor/from\_msgpack [\#462](https://github.com/nlohmann/json/issues/462) +- question: monospace font used in feature slideshow? [\#460](https://github.com/nlohmann/json/issues/460) +- Object.keys\(\) [\#459](https://github.com/nlohmann/json/issues/459) +- Use “, “ as delimiter for json-objects. [\#457](https://github.com/nlohmann/json/issues/457) +- Enum -\> string during serialization and vice versa [\#455](https://github.com/nlohmann/json/issues/455) +- doubles are printed as integers [\#454](https://github.com/nlohmann/json/issues/454) +- Warnings with Visual Studio c++ \(VS2015 Update 3\) [\#453](https://github.com/nlohmann/json/issues/453) +- Heap-buffer-overflow \(OSS-Fuzz issue 585\) [\#452](https://github.com/nlohmann/json/issues/452) +- use of undeclared identifier 'UINT8\_MAX' [\#451](https://github.com/nlohmann/json/issues/451) +- Question on the lifetime managment of objects at the lower levels [\#449](https://github.com/nlohmann/json/issues/449) +- Json should not be constructible with 'json\*' [\#448](https://github.com/nlohmann/json/issues/448) +- Move value\_t to namespace scope [\#447](https://github.com/nlohmann/json/issues/447) +- Typo in README.md [\#446](https://github.com/nlohmann/json/issues/446) +- make check compilation is unneccesarily slow [\#445](https://github.com/nlohmann/json/issues/445) +- Problem in dump\(\) in json.h caused by ss.imbue [\#444](https://github.com/nlohmann/json/issues/444) +- I want to create Windows Application in Visual Studio 2015 c++, and i have a problem [\#443](https://github.com/nlohmann/json/issues/443) +- Implicit conversion issues [\#442](https://github.com/nlohmann/json/issues/442) +- Parsing of floats locale dependent [\#302](https://github.com/nlohmann/json/issues/302) + +- Speedup CI builds using cotire [\#461](https://github.com/nlohmann/json/pull/461) ([tusharpm](https://github.com/tusharpm)) +- TurpentineDistillery feature/locale independent str to num [\#450](https://github.com/nlohmann/json/pull/450) ([nlohmann](https://github.com/nlohmann)) +- README: adjust boost::optional example [\#439](https://github.com/nlohmann/json/pull/439) ([jaredgrubb](https://github.com/jaredgrubb)) +- fix \#414 - comparing to 0 literal [\#415](https://github.com/nlohmann/json/pull/415) ([stanmihai4](https://github.com/stanmihai4)) + ## [v2.1.0](https://github.com/nlohmann/json/releases/tag/v2.1.0) (2017-01-28) [Full Changelog](https://github.com/nlohmann/json/compare/v2.0.10...v2.1.0) @@ -20,6 +54,7 @@ All notable changes to this project will be documented in this file. This projec - size parameter for parse\(\) [\#419](https://github.com/nlohmann/json/issues/419) - json.hpp forcibly defines GCC\_VERSION [\#417](https://github.com/nlohmann/json/issues/417) - Use-of-uninitialized-value \(OSS-Fuzz issue 377\) [\#416](https://github.com/nlohmann/json/issues/416) +- comparing to 0 literal [\#414](https://github.com/nlohmann/json/issues/414) - Single char converted to ASCII code instead of string [\#413](https://github.com/nlohmann/json/issues/413) - How to know if a string was parsed as utf-8? [\#406](https://github.com/nlohmann/json/issues/406) - Overloaded += to add objects to an array makes no sense? [\#404](https://github.com/nlohmann/json/issues/404) @@ -37,6 +72,7 @@ All notable changes to this project will be documented in this file. This projec - conversion from/to user-defined types [\#435](https://github.com/nlohmann/json/pull/435) ([nlohmann](https://github.com/nlohmann)) - Fix documentation error [\#430](https://github.com/nlohmann/json/pull/430) ([vjon](https://github.com/vjon)) +- locale-independent num-to-str [\#378](https://github.com/nlohmann/json/pull/378) ([TurpentineDistillery](https://github.com/TurpentineDistillery)) ## [v2.0.10](https://github.com/nlohmann/json/releases/tag/v2.0.10) (2017-01-02) [Full Changelog](https://github.com/nlohmann/json/compare/v2.0.9...v2.0.10) diff --git a/README.md b/README.md index 76042a09..1334180b 100644 --- a/README.md +++ b/README.md @@ -887,7 +887,7 @@ $ make json_unit -Ctest $ ./test/json_unit "*"" =============================================================================== -All tests passed (11202596 assertions in 47 test cases) +All tests passed (11202597 assertions in 47 test cases) ``` Alternatively, you can use [CMake](https://cmake.org) and run diff --git a/doc/Doxyfile b/doc/Doxyfile index b4f57863..27806a69 100644 --- a/doc/Doxyfile +++ b/doc/Doxyfile @@ -5,7 +5,7 @@ #--------------------------------------------------------------------------- DOXYFILE_ENCODING = UTF-8 PROJECT_NAME = "JSON for Modern C++" -PROJECT_NUMBER = 2.1.0 +PROJECT_NUMBER = 2.1.1 PROJECT_BRIEF = PROJECT_LOGO = OUTPUT_DIRECTORY = . diff --git a/doc/examples/meta.output b/doc/examples/meta.output index f361bb60..933aac0f 100644 --- a/doc/examples/meta.output +++ b/doc/examples/meta.output @@ -11,7 +11,7 @@ "version": { "major": 2, "minor": 1, - "patch": 0, - "string": "2.1.0" + "patch": 1, + "string": "2.1.1" } } diff --git a/doc/index.md b/doc/index.md index 2f12767f..9493412e 100644 --- a/doc/index.md +++ b/doc/index.md @@ -277,4 +277,4 @@ The container functions known from STL have been extended to support the differe @author [Niels Lohmann](http://nlohmann.me) @see https://github.com/nlohmann/json to download the source code -@version 2.1.0 +@version 2.1.1 diff --git a/doc/json.gif b/doc/json.gif index 9d05cfd691010a4cb1d930995334f72411c62bb6..2fbcde638d0883d9db4636ea5caa9cec1bef33e8 100644 GIT binary patch delta 48339 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 Vs7vTCVYr0x5_FsI98;|4{{Y!YhDHDY delta 48539 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

yC5qOk)@CC0>qU7|M-EbTeG>hJ226V-c@ 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 z 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