text: /*
   *  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 <catch2/catch_test_macros.hpp>
  #include <catch2/matchers/catch_matchers_exception.hpp>
  #include <catch2/matchers/catch_matchers_floating_point.hpp>
  #include <catch2/matchers/catch_matchers_predicate.hpp>
  #include <catch2/matchers/catch_matchers_string.hpp>
  #include <catch2/matchers/catch_matchers_vector.hpp>
  #include <catch2/matchers/catch_matchers_templated.hpp>
  
  #include <algorithm>
  #include <cmath>
  #include <list>
  #include <sstream>
  
  #ifdef __clang__
  #pragma clang diagnostic push
  #pragma clang diagnostic ignored "-Wweak-vtables"
  #pragma clang diagnostic ignored "-Wpadded"
  #endif
  
  namespace { namespace MatchersTests {
  
  #ifndef MATCHERS_TEST_HELPERS_INCLUDED // Don't compile this more than once per TU
  #define MATCHERS_TEST_HELPERS_INCLUDED
  
      inline const char *testStringForMatching() {
          return "this string contains 'abc' as a substring";
      }
  
      inline const char *testStringForMatching2() {
          return "some completely different text that contains one common word";
      }
  
      inline bool alwaysTrue(int) { return true; }
      inline bool alwaysFalse(int) { return false; }
  
  
  #ifdef _MSC_VER
  #pragma warning(disable:4702) // Unreachable code -- MSVC 19 (VS 2015) sees right through the indirection
  #endif
  
  #include <exception>
  
      struct SpecialException : std::exception {
          SpecialException(int i_) : i(i_) {}
  
          char const* what() const noexcept override {
              return "SpecialException::what";
          }
  
          int i;
      };
  
      struct DerivedException : std::exception {
          char const* what() const noexcept override {
              return "DerivedException::what";
          }
      };
  
      void doesNotThrow() {}
  
      [[noreturn]]
      void throwsSpecialException(int i) {
          throw SpecialException{i};
      }
  
      [[noreturn]]
      void throwsAsInt(int i) {
          throw i;
      }
  
      [[noreturn]]
      void throwsDerivedException() {
          throw DerivedException{};
      }
  
      class ExceptionMatcher : public Catch::Matchers::MatcherBase<SpecialException> {
          int m_expected;
      public:
          ExceptionMatcher(int i) : m_expected(i) {}
  
          bool match(SpecialException const &se) const override {
              return se.i == m_expected;
          }
  
          std::string describe() const override {
              std::ostringstream ss;
              ss << "special exception has value of " << m_expected;
              return ss.str();
          }
      };
  
  #endif
  
      using namespace Catch::Matchers;
  
  #ifdef __DJGPP__
      float nextafter(float from, float to)
      {
          return ::nextafterf(from, to);
      }
  
      double nextafter(double from, double to)
      {
          return ::nextafter(from, to);
      }
  #else
      using std::nextafter;
  #endif
  
      TEST_CASE("String matchers", "[matchers]") {
          REQUIRE_THAT(testStringForMatching(), Contains("string"));
          REQUIRE_THAT(testStringForMatching(), Contains("string", Catch::CaseSensitive::No));
          CHECK_THAT(testStringForMatching(), Contains("abc"));
          CHECK_THAT(testStringForMatching(), Contains("aBC", Catch::CaseSensitive::No));
  
          CHECK_THAT(testStringForMatching(), StartsWith("this"));
          CHECK_THAT(testStringForMatching(), StartsWith("THIS", Catch::CaseSensitive::No));
          CHECK_THAT(testStringForMatching(), EndsWith("substring"));
          CHECK_THAT(testStringForMatching(), EndsWith(" SuBsTrInG", Catch::CaseSensitive::No));
      }
  
      TEST_CASE("Contains string matcher", "[.][failing][matchers]") {
          CHECK_THAT(testStringForMatching(), Contains("not there", Catch::CaseSensitive::No));
          CHECK_THAT(testStringForMatching(), Contains("STRING"));
      }
  
      TEST_CASE("StartsWith string matcher", "[.][failing][matchers]") {
          CHECK_THAT(testStringForMatching(), StartsWith("This String"));
          CHECK_THAT(testStringForMatching(), StartsWith("string", Catch::CaseSensitive::No));
      }
  
      TEST_CASE("EndsWith string matcher", "[.][failing][matchers]") {
          CHECK_THAT(testStringForMatching(), EndsWith("Substring"));
          CHECK_THAT(testStringForMatching(), EndsWith("this", Catch::CaseSensitive::No));
      }
  
      TEST_CASE("Equals string matcher", "[.][failing][matchers]") {
          CHECK_THAT(testStringForMatching(), Equals("this string contains 'ABC' as a substring"));
          CHECK_THAT(testStringForMatching(), Equals("something else", Catch::CaseSensitive::No));
      }
  
      TEST_CASE("Equals", "[matchers]") {
          CHECK_THAT(testStringForMatching(), Equals("this string contains 'abc' as a substring"));
          CHECK_THAT(testStringForMatching(),
                     Equals("this string contains 'ABC' as a substring", Catch::CaseSensitive::No));
      }
  
  // <regex> does not work in libstdc++ 4.8, so we have to enable these tests only when they
  // are expected to pass and cannot have them in baselines
      TEST_CASE("Regex string matcher -- libstdc++-4.8 workaround", "[matchers][approvals]") {
  
  // This is fiiiine
  // Taken from an answer at
  // https://stackoverflow.com/questions/12530406/is-gcc-4-8-or-earlier-buggy-about-regular-expressions
  #if (!defined(__GNUC__)) || \
        (__cplusplus >= 201103L && \
        (!defined(__GLIBCXX__) || (__cplusplus >= 201402L) || \
          (defined(_GLIBCXX_REGEX_DFS_QUANTIFIERS_LIMIT) || \
            defined(_GLIBCXX_REGEX_STATE_LIMIT) || \
               (defined(_GLIBCXX_RELEASE) && \
               _GLIBCXX_RELEASE > 4))))
  
  // DJGPP meets the above condition but <regex> does not work properly anyway
  #ifndef __DJGPP__
              REQUIRE_THAT(testStringForMatching(), Matches("this string contains 'abc' as a substring"));
              REQUIRE_THAT(testStringForMatching(),
                           Matches("this string CONTAINS 'abc' as a substring", Catch::CaseSensitive::No));
              REQUIRE_THAT(testStringForMatching(), Matches("^this string contains 'abc' as a substring$"));
              REQUIRE_THAT(testStringForMatching(), Matches("^.* 'abc' .*$"));
              REQUIRE_THAT(testStringForMatching(), Matches("^.* 'ABC' .*$", Catch::CaseSensitive::No));
  #endif
  
  #endif
  
              REQUIRE_THAT(testStringForMatching2(), !Matches("this string contains 'abc' as a substring"));
          }
  
          TEST_CASE("Regex string matcher", "[matchers][.failing]") {
              CHECK_THAT(testStringForMatching(), Matches("this STRING contains 'abc' as a substring"));
              CHECK_THAT(testStringForMatching(), Matches("contains 'abc' as a substring"));
              CHECK_THAT(testStringForMatching(), Matches("this string contains 'abc' as a"));
          }
  
          TEST_CASE("Matchers can be (AllOf) composed with the && operator", "[matchers][operators][operator&&]") {
              CHECK_THAT(testStringForMatching(),
                         Contains("string") &&
                         Contains("abc") &&
                         Contains("substring") &&
                         Contains("contains"));
          }
  
          TEST_CASE("Matchers can be (AnyOf) composed with the || operator", "[matchers][operators][operator||]") {
              CHECK_THAT(testStringForMatching(), Contains("string") || Contains("different") || Contains("random"));
              CHECK_THAT(testStringForMatching2(), Contains("string") || Contains("different") || Contains("random"));
          }
  
          TEST_CASE("Matchers can be composed with both && and ||", "[matchers][operators][operator||][operator&&]") {
              CHECK_THAT(testStringForMatching(), (Contains("string") || Contains("different")) && Contains("substring"));
          }
  
          TEST_CASE("Matchers can be composed with both && and || - failing",
                    "[matchers][operators][operator||][operator&&][.failing]") {
              CHECK_THAT(testStringForMatching(), (Contains("string") || Contains("different")) && Contains("random"));
          }
  
          TEST_CASE("Matchers can be negated (Not) with the ! operator", "[matchers][operators][not]") {
              CHECK_THAT(testStringForMatching(), !Contains("different"));
          }
  
          TEST_CASE("Matchers can be negated (Not) with the ! operator - failing",
                    "[matchers][operators][not][.failing]") {
              CHECK_THAT(testStringForMatching(), !Contains("substring"));
          }
  
          template<typename T>
          struct CustomAllocator : private std::allocator<T>
          {
              using size_type = size_t;
              using difference_type = ptrdiff_t;
              using pointer = T*;
              using const_pointer = const T*;
              using reference = T&;
              using const_reference = const T&;
              using value_type = T;
  
              template<typename U>
              struct rebind
              { using other = CustomAllocator<U>; };
  
              using propagate_on_container_move_assignment = std::true_type;
              using is_always_equal = std::true_type;
  
              CustomAllocator() = default;
  
              CustomAllocator(const CustomAllocator& other)
                      : std::allocator<T>(other) { }
  
              template<typename U>
              CustomAllocator(const CustomAllocator<U>&) { }
  
              ~CustomAllocator() = default;
  
              using std::allocator<T>::address;
              using std::allocator<T>::allocate;
              using std::allocator<T>::construct;
              using std::allocator<T>::deallocate;
              using std::allocator<T>::max_size;
              using std::allocator<T>::destroy;
          };
  
          TEST_CASE("Vector matchers", "[matchers][vector]") {
              std::vector<int> v;
              v.push_back(1);
              v.push_back(2);
              v.push_back(3);
  
              std::vector<int> v2;
              v2.push_back(1);
              v2.push_back(2);
  
              std::vector<double> v3;
              v3.push_back(1);
              v3.push_back(2);
              v3.push_back(3);
  
              std::vector<double> v4;
              v4.push_back(1 + 1e-8);
              v4.push_back(2 + 1e-8);
              v4.push_back(3 + 1e-8);
  
              std::vector<int, CustomAllocator<int>> v5;
              v5.push_back(1);
              v5.push_back(2);
              v5.push_back(3);
  
              std::vector<int, CustomAllocator<int>> v6;
              v6.push_back(1);
              v6.push_back(2);
  
              std::vector<int> empty;
  
              SECTION("Contains (element)") {
                  CHECK_THAT(v, VectorContains(1));
                  CHECK_THAT(v, VectorContains(2));
                  CHECK_THAT(v5, (VectorContains<int, CustomAllocator<int>>(2)));
              }
              SECTION("Contains (vector)") {
                  CHECK_THAT(v, Contains(v2));
                  CHECK_THAT(v, Contains<int>({ 1, 2 }));
                  CHECK_THAT(v5, (Contains<int, std::allocator<int>, CustomAllocator<int>>(v2)));
  
                  v2.push_back(3); // now exactly matches
                  CHECK_THAT(v, Contains(v2));
  
                  CHECK_THAT(v, Contains(empty));
                  CHECK_THAT(empty, Contains(empty));
  
                  CHECK_THAT(v5, (Contains<int, std::allocator<int>, CustomAllocator<int>>(v2)));
                  CHECK_THAT(v5, Contains(v6));
              }
              SECTION("Contains (element), composed") {
                  CHECK_THAT(v, VectorContains(1) && VectorContains(2));
              }
  
              SECTION("Equals") {
  
                  // Same vector
                  CHECK_THAT(v, Equals(v));
  
                  CHECK_THAT(empty, Equals(empty));
  
                  // Different vector with same elements
                  CHECK_THAT(v, Equals<int>({ 1, 2, 3 }));
                  v2.push_back(3);
                  CHECK_THAT(v, Equals(v2));
  
                  CHECK_THAT(v5, (Equals<int, std::allocator<int>, CustomAllocator<int>>(v2)));
  
                  v6.push_back(3);
                  CHECK_THAT(v5, Equals(v6));
              }
              SECTION("UnorderedEquals") {
                  CHECK_THAT(v, UnorderedEquals(v));
                  CHECK_THAT(v, UnorderedEquals<int>({ 3, 2, 1 }));
                  CHECK_THAT(empty, UnorderedEquals(empty));
  
                  auto permuted = v;
                  std::next_permutation(begin(permuted), end(permuted));
                  REQUIRE_THAT(permuted, UnorderedEquals(v));
  
                  std::reverse(begin(permuted), end(permuted));
                  REQUIRE_THAT(permuted, UnorderedEquals(v));
  
                  CHECK_THAT(v5, (UnorderedEquals<int, std::allocator<int>, CustomAllocator<int>>(permuted)));
  
                  auto v5_permuted = v5;
                  std::next_permutation(begin(v5_permuted), end(v5_permuted));
                  CHECK_THAT(v5_permuted, UnorderedEquals(v5));
              }
          }
  
          TEST_CASE("Vector matchers that fail", "[matchers][vector][.][failing]") {
              std::vector<int> v;
              v.push_back(1);
              v.push_back(2);
              v.push_back(3);
  
              std::vector<int> v2;
              v2.push_back(1);
              v2.push_back(2);
  
              std::vector<double> v3;
              v3.push_back(1);
              v3.push_back(2);
              v3.push_back(3);
  
              std::vector<double> v4;
              v4.push_back(1.1);
              v4.push_back(2.1);
              v4.push_back(3.1);
  
              std::vector<int> empty;
  
              SECTION("Contains (element)") {
                  CHECK_THAT(v, VectorContains(-1));
                  CHECK_THAT(empty, VectorContains(1));
              }
              SECTION("Contains (vector)") {
                  CHECK_THAT(empty, Contains(v));
                  v2.push_back(4);
                  CHECK_THAT(v, Contains(v2));
              }
  
              SECTION("Equals") {
  
                  CHECK_THAT(v, Equals(v2));
                  CHECK_THAT(v2, Equals(v));
                  CHECK_THAT(empty, Equals(v));
                  CHECK_THAT(v, Equals(empty));
              }
              SECTION("UnorderedEquals") {
                  CHECK_THAT(v, UnorderedEquals(empty));
                  CHECK_THAT(empty, UnorderedEquals(v));
  
                  auto permuted = v;
                  std::next_permutation(begin(permuted), end(permuted));
                  permuted.pop_back();
                  CHECK_THAT(permuted, UnorderedEquals(v));
  
                  std::reverse(begin(permuted), end(permuted));
                  CHECK_THAT(permuted, UnorderedEquals(v));
              }
          }
  
          TEST_CASE("Exception matchers that succeed", "[matchers][exceptions][!throws]") {
              CHECK_THROWS_MATCHES(throwsSpecialException(1), SpecialException, ExceptionMatcher{1});
              REQUIRE_THROWS_MATCHES(throwsSpecialException(2), SpecialException, ExceptionMatcher{2});
          }
  
          TEST_CASE("Exception matchers that fail", "[matchers][exceptions][!throws][.failing]") {
              SECTION("No exception") {
                  CHECK_THROWS_MATCHES(doesNotThrow(), SpecialException, ExceptionMatcher{1});
                  REQUIRE_THROWS_MATCHES(doesNotThrow(), SpecialException, ExceptionMatcher{1});
              }
              SECTION("Type mismatch") {
                  CHECK_THROWS_MATCHES(throwsAsInt(1), SpecialException, ExceptionMatcher{1});
                  REQUIRE_THROWS_MATCHES(throwsAsInt(1), SpecialException, ExceptionMatcher{1});
              }
              SECTION("Contents are wrong") {
                  CHECK_THROWS_MATCHES(throwsSpecialException(3), SpecialException, ExceptionMatcher{1});
                  REQUIRE_THROWS_MATCHES(throwsSpecialException(4), SpecialException, ExceptionMatcher{1});
              }
          }
  
          TEST_CASE("Floating point matchers: float", "[matchers][floating-point]") {
              SECTION("Relative") {
                  REQUIRE_THAT(10.f,  WithinRel(11.1f, 0.1f));
                  REQUIRE_THAT(10.f, !WithinRel(11.2f, 0.1f));
                  REQUIRE_THAT( 1.f, !WithinRel(0.f, 0.99f));
                  REQUIRE_THAT(-0.f,  WithinRel(0.f));
                  SECTION("Some subnormal values") {
                      auto v1 = std::numeric_limits<float>::min();
                      auto v2 = v1;
                      for (int i = 0; i < 5; ++i) {
                          v2 = std::nextafter(v1, 0.f);
                      }
                      REQUIRE_THAT(v1, WithinRel(v2));
                  }
              }
              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(11.f, !WithinAbs(10.f, 0.5f));
                  REQUIRE_THAT(10.f, !WithinAbs(11.f, 0.5f));
                  REQUIRE_THAT(-10.f, WithinAbs(-10.f, 0.5f));
                  REQUIRE_THAT(-10.f, WithinAbs(-9.6f, 0.5f));
              }
              SECTION("ULPs") {
                  REQUIRE_THAT(1.f, WithinULP(1.f, 0));
  
                  REQUIRE_THAT(nextafter(1.f, 2.f), WithinULP(1.f, 1));
                  REQUIRE_THAT(0.f, WithinULP(nextafter(0.f, 1.f), 1));
                  REQUIRE_THAT(1.f, WithinULP(nextafter(1.f, 0.f), 1));
                  REQUIRE_THAT(1.f, !WithinULP(nextafter(1.f, 2.f), 0));
  
                  REQUIRE_THAT(1.f, WithinULP(1.f, 0));
                  REQUIRE_THAT(-0.f, WithinULP(0.f, 0));
              }
              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(0.0001f, WithinAbs(0.f, 0.001f) || WithinRel(0.f, 0.1f));
              }
              SECTION("Constructor validation") {
                  REQUIRE_NOTHROW(WithinAbs(1.f, 0.f));
                  REQUIRE_THROWS_AS(WithinAbs(1.f, -1.f), std::domain_error);
  
                  REQUIRE_NOTHROW(WithinULP(1.f, 0));
                  REQUIRE_THROWS_AS(WithinULP(1.f, static_cast<uint64_t>(-1)), std::domain_error);
  
                  REQUIRE_NOTHROW(WithinRel(1.f, 0.f));
                  REQUIRE_THROWS_AS(WithinRel(1.f, -0.2f), std::domain_error);
                  REQUIRE_THROWS_AS(WithinRel(1.f, 1.f), std::domain_error);
              }
          }
  
          TEST_CASE("Floating point matchers: double", "[matchers][floating-point]") {
              SECTION("Relative") {
                  REQUIRE_THAT(10., WithinRel(11.1, 0.1));
                  REQUIRE_THAT(10., !WithinRel(11.2, 0.1));
                  REQUIRE_THAT(1., !WithinRel(0., 0.99));
                  REQUIRE_THAT(-0., WithinRel(0.));
                  SECTION("Some subnormal values") {
                      auto v1 = std::numeric_limits<double>::min();
                      auto v2 = v1;
                      for (int i = 0; i < 5; ++i) {
                          v2 = std::nextafter(v1, 0);
                      }
                      REQUIRE_THAT(v1, WithinRel(v2));
                  }
              }
              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(11., !WithinAbs(10., 0.5));
                  REQUIRE_THAT(10., !WithinAbs(11., 0.5));
                  REQUIRE_THAT(-10., WithinAbs(-10., 0.5));
                  REQUIRE_THAT(-10., WithinAbs(-9.6, 0.5));
              }
              SECTION("ULPs") {
                  REQUIRE_THAT(1., WithinULP(1., 0));
  
                  REQUIRE_THAT(nextafter(1., 2.), WithinULP(1., 1));
                  REQUIRE_THAT(0.,  WithinULP(nextafter(0., 1.), 1));
                  REQUIRE_THAT(1.,  WithinULP(nextafter(1., 0.), 1));
                  REQUIRE_THAT(1., !WithinULP(nextafter(1., 2.), 0));
  
                  REQUIRE_THAT(1., WithinULP(1., 0));
                  REQUIRE_THAT(-0., WithinULP(0., 0));
              }
              SECTION("Composed") {
                  REQUIRE_THAT(1., WithinAbs(1., 0.5) || WithinULP(2., 1));
                  REQUIRE_THAT(1., WithinAbs(2., 0.5) || WithinULP(1., 0));
                  REQUIRE_THAT(0.0001, WithinAbs(0., 0.001) || WithinRel(0., 0.1));
              }
              SECTION("Constructor validation") {
                  REQUIRE_NOTHROW(WithinAbs(1., 0.));
                  REQUIRE_THROWS_AS(WithinAbs(1., -1.), std::domain_error);
  
                  REQUIRE_NOTHROW(WithinULP(1., 0));
  
                  REQUIRE_NOTHROW(WithinRel(1., 0.));
                  REQUIRE_THROWS_AS(WithinRel(1., -0.2), std::domain_error);
                  REQUIRE_THROWS_AS(WithinRel(1., 1.), std::domain_error);
              }
          }
  
          TEST_CASE("Floating point matchers that are problematic in approvals", "[approvals][matchers][floating-point]") {
              REQUIRE_THAT(NAN, !WithinAbs(NAN, 0));
              REQUIRE_THAT(NAN, !(WithinAbs(NAN, 100) || WithinULP(NAN, 123)));
              REQUIRE_THAT(NAN, !WithinULP(NAN, 123));
              REQUIRE_THAT(INFINITY, WithinRel(INFINITY));
              REQUIRE_THAT(-INFINITY, !WithinRel(INFINITY));
              REQUIRE_THAT(1., !WithinRel(INFINITY));
              REQUIRE_THAT(INFINITY, !WithinRel(1.));
              REQUIRE_THAT(NAN, !WithinRel(NAN));
              REQUIRE_THAT(1., !WithinRel(NAN));
              REQUIRE_THAT(NAN, !WithinRel(1.));
          }
  
          TEST_CASE("Arbitrary predicate matcher", "[matchers][generic]") {
              SECTION("Function pointer") {
                  REQUIRE_THAT(1,  Predicate<int>(alwaysTrue, "always true"));
                  REQUIRE_THAT(1, !Predicate<int>(alwaysFalse, "always false"));
              }
              SECTION("Lambdas + different type") {
                  REQUIRE_THAT("Hello olleH",
                               Predicate<std::string>(
                                   [] (std::string const& str) -> bool { return str.front() == str.back(); },
                                   "First and last character should be equal")
                  );
  
                  REQUIRE_THAT("This wouldn't pass",
                               !Predicate<std::string>(
                                   [] (std::string const& str) -> bool { return str.front() == str.back(); }
                               )
                  );
              }
          }
  
          TEST_CASE("Regression test #1", "[matchers][vector]") {
              // At some point, UnorderedEqualsMatcher skipped
              // mismatched prefixed before doing the comparison itself
              std::vector<char> actual = { 'a', 'b' };
              std::vector<char> expected = { 'c', 'b' };
  
              CHECK_THAT(actual, !UnorderedEquals(expected));
          }
  
          TEST_CASE("Predicate matcher can accept const char*", "[matchers][compilation]") {
              REQUIRE_THAT("foo", Predicate<const char*>([] (const char* const&) { return true; }));
          }
  
          TEST_CASE("Vector Approx matcher", "[matchers][approx][vector]") {
              using Catch::Matchers::Approx;
              SECTION("Empty vector is roughly equal to an empty vector") {
                  std::vector<double> empty;
                  REQUIRE_THAT(empty, Approx(empty));
              }
              SECTION("Vectors with elements") {
                  std::vector<double> v1({1., 2., 3.});
                  SECTION("A vector is approx equal to itself") {
                      REQUIRE_THAT(v1, Approx(v1));
                      REQUIRE_THAT(v1, Approx<double>({ 1., 2., 3. }));
                  }
                  std::vector<double> v2({1.5, 2.5, 3.5});
                  SECTION("Different length") {
                      auto temp(v1);
                      temp.push_back(4);
                      REQUIRE_THAT(v1, !Approx(temp));
                  }
                  SECTION("Same length, different elements") {
                      REQUIRE_THAT(v1, !Approx(v2));
                      REQUIRE_THAT(v1, Approx(v2).margin(0.5));
                      REQUIRE_THAT(v1, Approx(v2).epsilon(0.5));
                      REQUIRE_THAT(v1, Approx(v2).epsilon(0.1).scale(500));
                  }
              }
          }
  
          TEST_CASE("Vector Approx matcher -- failing", "[matchers][approx][vector][.failing]") {
              using Catch::Matchers::Approx;
              SECTION("Empty and non empty vectors are not approx equal") {
                  std::vector<double> empty, t1({1, 2});
                  CHECK_THAT(empty, Approx(t1));
              }
              SECTION("Just different vectors") {
                  std::vector<double> v1({2., 4., 6.}), v2({1., 3., 5.});
                  CHECK_THAT(v1, Approx(v2));
              }
          }
  
          TEST_CASE("Exceptions matchers", "[matchers][exceptions][!throws]") {
              REQUIRE_THROWS_MATCHES(throwsDerivedException(),  DerivedException,  Message("DerivedException::what"));
              REQUIRE_THROWS_MATCHES(throwsDerivedException(),  DerivedException, !Message("derivedexception::what"));
              REQUIRE_THROWS_MATCHES(throwsSpecialException(2), SpecialException, !Message("DerivedException::what"));
              REQUIRE_THROWS_MATCHES(throwsSpecialException(2), SpecialException,  Message("SpecialException::what"));
          }
  
          struct CheckedTestingMatcher : Catch::Matchers::MatcherBase<int> {
              mutable bool matchCalled = false;
              bool matchSucceeds = false;
  
              bool match(int const&) const override {
                  matchCalled = true;
                  return matchSucceeds;
              }
              std::string describe() const override {
                  return "CheckedTestingMatcher set to " + (matchSucceeds ? std::string("succeed") : std::string("fail"));
              }
          };
  
          TEST_CASE("Composed matchers shortcircuit", "[matchers][composed]") {
              // Check that if first returns false, second is not touched
              CheckedTestingMatcher first, second;
              SECTION("MatchAllOf") {
                  first.matchSucceeds = false;
  
                  Detail::MatchAllOf<int> matcher =
                      Detail::MatchAllOf<int>{} && first && second;
                  CHECK_FALSE( matcher.match( 1 ) );
  
                  // These two assertions are the important ones
                  REQUIRE(first.matchCalled);
                  REQUIRE(!second.matchCalled);
              }
              // Check that if first returns true, second is not touched
              SECTION("MatchAnyOf") {
                  first.matchSucceeds = true;
  
                  Detail::MatchAnyOf<int> matcher =
                      Detail::MatchAnyOf<int>{} || first || second;
                  CHECK( matcher.match( 1 ) );
  
                  // These two assertions are the important ones
                  REQUIRE(first.matchCalled);
                  REQUIRE(!second.matchCalled);
              }
          }
  
          struct CheckedTestingGenericMatcher : Catch::Matchers::MatcherGenericBase {
              mutable bool matchCalled = false;
              bool matchSucceeds = false;
  
              bool match(int const&) const {
                  matchCalled = true;
                  return matchSucceeds;
              }
              std::string describe() const override {
                  return "CheckedTestingGenericMatcher set to " + (matchSucceeds ? std::string("succeed") : std::string("fail"));
              }
          };
  
          TEST_CASE("Composed generic matchers shortcircuit", "[matchers][composed][generic]") {
              // Check that if first returns false, second is not touched
              CheckedTestingGenericMatcher first, second;
              SECTION("MatchAllOf") {
                  first.matchSucceeds = false;
  
                  Detail::MatchAllOfGeneric<CheckedTestingGenericMatcher,
                                            CheckedTestingGenericMatcher>
                      matcher{ first, second };
  
                  CHECK_FALSE( matcher.match( 1 ) );
  
                  // These two assertions are the important ones
                  REQUIRE(first.matchCalled);
                  REQUIRE(!second.matchCalled);
              }
              // Check that if first returns true, second is not touched
              SECTION("MatchAnyOf") {
                  first.matchSucceeds = true;
  
                  Detail::MatchAnyOfGeneric<CheckedTestingGenericMatcher,
                                            CheckedTestingGenericMatcher>
                      matcher{ first, second };
                  CHECK(matcher.match(1));
  
                  // These two assertions are the important ones
                  REQUIRE(first.matchCalled);
                  REQUIRE(!second.matchCalled);
              }
          }
  
  
      template<typename Range>
      struct EqualsRangeMatcher : Catch::Matchers::MatcherGenericBase {
  
          EqualsRangeMatcher(Range const& range) : m_range{ range } {}
  
          template<typename OtherRange>
          bool match(OtherRange const& other) const {
              using std::begin;
              using std::end;
  
              return std::equal(begin(m_range), end(m_range), begin(other), end(other));
          }
  
          std::string describe() const override {
              return "Equals: " + Catch::rangeToString(m_range);
          }
  
      private:
          Range const& m_range;
      };
  
      template<typename Range>
      auto EqualsRange(const Range& range) -> EqualsRangeMatcher<Range> {
          return EqualsRangeMatcher<Range>{range};
      }
  
      TEST_CASE("Combining templated matchers", "[matchers][templated]") {
          std::array<int, 3> container{{ 1,2,3 }};
  
          std::array<int, 3> a{{ 1,2,3 }};
          std::vector<int> b{ 0,1,2 };
          std::list<int> c{ 4,5,6 };
  
          REQUIRE_THAT(container, EqualsRange(a) || EqualsRange(b) || EqualsRange(c));
      }
  
      TEST_CASE("Combining templated and concrete matchers", "[matchers][templated]") {
          std::vector<int> vec{ 1, 3, 5 };
  
          std::array<int, 3> a{{ 5, 3, 1 }};
  
          REQUIRE_THAT(vec,
                      Predicate<std::vector<int>>([](auto const& v) {
                          return std::all_of(v.begin(), v.end(), [](int elem) {
                              return elem % 2 == 1;
                          });
                      }, "All elements are odd") &&
                      !EqualsRange(a));
  
          const std::string str = "foobar";
          const std::array<char, 6> arr{{ 'f', 'o', 'o', 'b', 'a', 'r' }};
          const std::array<char, 6> bad_arr{{ 'o', 'o', 'f', 'b', 'a', 'r' }};
  
          using Catch::Matchers::StartsWith;
          using Catch::Matchers::EndsWith;
  
          REQUIRE_THAT(str, StartsWith("foo") && EqualsRange(arr) && EndsWith("bar"));
          REQUIRE_THAT(str, StartsWith("foo") && !EqualsRange(bad_arr) && EndsWith("bar"));
  
          REQUIRE_THAT(str, EqualsRange(arr) && StartsWith("foo") && EndsWith("bar"));
          REQUIRE_THAT(str, !EqualsRange(bad_arr) && StartsWith("foo") && EndsWith("bar"));
  
          REQUIRE_THAT(str, EqualsRange(bad_arr) || (StartsWith("foo") && EndsWith("bar")));
          REQUIRE_THAT(str, (StartsWith("foo") && EndsWith("bar")) || EqualsRange(bad_arr));
      }
  
      TEST_CASE("Combining concrete matchers does not use templated matchers", "[matchers][templated]") {
          using Catch::Matchers::StartsWith;
          using Catch::Matchers::EndsWith;
  
          STATIC_REQUIRE(std::is_same<
              decltype(StartsWith("foo") || (StartsWith("bar") && EndsWith("bar") && !EndsWith("foo"))),
              Catch::Matchers::Detail::MatchAnyOf<std::string>
          >::value);
      }
  
      struct MatcherA : Catch::Matchers::MatcherGenericBase {
          std::string describe() const override { return "equals: (int) 1 or (float) 1.0f"; }
          bool match(int i) const { return i == 1; }
          bool match(float f) const { return f == 1.0f; }
      };
  
      struct MatcherB : Catch::Matchers::MatcherGenericBase {
          std::string describe() const override { return "equals: (long long) 1"; }
          bool match(long long l) const { return l == 1ll; }
      };
  
      struct MatcherC : Catch::Matchers::MatcherGenericBase {
          std::string describe() const override { return "equals: (T) 1"; }
          template<typename T>
          bool match(T t) const { return t == T{1}; }
      };
  
      struct MatcherD : Catch::Matchers::MatcherGenericBase {
          std::string describe() const override { return "equals: true"; }
          bool match(bool b) const { return b == true; }
      };
  
      TEST_CASE("Combining only templated matchers", "[matchers][templated]") {
          STATIC_REQUIRE(std::is_same<
              decltype(MatcherA() || MatcherB()),
              Catch::Matchers::Detail::MatchAnyOfGeneric<MatcherA, MatcherB>
          >::value);
  
          REQUIRE_THAT(1, MatcherA() || MatcherB());
  
          STATIC_REQUIRE(std::is_same<
              decltype(MatcherA() && MatcherB()),
              Catch::Matchers::Detail::MatchAllOfGeneric<MatcherA, MatcherB>
          >::value);
  
          REQUIRE_THAT(1, MatcherA() && MatcherB());
  
          STATIC_REQUIRE(std::is_same<
              decltype(MatcherA() || !MatcherB()),
              Catch::Matchers::Detail::MatchAnyOfGeneric<MatcherA, Catch::Matchers::Detail::MatchNotOfGeneric<MatcherB>>
          >::value);
  
          REQUIRE_THAT(1, MatcherA() || !MatcherB());
      }
  
      TEST_CASE("Combining MatchAnyOfGeneric does not nest", "[matchers][templated]") {
          // MatchAnyOfGeneric LHS + some matcher RHS
          STATIC_REQUIRE(std::is_same<
              decltype((MatcherA() || MatcherB()) || MatcherC()),
              Catch::Matchers::Detail::MatchAnyOfGeneric<MatcherA, MatcherB, MatcherC>
          >::value);
  
          REQUIRE_THAT(1, (MatcherA() || MatcherB()) || MatcherC());
  
          // some matcher LHS + MatchAnyOfGeneric RHS
          STATIC_REQUIRE(std::is_same<
                         decltype(MatcherA() || (MatcherB() || MatcherC())),
                         Catch::Matchers::Detail::MatchAnyOfGeneric<MatcherA, MatcherB, MatcherC>
          >::value);
  
          REQUIRE_THAT(1, MatcherA() || (MatcherB() || MatcherC()));
  
  
          // MatchAnyOfGeneric LHS + MatchAnyOfGeneric RHS
          STATIC_REQUIRE(std::is_same<
              decltype((MatcherA() || MatcherB()) || (MatcherC() || MatcherD())),
              Catch::Matchers::Detail::MatchAnyOfGeneric<MatcherA, MatcherB, MatcherC, MatcherD>
          >::value);
  
          REQUIRE_THAT(1, (MatcherA() || MatcherB()) || (MatcherC() || MatcherD()));
      }
  
      TEST_CASE("Combining MatchAllOfGeneric does not nest", "[matchers][templated]") {
          // MatchAllOfGeneric lhs + some matcher RHS
          STATIC_REQUIRE(std::is_same<
              decltype((MatcherA() && MatcherB()) && MatcherC()),
              Catch::Matchers::Detail::MatchAllOfGeneric<MatcherA, MatcherB, MatcherC>
          >::value);
  
          REQUIRE_THAT(1, (MatcherA() && MatcherB()) && MatcherC());
  
          // some matcher LHS + MatchAllOfGeneric RSH
          STATIC_REQUIRE(std::is_same<
                         decltype(MatcherA() && (MatcherB() && MatcherC())),
                         Catch::Matchers::Detail::MatchAllOfGeneric<MatcherA, MatcherB, MatcherC>
          >::value);
  
          REQUIRE_THAT(1, MatcherA() && (MatcherB() && MatcherC()));
  
  
          // MatchAllOfGeneric LHS + MatchAllOfGeneric RHS
          STATIC_REQUIRE(std::is_same<
              decltype((MatcherA() && MatcherB()) && (MatcherC() && MatcherD())),
              Catch::Matchers::Detail::MatchAllOfGeneric<MatcherA, MatcherB, MatcherC, MatcherD>
          >::value);
  
          REQUIRE_THAT(1, (MatcherA() && MatcherB()) && (MatcherC() && MatcherD()));
      }
  
      TEST_CASE("Combining MatchNotOfGeneric does not nest", "[matchers][templated]") {
          STATIC_REQUIRE(std::is_same<
              decltype(!MatcherA()),
              Catch::Matchers::Detail::MatchNotOfGeneric<MatcherA>
          >::value);
  
          REQUIRE_THAT(0, !MatcherA());
  
          STATIC_REQUIRE(std::is_same<
              decltype(!!MatcherA()),
              MatcherA const&
          >::value);
  
          REQUIRE_THAT(1, !!MatcherA());
  
          STATIC_REQUIRE(std::is_same<
              decltype(!!!MatcherA()),
              Catch::Matchers::Detail::MatchNotOfGeneric<MatcherA>
          >::value);
  
          REQUIRE_THAT(0, !!!MatcherA());
  
          STATIC_REQUIRE(std::is_same<
              decltype(!!!!MatcherA()),
              MatcherA const &
          >::value);
  
          REQUIRE_THAT(1, !!!!MatcherA());
      }
  
      struct EvilAddressOfOperatorUsed : std::exception {
          EvilAddressOfOperatorUsed() {}
          const char* what() const noexcept override {
              return "overloaded address-of operator of matcher was used instead of std::addressof";
          }
      };
  
      struct EvilCommaOperatorUsed : std::exception {
          EvilCommaOperatorUsed() {}
          const char* what() const noexcept override {
              return "overloaded comma operator of matcher was used";
          }
      };
  
      struct EvilMatcher : Catch::Matchers::MatcherGenericBase {
          std::string describe() const override {
              return "equals: 45";
          }
  
          bool match(int i) const {
              return i == 45;
          }
  
          EvilMatcher const* operator& () const {
              throw EvilAddressOfOperatorUsed();
          }
  
          int operator,(EvilMatcher const&) const {
              throw EvilCommaOperatorUsed();
          }
      };
  
      TEST_CASE("Overloaded comma or address-of operators are not used", "[matchers][templated]") {
          REQUIRE_THROWS_AS((EvilMatcher(), EvilMatcher()), EvilCommaOperatorUsed);
          REQUIRE_THROWS_AS(&EvilMatcher(), EvilAddressOfOperatorUsed);
          REQUIRE_NOTHROW(EvilMatcher() || (EvilMatcher() && !EvilMatcher()));
          REQUIRE_NOTHROW((EvilMatcher() && EvilMatcher()) || !EvilMatcher());
      }
  
      struct ImmovableMatcher : Catch::Matchers::MatcherGenericBase {
          ImmovableMatcher() = default;
          ImmovableMatcher(ImmovableMatcher const&) = delete;
          ImmovableMatcher(ImmovableMatcher &&) = delete;
          ImmovableMatcher& operator=(ImmovableMatcher const&) = delete;
          ImmovableMatcher& operator=(ImmovableMatcher &&) = delete;
  
          std::string describe() const override {
              return "always false";
          }
  
          template<typename T>
          bool match(T&&) const {
              return false;
          }
      };
  
      struct MatcherWasMovedOrCopied : std::exception {
          MatcherWasMovedOrCopied() {}
          const char* what() const noexcept override {
              return "attempted to copy or move a matcher";
          }
      };
  
      struct ThrowOnCopyOrMoveMatcher : Catch::Matchers::MatcherGenericBase {
          ThrowOnCopyOrMoveMatcher() = default;
          [[noreturn]]
          ThrowOnCopyOrMoveMatcher(ThrowOnCopyOrMoveMatcher const&): Catch::Matchers::MatcherGenericBase() {
              throw MatcherWasMovedOrCopied();
          }
          [[noreturn]]
          ThrowOnCopyOrMoveMatcher(ThrowOnCopyOrMoveMatcher &&): Catch::Matchers::MatcherGenericBase() {
              throw MatcherWasMovedOrCopied();
          }
          ThrowOnCopyOrMoveMatcher& operator=(ThrowOnCopyOrMoveMatcher const&) {
              throw MatcherWasMovedOrCopied();
          }
          ThrowOnCopyOrMoveMatcher& operator=(ThrowOnCopyOrMoveMatcher &&) {
              throw MatcherWasMovedOrCopied();
          }
  
          std::string describe() const override {
              return "always false";
          }
  
          template<typename T>
          bool match(T&&) const {
              return false;
          }
      };
  
      TEST_CASE("Matchers are not moved or copied", "[matchers][templated][approvals]") {
          REQUIRE_NOTHROW((ThrowOnCopyOrMoveMatcher() && ThrowOnCopyOrMoveMatcher()) || !ThrowOnCopyOrMoveMatcher());
      }
  
      TEST_CASE("Immovable matchers can be used", "[matchers][templated][approvals]") {
          REQUIRE_THAT(123, (ImmovableMatcher() && ImmovableMatcher()) || !ImmovableMatcher());
      }
  
      struct ReferencingMatcher : Catch::Matchers::MatcherGenericBase {
          std::string describe() const override {
              return "takes reference";
          }
          bool match(int& i) const {
              return i == 22;
          }
      };
  
      TEST_CASE("Matchers can take references", "[matchers][templated][approvals]") {
          REQUIRE_THAT(22, ReferencingMatcher{});
      }
  
  } } // namespace MatchersTests
  
  #ifdef __clang__
  #pragma clang diagnostic pop
  #endif
  