Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/kyua/utils/format/formatter_test.cpp
48178 views
1
// Copyright 2010 The Kyua Authors.
2
// All rights reserved.
3
//
4
// Redistribution and use in source and binary forms, with or without
5
// modification, are permitted provided that the following conditions are
6
// met:
7
//
8
// * Redistributions of source code must retain the above copyright
9
// notice, this list of conditions and the following disclaimer.
10
// * Redistributions in binary form must reproduce the above copyright
11
// notice, this list of conditions and the following disclaimer in the
12
// documentation and/or other materials provided with the distribution.
13
// * Neither the name of Google Inc. nor the names of its contributors
14
// may be used to endorse or promote products derived from this software
15
// without specific prior written permission.
16
//
17
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
29
#include "utils/format/formatter.hpp"
30
31
#include <ostream>
32
33
#include <atf-c++.hpp>
34
35
#include "utils/format/exceptions.hpp"
36
#include "utils/format/macros.hpp"
37
38
namespace format = utils::format;
39
40
41
namespace {
42
43
44
/// Wraps an integer in a C++ class.
45
///
46
/// This custom type exists to ensure that we can feed arbitrary objects that
47
/// support operator<< to the formatter;
48
class int_wrapper {
49
/// The wrapped integer.
50
int _value;
51
52
public:
53
/// Constructs a new wrapper.
54
///
55
/// \param value_ The value to wrap.
56
int_wrapper(const int value_) : _value(value_)
57
{
58
}
59
60
/// Returns the wrapped value.
61
///
62
/// \return An integer.
63
int
64
value(void) const
65
{
66
return _value;
67
}
68
};
69
70
71
/// Writes a wrapped integer into an output stream.
72
///
73
/// \param output The output stream into which to place the integer.
74
/// \param wrapper The wrapped integer.
75
///
76
/// \return The output stream.
77
std::ostream&
78
operator<<(std::ostream& output, const int_wrapper& wrapper)
79
{
80
return (output << wrapper.value());
81
}
82
83
84
} // anonymous namespace
85
86
87
/// Calls ATF_REQUIRE_EQ on an expected string and a formatter.
88
///
89
/// This is pure syntactic sugar to avoid calling the str() method on all the
90
/// individual tests below, which results in very long lines that require
91
/// wrapping and clutter readability.
92
///
93
/// \param expected The expected string generated by the formatter.
94
/// \param formatter The formatter to test.
95
#define EQ(expected, formatter) ATF_REQUIRE_EQ(expected, (formatter).str())
96
97
98
ATF_TEST_CASE_WITHOUT_HEAD(no_fields);
99
ATF_TEST_CASE_BODY(no_fields)
100
{
101
EQ("Plain string", F("Plain string"));
102
}
103
104
105
ATF_TEST_CASE_WITHOUT_HEAD(one_field);
106
ATF_TEST_CASE_BODY(one_field)
107
{
108
EQ("foo", F("%sfoo") % "");
109
EQ(" foo", F("%sfoo") % " ");
110
EQ("foo ", F("foo %s") % "");
111
EQ("foo bar", F("foo %s") % "bar");
112
EQ("foo bar baz", F("foo %s baz") % "bar");
113
EQ("foo %s %s", F("foo %s %s") % "%s" % "%s");
114
}
115
116
117
ATF_TEST_CASE_WITHOUT_HEAD(many_fields);
118
ATF_TEST_CASE_BODY(many_fields)
119
{
120
EQ("", F("%s%s") % "" % "");
121
EQ("foo", F("%s%s%s") % "" % "foo" % "");
122
EQ("some 5 text", F("%s %s %s") % "some" % 5 % "text");
123
EQ("f%s 5 text", F("%s %s %s") % "f%s" % 5 % "text");
124
}
125
126
127
ATF_TEST_CASE_WITHOUT_HEAD(escape);
128
ATF_TEST_CASE_BODY(escape)
129
{
130
EQ("%", F("%%"));
131
EQ("% %", F("%% %%"));
132
EQ("%% %%", F("%%%% %%%%"));
133
134
EQ("foo %", F("foo %%"));
135
EQ("foo bar %", F("foo %s %%") % "bar");
136
EQ("foo % bar", F("foo %% %s") % "bar");
137
138
EQ("foo %%", F("foo %s") % "%%");
139
EQ("foo a%%b", F("foo a%sb") % "%%");
140
EQ("foo a%%b", F("foo %s") % "a%%b");
141
142
EQ("foo % bar %%", F("foo %% %s %%%%") % "bar");
143
}
144
145
146
ATF_TEST_CASE_WITHOUT_HEAD(extra_args_error);
147
ATF_TEST_CASE_BODY(extra_args_error)
148
{
149
using format::extra_args_error;
150
151
ATF_REQUIRE_THROW(extra_args_error, F("foo") % "bar");
152
ATF_REQUIRE_THROW(extra_args_error, F("foo %%") % "bar");
153
ATF_REQUIRE_THROW(extra_args_error, F("foo %s") % "bar" % "baz");
154
ATF_REQUIRE_THROW(extra_args_error, F("foo %s") % "%s" % "bar");
155
ATF_REQUIRE_THROW(extra_args_error, F("%s foo %s") % "bar" % "baz" % "foo");
156
157
try {
158
F("foo %s %s") % "bar" % "baz" % "something extra";
159
fail("extra_args_error not raised");
160
} catch (const extra_args_error& e) {
161
ATF_REQUIRE_EQ("foo %s %s", e.format());
162
ATF_REQUIRE_EQ("something extra", e.arg());
163
}
164
}
165
166
167
ATF_TEST_CASE_WITHOUT_HEAD(format__class);
168
ATF_TEST_CASE_BODY(format__class)
169
{
170
EQ("foo bar", F("%s") % std::string("foo bar"));
171
EQ("3", F("%s") % int_wrapper(3));
172
}
173
174
175
ATF_TEST_CASE_WITHOUT_HEAD(format__pointer);
176
ATF_TEST_CASE_BODY(format__pointer)
177
{
178
EQ("0xcafebabe", F("%s") % reinterpret_cast< void* >(0xcafebabe));
179
EQ("foo bar", F("%s") % "foo bar");
180
}
181
182
183
ATF_TEST_CASE_WITHOUT_HEAD(format__bool);
184
ATF_TEST_CASE_BODY(format__bool)
185
{
186
EQ("true", F("%s") % true);
187
EQ("false", F("%s") % false);
188
}
189
190
191
ATF_TEST_CASE_WITHOUT_HEAD(format__char);
192
ATF_TEST_CASE_BODY(format__char)
193
{
194
EQ("Z", F("%s") % 'Z');
195
}
196
197
198
ATF_TEST_CASE_WITHOUT_HEAD(format__float);
199
ATF_TEST_CASE_BODY(format__float)
200
{
201
EQ("3", F("%s") % 3.0);
202
EQ("3.0", F("%.1s") % 3.0);
203
EQ("3.0", F("%0.1s") % 3.0);
204
EQ(" 15.600", F("%8.3s") % 15.6);
205
EQ("01.52", F("%05.2s") % 1.52);
206
}
207
208
209
ATF_TEST_CASE_WITHOUT_HEAD(format__int);
210
ATF_TEST_CASE_BODY(format__int)
211
{
212
EQ("3", F("%s") % 3);
213
EQ("3", F("%0s") % 3);
214
EQ(" -123", F("%5s") % -123);
215
EQ("00078", F("%05s") % 78);
216
}
217
218
219
ATF_TEST_CASE_WITHOUT_HEAD(format__error);
220
ATF_TEST_CASE_BODY(format__error)
221
{
222
using format::bad_format_error;
223
224
ATF_REQUIRE_THROW_RE(bad_format_error, "Trailing %", F("%"));
225
ATF_REQUIRE_THROW_RE(bad_format_error, "Trailing %", F("f%"));
226
ATF_REQUIRE_THROW_RE(bad_format_error, "Trailing %", F("f%%%"));
227
ATF_REQUIRE_THROW_RE(bad_format_error, "Trailing %", F("ab %s cd%") % "cd");
228
229
ATF_REQUIRE_THROW_RE(bad_format_error, "Invalid width", F("%1bs"));
230
231
ATF_REQUIRE_THROW_RE(bad_format_error, "Invalid precision", F("%.s"));
232
ATF_REQUIRE_THROW_RE(bad_format_error, "Invalid precision", F("%0.s"));
233
ATF_REQUIRE_THROW_RE(bad_format_error, "Invalid precision", F("%123.s"));
234
ATF_REQUIRE_THROW_RE(bad_format_error, "Invalid precision", F("%.12bs"));
235
236
ATF_REQUIRE_THROW_RE(bad_format_error, "Unterminated", F("%c") % 'Z');
237
ATF_REQUIRE_THROW_RE(bad_format_error, "Unterminated", F("%d") % 5);
238
ATF_REQUIRE_THROW_RE(bad_format_error, "Unterminated", F("%.1f") % 3);
239
ATF_REQUIRE_THROW_RE(bad_format_error, "Unterminated", F("%d%s") % 3 % "a");
240
241
try {
242
F("foo %s%") % "bar";
243
fail("bad_format_error not raised");
244
} catch (const bad_format_error& e) {
245
ATF_REQUIRE_EQ("foo %s%", e.format());
246
}
247
}
248
249
250
ATF_INIT_TEST_CASES(tcs)
251
{
252
ATF_ADD_TEST_CASE(tcs, no_fields);
253
ATF_ADD_TEST_CASE(tcs, one_field);
254
ATF_ADD_TEST_CASE(tcs, many_fields);
255
ATF_ADD_TEST_CASE(tcs, escape);
256
ATF_ADD_TEST_CASE(tcs, extra_args_error);
257
258
ATF_ADD_TEST_CASE(tcs, format__class);
259
ATF_ADD_TEST_CASE(tcs, format__pointer);
260
ATF_ADD_TEST_CASE(tcs, format__bool);
261
ATF_ADD_TEST_CASE(tcs, format__char);
262
ATF_ADD_TEST_CASE(tcs, format__float);
263
ATF_ADD_TEST_CASE(tcs, format__int);
264
ATF_ADD_TEST_CASE(tcs, format__error);
265
}
266
267