1 // Copyright 2012 The Kyua Authors.
2 // All rights reserved.
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are
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.
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.
29 #include "utils/text/operations.ipp"
36 #include <atf-c++.hpp>
38 #include "utils/text/exceptions.hpp"
40 namespace text = utils::text;
46 /// Tests text::refill() on an input string with a range of widths.
48 /// \param expected The expected refilled paragraph.
49 /// \param input The input paragraph to be refilled.
50 /// \param first_width The first width to validate.
51 /// \param last_width The last width to validate (inclusive).
53 refill_test(const char* expected, const char* input,
54 const std::size_t first_width, const std::size_t last_width)
56 for (std::size_t width = first_width; width <= last_width; ++width) {
57 const std::vector< std::string > lines = text::split(expected, '\n');
58 std::cout << "Breaking at width " << width << '\n';
59 ATF_REQUIRE_EQ(expected, text::refill_as_string(input, width));
60 ATF_REQUIRE(lines == text::refill(input, width));
65 } // anonymous namespace
68 ATF_TEST_CASE_WITHOUT_HEAD(escape_xml__empty);
69 ATF_TEST_CASE_BODY(escape_xml__empty)
71 ATF_REQUIRE_EQ("", text::escape_xml(""));
75 ATF_TEST_CASE_WITHOUT_HEAD(escape_xml__no_escaping);
76 ATF_TEST_CASE_BODY(escape_xml__no_escaping)
78 ATF_REQUIRE_EQ("a", text::escape_xml("a"));
79 ATF_REQUIRE_EQ("Some text!", text::escape_xml("Some text!"));
80 ATF_REQUIRE_EQ("\n\t\r", text::escape_xml("\n\t\r"));
84 ATF_TEST_CASE_WITHOUT_HEAD(escape_xml__some_escaping);
85 ATF_TEST_CASE_BODY(escape_xml__some_escaping)
87 ATF_REQUIRE_EQ("'", text::escape_xml("'"));
89 ATF_REQUIRE_EQ("foo "bar& <tag> yay' baz",
90 text::escape_xml("foo \"bar& <tag> yay' baz"));
92 ATF_REQUIRE_EQ(""&<>'", text::escape_xml("\"&<>'"));
93 ATF_REQUIRE_EQ("&&&", text::escape_xml("&&&"));
94 ATF_REQUIRE_EQ("&#8;&#11;", text::escape_xml("\b\v"));
95 ATF_REQUIRE_EQ("\t&#127;BAR&", text::escape_xml("\t\x7f""BAR&"));
99 ATF_TEST_CASE_WITHOUT_HEAD(quote__empty);
100 ATF_TEST_CASE_BODY(quote__empty)
102 ATF_REQUIRE_EQ("''", text::quote("", '\''));
103 ATF_REQUIRE_EQ("##", text::quote("", '#'));
107 ATF_TEST_CASE_WITHOUT_HEAD(quote__no_escaping);
108 ATF_TEST_CASE_BODY(quote__no_escaping)
110 ATF_REQUIRE_EQ("'Some text\"'", text::quote("Some text\"", '\''));
111 ATF_REQUIRE_EQ("#Another'string#", text::quote("Another'string", '#'));
115 ATF_TEST_CASE_WITHOUT_HEAD(quote__some_escaping);
116 ATF_TEST_CASE_BODY(quote__some_escaping)
118 ATF_REQUIRE_EQ("'Some\\'text'", text::quote("Some'text", '\''));
119 ATF_REQUIRE_EQ("#Some\\#text#", text::quote("Some#text", '#'));
121 ATF_REQUIRE_EQ("'More than one\\' quote\\''",
122 text::quote("More than one' quote'", '\''));
123 ATF_REQUIRE_EQ("'Multiple quotes \\'\\'\\' together'",
124 text::quote("Multiple quotes ''' together", '\''));
126 ATF_REQUIRE_EQ("'\\'escape at the beginning'",
127 text::quote("'escape at the beginning", '\''));
128 ATF_REQUIRE_EQ("'escape at the end\\''",
129 text::quote("escape at the end'", '\''));
133 ATF_TEST_CASE_WITHOUT_HEAD(refill__empty);
134 ATF_TEST_CASE_BODY(refill__empty)
136 ATF_REQUIRE_EQ(1, text::refill("", 0).size());
137 ATF_REQUIRE(text::refill("", 0)[0].empty());
138 ATF_REQUIRE_EQ("", text::refill_as_string("", 0));
140 ATF_REQUIRE_EQ(1, text::refill("", 10).size());
141 ATF_REQUIRE(text::refill("", 10)[0].empty());
142 ATF_REQUIRE_EQ("", text::refill_as_string("", 10));
146 ATF_TEST_CASE_WITHOUT_HEAD(refill__no_changes);
147 ATF_TEST_CASE_BODY(refill__no_changes)
149 std::vector< std::string > exp_lines;
150 exp_lines.push_back("foo bar\nbaz");
152 ATF_REQUIRE(exp_lines == text::refill("foo bar\nbaz", 12));
153 ATF_REQUIRE_EQ("foo bar\nbaz", text::refill_as_string("foo bar\nbaz", 12));
155 ATF_REQUIRE(exp_lines == text::refill("foo bar\nbaz", 18));
156 ATF_REQUIRE_EQ("foo bar\nbaz", text::refill_as_string("foo bar\nbaz", 80));
160 ATF_TEST_CASE_WITHOUT_HEAD(refill__break_one);
161 ATF_TEST_CASE_BODY(refill__break_one)
163 refill_test("only break the\nfirst line", "only break the first line",
168 ATF_TEST_CASE_WITHOUT_HEAD(refill__break_one__not_first_word);
169 ATF_TEST_CASE_BODY(refill__break_one__not_first_word)
171 refill_test("first-long-word\nother\nwords", "first-long-word other words",
173 refill_test("first-long-word\nother words", "first-long-word other words",
175 refill_test("first-long-word other\nwords", "first-long-word other words",
177 refill_test("first-long-word other words", "first-long-word other words",
182 ATF_TEST_CASE_WITHOUT_HEAD(refill__break_many);
183 ATF_TEST_CASE_BODY(refill__break_many)
185 refill_test("this is a long\nparagraph to be\nsplit into\npieces",
186 "this is a long paragraph to be split into pieces",
191 ATF_TEST_CASE_WITHOUT_HEAD(refill__cannot_break);
192 ATF_TEST_CASE_BODY(refill__cannot_break)
194 refill_test("this-is-a-long-string", "this-is-a-long-string", 5, 5);
196 refill_test("this is\na-string-with-long-words",
197 "this is a-string-with-long-words", 10, 10);
201 ATF_TEST_CASE_WITHOUT_HEAD(refill__preserve_whitespace);
202 ATF_TEST_CASE_BODY(refill__preserve_whitespace)
204 refill_test("foo bar baz ", "foo bar baz ", 80, 80);
205 refill_test("foo \n bar", "foo bar", 5, 5);
207 std::vector< std::string > exp_lines;
208 exp_lines.push_back("foo \n");
209 exp_lines.push_back(" bar");
210 ATF_REQUIRE(exp_lines == text::refill("foo \n bar", 5));
211 ATF_REQUIRE_EQ("foo \n\n bar", text::refill_as_string("foo \n bar", 5));
215 ATF_TEST_CASE_WITHOUT_HEAD(join__empty);
216 ATF_TEST_CASE_BODY(join__empty)
218 std::vector< std::string > lines;
219 ATF_REQUIRE_EQ("", text::join(lines, " "));
223 ATF_TEST_CASE_WITHOUT_HEAD(join__one);
224 ATF_TEST_CASE_BODY(join__one)
226 std::vector< std::string > lines;
227 lines.push_back("first line");
228 ATF_REQUIRE_EQ("first line", text::join(lines, "*"));
232 ATF_TEST_CASE_WITHOUT_HEAD(join__several);
233 ATF_TEST_CASE_BODY(join__several)
235 std::vector< std::string > lines;
236 lines.push_back("first abc");
237 lines.push_back("second");
238 lines.push_back("and last line");
239 ATF_REQUIRE_EQ("first abc second and last line", text::join(lines, " "));
240 ATF_REQUIRE_EQ("first abc***second***and last line",
241 text::join(lines, "***"));
245 ATF_TEST_CASE_WITHOUT_HEAD(join__unordered);
246 ATF_TEST_CASE_BODY(join__unordered)
248 std::set< std::string > lines;
249 lines.insert("first");
250 lines.insert("second");
251 const std::string joined = text::join(lines, " ");
252 ATF_REQUIRE(joined == "first second" || joined == "second first");
256 ATF_TEST_CASE_WITHOUT_HEAD(split__empty);
257 ATF_TEST_CASE_BODY(split__empty)
259 std::vector< std::string > words = text::split("", ' ');
260 std::vector< std::string > exp_words;
261 ATF_REQUIRE(exp_words == words);
265 ATF_TEST_CASE_WITHOUT_HEAD(split__one);
266 ATF_TEST_CASE_BODY(split__one)
268 std::vector< std::string > words = text::split("foo", ' ');
269 std::vector< std::string > exp_words;
270 exp_words.push_back("foo");
271 ATF_REQUIRE(exp_words == words);
275 ATF_TEST_CASE_WITHOUT_HEAD(split__several__simple);
276 ATF_TEST_CASE_BODY(split__several__simple)
278 std::vector< std::string > words = text::split("foo bar baz", ' ');
279 std::vector< std::string > exp_words;
280 exp_words.push_back("foo");
281 exp_words.push_back("bar");
282 exp_words.push_back("baz");
283 ATF_REQUIRE(exp_words == words);
287 ATF_TEST_CASE_WITHOUT_HEAD(split__several__delimiters);
288 ATF_TEST_CASE_BODY(split__several__delimiters)
290 std::vector< std::string > words = text::split("XfooXXbarXXXbazXX", 'X');
291 std::vector< std::string > exp_words;
292 exp_words.push_back("");
293 exp_words.push_back("foo");
294 exp_words.push_back("");
295 exp_words.push_back("bar");
296 exp_words.push_back("");
297 exp_words.push_back("");
298 exp_words.push_back("baz");
299 exp_words.push_back("");
300 exp_words.push_back("");
301 ATF_REQUIRE(exp_words == words);
305 ATF_TEST_CASE_WITHOUT_HEAD(replace_all__empty);
306 ATF_TEST_CASE_BODY(replace_all__empty)
308 ATF_REQUIRE_EQ("", text::replace_all("", "search", "replacement"));
312 ATF_TEST_CASE_WITHOUT_HEAD(replace_all__none);
313 ATF_TEST_CASE_BODY(replace_all__none)
315 ATF_REQUIRE_EQ("string without matches",
316 text::replace_all("string without matches",
317 "WITHOUT", "replacement"));
321 ATF_TEST_CASE_WITHOUT_HEAD(replace_all__one);
322 ATF_TEST_CASE_BODY(replace_all__one)
324 ATF_REQUIRE_EQ("string replacement matches",
325 text::replace_all("string without matches",
326 "without", "replacement"));
330 ATF_TEST_CASE_WITHOUT_HEAD(replace_all__several);
331 ATF_TEST_CASE_BODY(replace_all__several)
333 ATF_REQUIRE_EQ("OO fOO bar OOf baz OO",
334 text::replace_all("oo foo bar oof baz oo",
339 ATF_TEST_CASE_WITHOUT_HEAD(to_type__ok__bool);
340 ATF_TEST_CASE_BODY(to_type__ok__bool)
342 ATF_REQUIRE( text::to_type< bool >("true"));
343 ATF_REQUIRE(!text::to_type< bool >("false"));
347 ATF_TEST_CASE_WITHOUT_HEAD(to_type__ok__numerical);
348 ATF_TEST_CASE_BODY(to_type__ok__numerical)
350 ATF_REQUIRE_EQ(12, text::to_type< int >("12"));
351 ATF_REQUIRE_EQ(18745, text::to_type< int >("18745"));
352 ATF_REQUIRE_EQ(-12345, text::to_type< int >("-12345"));
354 ATF_REQUIRE_EQ(12.0, text::to_type< double >("12"));
355 ATF_REQUIRE_EQ(12.5, text::to_type< double >("12.5"));
359 ATF_TEST_CASE_WITHOUT_HEAD(to_type__ok__string);
360 ATF_TEST_CASE_BODY(to_type__ok__string)
362 // While this seems redundant, having this particular specialization that
363 // does nothing allows callers to delegate work to to_type without worrying
364 // about the particular type being converted.
365 ATF_REQUIRE_EQ("", text::to_type< std::string >(""));
366 ATF_REQUIRE_EQ(" abcd ", text::to_type< std::string >(" abcd "));
370 ATF_TEST_CASE_WITHOUT_HEAD(to_type__empty);
371 ATF_TEST_CASE_BODY(to_type__empty)
373 ATF_REQUIRE_THROW(text::value_error, text::to_type< int >(""));
377 ATF_TEST_CASE_WITHOUT_HEAD(to_type__invalid__bool);
378 ATF_TEST_CASE_BODY(to_type__invalid__bool)
380 ATF_REQUIRE_THROW(text::value_error, text::to_type< bool >(""));
381 ATF_REQUIRE_THROW(text::value_error, text::to_type< bool >("true "));
382 ATF_REQUIRE_THROW(text::value_error, text::to_type< bool >("foo"));
386 ATF_TEST_CASE_WITHOUT_HEAD(to_type__invalid__numerical);
387 ATF_TEST_CASE_BODY(to_type__invalid__numerical)
389 ATF_REQUIRE_THROW(text::value_error, text::to_type< int >(" 3"));
390 ATF_REQUIRE_THROW(text::value_error, text::to_type< int >("3 "));
391 ATF_REQUIRE_THROW(text::value_error, text::to_type< int >("3a"));
392 ATF_REQUIRE_THROW(text::value_error, text::to_type< int >("a3"));
396 ATF_INIT_TEST_CASES(tcs)
398 ATF_ADD_TEST_CASE(tcs, escape_xml__empty);
399 ATF_ADD_TEST_CASE(tcs, escape_xml__no_escaping);
400 ATF_ADD_TEST_CASE(tcs, escape_xml__some_escaping);
402 ATF_ADD_TEST_CASE(tcs, quote__empty);
403 ATF_ADD_TEST_CASE(tcs, quote__no_escaping);
404 ATF_ADD_TEST_CASE(tcs, quote__some_escaping);
406 ATF_ADD_TEST_CASE(tcs, refill__empty);
407 ATF_ADD_TEST_CASE(tcs, refill__no_changes);
408 ATF_ADD_TEST_CASE(tcs, refill__break_one);
409 ATF_ADD_TEST_CASE(tcs, refill__break_one__not_first_word);
410 ATF_ADD_TEST_CASE(tcs, refill__break_many);
411 ATF_ADD_TEST_CASE(tcs, refill__cannot_break);
412 ATF_ADD_TEST_CASE(tcs, refill__preserve_whitespace);
414 ATF_ADD_TEST_CASE(tcs, join__empty);
415 ATF_ADD_TEST_CASE(tcs, join__one);
416 ATF_ADD_TEST_CASE(tcs, join__several);
417 ATF_ADD_TEST_CASE(tcs, join__unordered);
419 ATF_ADD_TEST_CASE(tcs, split__empty);
420 ATF_ADD_TEST_CASE(tcs, split__one);
421 ATF_ADD_TEST_CASE(tcs, split__several__simple);
422 ATF_ADD_TEST_CASE(tcs, split__several__delimiters);
424 ATF_ADD_TEST_CASE(tcs, replace_all__empty);
425 ATF_ADD_TEST_CASE(tcs, replace_all__none);
426 ATF_ADD_TEST_CASE(tcs, replace_all__one);
427 ATF_ADD_TEST_CASE(tcs, replace_all__several);
429 ATF_ADD_TEST_CASE(tcs, to_type__ok__bool);
430 ATF_ADD_TEST_CASE(tcs, to_type__ok__numerical);
431 ATF_ADD_TEST_CASE(tcs, to_type__ok__string);
432 ATF_ADD_TEST_CASE(tcs, to_type__empty);
433 ATF_ADD_TEST_CASE(tcs, to_type__invalid__bool);
434 ATF_ADD_TEST_CASE(tcs, to_type__invalid__numerical);