-
-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathCustomString.cpp
198 lines (162 loc) · 4.61 KB
/
CustomString.cpp
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
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
// Copyright Dominic (DNKpp) Koepke 2024 - 2025.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// https://www.boost.org/LICENSE_1_0.txt)
#include "mimic++/Mock.hpp"
#include "mimic++/String.hpp"
namespace
{
//! [MyString]
class MyString
{
public:
explicit MyString(std::string str) noexcept
: m_Inner{std::move(str)}
{
}
std::string_view view() const noexcept
{
return std::string_view{m_Inner};
}
private:
std::string m_Inner{};
};
//! [MyString]
}
//! [MyString trait]
template <>
struct mimicpp::string_traits<MyString>
{
// must be the underlying char type
using char_t = char;
// must be a std::ranges::view like type and must be contiguous
using view_t = std::string_view;
// must construct a view object
[[nodiscard]]
static view_t view(const MyString& str) noexcept
{
return str.view();
}
};
//! [MyString trait]
TEST_CASE(
"mimic++ supports custom strings.",
"[example][example::string]")
{
//! [MyString example]
STATIC_REQUIRE(mimicpp::string<MyString>);
namespace expect = mimicpp::expect;
namespace matches = mimicpp::matches;
using matches::_;
mimicpp::Mock<void(MyString)> mock{};
SCOPED_EXP mock.expect_call("Hello, World!");
SCOPED_EXP mock.expect_call(matches::str::starts_with("Hi", mimicpp::case_insensitive));
mock(MyString{"Hello, World!"}); // matches the first expectation
mock(MyString{"hI, mimic++"}); // matches the second expectation (case-insensitive).
//! [MyString example]
}
//! [custom_char]
struct my_char
{
char c{};
bool operator==(const my_char&) const = default;
};
//! [custom_char]
//! [custom_string]
class ComplexString
{
public:
explicit ComplexString(std::vector<my_char> str) noexcept
: m_Inner{std::move(str)}
{
}
[[nodiscard]]
auto begin() const noexcept
{
return m_Inner.cbegin();
}
[[nodiscard]]
auto end() const noexcept
{
return m_Inner.cend();
}
private:
std::vector<my_char> m_Inner{};
};
//! [custom_string]
//! [custom_char trait]
template <>
struct mimicpp::is_character<my_char>
: public std::true_type
{
};
//! [custom_char trait]
//! [custom_string traits]
template <>
struct mimicpp::string_traits<ComplexString>
{
// must be the underlying char type
using char_t = my_char;
// must be a std::ranges::view like type and must be contiguous
using view_t = std::span<const char_t>;
// must construct a view object
[[nodiscard]]
static view_t view(const ComplexString& str) noexcept
{
return std::span{
str.begin(),
str.end()};
}
};
//! [custom_string traits]
TEST_CASE(
"mimic++ supports complex custom strings.",
"[example][example::string]")
{
//! [custom_string example]
STATIC_REQUIRE(mimicpp::string<ComplexString>);
mimicpp::Mock<void(ComplexString)> mock{};
ComplexString s{
{{'A'}, {'B'}, {'C'}}
};
SCOPED_EXP mock.expect_call(s);
mock(s);
//! [custom_string example]
}
//! [custom_char case-folding]
template <>
struct mimicpp::string_case_fold_converter<my_char>
{
// the string_case_fold_converter must expect the string's view-type and should return
// a forward-range with the underlying char-type.
[[nodiscard]]
auto operator()(string_view_t<ComplexString> view) const
{
return view
| std::views::transform(
[](const my_char c) {
// see notes of https://en.cppreference.com/w/cpp/string/byte/toupper
return my_char{
static_cast<char>(
static_cast<unsigned char>(std::toupper(c.c)))};
});
}
};
//! [custom_char case-folding]
TEST_CASE(
"mimic++ supports case-folding for custom char-types.",
"[example][example::string]")
{
//! [custom_string case-insensitive example]
STATIC_REQUIRE(mimicpp::case_foldable_string<ComplexString>);
namespace matches = mimicpp::matches;
mimicpp::Mock<void(ComplexString)> mock{};
SCOPED_EXP mock.expect_call(matches::str::starts_with(ComplexString{
{{'A'}, {'B'}, {'C'}}
},
mimicpp::case_insensitive));
mock(ComplexString{
{{'a'}, {'B'}, {'c'}}
});
//! [custom_string case-insensitive example]
}