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