fptr == 0
0 == 0
fptr == 0l
0 == 0
y.v == 0
0 == 0
0 == y.v
0 == 0
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
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

# outside assertions

answer := 42
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::EndsWith("aaa")
"aaa" ends with: "aaa"
templated_tests<int>(3)
true
f() == 0
1 == 0
errno == 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
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.23 == Approx( 1.23 )
d != 1.22_a
1.23 != Approx( 1.22 )
-d == -1.23_a
-1.23 == Approx( -1.23 )
d == 1.2_a .epsilon(.1)
1.23 == Approx( 1.2 )
d != 1.2_a .epsilon(.001)
1.23 != Approx( 1.2 )
d == 1_a .epsilon(.3)
1.23 == 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.3 != Approx( 100.0 )
100.3 == Approx(100.0).margin(0.5)
100.3 == 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.1428571429 == Approx( 3.141 )
divide( 22, 7 ) != Approx( 3.141 ).epsilon( 0.0001 )
3.1428571429 != Approx( 3.141 )
d != Approx( 1.231 )
1.23 != Approx( 1.231 )
d == Approx( 1.231 ).epsilon( 0.1 )
1.23 == Approx( 1.231 )
1.23f == Approx( 1.23f )
1.23f == Approx( 1.2300000191 )
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.234f == Approx( 1.234 )
dMedium == Approx( 1.234f )
1.234 == Approx( 1.2339999676 )

# 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)
true
true

# A section

true
true

## Another section

true
true
true
true

# A section

true
true

## Another other section

true
true
a := 1
b := 2
c := 3
a + b := 3
a+b := 3
c > b := true
a == 1 := true
std::vector<int>{1, 2, 3}[0, 1, 2] := 3
std::vector<int>{1, 2, 3}[(0, 1)] := 2
std::vector<int>{1, 2, 3}[0] := 1
(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

# Specifically escaped

tab == '\t'
'\t' == '\t'
newline == '\n'
'\n' == '\n'
carr_return == '\r'
'\r' == '\r'
form_feed == '\f'
'\f' == '\f'

# General chars

space == ' '
' ' == ' '
c == chars[i]
'a' == 'a'
c == chars[i]
'z' == 'z'
c == chars[i]
'A' == 'A'
c == chars[i]
'Z' == 'Z'

# Low ASCII

null_terminator == '\0'
0 == 0
c == i
2 == 2
c == i
3 == 3
c == i
4 == 4
c == i
5 == 5
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 }
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
testStringForMatching2(), !composed1
"some completely different text that contains one common word" not ( contains: "string" or contains: "random" )
testStringForMatching2(), composed2
"some completely different text that contains one common word" ( contains: "string" or contains: "random" or contains: "different" )

# &&

1, !(first && second)
1 not ( CheckedTestingMatcher set to fail and CheckedTestingMatcher set to fail )
first.matchCalled
true
!second.matchCalled
true

# ||

1, first || second
1 ( CheckedTestingMatcher set to succeed or CheckedTestingMatcher set to fail )
first.matchCalled
true
!second.matchCalled
true
testStringForMatching(), Contains("not there", Catch::CaseSensitive::No)
"this string contains 'abc' as a substring" contains: "not there" (case insensitive)
testStringForMatching(), Contains("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
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.000001 != Approx( 100.0 )
std::pow(10, -5) != Approx(std::pow(10, -7))
0.00001 != Approx( 0.0000001 )
enumInfo->lookup(0) == "Value1"
Value1 == "Value1"
enumInfo->lookup(1) == "Value2"
Value2 == "Value2"
enumInfo->lookup(3) == "{** unexpected enum value **}"
{** unexpected enum value **} == "{** unexpected enum value **}"
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.01 != 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.1f == Approx( 9.1099996567 )
data.float_nine_point_one == Approx( 9.0f )
9.1f == Approx( 9.0 )
data.float_nine_point_one == Approx( 1 )
9.1f == Approx( 1.0 )
data.float_nine_point_one == Approx( 0 )
9.1f == Approx( 0.0 )
data.double_pi == Approx( 3.1415 )
3.1415926535 == Approx( 3.1415 )
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.3 == Approx( 1.301 )
data.int_seven == 7
7 == 7
data.float_nine_point_one == Approx( 9.1f )
9.1f == Approx( 9.1000003815 )
data.double_pi == Approx( 3.1415926535 )
3.1415926535 == Approx( 3.1415926535 )
data.str_hello == "hello"
"hello" == "hello"
"hello" == data.str_hello
"hello" == "hello"
data.str_hello.size() == 5
5 == 5
x == Approx( 1.3 )
1.3 == Approx( 1.3 )
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

# 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(), Contains( "except" )
"expected exception" contains: "except"
thisThrows(), Contains( "exCept", Catch::CaseSensitive::No )
"expected exception" contains: "except" (case insensitive)
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
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>)

# Relative

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

## Some subnormal values

v1, WithinRel(v2)
0.0 and 2.22507e-308 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.99 of 1.0
0., !WithinAbs(1., 0.99)
0.0 not is within 0.99 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.6

# 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.0 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 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

# Relative

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

## Some subnormal values

v1, WithinRel(v2)
0.0f and 1.17549e-38 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.9900000095 of 1.0
0.f, !WithinAbs(1.f, 0.99f)
0.0f not is within 0.9900000095 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.6000003815

# ULPs

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.0f 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.001 of 0.0 or and 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

# 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

gen.get() == 1
1 == 1
gen.next()
true
gen.get() == 3
3 == 3
!(gen.next())
!false
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

# 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.9 == Approx( -0.9 )
Current expected value is -0.9
gen.next()
true
Current expected value is -0.8
gen.get() == Approx(expected)
-0.8 == Approx( -0.8 )
Current expected value is -0.8
gen.next()
true
Current expected value is -0.7
gen.get() == Approx(expected)
-0.7 == Approx( -0.7 )
Current expected value is -0.7
gen.next()
true
Current expected value is -0.6
gen.get() == Approx(expected)
-0.6 == Approx( -0.6 )
Current expected value is -0.6
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
Current expected value is -0.4
gen.get() == Approx(expected)
-0.4 == Approx( -0.4 )
Current expected value is -0.4
gen.next()
true
Current expected value is -0.3
gen.get() == Approx(expected)
-0.3 == Approx( -0.3 )
Current expected value is -0.3
gen.next()
true
Current expected value is -0.2
gen.get() == Approx(expected)
-0.2 == Approx( -0.2 )
Current expected value is -0.2
gen.next()
true
Current expected value is -0.1
gen.get() == Approx(expected)
-0.1 == Approx( -0.1 )
Current expected value is -0.1
gen.next()
true
Current expected value is -1.38778e-16
gen.get() == Approx(expected)
-0.0 == Approx( -0.0 )
Current expected value is -1.38778e-16
gen.next()
true
Current expected value is 0.1
gen.get() == Approx(expected)
0.1 == Approx( 0.1 )
Current expected value is 0.1
gen.next()
true
Current expected value is 0.2
gen.get() == Approx(expected)
0.2 == Approx( 0.2 )
Current expected value is 0.2
gen.next()
true
Current expected value is 0.3
gen.get() == Approx(expected)
0.3 == Approx( 0.3 )
Current expected value is 0.3
gen.next()
true
Current expected value is 0.4
gen.get() == Approx(expected)
0.4 == Approx( 0.4 )
Current expected value is 0.4
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
Current expected value is 0.6
gen.get() == Approx(expected)
0.6 == Approx( 0.6 )
Current expected value is 0.6
gen.next()
true
Current expected value is 0.7
gen.get() == Approx(expected)
0.7 == Approx( 0.7 )
Current expected value is 0.7
gen.next()
true
Current expected value is 0.8
gen.get() == Approx(expected)
0.8 == Approx( 0.8 )
Current expected value is 0.8
gen.next()
true
Current expected value is 0.9
gen.get() == Approx(expected)
0.9 == Approx( 0.9 )
Current expected value is 0.9
gen.next()
true
gen.get() == Approx( rangeEnd )
1.0 == 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.7 == Approx( -0.7 )
Current expected value is -0.7
gen.next()
true
Current expected value is -0.4
gen.get() == Approx(expected)
-0.4 == Approx( -0.4 )
Current expected value is -0.4
gen.next()
true
Current expected value is -0.1
gen.get() == Approx(expected)
-0.1 == Approx( -0.1 )
Current expected value is -0.1
gen.next()
true
Current expected value is 0.2
gen.get() == Approx(expected)
0.2 == Approx( 0.2 )
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.7 == Approx( -0.7 )
Current expected value is -0.7
gen.next()
true
Current expected value is -0.4
gen.get() == Approx(expected)
-0.4 == Approx( -0.4 )
Current expected value is -0.4
gen.next()
true
Current expected value is -0.1
gen.get() == Approx(expected)
-0.1 == Approx( -0.1 )
Current expected value is -0.1
gen.next()
true
Current expected value is 0.2
gen.get() == Approx(expected)
0.2 == Approx( 0.2 )
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.23 >= Approx( 1.22 )
d >= Approx( 1.23 )
1.23 >= Approx( 1.23 )
!(d >= Approx( 1.24 ))
!(1.23 >= Approx( 1.24 ))
d >= Approx( 1.24 ).epsilon(0.1)
1.23 >= Approx( 1.24 )
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
data.int_seven != 7
7 != 7
data.float_nine_point_one != Approx( 9.1f )
9.1f != Approx( 9.1000003815 )
data.double_pi != Approx( 3.1415926535 )
3.1415926535 != Approx( 3.1415926535 )
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.1f != Approx( 9.1099996567 )
data.float_nine_point_one != Approx( 9.0f )
9.1f != Approx( 9.0 )
data.float_nine_point_one != Approx( 1 )
9.1f != Approx( 1.0 )
data.float_nine_point_one != Approx( 0 )
9.1f != Approx( 0.0 )
data.double_pi != Approx( 3.1415 )
3.1415926535 != Approx( 3.1415 )
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
[]() { return true; }()
true
d <= Approx( 1.24 )
1.23 <= Approx( 1.24 )
d <= Approx( 1.23 )
1.23 <= Approx( 1.23 )
!(d <= Approx( 1.22 ))
!(1.23 <= Approx( 1.22 ))
d <= Approx( 1.22 ).epsilon(0.1)
1.23 <= Approx( 1.22 )
testStringForMatching(), Contains("string") && Contains("abc") && Contains("substring") && Contains("contains")
"this string contains 'abc' as a substring" ( contains: "string" and contains: "abc" and contains: "substring" and contains: "contains" )
testStringForMatching(), Contains("string") || Contains("different") || Contains("random")
"this string contains 'abc' as a substring" ( contains: "string" or contains: "different" or contains: "random" )
testStringForMatching2(), Contains("string") || Contains("different") || Contains("random")
"some completely different text that contains one common word" ( contains: "string" or contains: "different" or contains: "random" )
testStringForMatching(), (Contains("string") || Contains("different")) && Contains("substring")
"this string contains 'abc' as a substring" ( ( contains: "string" or contains: "different" ) and contains: "substring" )
testStringForMatching(), (Contains("string") || Contains("different")) && Contains("random")
"this string contains 'abc' as a substring" ( ( contains: "string" or contains: "different" ) and contains: "random" )
testStringForMatching(), !Contains("different")
"this string contains 'abc' as a substring" not contains: "different"
testStringForMatching(), !Contains("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"
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.1f < 9
data.float_nine_point_one > 10
9.1f > 10
data.float_nine_point_one > 9.2
9.1f > 9.2
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.1f > 9
data.float_nine_point_one < 10
9.1f < 10
data.float_nine_point_one < 9.2
9.1f < 9.2
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

# Empty test spec should have no filters

spec.hasFilters() == false
false == false
spec.matches( tcA ) == false
false == false
spec.matches( tcB ) == false
false == false

# Test spec from empty string should have no filters

spec.hasFilters() == false
false == false
spec.matches(tcA ) == false
false == false
spec.matches( tcB ) == false
false == false

# Test spec from just a comma should have no filters

spec.hasFilters() == false
false == false
spec.matches( tcA ) == false
false == false
spec.matches( tcB ) == false
false == false

# Test spec from name should have one filter

spec.hasFilters() == true
true == true
spec.matches( tcA ) == false
false == false
spec.matches( tcB ) == true
true == true

# Test spec from quoted name should have one filter

spec.hasFilters() == true
true == true
spec.matches( tcA ) == false
false == false
spec.matches( tcB ) == true
true == true

# Test spec from name should have one filter

spec.hasFilters() == true
true == true
spec.matches( tcA ) == false
false == false
spec.matches( tcB ) == true
true == true
spec.matches( tcC ) == false
false == false

# Wildcard at the start

spec.hasFilters() == true
true == true
spec.matches( tcA ) == false
false == false
spec.matches( tcB ) == false
false == false
spec.matches( tcC ) == true
true == true
spec.matches( tcD ) == false
false == false
parseTestSpec( "*a" ).matches( tcA ) == true
true == true

# Wildcard at the end

spec.hasFilters() == true
true == true
spec.matches( tcA ) == false
false == false
spec.matches( tcB ) == false
false == false
spec.matches( tcC ) == true
true == true
spec.matches( tcD ) == false
false == false
parseTestSpec( "a*" ).matches( tcA ) == true
true == true

# Wildcard at both ends

spec.hasFilters() == true
true == true
spec.matches( tcA ) == false
false == false
spec.matches( tcB ) == false
false == false
spec.matches( tcC ) == true
true == true
spec.matches( tcD ) == true
true == true
parseTestSpec( "*a*" ).matches( tcA ) == true
true == true

# Redundant wildcard at the start

spec.hasFilters() == true
true == true
spec.matches( tcA ) == true
true == true
spec.matches( tcB ) == false
false == false

# Redundant wildcard at the end

spec.hasFilters() == true
true == true
spec.matches( tcA ) == true
true == true
spec.matches( tcB ) == false
false == false

# Redundant wildcard at both ends

spec.hasFilters() == true
true == true
spec.matches( tcA ) == true
true == true
spec.matches( tcB ) == false
false == false

# Wildcard at both ends, redundant at start

spec.hasFilters() == true
true == true
spec.matches( tcA ) == false
false == false
spec.matches( tcB ) == false
false == false
spec.matches( tcC ) == true
true == true
spec.matches( tcD ) == true
true == true

# Just wildcard

spec.hasFilters() == true
true == true
spec.matches( tcA ) == true
true == true
spec.matches( tcB ) == true
true == true
spec.matches( tcC ) == true
true == true
spec.matches( tcD ) == true
true == true

# Single tag

spec.hasFilters() == true
true == true
spec.matches( tcA ) == false
false == false
spec.matches( tcB ) == true
true == true
spec.matches( tcC ) == false
false == false

# Single tag, two matches

spec.hasFilters() == true
true == true
spec.matches( tcA ) == false
false == false
spec.matches( tcB ) == true
true == true
spec.matches( tcC ) == true
true == true

# Two tags

spec.hasFilters() == true
true == true
spec.matches( tcA ) == false
false == false
spec.matches( tcB ) == false
false == false
spec.matches( tcC ) == true
true == true

# Two tags, spare separated

spec.hasFilters() == true
true == true
spec.matches( tcA ) == false
false == false
spec.matches( tcB ) == false
false == false
spec.matches( tcC ) == true
true == true

# Wildcarded name and tag

spec.hasFilters() == true
true == true
spec.matches( tcA ) == false
false == false
spec.matches( tcB ) == false
false == false
spec.matches( tcC ) == true
true == true
spec.matches( tcD ) == false
false == false

# Single tag exclusion

spec.hasFilters() == true
true == true
spec.matches( tcA ) == true
true == true
spec.matches( tcB ) == false
false == false
spec.matches( tcC ) == true
true == true

# One tag exclusion and one tag inclusion

spec.hasFilters() == true
true == true
spec.matches( tcA ) == false
false == false
spec.matches( tcB ) == true
true == true
spec.matches( tcC ) == false
false == false

# One tag exclusion and one wldcarded name inclusion

spec.hasFilters() == true
true == true
spec.matches( tcA ) == false
false == false
spec.matches( tcB ) == false
false == false
spec.matches( tcC ) == false
false == false
spec.matches( tcD ) == true
true == true

# One tag exclusion, using exclude:, and one wldcarded name inclusion

spec.hasFilters() == true
true == true
spec.matches( tcA ) == false
false == false
spec.matches( tcB ) == false
false == false
spec.matches( tcC ) == false
false == false
spec.matches( tcD ) == true
true == true

# name exclusion

spec.hasFilters() == true
true == true
spec.matches( tcA ) == true
true == true
spec.matches( tcB ) == false
false == false
spec.matches( tcC ) == true
true == true
spec.matches( tcD ) == true
true == true

# wildcarded name exclusion

spec.hasFilters() == true
true == true
spec.matches( tcA ) == true
true == true
spec.matches( tcB ) == true
true == true
spec.matches( tcC ) == false
false == false
spec.matches( tcD ) == false
false == false

# wildcarded name exclusion with tag inclusion

spec.hasFilters() == true
true == true
spec.matches( tcA ) == true
true == true
spec.matches( tcB ) == true
true == true
spec.matches( tcC ) == true
true == true
spec.matches( tcD ) == false
false == false

# wildcarded name exclusion, using exclude:, with tag inclusion

spec.hasFilters() == true
true == true
spec.matches( tcA ) == true
true == true
spec.matches( tcB ) == true
true == true
spec.matches( tcC ) == true
true == true
spec.matches( tcD ) == false
false == false

# two wildcarded names

spec.hasFilters() == true
true == true
spec.matches( tcA ) == false
false == false
spec.matches( tcB ) == false
false == false
spec.matches( tcC ) == true
true == true
spec.matches( tcD ) == false
false == false

# empty tag

spec.hasFilters() == false
false == false
spec.matches( tcA ) == false
false == false
spec.matches( tcB ) == false
false == false
spec.matches( tcC ) == false
false == false
spec.matches( tcD ) == false
false == false

# empty quoted name

spec.hasFilters() == false
false == false
spec.matches( tcA ) == false
false == false
spec.matches( tcB ) == false
false == false
spec.matches( tcC ) == false
false == false
spec.matches( tcD ) == false
false == false

# quoted string followed by tag exclusion

spec.hasFilters() == true
true == true
spec.matches( tcA ) == false
false == false
spec.matches( tcB ) == false
false == false
spec.matches( tcC ) == false
false == false
spec.matches( tcD ) == true
true == true

# Leading and trailing spaces in test spec

spec.matches( fakeTestCase( " aardvark " ) )
true
spec.matches( fakeTestCase( " aardvark" ) )
true
spec.matches( fakeTestCase( " aardvark " ) )
true
spec.matches( fakeTestCase( "aardvark " ) )
true
spec.matches( fakeTestCase( "aardvark" ) )
true

# Leading and trailing spaces in test name

spec.matches( fakeTestCase( " aardvark " ) )
true
spec.matches( fakeTestCase( " aardvark" ) )
true
spec.matches( fakeTestCase( " aardvark " ) )
true
spec.matches( fakeTestCase( "aardvark " ) )
true
spec.matches( fakeTestCase( "aardvark" ) )
true

# Shortened hide tags are split apart when parsing

spec.matches(fakeTestCase("hidden and foo", "[.][foo]"))
true
!(spec.matches(fakeTestCase("only foo", "[foo]")))
!false

# Shortened hide tags also properly handle exclusion

!(spec.matches(fakeTestCase("hidden and foo", "[.][foo]")))
!false
!(spec.matches(fakeTestCase("only foo", "[foo]")))
!false
!(spec.matches(fakeTestCase("only hidden", "[.]")))
!false
spec.matches(fakeTestCase("neither foo nor hidden", "[bar]"))
true
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.reporterName == "console"
"console" == "console"
!(cfg.hasTestFilters())
!false

# 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

cli.parse({"test", "-r", "console"})
{?}
config.reporterName == "console"
"console" == "console"

# reporter

## -r/xml

cli.parse({"test", "-r", "xml"})
{?}
config.reporterName == "xml"
"xml" == "xml"

# reporter

## --reporter/junit

cli.parse({"test", "--reporter", "junit"})
{?}
config.reporterName == "junit"
"junit" == "junit"

# reporter

## Only one reporter is accepted

!(cli.parse({ "test", "-r", "xml", "-r", "junit" }))
!{?}

# reporter

## must match one of the available ones

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

# 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(), Contains("convert") && Contains("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(), Contains("never") && Contains("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.outputFilename == "filename.ext"
"filename.ext" == "filename.ext"

# output filename

## --out

cli.parse({"test", "--out", "filename.ext"})
{?}
config.outputFilename == "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.useColour == UseColour::Auto
0 == 0

# use-colour

## auto

cli.parse({"test", "--use-colour", "auto"})
{?}
config.useColour == UseColour::Auto
0 == 0

# use-colour

## yes

cli.parse({"test", "--use-colour", "yes"})
{?}
config.useColour == UseColour::Yes
1 == 1

# use-colour

## no

cli.parse({"test", "--use-colour", "no"})
{?}
config.useColour == UseColour::No
2 == 2

# use-colour

## error

!result
true
result.errorMessage(), Contains( "colour mode must be one of" )
"colour mode must be one of: auto, yes or no. 'wrong' 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::Detail::Approx(0.99)
0.99 == Approx( 0.99 )

# 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::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
actual, !UnorderedEquals(expected)
{ 'a', 'b' } not UnorderedEquals: { 'c', 'b' }

# 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
A string sent directly to stdout
A string sent directly to stderr A string sent to stderr via clog
d == Approx( 1.23 )
1.23 == Approx( 1.23 )
d != Approx( 1.22 )
1.23 != Approx( 1.22 )
d != Approx( 1.24 )
1.23 != Approx( 1.24 )
d == 1.23_a
1.23 == Approx( 1.23 )
d != 1.22_a
1.23 != Approx( 1.22 )
Approx( d ) == 1.23
Approx( 1.23 ) == 1.23
Approx( d ) != 1.22
Approx( 1.23 ) != 1.22
Approx( d ) != 1.24
Approx( 1.23 ) != 1.24

# 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(), Contains("string")
"this string contains 'abc' as a substring" contains: "string"
testStringForMatching(), Contains("string", Catch::CaseSensitive::No)
"this string contains 'abc' as a substring" contains: "string" (case insensitive)
testStringForMatching(), Contains("abc")
"this string contains 'abc' as a substring" contains: "abc"
testStringForMatching(), Contains("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
empty.isNullTerminated()
true
std::strcmp( empty.c_str(), "" ) == 0
0 == 0

# From string literal

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

# From sub-string

original == "original"
original == "original"
!(original.isNullTerminated())
!false
original.c_str()
original.c_str()
original.data()
original.data()

# 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.c_str(), "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.c_str(), "world!") == 0
0 == 0

# Comparisons are deep

(char*)buffer1 != (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

# Simple constructors

# UDL construction

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, Contains( "[@zzz]" )
"error: tag alias, '[@zzz]' already registered. First seen at: file:2 Redefined at: file:10" contains: "[@zzz]"
what, Contains( "file" )
"error: tag alias, '[@zzz]' already registered. First seen at: file:2 Redefined at: file:10" contains: "file"
what, Contains( "2" )
"error: tag alias, '[@zzz]' already registered. First seen at: file:2 Redefined at: file:10" contains: "2"
what, Contains( "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 ) )
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
sizeof(TestType) > 0
1 > 0
sizeof(TestType) > 0
4 > 0
sizeof(TestType) > 0
1 > 0
sizeof(TestType) > 0
4 > 0
sizeof(TestType) > 0
4 > 0
sizeof(TestType) > 0
1 > 0
sizeof(TestType) > 0
4 > 0
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
0x<hex digits> == bit30and31
3221225472 (0x<hex digits>) == 3221225472
1 == 2
1 == 2
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
3.14
d == approx( 1.23 )
1.23 == Approx( 1.23 )
d == approx( 1.22 )
1.23 == Approx( 1.22 )
d == approx( 1.24 )
1.23 == Approx( 1.24 )
d != approx( 1.25 )
1.23 != Approx( 1.25 )
approx( d ) == 1.23
Approx( 1.23 ) == 1.23
approx( d ) == 1.22
Approx( 1.23 ) == 1.22
approx( d ) == 1.24
Approx( 1.23 ) == 1.24
approx( d ) != 1.25
Approx( 1.23 ) != 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

unexpected exception

Uncomment the code in this test to check that it gives a sensible compiler error

Uncomment the code in this test to check that it gives a sensible compiler error

# 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]"
testcase.tags, VectorContains(std::string(".")) && VectorContains(std::string("!hide"))
{ "!hide", "." } ( Contains: "." and Contains: "!hide" )
testcase.tags, VectorContains(std::string(".")) && VectorContains(std::string("!hide"))
{ "!hide", "." } ( Contains: "." and Contains: "!hide" )
testcase.tags, VectorContains(std::string(".")) && VectorContains(std::string("!hide"))
{ "!hide", ".", "foo" } ( Contains: "." and Contains: "!hide" )
Catch::Detail::stringify( empty ) == "{ }"
"{ }" == "{ }"
Catch::Detail::stringify( oneValue ) == "{ 42 }"
"{ 42 }" == "{ 42 }"
Catch::Detail::stringify( twoValues ) == "{ 42, 250 }"
"{ 42, 250 }" == "{ 42, 250 }"
x == 0
0 == 0
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
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

# c

## d (leaf)

# c

## e (leaf)

# f (leaf)

loose text artifact
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
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
s == "7"
"7" == "7"
ti == typeid(int)
{?} == {?}
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"

# escape '

Catch::replaceInPlace(s, "'", "|'")
true
s == "didn|'t"
"didn|'t" == "didn|'t"
3
false
false
hi
i := 7
false
false
testcase.tags, Catch::VectorContains(std::string("magic-tag")) && Catch::VectorContains(std::string("."))
{ "!hide", ".", "magic-tag" } ( Contains: "magic-tag" and Contains: "." )
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

# 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 } }"
std::string( "first" ) == "second"
"first" == "second"
::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
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
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.2f" == ::Catch::Detail::stringify(float(1.2))
"1.2f" == "1.2f"
"{ 1.2f, 0 }" == ::Catch::Detail::stringify(type{1.2f,0})
"{ 1.2f, 0 }" == "{ 1.2f, 0 }"
"{ 0 }" == ::Catch::Detail::stringify(type{0})
"{ 0 }" == "{ 0 }"
"{ 0, 42, \"Catch me\" }" == ::Catch::Detail::stringify(value)
"{ 0, 42, "Catch me" }" == "{ 0, 42, "Catch me" }"
"{ \"hello\", \"world\" }" == ::Catch::Detail::stringify(type{"hello","world"})
"{ "hello", "world" }" == "{ "hello", "world" }"
"{ { 42 }, { }, 1.2f }" == ::Catch::Detail::stringify(value)
"{ { 42 }, { }, 1.2f }" == "{ { 42 }, { }, 1.2f }"
::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

# 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: &&&"""<<<&"<<&"