y.v == 0
0 == 0
0 == y.v
0 == 0
t1 == t2
{?} == {?}
t1 != t2
{?} != {?}
t1 < t2
{?} < {?}
t1 > t2
{?} > {?}
t1 <= t2
{?} <= {?}
t1 >= t2
{?} >= {?}
uarr := "123"
sarr := "456"
std::memcmp(uarr, "123", sizeof(uarr)) == 0
0 == 0
uarr := "123"
sarr := "456"
std::memcmp(sarr, "456", sizeof(sarr)) == 0
0 == 0

# SectionName

h1 == h2
[1403 helper] == [1403 helper]

This info message starts with a linebreak

This warning message starts with a linebreak

1514
This would not be caught previously
Nor would this
std::is_same<TypeList<int>, TypeList<int>>::value
true
spec.matches(*fakeTestCase("spec . char"))
true
spec.matches(*fakeTestCase("spec , char"))
true
!(spec.matches(*fakeTestCase(R"(spec \, char)")))
!false

# Various parentheses

spec.matches(*fakeTestCase(R"(spec {a} char)"))
true
spec.matches(*fakeTestCase(R"(spec [a] char)"))
true
!(spec.matches(*fakeTestCase("differs but has similar tag", "[a]")))
!false

# backslash in test name

spec.matches(*fakeTestCase(R"(spec \ char)"))
true
counter < 7
3 < 7
counter < 7
6 < 7
i != j
1 != 3
i != j
1 != 4
i != j
2 != 3
i != j
2 != 4

# A

# B

m
1

# B

m
2

# B

m
3

# A

1
1
m
2
m
3
m
1
m
2
m
3

# A

i := 1
j := 3
k := 5

# B

i := 1
j := 3
k := 6

# B

i := 1
j := 4
k := 5
i := 1
j := 4
k := 6

# A

i := 2
j := 3
k := 5

# B

i := 2
j := 3
k := 6

# B

i := 2
j := 4
k := 5
i := 2
j := 4
k := 6
m
1
n
1
m
1
n
2
m
1
n
3
m
2
n
1
m
2
n
2
m
2
n
3
m
3
n
1
m
3
n
2
m
3
n
3
smallest_non_zero, WithinULP( -smallest_non_zero, 2 )
0.0 is within 2 ULPs of -4.9406564584124654e-324 ([-1.4821969375237396e-323, 4.9406564584124654e-324])
smallest_non_zero, !WithinULP( -smallest_non_zero, 1 )
0.0 not is within 1 ULPs of -4.9406564584124654e-324 ([-9.8813129168249309e-324, -0.0000000000000000e+00])
smallest_non_zero, WithinULP( -smallest_non_zero, 2 )
0.0f is within 2 ULPs of -1.40129846e-45f ([-4.20389539e-45, 1.40129846e-45])
smallest_non_zero, !WithinULP( -smallest_non_zero, 1 )
0.0f not is within 1 ULPs of -1.40129846e-45f ([-2.80259693e-45, -0.00000000e+00])
{Unknown expression after the reported line}
{Unknown expression after the reported line}
failure to init
bf.e == 1
1 == 1
1 == bf.e
1 == 1

# outside assertions

{Unknown expression after the reported line}
{Unknown expression after the reported line}
expected exception

# inside REQUIRE_NOTHROW

answer := 42
thisThrows()
thisThrows()
expected exception

# inside REQUIRE_THROWS

answer := 42
thisThrows()
thisThrows()
42 == f
42 == {?}
a == t
3 == 3
a == t
3 == 3
throws_int(true)
throws_int(true)
throws_int(true), int
throws_int(true), int
throws_int(false)
throws_int(false)
"aaa", Catch::Matchers::EndsWith("aaa")
"aaa" ends with: "aaa"
templated_tests<int>(3)
true
f() == 0
1 == 0
errno_after == 1
1 == 1
dummy := 0
x == 4
{?} == 4

# Looped section 0

# Looped section 1

# Looped section 2

# Looped section 3

# Looped section 4

false != false
false != false
true != true
true != true
!true
false
!(true)
!true
!trueValue
false
!(trueValue)
!true
!(1 == 1)
false
!(1 == 1)
!(1 == 1)
false == false
false == false
true == true
true == true
!false
true
!(false)
!false
!falseValue
true
!(falseValue)
!false
!(1 == 2)
true
!(1 == 2)
!(1 == 2)

# compare to true

is_true<true>::value == true
true == true
true == is_true<true>::value
true == true

# compare to false

is_true<false>::value == false
false == false
false == is_true<false>::value
false == false

# negation

!is_true<false>::value
true

# double negation

!!is_true<true>::value
true

# direct

is_true<true>::value
true
!(is_true<false>::value)
!false
x < y
1 < 4
y < z
4 < 7
x < z
1 < 7
x < y
1 < 4
y < z
4 < 8
x < z
1 < 8
x < y
1 < 4
y < z
4 < 9
x < z
1 < 9
x < y
1 < 5
y < z
5 < 7
x < z
1 < 7
x < y
1 < 5
y < z
5 < 8
x < z
1 < 8
x < y
1 < 5
y < z
5 < 9
x < z
1 < 9
x < y
1 < 6
y < z
6 < 7
x < z
1 < 7
x < y
1 < 6
y < z
6 < 8
x < z
1 < 8
x < y
1 < 6
y < z
6 < 9
x < z
1 < 9
x < y
2 < 4
y < z
4 < 7
x < z
2 < 7
x < y
2 < 4
y < z
4 < 8
x < z
2 < 8
x < y
2 < 4
y < z
4 < 9
x < z
2 < 9
x < y
2 < 5
y < z
5 < 7
x < z
2 < 7
x < y
2 < 5
y < z
5 < 8
x < z
2 < 8
x < y
2 < 5
y < z
5 < 9
x < z
2 < 9
x < y
2 < 6
y < z
6 < 7
x < z
2 < 7
x < y
2 < 6
y < z
6 < 8
x < z
2 < 8
x < y
2 < 6
y < z
6 < 9
x < z
2 < 9
x < y
3 < 4
y < z
4 < 7
x < z
3 < 7
x < y
3 < 4
y < z
4 < 8
x < z
3 < 8
x < y
3 < 4
y < z
4 < 9
x < z
3 < 9
x < y
3 < 5
y < z
5 < 7
x < z
3 < 7
x < y
3 < 5
y < z
5 < 8
x < z
3 < 8
x < y
3 < 5
y < z
5 < 9
x < z
3 < 9
x < y
3 < 6
y < z
6 < 7
x < z
3 < 7
x < y
3 < 6
y < z
6 < 8
x < z
3 < 8
x < y
3 < 6
y < z
6 < 9
x < z
3 < 9
s == "world"
"hello" == "world"
s == "hello"
"hello" == "hello"
Template_Fixture_2<TestType>::m_a.size() == 1
0 == 1
Template_Fixture_2<TestType>::m_a.size() == 1
0 == 1
Template_Fixture_2<TestType>::m_a.size() == 1
0 == 1
Template_Fixture_2<TestType>::m_a.size() == 1
0 == 1
Template_Fixture_2<TestType>::m_a.size() == 0
0 == 0
Template_Fixture_2<TestType>::m_a.size() == 0
0 == 0
Template_Fixture_2<TestType>::m_a.size() == 0
0 == 0
Template_Fixture_2<TestType>::m_a.size() == 0
0 == 0
Template_Fixture_2<TestType>{}.m_a.size() < 2
6 < 2
Template_Fixture_2<TestType>{}.m_a.size() < 2
2 < 2
Template_Fixture_2<TestType>{}.m_a.size() < 2
6 < 2
Template_Fixture_2<TestType>{}.m_a.size() < 2
2 < 2
Template_Fixture_2<TestType>{}.m_a.size() >= 2
6 >= 2
Template_Fixture_2<TestType>{}.m_a.size() >= 2
2 >= 2
Template_Fixture_2<TestType>{}.m_a.size() >= 2
6 >= 2
Template_Fixture_2<TestType>{}.m_a.size() >= 2
2 >= 2
Template_Fixture<TestType>::m_a == 2
1.0 == 2
Template_Fixture<TestType>::m_a == 2
1.0f == 2
Template_Fixture<TestType>::m_a == 2
1 == 2
Template_Fixture<TestType>::m_a == 1
1.0 == 1
Template_Fixture<TestType>::m_a == 1
1.0f == 1
Template_Fixture<TestType>::m_a == 1
1 == 1
Nttp_Fixture<V>::value == 0
1 == 0
Nttp_Fixture<V>::value == 0
3 == 0
Nttp_Fixture<V>::value == 0
6 == 0
Nttp_Fixture<V>::value > 0
1 > 0
Nttp_Fixture<V>::value > 0
3 > 0
Nttp_Fixture<V>::value > 0
6 > 0
m_a == 2
1 == 2
m_a == 1
1 == 1

# First partial run

m_a++ == 0
0 == 0

# Second partial run

m_a == 0
1 == 0

# First partial run

m_a++ == 0
0 == 0

# Second partial run

m_a == 1
1 == 1
x.size() == 0
0 == 0
x.size() == 0
0 == 0
x.size() == 0
0 == 0
x.size() == 0
0 == 0
x.size() > 0
42 > 0
x.size() > 0
9 > 0
x.size() > 0
42 > 0
x.size() > 0
9 > 0
d == 1.23_a
1.22999999999999998 == Approx( 1.22999999999999998 )
d != 1.22_a
1.22999999999999998 != Approx( 1.21999999999999997 )
-d == -1.23_a
-1.22999999999999998 == Approx( -1.22999999999999998 )
d == 1.2_a .epsilon(.1)
1.22999999999999998 == Approx( 1.19999999999999996 )
d != 1.2_a .epsilon(.001)
1.22999999999999998 != Approx( 1.19999999999999996 )
d == 1_a .epsilon(.3)
1.22999999999999998 == Approx( 1.0 )

# Outer

## Inner

to infinity and beyond
&o1 == &o2
0x<hex digits> == 0x<hex digits>
o1 == o2
{?} == {?}
104.0 != Approx(100.0)
104.0 != Approx( 100.0 )
104.0 == Approx(100.0).margin(5)
104.0 == Approx( 100.0 )
104.0 == Approx(100.0).margin(4)
104.0 == Approx( 100.0 )
104.0 != Approx(100.0).margin(3)
104.0 != Approx( 100.0 )
100.3 != Approx(100.0)
100.29999999999999716 != Approx( 100.0 )
100.3 == Approx(100.0).margin(0.5)
100.29999999999999716 == Approx( 100.0 )
i++ == 7
7 == 7
i++ == 8
8 == 8
1 == 1
1 == 1
{Unknown expression after the reported line}
{Unknown expression after the reported line}
unexpected exception
Approx(0).margin(0)
Approx(0).margin(0)
Approx(0).margin(1234656)
Approx(0).margin(1234656)
Approx(0).margin(-2), std::domain_error
Approx(0).margin(-2), std::domain_error
Approx(0).epsilon(0)
Approx(0).epsilon(0)
Approx(0).epsilon(1)
Approx(0).epsilon(1)
Approx(0).epsilon(-0.001), std::domain_error
Approx(0).epsilon(-0.001), std::domain_error
Approx(0).epsilon(1.0001), std::domain_error
Approx(0).epsilon(1.0001), std::domain_error
0.25f == Approx(0.0f).margin(0.25f)
0.25f == Approx( 0.0 )
0.0f == Approx(0.25f).margin(0.25f)
0.0f == Approx( 0.25 )
0.5f == Approx(0.25f).margin(0.25f)
0.5f == Approx( 0.25 )
245.0f == Approx(245.25f).margin(0.25f)
245.0f == Approx( 245.25 )
245.5f == Approx(245.25f).margin(0.25f)
245.5f == Approx( 245.25 )
divide( 22, 7 ) == Approx( 3.141 ).epsilon( 0.001 )
3.14285714285714279 == Approx( 3.14100000000000001 )
divide( 22, 7 ) != Approx( 3.141 ).epsilon( 0.0001 )
3.14285714285714279 != Approx( 3.14100000000000001 )
d != Approx( 1.231 )
1.22999999999999998 != Approx( 1.23100000000000009 )
d == Approx( 1.231 ).epsilon( 0.1 )
1.22999999999999998 == Approx( 1.23100000000000009 )
1.23f == Approx( 1.23f )
1.230000019f == Approx( 1.23000001907348633 )
0.0f == Approx( 0.0f )
0.0f == Approx( 0.0 )
1 == Approx( 1 )
1 == Approx( 1.0 )
0 == Approx( 0 )
0 == Approx( 0.0 )
1.0f == Approx( 1 )
1.0f == Approx( 1.0 )
0 == Approx( dZero)
0 == Approx( 0.0 )
0 == Approx( dSmall ).margin( 0.001 )
0 == Approx( 0.00001 )
1.234f == Approx( dMedium )
1.233999968f == Approx( 1.23399999999999999 )
dMedium == Approx( 1.234f )
1.23399999999999999 == Approx( 1.23399996757507324 )

# Function pointer

1, Predicate<int>( alwaysTrue, "always true" )
1 matches predicate: "always true"
1, !Predicate<int>( alwaysFalse, "always false" )
1 not matches predicate: "always false"

# Lambdas + different type

"Hello olleH", Predicate<std::string>( []( std::string const& str ) -> bool { return str.front() == str.back(); }, "First and last character should be equal" )
"Hello olleH" matches predicate: "First and last character should be equal"
"This wouldn't pass", !Predicate<std::string>( []( std::string const& str ) -> bool { return str.front() == str.back(); } )
"This wouldn't pass" not matches undescribed predicate
lhs | rhs
Val: 1 | Val: 2
!(lhs & rhs)
!(Val: 1 & Val: 2)
HasBitOperators{ 1 } & HasBitOperators{ 1 }
Val: 1 & Val: 1
lhs ^ rhs
Val: 1 ^ Val: 2
!(lhs ^ lhs)
!(Val: 1 ^ Val: 1)
i > 10
2 > 10
foo( 2 ) == 2
foo( 2 ) == 2
{ nested assertion failed }
true
true
i > 10
2 > 10
foo( 2 ) == 2
foo( 2 ) == 2
{ nested assertion failed }
true
true

# A section

true
true

## Another section

true
true
true
true

# A section

true
true

## Another other section

true
true

# Different argument ranges, same element type, default comparison

a, Contains(1)
{ 1, 2, 3 } contains element 1
b, Contains(1)
{ 0, 1, 2 } contains element 1
c, !Contains(1)
{ 4, 5, 6 } not contains element 1

# Different argument ranges, same element type, custom comparison

a, Contains(0, close_enough)
{ 1, 2, 3 } contains element 0
b, Contains(0, close_enough)
{ 0, 1, 2 } contains element 0
c, !Contains(0, close_enough)
{ 4, 5, 6 } not contains element 0

# Different element type, custom comparisons

a, Contains(4, [](auto&& lhs, size_t sz) { return lhs.size() == sz; })
{ "abc", "abcd", "abcde" } contains element 4

# Can handle type that requires ADL-found free function begin and end

in, Contains(1)
{ 1, 2, 3, 4, 5 } contains element 1
in, !Contains(8)
{ 1, 2, 3, 4, 5 } not contains element 8

# Initialization with move only types

in, Contains(MoveOnlyTestElement{ 2 })
{ 1, 2, 3 } contains element 2
in, !Contains(MoveOnlyTestElement{ 9 })
{ 1, 2, 3 } not contains element 9

# Matching using matcher

in, Contains(Catch::Matchers::WithinAbs(0.5, 0.5))
{ 1.0, 2.0, 3.0, 0.0 } contains element matching is within 0.5 of 0.5

# Simple, std-provided containers

empty_array, IsEmpty()
{ } is empty
non_empty_array, !IsEmpty()
{ 0.0 } not is empty
empty_vec, IsEmpty()
{ } is empty
non_empty_vec, !IsEmpty()
{ 'a', 'b', 'c' } not is empty
inner_lists_are_empty, !IsEmpty()
{ { } } not is empty
inner_lists_are_empty.front(), IsEmpty()
{ } is empty

# Type with empty

has_empty{}, !IsEmpty()
{?} not is empty

# Type requires ADL found empty free function

unrelated::ADL_empty{}, IsEmpty()
{?} is empty
a := 1
b := 2
c := 3
a + b := 3
a+b := 3
c > b := true
a == 1 := true
custom_index_op<int>{1, 2, 3}[0, 1, 2] := 0
custom_index_op<int>{1, 2, 3}[(0, 1)] := 0
custom_index_op<int>{1, 2, 3}[0] := 0
(helper_1436<int, int>{12, -12}) := { 12, -12 }
(helper_1436<int, int>(-12, 12)) := { -12, 12 }
(1, 2) := 2
(2, 3) := 3
("comma, in string", "escaped, \", ") := "escaped, ", "
"single quote in string,'," := "single quote in string,',"
"some escapes, \\,\\\\" := "some escapes, \,\\"
"some, ), unmatched, } prenheses {[<" := "some, ), unmatched, } prenheses {[<"
'"' := '"'
'\'' := '''
',' := ','
'}' := '}'
')' := ')'
'(' := '('
'{' := '{'

# Capture should stringify like assertions

i := 2
true
true

# Info should NOT stringify the way assertions do

3
true
true
a := 1
false
false

# Dummy section

a := 1
true
true
a := 1
false
false

# Degenerate cases

eq( "", "" )
true
!(eq( "", "a" ))
!false

# Plain comparisons

eq( "a", "a" )
true
eq( "a", "A" )
true
eq( "A", "a" )
true
eq( "A", "A" )
true
!(eq( "a", "b" ))
!false
!(eq( "a", "B" ))
!false

# Degenerate cases

lt( "", "a" )
true
!(lt( "a", "a" ))
!false
!(lt( "", "" ))
!false

# Plain comparisons

lt( "a", "b" )
true
lt( "a", "B" )
true
lt( "A", "b" )
true
lt( "A", "B" )
true

# Specifically escaped

::Catch::Detail::stringify('\t') == "'\\t'"
"'\t'" == "'\t'"
::Catch::Detail::stringify('\n') == "'\\n'"
"'\n'" == "'\n'"
::Catch::Detail::stringify('\r') == "'\\r'"
"'\r'" == "'\r'"
::Catch::Detail::stringify('\f') == "'\\f'"
"'\f'" == "'\f'"

# General chars

::Catch::Detail::stringify( ' ' ) == "' '"
"' '" == "' '"
::Catch::Detail::stringify( 'A' ) == "'A'"
"'A'" == "'A'"
::Catch::Detail::stringify( 'z' ) == "'z'"
"'z'" == "'z'"

# Low ASCII

::Catch::Detail::stringify( '\0' ) == "0"
"0" == "0"
::Catch::Detail::stringify( static_cast<char>(2) ) == "2"
"2" == "2"
::Catch::Detail::stringify( static_cast<char>(5) ) == "5"
"5" == "5"
name.empty()
true
result
{?}
result.type() == Catch::Clara::Detail::ResultType::Ok
0 == 0
parsed.type() == Catch::Clara::ParseResultType::NoMatch
1 == 1
parsed.remainingTokens().count() == 2
2 == 2
name.empty()
true
name.empty()
true
name == "foo"
"foo" == "foo"

# Parsing fails on multiple options without accept_many

!(parse_result)
!{?}

# Parsing succeeds on multiple options with accept_many

parse_result
{?}
res == std::vector<std::string>{ "aaa", "bbb" }
{ "aaa", "bbb" } == { "aaa", "bbb" }

# ColourGuard is disengaged by default

streamWrapper.str().empty()
true

# ColourGuard is engaged by op<<

streamWrapper.str() == "1\nUsing code: 2\n2\nUsing code: 0\n3\n"
"1 Using code: 2 2 Using code: 0 3 " == "1 Using code: 2 2 Using code: 0 3 "

# ColourGuard can be engaged explicitly

streamWrapper.str() == "Using code: 2\nA\nB\nUsing code: 0\nC\n"
"Using code: 2 A B Using code: 0 C " == "Using code: 2 A B Using code: 0 C "
1, ( MatcherA() && MatcherB() ) && MatcherC()
1 ( equals: (int) 1 or (string) "1" and equals: (long long) 1 and equals: (T) 1 )
1, MatcherA() && ( MatcherB() && MatcherC() )
1 ( equals: (int) 1 or (string) "1" and equals: (long long) 1 and equals: (T) 1 )
1, ( MatcherA() && MatcherB() ) && ( MatcherC() && MatcherD() )
1 ( equals: (int) 1 or (string) "1" and equals: (long long) 1 and equals: (T) 1 and equals: true )
1, ( MatcherA() || MatcherB() ) || MatcherC()
1 ( equals: (int) 1 or (string) "1" or equals: (long long) 1 or equals: (T) 1 )
1, MatcherA() || ( MatcherB() || MatcherC() )
1 ( equals: (int) 1 or (string) "1" or equals: (long long) 1 or equals: (T) 1 )
1, ( MatcherA() || MatcherB() ) || ( MatcherC() || MatcherD() )
1 ( equals: (int) 1 or (string) "1" or equals: (long long) 1 or equals: (T) 1 or equals: true )
0, !MatcherA()
0 not equals: (int) 1 or (string) "1"
1, !!MatcherA()
1 equals: (int) 1 or (string) "1"
0, !!!MatcherA()
0 not equals: (int) 1 or (string) "1"
1, !!!!MatcherA()
1 equals: (int) 1 or (string) "1"
1, MatcherA() || MatcherB()
1 ( equals: (int) 1 or (string) "1" or equals: (long long) 1 )
1, MatcherA() && MatcherB()
1 ( equals: (int) 1 or (string) "1" and equals: (long long) 1 )
1, MatcherA() || !MatcherB()
1 ( equals: (int) 1 or (string) "1" or not equals: (long long) 1 )
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 )
{ 1, 3, 5 } ( matches predicate: "All elements are odd" and not Equals: { 5, 3, 1 } )
str, StartsWith( "foo" ) && EqualsRange( arr ) && EndsWith( "bar" )
"foobar" ( starts with: "foo" and Equals: { 'f', 'o', 'o', 'b', 'a', 'r' } and ends with: "bar" )
str, StartsWith( "foo" ) && !EqualsRange( bad_arr ) && EndsWith( "bar" )
"foobar" ( starts with: "foo" and not Equals: { 'o', 'o', 'f', 'b', 'a', 'r' } and ends with: "bar" )
str, EqualsRange( arr ) && StartsWith( "foo" ) && EndsWith( "bar" )
"foobar" ( Equals: { 'f', 'o', 'o', 'b', 'a', 'r' } and starts with: "foo" and ends with: "bar" )
str, !EqualsRange( bad_arr ) && StartsWith( "foo" ) && EndsWith( "bar" )
"foobar" ( not Equals: { 'o', 'o', 'f', 'b', 'a', 'r' } and starts with: "foo" and ends with: "bar" )
str, EqualsRange( bad_arr ) || ( StartsWith( "foo" ) && EndsWith( "bar" ) )
"foobar" ( Equals: { 'o', 'o', 'f', 'b', 'a', 'r' } or ( starts with: "foo" and ends with: "bar" ) )
str, ( StartsWith( "foo" ) && EndsWith( "bar" ) ) || EqualsRange( bad_arr )
"foobar" ( ( starts with: "foo" and ends with: "bar" ) or Equals: { 'o', 'o', 'f', 'b', 'a', 'r' } )
container, EqualsRange( a ) || EqualsRange( b ) || EqualsRange( c )
{ 1, 2, 3 } ( Equals: { 1, 2, 3 } or Equals: { 0, 1, 2 } or Equals: { 4, 5, 6 } )
std::vector<constructor_throws>{constructor_throws{}, constructor_throws{}}
std::vector<constructor_throws>{constructor_throws{}, constructor_throws{}}
std::vector<constructor_throws>{constructor_throws{}, constructor_throws{}}
std::vector<constructor_throws>{constructor_throws{}, constructor_throws{}}
std::vector<int>{1, 2, 3} == std::vector<int>{1, 2, 3}
std::vector<int>{1, 2, 3} == std::vector<int>{1, 2, 3}
std::vector<int>{1, 2, 3} == std::vector<int>{1, 2, 3}
std::vector<int>{1, 2, 3} == std::vector<int>{1, 2, 3}
std::vector<int>{1, 2} == std::vector<int>{1, 2}
{ 1, 2 } == { 1, 2 }
std::vector<int>{1, 2} == std::vector<int>{1, 2}
{ 1, 2 } == { 1, 2 }
!(std::vector<int>{1, 2} == std::vector<int>{1, 2, 3})
!({ 1, 2 } == { 1, 2, 3 })
!(std::vector<int>{1, 2} == std::vector<int>{1, 2, 3})
!({ 1, 2 } == { 1, 2, 3 })
std::vector<int>{1, 2} == std::vector<int>{1, 2}
{ 1, 2 } == { 1, 2 }
std::vector<int>{1, 2} == std::vector<int>{1, 2}
{ 1, 2 } == { 1, 2 }
true
true
std::vector<int>{1, 2} == std::vector<int>{1, 2}
{ 1, 2 } == { 1, 2 }
!(ptr)
!0
ptr == ptr
0 == 0
!(ptr != ptr)
!(0 != 0)
!(ptr < ptr)
!(0 < 0)
ptr <= ptr
0 <= 0
!(ptr > ptr)
!(0 > 0)
ptr >= ptr
0 >= 0
a
0x<hex digits>
a == &foo
0x<hex digits> == 0x<hex digits>
SimplePcg32{} == SimplePcg32{}
{?} == {?}
SimplePcg32{ 0 } != SimplePcg32{}
{?} != {?}
!(SimplePcg32{ 1 } == SimplePcg32{ 2 })
!({?} == {?})
!(SimplePcg32{ 1 } != SimplePcg32{ 1 })
!({?} != {?})
td == Approx(10.0)
StrongDoubleTypedef(10) == Approx( 10.0 )
Approx(10.0) == td
Approx( 10.0 ) == StrongDoubleTypedef(10)
td != Approx(11.0)
StrongDoubleTypedef(10) != Approx( 11.0 )
Approx(11.0) != td
Approx( 11.0 ) != StrongDoubleTypedef(10)
td <= Approx(10.0)
StrongDoubleTypedef(10) <= Approx( 10.0 )
td <= Approx(11.0)
StrongDoubleTypedef(10) <= Approx( 11.0 )
Approx(10.0) <= td
Approx( 10.0 ) <= StrongDoubleTypedef(10)
Approx(9.0) <= td
Approx( 9.0 ) <= StrongDoubleTypedef(10)
td >= Approx(9.0)
StrongDoubleTypedef(10) >= Approx( 9.0 )
td >= Approx(td)
StrongDoubleTypedef(10) >= Approx( 10.0 )
Approx(td) >= td
Approx( 10.0 ) >= StrongDoubleTypedef(10)
Approx(11.0) >= td
Approx( 11.0 ) >= StrongDoubleTypedef(10)
54 == 6*9
54 == 54
( -1 > 2u )
true
-1 > 2u
-1 > 2
( 2u < -1 )
true
2u < -1
2 < -1
( minInt > 2u )
true
minInt > 2u
-2147483648 > 2
i == 1
1 == 1
ui == 2
2 == 2
l == 3
3 == 3
ul == 4
4 == 4
c == 5
5 == 5
uc == 6
6 == 6
1 == i
1 == 1
2 == ui
2 == 2
3 == l
3 == 3
4 == ul
4 == 4
5 == c
5 == 5
6 == uc
6 == 6
(std::numeric_limits<uint32_t>::max)() > ul
4294967295 (0x<hex digits>) > 4

# MatchAllOf

!(matcher.match( 1 ))
!false
first.matchCalled
true
!second.matchCalled
true

# MatchAnyOf

matcher.match( 1 )
true
first.matchCalled
true
!second.matchCalled
true

# MatchAllOf

!(matcher.match( 1 ))
!false
first.matchCalled
true
!second.matchCalled
true

# MatchAnyOf

matcher.match( 1 )
true
first.matchCalled
true
!second.matchCalled
true
testStringForMatching(), ContainsSubstring( "not there", Catch::CaseSensitive::No )
"this string contains 'abc' as a substring" contains: "not there" (case insensitive)
testStringForMatching(), ContainsSubstring( "STRING" )
"this string contains 'abc' as a substring" contains: "STRING"

# from var and iterators

elem % 2 == 1
1 == 1

# from var and iterators

elem % 2 == 1
1 == 1

# from var and iterators

elem % 2 == 1
1 == 1

# from var and iterators

elem % 2 == 1
1 == 1

# from var and iterators

elem % 2 == 1
1 == 1

# from var and iterators

elem % 2 == 1
1 == 1

# From a temporary container

elem % 2 == 1
1 == 1

# From a temporary container

elem % 2 == 1
1 == 1

# From a temporary container

elem % 2 == 1
1 == 1

# From a temporary container

elem % 2 == 1
1 == 1

# From a temporary container

elem % 2 == 1
1 == 1

# From a temporary container

elem % 2 == 1
1 == 1

# Final validation

call_count == 1
1 == 1
make_data().size() == test_count
6 == 6
Catch::makeStream( "-" )->isConsole()
true
throwCustom()
throwCustom()
custom exception - not std
throwCustom(), std::exception
throwCustom(), std::exception
custom exception - not std
custom std exception
101.000001 != Approx(100).epsilon(0.01)
101.00000099999999748 != Approx( 100.0 )
std::pow(10, -5) != Approx(std::pow(10, -7))
0.00001 != Approx( 0.0000001 )
a
true
true
b
false
false
enumInfo->lookup(0) == "Value1"
Value1 == "Value1"
enumInfo->lookup(1) == "Value2"
Value2 == "Value2"
enumInfo->lookup(3) == "{** unexpected enum value **}"
{** unexpected enum value **} == "{** unexpected enum value **}"
This generator is empty
Catch::makeStream( "" )->isConsole()
true
testStringForMatching(), EndsWith( "Substring" )
"this string contains 'abc' as a substring" ends with: "Substring"
testStringForMatching(), EndsWith( "this", Catch::CaseSensitive::No )
"this string contains 'abc' as a substring" ends with: "this" (case insensitive)
stringify( EnumClass3::Value1 ) == "Value1"
"Value1" == "Value1"
stringify( EnumClass3::Value2 ) == "Value2"
"Value2" == "Value2"
stringify( EnumClass3::Value3 ) == "Value3"
"Value3" == "Value3"
stringify( EnumClass3::Value4 ) == "{** unexpected enum value **}"
"{** unexpected enum value **}" == "{** unexpected enum value **}"
stringify( ec3 ) == "Value2"
"Value2" == "Value2"
stringify( Bikeshed::Colours::Red ) == "Red"
"Red" == "Red"
stringify( Bikeshed::Colours::Blue ) == "Blue"
"Blue" == "Blue"
101.01 != Approx(100).epsilon(0.01)
101.01000000000000512 != Approx( 100.0 )
data.int_seven == 6
7 == 6
data.int_seven == 8
7 == 8
data.int_seven == 0
7 == 0
data.float_nine_point_one == Approx( 9.11f )
9.100000381f == Approx( 9.10999965667724609 )
data.float_nine_point_one == Approx( 9.0f )
9.100000381f == Approx( 9.0 )
data.float_nine_point_one == Approx( 1 )
9.100000381f == Approx( 1.0 )
data.float_nine_point_one == Approx( 0 )
9.100000381f == Approx( 0.0 )
data.double_pi == Approx( 3.1415 )
3.14159265350000005 == Approx( 3.14150000000000018 )
data.str_hello == "goodbye"
"hello" == "goodbye"
data.str_hello == "hell"
"hello" == "hell"
data.str_hello == "hello1"
"hello" == "hello1"
data.str_hello.size() == 6
5 == 6
x == Approx( 1.301 )
1.30000000000000027 == Approx( 1.30099999999999993 )
data.int_seven == 7
7 == 7
data.float_nine_point_one == Approx( 9.1f )
9.100000381f == Approx( 9.10000038146972656 )
data.double_pi == Approx( 3.1415926535 )
3.14159265350000005 == Approx( 3.14159265350000005 )
data.str_hello == "hello"
"hello" == "hello"
"hello" == data.str_hello
"hello" == "hello"
data.str_hello.size() == 5
5 == 5
x == Approx( 1.3 )
1.30000000000000027 == Approx( 1.30000000000000004 )
testStringForMatching(), Equals( "this string contains 'abc' as a substring" )
"this string contains 'abc' as a substring" equals: "this string contains 'abc' as a substring"
testStringForMatching(), Equals( "this string contains 'ABC' as a substring", Catch::CaseSensitive::No )
"this string contains 'abc' as a substring" equals: "this string contains 'abc' as a substring" (case insensitive)
testStringForMatching(), Equals( "this string contains 'ABC' as a substring" )
"this string contains 'abc' as a substring" equals: "this string contains 'ABC' as a substring"
testStringForMatching(), Equals( "something else", Catch::CaseSensitive::No )
"this string contains 'abc' as a substring" equals: "something else" (case insensitive)
::Catch::Detail::stringify(WhatException{}) == "This exception has overridden what() method"
"This exception has overridden what() method" == "This exception has overridden what() method"
::Catch::Detail::stringify(OperatorException{}) == "OperatorException"
"OperatorException" == "OperatorException"
::Catch::Detail::stringify(StringMakerException{}) == "StringMakerException"
"StringMakerException" == "StringMakerException"

# No exception

doesNotThrow(), SpecialException, ExceptionMatcher{ 1 }
doesNotThrow(), SpecialException, ExceptionMatcher{ 1 }
doesNotThrow(), SpecialException, ExceptionMatcher{ 1 }
doesNotThrow(), SpecialException, ExceptionMatcher{ 1 }

# Type mismatch

throwsAsInt( 1 ), SpecialException, ExceptionMatcher{ 1 }
throwsAsInt( 1 ), SpecialException, ExceptionMatcher{ 1 }
Unknown exception
throwsAsInt( 1 ), SpecialException, ExceptionMatcher{ 1 }
throwsAsInt( 1 ), SpecialException, ExceptionMatcher{ 1 }
Unknown exception

# Contents are wrong

throwsSpecialException( 3 ), SpecialException, ExceptionMatcher{ 1 }
SpecialException::what special exception has value of 1
throwsSpecialException( 4 ), SpecialException, ExceptionMatcher{ 1 }
SpecialException::what special exception has value of 1
throwsSpecialException( 1 ), SpecialException, ExceptionMatcher{ 1 }
SpecialException::what special exception has value of 1
throwsSpecialException( 2 ), SpecialException, ExceptionMatcher{ 2 }
SpecialException::what special exception has value of 2
throwsDerivedException(), DerivedException, MessageMatches( StartsWith( "Derived" ) )
DerivedException::what matches "starts with: "Derived""
throwsDerivedException(), DerivedException, MessageMatches( EndsWith( "::what" ) )
DerivedException::what matches "ends with: "::what""
throwsDerivedException(), DerivedException, MessageMatches( !StartsWith( "::what" ) )
DerivedException::what matches "not starts with: "::what""
throwsSpecialException( 2 ), SpecialException, MessageMatches( StartsWith( "Special" ) )
SpecialException::what matches "starts with: "Special""

# exact match

thisThrows(), "expected exception"
"expected exception" equals: "expected exception"

# different case

thisThrows(), Equals( "expecteD Exception", Catch::CaseSensitive::No )
"expected exception" equals: "expected exception" (case insensitive)

# wildcarded

thisThrows(), StartsWith( "expected" )
"expected exception" starts with: "expected"
thisThrows(), EndsWith( "exception" )
"expected exception" ends with: "exception"
thisThrows(), ContainsSubstring( "except" )
"expected exception" contains: "except"
thisThrows(), ContainsSubstring( "exCept", Catch::CaseSensitive::No )
"expected exception" contains: "except" (case insensitive)
tos == tos
{ stringification failed with an exception: "Invalid" } == { stringification failed with an exception: "Invalid" }
throwsDerivedException(), DerivedException, Message( "DerivedException::what" )
DerivedException::what exception message matches "DerivedException::what"
throwsDerivedException(), DerivedException, !Message( "derivedexception::what" )
DerivedException::what not exception message matches "derivedexception::what"
throwsSpecialException( 2 ), SpecialException, !Message( "DerivedException::what" )
SpecialException::what not exception message matches "DerivedException::what"
throwsSpecialException( 2 ), SpecialException, Message( "SpecialException::what" )
SpecialException::what exception message matches "SpecialException::what"
thisThrows(), std::string
thisThrows(), std::string
expected exception
thisDoesntThrow(), std::domain_error
thisDoesntThrow(), std::domain_error
thisThrows()
thisThrows()
expected exception
This is a failure
Throw a Catch::TestFailureException
do_fail()
do_fail()
{ nested assertion failed }
This is a failure

This message appears in the output

Factorial(0) == 1
1 == 1
Factorial(1) == 1
1 == 1
Factorial(2) == 2
2 == 2
Factorial(3) == 6
6 == 6
Factorial(10) == 3628800
3628800 (0x<hex digits>) == 3628800 (0x<hex digits>)
filter( []( int ) { return false; }, value( 3 ) ), Catch::GeneratorException
filter( []( int ) { return false; }, value( 3 ) ), Catch::GeneratorException

# Relative

10., WithinRel( 11.1, 0.1 )
10.0 and 11.09999999999999964 are within 10% of each other
10., !WithinRel( 11.2, 0.1 )
10.0 not and 11.19999999999999929 are within 10% of each other
1., !WithinRel( 0., 0.99 )
1.0 not and 0.0 are within 99% of each other
-0., WithinRel( 0. )
-0.0 and 0.0 are within 2.22045e-12% of each other

## Some subnormal values

v1, WithinRel( v2 )
0.0 and 0.0 are within 2.22045e-12% of each other

# Margin

1., WithinAbs( 1., 0 )
1.0 is within 0.0 of 1.0
0., WithinAbs( 1., 1 )
0.0 is within 1.0 of 1.0
0., !WithinAbs( 1., 0.99 )
0.0 not is within 0.98999999999999999 of 1.0
0., !WithinAbs( 1., 0.99 )
0.0 not is within 0.98999999999999999 of 1.0
11., !WithinAbs( 10., 0.5 )
11.0 not is within 0.5 of 10.0
10., !WithinAbs( 11., 0.5 )
10.0 not is within 0.5 of 11.0
-10., WithinAbs( -10., 0.5 )
-10.0 is within 0.5 of -10.0
-10., WithinAbs( -9.6, 0.5 )
-10.0 is within 0.5 of -9.59999999999999964

# ULPs

1., WithinULP( 1., 0 )
1.0 is within 0 ULPs of 1.0000000000000000e+00 ([1.0000000000000000e+00, 1.0000000000000000e+00])
nextafter( 1., 2. ), WithinULP( 1., 1 )
1.00000000000000022 is within 1 ULPs of 1.0000000000000000e+00 ([9.9999999999999989e-01, 1.0000000000000002e+00])
0., WithinULP( nextafter( 0., 1. ), 1 )
0.0 is within 1 ULPs of 4.9406564584124654e-324 ([0.0000000000000000e+00, 9.8813129168249309e-324])
1., WithinULP( nextafter( 1., 0. ), 1 )
1.0 is within 1 ULPs of 9.9999999999999989e-01 ([9.9999999999999978e-01, 1.0000000000000000e+00])
1., !WithinULP( nextafter( 1., 2. ), 0 )
1.0 not is within 0 ULPs of 1.0000000000000002e+00 ([1.0000000000000002e+00, 1.0000000000000002e+00])
1., WithinULP( 1., 0 )
1.0 is within 0 ULPs of 1.0000000000000000e+00 ([1.0000000000000000e+00, 1.0000000000000000e+00])
-0., WithinULP( 0., 0 )
-0.0 is within 0 ULPs of 0.0000000000000000e+00 ([0.0000000000000000e+00, 0.0000000000000000e+00])

# Composed

1., WithinAbs( 1., 0.5 ) || WithinULP( 2., 1 )
1.0 ( is within 0.5 of 1.0 or is within 1 ULPs of 2.0000000000000000e+00 ([1.9999999999999998e+00, 2.0000000000000004e+00]) )
1., WithinAbs( 2., 0.5 ) || WithinULP( 1., 0 )
1.0 ( is within 0.5 of 2.0 or is within 0 ULPs of 1.0000000000000000e+00 ([1.0000000000000000e+00, 1.0000000000000000e+00]) )
0.0001, WithinAbs( 0., 0.001 ) || WithinRel( 0., 0.1 )
0.0001 ( is within 0.001 of 0.0 or and 0.0 are within 10% of each other )

# Constructor validation

WithinAbs( 1., 0. )
WithinAbs( 1., 0. )
WithinAbs( 1., -1. ), std::domain_error
WithinAbs( 1., -1. ), std::domain_error
WithinULP( 1., 0 )
WithinULP( 1., 0 )
WithinRel( 1., 0. )
WithinRel( 1., 0. )
WithinRel( 1., -0.2 ), std::domain_error
WithinRel( 1., -0.2 ), std::domain_error
WithinRel( 1., 1. ), std::domain_error
WithinRel( 1., 1. ), std::domain_error

# IsNaN

1., !IsNaN()
1.0 not is NaN

# Relative

10.f, WithinRel( 11.1f, 0.1f )
10.0f and 11.10000038146972656 are within 10% of each other
10.f, !WithinRel( 11.2f, 0.1f )
10.0f not and 11.19999980926513672 are within 10% of each other
1.f, !WithinRel( 0.f, 0.99f )
1.0f not and 0.0 are within 99% of each other
-0.f, WithinRel( 0.f )
-0.0f and 0.0 are within 0.00119209% of each other

## Some subnormal values

v1, WithinRel( v2 )
0.0f and 0.0 are within 0.00119209% of each other

# Margin

1.f, WithinAbs( 1.f, 0 )
1.0f is within 0.0 of 1.0
0.f, WithinAbs( 1.f, 1 )
0.0f is within 1.0 of 1.0
0.f, !WithinAbs( 1.f, 0.99f )
0.0f not is within 0.99000000953674316 of 1.0
0.f, !WithinAbs( 1.f, 0.99f )
0.0f not is within 0.99000000953674316 of 1.0
0.f, WithinAbs( -0.f, 0 )
0.0f is within 0.0 of -0.0
11.f, !WithinAbs( 10.f, 0.5f )
11.0f not is within 0.5 of 10.0
10.f, !WithinAbs( 11.f, 0.5f )
10.0f not is within 0.5 of 11.0
-10.f, WithinAbs( -10.f, 0.5f )
-10.0f is within 0.5 of -10.0
-10.f, WithinAbs( -9.6f, 0.5f )
-10.0f is within 0.5 of -9.60000038146972656

# ULPs

1.f, WithinULP( 1.f, 0 )
1.0f is within 0 ULPs of 1.00000000e+00f ([1.00000000e+00, 1.00000000e+00])
-1.f, WithinULP( -1.f, 0 )
-1.0f is within 0 ULPs of -1.00000000e+00f ([-1.00000000e+00, -1.00000000e+00])
nextafter( 1.f, 2.f ), WithinULP( 1.f, 1 )
1.000000119f is within 1 ULPs of 1.00000000e+00f ([9.99999940e-01, 1.00000012e+00])
0.f, WithinULP( nextafter( 0.f, 1.f ), 1 )
0.0f is within 1 ULPs of 1.40129846e-45f ([0.00000000e+00, 2.80259693e-45])
1.f, WithinULP( nextafter( 1.f, 0.f ), 1 )
1.0f is within 1 ULPs of 9.99999940e-01f ([9.99999881e-01, 1.00000000e+00])
1.f, !WithinULP( nextafter( 1.f, 2.f ), 0 )
1.0f not is within 0 ULPs of 1.00000012e+00f ([1.00000012e+00, 1.00000012e+00])
1.f, WithinULP( 1.f, 0 )
1.0f is within 0 ULPs of 1.00000000e+00f ([1.00000000e+00, 1.00000000e+00])
-0.f, WithinULP( 0.f, 0 )
-0.0f is within 0 ULPs of 0.00000000e+00f ([0.00000000e+00, 0.00000000e+00])

# Composed

1.f, WithinAbs( 1.f, 0.5 ) || WithinULP( 1.f, 1 )
1.0f ( is within 0.5 of 1.0 or is within 1 ULPs of 1.00000000e+00f ([9.99999940e-01, 1.00000012e+00]) )
1.f, WithinAbs( 2.f, 0.5 ) || WithinULP( 1.f, 0 )
1.0f ( is within 0.5 of 2.0 or is within 0 ULPs of 1.00000000e+00f ([1.00000000e+00, 1.00000000e+00]) )
0.0001f, WithinAbs( 0.f, 0.001f ) || WithinRel( 0.f, 0.1f )
0.0001f ( is within 0.00100000004749745 of 0.0 or and 0.0 are within 10% of each other )

# Constructor validation

WithinAbs( 1.f, 0.f )
WithinAbs( 1.f, 0.f )
WithinAbs( 1.f, -1.f ), std::domain_error
WithinAbs( 1.f, -1.f ), std::domain_error
WithinULP( 1.f, 0 )
WithinULP( 1.f, 0 )
WithinULP( 1.f, static_cast<uint64_t>( -1 ) ), std::domain_error
WithinULP( 1.f, static_cast<uint64_t>( -1 ) ), std::domain_error
WithinRel( 1.f, 0.f )
WithinRel( 1.f, 0.f )
WithinRel( 1.f, -0.2f ), std::domain_error
WithinRel( 1.f, -0.2f ), std::domain_error
WithinRel( 1.f, 1.f ), std::domain_error
WithinRel( 1.f, 1.f ), std::domain_error

# IsNaN

1., !IsNaN()
1.0 not is NaN
i % 2 == 0
0 == 0
i % 2 == 0
0 == 0
i % 2 == 0
0 == 0
i % 2 == 0
0 == 0

# Filtering by predicate

## Basic usage

i % 2 == 0
0 == 0

# Filtering by predicate

## Basic usage

i % 2 == 0
0 == 0

# Filtering by predicate

## Basic usage

i % 2 == 0
0 == 0

# Filtering by predicate

## Throws if there are no matching values

filter([] (int) {return false; }, value(1)), Catch::GeneratorException
filter([] (int) {return false; }, value(1)), Catch::GeneratorException

# Shortening a range

i < 4
1 < 4

# Shortening a range

i < 4
2 < 4

# Shortening a range

i < 4
3 < 4

# Transforming elements

## Same type

i % 2 == 0
0 == 0

# Transforming elements

## Same type

i % 2 == 0
0 == 0

# Transforming elements

## Same type

i % 2 == 0
0 == 0

# Transforming elements

## Different type

i.size() == 1
1 == 1

# Transforming elements

## Different type

i.size() == 1
1 == 1

# Transforming elements

## Different type

i.size() == 1
1 == 1

# Transforming elements

## Different deduced type

i.size() == 1
1 == 1

# Transforming elements

## Different deduced type

i.size() == 1
1 == 1

# Transforming elements

## Different deduced type

i.size() == 1
1 == 1

# Repeating a generator

j > 0
1 > 0

# Repeating a generator

j > 0
2 > 0

# Repeating a generator

j > 0
3 > 0

# Repeating a generator

j > 0
1 > 0

# Repeating a generator

j > 0
2 > 0

# Repeating a generator

j > 0
3 > 0

# Chunking a generator into sized pieces

## Number of elements in source is divisible by chunk size

chunk2.size() == 2
2 == 2
chunk2.front() == chunk2.back()
1 == 1

# Chunking a generator into sized pieces

## Number of elements in source is divisible by chunk size

chunk2.size() == 2
2 == 2
chunk2.front() == chunk2.back()
2 == 2

# Chunking a generator into sized pieces

## Number of elements in source is divisible by chunk size

chunk2.size() == 2
2 == 2
chunk2.front() == chunk2.back()
3 == 3

# Chunking a generator into sized pieces

## Number of elements in source is not divisible by chunk size

chunk2.size() == 2
2 == 2
chunk2.front() == chunk2.back()
1 == 1
chunk2.front() < 3
1 < 3

# Chunking a generator into sized pieces

## Number of elements in source is not divisible by chunk size

chunk2.size() == 2
2 == 2
chunk2.front() == chunk2.back()
2 == 2
chunk2.front() < 3
2 < 3

# Chunking a generator into sized pieces

## Chunk size of zero

chunk2.size() == 0
0 == 0

# Chunking a generator into sized pieces

## Chunk size of zero

chunk2.size() == 0
0 == 0

# Chunking a generator into sized pieces

## Chunk size of zero

chunk2.size() == 0
0 == 0

# Chunking a generator into sized pieces

## Throws on too small generators

chunk(2, value(1)), Catch::GeneratorException
chunk(2, value(1)), Catch::GeneratorException

# one

j < i
-3 < 1

# one

j < i
-2 < 1

# one

j < i
-1 < 1

# two

4u * i > str.size()
4 > 1

# two

4u * i > str.size()
4 > 2

# two

4u * i > str.size()
4 > 3

# one

j < i
-3 < 2

# one

j < i
-2 < 2

# one

j < i
-1 < 2

# two

4u * i > str.size()
8 > 1

# two

4u * i > str.size()
8 > 2

# two

4u * i > str.size()
8 > 3

# one

j < i
-3 < 3

# one

j < i
-2 < 3

# one

j < i
-1 < 3

# two

4u * i > str.size()
12 > 1

# two

4u * i > str.size()
12 > 2

# two

4u * i > str.size()
12 > 3

# Single value

gen.get() == 123
123 == 123
!(gen.next())
!false

# Preset values

gen.get() == 1
1 == 1
gen.next()
true
gen.get() == 3
3 == 3
gen.next()
true
gen.get() == 5
5 == 5
!(gen.next())
!false

# Generator combinator

gen.get() == 1
1 == 1
gen.next()
true
gen.get() == 5
5 == 5
gen.next()
true
gen.get() == 2
2 == 2
gen.next()
true
gen.get() == 4
4 == 4
gen.next()
true
gen.get() == 0
0 == 0
!(gen.next())
!false

# Explicitly typed generator sequence

gen.get().size() == 2
2 == 2
gen.get() == "aa"
"aa" == "aa"
gen.next()
true
gen.get() == "bb"
"bb" == "bb"
gen.next()
true
gen.get() == "cc"
"cc" == "cc"
!(gen.next())
!false

# Filter generator

## Simple filtering

gen.get() == 1
1 == 1
gen.next()
true
gen.get() == 3
3 == 3
!(gen.next())
!false

# Filter generator

## Filter out multiple elements at the start and end

gen.get() == 1
1 == 1
gen.next()
true
gen.get() == 3
3 == 3
!(gen.next())
!false

# Filter generator

## Throws on construction if it can't get initial element

filter([](int) { return false; }, value(1)), Catch::GeneratorException
filter([](int) { return false; }, value(1)), Catch::GeneratorException
filter([](int) { return false; }, values({ 1, 2, 3 })), Catch::GeneratorException
filter([](int) { return false; }, values({ 1, 2, 3 })), Catch::GeneratorException

# Filter generator

## Out-of-line predicates are copied into the generator

gen.get() == 1
1 == 1
gen.next()
true
gen.get() == 3
3 == 3
!(gen.next())
!false

# Take generator

## Take less

gen.get() == 1
1 == 1
gen.next()
true
gen.get() == 2
2 == 2
!(gen.next())
!false

# Take generator

## Take more

gen.get() == 1
1 == 1
!(gen.next())
!false

# Map with explicit return type

gen.get() == 2.0
2.0 == 2.0
gen.next()
true
gen.get() == 4.0
4.0 == 4.0
gen.next()
true
gen.get() == 6.0
6.0 == 6.0
!(gen.next())
!false

# Map with deduced return type

gen.get() == 2.0
2.0 == 2.0
gen.next()
true
gen.get() == 4.0
4.0 == 4.0
gen.next()
true
gen.get() == 6.0
6.0 == 6.0
!(gen.next())
!false

# Repeat

## Singular repeat

gen.get() == 3
3 == 3
!(gen.next())
!false

# Repeat

## Actual repeat

gen.get() == 1
1 == 1
gen.next()
true
gen.get() == 2
2 == 2
gen.next()
true
gen.get() == 3
3 == 3
gen.next()
true
gen.get() == 1
1 == 1
gen.next()
true
gen.get() == 2
2 == 2
gen.next()
true
gen.get() == 3
3 == 3
!(gen.next())
!false

# Range

## Positive auto step

### Integer

gen.get() == -2
-2 == -2
gen.next()
true
gen.get() == -1
-1 == -1
gen.next()
true
gen.get() == 0
0 == 0
gen.next()
true
gen.get() == 1
1 == 1
!(gen.next())
!false

# Range

## Negative auto step

### Integer

gen.get() == 2
2 == 2
gen.next()
true
gen.get() == 1
1 == 1
gen.next()
true
gen.get() == 0
0 == 0
gen.next()
true
gen.get() == -1
-1 == -1
!(gen.next())
!false

# Range

## Positive manual step

### Integer

#### Exact

gen.get() == -7
-7 == -7
gen.next()
true
gen.get() == -4
-4 == -4
gen.next()
true
gen.get() == -1
-1 == -1
gen.next()
true
gen.get() == 2
2 == 2
!(gen.next())
!false

# Range

## Positive manual step

### Integer

#### Slightly over end

gen.get() == -7
-7 == -7
gen.next()
true
gen.get() == -4
-4 == -4
gen.next()
true
gen.get() == -1
-1 == -1
gen.next()
true
gen.get() == 2
2 == 2
!(gen.next())
!false

# Range

## Positive manual step

### Integer

#### Slightly under end

gen.get() == -7
-7 == -7
gen.next()
true
gen.get() == -4
-4 == -4
gen.next()
true
gen.get() == -1
-1 == -1
gen.next()
true
gen.get() == 2
2 == 2
gen.next()
true
gen.get() == 5
5 == 5
!(gen.next())
!false

# Range

## Positive manual step

### Floating Point

#### Exact

Current expected value is -1
gen.get() == Approx(expected)
-1.0 == Approx( -1.0 )
Current expected value is -1
gen.next()
true
Current expected value is -0.9
gen.get() == Approx(expected)
-0.90000000000000002 == Approx( -0.90000000000000002 )
Current expected value is -0.9
gen.next()
true
Current expected value is -0.8
gen.get() == Approx(expected)
-0.80000000000000004 == Approx( -0.80000000000000004 )
Current expected value is -0.8
gen.next()
true
Current expected value is -0.7
gen.get() == Approx(expected)
-0.70000000000000007 == Approx( -0.70000000000000007 )
Current expected value is -0.7
gen.next()
true
Current expected value is -0.6
gen.get() == Approx(expected)
-0.60000000000000009 == Approx( -0.60000000000000009 )
Current expected value is -0.6
gen.next()
true
Current expected value is -0.5
gen.get() == Approx(expected)
-0.50000000000000011 == Approx( -0.50000000000000011 )
Current expected value is -0.5
gen.next()
true
Current expected value is -0.4
gen.get() == Approx(expected)
-0.40000000000000013 == Approx( -0.40000000000000013 )
Current expected value is -0.4
gen.next()
true
Current expected value is -0.3
gen.get() == Approx(expected)
-0.30000000000000016 == Approx( -0.30000000000000016 )
Current expected value is -0.3
gen.next()
true
Current expected value is -0.2
gen.get() == Approx(expected)
-0.20000000000000015 == Approx( -0.20000000000000015 )
Current expected value is -0.2
gen.next()
true
Current expected value is -0.1
gen.get() == Approx(expected)
-0.10000000000000014 == Approx( -0.10000000000000014 )
Current expected value is -0.1
gen.next()
true
Current expected value is -1.38778e-16
gen.get() == Approx(expected)
-0.00000000000000014 == Approx( -0.00000000000000014 )
Current expected value is -1.38778e-16
gen.next()
true
Current expected value is 0.1
gen.get() == Approx(expected)
0.09999999999999987 == Approx( 0.09999999999999987 )
Current expected value is 0.1
gen.next()
true
Current expected value is 0.2
gen.get() == Approx(expected)
0.19999999999999987 == Approx( 0.19999999999999987 )
Current expected value is 0.2
gen.next()
true
Current expected value is 0.3
gen.get() == Approx(expected)
0.29999999999999988 == Approx( 0.29999999999999988 )
Current expected value is 0.3
gen.next()
true
Current expected value is 0.4
gen.get() == Approx(expected)
0.39999999999999991 == Approx( 0.39999999999999991 )
Current expected value is 0.4
gen.next()
true
Current expected value is 0.5
gen.get() == Approx(expected)
0.49999999999999989 == Approx( 0.49999999999999989 )
Current expected value is 0.5
gen.next()
true
Current expected value is 0.6
gen.get() == Approx(expected)
0.59999999999999987 == Approx( 0.59999999999999987 )
Current expected value is 0.6
gen.next()
true
Current expected value is 0.7
gen.get() == Approx(expected)
0.69999999999999984 == Approx( 0.69999999999999984 )
Current expected value is 0.7
gen.next()
true
Current expected value is 0.8
gen.get() == Approx(expected)
0.79999999999999982 == Approx( 0.79999999999999982 )
Current expected value is 0.8
gen.next()
true
Current expected value is 0.9
gen.get() == Approx(expected)
0.8999999999999998 == Approx( 0.8999999999999998 )
Current expected value is 0.9
gen.next()
true
gen.get() == Approx( rangeEnd )
0.99999999999999978 == Approx( 1.0 )
!(gen.next())
!false

# Range

## Positive manual step

### Floating Point

#### Slightly over end

Current expected value is -1
gen.get() == Approx(expected)
-1.0 == Approx( -1.0 )
Current expected value is -1
gen.next()
true
Current expected value is -0.7
gen.get() == Approx(expected)
-0.69999999999999996 == Approx( -0.69999999999999996 )
Current expected value is -0.7
gen.next()
true
Current expected value is -0.4
gen.get() == Approx(expected)
-0.39999999999999997 == Approx( -0.39999999999999997 )
Current expected value is -0.4
gen.next()
true
Current expected value is -0.1
gen.get() == Approx(expected)
-0.09999999999999998 == Approx( -0.09999999999999998 )
Current expected value is -0.1
gen.next()
true
Current expected value is 0.2
gen.get() == Approx(expected)
0.20000000000000001 == Approx( 0.20000000000000001 )
Current expected value is 0.2
gen.next()
true
Current expected value is 0.5
gen.get() == Approx(expected)
0.5 == Approx( 0.5 )
Current expected value is 0.5
gen.next()
true
!(gen.next())
!false

# Range

## Positive manual step

### Floating Point

#### Slightly under end

Current expected value is -1
gen.get() == Approx(expected)
-1.0 == Approx( -1.0 )
Current expected value is -1
gen.next()
true
Current expected value is -0.7
gen.get() == Approx(expected)
-0.69999999999999996 == Approx( -0.69999999999999996 )
Current expected value is -0.7
gen.next()
true
Current expected value is -0.4
gen.get() == Approx(expected)
-0.39999999999999997 == Approx( -0.39999999999999997 )
Current expected value is -0.4
gen.next()
true
Current expected value is -0.1
gen.get() == Approx(expected)
-0.09999999999999998 == Approx( -0.09999999999999998 )
Current expected value is -0.1
gen.next()
true
Current expected value is 0.2
gen.get() == Approx(expected)
0.20000000000000001 == Approx( 0.20000000000000001 )
Current expected value is 0.2
gen.next()
true
Current expected value is 0.5
gen.get() == Approx(expected)
0.5 == Approx( 0.5 )
Current expected value is 0.5
gen.next()
true
!(gen.next())
!false

# Range

## Negative manual step

### Integer

#### Exact

gen.get() == 5
5 == 5
gen.next()
true
gen.get() == 2
2 == 2
gen.next()
true
gen.get() == -1
-1 == -1
gen.next()
true
gen.get() == -4
-4 == -4
!(gen.next())
!false

# Range

## Negative manual step

### Integer

#### Slightly over end

gen.get() == 5
5 == 5
gen.next()
true
gen.get() == 2
2 == 2
gen.next()
true
gen.get() == -1
-1 == -1
gen.next()
true
gen.get() == -4
-4 == -4
!(gen.next())
!false

# Range

## Negative manual step

### Integer

#### Slightly under end

gen.get() == 5
5 == 5
gen.next()
true
gen.get() == 2
2 == 2
gen.next()
true
gen.get() == -1
-1 == -1
gen.next()
true
gen.get() == -4
-4 == -4
gen.next()
true
gen.get() == -7
-7 == -7
!(gen.next())
!false
d >= Approx( 1.22 )
1.22999999999999998 >= Approx( 1.21999999999999997 )
d >= Approx( 1.23 )
1.22999999999999998 >= Approx( 1.22999999999999998 )
!(d >= Approx( 1.24 ))
!(1.22999999999999998 >= Approx( 1.23999999999999999 ))
d >= Approx( 1.24 ).epsilon(0.1)
1.22999999999999998 >= Approx( 1.23999999999999999 )
h1( dummy ) != h2( dummy )
3422778688 (0x<hex digits>) != 130711275 (0x<hex digits>)
h1( dummy ) == h2( dummy )
3422778688 (0x<hex digits>) == 3422778688 (0x<hex digits>)

# Different test name

h( dummy1 ) != h( dummy2 )
2903002874 (0x<hex digits>) != 2668622104 (0x<hex digits>)

# Different classname

h( dummy1 ) != h( dummy2 )
2673152918 (0x<hex digits>) != 3916075712 (0x<hex digits>)

# Different tags

h( dummy1 ) != h( dummy2 )
2074929312 (0x<hex digits>) != 3429949824 (0x<hex digits>)
h( dummy ) == h( dummy )
3422778688 (0x<hex digits>) == 3422778688 (0x<hex digits>)
This info has multiple parts.
This unscoped info has multiple parts.
Show infos!
this is a message

this is a warning

this message should be logged
so should this
a == 1
2 == 1
this message may be logged later
a == 2
2 == 2
this message may be logged later
this message should be logged
a == 1
2 == 1
this message may be logged later
this message should be logged
and this, but later
a == 0
2 == 0
this message may be logged later
this message should be logged
and this, but later
but not this
a == 2
2 == 2
current counter 0
i := 0
i < 10
0 < 10
current counter 1
i := 1
i < 10
1 < 10
current counter 2
i := 2
i < 10
2 < 10
current counter 3
i := 3
i < 10
3 < 10
current counter 4
i := 4
i < 10
4 < 10
current counter 5
i := 5
i < 10
5 < 10
current counter 6
i := 6
i < 10
6 < 10
current counter 7
i := 7
i < 10
7 < 10
current counter 8
i := 8
i < 10
8 < 10
current counter 9
i := 9
i < 10
9 < 10
current counter 10
i := 10
i < 10
10 < 10
Dummy
Dummy
Exception translation was disabled by CATCH_CONFIG_FAST_COMPILE
data.int_seven != 7
7 != 7
data.float_nine_point_one != Approx( 9.1f )
9.100000381f != Approx( 9.10000038146972656 )
data.double_pi != Approx( 3.1415926535 )
3.14159265350000005 != Approx( 3.14159265350000005 )
data.str_hello != "hello"
"hello" != "hello"
data.str_hello.size() != 5
5 != 5
data.int_seven != 6
7 != 6
data.int_seven != 8
7 != 8
data.float_nine_point_one != Approx( 9.11f )
9.100000381f != Approx( 9.10999965667724609 )
data.float_nine_point_one != Approx( 9.0f )
9.100000381f != Approx( 9.0 )
data.float_nine_point_one != Approx( 1 )
9.100000381f != Approx( 1.0 )
data.float_nine_point_one != Approx( 0 )
9.100000381f != Approx( 0.0 )
data.double_pi != Approx( 3.1415 )
3.14159265350000005 != Approx( 3.14150000000000018 )
data.str_hello != "goodbye"
"hello" != "goodbye"
data.str_hello != "hell"
"hello" != "hell"
data.str_hello != "hello1"
"hello" != "hello1"
data.str_hello.size() != 6
5 != 6

# Newly constructed JsonWriter does nothing

stream.str() == ""
"" == ""

# Calling writeObject will create an empty pair of braces

stream.str() == "{\n}"
"{ }" == "{ }"

# Calling writeObject with key will create an object to write the value

stream.str(), ContainsSubstring( "\"int\": 1," ) && ContainsSubstring( "\"double\": 1.5," ) && ContainsSubstring( "\"true\": true," ) && ContainsSubstring( "\"false\": false," ) && ContainsSubstring( "\"string\": \"this is a string\"," ) && ContainsSubstring( "\"array\": [\n 1,\n 2\n ]\n}" )
"{ "int": 1, "double": 1.5, "true": true, "false": false, "string": "this is a string", "array": [ 1, 2 ] }" ( contains: ""int": 1," and contains: ""double": 1.5," and contains: ""true": true," and contains: ""false": false," and contains: ""string": "this is a string"," and contains: ""array": [ 1, 2 ] }" )

# nesting objects

stream.str(), ContainsSubstring( "\"empty_object\": {\n }," ) && ContainsSubstring( "\"fully_object\": {\n \"key\": 1\n }" )
"{ "empty_object": { }, "fully_object": { "key": 1 } }" ( contains: ""empty_object": { }," and contains: ""fully_object": { "key": 1 }" )

# Calling writeArray will create an empty pair of braces

stream.str() == "[\n]"
"[ ]" == "[ ]"

# Calling writeArray creates array to write the values to

stream.str() == "[\n 1,\n 1.5,\n true,\n false,\n \"this is a string\",\n {\n \"object\": 42\n },\n [\n \"array\",\n 42.5\n ]\n]"
"[ 1, 1.5, true, false, "this is a string", { "object": 42 }, [ "array", 42.5 ] ]" == "[ 1, 1.5, true, false, "this is a string", { "object": 42 }, [ "array", 42.5 ] ]"

# Moved from JsonObjectWriter shall not insert superfluous brace

stream.str() == "{\n}"
"{ }" == "{ }"

# Moved from JsonArrayWriter shall not insert superfluous bracket

stream.str() == "[\n]"
"[ ]" == "[ ]"

# Custom class shall be quoted

stream.str() == "\"custom\""
""custom"" == ""custom""

# Quote in a string is escaped

sstream.str() == "\"\\\"\""
""\""" == ""\"""

# Backslash in a string is escaped

sstream.str() == "\"\\\\\""
""\\"" == ""\\""

# Forward slash in a string is **not** escaped

sstream.str() == "\"/\""
""/"" == ""/""

# Backspace in a string is escaped

sstream.str() == "\"\\b\""
""\b"" == ""\b""

# Formfeed in a string is escaped

sstream.str() == "\"\\f\""
""\f"" == ""\f""

# linefeed in a string is escaped

sstream.str() == "\"\\n\""
""\n"" == ""\n""

# carriage return in a string is escaped

sstream.str() == "\"\\r\""
""\r"" == ""\r""

# tab in a string is escaped

sstream.str() == "\"\\t\""
""\t"" == ""\t""

# combination of characters is escaped

sstream.str() == "\"\\\\/\\t\\r\\n\""
""\\/\t\r\n"" == ""\\/\t\r\n""
[]() { return true; }()
true
d <= Approx( 1.24 )
1.22999999999999998 <= Approx( 1.23999999999999999 )
d <= Approx( 1.23 )
1.22999999999999998 <= Approx( 1.22999999999999998 )
!(d <= Approx( 1.22 ))
!(1.22999999999999998 <= Approx( 1.21999999999999997 ))
d <= Approx( 1.22 ).epsilon(0.1)
1.22999999999999998 <= Approx( 1.21999999999999997 )
testStringForMatching(), ContainsSubstring( "string" ) && ContainsSubstring( "abc" ) && ContainsSubstring( "substring" ) && ContainsSubstring( "contains" )
"this string contains 'abc' as a substring" ( contains: "string" and contains: "abc" and contains: "substring" and contains: "contains" )
testStringForMatching(), ContainsSubstring( "string" ) || ContainsSubstring( "different" ) || ContainsSubstring( "random" )
"this string contains 'abc' as a substring" ( contains: "string" or contains: "different" or contains: "random" )
testStringForMatching2(), ContainsSubstring( "string" ) || ContainsSubstring( "different" ) || ContainsSubstring( "random" )
"some completely different text that contains one common word" ( contains: "string" or contains: "different" or contains: "random" )
testStringForMatching(), ( ContainsSubstring( "string" ) || ContainsSubstring( "different" ) ) && ContainsSubstring( "substring" )
"this string contains 'abc' as a substring" ( ( contains: "string" or contains: "different" ) and contains: "substring" )
testStringForMatching(), ( ContainsSubstring( "string" ) || ContainsSubstring( "different" ) ) && ContainsSubstring( "random" )
"this string contains 'abc' as a substring" ( ( contains: "string" or contains: "different" ) and contains: "random" )
testStringForMatching(), !ContainsSubstring( "different" )
"this string contains 'abc' as a substring" not contains: "different"
testStringForMatching(), !ContainsSubstring( "substring" )
"this string contains 'abc' as a substring" not contains: "substring"

# A

## 1

# A

## 2

# A

# B

## 1

# B

## 2

# B

thisThrows(), "expected exception"
"expected exception" equals: "expected exception"
thisThrows(), "should fail"
"expected exception" equals: "should fail"
records == expected
{ "Hello", "world", "Goodbye", "world" } == { "Hello", "world", "Goodbye", "world" }
multiReporter.getPreferences().shouldRedirectStdOut == false
false == false
multiReporter.getPreferences().shouldReportAllAssertions == false
false == false

# Adding listeners

multiReporter.getPreferences().shouldRedirectStdOut == true
true == true
multiReporter.getPreferences().shouldReportAllAssertions == false
false == false
multiReporter.getPreferences().shouldRedirectStdOut == true
true == true
multiReporter.getPreferences().shouldReportAllAssertions == true
true == true
multiReporter.getPreferences().shouldRedirectStdOut == true
true == true
multiReporter.getPreferences().shouldReportAllAssertions == true
true == true
multiReporter.getPreferences().shouldRedirectStdOut == false
false == false
multiReporter.getPreferences().shouldReportAllAssertions == false
false == false

# Adding reporters

multiReporter.getPreferences().shouldRedirectStdOut == true
true == true
multiReporter.getPreferences().shouldReportAllAssertions == false
false == false
multiReporter.getPreferences().shouldRedirectStdOut == true
true == true
multiReporter.getPreferences().shouldReportAllAssertions == true
true == true
multiReporter.getPreferences().shouldRedirectStdOut == true
true == true
multiReporter.getPreferences().shouldReportAllAssertions == true
true == true
values > -6
3 > -6
values > -6
4 > -6
values > -6
5 > -6
values > -6
6 > -6
values > -6
-5 > -6
values > -6
-4 > -6
values > -6
90 > -6
values > -6
91 > -6
values > -6
92 > -6
values > -6
93 > -6
values > -6
94 > -6
values > -6
95 > -6
values > -6
96 > -6
values > -6
97 > -6
values > -6
98 > -6
values > -6
99 > -6

This one ran

custom exception
True
{?}
!False
true
!(False)
!{?}
data.int_seven > 7
7 > 7
data.int_seven < 7
7 < 7
data.int_seven > 8
7 > 8
data.int_seven < 6
7 < 6
data.int_seven < 0
7 < 0
data.int_seven < -1
7 < -1
data.int_seven >= 8
7 >= 8
data.int_seven <= 6
7 <= 6
data.float_nine_point_one < 9
9.100000381f < 9
data.float_nine_point_one > 10
9.100000381f > 10
data.float_nine_point_one > 9.2
9.100000381f > 9.19999999999999929
data.str_hello > "hello"
"hello" > "hello"
data.str_hello < "hello"
"hello" < "hello"
data.str_hello > "hellp"
"hello" > "hellp"
data.str_hello > "z"
"hello" > "z"
data.str_hello < "hellm"
"hello" < "hellm"
data.str_hello < "a"
"hello" < "a"
data.str_hello >= "z"
"hello" >= "z"
data.str_hello <= "a"
"hello" <= "a"
data.int_seven < 8
7 < 8
data.int_seven > 6
7 > 6
data.int_seven > 0
7 > 0
data.int_seven > -1
7 > -1
data.int_seven >= 7
7 >= 7
data.int_seven >= 6
7 >= 6
data.int_seven <= 7
7 <= 7
data.int_seven <= 8
7 <= 8
data.float_nine_point_one > 9
9.100000381f > 9
data.float_nine_point_one < 10
9.100000381f < 10
data.float_nine_point_one < 9.2
9.100000381f < 9.19999999999999929
data.str_hello <= "hello"
"hello" <= "hello"
data.str_hello >= "hello"
"hello" >= "hello"
data.str_hello < "hellp"
"hello" < "hellp"
data.str_hello < "zebra"
"hello" < "zebra"
data.str_hello > "hellm"
"hello" > "hellm"
data.str_hello > "a"
"hello" > "a"

# Default seeded

rng() == 0x<hex digits>
4242248763 (0x<hex digits>) == 4242248763 (0x<hex digits>)
rng() == 0x<hex digits>
1867888929 (0x<hex digits>) == 1867888929 (0x<hex digits>)
rng() == 0x<hex digits>
1276619030 (0x<hex digits>) == 1276619030 (0x<hex digits>)
rng() == 0x<hex digits>
1911218783 (0x<hex digits>) == 1911218783 (0x<hex digits>)
rng() == 0x<hex digits>
1827115164 (0x<hex digits>) == 1827115164 (0x<hex digits>)

# Specific seed

rng() == 0x<hex digits>
1472234645 (0x<hex digits>) == 1472234645 (0x<hex digits>)
rng() == 0x<hex digits>
868832940 (0x<hex digits>) == 868832940 (0x<hex digits>)
rng() == 0x<hex digits>
570883446 (0x<hex digits>) == 570883446 (0x<hex digits>)
rng() == 0x<hex digits>
889299803 (0x<hex digits>) == 889299803 (0x<hex digits>)
rng() == 0x<hex digits>
4261393167 (0x<hex digits>) == 4261393167 (0x<hex digits>)
rng() == 0x<hex digits>
1472234645 (0x<hex digits>) == 1472234645 (0x<hex digits>)
rng() == 0x<hex digits>
868832940 (0x<hex digits>) == 868832940 (0x<hex digits>)
rng() == 0x<hex digits>
570883446 (0x<hex digits>) == 570883446 (0x<hex digits>)
rng() == 0x<hex digits>
889299803 (0x<hex digits>) == 889299803 (0x<hex digits>)
rng() == 0x<hex digits>
4261393167 (0x<hex digits>) == 4261393167 (0x<hex digits>)

# one

Message from section one

# two

Message from section two
( EvilMatcher(), EvilMatcher() ), EvilCommaOperatorUsed
( EvilMatcher(), EvilMatcher() ), EvilCommaOperatorUsed
&EvilMatcher(), EvilAddressOfOperatorUsed
&EvilMatcher(), EvilAddressOfOperatorUsed
EvilMatcher() || ( EvilMatcher() && !EvilMatcher() )
EvilMatcher() || ( EvilMatcher() && !EvilMatcher() )
( EvilMatcher() && EvilMatcher() ) || !EvilMatcher()
( EvilMatcher() && EvilMatcher() ) || !EvilMatcher()

# proper inputs

parseUInt( "0" ) == Optional<unsigned int>{ 0 }
{?} == {?}
parseUInt( "100" ) == Optional<unsigned int>{ 100 }
{?} == {?}
parseUInt( "4294967295" ) == Optional<unsigned int>{ 4294967295 }
{?} == {?}
parseUInt( "0x<hex digits>", 16 ) == Optional<unsigned int>{ 255 }
{?} == {?}

# Bad inputs

!(parseUInt( "" ))
!{?}
!(parseUInt( "!!KJHF*#" ))
!{?}
!(parseUInt( "-1" ))
!{?}
!(parseUInt( "4294967296" ))
!{?}
!(parseUInt( "42949672964294967296429496729642949672964294967296" ))
!{?}
!(parseUInt( "2 4" ))
!{?}
!(parseUInt( "0x<hex digits>", 10 ))
!{?}
spec.hasFilters()
true
spec.getInvalidSpecs().empty()
true
spec.matches( testCase )
true

# shard-count

cli.parse({ "test", "--shard-count=8" })
{?}
config.shardCount == 8
8 == 8

# Negative shard count reports error

!(result)
!{?}
result.errorMessage(), ContainsSubstring( "Could not parse '-1' as shard count" )
"Could not parse '-1' as shard count" contains: "Could not parse '-1' as shard count"

# Zero shard count reports error

!(result)
!{?}
result.errorMessage(), ContainsSubstring( "Shard count must be positive" )
"Shard count must be positive" contains: "Shard count must be positive"

# shard-index

cli.parse({ "test", "--shard-index=2" })
{?}
config.shardIndex == 2
2 == 2

# Negative shard index reports error

!(result)
!{?}
result.errorMessage(), ContainsSubstring( "Could not parse '-12' as shard index" )
"Could not parse '-12' as shard index" contains: "Could not parse '-12' as shard index"

# Shard index 0 is accepted

cli.parse({ "test", "--shard-index=0" })
{?}
config.shardIndex == 0
0 == 0
tagString := "[tag with spaces]"
spec.hasFilters()
true
tagString := "[tag with spaces]"
spec.getInvalidSpecs().empty()
true
tagString := "[tag with spaces]"
spec.matches( testCase )
true
tagString := "[I said "good day" sir!]"
spec.hasFilters()
true
tagString := "[I said "good day" sir!]"
spec.getInvalidSpecs().empty()
true
tagString := "[I said "good day" sir!]"
spec.matches( testCase )
true

# NoAssertions

cli.parse( { "test", "-w", "NoAssertions" } )
{?}
config.warnings == WarnAbout::NoAssertions
1 == 1

# NoTests is no longer supported

!(cli.parse( { "test", "-w", "NoTests" } ))
!{?}

# Combining multiple warnings

cli.parse( { "test", "--warn", "NoAssertions", "--warn", "UnmatchedTestSpec" } )
{?}
config.warnings == ( WarnAbout::NoAssertions | WarnAbout::UnmatchedTestSpec )
3 == 3
p == 0
0 == 0
p == pNULL
0 == 0
p != 0
0x<hex digits> != 0
cp != 0
0x<hex digits> != 0
cpc != 0
0x<hex digits> != 0
returnsNull() == 0
{null string} == 0
returnsConstNull() == 0
{null string} == 0
0 != p
0 != 0x<hex digits>

# Floats

str1.size() == 3 + 5
8 == 8
str2.size() == 3 + 10
13 == 13

# Double

str1.size() == 2 + 5
7 == 7
str2.size() == 2 + 15
17 == 17
"foo", Predicate<const char*>( []( const char* const& ) { return true; } )
"foo" matches undescribed predicate

# empty args don't cause a crash

result
{?}
config.processName == ""
"" == ""

# default - no arguments

result
{?}
config.processName == "test"
"test" == "test"
config.shouldDebugBreak == false
false == false
config.abortAfter == -1
-1 == -1
config.noThrow == false
false == false
config.reporterSpecifications.empty()
true
!(cfg.hasTestFilters())
!false
cfg.getReporterSpecs().size() == 1
1 == 1
cfg.getReporterSpecs()[0] == Catch::ReporterSpec{ expectedReporter, {}, {}, {} }
{?} == {?}
cfg.getProcessedReporterSpecs().size() == 1
1 == 1
cfg.getProcessedReporterSpecs()[0] == Catch::ProcessedReporterSpec{ expectedReporter, std::string{}, Catch::ColourMode::PlatformDefault, {} }
{?} == {?}

# test lists

## Specify one test case using

result
{?}
cfg.hasTestFilters()
true
cfg.testSpec().matches(*fakeTestCase("notIncluded")) == false
false == false
cfg.testSpec().matches(*fakeTestCase("test1"))
true

# test lists

## Specify one test case exclusion using exclude:

result
{?}
cfg.hasTestFilters()
true
cfg.testSpec().matches(*fakeTestCase("test1")) == false
false == false
cfg.testSpec().matches(*fakeTestCase("alwaysIncluded"))
true

# test lists

## Specify one test case exclusion using ~

result
{?}
cfg.hasTestFilters()
true
cfg.testSpec().matches(*fakeTestCase("test1")) == false
false == false
cfg.testSpec().matches(*fakeTestCase("alwaysIncluded"))
true

# reporter

## -r/console

result.errorMessage() := ""
result
{?}
result.errorMessage() := ""
config.reporterSpecifications == vec_Specs{ { "console", {}, {}, {} } }
{ {?} } == { {?} }

# reporter

## -r/xml

result.errorMessage() := ""
result
{?}
result.errorMessage() := ""
config.reporterSpecifications == vec_Specs{ { "xml", {}, {}, {} } }
{ {?} } == { {?} }

# reporter

## --reporter/junit

result.errorMessage() := ""
result
{?}
result.errorMessage() := ""
config.reporterSpecifications == vec_Specs{ { "junit", {}, {}, {} } }
{ {?} } == { {?} }

# reporter

## must match one of the available ones

!result
true
result.errorMessage(), ContainsSubstring("Unrecognized reporter")
"Unrecognized reporter, 'unsupported'. Check available with --list-reporters" contains: "Unrecognized reporter"

# reporter

## With output file

result.errorMessage() := ""
result
{?}
result.errorMessage() := ""
config.reporterSpecifications == vec_Specs{ { "console", "out.txt"s, {}, {} } }
{ {?} } == { {?} }

# reporter

## With Windows-like absolute path as output file

result.errorMessage() := ""
result
{?}
result.errorMessage() := ""
config.reporterSpecifications == vec_Specs{ { "console", "C:\\Temp\\out.txt"s, {}, {} } }
{ {?} } == { {?} }

# reporter

## Multiple reporters

### All with output files

cli.parse({ "test", "-r", "xml::out=output.xml", "-r", "junit::out=output-junit.xml" })
{?}
config.reporterSpecifications == vec_Specs{ { "xml", "output.xml"s, {}, {} }, { "junit", "output-junit.xml"s, {}, {} } }
{ {?}, {?} } == { {?}, {?} }

# reporter

## Multiple reporters

### Mixed output files and default output

cli.parse({ "test", "-r", "xml::out=output.xml", "-r", "console" })
{?}
config.reporterSpecifications == vec_Specs{ { "xml", "output.xml"s, {}, {} }, { "console", {}, {}, {} } }
{ {?}, {?} } == { {?}, {?} }

# reporter

## Multiple reporters

### cannot have multiple reporters with default output

!result
true
result.errorMessage(), ContainsSubstring("Only one reporter may have unspecified output file.")
"Only one reporter may have unspecified output file." contains: "Only one reporter may have unspecified output file."

# debugger

## -b

cli.parse({"test", "-b"})
{?}
config.shouldDebugBreak == true
true == true

# debugger

## --break

cli.parse({"test", "--break"})
{?}
config.shouldDebugBreak
true

# abort

## -a aborts after first failure

cli.parse({"test", "-a"})
{?}
config.abortAfter == 1
1 == 1

# abort

## -x 2 aborts after two failures

cli.parse({"test", "-x", "2"})
{?}
config.abortAfter == 2
2 == 2

# abort

## -x must be numeric

!result
true
result.errorMessage(), ContainsSubstring("convert") && ContainsSubstring("oops")
"Unable to convert 'oops' to destination type" ( contains: "convert" and contains: "oops" )

# abort

## wait-for-keypress

### Accepted options

cli.parse({"test", "--wait-for-keypress", std::get<0>(input)})
{?}
config.waitForKeypress == std::get<1>(input)
0 == 0

# abort

## wait-for-keypress

### Accepted options

cli.parse({"test", "--wait-for-keypress", std::get<0>(input)})
{?}
config.waitForKeypress == std::get<1>(input)
1 == 1

# abort

## wait-for-keypress

### Accepted options

cli.parse({"test", "--wait-for-keypress", std::get<0>(input)})
{?}
config.waitForKeypress == std::get<1>(input)
2 == 2

# abort

## wait-for-keypress

### Accepted options

cli.parse({"test", "--wait-for-keypress", std::get<0>(input)})
{?}
config.waitForKeypress == std::get<1>(input)
3 == 3

# abort

## wait-for-keypress

### invalid options are reported

!result
true
result.errorMessage(), ContainsSubstring("never") && ContainsSubstring("both")
"keypress argument must be one of: never, start, exit or both. 'sometimes' not recognised" ( contains: "never" and contains: "both" )

# nothrow

## -e

cli.parse({"test", "-e"})
{?}
config.noThrow
true

# nothrow

## --nothrow

cli.parse({"test", "--nothrow"})
{?}
config.noThrow
true

# output filename

## -o filename

cli.parse({"test", "-o", "filename.ext"})
{?}
config.defaultOutputFilename == "filename.ext"
"filename.ext" == "filename.ext"

# output filename

## --out

cli.parse({"test", "--out", "filename.ext"})
{?}
config.defaultOutputFilename == "filename.ext"
"filename.ext" == "filename.ext"

# combinations

## Single character flags can be combined

cli.parse({"test", "-abe"})
{?}
config.abortAfter == 1
1 == 1
config.shouldDebugBreak
true
config.noThrow == true
true == true

# use-colour

## without option

cli.parse({"test"})
{?}
config.defaultColourMode == ColourMode::PlatformDefault
0 == 0

# use-colour

## auto

cli.parse( { "test", "--colour-mode", "default" } )
{?}
config.defaultColourMode == ColourMode::PlatformDefault
0 == 0

# use-colour

## yes

cli.parse({"test", "--colour-mode", "ansi"})
{?}
config.defaultColourMode == ColourMode::ANSI
1 == 1

# use-colour

## no

cli.parse({"test", "--colour-mode", "none"})
{?}
config.defaultColourMode == ColourMode::None
3 == 3

# use-colour

## error

!result
true
result.errorMessage(), ContainsSubstring( "colour mode must be one of" )
"colour mode must be one of: default, ansi, win32, or none. 'wrong' is not recognised" contains: "colour mode must be one of"

# Benchmark options

## samples

cli.parse({ "test", "--benchmark-samples=200" })
{?}
config.benchmarkSamples == 200
200 == 200

# Benchmark options

## resamples

cli.parse({ "test", "--benchmark-resamples=20000" })
{?}
config.benchmarkResamples == 20000
20000 (0x<hex digits>) == 20000 (0x<hex digits>)

# Benchmark options

## confidence-interval

cli.parse({ "test", "--benchmark-confidence-interval=0.99" })
{?}
config.benchmarkConfidenceInterval == Catch::Approx(0.99)
0.98999999999999999 == Approx( 0.98999999999999999 )

# Benchmark options

## no-analysis

cli.parse({ "test", "--benchmark-no-analysis" })
{?}
config.benchmarkNoAnalysis
true

# Benchmark options

## warmup-time

cli.parse({ "test", "--benchmark-warmup-time=10" })
{?}
config.benchmarkWarmupTime == 10
10 == 10
std::tuple_size<TestType>::value >= 1
3 >= 1
std::tuple_size<TestType>::value >= 1
2 >= 1
std::tuple_size<TestType>::value >= 1
1 >= 1
Catch::generateRandomSeed(method)
Catch::generateRandomSeed(method)
Catch::generateRandomSeed(method)
Catch::generateRandomSeed(method)
Catch::generateRandomSeed(method)
Catch::generateRandomSeed(method)
Catch::generateRandomSeed(static_cast<Catch::GenerateFrom>(77))
Catch::generateRandomSeed(static_cast<Catch::GenerateFrom>(77))
Catch::Detail::stringify(UsesSentinel{}) == "{ }"
"{ }" == "{ }"
truthy(false)
Hey, its truthy!
testStringForMatching(), Matches( "this STRING contains 'abc' as a substring" )
"this string contains 'abc' as a substring" matches "this STRING contains 'abc' as a substring" case sensitively
testStringForMatching(), Matches( "contains 'abc' as a substring" )
"this string contains 'abc' as a substring" matches "contains 'abc' as a substring" case sensitively
testStringForMatching(), Matches( "this string contains 'abc' as a" )
"this string contains 'abc' as a substring" matches "this string contains 'abc' as a" case sensitively
registry.registerReporter( "with::doublecolons", Catch::Detail::make_unique<TestReporterFactory>() ), "'::' is not allowed in reporter name: 'with::doublecolons'"
"'::' is not allowed in reporter name: 'with::doublecolons'" equals: "'::' is not allowed in reporter name: 'with::doublecolons'"
actual, !UnorderedEquals( expected )
{ 'a', 'b' } not UnorderedEquals: { 'c', 'b' }
!(factories.empty())
!false

# Automake reporter lists tags

Tested reporter: Automake
listingString, ContainsSubstring("fakeTag"s)
"All available tags: 1 [fakeTag] 1 tag

" contains: "fakeTag"
!(factories.empty())
!false

# Automake reporter lists reporters

Tested reporter: Automake
listingString, ContainsSubstring("fake reporter"s)
"Available reporters: fake reporter: fake description

" contains: "fake reporter"
!(factories.empty())
!false

# Automake reporter lists tests

Tested reporter: Automake
listingString, ContainsSubstring( "fake test name"s ) && ContainsSubstring( "fakeTestTag"s )
"All available test cases: fake test name [fakeTestTag] 1 test case

" ( contains: "fake test name" and contains: "fakeTestTag" )
!(factories.empty())
!false

# compact reporter lists tags

Tested reporter: compact
listingString, ContainsSubstring("fakeTag"s)
"All available tags: 1 [fakeTag] 1 tag

" contains: "fakeTag"
!(factories.empty())
!false

# compact reporter lists reporters

Tested reporter: compact
listingString, ContainsSubstring("fake reporter"s)
"Available reporters: fake reporter: fake description

" contains: "fake reporter"
!(factories.empty())
!false

# compact reporter lists tests

Tested reporter: compact
listingString, ContainsSubstring( "fake test name"s ) && ContainsSubstring( "fakeTestTag"s )
"All available test cases: fake test name [fakeTestTag] 1 test case

" ( contains: "fake test name" and contains: "fakeTestTag" )
!(factories.empty())
!false

# console reporter lists tags

Tested reporter: console
listingString, ContainsSubstring("fakeTag"s)
"All available tags: 1 [fakeTag] 1 tag

" contains: "fakeTag"
!(factories.empty())
!false

# console reporter lists reporters

Tested reporter: console
listingString, ContainsSubstring("fake reporter"s)
"Available reporters: fake reporter: fake description

" contains: "fake reporter"
!(factories.empty())
!false

# console reporter lists tests

Tested reporter: console
listingString, ContainsSubstring( "fake test name"s ) && ContainsSubstring( "fakeTestTag"s )
"All available test cases: fake test name [fakeTestTag] 1 test case

" ( contains: "fake test name" and contains: "fakeTestTag" )
!(factories.empty())
!false

# JSON reporter lists tags

Tested reporter: JSON
listingString, ContainsSubstring("fakeTag"s)
"{ "version": 1, "metadata": { "name": "", "rng-seed": 1234, "catch2-version": "<version>" }, "listings": { "tags": [ { "aliases": [ "fakeTag" ], "count": 1 } ]" contains: "fakeTag"
!(factories.empty())
!false

# JSON reporter lists reporters

Tested reporter: JSON
listingString, ContainsSubstring("fake reporter"s)
"{ "version": 1, "metadata": { "name": "", "rng-seed": 1234, "catch2-version": "<version>" }, "listings": { "reporters": [ { "name": "fake reporter", "description": "fake description" } ]" contains: "fake reporter"
!(factories.empty())
!false

# JSON reporter lists tests

Tested reporter: JSON
listingString, ContainsSubstring( "fake test name"s ) && ContainsSubstring( "fakeTestTag"s )
"{ "version": 1, "metadata": { "name": "", "rng-seed": 1234, "catch2-version": "<version>" }, "listings": { "tests": [ { "name": "fake test name", "class-name": "", "tags": [ "fakeTestTag" ], "source-location": { "filename": "fake-file.cpp", "line": 123456789 } } ]" ( contains: "fake test name" and contains: "fakeTestTag" )
!(factories.empty())
!false

# JUnit reporter lists tags

Tested reporter: JUnit
listingString, ContainsSubstring("fakeTag"s)
"<?xml version="1.0" encoding="UTF-8"?> All available tags: 1 [fakeTag] 1 tag

" contains: "fakeTag"
!(factories.empty())
!false

# JUnit reporter lists reporters

Tested reporter: JUnit
listingString, ContainsSubstring("fake reporter"s)
"<?xml version="1.0" encoding="UTF-8"?> Available reporters: fake reporter: fake description

" contains: "fake reporter"
!(factories.empty())
!false

# JUnit reporter lists tests

Tested reporter: JUnit
listingString, ContainsSubstring( "fake test name"s ) && ContainsSubstring( "fakeTestTag"s )
"<?xml version="1.0" encoding="UTF-8"?> All available test cases: fake test name [fakeTestTag] 1 test case

" ( contains: "fake test name" and contains: "fakeTestTag" )
!(factories.empty())
!false

# SonarQube reporter lists tags

Tested reporter: SonarQube
listingString, ContainsSubstring("fakeTag"s)
"<?xml version="1.0" encoding="UTF-8"?> All available tags: 1 [fakeTag] 1 tag

" contains: "fakeTag"
!(factories.empty())
!false

# SonarQube reporter lists reporters

Tested reporter: SonarQube
listingString, ContainsSubstring("fake reporter"s)
"<?xml version="1.0" encoding="UTF-8"?> Available reporters: fake reporter: fake description

" contains: "fake reporter"
!(factories.empty())
!false

# SonarQube reporter lists tests

Tested reporter: SonarQube
listingString, ContainsSubstring( "fake test name"s ) && ContainsSubstring( "fakeTestTag"s )
"<?xml version="1.0" encoding="UTF-8"?> All available test cases: fake test name [fakeTestTag] 1 test case

" ( contains: "fake test name" and contains: "fakeTestTag" )
!(factories.empty())
!false

# TAP reporter lists tags

Tested reporter: TAP
listingString, ContainsSubstring("fakeTag"s)
"All available tags: 1 [fakeTag] 1 tag

" contains: "fakeTag"
!(factories.empty())
!false

# TAP reporter lists reporters

Tested reporter: TAP
listingString, ContainsSubstring("fake reporter"s)
"Available reporters: fake reporter: fake description

" contains: "fake reporter"
!(factories.empty())
!false

# TAP reporter lists tests

Tested reporter: TAP
listingString, ContainsSubstring( "fake test name"s ) && ContainsSubstring( "fakeTestTag"s )
"All available test cases: fake test name [fakeTestTag] 1 test case

" ( contains: "fake test name" and contains: "fakeTestTag" )
!(factories.empty())
!false

# TeamCity reporter lists tags

Tested reporter: TeamCity
listingString, ContainsSubstring("fakeTag"s)
"All available tags: 1 [fakeTag] 1 tag

" contains: "fakeTag"
!(factories.empty())
!false

# TeamCity reporter lists reporters

Tested reporter: TeamCity
listingString, ContainsSubstring("fake reporter"s)
"Available reporters: fake reporter: fake description

" contains: "fake reporter"
!(factories.empty())
!false

# TeamCity reporter lists tests

Tested reporter: TeamCity
listingString, ContainsSubstring( "fake test name"s ) && ContainsSubstring( "fakeTestTag"s )
"All available test cases: fake test name [fakeTestTag] 1 test case

" ( contains: "fake test name" and contains: "fakeTestTag" )
!(factories.empty())
!false

# XML reporter lists tags

Tested reporter: XML
listingString, ContainsSubstring("fakeTag"s)
"<?xml version="1.0" encoding="UTF-8"?> <TagsFromMatchingTests> <Tag> <Count>1</Count> <Aliases> <Alias>fakeTag</Alias> </Aliases> </Tag> </TagsFromMatchingTests>" contains: "fakeTag"
!(factories.empty())
!false

# XML reporter lists reporters

Tested reporter: XML
listingString, ContainsSubstring("fake reporter"s)
"<?xml version="1.0" encoding="UTF-8"?> <AvailableReporters> <Reporter> <Name>fake reporter</Name> <Description>fake description</Description> </Reporter> </AvailableReporters>" contains: "fake reporter"
!(factories.empty())
!false

# XML reporter lists tests

Tested reporter: XML
listingString, ContainsSubstring( "fake test name"s ) && ContainsSubstring( "fakeTestTag"s )
"<?xml version="1.0" encoding="UTF-8"?> <MatchingTests> <TestCase> <Name>fake test name</Name> <ClassName/> <Tags>[fakeTestTag]</Tags> <SourceInfo> <File>fake-file.cpp</File> <Line>123456789</Line> </SourceInfo> </TestCase> </MatchingTests>" ( contains: "fake test name" and contains: "fakeTestTag" )

# Given: No operations precede me

before == 0
0 == 0

## When: We get the count

### Then: Subsequently values are higher

after > before
1 > 0

# Given: This stuff exists

## And given: And some assumption

### When: I do this

#### Then: it should do this

itDoesThis()
true

##### And: do that

itDoesThat()
true

# Given: A section name that is so long that it cannot fit in a single console width

## When: The test headers are printed as part of the normal running of the scenario

### Then: The, deliberately very long and overly verbose (you see what I did there?) section names must wrap, along with an indent

# Given: an empty vector

v.size() == 0
0 == 0

## When: it is made larger

### Then: the size and capacity go up

v.size() == 10
10 == 10
v.capacity() >= 10
10 >= 10

#### And when: it is made smaller again

##### Then: the size goes down but the capacity stays the same

v.size() == 5
5 == 5
v.capacity() >= 10
10 >= 10

# Given: an empty vector

v.size() == 0
0 == 0

## When: we reserve more space

### Then: The capacity is increased but the size remains the same

v.capacity() >= 10
10 >= 10
v.size() == 0
0 == 0
This will be reported multiple times
false
false
This will be reported multiple times
false
false
Should be in scope at the end
false
false

# Dummy section

Should survive a section end
true
true
Should survive a section end
false
false
A string sent directly to stdout
A string sent directly to stderr A string sent to stderr via clog
d == Approx( 1.23 )
1.22999999999999998 == Approx( 1.22999999999999998 )
d != Approx( 1.22 )
1.22999999999999998 != Approx( 1.21999999999999997 )
d != Approx( 1.24 )
1.22999999999999998 != Approx( 1.23999999999999999 )
d == 1.23_a
1.22999999999999998 == Approx( 1.22999999999999998 )
d != 1.22_a
1.22999999999999998 != Approx( 1.21999999999999997 )
Approx( d ) == 1.23
Approx( 1.22999999999999998 ) == 1.22999999999999998
Approx( d ) != 1.22
Approx( 1.22999999999999998 ) != 1.21999999999999997
Approx( d ) != 1.24
Approx( 1.22999999999999998 ) != 1.23999999999999999

# one

# two

Message from section one Message from section two
testStringForMatching(), StartsWith( "This String" )
"this string contains 'abc' as a substring" starts with: "This String"
testStringForMatching(), StartsWith( "string", Catch::CaseSensitive::No )
"this string contains 'abc' as a substring" starts with: "string" (case insensitive)

# Single item

Catch::Detail::stringify(singular) == "{ 1 }"
"{ 1 }" == "{ 1 }"

# Multiple

Catch::Detail::stringify(arr) == "{ 3, 2, 1 }"
"{ 3, 2, 1 }" == "{ 3, 2, 1 }"

# Non-trivial inner items

Catch::Detail::stringify(arr) == R"({ { "1:1", "1:2", "1:3" }, { "2:1", "2:2" } })"
"{ { "1:1", "1:2", "1:3" }, { "2:1", "2:2" } }" == "{ { "1:1", "1:2", "1:3" }, { "2:1", "2:2" } }"
testStringForMatching(), ContainsSubstring( "string" )
"this string contains 'abc' as a substring" contains: "string"
testStringForMatching(), ContainsSubstring( "string", Catch::CaseSensitive::No )
"this string contains 'abc' as a substring" contains: "string" (case insensitive)
testStringForMatching(), ContainsSubstring( "abc" )
"this string contains 'abc' as a substring" contains: "abc"
testStringForMatching(), ContainsSubstring( "aBC", Catch::CaseSensitive::No )
"this string contains 'abc' as a substring" contains: "abc" (case insensitive)
testStringForMatching(), StartsWith( "this" )
"this string contains 'abc' as a substring" starts with: "this"
testStringForMatching(), StartsWith( "THIS", Catch::CaseSensitive::No )
"this string contains 'abc' as a substring" starts with: "this" (case insensitive)
testStringForMatching(), EndsWith( "substring" )
"this string contains 'abc' as a substring" ends with: "substring"
testStringForMatching(), EndsWith( " SuBsTrInG", Catch::CaseSensitive::No )
"this string contains 'abc' as a substring" ends with: " substring" (case insensitive)

# Empty string

empty.empty()
true
empty.size() == 0
0 == 0
std::strcmp( empty.data(), "" ) == 0
0 == 0

# From string literal

s.empty() == false
false == false
s.size() == 5
5 == 5
std::strcmp( rawChars, "hello" ) == 0
0 == 0
s.data() == rawChars
"hello" == "hello"

# From sub-string

original == "original"
original == "original"
original.data()
original.data()

# Copy construction is shallow

original.begin() == copy.begin()
"original string" == "original string"

# Copy assignment is shallow

original.begin() == copy.begin()
"original string" == "original string"

# Substrings

## zero-based substring

ss.empty() == false
false == false
ss.size() == 5
5 == 5
std::strncmp( ss.data(), "hello", 5 ) == 0
0 == 0
ss == "hello"
hello == "hello"

# Substrings

## non-zero-based substring

ss.size() == 6
6 == 6
std::strcmp( ss.data(), "world!" ) == 0
0 == 0

# Substrings

## Pointer values of full refs should match

s.data() == s2.data()
"hello world!" == "hello world!"

# Substrings

## Pointer values of substring refs should also match

s.data() == ss.data()
"hello world!" == "hello world!"

# Substrings

## Past the end substring

s.substr(s.size() + 1, 123).empty()
true

# Substrings

## Substring off the end are trimmed

std::strcmp(ss.data(), "world!") == 0
0 == 0

# Substrings

## substring start after the end is empty

s.substr(1'000'000, 1).empty()
true

# Comparisons are deep

reinterpret_cast<char*>(buffer1) != reinterpret_cast<char*>(buffer2)
"Hello" != "Hello"
left == right
Hello == Hello
left != left.substr(0, 3)
Hello != Hel

# from std::string

## implicitly constructed

sr == "a standard string"
a standard string == "a standard string"
sr.size() == stdStr.size()
17 == 17

# from std::string

## explicitly constructed

sr == "a standard string"
a standard string == "a standard string"
sr.size() == stdStr.size()
17 == 17

# from std::string

## assigned

sr == "a standard string"
a standard string == "a standard string"
sr.size() == stdStr.size()
17 == 17

# to std::string

## explicitly constructed

stdStr == "a stringref"
"a stringref" == "a stringref"
stdStr.size() == sr.size()
11 == 11

# to std::string

## assigned

stdStr == "a stringref"
"a stringref" == "a stringref"
stdStr.size() == sr.size()
11 == 11

# std::string += StringRef

lhs == "some string += the stringref contents"
"some string += the stringref contents" == "some string += the stringref contents"

# StringRef + StringRef

together == "abrakadabra"
"abrakadabra" == "abrakadabra"

# Simple constructors

# UDL construction

::Catch::Detail::stringify( with_null_terminator ) == R"("abc")"s
""abc"" == ""abc""
::Catch::Detail::stringify( no_null_terminator ) == R"("abc")"s
""abc"" == ""abc""
::Catch::Detail::stringify( with_null_terminator ) == R"("abc")"s
""abc"" == ""abc""
::Catch::Detail::stringify( no_null_terminator ) == R"("abc")"s
""abc"" == ""abc""
::Catch::Detail::stringify( with_null_terminator ) == R"("abc")"s
""abc"" == ""abc""
::Catch::Detail::stringify( no_null_terminator ) == R"("abc")"s
""abc"" == ""abc""
minute == seconds
1 m == 60 s
hour != seconds
1 h != 60 s
micro != milli
1 us != 1 ms
nano != micro
1 ns != 1 us
half_minute != femto_second
1 [30/1]s != 1 fs
pico_second != atto_second
1 ps != 1 as
now != later
{iso8601-timestamp} != {iso8601-timestamp}
s1 == s2
"if ($b == 10) { $a = 20; }" == "if ($b == 10) { $a = 20; } "

# The same tag alias can only be registered once

what, ContainsSubstring( "[@zzz]" )
"error: tag alias, '[@zzz]' already registered. First seen at: file:2 Redefined at: file:10" contains: "[@zzz]"
what, ContainsSubstring( "file" )
"error: tag alias, '[@zzz]' already registered. First seen at: file:2 Redefined at: file:10" contains: "file"
what, ContainsSubstring( "2" )
"error: tag alias, '[@zzz]' already registered. First seen at: file:2 Redefined at: file:10" contains: "2"
what, ContainsSubstring( "10" )
"error: tag alias, '[@zzz]' already registered. First seen at: file:2 Redefined at: file:10" contains: "10"

# Tag aliases must be of the form [@name]

registry.add( "[no ampersat]", "", Catch::SourceLineInfo( "file", 3 ) )
registry.add( "[no ampersat]", "", Catch::SourceLineInfo( "file", 3 ) )
registry.add( "[the @ is not at the start]", "", Catch::SourceLineInfo( "file", 3 ) )
registry.add( "[the @ is not at the start]", "", Catch::SourceLineInfo( "file", 3 ) )
registry.add( "@no square bracket at start]", "", Catch::SourceLineInfo( "file", 3 ) )
registry.add( "@no square bracket at start]", "", Catch::SourceLineInfo( "file", 3 ) )
registry.add( "[@no square bracket at end", "", Catch::SourceLineInfo( "file", 3 ) )
registry.add( "[@no square bracket at end", "", Catch::SourceLineInfo( "file", 3 ) )
testCase.tags.size() == 2
2 == 2
testCase.tags, VectorContains( Tag( "tag with spaces" ) ) && VectorContains( Tag( "I said \"good day\" sir!"_catch_sr ) )
{ {?}, {?} } ( Contains: {?} and Contains: {?} )
Template_Fixture<TestType>::m_a == 1
1 == 1
Template_Fixture<TestType>::m_a == 1
1 == 1
Template_Fixture<TestType>::m_a == 1
1.0 == 1
std::is_default_constructible<TestType>::value
true
std::is_default_constructible<TestType>::value
true
std::is_trivially_copyable<TestType>::value
true
std::is_trivially_copyable<TestType>::value
true
std::is_arithmetic<TestType>::value
true
std::is_arithmetic<TestType>::value
true
std::is_arithmetic<TestType>::value
true
v.size() == 5
5 == 5
v.capacity() >= 5
5 >= 5

# resizing bigger changes size and capacity

v.size() == 10
10 == 10
v.capacity() >= 10
10 >= 10
v.size() == 5
5 == 5
v.capacity() >= 5
5 >= 5

# resizing smaller changes size but not capacity

v.size() == 0
0 == 0
v.capacity() >= 5
5 >= 5

## We can use the 'swap trick' to reset the capacity

v.capacity() == 0
0 == 0
v.size() == 5
5 == 5
v.capacity() >= 5
5 >= 5

# reserving bigger changes capacity but not size

v.size() == 5
5 == 5
v.capacity() >= 10
10 >= 10
v.size() == 5
5 == 5
v.capacity() >= 5
5 >= 5

# reserving smaller does not change size or capacity

v.size() == 5
5 == 5
v.capacity() >= 5
5 >= 5
v.size() == 5
5 == 5
v.capacity() >= 5
5 >= 5

# resizing bigger changes size and capacity

v.size() == 10
10 == 10
v.capacity() >= 10
10 >= 10
v.size() == 5
5 == 5
v.capacity() >= 5
5 >= 5

# resizing smaller changes size but not capacity

v.size() == 0
0 == 0
v.capacity() >= 5
5 >= 5

## We can use the 'swap trick' to reset the capacity

v.capacity() == 0
0 == 0
v.size() == 5
5 == 5
v.capacity() >= 5
5 >= 5

# reserving bigger changes capacity but not size

v.size() == 5
5 == 5
v.capacity() >= 10
10 >= 10
v.size() == 5
5 == 5
v.capacity() >= 5
5 >= 5

# reserving smaller does not change size or capacity

v.size() == 5
5 == 5
v.capacity() >= 5
5 >= 5
v.size() == 5
5 == 5
v.capacity() >= 5
5 >= 5

# resizing bigger changes size and capacity

v.size() == 10
10 == 10
v.capacity() >= 10
10 >= 10
v.size() == 5
5 == 5
v.capacity() >= 5
5 >= 5

# resizing smaller changes size but not capacity

v.size() == 0
0 == 0
v.capacity() >= 5
5 >= 5

## We can use the 'swap trick' to reset the capacity

v.capacity() == 0
0 == 0
v.size() == 5
5 == 5
v.capacity() >= 5
5 >= 5

# reserving bigger changes capacity but not size

v.size() == 5
5 == 5
v.capacity() >= 10
10 >= 10
v.size() == 5
5 == 5
v.capacity() >= 5
5 >= 5

# reserving smaller does not change size or capacity

v.size() == 5
5 == 5
v.capacity() >= 5
5 >= 5
v.size() == 5
5 == 5
v.capacity() >= 5
5 >= 5

# resizing bigger changes size and capacity

v.size() == 10
10 == 10
v.capacity() >= 10
10 >= 10
v.size() == 5
5 == 5
v.capacity() >= 5
5 >= 5

# resizing smaller changes size but not capacity

v.size() == 0
0 == 0
v.capacity() >= 5
5 >= 5

## We can use the 'swap trick' to reset the capacity

v.capacity() == 0
0 == 0
v.size() == 5
5 == 5
v.capacity() >= 5
5 >= 5

# reserving bigger changes capacity but not size

v.size() == 5
5 == 5
v.capacity() >= 10
10 >= 10
v.size() == 5
5 == 5
v.capacity() >= 5
5 >= 5

# reserving smaller does not change size or capacity

v.size() == 5
5 == 5
v.capacity() >= 5
5 >= 5
v.size() == V
6 == 6
v.capacity() >= V
6 >= 6

# resizing bigger changes size and capacity

v.size() == 2 * V
12 == 12
v.capacity() >= 2 * V
12 >= 12
v.size() == V
6 == 6
v.capacity() >= V
6 >= 6

# resizing smaller changes size but not capacity

v.size() == 0
0 == 0
v.capacity() >= V
6 >= 6

## We can use the 'swap trick' to reset the capacity

v.capacity() == 0
0 == 0
v.size() == V
6 == 6
v.capacity() >= V
6 >= 6

# reserving bigger changes capacity but not size

v.size() == V
6 == 6
v.capacity() >= 2 * V
12 >= 12
v.size() == V
6 == 6
v.capacity() >= V
6 >= 6

# reserving smaller does not change size or capacity

v.size() == V
6 == 6
v.capacity() >= V
6 >= 6
v.size() == V
4 == 4
v.capacity() >= V
4 >= 4

# resizing bigger changes size and capacity

v.size() == 2 * V
8 == 8
v.capacity() >= 2 * V
8 >= 8
v.size() == V
4 == 4
v.capacity() >= V
4 >= 4

# resizing smaller changes size but not capacity

v.size() == 0
0 == 0
v.capacity() >= V
4 >= 4

## We can use the 'swap trick' to reset the capacity

v.capacity() == 0
0 == 0
v.size() == V
4 == 4
v.capacity() >= V
4 >= 4

# reserving bigger changes capacity but not size

v.size() == V
4 == 4
v.capacity() >= 2 * V
8 >= 8
v.size() == V
4 == 4
v.capacity() >= V
4 >= 4

# reserving smaller does not change size or capacity

v.size() == V
4 == 4
v.capacity() >= V
4 >= 4
v.size() == V
5 == 5
v.capacity() >= V
5 >= 5

# resizing bigger changes size and capacity

v.size() == 2 * V
10 == 10
v.capacity() >= 2 * V
10 >= 10
v.size() == V
5 == 5
v.capacity() >= V
5 >= 5

# resizing smaller changes size but not capacity

v.size() == 0
0 == 0
v.capacity() >= V
5 >= 5

## We can use the 'swap trick' to reset the capacity

v.capacity() == 0
0 == 0
v.size() == V
5 == 5
v.capacity() >= V
5 >= 5

# reserving bigger changes capacity but not size

v.size() == V
5 == 5
v.capacity() >= 2 * V
10 >= 10
v.size() == V
5 == 5
v.capacity() >= V
5 >= 5

# reserving smaller does not change size or capacity

v.size() == V
5 == 5
v.capacity() >= V
5 >= 5
v.size() == V
15 == 15
v.capacity() >= V
15 >= 15

# resizing bigger changes size and capacity

v.size() == 2 * V
30 == 30
v.capacity() >= 2 * V
30 >= 30
v.size() == V
15 == 15
v.capacity() >= V
15 >= 15

# resizing smaller changes size but not capacity

v.size() == 0
0 == 0
v.capacity() >= V
15 >= 15

## We can use the 'swap trick' to reset the capacity

v.capacity() == 0
0 == 0
v.size() == V
15 == 15
v.capacity() >= V
15 >= 15

# reserving bigger changes capacity but not size

v.size() == V
15 == 15
v.capacity() >= 2 * V
30 >= 30
v.size() == V
15 == 15
v.capacity() >= V
15 >= 15

# reserving smaller does not change size or capacity

v.size() == V
15 == 15
v.capacity() >= V
15 >= 15
testCase.tags.size() == 1
1 == 1
testCase.tags[0] == Tag( "tag1" )
{?} == {?}
0x<hex digits> == bit30and31
3221225472 (0x<hex digits>) == 3221225472
true
true
false
false
true
true
false
false
true
true
false
false
true
true
{Unknown expression after the reported line}
{Unknown expression after the reported line}
Uncaught exception should fail!
false
false
{Unknown expression after the reported line}
{Unknown expression after the reported line}
Uncaught exception should fail!
1 == 2
1 == 2

# Listing tags

listingString, ContainsSubstring("[fakeTag]"s)
"All available tags: 1 [fakeTag] 1 tag

" contains: "[fakeTag]"

# Listing reporters

listingString, ContainsSubstring( "fake reporter"s ) && ContainsSubstring( "fake description"s )
"Available reporters: fake reporter: fake description

" ( contains: "fake reporter" and contains: "fake description" )

# Listing tests

listingString, ContainsSubstring( "fake test name"s ) && ContainsSubstring( "fakeTestTag"s )
"All available test cases: fake test name [fakeTestTag] 1 test case

" ( contains: "fake test name" and contains: "fakeTestTag" )

# Listing listeners

listingString, ContainsSubstring( "fakeListener"s ) && ContainsSubstring( "fake description"s )
"Registered listeners: fakeListener: fake description

" ( contains: "fakeListener" and contains: "fake description" )
For some reason someone is throwing a string literal!
testCase.isOpen()
true
s1.isOpen()
true

# successfully close one section

s1.isSuccessfullyCompleted()
true
testCase.isComplete() == false
false == false
ctx.completedCycle()
true
testCase.isSuccessfullyCompleted()
true
testCase.isOpen()
true
s1.isOpen()
true

# fail one section

s1.isComplete()
true
s1.isSuccessfullyCompleted() == false
false == false
testCase.isComplete() == false
false == false
ctx.completedCycle()
true
testCase.isSuccessfullyCompleted() == false
false == false

## re-enter after failed section

testCase2.isOpen()
true
s1b.isOpen() == false
false == false
ctx.completedCycle()
true
testCase.isComplete()
true
testCase.isSuccessfullyCompleted()
true
testCase.isOpen()
true
s1.isOpen()
true

# fail one section

s1.isComplete()
true
s1.isSuccessfullyCompleted() == false
false == false
testCase.isComplete() == false
false == false
ctx.completedCycle()
true
testCase.isSuccessfullyCompleted() == false
false == false

## re-enter after failed section and find next section

testCase2.isOpen()
true
s1b.isOpen() == false
false == false
s2.isOpen()
true
ctx.completedCycle()
true
testCase.isComplete()
true
testCase.isSuccessfullyCompleted()
true
testCase.isOpen()
true
s1.isOpen()
true

# successfully close one section, then find another

s2.isOpen() == false
false == false
testCase.isComplete() == false
false == false

## Re-enter - skips S1 and enters S2

testCase2.isOpen()
true
s1b.isOpen() == false
false == false
s2b.isOpen()
true
ctx.completedCycle() == false
false == false

### Successfully close S2

ctx.completedCycle()
true
s2b.isSuccessfullyCompleted()
true
testCase2.isComplete() == false
false == false
testCase2.isSuccessfullyCompleted()
true
testCase.isOpen()
true
s1.isOpen()
true

# successfully close one section, then find another

s2.isOpen() == false
false == false
testCase.isComplete() == false
false == false

## Re-enter - skips S1 and enters S2

testCase2.isOpen()
true
s1b.isOpen() == false
false == false
s2b.isOpen()
true
ctx.completedCycle() == false
false == false

### fail S2

ctx.completedCycle()
true
s2b.isComplete()
true
s2b.isSuccessfullyCompleted() == false
false == false
testCase2.isSuccessfullyCompleted() == false
false == false
testCase3.isOpen()
true
s1c.isOpen() == false
false == false
s2c.isOpen() == false
false == false
testCase3.isSuccessfullyCompleted()
true
testCase.isOpen()
true
s1.isOpen()
true

# open a nested section

s2.isOpen()
true
s2.isComplete()
true
s1.isComplete() == false
false == false
s1.isComplete()
true
testCase.isComplete() == false
false == false
testCase.isComplete()
true
trim(std::string(no_whitespace)) == no_whitespace
"There is no extra whitespace here" == "There is no extra whitespace here"
trim(std::string(leading_whitespace)) == no_whitespace
"There is no extra whitespace here" == "There is no extra whitespace here"
trim(std::string(trailing_whitespace)) == no_whitespace
"There is no extra whitespace here" == "There is no extra whitespace here"
trim(std::string(whitespace_at_both_ends)) == no_whitespace
"There is no extra whitespace here" == "There is no extra whitespace here"
trim(StringRef(no_whitespace)) == StringRef(no_whitespace)
There is no extra whitespace here == There is no extra whitespace here
trim(StringRef(leading_whitespace)) == StringRef(no_whitespace)
There is no extra whitespace here == There is no extra whitespace here
trim(StringRef(trailing_whitespace)) == StringRef(no_whitespace)
There is no extra whitespace here == There is no extra whitespace here
trim(StringRef(whitespace_at_both_ends)) == StringRef(no_whitespace)
There is no extra whitespace here == There is no extra whitespace here

# Container conversions

## Two equal containers of different container types

array_int_a, RangeEquals( c_array )
{ 1, 2, 3 } elements are { 1, 2, 3 }
array_int_a, UnorderedRangeEquals( c_array )
{ 1, 2, 3 } unordered elements are { 1, 2, 3 }

# Container conversions

## Two equal containers of different container types (differ in array N)

array_int_3, !RangeEquals( array_int_4 )
{ 1, 2, 3 } not elements are { 1, 2, 3, 4 }
array_int_3, !UnorderedRangeEquals( array_int_4 )
{ 1, 2, 3 } not unordered elements are { 1, 2, 3, 4 }

# Container conversions

## Two equal containers of different container types and value types

array_int_a, RangeEquals( vector_char_a )
{ 1, 2, 3 } elements are { 1, 2, 3 }
array_int_a, UnorderedRangeEquals( vector_char_a )
{ 1, 2, 3 } unordered elements are { 1, 2, 3 }

# Container conversions

## Two equal containers, one random access, one not

array_int_a, RangeEquals( list_char_a )
{ 1, 2, 3 } elements are { 1, 2, 3 }
array_int_a, UnorderedRangeEquals( list_char_a )
{ 1, 2, 3 } unordered elements are { 1, 2, 3 }

# Value type

## Two equal containers of different value types

vector_int_a, RangeEquals( vector_char_a )
{ 1, 2, 3 } elements are { 1, 2, 3 }
vector_int_a, UnorderedRangeEquals( vector_char_a )
{ 1, 2, 3 } unordered elements are { 1, 2, 3 }

# Value type

## Two non-equal containers of different value types

vector_int_a, !RangeEquals( vector_char_b )
{ 1, 2, 3 } not elements are { 1, 2, 2 }
vector_int_a, !UnorderedRangeEquals( vector_char_b )
{ 1, 2, 3 } not unordered elements are { 1, 2, 2 }

# Ranges with begin that needs ADL

a, !RangeEquals( b )
{ 1, 2, 3 } not elements are { 3, 2, 1 }
a, UnorderedRangeEquals( b )
{ 1, 2, 3 } unordered elements are { 3, 2, 1 }

# Custom predicate

## Two equal non-empty containers (close enough)

vector_a, RangeEquals( array_a_plus_1, close_enough )
{ 1, 2, 3 } elements are { 2, 3, 4 }
vector_a, UnorderedRangeEquals( array_a_plus_1, close_enough )
{ 1, 2, 3 } unordered elements are { 2, 3, 4 }
3.14000000000000012

# Move constructor

bptr->i == 3
3 == 3

# move assignment

bptr->i == 3
3 == 3

# Basic usage

data, AllMatch(SizeIs(5))
{ { 0, 1, 2, 3, 5 }, { 4, -3, -2, 5, 0 }, { 0, 0, 0, 5, 0 }, { 0, -5, 0, 5, 0 }, { 1, 0, 0, -1, 5 } } all match has size == 5
data, !AllMatch(Contains(0) && Contains(1))
{ { 0, 1, 2, 3, 5 }, { 4, -3, -2, 5, 0 }, { 0, 0, 0, 5, 0 }, { 0, -5, 0, 5, 0 }, { 1, 0, 0, -1, 5 } } not all match ( contains element 0 and contains element 1 )

# Type requires ADL found begin and end

needs_adl, AllMatch( Predicate<int>( []( int elem ) { return elem < 6; } ) )
{ 1, 2, 3, 4, 5 } all match matches undescribed predicate

# Shortcircuiting

## All are read

mocked, allMatch
{ 1, 2, 3, 4, 5 } all match matches undescribed predicate
mocked.m_derefed[0]
true
mocked.m_derefed[1]
true
mocked.m_derefed[2]
true
mocked.m_derefed[3]
true
mocked.m_derefed[4]
true

# Shortcircuiting

## Short-circuited

mocked, !allMatch
{ 1, 2, 3, 4, 5 } not all match matches undescribed predicate
mocked.m_derefed[0]
true
mocked.m_derefed[1]
true
mocked.m_derefed[2]
true
!(mocked.m_derefed[3])
!false
!(mocked.m_derefed[4])
!false

# Basic usage

## All true evaluates to true

data, AllTrue()
{ true, true, true, true, true } contains only true

# Basic usage

## Empty evaluates to true

data, AllTrue()
{ } contains only true

# Basic usage

## One false evaluates to false

data, !AllTrue()
{ true, true, false, true, true } not contains only true

# Basic usage

## All false evaluates to false

data, !AllTrue()
{ false, false, false, false, false } not contains only true

# Contained type is convertible to bool

## All true evaluates to true

data, AllTrue()
{ true, true, true, true, true } contains only true

# Contained type is convertible to bool

## One false evaluates to false

data, !AllTrue()
{ true, true, false, true, true } not contains only true

# Contained type is convertible to bool

## All false evaluates to false

data, !AllTrue()
{ false, false, false, false, false } not contains only true

# Shortcircuiting

## All are read

mocked, AllTrue()
{ true, true, true, true, true } contains only true
mocked.m_derefed[0]
true
mocked.m_derefed[1]
true
mocked.m_derefed[2]
true
mocked.m_derefed[3]
true
mocked.m_derefed[4]
true

# Shortcircuiting

## Short-circuited

mocked, !AllTrue()
{ true, true, false, true, true } not contains only true
mocked.m_derefed[0]
true
mocked.m_derefed[1]
true
mocked.m_derefed[2]
true
!(mocked.m_derefed[3])
!false
!(mocked.m_derefed[4])
!false

# Basic usage

data, AnyMatch(SizeIs(5))
{ { 0, 1, 2, 3, 5 }, { 4, -3, -2, 5, 0 }, { 0, 0, 0, 5, 0 }, { 0, -5, 0, 5, 0 }, { 1, 0, 0, -1, 5 } } any match has size == 5
data, !AnyMatch(Contains(0) && Contains(10))
{ { 0, 1, 2, 3, 5 }, { 4, -3, -2, 5, 0 }, { 0, 0, 0, 5, 0 }, { 0, -5, 0, 5, 0 }, { 1, 0, 0, -1, 5 } } not any match ( contains element 0 and contains element 10 )

# Type requires ADL found begin and end

needs_adl, AnyMatch( Predicate<int>( []( int elem ) { return elem < 3; } ) )
{ 1, 2, 3, 4, 5 } any match matches undescribed predicate

# Shortcircuiting

## All are read

mocked, !anyMatch
{ 1, 2, 3, 4, 5 } not any match matches undescribed predicate
mocked.m_derefed[0]
true
mocked.m_derefed[1]
true
mocked.m_derefed[2]
true
mocked.m_derefed[3]
true
mocked.m_derefed[4]
true

# Shortcircuiting

## Short-circuited

mocked, anyMatch
{ 1, 2, 3, 4, 5 } any match matches undescribed predicate
mocked.m_derefed[0]
true
!(mocked.m_derefed[1])
!false
!(mocked.m_derefed[2])
!false
!(mocked.m_derefed[3])
!false
!(mocked.m_derefed[4])
!false

# Basic usage

## All true evaluates to true

data, AnyTrue()
{ true, true, true, true, true } contains at least one true

# Basic usage

## Empty evaluates to false

data, !AnyTrue()
{ } not contains at least one true

# Basic usage

## One true evaluates to true

data, AnyTrue()
{ false, false, true, false, false } contains at least one true

# Basic usage

## All false evaluates to false

data, !AnyTrue()
{ false, false, false, false, false } not contains at least one true

# Contained type is convertible to bool

## All true evaluates to true

data, AnyTrue()
{ true, true, true, true, true } contains at least one true

# Contained type is convertible to bool

## One true evaluates to true

data, AnyTrue()
{ false, false, true, false, false } contains at least one true

# Contained type is convertible to bool

## All false evaluates to false

data, !AnyTrue()
{ false, false, false, false, false } not contains at least one true

# Shortcircuiting

## All are read

mocked, AnyTrue()
{ false, false, false, false, true } contains at least one true
mocked.m_derefed[0]
true
mocked.m_derefed[1]
true
mocked.m_derefed[2]
true
mocked.m_derefed[3]
true
mocked.m_derefed[4]
true

# Shortcircuiting

## Short-circuited

mocked, AnyTrue()
{ false, false, true, true, true } contains at least one true
mocked.m_derefed[0]
true
mocked.m_derefed[1]
true
mocked.m_derefed[2]
true
!(mocked.m_derefed[3])
!false
!(mocked.m_derefed[4])
!false

# Basic usage

data, NoneMatch(SizeIs(6))
{ { 0, 1, 2, 3, 5 }, { 4, -3, -2, 5, 0 }, { 0, 0, 0, 5, 0 }, { 0, -5, 0, 5, 0 }, { 1, 0, 0, -1, 5 } } none match has size == 6
data, !NoneMatch(Contains(0) && Contains(1))
{ { 0, 1, 2, 3, 5 }, { 4, -3, -2, 5, 0 }, { 0, 0, 0, 5, 0 }, { 0, -5, 0, 5, 0 }, { 1, 0, 0, -1, 5 } } not none match ( contains element 0 and contains element 1 )

# Type requires ADL found begin and end

needs_adl, NoneMatch( Predicate<int>( []( int elem ) { return elem > 6; } ) )
{ 1, 2, 3, 4, 5 } none match matches undescribed predicate

# Shortcircuiting

## All are read

mocked, noneMatch
{ 1, 2, 3, 4, 5 } none match matches undescribed predicate
mocked.m_derefed[0]
true
mocked.m_derefed[1]
true
mocked.m_derefed[2]
true
mocked.m_derefed[3]
true
mocked.m_derefed[4]
true

# Shortcircuiting

## Short-circuited

mocked, !noneMatch
{ 1, 2, 3, 4, 5 } not none match matches undescribed predicate
mocked.m_derefed[0]
true
!(mocked.m_derefed[1])
!false
!(mocked.m_derefed[2])
!false
!(mocked.m_derefed[3])
!false
!(mocked.m_derefed[4])
!false

# Basic usage

## All true evaluates to false

data, !NoneTrue()
{ true, true, true, true, true } not contains no true

# Basic usage

## Empty evaluates to true

data, NoneTrue()
{ } contains no true

# Basic usage

## One true evaluates to false

data, !NoneTrue()
{ false, false, true, false, false } not contains no true

# Basic usage

## All false evaluates to true

data, NoneTrue()
{ false, false, false, false, false } contains no true

# Contained type is convertible to bool

## All true evaluates to false

data, !NoneTrue()
{ true, true, true, true, true } not contains no true

# Contained type is convertible to bool

## One true evaluates to false

data, !NoneTrue()
{ false, false, true, false, false } not contains no true

# Contained type is convertible to bool

## All false evaluates to true

data, NoneTrue()
{ false, false, false, false, false } contains no true

# Shortcircuiting

## All are read

mocked, NoneTrue()
{ false, false, false, false, false } contains no true
mocked.m_derefed[0]
true
mocked.m_derefed[1]
true
mocked.m_derefed[2]
true
mocked.m_derefed[3]
true
mocked.m_derefed[4]
true

# Shortcircuiting

## Short-circuited

mocked, !NoneTrue()
{ false, false, true, true, true } not contains no true
mocked.m_derefed[0]
true
mocked.m_derefed[1]
true
mocked.m_derefed[2]
true
!(mocked.m_derefed[3])
!false
!(mocked.m_derefed[4])
!false

# Basic usage

## Empty container matches empty container

empty_vector, RangeEquals( empty_vector )
{ } elements are { }

# Basic usage

## Empty container does not match non-empty container

empty_vector, !RangeEquals( non_empty_vector )
{ } not elements are { 1 }
non_empty_vector, !RangeEquals( empty_vector )
{ 1 } not elements are { }

# Basic usage

## Two equal 1-length non-empty containers

non_empty_array, RangeEquals( non_empty_array )
{ 1 } elements are { 1 }

# Basic usage

## Two equal-sized, equal, non-empty containers

array_a, RangeEquals( array_a )
{ 1, 2, 3 } elements are { 1, 2, 3 }

# Basic usage

## Two equal-sized, non-equal, non-empty containers

array_a, !RangeEquals( array_b )
{ 1, 2, 3 } not elements are { 2, 2, 3 }
array_a, !RangeEquals( array_c )
{ 1, 2, 3 } not elements are { 1, 2, 2 }

# Basic usage

## Two non-equal-sized, non-empty containers (with same first elements)

vector_a, !RangeEquals( vector_b )
{ 1, 2, 3 } not elements are { 1, 2, 3, 4 }

# Custom predicate

## Two equal non-empty containers (close enough)

vector_a, RangeEquals( vector_a_plus_1, close_enough )
{ 1, 2, 3 } elements are { 2, 3, 4 }

# Custom predicate

## Two non-equal non-empty containers (close enough)

vector_a, !RangeEquals( vector_b, close_enough )
{ 1, 2, 3 } not elements are { 3, 3, 4 }

# Ranges that need ADL begin/end

needs_adl1, RangeEquals( needs_adl2 )
{ 1, 2, 3, 4, 5 } elements are { 1, 2, 3, 4, 5 }
needs_adl1, RangeEquals( needs_adl3, []( int l, int r ) { return l + 1 == r; } )
{ 1, 2, 3, 4, 5 } elements are { 2, 3, 4, 5, 6 }

# Compare against std::initializer_list

array_a, RangeEquals( { 1, 2, 3 } )
{ 1, 2, 3 } elements are { 1, 2, 3 }
array_a, RangeEquals( { 2, 4, 6 }, []( int l, int r ) { return l * 2 == r; } )
{ 1, 2, 3 } elements are { 2, 4, 6 }

# Check short-circuiting behaviour

## Check short-circuits on failure

mocked1, !RangeEquals( arr )
{ 1, 2, 3, 4 } not elements are { 1, 2, 4, 4 }
mocked1.m_derefed[0]
true
mocked1.m_derefed[1]
true
mocked1.m_derefed[2]
true
!(mocked1.m_derefed[3])
!false

# Check short-circuiting behaviour

## All elements are checked on success

mocked1, RangeEquals( arr )
{ 1, 2, 3, 4 } elements are { 1, 2, 3, 4 }
mocked1.m_derefed[0]
true
mocked1.m_derefed[1]
true
mocked1.m_derefed[2]
true
mocked1.m_derefed[3]
true

# Basic usage

## Empty container matches empty container

empty_vector, UnorderedRangeEquals( empty_vector )
{ } unordered elements are { }

# Basic usage

## Empty container does not match non-empty container

empty_vector, !UnorderedRangeEquals( non_empty_vector )
{ } not unordered elements are { 1 }
non_empty_vector, !UnorderedRangeEquals( empty_vector )
{ 1 } not unordered elements are { }

# Basic usage

## Two equal 1-length non-empty containers

non_empty_array, UnorderedRangeEquals( non_empty_array )
{ 1 } unordered elements are { 1 }

# Basic usage

## Two equal-sized, equal, non-empty containers

array_a, UnorderedRangeEquals( array_a )
{ 1, 2, 3 } unordered elements are { 1, 2, 3 }

# Basic usage

## Two equal-sized, non-equal, non-empty containers

array_a, !UnorderedRangeEquals( array_b )
{ 1, 2, 3 } not unordered elements are { 2, 2, 3 }

# Basic usage

## Two non-equal-sized, non-empty containers

vector_a, !UnorderedRangeEquals( vector_b )
{ 1, 2, 3 } not unordered elements are { 1, 2, 3, 4 }

# Custom predicate

## Two equal non-empty containers (close enough)

vector_a, UnorderedRangeEquals( vector_a_plus_1, close_enough )
{ 1, 10, 20 } unordered elements are { 11, 21, 2 }

# Custom predicate

## Two non-equal non-empty containers (close enough)

vector_a, !UnorderedRangeEquals( vector_b, close_enough )
{ 1, 10, 21 } not unordered elements are { 11, 21, 3 }

# Ranges that need ADL begin/end

needs_adl1, UnorderedRangeEquals( needs_adl2 )
{ 1, 2, 3, 4, 5 } unordered elements are { 1, 2, 3, 4, 5 }

# Compare against std::initializer_list

array_a, UnorderedRangeEquals( { 10, 20, 1 } )
{ 1, 10, 20 } unordered elements are { 10, 20, 1 }
array_a, UnorderedRangeEquals( { 11, 21, 2 }, []( int l, int r ) { return std::abs( l - r ) <= 1; } )
{ 1, 10, 20 } unordered elements are { 11, 21, 2 }

# Some with stdlib containers

empty_vec, SizeIs(0)
{ } has size == 0
empty_vec, !SizeIs(2)
{ } not has size == 2
empty_vec, SizeIs(Lt(2))
{ } size matches is less than 2
arr, SizeIs(2)
{ 0, 0 } has size == 2
arr, SizeIs( Lt(3))
{ 0, 0 } size matches is less than 3
arr, !SizeIs(!Lt(3))
{ 0, 0 } not size matches not is less than 3
map, SizeIs(3)
{ {?}, {?}, {?} } has size == 3

# Type requires ADL found size free function

unrelated::ADL_size{}, SizeIs(12)
{?} has size == 12

# Type has size member

has_size{}, SizeIs(13)
{?} has size == 13
d == approx( 1.23 )
1.22999999999999998 == Approx( 1.22999999999999998 )
d == approx( 1.22 )
1.22999999999999998 == Approx( 1.21999999999999997 )
d == approx( 1.24 )
1.22999999999999998 == Approx( 1.23999999999999999 )
d != approx( 1.25 )
1.22999999999999998 != Approx( 1.25 )
approx( d ) == 1.23
Approx( 1.22999999999999998 ) == 1.22999999999999998
approx( d ) == 1.22
Approx( 1.22999999999999998 ) == 1.21999999999999997
approx( d ) == 1.24
Approx( 1.22999999999999998 ) == 1.23999999999999999
approx( d ) != 1.25
Approx( 1.22999999999999998 ) != 1.25

# Section with one argument

# Empty vector is roughly equal to an empty vector

empty, Approx( empty )
{ } is approx: { }

# Vectors with elements

## A vector is approx equal to itself

v1, Approx( v1 )
{ 1.0, 2.0, 3.0 } is approx: { 1.0, 2.0, 3.0 }
v1, Approx<double>( { 1., 2., 3. } )
{ 1.0, 2.0, 3.0 } is approx: { 1.0, 2.0, 3.0 }

# Vectors with elements

## Different length

v1, !Approx( temp )
{ 1.0, 2.0, 3.0 } not is approx: { 1.0, 2.0, 3.0, 4.0 }

# Vectors with elements

## Same length, different elements

v1, !Approx( v2 )
{ 1.0, 2.0, 3.0 } not is approx: { 1.5, 2.5, 3.5 }
v1, Approx( v2 ).margin( 0.5 )
{ 1.0, 2.0, 3.0 } is approx: { 1.5, 2.5, 3.5 }
v1, Approx( v2 ).epsilon( 0.5 )
{ 1.0, 2.0, 3.0 } is approx: { 1.5, 2.5, 3.5 }
v1, Approx( v2 ).epsilon( 0.1 ).scale( 500 )
{ 1.0, 2.0, 3.0 } is approx: { 1.5, 2.5, 3.5 }

# Empty and non empty vectors are not approx equal

empty, Approx( t1 )
{ } is approx: { 1.0, 2.0 }

# Just different vectors

v1, Approx( v2 )
{ 2.0, 4.0, 6.0 } is approx: { 1.0, 3.0, 5.0 }

# Contains (element)

v, VectorContains( 1 )
{ 1, 2, 3 } Contains: 1
v, VectorContains( 2 )
{ 1, 2, 3 } Contains: 2
v5, ( VectorContains<int, CustomAllocator<int>>( 2 ) )
{ 1, 2, 3 } Contains: 2

# Contains (vector)

v, Contains( v2 )
{ 1, 2, 3 } Contains: { 1, 2 }
v, Contains<int>( { 1, 2 } )
{ 1, 2, 3 } Contains: { 1, 2 }
v5, ( Contains<int, std::allocator<int>, CustomAllocator<int>>( v2 ) )
{ 1, 2, 3 } Contains: { 1, 2 }
v, Contains( v2 )
{ 1, 2, 3 } Contains: { 1, 2, 3 }
v, Contains( empty )
{ 1, 2, 3 } Contains: { }
empty, Contains( empty )
{ } Contains: { }
v5, ( Contains<int, std::allocator<int>, CustomAllocator<int>>( v2 ) )
{ 1, 2, 3 } Contains: { 1, 2, 3 }
v5, Contains( v6 )
{ 1, 2, 3 } Contains: { 1, 2 }

# Contains (element), composed

v, VectorContains( 1 ) && VectorContains( 2 )
{ 1, 2, 3 } ( Contains: 1 and Contains: 2 )

# Equals

v, Equals( v )
{ 1, 2, 3 } Equals: { 1, 2, 3 }
empty, Equals( empty )
{ } Equals: { }
v, Equals<int>( { 1, 2, 3 } )
{ 1, 2, 3 } Equals: { 1, 2, 3 }
v, Equals( v2 )
{ 1, 2, 3 } Equals: { 1, 2, 3 }
v5, ( Equals<int, std::allocator<int>, CustomAllocator<int>>( v2 ) )
{ 1, 2, 3 } Equals: { 1, 2, 3 }
v5, Equals( v6 )
{ 1, 2, 3 } Equals: { 1, 2, 3 }

# UnorderedEquals

v, UnorderedEquals( v )
{ 1, 2, 3 } UnorderedEquals: { 1, 2, 3 }
v, UnorderedEquals<int>( { 3, 2, 1 } )
{ 1, 2, 3 } UnorderedEquals: { 3, 2, 1 }
empty, UnorderedEquals( empty )
{ } UnorderedEquals: { }
permuted, UnorderedEquals( v )
{ 1, 3, 2 } UnorderedEquals: { 1, 2, 3 }
permuted, UnorderedEquals( v )
{ 2, 3, 1 } UnorderedEquals: { 1, 2, 3 }
v5, ( UnorderedEquals<int, std::allocator<int>, CustomAllocator<int>>( permuted ) )
{ 1, 2, 3 } UnorderedEquals: { 2, 3, 1 }
v5_permuted, UnorderedEquals( v5 )
{ 1, 3, 2 } UnorderedEquals: { 1, 2, 3 }

# Contains (element)

v, VectorContains( -1 )
{ 1, 2, 3 } Contains: -1
empty, VectorContains( 1 )
{ } Contains: 1

# Contains (vector)

empty, Contains( v )
{ } Contains: { 1, 2, 3 }
v, Contains( v2 )
{ 1, 2, 3 } Contains: { 1, 2, 4 }

# Equals

v, Equals( v2 )
{ 1, 2, 3 } Equals: { 1, 2 }
v2, Equals( v )
{ 1, 2 } Equals: { 1, 2, 3 }
empty, Equals( v )
{ } Equals: { 1, 2, 3 }
v, Equals( empty )
{ 1, 2, 3 } Equals: { }

# UnorderedEquals

v, UnorderedEquals( empty )
{ 1, 2, 3 } UnorderedEquals: { }
empty, UnorderedEquals( v )
{ } UnorderedEquals: { 1, 2, 3 }
permuted, UnorderedEquals( v )
{ 1, 3 } UnorderedEquals: { 1, 2, 3 }
permuted, UnorderedEquals( v )
{ 3, 1 } UnorderedEquals: { 1, 2, 3 }
thisThrows(), std::domain_error
thisThrows(), std::domain_error
thisDoesntThrow()
thisDoesntThrow()
thisThrows()
thisThrows()
unexpected exception
thisThrows() == 0
thisThrows() == 0
expected exception
thisThrows() == 0
thisThrows() == 0
expected exception
thisThrows() == 0
thisThrows() == 0
expected exception

# section name

{Unknown expression after the reported line}
{Unknown expression after the reported line}
unexpected exception

# normal string

encode( "normal string" ) == "normal string"
"normal string" == "normal string"

# empty string

encode( "" ) == ""
"" == ""

# string with ampersand

encode( "smith & jones" ) == "smith &amp; jones"
"smith &amp; jones" == "smith &amp; jones"

# string with less-than

encode( "smith < jones" ) == "smith &lt; jones"
"smith &lt; jones" == "smith &lt; jones"

# string with greater-than

encode( "smith > jones" ) == "smith > jones"
"smith > jones" == "smith > jones"
encode( "smith ]]> jones" ) == "smith ]]&gt; jones"
"smith ]]&gt; jones" == "smith ]]&gt; jones"

# string with quotes

encode( stringWithQuotes ) == stringWithQuotes
"don't "quote" me on that" == "don't "quote" me on that"
encode( stringWithQuotes, Catch::XmlEncode::ForAttributes ) == "don't &quot;quote&quot; me on that"
"don't &quot;quote&quot; me on that" == "don't &quot;quote&quot; me on that"

# string with control char (1)

encode( "[\x01]" ) == "[\\x01]"
"[\x01]" == "[\x01]"

# string with control char (x7F)

encode( "[\x7F]" ) == "[\\x7F]"
"[\x7F]" == "[\x7F]"
stream.str(), ContainsSubstring(R"(attr1="true")") && ContainsSubstring(R"(attr2="false")")
"<?xml version="1.0" encoding="UTF-8"?> <Element1 attr1="true" attr2="false"/> " ( contains: "attr1="true"" and contains: "attr2="false"" )
analysis.mean.point.count() == 23
23.0 == 23
analysis.mean.lower_bound.count() == 23
23.0 == 23
analysis.mean.upper_bound.count() == 23
23.0 == 23
analysis.standard_deviation.point.count() == 0
0.0 == 0
analysis.standard_deviation.lower_bound.count() == 0
0.0 == 0
analysis.standard_deviation.upper_bound.count() == 0
0.0 == 0
analysis.outliers.total() == 0
0 == 0
analysis.outliers.low_mild == 0
0 == 0
analysis.outliers.low_severe == 0
0 == 0
analysis.outliers.high_mild == 0
0 == 0
analysis.outliers.high_severe == 0
0 == 0
analysis.outliers.samples_seen == 0
0 == 0
analysis.outlier_variance == 0
0.0 == 0
Catch::Detail::stringify( empty ) == "{ }"
"{ }" == "{ }"
Catch::Detail::stringify( oneValue ) == "{ 42 }"
"{ 42 }" == "{ 42 }"
Catch::Detail::stringify( twoValues ) == "{ 42, 250 }"
"{ 42, 250 }" == "{ 42, 250 }"

# without chronometer

model.started == 1
1 == 1
model.finished == 0
0 == 0
model.started == 1
1 == 1
model.finished == 1
1 == 1
called == 1
1 == 1

# with chronometer

model.started == 0
0 == 0
model.finished == 0
0 == 0
model.started == 0
0 == 0
model.finished == 0
0 == 0
called == 1
1 == 1
obj.prop != 0
0x<hex digits> != 0
flag
true
testCheckedElse( true )
true
flag
false
testCheckedElse( false )
false
flag
true
testCheckedIf( true )
true
flag
false
testCheckedIf( false )
false

# none

o.samples_seen == static_cast<int>(x.size())
6 == 6
o.low_severe == los
0 == 0
o.low_mild == lom
0 == 0
o.high_mild == him
0 == 0
o.high_severe == his
0 == 0
o.total() == los + lom + him + his
0 == 0

# low severe

o.samples_seen == static_cast<int>(x.size())
6 == 6
o.low_severe == los
1 == 1
o.low_mild == lom
0 == 0
o.high_mild == him
0 == 0
o.high_severe == his
0 == 0
o.total() == los + lom + him + his
1 == 1

# low mild

o.samples_seen == static_cast<int>(x.size())
6 == 6
o.low_severe == los
0 == 0
o.low_mild == lom
1 == 1
o.high_mild == him
0 == 0
o.high_severe == his
0 == 0
o.total() == los + lom + him + his
1 == 1

# high mild

o.samples_seen == static_cast<int>(x.size())
6 == 6
o.low_severe == los
0 == 0
o.low_mild == lom
0 == 0
o.high_mild == him
1 == 1
o.high_severe == his
0 == 0
o.total() == los + lom + him + his
1 == 1

# high severe

o.samples_seen == static_cast<int>(x.size())
6 == 6
o.low_severe == los
0 == 0
o.low_mild == lom
0 == 0
o.high_mild == him
0 == 0
o.high_severe == his
1 == 1
o.total() == los + lom + him + his
1 == 1

# mixed

o.samples_seen == static_cast<int>(x.size())
6 == 6
o.low_severe == los
1 == 1
o.low_mild == lom
0 == 0
o.high_mild == him
1 == 1
o.high_severe == his
0 == 0
o.total() == los + lom + him + his
2 == 2
unsigned_char_var == 1
1 == 1
unsigned_short_var == 1
1 == 1
unsigned_int_var == 1
1 == 1
unsigned_long_var == 1
1 == 1
long_var == unsigned_char_var
1 == 1
long_var == unsigned_short_var
1 == 1
long_var == unsigned_int_var
1 == 1
long_var == unsigned_long_var
1 == 1
convertToBits( 0.f ) == 0
0 == 0
convertToBits( -0.f ) == ( 1ULL << 31 )
2147483648 (0x<hex digits>) == 2147483648 (0x<hex digits>)
convertToBits( 0. ) == 0
0 == 0
convertToBits( -0. ) == ( 1ULL << 63 )
9223372036854775808 (0x<hex digits>) == 9223372036854775808 (0x<hex digits>)
convertToBits( std::numeric_limits<float>::denorm_min() ) == 1
1 == 1
convertToBits( std::numeric_limits<double>::denorm_min() ) == 1
1 == 1
skipping because answer = 41
skipping because answer = 43
Catch::TestCaseInfo("", { "test with an empty tag", "[]" }, dummySourceLineInfo)
Catch::TestCaseInfo("", { "test with an empty tag", "[]" }, dummySourceLineInfo)
erfc_inv(1.103560) == Approx(-0.09203687623843015)
-0.09203687623843014 == Approx( -0.09203687623843015 )
erfc_inv(1.067400) == Approx(-0.05980291115763361)
-0.05980291115763361 == Approx( -0.05980291115763361 )
erfc_inv(0.050000) == Approx(1.38590382434967796)
1.38590382434967774 == Approx( 1.38590382434967796 )
res.mean.count() == rate
2000.0 == 2000 (0x<hex digits>)
res.outliers.total() == 0
0 == 0

# c

## d (leaf)

# c

## e (leaf)

# f (leaf)

3 == 4
3 == 4

# skipped

# not skipped

Previous info should not be seen
previous unscoped info SHOULD not be seen
l == std::numeric_limits<long long>::max()
9223372036854775807 (0x<hex digits>) == 9223372036854775807 (0x<hex digits>)

# b is currently: 0

b > a
0 > 1

# b is currently: 1

b > a
1 > 1

# b is currently: 2

b > a
2 > 1

# b is currently: 3

b > a
3 > 1

# b is currently: 4

b > a
4 > 1

# b is currently: 5

b > a
5 > 1

# b is currently: 6

b > a
6 > 1

# b is currently: 7

b > a
7 > 1

# b is currently: 8

b > a
8 > 1

# b is currently: 9

b > a
9 > 1
Testing if fib[0] (1) is even
( fib[i] % 2 ) == 0
1 == 0
Testing if fib[1] (1) is even
( fib[i] % 2 ) == 0
1 == 0
Testing if fib[2] (2) is even
( fib[i] % 2 ) == 0
0 == 0
Testing if fib[3] (3) is even
( fib[i] % 2 ) == 0
1 == 0
Testing if fib[4] (5) is even
( fib[i] % 2 ) == 0
1 == 0
Testing if fib[5] (8) is even
( fib[i] % 2 ) == 0
0 == 0
Testing if fib[6] (13) is even
( fib[i] % 2 ) == 0
1 == 0
Testing if fib[7] (21) is even
( fib[i] % 2 ) == 0
1 == 0
Catch::makeStream( "%debug" )
Catch::makeStream( "%debug" )

# From lvalue copies

!(lval.has_moved)
!false

# From rvalue moves

rval.has_moved
true

# Variadic constructor

*ptr == std::tuple<int, double, int>{1, 2., 3}
{?} == {?}
m == 19.
19.0 == 19.0
x == 17
17 == 17
x == 23
23 == 23
r.elapsed.count() == 42
42 == 42
r.result == 23
23 == 23
r.iterations == 1
1 == 1
s.elapsed.count() == 69
69 == 69
s.result == 17
17 == 17
s.iterations == 1
1 == 1
info
unscoped info

and warn may mix

info
unscoped info

they are not cleared after warnings

# doesn't equal

## equal

a == b
1 == 2

# doesn't equal

## not equal

a != b
1 != 2

# doesn't equal

## less than

a < b
1 < 2

# doesn't equal

a != b
1 != 2
b != a
2 != 1

## not equal

a != b
1 != 2

# A

# B

## B1

# B

## B2

# B

a! b1! !
s == "7"
"7" == "7"
ti == typeid(int)
{?} == {?}
normal_quantile(0.551780) == Approx(0.13015979861484198)
0.13015979861484195 == Approx( 0.13015979861484198 )
normal_quantile(0.533700) == Approx(0.08457408802851875)
0.08457408802851875 == Approx( 0.08457408802851875 )
normal_quantile(0.025000) == Approx(-1.95996398454005449)
-1.95996398454005405 == Approx( -1.95996398454005449 )
this MAY be seen only for the FIRST assertion IF info is printed for passing assertions
true
true
this MAY be seen only for the SECOND assertion IF info is printed for passing assertions
true
true
this SHOULD be seen
false
false
makeString( false ) != static_cast<char*>(0)
"valid string" != {null string}
makeString( true ) == static_cast<char*>(0)
{null string} == {null string}
ptr.get() == 0
0 == 0
::Catch::Detail::stringify( pair ) == "{ { 42, \"Arthur\" }, { \"Ford\", 24 } }"
"{ { 42, "Arthur" }, { "Ford", 24 } }" == "{ { 42, "Arthur" }, { "Ford", 24 } }"

# No enums

parseEnums( "" ), Equals( std::vector<Catch::StringRef>{} )
{ } Equals: { }

# One enum value

parseEnums( "ClassName::EnumName::Value1" ), Equals(std::vector<Catch::StringRef>{"Value1"} )
{ Value1 } Equals: { Value1 }
parseEnums( "Value1" ), Equals( std::vector<Catch::StringRef>{"Value1"} )
{ Value1 } Equals: { Value1 }
parseEnums( "EnumName::Value1" ), Equals(std::vector<Catch::StringRef>{"Value1"} )
{ Value1 } Equals: { Value1 }

# Multiple enum values

parseEnums( "ClassName::EnumName::Value1, ClassName::EnumName::Value2" ), Equals( std::vector<Catch::StringRef>{"Value1", "Value2"} )
{ Value1, Value2 } Equals: { Value1, Value2 }
parseEnums( "ClassName::EnumName::Value1, ClassName::EnumName::Value2, ClassName::EnumName::Value3" ), Equals( std::vector<Catch::StringRef>{"Value1", "Value2", "Value3"} )
{ Value1, Value2, Value3 } Equals: { Value1, Value2, Value3 }
parseEnums( "ClassName::EnumName::Value1,ClassName::EnumName::Value2 , ClassName::EnumName::Value3" ), Equals( std::vector<Catch::StringRef>{"Value1", "Value2", "Value3"} )
{ Value1, Value2, Value3 } Equals: { Value1, Value2, Value3 }
p == 0
0 == 0
this MAY be seen IF info is printed for passing assertions
true
true
this SHOULD be seen
this SHOULD also be seen
false
false
this SHOULD be seen only ONCE
false
false
true
true
this MAY also be seen only ONCE IF info is printed for passing assertions
true
true
true
true

# doesn't equal

a != b
1 != 2
b != a
2 != 1

# not equal

a != b
1 != 2

# replace single char

Catch::replaceInPlace(letters, "b", "z")
true
letters == "azcdefcg"
"azcdefcg" == "azcdefcg"

# replace two chars

Catch::replaceInPlace(letters, "c", "z")
true
letters == "abzdefzg"
"abzdefzg" == "abzdefzg"

# replace first char

Catch::replaceInPlace(letters, "a", "z")
true
letters == "zbcdefcg"
"zbcdefcg" == "zbcdefcg"

# replace last char

Catch::replaceInPlace(letters, "g", "z")
true
letters == "abcdefcz"
"abcdefcz" == "abcdefcz"

# replace all chars

Catch::replaceInPlace(letters, letters, "replaced")
true
letters == "replaced"
"replaced" == "replaced"

# replace no chars

!(Catch::replaceInPlace(letters, "x", "z"))
!false
letters == letters
"abcdefcg" == "abcdefcg"

# no replace in already-replaced string

## lengthening

Catch::replaceInPlace(letters, "c", "cc")
true
letters == "abccdefccg"
"abccdefccg" == "abccdefccg"

# no replace in already-replaced string

## shortening

Catch::replaceInPlace(s, "--", "-")
true
s == "--"
"--" == "--"

# escape '

Catch::replaceInPlace(s, "'", "|'")
true
s == "didn|'t"
"didn|'t" == "didn|'t"
Catch::makeStream( "%somestream" )
Catch::makeStream( "%somestream" )
res.size() == count
10 == 10
res[i] == rate
1000.0 == 1000 (0x<hex digits>)
res[i] == rate
1000.0 == 1000 (0x<hex digits>)
res[i] == rate
1000.0 == 1000 (0x<hex digits>)
res[i] == rate
1000.0 == 1000 (0x<hex digits>)
res[i] == rate
1000.0 == 1000 (0x<hex digits>)
res[i] == rate
1000.0 == 1000 (0x<hex digits>)
res[i] == rate
1000.0 == 1000 (0x<hex digits>)
res[i] == rate
1000.0 == 1000 (0x<hex digits>)
res[i] == rate
1000.0 == 1000 (0x<hex digits>)
meter.runs() >= old_runs
1 >= 1
meter.runs() >= old_runs
2 >= 1
meter.runs() >= old_runs
4 >= 2
meter.runs() >= old_runs
8 >= 4
meter.runs() >= old_runs
16 >= 8
meter.runs() >= old_runs
32 >= 16
meter.runs() >= old_runs
64 >= 32
meter.runs() >= old_runs
128 >= 64
Timing.elapsed >= time
128 ns >= 100 ns
Timing.result == Timing.iterations + 17
145 == 145
Timing.iterations >= time.count()
128 >= 100
x >= old_x
1 >= 1
x >= old_x
2 >= 1
x >= old_x
4 >= 2
x >= old_x
8 >= 4
x >= old_x
16 >= 8
x >= old_x
32 >= 16
x >= old_x
64 >= 32
x >= old_x
128 >= 64
Timing.elapsed >= time
128 ns >= 100 ns
Timing.result == Timing.iterations + 17
145 == 145
Timing.iterations >= time.count()
128 >= 100

# not skipped

# skipped

# also not skipped

3
false
false
hi
i := 7
false
false
testcase.tags, VectorContains( Tag( "magic-tag" ) ) && VectorContains( Tag( "."_catch_sr ) )
{ {?}, {?} } ( Contains: {?} and Contains: {?} )
skipping because answer = 43
splitStringRef("", ','), Equals(std::vector<StringRef>())
{ } Equals: { }
splitStringRef("abc", ','), Equals(std::vector<StringRef>{"abc"})
{ abc } Equals: { abc }
splitStringRef("abc,def", ','), Equals(std::vector<StringRef>{"abc", "def"})
{ abc, def } Equals: { abc, def }
Count 1 to 3...
1
2
3
false
false
Count 4 to 6...
4
5
6
false
false
!(startsWith("", 'c'))
!false
startsWith(std::string("abc"), 'a')
true
startsWith("def"_catch_sr, 'd')
true

# empty

Catch::Detail::stringify( emptyMap ) == "{ }"
"{ }" == "{ }"

# single item

Catch::Detail::stringify( map ) == "{ { \"one\", 1 } }"
"{ { "one", 1 } }" == "{ { "one", 1 } }"

# several items

Catch::Detail::stringify( map ) == "{ { \"abc\", 1 }, { \"def\", 2 }, { \"ghi\", 3 } }"
"{ { "abc", 1 }, { "def", 2 }, { "ghi", 3 } }" == "{ { "abc", 1 }, { "def", 2 }, { "ghi", 3 } }"
::Catch::Detail::stringify(value) == "{ 34, \"xyzzy\" }"
"{ 34, "xyzzy" }" == "{ 34, "xyzzy" }"
::Catch::Detail::stringify( value ) == "{ 34, \"xyzzy\" }"
"{ 34, "xyzzy" }" == "{ 34, "xyzzy" }"

# empty

Catch::Detail::stringify( emptySet ) == "{ }"
"{ }" == "{ }"

# single item

Catch::Detail::stringify( set ) == "{ \"one\" }"
"{ "one" }" == "{ "one" }"

# several items

Catch::Detail::stringify( set ) == "{ \"abc\", \"def\", \"ghi\" }"
"{ "abc", "def", "ghi" }" == "{ "abc", "def", "ghi" }"
::Catch::Detail::stringify( pr ) == "{ { \"green\", 55 } }"
"{ { "green", 55 } }" == "{ { "green", 55 } }"
Catch::makeStream( "%stderr" )->isConsole()
true
Catch::makeStream( "%stdout" )->isConsole()
true
::Catch::Detail::stringify(streamable_range{}) == "op<<(streamable_range)"
"op<<(streamable_range)" == "op<<(streamable_range)"
::Catch::Detail::stringify(stringmaker_range{}) == "stringmaker(streamable_range)"
"stringmaker(streamable_range)" == "stringmaker(streamable_range)"
::Catch::Detail::stringify(just_range{}) == "{ 1, 2, 3, 4 }"
"{ 1, 2, 3, 4 }" == "{ 1, 2, 3, 4 }"
::Catch::Detail::stringify(disabled_range{}) == "{?}"
"{?}" == "{?}"
::Catch::Detail::stringify( item ) == "StringMaker<has_maker>"
"StringMaker<has_maker>" == "StringMaker<has_maker>"
::Catch::Detail::stringify( item ) == "StringMaker<has_maker_and_operator>"
"StringMaker<has_maker_and_operator>" == "StringMaker<has_maker_and_operator>"
::Catch::Detail::stringify(item) == "{?}"
"{?}" == "{?}"
::Catch::Detail::stringify( item ) == "operator<<( has_operator )"
"operator<<( has_operator )" == "operator<<( has_operator )"
::Catch::Detail::stringify( item ) == "operator<<( has_template_operator )"
"operator<<( has_template_operator )" == "operator<<( has_template_operator )"
::Catch::Detail::stringify( v ) == "{ StringMaker<has_maker> }"
"{ StringMaker<has_maker> }" == "{ StringMaker<has_maker> }"
::Catch::Detail::stringify( v ) == "{ StringMaker<has_maker_and_operator> }"
"{ StringMaker<has_maker_and_operator> }" == "{ StringMaker<has_maker_and_operator> }"
::Catch::Detail::stringify( v ) == "{ operator<<( has_operator ) }"
"{ operator<<( has_operator ) }" == "{ operator<<( has_operator ) }"
data.str.size() == data.len
3 == 3
data.str.size() == data.len
3 == 3
data.str.size() == data.len
5 == 5
data.str.size() == data.len
4 == 4
tp1 == tp2
{iso8601-timestamp} == {iso8601-timestamp}
strlen(std::get<0>(data)) == static_cast<size_t>(std::get<1>(data))
5 == 5
strlen(std::get<0>(data)) == static_cast<size_t>(std::get<1>(data))
6 == 6
strlen(std::get<0>(data)) == static_cast<size_t>(std::get<1>(data))
5 == 5
strlen(std::get<0>(data)) == static_cast<size_t>(std::get<1>(data))
6 == 6
testcase.tags.size() == 1
1 == 1
testcase.tags[0].original == "magic.tag"_catch_sr
magic.tag == magic.tag
Why would you throw a std::string?
result == "\"wide load\""
""wide load"" == ""wide load""
result == "\"wide load\""
""wide load"" == ""wide load""
result == "\"wide load\""
""wide load"" == ""wide load""
result == "\"wide load\""
""wide load"" == ""wide load""
::Catch::Detail::stringify(e0) == "E2/V0"
"E2/V0" == "E2/V0"
::Catch::Detail::stringify(e1) == "E2/V1"
"E2/V1" == "E2/V1"
::Catch::Detail::stringify(e3) == "Unknown enum value 10"
"Unknown enum value 10" == "Unknown enum value 10"
::Catch::Detail::stringify(e0) == "0"
"0" == "0"
::Catch::Detail::stringify(e1) == "1"
"1" == "1"
::Catch::Detail::stringify(e0) == "E2{0}"
"E2{0}" == "E2{0}"
::Catch::Detail::stringify(e1) == "E2{1}"
"E2{1}" == "E2{1}"
::Catch::Detail::stringify(e0) == "0"
"0" == "0"
::Catch::Detail::stringify(e1) == "1"
"1" == "1"
"{ }" == ::Catch::Detail::stringify(type{})
"{ }" == "{ }"
"{ }" == ::Catch::Detail::stringify(value)
"{ }" == "{ }"
"1.5f" == ::Catch::Detail::stringify(float(1.5))
"1.5f" == "1.5f"
"{ 1.5f, 0 }" == ::Catch::Detail::stringify(type{1.5f,0})
"{ 1.5f, 0 }" == "{ 1.5f, 0 }"
"{ 0 }" == ::Catch::Detail::stringify(type{0})
"{ 0 }" == "{ 0 }"
"{ \"hello\", \"world\" }" == ::Catch::Detail::stringify(type{"hello","world"})
"{ "hello", "world" }" == "{ "hello", "world" }"
"{ { 42 }, { }, 1.5f }" == ::Catch::Detail::stringify(value)
"{ { 42 }, { }, 1.5f }" == "{ { 42 }, { }, 1.5f }"
e.point == 23
23.0 == 23
e.upper_bound == 23
23.0 == 23
e.lower_bound == 23
23.0 == 23
e.confidence_interval == 0.95
0.94999999999999996 == 0.94999999999999996
dist.a() == -10
-10 == -10
dist.b() == 10
10 == 10

# Default constructed unique_ptr is empty

!(ptr)
!{?}
ptr.get() == 0
0 == 0

# Take ownership of allocation

ptr
{?}
*ptr == 0
0 == 0
ptr.get() == naked_ptr
0x<hex digits> == 0x<hex digits>

## Plain reset deallocates

!(ptr)
!{?}
ptr.get() == 0
0 == 0

# Take ownership of allocation

ptr
{?}
*ptr == 0
0 == 0
ptr.get() == naked_ptr
0x<hex digits> == 0x<hex digits>

## Reset replaces ownership

ptr
{?}
ptr.get() != 0
0x<hex digits> != 0
*ptr == 2
2 == 2

# Release releases ownership

!(ptr)
!{?}
ptr.get() == 0
0 == 0

# Move constructor

!(ptr1)
!{?}
ptr2
{?}
*ptr2 == 1
1 == 1

# Move assignment

!(ptr2)
!{?}
ptr1
{?}
*ptr1 == 2
2 == 2

# free swap

*ptr1 == 2
2 == 2
*ptr2 == 1
1 == 1
::Catch::Detail::stringify(v) == "{ }"
"{ }" == "{ }"
::Catch::Detail::stringify(v) == "{ { \"hello\" }, { \"world\" } }"
"{ { "hello" }, { "world" } }" == "{ { "hello" }, { "world" } }"
::Catch::Detail::stringify(bools) == "{ }"
"{ }" == "{ }"
::Catch::Detail::stringify(bools) == "{ true }"
"{ true }" == "{ true }"
::Catch::Detail::stringify(bools) == "{ true, false }"
"{ true, false }" == "{ true, false }"
::Catch::Detail::stringify(vv) == "{ }"
"{ }" == "{ }"
::Catch::Detail::stringify(vv) == "{ 42 }"
"{ 42 }" == "{ 42 }"
::Catch::Detail::stringify(vv) == "{ 42, 250 }"
"{ 42, 250 }" == "{ 42, 250 }"
::Catch::Detail::stringify(vv) == "{ }"
"{ }" == "{ }"
::Catch::Detail::stringify(vv) == "{ 42 }"
"{ 42 }" == "{ 42 }"
::Catch::Detail::stringify(vv) == "{ 42, 250 }"
"{ 42, 250 }" == "{ 42, 250 }"
::Catch::Detail::stringify(vv) == "{ }"
"{ }" == "{ }"
::Catch::Detail::stringify(vv) == "{ \"hello\" }"
"{ "hello" }" == "{ "hello" }"
::Catch::Detail::stringify(vv) == "{ \"hello\", \"world\" }"
"{ "hello", "world" }" == "{ "hello", "world" }"
v.size() == 5
5 == 5
v.capacity() >= 5
5 >= 5

# resizing bigger changes size and capacity

v.size() == 10
10 == 10
v.capacity() >= 10
10 >= 10
v.size() == 5
5 == 5
v.capacity() >= 5
5 >= 5

# resizing smaller changes size but not capacity

v.size() == 0
0 == 0
v.capacity() >= 5
5 >= 5

## We can use the 'swap trick' to reset the capacity

v.capacity() == 0
0 == 0
v.size() == 5
5 == 5
v.capacity() >= 5
5 >= 5

# reserving bigger changes capacity but not size

v.size() == 5
5 == 5
v.capacity() >= 10
10 >= 10
v.size() == 5
5 == 5
v.capacity() >= 5
5 >= 5

# reserving smaller does not change size or capacity

v.size() == 5
5 == 5
v.capacity() >= 5
5 >= 5
(iterations * rate) > Catch::Benchmark::Detail::warmup_time.count()
160000000 (0x<hex digits>) > 100
(end - start) > Catch::Benchmark::Detail::warmup_time
310016000 ns > 100 ms
q1 == 14.5
14.5 == 14.5
med == 18.
18.0 == 18.0
q3 == 23.
23.0 == 23.0

# embedded xml: <test>it should be possible to embed xml characters, such as <, " or &, or even whole <xml>documents</xml> within an attribute</test>

# encoded chars: these should all be encoded: &&&"""<<<&"<<&"