Path: blob/main/contrib/kyua/utils/text/operations_test.cpp
48180 views
// Copyright 2012 The Kyua Authors.1// All rights reserved.2//3// Redistribution and use in source and binary forms, with or without4// modification, are permitted provided that the following conditions are5// met:6//7// * Redistributions of source code must retain the above copyright8// notice, this list of conditions and the following disclaimer.9// * Redistributions in binary form must reproduce the above copyright10// notice, this list of conditions and the following disclaimer in the11// documentation and/or other materials provided with the distribution.12// * Neither the name of Google Inc. nor the names of its contributors13// may be used to endorse or promote products derived from this software14// without specific prior written permission.15//16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.2728#include "utils/text/operations.ipp"2930#include <iostream>31#include <set>32#include <string>33#include <vector>3435#include <atf-c++.hpp>3637#include "utils/text/exceptions.hpp"3839namespace text = utils::text;404142namespace {434445/// Tests text::refill() on an input string with a range of widths.46///47/// \param expected The expected refilled paragraph.48/// \param input The input paragraph to be refilled.49/// \param first_width The first width to validate.50/// \param last_width The last width to validate (inclusive).51static void52refill_test(const char* expected, const char* input,53const std::size_t first_width, const std::size_t last_width)54{55for (std::size_t width = first_width; width <= last_width; ++width) {56const std::vector< std::string > lines = text::split(expected, '\n');57std::cout << "Breaking at width " << width << '\n';58ATF_REQUIRE_EQ(expected, text::refill_as_string(input, width));59ATF_REQUIRE(lines == text::refill(input, width));60}61}626364} // anonymous namespace656667ATF_TEST_CASE_WITHOUT_HEAD(escape_xml__empty);68ATF_TEST_CASE_BODY(escape_xml__empty)69{70ATF_REQUIRE_EQ("", text::escape_xml(""));71}727374ATF_TEST_CASE_WITHOUT_HEAD(escape_xml__no_escaping);75ATF_TEST_CASE_BODY(escape_xml__no_escaping)76{77ATF_REQUIRE_EQ("a", text::escape_xml("a"));78ATF_REQUIRE_EQ("Some text!", text::escape_xml("Some text!"));79ATF_REQUIRE_EQ("\n\t\r", text::escape_xml("\n\t\r"));80}818283ATF_TEST_CASE_WITHOUT_HEAD(escape_xml__some_escaping);84ATF_TEST_CASE_BODY(escape_xml__some_escaping)85{86ATF_REQUIRE_EQ("'", text::escape_xml("'"));8788ATF_REQUIRE_EQ("foo "bar& <tag> yay' baz",89text::escape_xml("foo \"bar& <tag> yay' baz"));9091ATF_REQUIRE_EQ(""&<>'", text::escape_xml("\"&<>'"));92ATF_REQUIRE_EQ("&&&", text::escape_xml("&&&"));93ATF_REQUIRE_EQ("&#8;&#11;", text::escape_xml("\b\v"));94ATF_REQUIRE_EQ("\t&#127;BAR&", text::escape_xml("\t\x7f""BAR&"));95}969798ATF_TEST_CASE_WITHOUT_HEAD(quote__empty);99ATF_TEST_CASE_BODY(quote__empty)100{101ATF_REQUIRE_EQ("''", text::quote("", '\''));102ATF_REQUIRE_EQ("##", text::quote("", '#'));103}104105106ATF_TEST_CASE_WITHOUT_HEAD(quote__no_escaping);107ATF_TEST_CASE_BODY(quote__no_escaping)108{109ATF_REQUIRE_EQ("'Some text\"'", text::quote("Some text\"", '\''));110ATF_REQUIRE_EQ("#Another'string#", text::quote("Another'string", '#'));111}112113114ATF_TEST_CASE_WITHOUT_HEAD(quote__some_escaping);115ATF_TEST_CASE_BODY(quote__some_escaping)116{117ATF_REQUIRE_EQ("'Some\\'text'", text::quote("Some'text", '\''));118ATF_REQUIRE_EQ("#Some\\#text#", text::quote("Some#text", '#'));119120ATF_REQUIRE_EQ("'More than one\\' quote\\''",121text::quote("More than one' quote'", '\''));122ATF_REQUIRE_EQ("'Multiple quotes \\'\\'\\' together'",123text::quote("Multiple quotes ''' together", '\''));124125ATF_REQUIRE_EQ("'\\'escape at the beginning'",126text::quote("'escape at the beginning", '\''));127ATF_REQUIRE_EQ("'escape at the end\\''",128text::quote("escape at the end'", '\''));129}130131132ATF_TEST_CASE_WITHOUT_HEAD(refill__empty);133ATF_TEST_CASE_BODY(refill__empty)134{135ATF_REQUIRE_EQ(1, text::refill("", 0).size());136ATF_REQUIRE(text::refill("", 0)[0].empty());137ATF_REQUIRE_EQ("", text::refill_as_string("", 0));138139ATF_REQUIRE_EQ(1, text::refill("", 10).size());140ATF_REQUIRE(text::refill("", 10)[0].empty());141ATF_REQUIRE_EQ("", text::refill_as_string("", 10));142}143144145ATF_TEST_CASE_WITHOUT_HEAD(refill__no_changes);146ATF_TEST_CASE_BODY(refill__no_changes)147{148std::vector< std::string > exp_lines;149exp_lines.push_back("foo bar\nbaz");150151ATF_REQUIRE(exp_lines == text::refill("foo bar\nbaz", 12));152ATF_REQUIRE_EQ("foo bar\nbaz", text::refill_as_string("foo bar\nbaz", 12));153154ATF_REQUIRE(exp_lines == text::refill("foo bar\nbaz", 18));155ATF_REQUIRE_EQ("foo bar\nbaz", text::refill_as_string("foo bar\nbaz", 80));156}157158159ATF_TEST_CASE_WITHOUT_HEAD(refill__break_one);160ATF_TEST_CASE_BODY(refill__break_one)161{162refill_test("only break the\nfirst line", "only break the first line",16314, 19);164}165166167ATF_TEST_CASE_WITHOUT_HEAD(refill__break_one__not_first_word);168ATF_TEST_CASE_BODY(refill__break_one__not_first_word)169{170refill_test("first-long-word\nother\nwords", "first-long-word other words",1716, 10);172refill_test("first-long-word\nother words", "first-long-word other words",17311, 20);174refill_test("first-long-word other\nwords", "first-long-word other words",17521, 26);176refill_test("first-long-word other words", "first-long-word other words",17727, 28);178}179180181ATF_TEST_CASE_WITHOUT_HEAD(refill__break_many);182ATF_TEST_CASE_BODY(refill__break_many)183{184refill_test("this is a long\nparagraph to be\nsplit into\npieces",185"this is a long paragraph to be split into pieces",18615, 15);187}188189190ATF_TEST_CASE_WITHOUT_HEAD(refill__cannot_break);191ATF_TEST_CASE_BODY(refill__cannot_break)192{193refill_test("this-is-a-long-string", "this-is-a-long-string", 5, 5);194195refill_test("this is\na-string-with-long-words",196"this is a-string-with-long-words", 10, 10);197}198199200ATF_TEST_CASE_WITHOUT_HEAD(refill__preserve_whitespace);201ATF_TEST_CASE_BODY(refill__preserve_whitespace)202{203refill_test("foo bar baz ", "foo bar baz ", 80, 80);204refill_test("foo \n bar", "foo bar", 5, 5);205206std::vector< std::string > exp_lines;207exp_lines.push_back("foo \n");208exp_lines.push_back(" bar");209ATF_REQUIRE(exp_lines == text::refill("foo \n bar", 5));210ATF_REQUIRE_EQ("foo \n\n bar", text::refill_as_string("foo \n bar", 5));211}212213214ATF_TEST_CASE_WITHOUT_HEAD(join__empty);215ATF_TEST_CASE_BODY(join__empty)216{217std::vector< std::string > lines;218ATF_REQUIRE_EQ("", text::join(lines, " "));219}220221222ATF_TEST_CASE_WITHOUT_HEAD(join__one);223ATF_TEST_CASE_BODY(join__one)224{225std::vector< std::string > lines;226lines.push_back("first line");227ATF_REQUIRE_EQ("first line", text::join(lines, "*"));228}229230231ATF_TEST_CASE_WITHOUT_HEAD(join__several);232ATF_TEST_CASE_BODY(join__several)233{234std::vector< std::string > lines;235lines.push_back("first abc");236lines.push_back("second");237lines.push_back("and last line");238ATF_REQUIRE_EQ("first abc second and last line", text::join(lines, " "));239ATF_REQUIRE_EQ("first abc***second***and last line",240text::join(lines, "***"));241}242243244ATF_TEST_CASE_WITHOUT_HEAD(join__unordered);245ATF_TEST_CASE_BODY(join__unordered)246{247std::set< std::string > lines;248lines.insert("first");249lines.insert("second");250const std::string joined = text::join(lines, " ");251ATF_REQUIRE(joined == "first second" || joined == "second first");252}253254255ATF_TEST_CASE_WITHOUT_HEAD(split__empty);256ATF_TEST_CASE_BODY(split__empty)257{258std::vector< std::string > words = text::split("", ' ');259std::vector< std::string > exp_words;260ATF_REQUIRE(exp_words == words);261}262263264ATF_TEST_CASE_WITHOUT_HEAD(split__one);265ATF_TEST_CASE_BODY(split__one)266{267std::vector< std::string > words = text::split("foo", ' ');268std::vector< std::string > exp_words;269exp_words.push_back("foo");270ATF_REQUIRE(exp_words == words);271}272273274ATF_TEST_CASE_WITHOUT_HEAD(split__several__simple);275ATF_TEST_CASE_BODY(split__several__simple)276{277std::vector< std::string > words = text::split("foo bar baz", ' ');278std::vector< std::string > exp_words;279exp_words.push_back("foo");280exp_words.push_back("bar");281exp_words.push_back("baz");282ATF_REQUIRE(exp_words == words);283}284285286ATF_TEST_CASE_WITHOUT_HEAD(split__several__delimiters);287ATF_TEST_CASE_BODY(split__several__delimiters)288{289std::vector< std::string > words = text::split("XfooXXbarXXXbazXX", 'X');290std::vector< std::string > exp_words;291exp_words.push_back("");292exp_words.push_back("foo");293exp_words.push_back("");294exp_words.push_back("bar");295exp_words.push_back("");296exp_words.push_back("");297exp_words.push_back("baz");298exp_words.push_back("");299exp_words.push_back("");300ATF_REQUIRE(exp_words == words);301}302303304ATF_TEST_CASE_WITHOUT_HEAD(replace_all__empty);305ATF_TEST_CASE_BODY(replace_all__empty)306{307ATF_REQUIRE_EQ("", text::replace_all("", "search", "replacement"));308}309310311ATF_TEST_CASE_WITHOUT_HEAD(replace_all__none);312ATF_TEST_CASE_BODY(replace_all__none)313{314ATF_REQUIRE_EQ("string without matches",315text::replace_all("string without matches",316"WITHOUT", "replacement"));317}318319320ATF_TEST_CASE_WITHOUT_HEAD(replace_all__one);321ATF_TEST_CASE_BODY(replace_all__one)322{323ATF_REQUIRE_EQ("string replacement matches",324text::replace_all("string without matches",325"without", "replacement"));326}327328329ATF_TEST_CASE_WITHOUT_HEAD(replace_all__several);330ATF_TEST_CASE_BODY(replace_all__several)331{332ATF_REQUIRE_EQ("OO fOO bar OOf baz OO",333text::replace_all("oo foo bar oof baz oo",334"oo", "OO"));335}336337338ATF_TEST_CASE_WITHOUT_HEAD(to_type__ok__bool);339ATF_TEST_CASE_BODY(to_type__ok__bool)340{341ATF_REQUIRE( text::to_type< bool >("true"));342ATF_REQUIRE(!text::to_type< bool >("false"));343}344345346ATF_TEST_CASE_WITHOUT_HEAD(to_type__ok__numerical);347ATF_TEST_CASE_BODY(to_type__ok__numerical)348{349ATF_REQUIRE_EQ(12, text::to_type< int >("12"));350ATF_REQUIRE_EQ(18745, text::to_type< int >("18745"));351ATF_REQUIRE_EQ(-12345, text::to_type< int >("-12345"));352353ATF_REQUIRE_EQ(12.0, text::to_type< double >("12"));354ATF_REQUIRE_EQ(12.5, text::to_type< double >("12.5"));355}356357358ATF_TEST_CASE_WITHOUT_HEAD(to_type__ok__string);359ATF_TEST_CASE_BODY(to_type__ok__string)360{361// While this seems redundant, having this particular specialization that362// does nothing allows callers to delegate work to to_type without worrying363// about the particular type being converted.364ATF_REQUIRE_EQ("", text::to_type< std::string >(""));365ATF_REQUIRE_EQ(" abcd ", text::to_type< std::string >(" abcd "));366}367368369ATF_TEST_CASE_WITHOUT_HEAD(to_type__empty);370ATF_TEST_CASE_BODY(to_type__empty)371{372ATF_REQUIRE_THROW(text::value_error, text::to_type< int >(""));373}374375376ATF_TEST_CASE_WITHOUT_HEAD(to_type__invalid__bool);377ATF_TEST_CASE_BODY(to_type__invalid__bool)378{379ATF_REQUIRE_THROW(text::value_error, text::to_type< bool >(""));380ATF_REQUIRE_THROW(text::value_error, text::to_type< bool >("true "));381ATF_REQUIRE_THROW(text::value_error, text::to_type< bool >("foo"));382}383384385ATF_TEST_CASE_WITHOUT_HEAD(to_type__invalid__numerical);386ATF_TEST_CASE_BODY(to_type__invalid__numerical)387{388ATF_REQUIRE_THROW(text::value_error, text::to_type< int >(" 3"));389ATF_REQUIRE_THROW(text::value_error, text::to_type< int >("3 "));390ATF_REQUIRE_THROW(text::value_error, text::to_type< int >("3a"));391ATF_REQUIRE_THROW(text::value_error, text::to_type< int >("a3"));392}393394395ATF_INIT_TEST_CASES(tcs)396{397ATF_ADD_TEST_CASE(tcs, escape_xml__empty);398ATF_ADD_TEST_CASE(tcs, escape_xml__no_escaping);399ATF_ADD_TEST_CASE(tcs, escape_xml__some_escaping);400401ATF_ADD_TEST_CASE(tcs, quote__empty);402ATF_ADD_TEST_CASE(tcs, quote__no_escaping);403ATF_ADD_TEST_CASE(tcs, quote__some_escaping);404405ATF_ADD_TEST_CASE(tcs, refill__empty);406ATF_ADD_TEST_CASE(tcs, refill__no_changes);407ATF_ADD_TEST_CASE(tcs, refill__break_one);408ATF_ADD_TEST_CASE(tcs, refill__break_one__not_first_word);409ATF_ADD_TEST_CASE(tcs, refill__break_many);410ATF_ADD_TEST_CASE(tcs, refill__cannot_break);411ATF_ADD_TEST_CASE(tcs, refill__preserve_whitespace);412413ATF_ADD_TEST_CASE(tcs, join__empty);414ATF_ADD_TEST_CASE(tcs, join__one);415ATF_ADD_TEST_CASE(tcs, join__several);416ATF_ADD_TEST_CASE(tcs, join__unordered);417418ATF_ADD_TEST_CASE(tcs, split__empty);419ATF_ADD_TEST_CASE(tcs, split__one);420ATF_ADD_TEST_CASE(tcs, split__several__simple);421ATF_ADD_TEST_CASE(tcs, split__several__delimiters);422423ATF_ADD_TEST_CASE(tcs, replace_all__empty);424ATF_ADD_TEST_CASE(tcs, replace_all__none);425ATF_ADD_TEST_CASE(tcs, replace_all__one);426ATF_ADD_TEST_CASE(tcs, replace_all__several);427428ATF_ADD_TEST_CASE(tcs, to_type__ok__bool);429ATF_ADD_TEST_CASE(tcs, to_type__ok__numerical);430ATF_ADD_TEST_CASE(tcs, to_type__ok__string);431ATF_ADD_TEST_CASE(tcs, to_type__empty);432ATF_ADD_TEST_CASE(tcs, to_type__invalid__bool);433ATF_ADD_TEST_CASE(tcs, to_type__invalid__numerical);434}435436437