str_replace_test.cc
Go to the documentation of this file.
00001 // Copyright 2017 The Abseil Authors.
00002 //
00003 // Licensed under the Apache License, Version 2.0 (the "License");
00004 // you may not use this file except in compliance with the License.
00005 // You may obtain a copy of the License at
00006 //
00007 //      https://www.apache.org/licenses/LICENSE-2.0
00008 //
00009 // Unless required by applicable law or agreed to in writing, software
00010 // distributed under the License is distributed on an "AS IS" BASIS,
00011 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00012 // See the License for the specific language governing permissions and
00013 // limitations under the License.
00014 
00015 #include "absl/strings/str_replace.h"
00016 
00017 #include <list>
00018 #include <map>
00019 #include <tuple>
00020 
00021 #include "gtest/gtest.h"
00022 #include "absl/strings/str_cat.h"
00023 #include "absl/strings/str_split.h"
00024 
00025 TEST(StrReplaceAll, OneReplacement) {
00026   std::string s;
00027 
00028   // Empty std::string.
00029   s = absl::StrReplaceAll(s, {{"", ""}});
00030   EXPECT_EQ(s, "");
00031   s = absl::StrReplaceAll(s, {{"x", ""}});
00032   EXPECT_EQ(s, "");
00033   s = absl::StrReplaceAll(s, {{"", "y"}});
00034   EXPECT_EQ(s, "");
00035   s = absl::StrReplaceAll(s, {{"x", "y"}});
00036   EXPECT_EQ(s, "");
00037 
00038   // Empty substring.
00039   s = absl::StrReplaceAll("abc", {{"", ""}});
00040   EXPECT_EQ(s, "abc");
00041   s = absl::StrReplaceAll("abc", {{"", "y"}});
00042   EXPECT_EQ(s, "abc");
00043   s = absl::StrReplaceAll("abc", {{"x", ""}});
00044   EXPECT_EQ(s, "abc");
00045 
00046   // Substring not found.
00047   s = absl::StrReplaceAll("abc", {{"xyz", "123"}});
00048   EXPECT_EQ(s, "abc");
00049 
00050   // Replace entire std::string.
00051   s = absl::StrReplaceAll("abc", {{"abc", "xyz"}});
00052   EXPECT_EQ(s, "xyz");
00053 
00054   // Replace once at the start.
00055   s = absl::StrReplaceAll("abc", {{"a", "x"}});
00056   EXPECT_EQ(s, "xbc");
00057 
00058   // Replace once in the middle.
00059   s = absl::StrReplaceAll("abc", {{"b", "x"}});
00060   EXPECT_EQ(s, "axc");
00061 
00062   // Replace once at the end.
00063   s = absl::StrReplaceAll("abc", {{"c", "x"}});
00064   EXPECT_EQ(s, "abx");
00065 
00066   // Replace multiple times with varying lengths of original/replacement.
00067   s = absl::StrReplaceAll("ababa", {{"a", "xxx"}});
00068   EXPECT_EQ(s, "xxxbxxxbxxx");
00069 
00070   s = absl::StrReplaceAll("ababa", {{"b", "xxx"}});
00071   EXPECT_EQ(s, "axxxaxxxa");
00072 
00073   s = absl::StrReplaceAll("aaabaaabaaa", {{"aaa", "x"}});
00074   EXPECT_EQ(s, "xbxbx");
00075 
00076   s = absl::StrReplaceAll("abbbabbba", {{"bbb", "x"}});
00077   EXPECT_EQ(s, "axaxa");
00078 
00079   // Overlapping matches are replaced greedily.
00080   s = absl::StrReplaceAll("aaa", {{"aa", "x"}});
00081   EXPECT_EQ(s, "xa");
00082 
00083   // The replacements are not recursive.
00084   s = absl::StrReplaceAll("aaa", {{"aa", "a"}});
00085   EXPECT_EQ(s, "aa");
00086 }
00087 
00088 TEST(StrReplaceAll, ManyReplacements) {
00089   std::string s;
00090 
00091   // Empty std::string.
00092   s = absl::StrReplaceAll("", {{"", ""}, {"x", ""}, {"", "y"}, {"x", "y"}});
00093   EXPECT_EQ(s, "");
00094 
00095   // Empty substring.
00096   s = absl::StrReplaceAll("abc", {{"", ""}, {"", "y"}, {"x", ""}});
00097   EXPECT_EQ(s, "abc");
00098 
00099   // Replace entire std::string, one char at a time
00100   s = absl::StrReplaceAll("abc", {{"a", "x"}, {"b", "y"}, {"c", "z"}});
00101   EXPECT_EQ(s, "xyz");
00102   s = absl::StrReplaceAll("zxy", {{"z", "x"}, {"x", "y"}, {"y", "z"}});
00103   EXPECT_EQ(s, "xyz");
00104 
00105   // Replace once at the start (longer matches take precedence)
00106   s = absl::StrReplaceAll("abc", {{"a", "x"}, {"ab", "xy"}, {"abc", "xyz"}});
00107   EXPECT_EQ(s, "xyz");
00108 
00109   // Replace once in the middle.
00110   s = absl::StrReplaceAll(
00111       "Abc!", {{"a", "x"}, {"ab", "xy"}, {"b", "y"}, {"bc", "yz"}, {"c", "z"}});
00112   EXPECT_EQ(s, "Ayz!");
00113 
00114   // Replace once at the end.
00115   s = absl::StrReplaceAll(
00116       "Abc!",
00117       {{"a", "x"}, {"ab", "xy"}, {"b", "y"}, {"bc!", "yz?"}, {"c!", "z;"}});
00118   EXPECT_EQ(s, "Ayz?");
00119 
00120   // Replace multiple times with varying lengths of original/replacement.
00121   s = absl::StrReplaceAll("ababa", {{"a", "xxx"}, {"b", "XXXX"}});
00122   EXPECT_EQ(s, "xxxXXXXxxxXXXXxxx");
00123 
00124   // Overlapping matches are replaced greedily.
00125   s = absl::StrReplaceAll("aaa", {{"aa", "x"}, {"a", "X"}});
00126   EXPECT_EQ(s, "xX");
00127   s = absl::StrReplaceAll("aaa", {{"a", "X"}, {"aa", "x"}});
00128   EXPECT_EQ(s, "xX");
00129 
00130   // Two well-known sentences
00131   s = absl::StrReplaceAll("the quick brown fox jumped over the lazy dogs",
00132                           {
00133                               {"brown", "box"},
00134                               {"dogs", "jugs"},
00135                               {"fox", "with"},
00136                               {"jumped", "five"},
00137                               {"over", "dozen"},
00138                               {"quick", "my"},
00139                               {"the", "pack"},
00140                               {"the lazy", "liquor"},
00141                           });
00142   EXPECT_EQ(s, "pack my box with five dozen liquor jugs");
00143 }
00144 
00145 TEST(StrReplaceAll, ManyReplacementsInMap) {
00146   std::map<const char *, const char *> replacements;
00147   replacements["$who"] = "Bob";
00148   replacements["$count"] = "5";
00149   replacements["#Noun"] = "Apples";
00150   std::string s = absl::StrReplaceAll("$who bought $count #Noun. Thanks $who!",
00151                                       replacements);
00152   EXPECT_EQ("Bob bought 5 Apples. Thanks Bob!", s);
00153 }
00154 
00155 TEST(StrReplaceAll, ReplacementsInPlace) {
00156   std::string s = std::string("$who bought $count #Noun. Thanks $who!");
00157   int count;
00158   count = absl::StrReplaceAll({{"$count", absl::StrCat(5)},
00159                               {"$who", "Bob"},
00160                               {"#Noun", "Apples"}}, &s);
00161   EXPECT_EQ(count, 4);
00162   EXPECT_EQ("Bob bought 5 Apples. Thanks Bob!", s);
00163 }
00164 
00165 TEST(StrReplaceAll, ReplacementsInPlaceInMap) {
00166   std::string s = std::string("$who bought $count #Noun. Thanks $who!");
00167   std::map<absl::string_view, absl::string_view> replacements;
00168   replacements["$who"] = "Bob";
00169   replacements["$count"] = "5";
00170   replacements["#Noun"] = "Apples";
00171   int count;
00172   count = absl::StrReplaceAll(replacements, &s);
00173   EXPECT_EQ(count, 4);
00174   EXPECT_EQ("Bob bought 5 Apples. Thanks Bob!", s);
00175 }
00176 
00177 struct Cont {
00178   Cont() {}
00179   explicit Cont(absl::string_view src) : data(src) {}
00180 
00181   absl::string_view data;
00182 };
00183 
00184 template <int index>
00185 absl::string_view get(const Cont& c) {
00186   auto splitter = absl::StrSplit(c.data, ':');
00187   auto it = splitter.begin();
00188   for (int i = 0; i < index; ++i) ++it;
00189 
00190   return *it;
00191 }
00192 
00193 TEST(StrReplaceAll, VariableNumber) {
00194   std::string s;
00195   {
00196     std::vector<std::pair<std::string, std::string>> replacements;
00197 
00198     s = "abc";
00199     EXPECT_EQ(0, absl::StrReplaceAll(replacements, &s));
00200     EXPECT_EQ("abc", s);
00201 
00202     s = "abc";
00203     replacements.push_back({"a", "A"});
00204     EXPECT_EQ(1, absl::StrReplaceAll(replacements, &s));
00205     EXPECT_EQ("Abc", s);
00206 
00207     s = "abc";
00208     replacements.push_back({"b", "B"});
00209     EXPECT_EQ(2, absl::StrReplaceAll(replacements, &s));
00210     EXPECT_EQ("ABc", s);
00211 
00212     s = "abc";
00213     replacements.push_back({"d", "D"});
00214     EXPECT_EQ(2, absl::StrReplaceAll(replacements, &s));
00215     EXPECT_EQ("ABc", s);
00216 
00217     EXPECT_EQ("ABcABc", absl::StrReplaceAll("abcabc", replacements));
00218   }
00219 
00220   {
00221     std::map<const char*, const char*> replacements;
00222     replacements["aa"] = "x";
00223     replacements["a"] = "X";
00224     s = "aaa";
00225     EXPECT_EQ(2, absl::StrReplaceAll(replacements, &s));
00226     EXPECT_EQ("xX", s);
00227 
00228     EXPECT_EQ("xxX", absl::StrReplaceAll("aaaaa", replacements));
00229   }
00230 
00231   {
00232     std::list<std::pair<absl::string_view, absl::string_view>> replacements = {
00233         {"a", "x"}, {"b", "y"}, {"c", "z"}};
00234 
00235     std::string s = absl::StrReplaceAll("abc", replacements);
00236     EXPECT_EQ(s, "xyz");
00237   }
00238 
00239   {
00240     using X = std::tuple<absl::string_view, std::string, int>;
00241     std::vector<X> replacements(3);
00242     replacements[0] = X{"a", "x", 1};
00243     replacements[1] = X{"b", "y", 0};
00244     replacements[2] = X{"c", "z", -1};
00245 
00246     std::string s = absl::StrReplaceAll("abc", replacements);
00247     EXPECT_EQ(s, "xyz");
00248   }
00249 
00250   {
00251     std::vector<Cont> replacements(3);
00252     replacements[0] = Cont{"a:x"};
00253     replacements[1] = Cont{"b:y"};
00254     replacements[2] = Cont{"c:z"};
00255 
00256     std::string s = absl::StrReplaceAll("abc", replacements);
00257     EXPECT_EQ(s, "xyz");
00258   }
00259 }
00260 
00261 // Same as above, but using the in-place variant of absl::StrReplaceAll,
00262 // that returns the # of replacements performed.
00263 TEST(StrReplaceAll, Inplace) {
00264   std::string s;
00265   int reps;
00266 
00267   // Empty std::string.
00268   s = "";
00269   reps = absl::StrReplaceAll({{"", ""}, {"x", ""}, {"", "y"}, {"x", "y"}}, &s);
00270   EXPECT_EQ(reps, 0);
00271   EXPECT_EQ(s, "");
00272 
00273   // Empty substring.
00274   s = "abc";
00275   reps = absl::StrReplaceAll({{"", ""}, {"", "y"}, {"x", ""}}, &s);
00276   EXPECT_EQ(reps, 0);
00277   EXPECT_EQ(s, "abc");
00278 
00279   // Replace entire std::string, one char at a time
00280   s = "abc";
00281   reps = absl::StrReplaceAll({{"a", "x"}, {"b", "y"}, {"c", "z"}}, &s);
00282   EXPECT_EQ(reps, 3);
00283   EXPECT_EQ(s, "xyz");
00284   s = "zxy";
00285   reps = absl::StrReplaceAll({{"z", "x"}, {"x", "y"}, {"y", "z"}}, &s);
00286   EXPECT_EQ(reps, 3);
00287   EXPECT_EQ(s, "xyz");
00288 
00289   // Replace once at the start (longer matches take precedence)
00290   s = "abc";
00291   reps = absl::StrReplaceAll({{"a", "x"}, {"ab", "xy"}, {"abc", "xyz"}}, &s);
00292   EXPECT_EQ(reps, 1);
00293   EXPECT_EQ(s, "xyz");
00294 
00295   // Replace once in the middle.
00296   s = "Abc!";
00297   reps = absl::StrReplaceAll(
00298       {{"a", "x"}, {"ab", "xy"}, {"b", "y"}, {"bc", "yz"}, {"c", "z"}}, &s);
00299   EXPECT_EQ(reps, 1);
00300   EXPECT_EQ(s, "Ayz!");
00301 
00302   // Replace once at the end.
00303   s = "Abc!";
00304   reps = absl::StrReplaceAll(
00305       {{"a", "x"}, {"ab", "xy"}, {"b", "y"}, {"bc!", "yz?"}, {"c!", "z;"}}, &s);
00306   EXPECT_EQ(reps, 1);
00307   EXPECT_EQ(s, "Ayz?");
00308 
00309   // Replace multiple times with varying lengths of original/replacement.
00310   s = "ababa";
00311   reps = absl::StrReplaceAll({{"a", "xxx"}, {"b", "XXXX"}}, &s);
00312   EXPECT_EQ(reps, 5);
00313   EXPECT_EQ(s, "xxxXXXXxxxXXXXxxx");
00314 
00315   // Overlapping matches are replaced greedily.
00316   s = "aaa";
00317   reps = absl::StrReplaceAll({{"aa", "x"}, {"a", "X"}}, &s);
00318   EXPECT_EQ(reps, 2);
00319   EXPECT_EQ(s, "xX");
00320   s = "aaa";
00321   reps = absl::StrReplaceAll({{"a", "X"}, {"aa", "x"}}, &s);
00322   EXPECT_EQ(reps, 2);
00323   EXPECT_EQ(s, "xX");
00324 
00325   // Two well-known sentences
00326   s = "the quick brown fox jumped over the lazy dogs";
00327   reps = absl::StrReplaceAll(
00328       {
00329           {"brown", "box"},
00330           {"dogs", "jugs"},
00331           {"fox", "with"},
00332           {"jumped", "five"},
00333           {"over", "dozen"},
00334           {"quick", "my"},
00335           {"the", "pack"},
00336           {"the lazy", "liquor"},
00337       },
00338       &s);
00339   EXPECT_EQ(reps, 8);
00340   EXPECT_EQ(s, "pack my box with five dozen liquor jugs");
00341 }


abseil_cpp
Author(s):
autogenerated on Wed Jun 19 2019 19:42:15