aboutsummaryrefslogtreecommitdiffhomepage
path: root/tests/SelfTest/IntrospectiveTests/Details.tests.cpp
blob: d7175756b5c6b212ebdacf43afbdc19ed137f8ea (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172

//              Copyright Catch2 Authors
// Distributed under the Boost Software License, Version 1.0.
//   (See accompanying file LICENSE.txt or copy at
//        https://www.boost.org/LICENSE_1_0.txt)

// SPDX-License-Identifier: BSL-1.0

#include <catch2/catch_test_macros.hpp>
#include <catch2/internal/catch_enforce.hpp>
#include <catch2/internal/catch_case_insensitive_comparisons.hpp>
#include <catch2/internal/catch_optional.hpp>

#include <helpers/type_with_lit_0_comparisons.hpp>

#if defined(_MSC_VER)
#pragma warning(push)
#pragma warning(disable:4702) // unreachable code in the macro expansions
#endif

TEST_CASE("Check that our error handling macros throw the right exceptions", "[!throws][internals][approvals]") {
    REQUIRE_THROWS_AS(CATCH_INTERNAL_ERROR(""), std::logic_error);
    REQUIRE_THROWS_AS(CATCH_ERROR(""), std::domain_error);
    REQUIRE_THROWS_AS(CATCH_RUNTIME_ERROR(""), std::runtime_error);
    REQUIRE_THROWS_AS([](){CATCH_ENFORCE(false, "");}(), std::domain_error);
    REQUIRE_NOTHROW([](){CATCH_ENFORCE(true, "");}());
}

#if defined(_MSC_VER)
#pragma warning(pop) // unreachable code in the macro expansions
#endif

TEST_CASE("CaseInsensitiveLess is case insensitive", "[comparisons][string-case]") {
    Catch::Detail::CaseInsensitiveLess lt;
    SECTION( "Degenerate cases" ) {
        REQUIRE( lt( "", "a" ) );
        REQUIRE_FALSE( lt( "a", "a" ) );
        REQUIRE_FALSE( lt( "", "" ) );
    }
    SECTION("Plain comparisons") {
        REQUIRE( lt( "a", "b" ) );
        REQUIRE( lt( "a", "B" ) );
        REQUIRE( lt( "A", "b" ) );
        REQUIRE( lt( "A", "B" ) );
    }
}

TEST_CASE( "CaseInsensitiveEqualsTo is case insensitive",
           "[comparisons][string-case]" ) {
    Catch::Detail::CaseInsensitiveEqualTo eq;
    SECTION( "Degenerate cases" ) {
        REQUIRE( eq( "", "" ) );
        REQUIRE_FALSE( eq( "", "a" ) );
    }
    SECTION( "Plain comparisons" ) {
        REQUIRE( eq( "a", "a" ) );
        REQUIRE( eq( "a", "A" ) );
        REQUIRE( eq( "A", "a" ) );
        REQUIRE( eq( "A", "A" ) );
        REQUIRE_FALSE( eq( "a", "b" ) );
        REQUIRE_FALSE( eq( "a", "B" ) );
    }
}

TEST_CASE("Optional comparison ops", "[optional][approvals]") {
    using Catch::Optional;

    Optional<int> a, b;

    SECTION( "Empty optionals are equal" ) {
        REQUIRE( a == b );
        REQUIRE_FALSE( a != b );
    }
    SECTION( "Empty and non-empty optionals are never equal" ) {
        a = 1;
        REQUIRE_FALSE( a == b );
        REQUIRE( a != b );
    }
    SECTION(
        "non-empty optionals are equal if the contained elements are equal") {
        a = 1;
        b = 2;
        REQUIRE( a != b );
        REQUIRE_FALSE( a == b );

        a = 2;
        REQUIRE( a == b );
        REQUIRE_FALSE( a != b );
    }
}

namespace {
    struct MoveChecker {
        bool has_moved = false;
        MoveChecker() = default;
        MoveChecker( MoveChecker const& rhs ) = default;
        MoveChecker& operator=( MoveChecker const& rhs ) = default;
        MoveChecker( MoveChecker&& rhs ) noexcept { rhs.has_moved = true; }
        MoveChecker& operator=( MoveChecker&& rhs ) noexcept {
            rhs.has_moved = true;
            return *this;
        }
    };
}

TEST_CASE( "Optional supports move ops", "[optional][approvals]" ) {
    using Catch::Optional;
    MoveChecker a;
    Optional<MoveChecker> opt_A( a );
    REQUIRE_FALSE( a.has_moved );
    REQUIRE_FALSE( opt_A->has_moved );

    SECTION( "Move construction from element" ) {
        Optional<MoveChecker> opt_B( CATCH_MOVE( a ) );
        REQUIRE( a.has_moved );
    }
    SECTION( "Move assignment from element" ) {
        opt_A = CATCH_MOVE( a );
        REQUIRE( a.has_moved );
    }
    SECTION( "Move construction from optional" ) {
        Optional<MoveChecker> opt_B( CATCH_MOVE( opt_A ) );
        REQUIRE( opt_A->has_moved );
    }
    SECTION( "Move assignment from optional" ) {
        Optional<MoveChecker> opt_B( opt_A );
        REQUIRE_FALSE( opt_A->has_moved );
        opt_B = CATCH_MOVE( opt_A );
        REQUIRE( opt_A->has_moved );
    }
}

TEST_CASE( "Decomposer checks that the argument is 0 when handling "
           "only-0-comparable types",
           "[decomposition][approvals]" ) {
    TypeWithLit0Comparisons t{};

    CATCH_INTERNAL_START_WARNINGS_SUPPRESSION
    CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS

    REQUIRE_THROWS( Catch::Decomposer{} <= t == 42 );
    REQUIRE_THROWS( Catch::Decomposer{} <= 42 == t );
    REQUIRE_NOTHROW( Catch::Decomposer{} <= t == 0 );
    REQUIRE_NOTHROW( Catch::Decomposer{} <= 0 == t );

    REQUIRE_THROWS( Catch::Decomposer{} <= t != 42 );
    REQUIRE_THROWS( Catch::Decomposer{} <= 42 != t );
    REQUIRE_NOTHROW( Catch::Decomposer{} <= t != 0 );
    REQUIRE_NOTHROW( Catch::Decomposer{} <= 0 != t );

    REQUIRE_THROWS( Catch::Decomposer{} <= t < 42 );
    REQUIRE_THROWS( Catch::Decomposer{} <= 42 < t );
    REQUIRE_NOTHROW( Catch::Decomposer{} <= t < 0 );
    REQUIRE_NOTHROW( Catch::Decomposer{} <= 0 < t );

    REQUIRE_THROWS( Catch::Decomposer{} <= t <= 42 );
    REQUIRE_THROWS( Catch::Decomposer{} <= 42 <= t );
    REQUIRE_NOTHROW( Catch::Decomposer{} <= t <= 0 );
    REQUIRE_NOTHROW( Catch::Decomposer{} <= 0 <= t );

    REQUIRE_THROWS( Catch::Decomposer{} <= t > 42 );
    REQUIRE_THROWS( Catch::Decomposer{} <= 42 > t );
    REQUIRE_NOTHROW( Catch::Decomposer{} <= t > 0 );
    REQUIRE_NOTHROW( Catch::Decomposer{} <= 0 > t );

    REQUIRE_THROWS( Catch::Decomposer{} <= t >= 42 );
    REQUIRE_THROWS( Catch::Decomposer{} <= 42 >= t );
    REQUIRE_NOTHROW( Catch::Decomposer{} <= t >= 0 );
    REQUIRE_NOTHROW( Catch::Decomposer{} <= 0 >= t );

    CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION
}