mirror of
				https://github.com/catchorg/Catch2.git
				synced 2025-10-31 04:07:10 +01:00 
			
		
		
		
	| @@ -140,6 +140,7 @@ set(INTERNAL_HEADERS | ||||
|         ${HEADER_DIR}/internal/catch_leak_detector.h | ||||
|         ${HEADER_DIR}/internal/catch_list.h | ||||
|         ${HEADER_DIR}/internal/catch_matchers.h | ||||
|         ${HEADER_DIR}/internal/catch_matchers_floating.h | ||||
|         ${HEADER_DIR}/internal/catch_matchers_string.h | ||||
|         ${HEADER_DIR}/internal/catch_matchers_vector.h | ||||
|         ${HEADER_DIR}/internal/catch_message.h | ||||
| @@ -206,6 +207,7 @@ set(IMPL_SOURCES | ||||
|         ${HEADER_DIR}/internal/catch_list.cpp | ||||
|         ${HEADER_DIR}/internal/catch_leak_detector.cpp | ||||
|         ${HEADER_DIR}/internal/catch_matchers.cpp | ||||
|         ${HEADER_DIR}/internal/catch_matchers_floating.cpp | ||||
|         ${HEADER_DIR}/internal/catch_matchers_string.cpp | ||||
|         ${HEADER_DIR}/internal/catch_message.cpp | ||||
|         ${HEADER_DIR}/internal/catch_registry_hub.cpp | ||||
|   | ||||
| @@ -36,10 +36,19 @@ REQUIRE_THAT( str, | ||||
| ``` | ||||
|  | ||||
| ## Built in matchers | ||||
| Currently Catch has some string matchers and some vector matchers. They are in the `Catch::Matchers` and `Catch` namespaces. | ||||
| Catch currently provides some matchers, they are in the `Catch::Matchers` and `Catch` namespaces. | ||||
|  | ||||
| ### String matchers | ||||
| The string matchers are `StartsWith`, `EndsWith`, `Contains` and `Equals`. Each of them also takes an optional second argument, that decides case sensitivity (by-default, they are case sensitive). | ||||
|  | ||||
| ### Vector matchers | ||||
| The vector matchers are `Contains`, `VectorContains` and `Equals`. `VectorContains` looks for a single element in the matched vector, `Contains` looks for a set (vector) of elements inside the matched vector. | ||||
|  | ||||
| ### Floating point matchers | ||||
| The floating point matchers are `WithinULP` and `WithinAbs`. `WithinAbs` accepts floating point numbers that are within a certain margin of target. `WithinULP` performs an [ULP](https://en.wikipedia.org/wiki/Unit_in_the_last_place)-based comparison of two floating point numbers and accepts them if they are less than certain number of ULPs apart. | ||||
|  | ||||
| Do note that ULP-based checks only make sense when both compared numbers are of the same type and `WithinULP` will use type of its argument as the target type. This means that `WithinULP(1.f, 1)` will expect to compare `float`s, but `WithinULP(1., 1)` will expect to compare `double`s. | ||||
|  | ||||
|  | ||||
| ## Custom matchers | ||||
| It's easy to provide your own matchers to extend Catch or just to work with your own types. | ||||
|   | ||||
| @@ -10,6 +10,7 @@ | ||||
|  | ||||
| #include "catch_capture.hpp" | ||||
| #include "catch_matchers.h" | ||||
| #include "catch_matchers_floating.h" | ||||
| #include "catch_matchers_string.h" | ||||
| #include "catch_matchers_vector.h" | ||||
|  | ||||
|   | ||||
							
								
								
									
										144
									
								
								include/internal/catch_matchers_floating.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										144
									
								
								include/internal/catch_matchers_floating.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,144 @@ | ||||
| /* | ||||
|  *  Created by Martin on 07/11/2017. | ||||
|  * | ||||
|  * Distributed under the Boost Software License, Version 1.0. (See accompanying | ||||
|  * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | ||||
|  */ | ||||
|  | ||||
| #include "catch_matchers_floating.h" | ||||
|  | ||||
| #include <cmath> | ||||
| #include <cstdint> | ||||
| #include <cstring> | ||||
| #include <stdexcept> | ||||
|  | ||||
| namespace Catch { | ||||
| namespace Matchers { | ||||
| namespace Floating { | ||||
| enum class FloatingPointKind : uint8_t { | ||||
|     Float, | ||||
|     Double | ||||
| }; | ||||
| } | ||||
| } | ||||
| } | ||||
|  | ||||
| namespace { | ||||
| union Float_t { | ||||
|     Float_t(float num = 0.0f) : f(num) {} | ||||
|     // Portable extraction of components. | ||||
|     bool Negative() const { return i < 0; } | ||||
|     int32_t RawMantissa() const { return i & ((1 << 23) - 1); } | ||||
|     int32_t RawExponent() const { return (i >> 23) & 0xFF; } | ||||
|  | ||||
|     int32_t i; | ||||
|     float f; | ||||
| }; | ||||
|  | ||||
| template <typename T> | ||||
| struct Converter; | ||||
|  | ||||
| template <> | ||||
| struct Converter<float> { | ||||
|     static_assert(sizeof(float) == sizeof(int32_t), "Important ULP matcher assumption violated"); | ||||
|     Converter(float f) { | ||||
|         std::memcpy(&i, &f, sizeof(f)); | ||||
|     } | ||||
|     int32_t i; | ||||
| }; | ||||
|  | ||||
| template <> | ||||
| struct Converter<double> { | ||||
|     static_assert(sizeof(double) == sizeof(int64_t), "Important ULP matcher assumption violated"); | ||||
|     Converter(double d) { | ||||
|         std::memcpy(&i, &d, sizeof(d)); | ||||
|     } | ||||
|     int64_t i; | ||||
| }; | ||||
|  | ||||
| template <typename T> | ||||
| auto convert(T t) -> Converter<T> { | ||||
|     return Converter<T>(t); | ||||
| } | ||||
|  | ||||
| template <typename FP> | ||||
| bool almostEqualUlps(FP lhs, FP rhs, int maxUlpDiff) { | ||||
|     // Comparison with NaN should always be false. | ||||
|     // This way we can rule it out before getting into the ugly details | ||||
|     if (std::isnan(lhs) || std::isnan(rhs)) { | ||||
|         return false; | ||||
|     } | ||||
|  | ||||
|     auto lc = convert(lhs); | ||||
|     auto rc = convert(rhs); | ||||
|  | ||||
|     if ((lc.i < 0) != (rc.i < 0)) { | ||||
|         // Potentially we can have +0 and -0 | ||||
|         return lhs == rhs; | ||||
|     } | ||||
|  | ||||
|     auto ulpDiff = abs(lc.i - rc.i); | ||||
|     return ulpDiff <= maxUlpDiff; | ||||
| } | ||||
|  | ||||
| } | ||||
|  | ||||
|  | ||||
| namespace Catch { | ||||
| namespace Matchers { | ||||
| namespace Floating { | ||||
|     WithinAbsMatcher::WithinAbsMatcher(double target, double margin) | ||||
|         :m_target{ target }, m_margin{ margin } {} | ||||
|  | ||||
|     // Performs equivalent check of std::fabs(lhs - rhs) <= margin | ||||
|     // But without the subtraction to allow for INFINITY in comparison | ||||
|     bool WithinAbsMatcher::match(double const& matchee) const { | ||||
|         return (matchee + m_margin >= m_target) && (m_target + m_margin >= m_margin); | ||||
|     } | ||||
|  | ||||
|     std::string WithinAbsMatcher::describe() const { | ||||
|         return "is within " + std::to_string(m_margin) + " of " + std::to_string(m_target); | ||||
|     } | ||||
|  | ||||
|  | ||||
|     WithinUlpsMatcher::WithinUlpsMatcher(double target, int ulps, FloatingPointKind baseType) | ||||
|         :m_target{ target }, m_ulps{ ulps }, m_type{ baseType } { | ||||
|         if (m_ulps < 0) { | ||||
|             throw std::domain_error("Expected ulp difference has to be >0"); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     bool WithinUlpsMatcher::match(double const& matchee) const { | ||||
|         switch (m_type) { | ||||
|         case FloatingPointKind::Float: | ||||
|             return almostEqualUlps<float>(static_cast<float>(matchee), static_cast<float>(m_target), m_ulps); | ||||
|         case FloatingPointKind::Double: | ||||
|             return almostEqualUlps<double>(matchee, m_target, m_ulps); | ||||
|         default: | ||||
|             throw std::domain_error("Unknown FloatingPointKind value"); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     std::string WithinUlpsMatcher::describe() const { | ||||
|         return "is within " + std::to_string(m_ulps) + " ULPs of " + std::to_string(m_target) + ((m_type == FloatingPointKind::Float)? "f" : ""); | ||||
|     } | ||||
|  | ||||
| }// namespace Floating | ||||
|  | ||||
|  | ||||
|  | ||||
| Floating::WithinUlpsMatcher WithinULP(double target, int maxUlpDiff) { | ||||
|     return Floating::WithinUlpsMatcher(target, maxUlpDiff, Floating::FloatingPointKind::Double); | ||||
| } | ||||
|  | ||||
| Floating::WithinUlpsMatcher WithinULP(float target, int maxUlpDiff) { | ||||
|     return Floating::WithinUlpsMatcher(target, maxUlpDiff, Floating::FloatingPointKind::Float); | ||||
| } | ||||
|  | ||||
| Floating::WithinAbsMatcher WithinAbs(double target, double margin) { | ||||
|     return Floating::WithinAbsMatcher(target, margin); | ||||
| } | ||||
|  | ||||
| } // namespace Matchers | ||||
| } // namespace Catch | ||||
|  | ||||
							
								
								
									
										59
									
								
								include/internal/catch_matchers_floating.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										59
									
								
								include/internal/catch_matchers_floating.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,59 @@ | ||||
| /* | ||||
|  *  Created by Martin on 07/11/2017. | ||||
|  * | ||||
|  * Distributed under the Boost Software License, Version 1.0. (See accompanying | ||||
|  * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | ||||
|  */ | ||||
| #ifndef TWOBLUECUBES_CATCH_MATCHERS_FLOATING_H_INCLUDED | ||||
| #define TWOBLUECUBES_CATCH_MATCHERS_FLOATING_H_INCLUDED | ||||
|  | ||||
| #include "catch_matchers.h" | ||||
|  | ||||
| #include <type_traits> | ||||
| #include <cmath> | ||||
|  | ||||
| namespace Catch { | ||||
| namespace Matchers { | ||||
|  | ||||
|     namespace Floating { | ||||
|  | ||||
|         enum class FloatingPointKind : uint8_t; | ||||
|  | ||||
|         struct WithinAbsMatcher : MatcherBase<double> { | ||||
|             WithinAbsMatcher(double target, double margin); | ||||
|             bool match(double const& matchee) const override; | ||||
|             std::string describe() const override; | ||||
|         private: | ||||
|             double m_target; | ||||
|             double m_margin; | ||||
|         }; | ||||
|  | ||||
|         struct WithinUlpsMatcher : MatcherBase<double> { | ||||
|             WithinUlpsMatcher(double target, int ulps, FloatingPointKind baseType); | ||||
|             bool match(double const& matchee) const override; | ||||
|             std::string describe() const override; | ||||
|         private: | ||||
|             double m_target; | ||||
|             int m_ulps; | ||||
|             FloatingPointKind m_type; | ||||
|         }; | ||||
|  | ||||
|  | ||||
|     } // namespace Floating | ||||
|  | ||||
|     Floating::WithinUlpsMatcher WithinULP(double target, int maxUlpDiff); | ||||
|     Floating::WithinUlpsMatcher WithinULP(float target, int maxUlpDiff); | ||||
|     Floating::WithinAbsMatcher WithinAbs(double target, double margin); | ||||
|  | ||||
|     // The following functions create the actual matcher objects. | ||||
|     // This allows the types to be inferred | ||||
|  | ||||
| //    StdString::EqualsMatcher Equals( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ); | ||||
| //    StdString::ContainsMatcher Contains( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ); | ||||
| //    StdString::EndsWithMatcher EndsWith( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ); | ||||
| //    StdString::StartsWithMatcher StartsWith( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ); | ||||
|  | ||||
| } // namespace Matchers | ||||
| } // namespace Catch | ||||
|  | ||||
| #endif // TWOBLUECUBES_CATCH_MATCHERS_FLOATING_H_INCLUDED | ||||
| @@ -1003,6 +1003,6 @@ with expansion: | ||||
|   "{?}" == "1" | ||||
|  | ||||
| =============================================================================== | ||||
| test cases: 185 | 134 passed | 47 failed |  4 failed as expected | ||||
| assertions: 904 | 787 passed | 96 failed | 21 failed as expected | ||||
| test cases: 187 | 136 passed | 47 failed |  4 failed as expected | ||||
| assertions: 935 | 818 passed | 96 failed | 21 failed as expected | ||||
|  | ||||
|   | ||||
| @@ -1717,6 +1717,234 @@ PASSED: | ||||
| with expansion: | ||||
|   3628800 (0x<hex digits>) == 3628800 (0x<hex digits>) | ||||
|  | ||||
| ------------------------------------------------------------------------------- | ||||
| Floating point matchers: double | ||||
|   Margin | ||||
| ------------------------------------------------------------------------------- | ||||
| MatchersTests.cpp:<line number> | ||||
| ............................................................................... | ||||
|  | ||||
| MatchersTests.cpp:<line number>: | ||||
| PASSED: | ||||
|   REQUIRE_THAT( 1., WithinAbs(1., 0) ) | ||||
| with expansion: | ||||
|   1.0 is within 0.000000 of 1.000000 | ||||
|  | ||||
| MatchersTests.cpp:<line number>: | ||||
| PASSED: | ||||
|   REQUIRE_THAT( 0., WithinAbs(1., 1) ) | ||||
| with expansion: | ||||
|   0.0 is within 1.000000 of 1.000000 | ||||
|  | ||||
| MatchersTests.cpp:<line number>: | ||||
| PASSED: | ||||
|   REQUIRE_THAT( 0., !WithinAbs(1., 0.99) ) | ||||
| with expansion: | ||||
|   0.0 not is within 0.990000 of 1.000000 | ||||
|  | ||||
| MatchersTests.cpp:<line number>: | ||||
| PASSED: | ||||
|   REQUIRE_THAT( 0., !WithinAbs(1., 0.99) ) | ||||
| with expansion: | ||||
|   0.0 not is within 0.990000 of 1.000000 | ||||
|  | ||||
| MatchersTests.cpp:<line number>: | ||||
| PASSED: | ||||
|   REQUIRE_THAT( NAN, !WithinAbs(NAN, 0) ) | ||||
| with expansion: | ||||
|   nanf not is within 0.000000 of nan | ||||
|  | ||||
| ------------------------------------------------------------------------------- | ||||
| Floating point matchers: double | ||||
|   ULPs | ||||
| ------------------------------------------------------------------------------- | ||||
| MatchersTests.cpp:<line number> | ||||
| ............................................................................... | ||||
|  | ||||
| MatchersTests.cpp:<line number>: | ||||
| PASSED: | ||||
|   REQUIRE_THAT( 1., WithinULP(1., 0) ) | ||||
| with expansion: | ||||
|   1.0 is within 0 ULPs of 1.000000 | ||||
|  | ||||
| MatchersTests.cpp:<line number>: | ||||
| PASSED: | ||||
|   REQUIRE_THAT( std::nextafter(1., 2.), WithinULP(1., 1) ) | ||||
| with expansion: | ||||
|   1.0 is within 1 ULPs of 1.000000 | ||||
|  | ||||
| MatchersTests.cpp:<line number>: | ||||
| PASSED: | ||||
|   REQUIRE_THAT( std::nextafter(1., 0.), WithinULP(1., 1) ) | ||||
| with expansion: | ||||
|   1.0 is within 1 ULPs of 1.000000 | ||||
|  | ||||
| MatchersTests.cpp:<line number>: | ||||
| PASSED: | ||||
|   REQUIRE_THAT( std::nextafter(1., 2.), !WithinULP(1., 0) ) | ||||
| with expansion: | ||||
|   1.0 not is within 0 ULPs of 1.000000 | ||||
|  | ||||
| MatchersTests.cpp:<line number>: | ||||
| PASSED: | ||||
|   REQUIRE_THAT( 1., WithinULP(1., 0) ) | ||||
| with expansion: | ||||
|   1.0 is within 0 ULPs of 1.000000 | ||||
|  | ||||
| MatchersTests.cpp:<line number>: | ||||
| PASSED: | ||||
|   REQUIRE_THAT( -0., WithinULP(0., 0) ) | ||||
| with expansion: | ||||
|   -0.0 is within 0 ULPs of 0.000000 | ||||
|  | ||||
| MatchersTests.cpp:<line number>: | ||||
| PASSED: | ||||
|   REQUIRE_THAT( NAN, !WithinULP(NAN, 123) ) | ||||
| with expansion: | ||||
|   nanf not is within 123 ULPs of nanf | ||||
|  | ||||
| ------------------------------------------------------------------------------- | ||||
| Floating point matchers: double | ||||
|   Composed | ||||
| ------------------------------------------------------------------------------- | ||||
| MatchersTests.cpp:<line number> | ||||
| ............................................................................... | ||||
|  | ||||
| MatchersTests.cpp:<line number>: | ||||
| PASSED: | ||||
|   REQUIRE_THAT( 1., WithinAbs(1., 0.5) || WithinULP(2., 1) ) | ||||
| with expansion: | ||||
|   1.0 ( is within 0.500000 of 1.000000 or is within 1 ULPs of 2.000000 ) | ||||
|  | ||||
| MatchersTests.cpp:<line number>: | ||||
| PASSED: | ||||
|   REQUIRE_THAT( 1., WithinAbs(2., 0.5) || WithinULP(1., 0) ) | ||||
| with expansion: | ||||
|   1.0 ( is within 0.500000 of 2.000000 or is within 0 ULPs of 1.000000 ) | ||||
|  | ||||
| MatchersTests.cpp:<line number>: | ||||
| PASSED: | ||||
|   REQUIRE_THAT( NAN, !(WithinAbs(NAN, 100) || WithinULP(NAN, 123)) ) | ||||
| with expansion: | ||||
|   nanf not ( is within 100.000000 of nan or is within 123 ULPs of nanf ) | ||||
|  | ||||
| ------------------------------------------------------------------------------- | ||||
| Floating point matchers: float | ||||
|   Margin | ||||
| ------------------------------------------------------------------------------- | ||||
| MatchersTests.cpp:<line number> | ||||
| ............................................................................... | ||||
|  | ||||
| MatchersTests.cpp:<line number>: | ||||
| PASSED: | ||||
|   REQUIRE_THAT( 1.f, WithinAbs(1.f, 0) ) | ||||
| with expansion: | ||||
|   1.0f is within 0.000000 of 1.000000 | ||||
|  | ||||
| MatchersTests.cpp:<line number>: | ||||
| PASSED: | ||||
|   REQUIRE_THAT( 0.f, WithinAbs(1.f, 1) ) | ||||
| with expansion: | ||||
|   0.0f is within 1.000000 of 1.000000 | ||||
|  | ||||
| MatchersTests.cpp:<line number>: | ||||
| PASSED: | ||||
|   REQUIRE_THAT( 0.f, !WithinAbs(1.f, 0.99f) ) | ||||
| with expansion: | ||||
|   0.0f not is within 0.990000 of 1.000000 | ||||
|  | ||||
| MatchersTests.cpp:<line number>: | ||||
| PASSED: | ||||
|   REQUIRE_THAT( 0.f, !WithinAbs(1.f, 0.99f) ) | ||||
| with expansion: | ||||
|   0.0f not is within 0.990000 of 1.000000 | ||||
|  | ||||
| MatchersTests.cpp:<line number>: | ||||
| PASSED: | ||||
|   REQUIRE_THAT( 0.f, WithinAbs(-0.f, 0) ) | ||||
| with expansion: | ||||
|   0.0f is within 0.000000 of -0.000000 | ||||
|  | ||||
| MatchersTests.cpp:<line number>: | ||||
| PASSED: | ||||
|   REQUIRE_THAT( NAN, !WithinAbs(NAN, 0) ) | ||||
| with expansion: | ||||
|   nanf not is within 0.000000 of nan | ||||
|  | ||||
| ------------------------------------------------------------------------------- | ||||
| Floating point matchers: float | ||||
|   ULPs | ||||
| ------------------------------------------------------------------------------- | ||||
| MatchersTests.cpp:<line number> | ||||
| ............................................................................... | ||||
|  | ||||
| MatchersTests.cpp:<line number>: | ||||
| PASSED: | ||||
|   REQUIRE_THAT( 1.f, WithinULP(1.f, 0) ) | ||||
| with expansion: | ||||
|   1.0f is within 0 ULPs of 1.000000f | ||||
|  | ||||
| MatchersTests.cpp:<line number>: | ||||
| PASSED: | ||||
|   REQUIRE_THAT( std::nextafter(1.f, 2.f), WithinULP(1.f, 1) ) | ||||
| with expansion: | ||||
|   1.0f is within 1 ULPs of 1.000000f | ||||
|  | ||||
| MatchersTests.cpp:<line number>: | ||||
| PASSED: | ||||
|   REQUIRE_THAT( std::nextafter(1.f, 0.f), WithinULP(1.f, 1) ) | ||||
| with expansion: | ||||
|   1.0f is within 1 ULPs of 1.000000f | ||||
|  | ||||
| MatchersTests.cpp:<line number>: | ||||
| PASSED: | ||||
|   REQUIRE_THAT( std::nextafter(1.f, 2.f), !WithinULP(1.f, 0) ) | ||||
| with expansion: | ||||
|   1.0f not is within 0 ULPs of 1.000000f | ||||
|  | ||||
| MatchersTests.cpp:<line number>: | ||||
| PASSED: | ||||
|   REQUIRE_THAT( 1.f, WithinULP(1.f, 0) ) | ||||
| with expansion: | ||||
|   1.0f is within 0 ULPs of 1.000000f | ||||
|  | ||||
| MatchersTests.cpp:<line number>: | ||||
| PASSED: | ||||
|   REQUIRE_THAT( -0.f, WithinULP(0.f, 0) ) | ||||
| with expansion: | ||||
|   -0.0f is within 0 ULPs of 0.000000f | ||||
|  | ||||
| MatchersTests.cpp:<line number>: | ||||
| PASSED: | ||||
|   REQUIRE_THAT( NAN, !WithinULP(NAN, 123) ) | ||||
| with expansion: | ||||
|   nanf not is within 123 ULPs of nanf | ||||
|  | ||||
| ------------------------------------------------------------------------------- | ||||
| Floating point matchers: float | ||||
|   Composed | ||||
| ------------------------------------------------------------------------------- | ||||
| MatchersTests.cpp:<line number> | ||||
| ............................................................................... | ||||
|  | ||||
| MatchersTests.cpp:<line number>: | ||||
| PASSED: | ||||
|   REQUIRE_THAT( 1.f, WithinAbs(1.f, 0.5) || WithinULP(1.f, 1) ) | ||||
| with expansion: | ||||
|   1.0f ( is within 0.500000 of 1.000000 or is within 1 ULPs of 1.000000f ) | ||||
|  | ||||
| MatchersTests.cpp:<line number>: | ||||
| PASSED: | ||||
|   REQUIRE_THAT( 1.f, WithinAbs(2.f, 0.5) || WithinULP(1.f, 0) ) | ||||
| with expansion: | ||||
|   1.0f ( is within 0.500000 of 2.000000 or is within 0 ULPs of 1.000000f ) | ||||
|  | ||||
| MatchersTests.cpp:<line number>: | ||||
| PASSED: | ||||
|   REQUIRE_THAT( NAN, !(WithinAbs(NAN, 100) || WithinULP(NAN, 123)) ) | ||||
| with expansion: | ||||
|   nanf not ( is within 100.000000 of nan or is within 123 ULPs of nanf ) | ||||
|  | ||||
| ------------------------------------------------------------------------------- | ||||
| Greater-than inequalities with different epsilons | ||||
| ------------------------------------------------------------------------------- | ||||
| @@ -7632,6 +7860,6 @@ MiscTests.cpp:<line number>: | ||||
| PASSED: | ||||
|  | ||||
| =============================================================================== | ||||
| test cases: 185 | 132 passed | 49 failed |  4 failed as expected | ||||
| assertions: 903 | 783 passed | 99 failed | 21 failed as expected | ||||
| test cases: 187 | 134 passed | 49 failed |  4 failed as expected | ||||
| assertions: 934 | 814 passed | 99 failed | 21 failed as expected | ||||
|  | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| <?xml version="1.0" encoding="UTF-8"?> | ||||
| <testsuitesloose text artifact | ||||
| > | ||||
|   <testsuite name="<exe-name>" errors="15" failures="85" tests="904" hostname="tbd" time="{duration}" timestamp="{iso8601-timestamp}"> | ||||
|   <testsuite name="<exe-name>" errors="15" failures="85" tests="935" hostname="tbd" time="{duration}" timestamp="{iso8601-timestamp}"> | ||||
|     <testcase classname="<exe-name>.global" name="# A test name that starts with a #" time="{duration}"/> | ||||
|     <testcase classname="<exe-name>.global" name="#1005: Comparing pointer to int and long (NULL can be either on various systems)" time="{duration}"/> | ||||
|     <testcase classname="<exe-name>.global" name="#748 - captures with unexpected exceptions/outside assertions" time="{duration}"> | ||||
| @@ -263,6 +263,12 @@ MessageTests.cpp:<line number> | ||||
|       </failure> | ||||
|     </testcase> | ||||
|     <testcase classname="<exe-name>.global" name="Factorials are computed" time="{duration}"/> | ||||
|     <testcase classname="<exe-name>.global" name="Floating point matchers: double/Margin" time="{duration}"/> | ||||
|     <testcase classname="<exe-name>.global" name="Floating point matchers: double/ULPs" time="{duration}"/> | ||||
|     <testcase classname="<exe-name>.global" name="Floating point matchers: double/Composed" time="{duration}"/> | ||||
|     <testcase classname="<exe-name>.global" name="Floating point matchers: float/Margin" time="{duration}"/> | ||||
|     <testcase classname="<exe-name>.global" name="Floating point matchers: float/ULPs" time="{duration}"/> | ||||
|     <testcase classname="<exe-name>.global" name="Floating point matchers: float/Composed" time="{duration}"/> | ||||
|     <testcase classname="<exe-name>.global" name="Greater-than inequalities with different epsilons" time="{duration}"/> | ||||
|     <testcase classname="<exe-name>.global" name="INFO and WARN do not abort tests" time="{duration}"/> | ||||
|     <testcase classname="<exe-name>.global" name="INFO gets logged on failure" time="{duration}"> | ||||
|   | ||||
| @@ -1945,6 +1945,278 @@ | ||||
|       </Expression> | ||||
|       <OverallResult success="true"/> | ||||
|     </TestCase> | ||||
|     <TestCase name="Floating point matchers: double" tags="[floating-point][matchers]" filename="projects/<exe-name>/MatchersTests.cpp" > | ||||
|       <Section name="Margin" filename="projects/<exe-name>/MatchersTests.cpp" > | ||||
|         <Expression success="true" type="REQUIRE_THAT" filename="projects/<exe-name>/MatchersTests.cpp" > | ||||
|           <Original> | ||||
|             1., WithinAbs(1., 0) | ||||
|           </Original> | ||||
|           <Expanded> | ||||
|             1.0 is within 0.000000 of 1.000000 | ||||
|           </Expanded> | ||||
|         </Expression> | ||||
|         <Expression success="true" type="REQUIRE_THAT" filename="projects/<exe-name>/MatchersTests.cpp" > | ||||
|           <Original> | ||||
|             0., WithinAbs(1., 1) | ||||
|           </Original> | ||||
|           <Expanded> | ||||
|             0.0 is within 1.000000 of 1.000000 | ||||
|           </Expanded> | ||||
|         </Expression> | ||||
|         <Expression success="true" type="REQUIRE_THAT" filename="projects/<exe-name>/MatchersTests.cpp" > | ||||
|           <Original> | ||||
|             0., !WithinAbs(1., 0.99) | ||||
|           </Original> | ||||
|           <Expanded> | ||||
|             0.0 not is within 0.990000 of 1.000000 | ||||
|           </Expanded> | ||||
|         </Expression> | ||||
|         <Expression success="true" type="REQUIRE_THAT" filename="projects/<exe-name>/MatchersTests.cpp" > | ||||
|           <Original> | ||||
|             0., !WithinAbs(1., 0.99) | ||||
|           </Original> | ||||
|           <Expanded> | ||||
|             0.0 not is within 0.990000 of 1.000000 | ||||
|           </Expanded> | ||||
|         </Expression> | ||||
|         <Expression success="true" type="REQUIRE_THAT" filename="projects/<exe-name>/MatchersTests.cpp" > | ||||
|           <Original> | ||||
|             NAN, !WithinAbs(NAN, 0) | ||||
|           </Original> | ||||
|           <Expanded> | ||||
|             nanf not is within 0.000000 of nan | ||||
|           </Expanded> | ||||
|         </Expression> | ||||
|         <OverallResults successes="5" failures="0" expectedFailures="0"/> | ||||
|       </Section> | ||||
|       <Section name="ULPs" filename="projects/<exe-name>/MatchersTests.cpp" > | ||||
|         <Expression success="true" type="REQUIRE_THAT" filename="projects/<exe-name>/MatchersTests.cpp" > | ||||
|           <Original> | ||||
|             1., WithinULP(1., 0) | ||||
|           </Original> | ||||
|           <Expanded> | ||||
|             1.0 is within 0 ULPs of 1.000000 | ||||
|           </Expanded> | ||||
|         </Expression> | ||||
|         <Expression success="true" type="REQUIRE_THAT" filename="projects/<exe-name>/MatchersTests.cpp" > | ||||
|           <Original> | ||||
|             std::nextafter(1., 2.), WithinULP(1., 1) | ||||
|           </Original> | ||||
|           <Expanded> | ||||
|             1.0 is within 1 ULPs of 1.000000 | ||||
|           </Expanded> | ||||
|         </Expression> | ||||
|         <Expression success="true" type="REQUIRE_THAT" filename="projects/<exe-name>/MatchersTests.cpp" > | ||||
|           <Original> | ||||
|             std::nextafter(1., 0.), WithinULP(1., 1) | ||||
|           </Original> | ||||
|           <Expanded> | ||||
|             1.0 is within 1 ULPs of 1.000000 | ||||
|           </Expanded> | ||||
|         </Expression> | ||||
|         <Expression success="true" type="REQUIRE_THAT" filename="projects/<exe-name>/MatchersTests.cpp" > | ||||
|           <Original> | ||||
|             std::nextafter(1., 2.), !WithinULP(1., 0) | ||||
|           </Original> | ||||
|           <Expanded> | ||||
|             1.0 not is within 0 ULPs of 1.000000 | ||||
|           </Expanded> | ||||
|         </Expression> | ||||
|         <Expression success="true" type="REQUIRE_THAT" filename="projects/<exe-name>/MatchersTests.cpp" > | ||||
|           <Original> | ||||
|             1., WithinULP(1., 0) | ||||
|           </Original> | ||||
|           <Expanded> | ||||
|             1.0 is within 0 ULPs of 1.000000 | ||||
|           </Expanded> | ||||
|         </Expression> | ||||
|         <Expression success="true" type="REQUIRE_THAT" filename="projects/<exe-name>/MatchersTests.cpp" > | ||||
|           <Original> | ||||
|             -0., WithinULP(0., 0) | ||||
|           </Original> | ||||
|           <Expanded> | ||||
|             -0.0 is within 0 ULPs of 0.000000 | ||||
|           </Expanded> | ||||
|         </Expression> | ||||
|         <Expression success="true" type="REQUIRE_THAT" filename="projects/<exe-name>/MatchersTests.cpp" > | ||||
|           <Original> | ||||
|             NAN, !WithinULP(NAN, 123) | ||||
|           </Original> | ||||
|           <Expanded> | ||||
|             nanf not is within 123 ULPs of nanf | ||||
|           </Expanded> | ||||
|         </Expression> | ||||
|         <OverallResults successes="7" failures="0" expectedFailures="0"/> | ||||
|       </Section> | ||||
|       <Section name="Composed" filename="projects/<exe-name>/MatchersTests.cpp" > | ||||
|         <Expression success="true" type="REQUIRE_THAT" filename="projects/<exe-name>/MatchersTests.cpp" > | ||||
|           <Original> | ||||
|             1., WithinAbs(1., 0.5) || WithinULP(2., 1) | ||||
|           </Original> | ||||
|           <Expanded> | ||||
|             1.0 ( is within 0.500000 of 1.000000 or is within 1 ULPs of 2.000000 ) | ||||
|           </Expanded> | ||||
|         </Expression> | ||||
|         <Expression success="true" type="REQUIRE_THAT" filename="projects/<exe-name>/MatchersTests.cpp" > | ||||
|           <Original> | ||||
|             1., WithinAbs(2., 0.5) || WithinULP(1., 0) | ||||
|           </Original> | ||||
|           <Expanded> | ||||
|             1.0 ( is within 0.500000 of 2.000000 or is within 0 ULPs of 1.000000 ) | ||||
|           </Expanded> | ||||
|         </Expression> | ||||
|         <Expression success="true" type="REQUIRE_THAT" filename="projects/<exe-name>/MatchersTests.cpp" > | ||||
|           <Original> | ||||
|             NAN, !(WithinAbs(NAN, 100) || WithinULP(NAN, 123)) | ||||
|           </Original> | ||||
|           <Expanded> | ||||
|             nanf not ( is within 100.000000 of nan or is within 123 ULPs of nanf ) | ||||
|           </Expanded> | ||||
|         </Expression> | ||||
|         <OverallResults successes="3" failures="0" expectedFailures="0"/> | ||||
|       </Section> | ||||
|       <OverallResult success="true"/> | ||||
|     </TestCase> | ||||
|     <TestCase name="Floating point matchers: float" tags="[floating-point][matchers]" filename="projects/<exe-name>/MatchersTests.cpp" > | ||||
|       <Section name="Margin" filename="projects/<exe-name>/MatchersTests.cpp" > | ||||
|         <Expression success="true" type="REQUIRE_THAT" filename="projects/<exe-name>/MatchersTests.cpp" > | ||||
|           <Original> | ||||
|             1.f, WithinAbs(1.f, 0) | ||||
|           </Original> | ||||
|           <Expanded> | ||||
|             1.0f is within 0.000000 of 1.000000 | ||||
|           </Expanded> | ||||
|         </Expression> | ||||
|         <Expression success="true" type="REQUIRE_THAT" filename="projects/<exe-name>/MatchersTests.cpp" > | ||||
|           <Original> | ||||
|             0.f, WithinAbs(1.f, 1) | ||||
|           </Original> | ||||
|           <Expanded> | ||||
|             0.0f is within 1.000000 of 1.000000 | ||||
|           </Expanded> | ||||
|         </Expression> | ||||
|         <Expression success="true" type="REQUIRE_THAT" filename="projects/<exe-name>/MatchersTests.cpp" > | ||||
|           <Original> | ||||
|             0.f, !WithinAbs(1.f, 0.99f) | ||||
|           </Original> | ||||
|           <Expanded> | ||||
|             0.0f not is within 0.990000 of 1.000000 | ||||
|           </Expanded> | ||||
|         </Expression> | ||||
|         <Expression success="true" type="REQUIRE_THAT" filename="projects/<exe-name>/MatchersTests.cpp" > | ||||
|           <Original> | ||||
|             0.f, !WithinAbs(1.f, 0.99f) | ||||
|           </Original> | ||||
|           <Expanded> | ||||
|             0.0f not is within 0.990000 of 1.000000 | ||||
|           </Expanded> | ||||
|         </Expression> | ||||
|         <Expression success="true" type="REQUIRE_THAT" filename="projects/<exe-name>/MatchersTests.cpp" > | ||||
|           <Original> | ||||
|             0.f, WithinAbs(-0.f, 0) | ||||
|           </Original> | ||||
|           <Expanded> | ||||
|             0.0f is within 0.000000 of -0.000000 | ||||
|           </Expanded> | ||||
|         </Expression> | ||||
|         <Expression success="true" type="REQUIRE_THAT" filename="projects/<exe-name>/MatchersTests.cpp" > | ||||
|           <Original> | ||||
|             NAN, !WithinAbs(NAN, 0) | ||||
|           </Original> | ||||
|           <Expanded> | ||||
|             nanf not is within 0.000000 of nan | ||||
|           </Expanded> | ||||
|         </Expression> | ||||
|         <OverallResults successes="6" failures="0" expectedFailures="0"/> | ||||
|       </Section> | ||||
|       <Section name="ULPs" filename="projects/<exe-name>/MatchersTests.cpp" > | ||||
|         <Expression success="true" type="REQUIRE_THAT" filename="projects/<exe-name>/MatchersTests.cpp" > | ||||
|           <Original> | ||||
|             1.f, WithinULP(1.f, 0) | ||||
|           </Original> | ||||
|           <Expanded> | ||||
|             1.0f is within 0 ULPs of 1.000000f | ||||
|           </Expanded> | ||||
|         </Expression> | ||||
|         <Expression success="true" type="REQUIRE_THAT" filename="projects/<exe-name>/MatchersTests.cpp" > | ||||
|           <Original> | ||||
|             std::nextafter(1.f, 2.f), WithinULP(1.f, 1) | ||||
|           </Original> | ||||
|           <Expanded> | ||||
|             1.0f is within 1 ULPs of 1.000000f | ||||
|           </Expanded> | ||||
|         </Expression> | ||||
|         <Expression success="true" type="REQUIRE_THAT" filename="projects/<exe-name>/MatchersTests.cpp" > | ||||
|           <Original> | ||||
|             std::nextafter(1.f, 0.f), WithinULP(1.f, 1) | ||||
|           </Original> | ||||
|           <Expanded> | ||||
|             1.0f is within 1 ULPs of 1.000000f | ||||
|           </Expanded> | ||||
|         </Expression> | ||||
|         <Expression success="true" type="REQUIRE_THAT" filename="projects/<exe-name>/MatchersTests.cpp" > | ||||
|           <Original> | ||||
|             std::nextafter(1.f, 2.f), !WithinULP(1.f, 0) | ||||
|           </Original> | ||||
|           <Expanded> | ||||
|             1.0f not is within 0 ULPs of 1.000000f | ||||
|           </Expanded> | ||||
|         </Expression> | ||||
|         <Expression success="true" type="REQUIRE_THAT" filename="projects/<exe-name>/MatchersTests.cpp" > | ||||
|           <Original> | ||||
|             1.f, WithinULP(1.f, 0) | ||||
|           </Original> | ||||
|           <Expanded> | ||||
|             1.0f is within 0 ULPs of 1.000000f | ||||
|           </Expanded> | ||||
|         </Expression> | ||||
|         <Expression success="true" type="REQUIRE_THAT" filename="projects/<exe-name>/MatchersTests.cpp" > | ||||
|           <Original> | ||||
|             -0.f, WithinULP(0.f, 0) | ||||
|           </Original> | ||||
|           <Expanded> | ||||
|             -0.0f is within 0 ULPs of 0.000000f | ||||
|           </Expanded> | ||||
|         </Expression> | ||||
|         <Expression success="true" type="REQUIRE_THAT" filename="projects/<exe-name>/MatchersTests.cpp" > | ||||
|           <Original> | ||||
|             NAN, !WithinULP(NAN, 123) | ||||
|           </Original> | ||||
|           <Expanded> | ||||
|             nanf not is within 123 ULPs of nanf | ||||
|           </Expanded> | ||||
|         </Expression> | ||||
|         <OverallResults successes="7" failures="0" expectedFailures="0"/> | ||||
|       </Section> | ||||
|       <Section name="Composed" filename="projects/<exe-name>/MatchersTests.cpp" > | ||||
|         <Expression success="true" type="REQUIRE_THAT" filename="projects/<exe-name>/MatchersTests.cpp" > | ||||
|           <Original> | ||||
|             1.f, WithinAbs(1.f, 0.5) || WithinULP(1.f, 1) | ||||
|           </Original> | ||||
|           <Expanded> | ||||
|             1.0f ( is within 0.500000 of 1.000000 or is within 1 ULPs of 1.000000f ) | ||||
|           </Expanded> | ||||
|         </Expression> | ||||
|         <Expression success="true" type="REQUIRE_THAT" filename="projects/<exe-name>/MatchersTests.cpp" > | ||||
|           <Original> | ||||
|             1.f, WithinAbs(2.f, 0.5) || WithinULP(1.f, 0) | ||||
|           </Original> | ||||
|           <Expanded> | ||||
|             1.0f ( is within 0.500000 of 2.000000 or is within 0 ULPs of 1.000000f ) | ||||
|           </Expanded> | ||||
|         </Expression> | ||||
|         <Expression success="true" type="REQUIRE_THAT" filename="projects/<exe-name>/MatchersTests.cpp" > | ||||
|           <Original> | ||||
|             NAN, !(WithinAbs(NAN, 100) || WithinULP(NAN, 123)) | ||||
|           </Original> | ||||
|           <Expanded> | ||||
|             nanf not ( is within 100.000000 of nan or is within 123 ULPs of nanf ) | ||||
|           </Expanded> | ||||
|         </Expression> | ||||
|         <OverallResults successes="3" failures="0" expectedFailures="0"/> | ||||
|       </Section> | ||||
|       <OverallResult success="true"/> | ||||
|     </TestCase> | ||||
|     <TestCase name="Greater-than inequalities with different epsilons" tags="[Approx]" filename="projects/<exe-name>/ApproxTests.cpp" > | ||||
|       <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/ApproxTests.cpp" > | ||||
|         <Original> | ||||
| @@ -8446,7 +8718,7 @@ loose text artifact | ||||
|       </Section> | ||||
|       <OverallResult success="true"/> | ||||
|     </TestCase> | ||||
|     <OverallResults successes="783" failures="100" expectedFailures="21"/> | ||||
|     <OverallResults successes="814" failures="100" expectedFailures="21"/> | ||||
|   </Group> | ||||
|   <OverallResults successes="783" failures="99" expectedFailures="21"/> | ||||
|   <OverallResults successes="814" failures="99" expectedFailures="21"/> | ||||
| </Catch> | ||||
|   | ||||
| @@ -226,6 +226,67 @@ TEST_CASE("Exception matchers that fail", "[matchers][exceptions][!throws][.fail | ||||
|     } | ||||
| } | ||||
|  | ||||
| TEST_CASE("Floating point matchers: float", "[matchers][floating-point]") { | ||||
|     SECTION("Margin") { | ||||
|         REQUIRE_THAT(1.f, WithinAbs(1.f, 0)); | ||||
|         REQUIRE_THAT(0.f, WithinAbs(1.f, 1)); | ||||
|  | ||||
|         REQUIRE_THAT(0.f, !WithinAbs(1.f, 0.99f)); | ||||
|         REQUIRE_THAT(0.f, !WithinAbs(1.f, 0.99f)); | ||||
|  | ||||
|         REQUIRE_THAT(0.f, WithinAbs(-0.f, 0)); | ||||
|         REQUIRE_THAT(NAN, !WithinAbs(NAN, 0)); | ||||
|     } | ||||
|     SECTION("ULPs") { | ||||
|         REQUIRE_THAT(1.f, WithinULP(1.f, 0)); | ||||
|  | ||||
|         REQUIRE_THAT(std::nextafter(1.f, 2.f), WithinULP(1.f, 1)); | ||||
|         REQUIRE_THAT(std::nextafter(1.f, 0.f), WithinULP(1.f, 1)); | ||||
|         REQUIRE_THAT(std::nextafter(1.f, 2.f), !WithinULP(1.f, 0)); | ||||
|  | ||||
|         REQUIRE_THAT(1.f, WithinULP(1.f, 0)); | ||||
|         REQUIRE_THAT(-0.f, WithinULP(0.f, 0)); | ||||
|  | ||||
|         REQUIRE_THAT(NAN, !WithinULP(NAN, 123)); | ||||
|     } | ||||
|     SECTION("Composed") { | ||||
|         REQUIRE_THAT(1.f, WithinAbs(1.f, 0.5) || WithinULP(1.f, 1)); | ||||
|         REQUIRE_THAT(1.f, WithinAbs(2.f, 0.5) || WithinULP(1.f, 0)); | ||||
|  | ||||
|         REQUIRE_THAT(NAN, !(WithinAbs(NAN, 100) || WithinULP(NAN, 123))); | ||||
|     } | ||||
| } | ||||
|  | ||||
| TEST_CASE("Floating point matchers: double", "[matchers][floating-point]") { | ||||
|     SECTION("Margin") { | ||||
|         REQUIRE_THAT(1., WithinAbs(1., 0)); | ||||
|         REQUIRE_THAT(0., WithinAbs(1., 1)); | ||||
|  | ||||
|         REQUIRE_THAT(0., !WithinAbs(1., 0.99)); | ||||
|         REQUIRE_THAT(0., !WithinAbs(1., 0.99)); | ||||
|  | ||||
|         REQUIRE_THAT(NAN, !WithinAbs(NAN, 0)); | ||||
|     } | ||||
|     SECTION("ULPs") { | ||||
|         REQUIRE_THAT(1., WithinULP(1., 0)); | ||||
|  | ||||
|         REQUIRE_THAT(std::nextafter(1., 2.), WithinULP(1., 1)); | ||||
|         REQUIRE_THAT(std::nextafter(1., 0.), WithinULP(1., 1)); | ||||
|         REQUIRE_THAT(std::nextafter(1., 2.), !WithinULP(1., 0)); | ||||
|  | ||||
|         REQUIRE_THAT(1., WithinULP(1., 0)); | ||||
|         REQUIRE_THAT(-0., WithinULP(0., 0)); | ||||
|  | ||||
|         REQUIRE_THAT(NAN, !WithinULP(NAN, 123)); | ||||
|     } | ||||
|     SECTION("Composed") { | ||||
|         REQUIRE_THAT(1., WithinAbs(1., 0.5) || WithinULP(2., 1)); | ||||
|         REQUIRE_THAT(1., WithinAbs(2., 0.5) || WithinULP(1., 0)); | ||||
|  | ||||
|         REQUIRE_THAT(NAN, !(WithinAbs(NAN, 100) || WithinULP(NAN, 123))); | ||||
|     } | ||||
| } | ||||
|  | ||||
| #endif // CATCH_CONFIG_DISABLE_MATCHERS | ||||
|  | ||||
| #ifdef __clang__ | ||||
|   | ||||
| @@ -52,6 +52,12 @@ infParser = re.compile(r''' | ||||
|     | | ||||
|     __builtin_huge_valf\(\)               # OSX macro | ||||
| ''', re.VERBOSE) | ||||
| nanParser = re.compile(r''' | ||||
|     \(\(float\)\(\(\(float\)\(1e\+300\ \*\ 1e\+300\)\)\ \*\ 0\.0F\)\) # MSVC NAN macro | ||||
|     | | ||||
|     \(__builtin_nanf\ \(""\)\)                 # Linux (ubuntu) NAN macro | ||||
| ''', re.VERBOSE) | ||||
|  | ||||
|  | ||||
| if len(sys.argv) == 2: | ||||
|     cmdPath = sys.argv[1] | ||||
| @@ -110,6 +116,7 @@ def filterLine(line): | ||||
|     line = errnoParser.sub('errno', line) | ||||
|     line = sinceEpochParser.sub('{since-epoch-report}', line) | ||||
|     line = infParser.sub('INFINITY', line) | ||||
|     line = nanParser.sub('NAN', line) | ||||
|     return line | ||||
|  | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Martin Hořeňovský
					Martin Hořeňovský