Home | History | Annotate | Line # | Download | only in text
      1 // Copyright 2012 Google Inc.
      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/text/operations.ipp"
     30 
     31 #include <iostream>
     32 #include <set>
     33 #include <string>
     34 #include <vector>
     35 
     36 #include <atf-c++.hpp>
     37 
     38 #include "utils/text/exceptions.hpp"
     39 
     40 namespace text = utils::text;
     41 
     42 
     43 namespace {
     44 
     45 
     46 /// Tests text::refill() on an input string with a range of widths.
     47 ///
     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).
     52 static void
     53 refill_test(const char* expected, const char* input,
     54             const std::size_t first_width, const std::size_t last_width)
     55 {
     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));
     61     }
     62 }
     63 
     64 
     65 }  // anonymous namespace
     66 
     67 
     68 ATF_TEST_CASE_WITHOUT_HEAD(quote__empty);
     69 ATF_TEST_CASE_BODY(quote__empty)
     70 {
     71     ATF_REQUIRE_EQ("''", text::quote("", '\''));
     72     ATF_REQUIRE_EQ("##", text::quote("", '#'));
     73 }
     74 
     75 
     76 ATF_TEST_CASE_WITHOUT_HEAD(quote__no_escaping);
     77 ATF_TEST_CASE_BODY(quote__no_escaping)
     78 {
     79     ATF_REQUIRE_EQ("'Some text\"'", text::quote("Some text\"", '\''));
     80     ATF_REQUIRE_EQ("#Another'string#", text::quote("Another'string", '#'));
     81 }
     82 
     83 
     84 ATF_TEST_CASE_WITHOUT_HEAD(quote__some_escaping);
     85 ATF_TEST_CASE_BODY(quote__some_escaping)
     86 {
     87     ATF_REQUIRE_EQ("'Some\\'text'", text::quote("Some'text", '\''));
     88     ATF_REQUIRE_EQ("#Some\\#text#", text::quote("Some#text", '#'));
     89 
     90     ATF_REQUIRE_EQ("'More than one\\' quote\\''",
     91                    text::quote("More than one' quote'", '\''));
     92     ATF_REQUIRE_EQ("'Multiple quotes \\'\\'\\' together'",
     93                    text::quote("Multiple quotes ''' together", '\''));
     94 
     95     ATF_REQUIRE_EQ("'\\'escape at the beginning'",
     96                    text::quote("'escape at the beginning", '\''));
     97     ATF_REQUIRE_EQ("'escape at the end\\''",
     98                    text::quote("escape at the end'", '\''));
     99 }
    100 
    101 
    102 ATF_TEST_CASE_WITHOUT_HEAD(refill__empty);
    103 ATF_TEST_CASE_BODY(refill__empty)
    104 {
    105     ATF_REQUIRE_EQ(1, text::refill("", 0).size());
    106     ATF_REQUIRE(text::refill("", 0)[0].empty());
    107     ATF_REQUIRE_EQ("", text::refill_as_string("", 0));
    108 
    109     ATF_REQUIRE_EQ(1, text::refill("", 10).size());
    110     ATF_REQUIRE(text::refill("", 10)[0].empty());
    111     ATF_REQUIRE_EQ("", text::refill_as_string("", 10));
    112 }
    113 
    114 
    115 ATF_TEST_CASE_WITHOUT_HEAD(refill__no_changes);
    116 ATF_TEST_CASE_BODY(refill__no_changes)
    117 {
    118     std::vector< std::string > exp_lines;
    119     exp_lines.push_back("foo bar\nbaz");
    120 
    121     ATF_REQUIRE(exp_lines == text::refill("foo bar\nbaz", 12));
    122     ATF_REQUIRE_EQ("foo bar\nbaz", text::refill_as_string("foo bar\nbaz", 12));
    123 
    124     ATF_REQUIRE(exp_lines == text::refill("foo bar\nbaz", 18));
    125     ATF_REQUIRE_EQ("foo bar\nbaz", text::refill_as_string("foo bar\nbaz", 80));
    126 }
    127 
    128 
    129 ATF_TEST_CASE_WITHOUT_HEAD(refill__break_one);
    130 ATF_TEST_CASE_BODY(refill__break_one)
    131 {
    132     refill_test("only break the\nfirst line", "only break the first line",
    133                 14, 19);
    134 }
    135 
    136 
    137 ATF_TEST_CASE_WITHOUT_HEAD(refill__break_one__not_first_word);
    138 ATF_TEST_CASE_BODY(refill__break_one__not_first_word)
    139 {
    140     refill_test("first-long-word\nother\nwords", "first-long-word other words",
    141                 6, 10);
    142     refill_test("first-long-word\nother words", "first-long-word other words",
    143                 11, 20);
    144     refill_test("first-long-word other\nwords", "first-long-word other words",
    145                 21, 26);
    146     refill_test("first-long-word other words", "first-long-word other words",
    147                 27, 28);
    148 }
    149 
    150 
    151 ATF_TEST_CASE_WITHOUT_HEAD(refill__break_many);
    152 ATF_TEST_CASE_BODY(refill__break_many)
    153 {
    154     refill_test("this is a long\nparagraph to be\nsplit into\npieces",
    155                 "this is a long paragraph to be split into pieces",
    156                 15, 15);
    157 }
    158 
    159 
    160 ATF_TEST_CASE_WITHOUT_HEAD(refill__cannot_break);
    161 ATF_TEST_CASE_BODY(refill__cannot_break)
    162 {
    163     refill_test("this-is-a-long-string", "this-is-a-long-string", 5, 5);
    164 
    165     refill_test("this is\na-string-with-long-words",
    166                 "this is a-string-with-long-words", 10, 10);
    167 }
    168 
    169 
    170 ATF_TEST_CASE_WITHOUT_HEAD(refill__preserve_whitespace);
    171 ATF_TEST_CASE_BODY(refill__preserve_whitespace)
    172 {
    173     refill_test("foo  bar baz  ", "foo  bar baz  ", 80, 80);
    174     refill_test("foo  \n bar", "foo    bar", 5, 5);
    175 
    176     std::vector< std::string > exp_lines;
    177     exp_lines.push_back("foo \n");
    178     exp_lines.push_back(" bar");
    179     ATF_REQUIRE(exp_lines == text::refill("foo \n  bar", 5));
    180     ATF_REQUIRE_EQ("foo \n\n bar", text::refill_as_string("foo \n  bar", 5));
    181 }
    182 
    183 
    184 ATF_TEST_CASE_WITHOUT_HEAD(join__empty);
    185 ATF_TEST_CASE_BODY(join__empty)
    186 {
    187     std::vector< std::string > lines;
    188     ATF_REQUIRE_EQ("", text::join(lines, " "));
    189 }
    190 
    191 
    192 ATF_TEST_CASE_WITHOUT_HEAD(join__one);
    193 ATF_TEST_CASE_BODY(join__one)
    194 {
    195     std::vector< std::string > lines;
    196     lines.push_back("first line");
    197     ATF_REQUIRE_EQ("first line", text::join(lines, "*"));
    198 }
    199 
    200 
    201 ATF_TEST_CASE_WITHOUT_HEAD(join__several);
    202 ATF_TEST_CASE_BODY(join__several)
    203 {
    204     std::vector< std::string > lines;
    205     lines.push_back("first abc");
    206     lines.push_back("second");
    207     lines.push_back("and last line");
    208     ATF_REQUIRE_EQ("first abc second and last line", text::join(lines, " "));
    209     ATF_REQUIRE_EQ("first abc***second***and last line",
    210                    text::join(lines, "***"));
    211 }
    212 
    213 
    214 ATF_TEST_CASE_WITHOUT_HEAD(join__unordered);
    215 ATF_TEST_CASE_BODY(join__unordered)
    216 {
    217     std::set< std::string > lines;
    218     lines.insert("first");
    219     lines.insert("second");
    220     const std::string joined = text::join(lines, " ");
    221     ATF_REQUIRE(joined == "first second" || joined == "second first");
    222 }
    223 
    224 
    225 ATF_TEST_CASE_WITHOUT_HEAD(split__empty);
    226 ATF_TEST_CASE_BODY(split__empty)
    227 {
    228     std::vector< std::string > words = text::split("", ' ');
    229     std::vector< std::string > exp_words;
    230     ATF_REQUIRE(exp_words == words);
    231 }
    232 
    233 
    234 ATF_TEST_CASE_WITHOUT_HEAD(split__one);
    235 ATF_TEST_CASE_BODY(split__one)
    236 {
    237     std::vector< std::string > words = text::split("foo", ' ');
    238     std::vector< std::string > exp_words;
    239     exp_words.push_back("foo");
    240     ATF_REQUIRE(exp_words == words);
    241 }
    242 
    243 
    244 ATF_TEST_CASE_WITHOUT_HEAD(split__several__simple);
    245 ATF_TEST_CASE_BODY(split__several__simple)
    246 {
    247     std::vector< std::string > words = text::split("foo bar baz", ' ');
    248     std::vector< std::string > exp_words;
    249     exp_words.push_back("foo");
    250     exp_words.push_back("bar");
    251     exp_words.push_back("baz");
    252     ATF_REQUIRE(exp_words == words);
    253 }
    254 
    255 
    256 ATF_TEST_CASE_WITHOUT_HEAD(split__several__delimiters);
    257 ATF_TEST_CASE_BODY(split__several__delimiters)
    258 {
    259     std::vector< std::string > words = text::split("XfooXXbarXXXbazXX", 'X');
    260     std::vector< std::string > exp_words;
    261     exp_words.push_back("");
    262     exp_words.push_back("foo");
    263     exp_words.push_back("");
    264     exp_words.push_back("bar");
    265     exp_words.push_back("");
    266     exp_words.push_back("");
    267     exp_words.push_back("baz");
    268     exp_words.push_back("");
    269     exp_words.push_back("");
    270     ATF_REQUIRE(exp_words == words);
    271 }
    272 
    273 
    274 ATF_TEST_CASE_WITHOUT_HEAD(to_type__ok__bool);
    275 ATF_TEST_CASE_BODY(to_type__ok__bool)
    276 {
    277     ATF_REQUIRE( text::to_type< bool >("true"));
    278     ATF_REQUIRE(!text::to_type< bool >("false"));
    279 }
    280 
    281 
    282 ATF_TEST_CASE_WITHOUT_HEAD(to_type__ok__numerical);
    283 ATF_TEST_CASE_BODY(to_type__ok__numerical)
    284 {
    285     ATF_REQUIRE_EQ(12, text::to_type< int >("12"));
    286     ATF_REQUIRE_EQ(18745, text::to_type< int >("18745"));
    287     ATF_REQUIRE_EQ(-12345, text::to_type< int >("-12345"));
    288 
    289     ATF_REQUIRE_EQ(12.0, text::to_type< double >("12"));
    290     ATF_REQUIRE_EQ(12.5, text::to_type< double >("12.5"));
    291 }
    292 
    293 
    294 ATF_TEST_CASE_WITHOUT_HEAD(to_type__ok__string);
    295 ATF_TEST_CASE_BODY(to_type__ok__string)
    296 {
    297     // While this seems redundant, having this particular specialization that
    298     // does nothing allows callers to delegate work to to_type without worrying
    299     // about the particular type being converted.
    300     ATF_REQUIRE_EQ("", text::to_type< std::string >(""));
    301     ATF_REQUIRE_EQ("  abcd  ", text::to_type< std::string >("  abcd  "));
    302 }
    303 
    304 
    305 ATF_TEST_CASE_WITHOUT_HEAD(to_type__empty);
    306 ATF_TEST_CASE_BODY(to_type__empty)
    307 {
    308     ATF_REQUIRE_THROW(text::value_error, text::to_type< int >(""));
    309 }
    310 
    311 
    312 ATF_TEST_CASE_WITHOUT_HEAD(to_type__invalid__bool);
    313 ATF_TEST_CASE_BODY(to_type__invalid__bool)
    314 {
    315     ATF_REQUIRE_THROW(text::value_error, text::to_type< bool >(""));
    316     ATF_REQUIRE_THROW(text::value_error, text::to_type< bool >("true "));
    317     ATF_REQUIRE_THROW(text::value_error, text::to_type< bool >("foo"));
    318 }
    319 
    320 
    321 ATF_TEST_CASE_WITHOUT_HEAD(to_type__invalid__numerical);
    322 ATF_TEST_CASE_BODY(to_type__invalid__numerical)
    323 {
    324     ATF_REQUIRE_THROW(text::value_error, text::to_type< int >(" 3"));
    325     ATF_REQUIRE_THROW(text::value_error, text::to_type< int >("3 "));
    326     ATF_REQUIRE_THROW(text::value_error, text::to_type< int >("3a"));
    327     ATF_REQUIRE_THROW(text::value_error, text::to_type< int >("a3"));
    328 }
    329 
    330 
    331 ATF_INIT_TEST_CASES(tcs)
    332 {
    333     ATF_ADD_TEST_CASE(tcs, quote__empty);
    334     ATF_ADD_TEST_CASE(tcs, quote__no_escaping);
    335     ATF_ADD_TEST_CASE(tcs, quote__some_escaping);
    336 
    337     ATF_ADD_TEST_CASE(tcs, refill__empty);
    338     ATF_ADD_TEST_CASE(tcs, refill__no_changes);
    339     ATF_ADD_TEST_CASE(tcs, refill__break_one);
    340     ATF_ADD_TEST_CASE(tcs, refill__break_one__not_first_word);
    341     ATF_ADD_TEST_CASE(tcs, refill__break_many);
    342     ATF_ADD_TEST_CASE(tcs, refill__cannot_break);
    343     ATF_ADD_TEST_CASE(tcs, refill__preserve_whitespace);
    344 
    345     ATF_ADD_TEST_CASE(tcs, join__empty);
    346     ATF_ADD_TEST_CASE(tcs, join__one);
    347     ATF_ADD_TEST_CASE(tcs, join__several);
    348     ATF_ADD_TEST_CASE(tcs, join__unordered);
    349 
    350     ATF_ADD_TEST_CASE(tcs, split__empty);
    351     ATF_ADD_TEST_CASE(tcs, split__one);
    352     ATF_ADD_TEST_CASE(tcs, split__several__simple);
    353     ATF_ADD_TEST_CASE(tcs, split__several__delimiters);
    354 
    355     ATF_ADD_TEST_CASE(tcs, to_type__ok__bool);
    356     ATF_ADD_TEST_CASE(tcs, to_type__ok__numerical);
    357     ATF_ADD_TEST_CASE(tcs, to_type__ok__string);
    358     ATF_ADD_TEST_CASE(tcs, to_type__empty);
    359     ATF_ADD_TEST_CASE(tcs, to_type__invalid__bool);
    360     ATF_ADD_TEST_CASE(tcs, to_type__invalid__numerical);
    361 }
    362