1 #include "catch.hpp" 2 #include <vector> 3 #include <list> 4 #include <functional> 5 #include <cstring> 6 #include <locale.h> 7 8 #include "stringutil.h" 9 10 // Test plain arrays, vectors, and lists (not random-access), with const variants of both 11 TEMPLATE_TEST_CASE( "comma_separated_*", "[single-file]", 12 const char *[], string[], const string[], 13 vector<const char *>, const vector<string>, 14 list<const char *>, const list<const char *> ) 15 { 16 TestType several = { "foo", "bar", "baz" }; 17 TestType two = { "foo", "bar" }; 18 TestType one = { "foo" }; 19 20 CHECK(comma_separated_line(begin(several), end(several)) == "foo, bar and baz"); 21 CHECK(comma_separated_line(begin(two), end(two)) == "foo and bar"); 22 CHECK(comma_separated_line(begin(one), end(one)) == *begin(one)); 23 // N.b. begin() twice is intentional, to get an empty range (likewise below) 24 CHECK(comma_separated_line(begin(one), begin(one)) == ""); 25 26 CHECK(comma_separated_line(begin(several), end(several), "&", "+") == "foo+bar&baz"); 27 CHECK(comma_separated_line(begin(two), end(two), "&", "+") == "foo&bar"); 28 CHECK(comma_separated_line(begin(one), end(one), "&", "+") == *begin(one)); 29 CHECK(comma_separated_line(begin(one), begin(one), "&", "+") == ""); 30 31 CHECK(join_strings(begin(several), end(several)) == "foo bar baz"); 32 CHECK(join_strings(begin(two), end(two)) == "foo bar"); 33 CHECK(join_strings(begin(one), end(one)) == *begin(one)); 34 CHECK(join_strings(begin(one), begin(one)) == ""); 35 36 CHECK(comma_separated_fn(begin(several), end(several), uppercase_string) 37 == "FOO, BAR and BAZ"); 38 CHECK(comma_separated_fn(begin(two), end(two), uppercase_string) == "FOO and BAR"); 39 CHECK(comma_separated_fn(begin(one), end(one), uppercase_string) 40 == uppercase_string(*begin(one))); 41 CHECK(comma_separated_fn(begin(one), begin(one), uppercase_string) == ""); 42 43 CHECK(comma_separated_fn(begin(several), end(several), uppercase_string, "&", "+") 44 == "FOO+BAR&BAZ"); 45 CHECK(comma_separated_fn(begin(two), end(two), uppercase_string, "&", "+") == "FOO&BAR"); 46 CHECK(comma_separated_fn(begin(one), end(one), uppercase_string, "&", "+") 47 == uppercase_string(*begin(one))); 48 CHECK(comma_separated_fn(begin(one), begin(one), uppercase_string, "&", "+") == ""); 49 50 } 51 52 TEST_CASE( "comma_separated_fn with a non-string", "[single-file]") 53 { 54 int numlist[] = { 1, 2, 3, 4 }; 55 // Select a specific overload of std::to_string. 56 string (*fn)(int) = to_string; 57 // Also with a std::function 58 function<string(int)> fn_func{fn}; 59 60 CHECK(comma_separated_fn(begin(numlist), end(numlist), fn) == "1, 2, 3 and 4"); 61 CHECK(comma_separated_fn(begin(numlist), end(numlist), fn_func) == "1, 2, 3 and 4"); 62 } 63 64 TEST_CASE( "uppercase and lowercase", "[single-file]") 65 { 66 for (int i = 0; i < 2; ++i) { 67 // Also try with a Turkish locale, where tolower("I") is not "i". Our uppercase 68 // and lowercase functions should ignore the locale for ASCII characters, because 69 // they are also used for things that aren't exactly "text". 70 if (i > 0) 71 setlocale(LC_ALL, "tr_TR"); 72 73 // N.b. includes a capital I 74 const char orig[] = "mIxEdCaSe"; 75 string in_s(orig); 76 const string in_cs(orig); 77 const char *in = in_s.c_str(); 78 79 // First, the non-mutating versions. 80 CHECK(lowercase_string(in) == "mixedcase"); 81 CHECK(lowercase_string(in_s) == "mixedcase"); 82 CHECK(lowercase_string(in_cs) == "mixedcase"); 83 84 // Ensure they didn't mutate the input, and abort the test case if they did. 85 REQUIRE(in_s == orig); 86 REQUIRE(strcmp(in, orig) == 0); 87 88 // Again for uppercasing 89 CHECK(uppercase_string(in) == "MIXEDCASE"); 90 CHECK(uppercase_string(in_s) == "MIXEDCASE"); 91 CHECK(uppercase_string(in_cs) == "MIXEDCASE"); 92 93 REQUIRE(in_s == orig); 94 REQUIRE(strcmp(in, orig) == 0); 95 96 // Again for title-casing 97 CHECK(uppercase_first(in) == "MIxEdCaSe"); 98 CHECK(uppercase_first(in_s) == "MIxEdCaSe"); 99 CHECK(uppercase_first(in_cs) == "MIxEdCaSe"); 100 101 REQUIRE(in_s == orig); 102 REQUIRE(strcmp(in, orig) == 0); 103 104 // Now the mutating versions 105 string s1(orig); 106 string &result = uppercase(s1); 107 CHECK(result == "MIXEDCASE"); 108 // Verify identity 109 CHECK(&result == &s1); 110 111 string &result2 = lowercase(result); 112 CHECK(result2 == "mixedcase"); 113 // Verify identity 114 CHECK(&result2 == &s1); 115 } 116 } 117