string_util_unittest.cc 57 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556
  1. // Copyright 2013 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "base/strings/string_util.h"
  5. #include <math.h>
  6. #include <stdarg.h>
  7. #include <stddef.h>
  8. #include <stdint.h>
  9. #include <algorithm>
  10. #include <string>
  11. #include <type_traits>
  12. #include "base/bits.h"
  13. #include "base/strings/string_piece.h"
  14. #include "base/strings/utf_string_conversions.h"
  15. #include "build/build_config.h"
  16. #include "testing/gmock/include/gmock/gmock.h"
  17. #include "testing/gtest/include/gtest/gtest.h"
  18. using ::testing::ElementsAre;
  19. namespace base {
  20. static const struct trim_case {
  21. const wchar_t* input;
  22. const TrimPositions positions;
  23. const wchar_t* output;
  24. const TrimPositions return_value;
  25. } trim_cases[] = {
  26. {L" Google Video ", TRIM_LEADING, L"Google Video ", TRIM_LEADING},
  27. {L" Google Video ", TRIM_TRAILING, L" Google Video", TRIM_TRAILING},
  28. {L" Google Video ", TRIM_ALL, L"Google Video", TRIM_ALL},
  29. {L"Google Video", TRIM_ALL, L"Google Video", TRIM_NONE},
  30. {L"", TRIM_ALL, L"", TRIM_NONE},
  31. {L" ", TRIM_LEADING, L"", TRIM_LEADING},
  32. {L" ", TRIM_TRAILING, L"", TRIM_TRAILING},
  33. {L" ", TRIM_ALL, L"", TRIM_ALL},
  34. {L"\t\rTest String\n", TRIM_ALL, L"Test String", TRIM_ALL},
  35. {L"\x2002Test String\x00A0\x3000", TRIM_ALL, L"Test String", TRIM_ALL},
  36. };
  37. static const struct trim_case_ascii {
  38. const char* input;
  39. const TrimPositions positions;
  40. const char* output;
  41. const TrimPositions return_value;
  42. } trim_cases_ascii[] = {
  43. {" Google Video ", TRIM_LEADING, "Google Video ", TRIM_LEADING},
  44. {" Google Video ", TRIM_TRAILING, " Google Video", TRIM_TRAILING},
  45. {" Google Video ", TRIM_ALL, "Google Video", TRIM_ALL},
  46. {"Google Video", TRIM_ALL, "Google Video", TRIM_NONE},
  47. {"", TRIM_ALL, "", TRIM_NONE},
  48. {" ", TRIM_LEADING, "", TRIM_LEADING},
  49. {" ", TRIM_TRAILING, "", TRIM_TRAILING},
  50. {" ", TRIM_ALL, "", TRIM_ALL},
  51. {"\t\rTest String\n", TRIM_ALL, "Test String", TRIM_ALL},
  52. };
  53. namespace {
  54. // Helper used to test TruncateUTF8ToByteSize.
  55. bool Truncated(const std::string& input,
  56. const size_t byte_size,
  57. std::string* output) {
  58. size_t prev = input.length();
  59. TruncateUTF8ToByteSize(input, byte_size, output);
  60. return prev != output->length();
  61. }
  62. using TestFunction = bool (*)(StringPiece str);
  63. // Helper used to test IsStringUTF8{,AllowingNoncharacters}.
  64. void TestStructurallyValidUtf8(TestFunction fn) {
  65. EXPECT_TRUE(fn("abc"));
  66. EXPECT_TRUE(fn("\xC2\x81"));
  67. EXPECT_TRUE(fn("\xE1\x80\xBF"));
  68. EXPECT_TRUE(fn("\xF1\x80\xA0\xBF"));
  69. EXPECT_TRUE(fn("\xF1\x80\xA0\xBF"));
  70. EXPECT_TRUE(fn("a\xC2\x81\xE1\x80\xBF\xF1\x80\xA0\xBF"));
  71. // U+FEFF used as UTF-8 BOM.
  72. // clang-format off
  73. EXPECT_TRUE(fn("\xEF\xBB\xBF" "abc"));
  74. // clang-format on
  75. // Embedded nulls in canonical UTF-8 representation.
  76. using std::string_literals::operator""s;
  77. const std::string kEmbeddedNull = "embedded\0null"s;
  78. EXPECT_TRUE(fn(kEmbeddedNull));
  79. }
  80. // Helper used to test IsStringUTF8{,AllowingNoncharacters}.
  81. void TestStructurallyInvalidUtf8(TestFunction fn) {
  82. // Invalid encoding of U+1FFFE (0x8F instead of 0x9F)
  83. EXPECT_FALSE(fn("\xF0\x8F\xBF\xBE"));
  84. // Surrogate code points
  85. EXPECT_FALSE(fn("\xED\xA0\x80\xED\xBF\xBF"));
  86. EXPECT_FALSE(fn("\xED\xA0\x8F"));
  87. EXPECT_FALSE(fn("\xED\xBF\xBF"));
  88. // Overlong sequences
  89. EXPECT_FALSE(fn("\xC0\x80")); // U+0000
  90. EXPECT_FALSE(fn("\xC1\x80\xC1\x81")); // "AB"
  91. EXPECT_FALSE(fn("\xE0\x80\x80")); // U+0000
  92. EXPECT_FALSE(fn("\xE0\x82\x80")); // U+0080
  93. EXPECT_FALSE(fn("\xE0\x9F\xBF")); // U+07FF
  94. EXPECT_FALSE(fn("\xF0\x80\x80\x8D")); // U+000D
  95. EXPECT_FALSE(fn("\xF0\x80\x82\x91")); // U+0091
  96. EXPECT_FALSE(fn("\xF0\x80\xA0\x80")); // U+0800
  97. EXPECT_FALSE(fn("\xF0\x8F\xBB\xBF")); // U+FEFF (BOM)
  98. EXPECT_FALSE(fn("\xF8\x80\x80\x80\xBF")); // U+003F
  99. EXPECT_FALSE(fn("\xFC\x80\x80\x80\xA0\xA5")); // U+00A5
  100. // Beyond U+10FFFF (the upper limit of Unicode codespace)
  101. EXPECT_FALSE(fn("\xF4\x90\x80\x80")); // U+110000
  102. EXPECT_FALSE(fn("\xF8\xA0\xBF\x80\xBF")); // 5 bytes
  103. EXPECT_FALSE(fn("\xFC\x9C\xBF\x80\xBF\x80")); // 6 bytes
  104. // BOM in UTF-16(BE|LE)
  105. EXPECT_FALSE(fn("\xFE\xFF"));
  106. EXPECT_FALSE(fn("\xFF\xFE"));
  107. // Strings in legacy encodings. We can certainly make up strings
  108. // in a legacy encoding that are valid in UTF-8, but in real data,
  109. // most of them are invalid as UTF-8.
  110. // cafe with U+00E9 in ISO-8859-1
  111. EXPECT_FALSE(fn("caf\xE9"));
  112. // U+AC00, U+AC001 in EUC-KR
  113. EXPECT_FALSE(fn("\xB0\xA1\xB0\xA2"));
  114. // U+4F60 U+597D in Big5
  115. EXPECT_FALSE(fn("\xA7\x41\xA6\x6E"));
  116. // "abc" with U+201[CD] in windows-125[0-8]
  117. // clang-format off
  118. EXPECT_FALSE(fn("\x93" "abc\x94"));
  119. // clang-format on
  120. // U+0639 U+064E U+0644 U+064E in ISO-8859-6
  121. EXPECT_FALSE(fn("\xD9\xEE\xE4\xEE"));
  122. // U+03B3 U+03B5 U+03B9 U+03AC in ISO-8859-7
  123. EXPECT_FALSE(fn("\xE3\xE5\xE9\xDC"));
  124. // BOM in UTF-32(BE|LE)
  125. using std::string_literals::operator""s;
  126. const std::string kUtf32BeBom = "\x00\x00\xFE\xFF"s;
  127. EXPECT_FALSE(fn(kUtf32BeBom));
  128. const std::string kUtf32LeBom = "\xFF\xFE\x00\x00"s;
  129. EXPECT_FALSE(fn(kUtf32LeBom));
  130. }
  131. // Helper used to test IsStringUTF8{,AllowingNoncharacters}.
  132. void TestNoncharacters(TestFunction fn, bool expected_result) {
  133. EXPECT_EQ(fn("\xEF\xB7\x90"), expected_result); // U+FDD0
  134. EXPECT_EQ(fn("\xEF\xB7\x9F"), expected_result); // U+FDDF
  135. EXPECT_EQ(fn("\xEF\xB7\xAF"), expected_result); // U+FDEF
  136. EXPECT_EQ(fn("\xEF\xBF\xBE"), expected_result); // U+FFFE
  137. EXPECT_EQ(fn("\xEF\xBF\xBF"), expected_result); // U+FFFF
  138. EXPECT_EQ(fn("\xF0\x9F\xBF\xBE"), expected_result); // U+01FFFE
  139. EXPECT_EQ(fn("\xF0\x9F\xBF\xBF"), expected_result); // U+01FFFF
  140. EXPECT_EQ(fn("\xF0\xAF\xBF\xBE"), expected_result); // U+02FFFE
  141. EXPECT_EQ(fn("\xF0\xAF\xBF\xBF"), expected_result); // U+02FFFF
  142. EXPECT_EQ(fn("\xF0\xBF\xBF\xBE"), expected_result); // U+03FFFE
  143. EXPECT_EQ(fn("\xF0\xBF\xBF\xBF"), expected_result); // U+03FFFF
  144. EXPECT_EQ(fn("\xF1\x8F\xBF\xBE"), expected_result); // U+04FFFE
  145. EXPECT_EQ(fn("\xF1\x8F\xBF\xBF"), expected_result); // U+04FFFF
  146. EXPECT_EQ(fn("\xF1\x9F\xBF\xBE"), expected_result); // U+05FFFE
  147. EXPECT_EQ(fn("\xF1\x9F\xBF\xBF"), expected_result); // U+05FFFF
  148. EXPECT_EQ(fn("\xF1\xAF\xBF\xBE"), expected_result); // U+06FFFE
  149. EXPECT_EQ(fn("\xF1\xAF\xBF\xBF"), expected_result); // U+06FFFF
  150. EXPECT_EQ(fn("\xF1\xBF\xBF\xBE"), expected_result); // U+07FFFE
  151. EXPECT_EQ(fn("\xF1\xBF\xBF\xBF"), expected_result); // U+07FFFF
  152. EXPECT_EQ(fn("\xF2\x8F\xBF\xBE"), expected_result); // U+08FFFE
  153. EXPECT_EQ(fn("\xF2\x8F\xBF\xBF"), expected_result); // U+08FFFF
  154. EXPECT_EQ(fn("\xF2\x9F\xBF\xBE"), expected_result); // U+09FFFE
  155. EXPECT_EQ(fn("\xF2\x9F\xBF\xBF"), expected_result); // U+09FFFF
  156. EXPECT_EQ(fn("\xF2\xAF\xBF\xBE"), expected_result); // U+0AFFFE
  157. EXPECT_EQ(fn("\xF2\xAF\xBF\xBF"), expected_result); // U+0AFFFF
  158. EXPECT_EQ(fn("\xF2\xBF\xBF\xBE"), expected_result); // U+0BFFFE
  159. EXPECT_EQ(fn("\xF2\xBF\xBF\xBF"), expected_result); // U+0BFFFF
  160. EXPECT_EQ(fn("\xF3\x8F\xBF\xBE"), expected_result); // U+0CFFFE
  161. EXPECT_EQ(fn("\xF3\x8F\xBF\xBF"), expected_result); // U+0CFFFF
  162. EXPECT_EQ(fn("\xF3\x9F\xBF\xBE"), expected_result); // U+0DFFFE
  163. EXPECT_EQ(fn("\xF3\x9F\xBF\xBF"), expected_result); // U+0DFFFF
  164. EXPECT_EQ(fn("\xF3\xAF\xBF\xBE"), expected_result); // U+0EFFFE
  165. EXPECT_EQ(fn("\xF3\xAF\xBF\xBF"), expected_result); // U+0EFFFF
  166. EXPECT_EQ(fn("\xF3\xBF\xBF\xBE"), expected_result); // U+0FFFFE
  167. EXPECT_EQ(fn("\xF3\xBF\xBF\xBF"), expected_result); // U+0FFFFF
  168. EXPECT_EQ(fn("\xF4\x8F\xBF\xBE"), expected_result); // U+10FFFE
  169. EXPECT_EQ(fn("\xF4\x8F\xBF\xBF"), expected_result); // U+10FFFF
  170. }
  171. } // namespace
  172. TEST(StringUtilTest, TruncateUTF8ToByteSize) {
  173. std::string output;
  174. // Empty strings and invalid byte_size arguments
  175. EXPECT_FALSE(Truncated(std::string(), 0, &output));
  176. EXPECT_EQ(output, "");
  177. EXPECT_TRUE(Truncated("\xe1\x80\xbf", 0, &output));
  178. EXPECT_EQ(output, "");
  179. EXPECT_FALSE(Truncated("\xe1\x80\xbf", static_cast<size_t>(-1), &output));
  180. EXPECT_FALSE(Truncated("\xe1\x80\xbf", 4, &output));
  181. // Testing the truncation of valid UTF8 correctly
  182. EXPECT_TRUE(Truncated("abc", 2, &output));
  183. EXPECT_EQ(output, "ab");
  184. EXPECT_TRUE(Truncated("\xc2\x81\xc2\x81", 2, &output));
  185. EXPECT_EQ(output.compare("\xc2\x81"), 0);
  186. EXPECT_TRUE(Truncated("\xc2\x81\xc2\x81", 3, &output));
  187. EXPECT_EQ(output.compare("\xc2\x81"), 0);
  188. EXPECT_FALSE(Truncated("\xc2\x81\xc2\x81", 4, &output));
  189. EXPECT_EQ(output.compare("\xc2\x81\xc2\x81"), 0);
  190. {
  191. const char array[] = "\x00\x00\xc2\x81\xc2\x81";
  192. const std::string array_string(array, std::size(array));
  193. EXPECT_TRUE(Truncated(array_string, 4, &output));
  194. EXPECT_EQ(output.compare(std::string("\x00\x00\xc2\x81", 4)), 0);
  195. }
  196. {
  197. const char array[] = "\x00\xc2\x81\xc2\x81";
  198. const std::string array_string(array, std::size(array));
  199. EXPECT_TRUE(Truncated(array_string, 4, &output));
  200. EXPECT_EQ(output.compare(std::string("\x00\xc2\x81", 3)), 0);
  201. }
  202. // Testing invalid UTF8
  203. EXPECT_TRUE(Truncated("\xed\xa0\x80\xed\xbf\xbf", 6, &output));
  204. EXPECT_EQ(output.compare(""), 0);
  205. EXPECT_TRUE(Truncated("\xed\xa0\x8f", 3, &output));
  206. EXPECT_EQ(output.compare(""), 0);
  207. EXPECT_TRUE(Truncated("\xed\xbf\xbf", 3, &output));
  208. EXPECT_EQ(output.compare(""), 0);
  209. // Testing invalid UTF8 mixed with valid UTF8
  210. EXPECT_FALSE(Truncated("\xe1\x80\xbf", 3, &output));
  211. EXPECT_EQ(output.compare("\xe1\x80\xbf"), 0);
  212. EXPECT_FALSE(Truncated("\xf1\x80\xa0\xbf", 4, &output));
  213. EXPECT_EQ(output.compare("\xf1\x80\xa0\xbf"), 0);
  214. EXPECT_FALSE(Truncated("a\xc2\x81\xe1\x80\xbf\xf1\x80\xa0\xbf",
  215. 10, &output));
  216. EXPECT_EQ(output.compare("a\xc2\x81\xe1\x80\xbf\xf1\x80\xa0\xbf"), 0);
  217. EXPECT_TRUE(Truncated("a\xc2\x81\xe1\x80\xbf\xf1""a""\x80\xa0",
  218. 10, &output));
  219. EXPECT_EQ(output.compare("a\xc2\x81\xe1\x80\xbf\xf1""a"), 0);
  220. EXPECT_FALSE(Truncated("\xef\xbb\xbf" "abc", 6, &output));
  221. EXPECT_EQ(output.compare("\xef\xbb\xbf" "abc"), 0);
  222. // Overlong sequences
  223. EXPECT_TRUE(Truncated("\xc0\x80", 2, &output));
  224. EXPECT_EQ(output.compare(""), 0);
  225. EXPECT_TRUE(Truncated("\xc1\x80\xc1\x81", 4, &output));
  226. EXPECT_EQ(output.compare(""), 0);
  227. EXPECT_TRUE(Truncated("\xe0\x80\x80", 3, &output));
  228. EXPECT_EQ(output.compare(""), 0);
  229. EXPECT_TRUE(Truncated("\xe0\x82\x80", 3, &output));
  230. EXPECT_EQ(output.compare(""), 0);
  231. EXPECT_TRUE(Truncated("\xe0\x9f\xbf", 3, &output));
  232. EXPECT_EQ(output.compare(""), 0);
  233. EXPECT_TRUE(Truncated("\xf0\x80\x80\x8D", 4, &output));
  234. EXPECT_EQ(output.compare(""), 0);
  235. EXPECT_TRUE(Truncated("\xf0\x80\x82\x91", 4, &output));
  236. EXPECT_EQ(output.compare(""), 0);
  237. EXPECT_TRUE(Truncated("\xf0\x80\xa0\x80", 4, &output));
  238. EXPECT_EQ(output.compare(""), 0);
  239. EXPECT_TRUE(Truncated("\xf0\x8f\xbb\xbf", 4, &output));
  240. EXPECT_EQ(output.compare(""), 0);
  241. EXPECT_TRUE(Truncated("\xf8\x80\x80\x80\xbf", 5, &output));
  242. EXPECT_EQ(output.compare(""), 0);
  243. EXPECT_TRUE(Truncated("\xfc\x80\x80\x80\xa0\xa5", 6, &output));
  244. EXPECT_EQ(output.compare(""), 0);
  245. // Beyond U+10FFFF (the upper limit of Unicode codespace)
  246. EXPECT_TRUE(Truncated("\xf4\x90\x80\x80", 4, &output));
  247. EXPECT_EQ(output.compare(""), 0);
  248. EXPECT_TRUE(Truncated("\xf8\xa0\xbf\x80\xbf", 5, &output));
  249. EXPECT_EQ(output.compare(""), 0);
  250. EXPECT_TRUE(Truncated("\xfc\x9c\xbf\x80\xbf\x80", 6, &output));
  251. EXPECT_EQ(output.compare(""), 0);
  252. // BOMs in UTF-16(BE|LE) and UTF-32(BE|LE)
  253. EXPECT_TRUE(Truncated("\xfe\xff", 2, &output));
  254. EXPECT_EQ(output.compare(""), 0);
  255. EXPECT_TRUE(Truncated("\xff\xfe", 2, &output));
  256. EXPECT_EQ(output.compare(""), 0);
  257. {
  258. const char array[] = "\x00\x00\xfe\xff";
  259. const std::string array_string(array, std::size(array));
  260. EXPECT_TRUE(Truncated(array_string, 4, &output));
  261. EXPECT_EQ(output.compare(std::string("\x00\x00", 2)), 0);
  262. }
  263. // Variants on the previous test
  264. {
  265. const char array[] = "\xff\xfe\x00\x00";
  266. const std::string array_string(array, 4);
  267. EXPECT_FALSE(Truncated(array_string, 4, &output));
  268. EXPECT_EQ(output.compare(std::string("\xff\xfe\x00\x00", 4)), 0);
  269. }
  270. {
  271. const char array[] = "\xff\x00\x00\xfe";
  272. const std::string array_string(array, std::size(array));
  273. EXPECT_TRUE(Truncated(array_string, 4, &output));
  274. EXPECT_EQ(output.compare(std::string("\xff\x00\x00", 3)), 0);
  275. }
  276. // Non-characters : U+xxFFF[EF] where xx is 0x00 through 0x10 and <FDD0,FDEF>
  277. EXPECT_TRUE(Truncated("\xef\xbf\xbe", 3, &output));
  278. EXPECT_EQ(output.compare(""), 0);
  279. EXPECT_TRUE(Truncated("\xf0\x8f\xbf\xbe", 4, &output));
  280. EXPECT_EQ(output.compare(""), 0);
  281. EXPECT_TRUE(Truncated("\xf3\xbf\xbf\xbf", 4, &output));
  282. EXPECT_EQ(output.compare(""), 0);
  283. EXPECT_TRUE(Truncated("\xef\xb7\x90", 3, &output));
  284. EXPECT_EQ(output.compare(""), 0);
  285. EXPECT_TRUE(Truncated("\xef\xb7\xaf", 3, &output));
  286. EXPECT_EQ(output.compare(""), 0);
  287. // Strings in legacy encodings that are valid in UTF-8, but
  288. // are invalid as UTF-8 in real data.
  289. EXPECT_TRUE(Truncated("caf\xe9", 4, &output));
  290. EXPECT_EQ(output.compare("caf"), 0);
  291. EXPECT_TRUE(Truncated("\xb0\xa1\xb0\xa2", 4, &output));
  292. EXPECT_EQ(output.compare(""), 0);
  293. EXPECT_FALSE(Truncated("\xa7\x41\xa6\x6e", 4, &output));
  294. EXPECT_EQ(output.compare("\xa7\x41\xa6\x6e"), 0);
  295. EXPECT_TRUE(Truncated("\xa7\x41\xa6\x6e\xd9\xee\xe4\xee", 7,
  296. &output));
  297. EXPECT_EQ(output.compare("\xa7\x41\xa6\x6e"), 0);
  298. // Testing using the same string as input and output.
  299. EXPECT_FALSE(Truncated(output, 4, &output));
  300. EXPECT_EQ(output.compare("\xa7\x41\xa6\x6e"), 0);
  301. EXPECT_TRUE(Truncated(output, 3, &output));
  302. EXPECT_EQ(output.compare("\xa7\x41"), 0);
  303. // "abc" with U+201[CD] in windows-125[0-8]
  304. EXPECT_TRUE(Truncated("\x93" "abc\x94", 5, &output));
  305. EXPECT_EQ(output.compare("\x93" "abc"), 0);
  306. // U+0639 U+064E U+0644 U+064E in ISO-8859-6
  307. EXPECT_TRUE(Truncated("\xd9\xee\xe4\xee", 4, &output));
  308. EXPECT_EQ(output.compare(""), 0);
  309. // U+03B3 U+03B5 U+03B9 U+03AC in ISO-8859-7
  310. EXPECT_TRUE(Truncated("\xe3\xe5\xe9\xdC", 4, &output));
  311. EXPECT_EQ(output.compare(""), 0);
  312. }
  313. #if defined(WCHAR_T_IS_UTF16)
  314. TEST(StringUtilTest, as_wcstr) {
  315. char16_t rw_buffer[10] = {};
  316. static_assert(
  317. std::is_same<wchar_t*, decltype(as_writable_wcstr(rw_buffer))>::value,
  318. "");
  319. EXPECT_EQ(static_cast<void*>(rw_buffer), as_writable_wcstr(rw_buffer));
  320. std::u16string rw_str(10, '\0');
  321. static_assert(
  322. std::is_same<wchar_t*, decltype(as_writable_wcstr(rw_str))>::value, "");
  323. EXPECT_EQ(static_cast<const void*>(rw_str.data()), as_writable_wcstr(rw_str));
  324. const char16_t ro_buffer[10] = {};
  325. static_assert(
  326. std::is_same<const wchar_t*, decltype(as_wcstr(ro_buffer))>::value, "");
  327. EXPECT_EQ(static_cast<const void*>(ro_buffer), as_wcstr(ro_buffer));
  328. const std::u16string ro_str(10, '\0');
  329. static_assert(std::is_same<const wchar_t*, decltype(as_wcstr(ro_str))>::value,
  330. "");
  331. EXPECT_EQ(static_cast<const void*>(ro_str.data()), as_wcstr(ro_str));
  332. StringPiece16 piece = ro_buffer;
  333. static_assert(std::is_same<const wchar_t*, decltype(as_wcstr(piece))>::value,
  334. "");
  335. EXPECT_EQ(static_cast<const void*>(piece.data()), as_wcstr(piece));
  336. }
  337. TEST(StringUtilTest, as_u16cstr) {
  338. wchar_t rw_buffer[10] = {};
  339. static_assert(
  340. std::is_same<char16_t*, decltype(as_writable_u16cstr(rw_buffer))>::value,
  341. "");
  342. EXPECT_EQ(static_cast<void*>(rw_buffer), as_writable_u16cstr(rw_buffer));
  343. std::wstring rw_str(10, '\0');
  344. static_assert(
  345. std::is_same<char16_t*, decltype(as_writable_u16cstr(rw_str))>::value,
  346. "");
  347. EXPECT_EQ(static_cast<const void*>(rw_str.data()),
  348. as_writable_u16cstr(rw_str));
  349. const wchar_t ro_buffer[10] = {};
  350. static_assert(
  351. std::is_same<const char16_t*, decltype(as_u16cstr(ro_buffer))>::value,
  352. "");
  353. EXPECT_EQ(static_cast<const void*>(ro_buffer), as_u16cstr(ro_buffer));
  354. const std::wstring ro_str(10, '\0');
  355. static_assert(
  356. std::is_same<const char16_t*, decltype(as_u16cstr(ro_str))>::value, "");
  357. EXPECT_EQ(static_cast<const void*>(ro_str.data()), as_u16cstr(ro_str));
  358. WStringPiece piece = ro_buffer;
  359. static_assert(
  360. std::is_same<const char16_t*, decltype(as_u16cstr(piece))>::value, "");
  361. EXPECT_EQ(static_cast<const void*>(piece.data()), as_u16cstr(piece));
  362. }
  363. #endif // defined(WCHAR_T_IS_UTF16)
  364. TEST(StringUtilTest, TrimWhitespace) {
  365. std::u16string output; // Allow contents to carry over to next testcase
  366. for (const auto& value : trim_cases) {
  367. EXPECT_EQ(value.return_value,
  368. TrimWhitespace(WideToUTF16(value.input), value.positions,
  369. &output));
  370. EXPECT_EQ(WideToUTF16(value.output), output);
  371. }
  372. // Test that TrimWhitespace() can take the same string for input and output
  373. output = u" This is a test \r\n";
  374. EXPECT_EQ(TRIM_ALL, TrimWhitespace(output, TRIM_ALL, &output));
  375. EXPECT_EQ(u"This is a test", output);
  376. // Once more, but with a string of whitespace
  377. output = u" \r\n";
  378. EXPECT_EQ(TRIM_ALL, TrimWhitespace(output, TRIM_ALL, &output));
  379. EXPECT_EQ(std::u16string(), output);
  380. std::string output_ascii;
  381. for (const auto& value : trim_cases_ascii) {
  382. EXPECT_EQ(value.return_value,
  383. TrimWhitespaceASCII(value.input, value.positions, &output_ascii));
  384. EXPECT_EQ(value.output, output_ascii);
  385. }
  386. }
  387. static const struct collapse_case {
  388. const wchar_t* input;
  389. const bool trim;
  390. const wchar_t* output;
  391. } collapse_cases[] = {
  392. {L" Google Video ", false, L"Google Video"},
  393. {L"Google Video", false, L"Google Video"},
  394. {L"", false, L""},
  395. {L" ", false, L""},
  396. {L"\t\rTest String\n", false, L"Test String"},
  397. {L"\x2002Test String\x00A0\x3000", false, L"Test String"},
  398. {L" Test \n \t String ", false, L"Test String"},
  399. {L"\x2002Test\x1680 \x2028 \tString\x00A0\x3000", false, L"Test String"},
  400. {L" Test String", false, L"Test String"},
  401. {L"Test String ", false, L"Test String"},
  402. {L"Test String", false, L"Test String"},
  403. {L"", true, L""},
  404. {L"\n", true, L""},
  405. {L" \r ", true, L""},
  406. {L"\nFoo", true, L"Foo"},
  407. {L"\r Foo ", true, L"Foo"},
  408. {L" Foo bar ", true, L"Foo bar"},
  409. {L" \tFoo bar \n", true, L"Foo bar"},
  410. {L" a \r b\n c \r\n d \t\re \t f \n ", true, L"abcde f"},
  411. };
  412. TEST(StringUtilTest, CollapseWhitespace) {
  413. for (const auto& value : collapse_cases) {
  414. EXPECT_EQ(WideToUTF16(value.output),
  415. CollapseWhitespace(WideToUTF16(value.input), value.trim));
  416. }
  417. }
  418. static const struct collapse_case_ascii {
  419. const char* input;
  420. const bool trim;
  421. const char* output;
  422. } collapse_cases_ascii[] = {
  423. {" Google Video ", false, "Google Video"},
  424. {"Google Video", false, "Google Video"},
  425. {"", false, ""},
  426. {" ", false, ""},
  427. {"\t\rTest String\n", false, "Test String"},
  428. {" Test \n \t String ", false, "Test String"},
  429. {" Test String", false, "Test String"},
  430. {"Test String ", false, "Test String"},
  431. {"Test String", false, "Test String"},
  432. {"", true, ""},
  433. {"\n", true, ""},
  434. {" \r ", true, ""},
  435. {"\nFoo", true, "Foo"},
  436. {"\r Foo ", true, "Foo"},
  437. {" Foo bar ", true, "Foo bar"},
  438. {" \tFoo bar \n", true, "Foo bar"},
  439. {" a \r b\n c \r\n d \t\re \t f \n ", true, "abcde f"},
  440. };
  441. TEST(StringUtilTest, CollapseWhitespaceASCII) {
  442. for (const auto& value : collapse_cases_ascii) {
  443. EXPECT_EQ(value.output, CollapseWhitespaceASCII(value.input, value.trim));
  444. }
  445. }
  446. TEST(StringUtilTest, IsStringUTF8) {
  447. {
  448. SCOPED_TRACE("IsStringUTF8");
  449. TestStructurallyValidUtf8(&IsStringUTF8);
  450. TestStructurallyInvalidUtf8(&IsStringUTF8);
  451. TestNoncharacters(&IsStringUTF8, false);
  452. }
  453. {
  454. SCOPED_TRACE("IsStringUTF8AllowingNoncharacters");
  455. TestStructurallyValidUtf8(&IsStringUTF8AllowingNoncharacters);
  456. TestStructurallyInvalidUtf8(&IsStringUTF8AllowingNoncharacters);
  457. TestNoncharacters(&IsStringUTF8AllowingNoncharacters, true);
  458. }
  459. }
  460. TEST(StringUtilTest, IsStringASCII) {
  461. static char char_ascii[] =
  462. "0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF";
  463. static char16_t char16_ascii[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8',
  464. '9', '0', 'A', 'B', 'C', 'D', 'E', 'F', '0',
  465. '1', '2', '3', '4', '5', '6', '7', '8', '9',
  466. '0', 'A', 'B', 'C', 'D', 'E', 'F', 0};
  467. static std::wstring wchar_ascii(
  468. L"0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF");
  469. // Test a variety of the fragment start positions and lengths in order to make
  470. // sure that bit masking in IsStringASCII works correctly.
  471. // Also, test that a non-ASCII character will be detected regardless of its
  472. // position inside the string.
  473. {
  474. const size_t string_length = std::size(char_ascii) - 1;
  475. for (size_t offset = 0; offset < 8; ++offset) {
  476. for (size_t len = 0, max_len = string_length - offset; len < max_len;
  477. ++len) {
  478. EXPECT_TRUE(IsStringASCII(StringPiece(char_ascii + offset, len)));
  479. for (size_t char_pos = offset; char_pos < len; ++char_pos) {
  480. char_ascii[char_pos] |= '\x80';
  481. EXPECT_FALSE(IsStringASCII(StringPiece(char_ascii + offset, len)));
  482. char_ascii[char_pos] &= ~'\x80';
  483. }
  484. }
  485. }
  486. }
  487. {
  488. const size_t string_length = std::size(char16_ascii) - 1;
  489. for (size_t offset = 0; offset < 4; ++offset) {
  490. for (size_t len = 0, max_len = string_length - offset; len < max_len;
  491. ++len) {
  492. EXPECT_TRUE(IsStringASCII(StringPiece16(char16_ascii + offset, len)));
  493. for (size_t char_pos = offset; char_pos < len; ++char_pos) {
  494. char16_ascii[char_pos] |= 0x80;
  495. EXPECT_FALSE(
  496. IsStringASCII(StringPiece16(char16_ascii + offset, len)));
  497. char16_ascii[char_pos] &= ~0x80;
  498. // Also test when the upper half is non-zero.
  499. char16_ascii[char_pos] |= 0x100;
  500. EXPECT_FALSE(
  501. IsStringASCII(StringPiece16(char16_ascii + offset, len)));
  502. char16_ascii[char_pos] &= ~0x100;
  503. }
  504. }
  505. }
  506. }
  507. #if defined(WCHAR_T_IS_UTF32)
  508. {
  509. const size_t string_length = wchar_ascii.length();
  510. for (size_t len = 0; len < string_length; ++len) {
  511. EXPECT_TRUE(IsStringASCII(wchar_ascii.substr(0, len)));
  512. for (size_t char_pos = 0; char_pos < len; ++char_pos) {
  513. wchar_ascii[char_pos] |= 0x80;
  514. EXPECT_FALSE(IsStringASCII(wchar_ascii.substr(0, len)));
  515. wchar_ascii[char_pos] &= ~0x80;
  516. wchar_ascii[char_pos] |= 0x100;
  517. EXPECT_FALSE(IsStringASCII(wchar_ascii.substr(0, len)));
  518. wchar_ascii[char_pos] &= ~0x100;
  519. wchar_ascii[char_pos] |= 0x10000;
  520. EXPECT_FALSE(IsStringASCII(wchar_ascii.substr(0, len)));
  521. wchar_ascii[char_pos] &= ~0x10000;
  522. }
  523. }
  524. }
  525. #endif // WCHAR_T_IS_UTF32
  526. }
  527. TEST(StringUtilTest, ConvertASCII) {
  528. static const char* const char_cases[] = {
  529. "Google Video",
  530. "Hello, world\n",
  531. "0123ABCDwxyz \a\b\t\r\n!+,.~"
  532. };
  533. static const wchar_t* const wchar_cases[] = {
  534. L"Google Video",
  535. L"Hello, world\n",
  536. L"0123ABCDwxyz \a\b\t\r\n!+,.~"
  537. };
  538. for (size_t i = 0; i < std::size(char_cases); ++i) {
  539. EXPECT_TRUE(IsStringASCII(char_cases[i]));
  540. std::u16string utf16 = ASCIIToUTF16(char_cases[i]);
  541. EXPECT_EQ(WideToUTF16(wchar_cases[i]), utf16);
  542. std::string ascii = UTF16ToASCII(WideToUTF16(wchar_cases[i]));
  543. EXPECT_EQ(char_cases[i], ascii);
  544. }
  545. EXPECT_FALSE(IsStringASCII("Google \x80Video"));
  546. // Convert empty strings.
  547. std::u16string empty16;
  548. std::string empty;
  549. EXPECT_EQ(empty, UTF16ToASCII(empty16));
  550. EXPECT_EQ(empty16, ASCIIToUTF16(empty));
  551. // Convert strings with an embedded NUL character.
  552. const char chars_with_nul[] = "test\0string";
  553. const int length_with_nul = std::size(chars_with_nul) - 1;
  554. std::string string_with_nul(chars_with_nul, length_with_nul);
  555. std::u16string string16_with_nul = ASCIIToUTF16(string_with_nul);
  556. EXPECT_EQ(static_cast<std::u16string::size_type>(length_with_nul),
  557. string16_with_nul.length());
  558. std::string narrow_with_nul = UTF16ToASCII(string16_with_nul);
  559. EXPECT_EQ(static_cast<std::string::size_type>(length_with_nul),
  560. narrow_with_nul.length());
  561. EXPECT_EQ(0, string_with_nul.compare(narrow_with_nul));
  562. }
  563. TEST(StringUtilTest, ToLowerASCII) {
  564. EXPECT_EQ('c', ToLowerASCII('C'));
  565. EXPECT_EQ('c', ToLowerASCII('c'));
  566. EXPECT_EQ('2', ToLowerASCII('2'));
  567. EXPECT_EQ(u'c', ToLowerASCII(u'C'));
  568. EXPECT_EQ(u'c', ToLowerASCII(u'c'));
  569. EXPECT_EQ(u'2', ToLowerASCII(u'2'));
  570. EXPECT_EQ("cc2", ToLowerASCII("Cc2"));
  571. EXPECT_EQ(u"cc2", ToLowerASCII(u"Cc2"));
  572. }
  573. TEST(StringUtilTest, ToUpperASCII) {
  574. EXPECT_EQ('C', ToUpperASCII('C'));
  575. EXPECT_EQ('C', ToUpperASCII('c'));
  576. EXPECT_EQ('2', ToUpperASCII('2'));
  577. EXPECT_EQ(u'C', ToUpperASCII(u'C'));
  578. EXPECT_EQ(u'C', ToUpperASCII(u'c'));
  579. EXPECT_EQ(u'2', ToUpperASCII(u'2'));
  580. EXPECT_EQ("CC2", ToUpperASCII("Cc2"));
  581. EXPECT_EQ(u"CC2", ToUpperASCII(u"Cc2"));
  582. }
  583. TEST(StringUtilTest, FormatBytesUnlocalized) {
  584. static const struct {
  585. int64_t bytes;
  586. const char* expected;
  587. } cases[] = {
  588. // Expected behavior: we show one post-decimal digit when we have
  589. // under two pre-decimal digits, except in cases where it makes no
  590. // sense (zero or bytes).
  591. // Since we switch units once we cross the 1000 mark, this keeps
  592. // the display of file sizes or bytes consistently around three
  593. // digits.
  594. {0, "0 B"},
  595. {512, "512 B"},
  596. {1024 * 1024, "1.0 MB"},
  597. {1024 * 1024 * 1024, "1.0 GB"},
  598. {10LL * 1024 * 1024 * 1024, "10.0 GB"},
  599. {99LL * 1024 * 1024 * 1024, "99.0 GB"},
  600. {105LL * 1024 * 1024 * 1024, "105 GB"},
  601. {105LL * 1024 * 1024 * 1024 + 500LL * 1024 * 1024, "105 GB"},
  602. {~(bits::LeftmostBit<int64_t>()), "8192 PB"},
  603. {99 * 1024 + 103, "99.1 kB"},
  604. {1024 * 1024 + 103, "1.0 MB"},
  605. {1024 * 1024 + 205 * 1024, "1.2 MB"},
  606. {1024 * 1024 * 1024 + (927 * 1024 * 1024), "1.9 GB"},
  607. {10LL * 1024 * 1024 * 1024, "10.0 GB"},
  608. {100LL * 1024 * 1024 * 1024, "100 GB"},
  609. };
  610. for (const auto& i : cases) {
  611. EXPECT_EQ(ASCIIToUTF16(i.expected), FormatBytesUnlocalized(i.bytes));
  612. }
  613. }
  614. TEST(StringUtilTest, ReplaceSubstringsAfterOffset) {
  615. static const struct {
  616. StringPiece str;
  617. size_t start_offset;
  618. StringPiece find_this;
  619. StringPiece replace_with;
  620. StringPiece expected;
  621. } cases[] = {
  622. {"aaa", 0, "", "b", "aaa"},
  623. {"aaa", 1, "", "b", "aaa"},
  624. {"aaa", 0, "a", "b", "bbb"},
  625. {"aaa", 0, "aa", "b", "ba"},
  626. {"aaa", 0, "aa", "bbb", "bbba"},
  627. {"aaaaa", 0, "aa", "b", "bba"},
  628. {"ababaaababa", 0, "aba", "", "baaba"},
  629. {"ababaaababa", 0, "aba", "_", "_baa_ba"},
  630. {"ababaaababa", 0, "aba", "__", "__baa__ba"},
  631. {"ababaaababa", 0, "aba", "___", "___baa___ba"},
  632. {"ababaaababa", 0, "aba", "____", "____baa____ba"},
  633. {"ababaaababa", 0, "aba", "_____", "_____baa_____ba"},
  634. {"abb", 0, "ab", "a", "ab"},
  635. {"Removing some substrings inging", 0, "ing", "", "Remov some substrs "},
  636. {"Not found", 0, "x", "0", "Not found"},
  637. {"Not found again", 5, "x", "0", "Not found again"},
  638. {" Making it much longer ", 0, " ", "Four score and seven years ago",
  639. "Four score and seven years agoMakingFour score and seven years agoit"
  640. "Four score and seven years agomuchFour score and seven years agolonger"
  641. "Four score and seven years ago"},
  642. {" Making it much much much much shorter ", 0,
  643. "Making it much much much much shorter", "", " "},
  644. {"so much much much much much very much much much shorter", 0, "much ",
  645. "", "so very shorter"},
  646. {"Invalid offset", 9999, "t", "foobar", "Invalid offset"},
  647. {"Replace me only me once", 9, "me ", "", "Replace me only once"},
  648. {"abababab", 2, "ab", "c", "abccc"},
  649. {"abababab", 1, "ab", "c", "abccc"},
  650. {"abababab", 1, "aba", "c", "abcbab"},
  651. };
  652. // std::u16string variant
  653. for (const auto& scenario : cases) {
  654. std::u16string str = ASCIIToUTF16(scenario.str);
  655. ReplaceSubstringsAfterOffset(&str, scenario.start_offset,
  656. ASCIIToUTF16(scenario.find_this),
  657. ASCIIToUTF16(scenario.replace_with));
  658. EXPECT_EQ(ASCIIToUTF16(scenario.expected), str);
  659. }
  660. // std::string with insufficient capacity: expansion must realloc the buffer.
  661. for (const auto& scenario : cases) {
  662. std::string str(scenario.str);
  663. str.shrink_to_fit(); // This is nonbinding, but it's the best we've got.
  664. ReplaceSubstringsAfterOffset(&str, scenario.start_offset,
  665. scenario.find_this, scenario.replace_with);
  666. EXPECT_EQ(scenario.expected, str);
  667. }
  668. // std::string with ample capacity: should be possible to grow in-place.
  669. for (const auto& scenario : cases) {
  670. std::string str(scenario.str);
  671. str.reserve(std::max(scenario.str.length(), scenario.expected.length()) *
  672. 2);
  673. ReplaceSubstringsAfterOffset(&str, scenario.start_offset,
  674. scenario.find_this, scenario.replace_with);
  675. EXPECT_EQ(scenario.expected, str);
  676. }
  677. }
  678. TEST(StringUtilTest, ReplaceFirstSubstringAfterOffset) {
  679. static const struct {
  680. const char* str;
  681. std::u16string::size_type start_offset;
  682. const char* find_this;
  683. const char* replace_with;
  684. const char* expected;
  685. } cases[] = {
  686. {"aaa", 0, "a", "b", "baa"},
  687. {"abb", 0, "ab", "a", "ab"},
  688. {"Removing some substrings inging", 0, "ing", "",
  689. "Remov some substrings inging"},
  690. {"Not found", 0, "x", "0", "Not found"},
  691. {"Not found again", 5, "x", "0", "Not found again"},
  692. {" Making it much longer ", 0, " ", "Four score and seven years ago",
  693. "Four score and seven years agoMaking it much longer "},
  694. {"Invalid offset", 9999, "t", "foobar", "Invalid offset"},
  695. {"Replace me only me once", 4, "me ", "", "Replace only me once"},
  696. {"abababab", 2, "ab", "c", "abcabab"},
  697. };
  698. for (const auto& i : cases) {
  699. std::u16string str = ASCIIToUTF16(i.str);
  700. ReplaceFirstSubstringAfterOffset(&str, i.start_offset,
  701. ASCIIToUTF16(i.find_this),
  702. ASCIIToUTF16(i.replace_with));
  703. EXPECT_EQ(ASCIIToUTF16(i.expected), str);
  704. }
  705. }
  706. TEST(StringUtilTest, HexDigitToInt) {
  707. EXPECT_EQ(0, HexDigitToInt('0'));
  708. EXPECT_EQ(1, HexDigitToInt('1'));
  709. EXPECT_EQ(2, HexDigitToInt('2'));
  710. EXPECT_EQ(3, HexDigitToInt('3'));
  711. EXPECT_EQ(4, HexDigitToInt('4'));
  712. EXPECT_EQ(5, HexDigitToInt('5'));
  713. EXPECT_EQ(6, HexDigitToInt('6'));
  714. EXPECT_EQ(7, HexDigitToInt('7'));
  715. EXPECT_EQ(8, HexDigitToInt('8'));
  716. EXPECT_EQ(9, HexDigitToInt('9'));
  717. EXPECT_EQ(10, HexDigitToInt('A'));
  718. EXPECT_EQ(11, HexDigitToInt('B'));
  719. EXPECT_EQ(12, HexDigitToInt('C'));
  720. EXPECT_EQ(13, HexDigitToInt('D'));
  721. EXPECT_EQ(14, HexDigitToInt('E'));
  722. EXPECT_EQ(15, HexDigitToInt('F'));
  723. // Verify the lower case as well.
  724. EXPECT_EQ(10, HexDigitToInt('a'));
  725. EXPECT_EQ(11, HexDigitToInt('b'));
  726. EXPECT_EQ(12, HexDigitToInt('c'));
  727. EXPECT_EQ(13, HexDigitToInt('d'));
  728. EXPECT_EQ(14, HexDigitToInt('e'));
  729. EXPECT_EQ(15, HexDigitToInt('f'));
  730. }
  731. TEST(StringUtilTest, JoinString) {
  732. std::string separator(", ");
  733. std::vector<std::string> parts;
  734. EXPECT_EQ(std::string(), JoinString(parts, separator));
  735. parts.push_back(std::string());
  736. EXPECT_EQ(std::string(), JoinString(parts, separator));
  737. parts.clear();
  738. parts.push_back("a");
  739. EXPECT_EQ("a", JoinString(parts, separator));
  740. parts.push_back("b");
  741. parts.push_back("c");
  742. EXPECT_EQ("a, b, c", JoinString(parts, separator));
  743. parts.push_back(std::string());
  744. EXPECT_EQ("a, b, c, ", JoinString(parts, separator));
  745. parts.push_back(" ");
  746. EXPECT_EQ("a|b|c|| ", JoinString(parts, "|"));
  747. }
  748. TEST(StringUtilTest, JoinString16) {
  749. std::u16string separator = u", ";
  750. std::vector<std::u16string> parts;
  751. EXPECT_EQ(std::u16string(), JoinString(parts, separator));
  752. parts.push_back(std::u16string());
  753. EXPECT_EQ(std::u16string(), JoinString(parts, separator));
  754. parts.clear();
  755. parts.push_back(u"a");
  756. EXPECT_EQ(u"a", JoinString(parts, separator));
  757. parts.push_back(u"b");
  758. parts.push_back(u"c");
  759. EXPECT_EQ(u"a, b, c", JoinString(parts, separator));
  760. parts.push_back(u"");
  761. EXPECT_EQ(u"a, b, c, ", JoinString(parts, separator));
  762. parts.push_back(u" ");
  763. EXPECT_EQ(u"a|b|c|| ", JoinString(parts, u"|"));
  764. }
  765. TEST(StringUtilTest, JoinStringPiece) {
  766. std::string separator(", ");
  767. std::vector<StringPiece> parts;
  768. EXPECT_EQ(std::string(), JoinString(parts, separator));
  769. // Test empty first part (https://crbug.com/698073).
  770. parts.push_back(StringPiece());
  771. EXPECT_EQ(std::string(), JoinString(parts, separator));
  772. parts.clear();
  773. parts.push_back("a");
  774. EXPECT_EQ("a", JoinString(parts, separator));
  775. parts.push_back("b");
  776. parts.push_back("c");
  777. EXPECT_EQ("a, b, c", JoinString(parts, separator));
  778. parts.push_back(StringPiece());
  779. EXPECT_EQ("a, b, c, ", JoinString(parts, separator));
  780. parts.push_back(" ");
  781. EXPECT_EQ("a|b|c|| ", JoinString(parts, "|"));
  782. }
  783. TEST(StringUtilTest, JoinStringPiece16) {
  784. std::u16string separator = u", ";
  785. std::vector<StringPiece16> parts;
  786. EXPECT_EQ(std::u16string(), JoinString(parts, separator));
  787. // Test empty first part (https://crbug.com/698073).
  788. parts.push_back(StringPiece16());
  789. EXPECT_EQ(std::u16string(), JoinString(parts, separator));
  790. parts.clear();
  791. const std::u16string kA = u"a";
  792. parts.push_back(kA);
  793. EXPECT_EQ(u"a", JoinString(parts, separator));
  794. const std::u16string kB = u"b";
  795. parts.push_back(kB);
  796. const std::u16string kC = u"c";
  797. parts.push_back(kC);
  798. EXPECT_EQ(u"a, b, c", JoinString(parts, separator));
  799. parts.push_back(StringPiece16());
  800. EXPECT_EQ(u"a, b, c, ", JoinString(parts, separator));
  801. const std::u16string kSpace = u" ";
  802. parts.push_back(kSpace);
  803. EXPECT_EQ(u"a|b|c|| ", JoinString(parts, u"|"));
  804. }
  805. TEST(StringUtilTest, JoinStringInitializerList) {
  806. std::string separator(", ");
  807. EXPECT_EQ(std::string(), JoinString({}, separator));
  808. // Test empty first part (https://crbug.com/698073).
  809. EXPECT_EQ(std::string(), JoinString({StringPiece()}, separator));
  810. // With const char*s.
  811. EXPECT_EQ("a", JoinString({"a"}, separator));
  812. EXPECT_EQ("a, b, c", JoinString({"a", "b", "c"}, separator));
  813. EXPECT_EQ("a, b, c, ", JoinString({"a", "b", "c", StringPiece()}, separator));
  814. EXPECT_EQ("a|b|c|| ", JoinString({"a", "b", "c", StringPiece(), " "}, "|"));
  815. // With std::strings.
  816. const std::string kA = "a";
  817. const std::string kB = "b";
  818. EXPECT_EQ("a, b", JoinString({kA, kB}, separator));
  819. // With StringPieces.
  820. const StringPiece kPieceA = kA;
  821. const StringPiece kPieceB = kB;
  822. EXPECT_EQ("a, b", JoinString({kPieceA, kPieceB}, separator));
  823. }
  824. TEST(StringUtilTest, JoinStringInitializerList16) {
  825. std::u16string separator = u", ";
  826. EXPECT_EQ(std::u16string(), JoinString({}, separator));
  827. // Test empty first part (https://crbug.com/698073).
  828. EXPECT_EQ(std::u16string(), JoinString({StringPiece16()}, separator));
  829. // With string16s.
  830. const std::u16string kA = u"a";
  831. EXPECT_EQ(u"a", JoinString({kA}, separator));
  832. const std::u16string kB = u"b";
  833. const std::u16string kC = u"c";
  834. EXPECT_EQ(u"a, b, c", JoinString({kA, kB, kC}, separator));
  835. EXPECT_EQ(u"a, b, c, ", JoinString({kA, kB, kC, StringPiece16()}, separator));
  836. const std::u16string kSpace = u" ";
  837. EXPECT_EQ(u"a|b|c|| ",
  838. JoinString({kA, kB, kC, StringPiece16(), kSpace}, u"|"));
  839. // With StringPiece16s.
  840. const StringPiece16 kPieceA = kA;
  841. const StringPiece16 kPieceB = kB;
  842. EXPECT_EQ(u"a, b", JoinString({kPieceA, kPieceB}, separator));
  843. }
  844. TEST(StringUtilTest, StartsWith) {
  845. EXPECT_TRUE(StartsWith("javascript:url", "javascript",
  846. base::CompareCase::SENSITIVE));
  847. EXPECT_FALSE(StartsWith("JavaScript:url", "javascript",
  848. base::CompareCase::SENSITIVE));
  849. EXPECT_TRUE(StartsWith("javascript:url", "javascript",
  850. base::CompareCase::INSENSITIVE_ASCII));
  851. EXPECT_TRUE(StartsWith("JavaScript:url", "javascript",
  852. base::CompareCase::INSENSITIVE_ASCII));
  853. EXPECT_FALSE(StartsWith("java", "javascript", base::CompareCase::SENSITIVE));
  854. EXPECT_FALSE(StartsWith("java", "javascript",
  855. base::CompareCase::INSENSITIVE_ASCII));
  856. EXPECT_FALSE(StartsWith(std::string(), "javascript",
  857. base::CompareCase::INSENSITIVE_ASCII));
  858. EXPECT_FALSE(StartsWith(std::string(), "javascript",
  859. base::CompareCase::SENSITIVE));
  860. EXPECT_TRUE(StartsWith("java", std::string(),
  861. base::CompareCase::INSENSITIVE_ASCII));
  862. EXPECT_TRUE(StartsWith("java", std::string(), base::CompareCase::SENSITIVE));
  863. EXPECT_TRUE(StartsWith(u"javascript:url", u"javascript",
  864. base::CompareCase::SENSITIVE));
  865. EXPECT_FALSE(StartsWith(u"JavaScript:url", u"javascript",
  866. base::CompareCase::SENSITIVE));
  867. EXPECT_TRUE(StartsWith(u"javascript:url", u"javascript",
  868. base::CompareCase::INSENSITIVE_ASCII));
  869. EXPECT_TRUE(StartsWith(u"JavaScript:url", u"javascript",
  870. base::CompareCase::INSENSITIVE_ASCII));
  871. EXPECT_FALSE(
  872. StartsWith(u"java", u"javascript", base::CompareCase::SENSITIVE));
  873. EXPECT_FALSE(
  874. StartsWith(u"java", u"javascript", base::CompareCase::INSENSITIVE_ASCII));
  875. EXPECT_FALSE(StartsWith(std::u16string(), u"javascript",
  876. base::CompareCase::INSENSITIVE_ASCII));
  877. EXPECT_FALSE(StartsWith(std::u16string(), u"javascript",
  878. base::CompareCase::SENSITIVE));
  879. EXPECT_TRUE(StartsWith(u"java", std::u16string(),
  880. base::CompareCase::INSENSITIVE_ASCII));
  881. EXPECT_TRUE(
  882. StartsWith(u"java", std::u16string(), base::CompareCase::SENSITIVE));
  883. }
  884. TEST(StringUtilTest, EndsWith) {
  885. EXPECT_TRUE(
  886. EndsWith(u"Foo.plugin", u".plugin", base::CompareCase::SENSITIVE));
  887. EXPECT_FALSE(
  888. EndsWith(u"Foo.Plugin", u".plugin", base::CompareCase::SENSITIVE));
  889. EXPECT_TRUE(EndsWith(u"Foo.plugin", u".plugin",
  890. base::CompareCase::INSENSITIVE_ASCII));
  891. EXPECT_TRUE(EndsWith(u"Foo.Plugin", u".plugin",
  892. base::CompareCase::INSENSITIVE_ASCII));
  893. EXPECT_FALSE(EndsWith(u".plug", u".plugin", base::CompareCase::SENSITIVE));
  894. EXPECT_FALSE(
  895. EndsWith(u".plug", u".plugin", base::CompareCase::INSENSITIVE_ASCII));
  896. EXPECT_FALSE(
  897. EndsWith(u"Foo.plugin Bar", u".plugin", base::CompareCase::SENSITIVE));
  898. EXPECT_FALSE(EndsWith(u"Foo.plugin Bar", u".plugin",
  899. base::CompareCase::INSENSITIVE_ASCII));
  900. EXPECT_FALSE(EndsWith(std::u16string(), u".plugin",
  901. base::CompareCase::INSENSITIVE_ASCII));
  902. EXPECT_FALSE(
  903. EndsWith(std::u16string(), u".plugin", base::CompareCase::SENSITIVE));
  904. EXPECT_TRUE(EndsWith(u"Foo.plugin", std::u16string(),
  905. base::CompareCase::INSENSITIVE_ASCII));
  906. EXPECT_TRUE(
  907. EndsWith(u"Foo.plugin", std::u16string(), base::CompareCase::SENSITIVE));
  908. EXPECT_TRUE(
  909. EndsWith(u".plugin", u".plugin", base::CompareCase::INSENSITIVE_ASCII));
  910. EXPECT_TRUE(EndsWith(u".plugin", u".plugin", base::CompareCase::SENSITIVE));
  911. EXPECT_TRUE(EndsWith(std::u16string(), std::u16string(),
  912. base::CompareCase::INSENSITIVE_ASCII));
  913. EXPECT_TRUE(EndsWith(std::u16string(), std::u16string(),
  914. base::CompareCase::SENSITIVE));
  915. }
  916. TEST(StringUtilTest, GetStringFWithOffsets) {
  917. std::vector<std::u16string> subst;
  918. subst.push_back(u"1");
  919. subst.push_back(u"2");
  920. std::vector<size_t> offsets;
  921. ReplaceStringPlaceholders(u"Hello, $1. Your number is $2.", subst, &offsets);
  922. EXPECT_EQ(2U, offsets.size());
  923. EXPECT_EQ(7U, offsets[0]);
  924. EXPECT_EQ(25U, offsets[1]);
  925. offsets.clear();
  926. ReplaceStringPlaceholders(u"Hello, $2. Your number is $1.", subst, &offsets);
  927. EXPECT_EQ(2U, offsets.size());
  928. EXPECT_EQ(25U, offsets[0]);
  929. EXPECT_EQ(7U, offsets[1]);
  930. offsets.clear();
  931. }
  932. TEST(StringUtilTest, ReplaceStringPlaceholdersTooFew) {
  933. // Test whether replacestringplaceholders works as expected when there
  934. // are fewer inputs than outputs.
  935. std::vector<std::u16string> subst;
  936. subst.push_back(u"9a");
  937. subst.push_back(u"8b");
  938. subst.push_back(u"7c");
  939. std::u16string formatted = ReplaceStringPlaceholders(
  940. u"$1a,$2b,$3c,$4d,$5e,$6f,$1g,$2h,$3i", subst, nullptr);
  941. EXPECT_EQ(u"9aa,8bb,7cc,d,e,f,9ag,8bh,7ci", formatted);
  942. }
  943. TEST(StringUtilTest, ReplaceStringPlaceholders) {
  944. std::vector<std::u16string> subst;
  945. subst.push_back(u"9a");
  946. subst.push_back(u"8b");
  947. subst.push_back(u"7c");
  948. subst.push_back(u"6d");
  949. subst.push_back(u"5e");
  950. subst.push_back(u"4f");
  951. subst.push_back(u"3g");
  952. subst.push_back(u"2h");
  953. subst.push_back(u"1i");
  954. std::u16string formatted = ReplaceStringPlaceholders(
  955. u"$1a,$2b,$3c,$4d,$5e,$6f,$7g,$8h,$9i", subst, nullptr);
  956. EXPECT_EQ(u"9aa,8bb,7cc,6dd,5ee,4ff,3gg,2hh,1ii", formatted);
  957. }
  958. TEST(StringUtilTest, ReplaceStringPlaceholdersNetExpansionWithContraction) {
  959. // In this test, some of the substitutions are shorter than the placeholders,
  960. // but overall the string gets longer.
  961. std::vector<std::u16string> subst;
  962. subst.push_back(u"9a____");
  963. subst.push_back(u"B");
  964. subst.push_back(u"7c___");
  965. subst.push_back(u"d");
  966. subst.push_back(u"5e____");
  967. subst.push_back(u"F");
  968. subst.push_back(u"3g___");
  969. subst.push_back(u"h");
  970. subst.push_back(u"1i_____");
  971. std::u16string original = u"$1a,$2b,$3c,$4d,$5e,$6f,$7g,$8h,$9i";
  972. std::u16string expected =
  973. u"9a____a,Bb,7c___c,dd,5e____e,Ff,3g___g,hh,1i_____i";
  974. EXPECT_EQ(expected, ReplaceStringPlaceholders(original, subst, nullptr));
  975. std::vector<size_t> offsets;
  976. EXPECT_EQ(expected, ReplaceStringPlaceholders(original, subst, &offsets));
  977. std::vector<size_t> expected_offsets = {0, 8, 11, 18, 21, 29, 32, 39, 42};
  978. EXPECT_EQ(offsets.size(), subst.size());
  979. EXPECT_EQ(expected_offsets, offsets);
  980. for (size_t i = 0; i < offsets.size(); i++) {
  981. EXPECT_EQ(expected.substr(expected_offsets[i], subst[i].length()),
  982. subst[i]);
  983. }
  984. }
  985. TEST(StringUtilTest, ReplaceStringPlaceholdersNetContractionWithExpansion) {
  986. // In this test, some of the substitutions are longer than the placeholders,
  987. // but overall the string gets smaller. Additionally, the placeholders appear
  988. // in a permuted order.
  989. std::vector<std::u16string> subst;
  990. subst.push_back(u"z");
  991. subst.push_back(u"y");
  992. subst.push_back(u"XYZW");
  993. subst.push_back(u"x");
  994. subst.push_back(u"w");
  995. std::u16string formatted =
  996. ReplaceStringPlaceholders(u"$3_$4$2$1$5", subst, nullptr);
  997. EXPECT_EQ(u"XYZW_xyzw", formatted);
  998. }
  999. TEST(StringUtilTest, ReplaceStringPlaceholdersOneDigit) {
  1000. std::vector<std::u16string> subst;
  1001. subst.push_back(u"1a");
  1002. std::u16string formatted =
  1003. ReplaceStringPlaceholders(u" $16 ", subst, nullptr);
  1004. EXPECT_EQ(u" 1a6 ", formatted);
  1005. }
  1006. TEST(StringUtilTest, ReplaceStringPlaceholdersInvalidPlaceholder) {
  1007. std::vector<std::u16string> subst;
  1008. subst.push_back(u"1a");
  1009. std::u16string formatted =
  1010. ReplaceStringPlaceholders(u"+$-+$A+$1+", subst, nullptr);
  1011. EXPECT_EQ(u"+++1a+", formatted);
  1012. }
  1013. TEST(StringUtilTest, StdStringReplaceStringPlaceholders) {
  1014. std::vector<std::string> subst;
  1015. subst.push_back("9a");
  1016. subst.push_back("8b");
  1017. subst.push_back("7c");
  1018. subst.push_back("6d");
  1019. subst.push_back("5e");
  1020. subst.push_back("4f");
  1021. subst.push_back("3g");
  1022. subst.push_back("2h");
  1023. subst.push_back("1i");
  1024. std::string formatted =
  1025. ReplaceStringPlaceholders(
  1026. "$1a,$2b,$3c,$4d,$5e,$6f,$7g,$8h,$9i", subst, nullptr);
  1027. EXPECT_EQ("9aa,8bb,7cc,6dd,5ee,4ff,3gg,2hh,1ii", formatted);
  1028. }
  1029. TEST(StringUtilTest, StdStringReplaceStringPlaceholdersMultipleMatches) {
  1030. std::vector<std::string> subst;
  1031. subst.push_back("4"); // Referenced twice.
  1032. subst.push_back("?"); // Unreferenced.
  1033. subst.push_back("!"); // Unreferenced.
  1034. subst.push_back("16"); // Referenced once.
  1035. std::string original = "$1 * $1 == $4";
  1036. std::string expected = "4 * 4 == 16";
  1037. EXPECT_EQ(expected, ReplaceStringPlaceholders(original, subst, nullptr));
  1038. std::vector<size_t> offsets;
  1039. EXPECT_EQ(expected, ReplaceStringPlaceholders(original, subst, &offsets));
  1040. std::vector<size_t> expected_offsets = {0, 4, 9};
  1041. EXPECT_EQ(expected_offsets, offsets);
  1042. }
  1043. TEST(StringUtilTest, ReplaceStringPlaceholdersConsecutiveDollarSigns) {
  1044. std::vector<std::string> subst;
  1045. subst.push_back("a");
  1046. subst.push_back("b");
  1047. subst.push_back("c");
  1048. EXPECT_EQ(ReplaceStringPlaceholders("$$1 $$$2 $$$$3", subst, nullptr),
  1049. "$1 $$2 $$$3");
  1050. }
  1051. TEST(StringUtilTest, LcpyTest) {
  1052. // Test the normal case where we fit in our buffer.
  1053. {
  1054. char dst[10];
  1055. wchar_t wdst[10];
  1056. EXPECT_EQ(7U, strlcpy(dst, "abcdefg", std::size(dst)));
  1057. EXPECT_EQ(0, memcmp(dst, "abcdefg", 8));
  1058. EXPECT_EQ(7U, wcslcpy(wdst, L"abcdefg", std::size(wdst)));
  1059. EXPECT_EQ(0, memcmp(wdst, L"abcdefg", sizeof(wchar_t) * 8));
  1060. }
  1061. // Test dst_size == 0, nothing should be written to |dst| and we should
  1062. // have the equivalent of strlen(src).
  1063. {
  1064. char dst[2] = {1, 2};
  1065. wchar_t wdst[2] = {1, 2};
  1066. EXPECT_EQ(7U, strlcpy(dst, "abcdefg", 0));
  1067. EXPECT_EQ(1, dst[0]);
  1068. EXPECT_EQ(2, dst[1]);
  1069. EXPECT_EQ(7U, wcslcpy(wdst, L"abcdefg", 0));
  1070. EXPECT_EQ(static_cast<wchar_t>(1), wdst[0]);
  1071. EXPECT_EQ(static_cast<wchar_t>(2), wdst[1]);
  1072. }
  1073. // Test the case were we _just_ competely fit including the null.
  1074. {
  1075. char dst[8];
  1076. wchar_t wdst[8];
  1077. EXPECT_EQ(7U, strlcpy(dst, "abcdefg", std::size(dst)));
  1078. EXPECT_EQ(0, memcmp(dst, "abcdefg", 8));
  1079. EXPECT_EQ(7U, wcslcpy(wdst, L"abcdefg", std::size(wdst)));
  1080. EXPECT_EQ(0, memcmp(wdst, L"abcdefg", sizeof(wchar_t) * 8));
  1081. }
  1082. // Test the case were we we are one smaller, so we can't fit the null.
  1083. {
  1084. char dst[7];
  1085. wchar_t wdst[7];
  1086. EXPECT_EQ(7U, strlcpy(dst, "abcdefg", std::size(dst)));
  1087. EXPECT_EQ(0, memcmp(dst, "abcdef", 7));
  1088. EXPECT_EQ(7U, wcslcpy(wdst, L"abcdefg", std::size(wdst)));
  1089. EXPECT_EQ(0, memcmp(wdst, L"abcdef", sizeof(wchar_t) * 7));
  1090. }
  1091. // Test the case were we are just too small.
  1092. {
  1093. char dst[3];
  1094. wchar_t wdst[3];
  1095. EXPECT_EQ(7U, strlcpy(dst, "abcdefg", std::size(dst)));
  1096. EXPECT_EQ(0, memcmp(dst, "ab", 3));
  1097. EXPECT_EQ(7U, wcslcpy(wdst, L"abcdefg", std::size(wdst)));
  1098. EXPECT_EQ(0, memcmp(wdst, L"ab", sizeof(wchar_t) * 3));
  1099. }
  1100. }
  1101. TEST(StringUtilTest, WprintfFormatPortabilityTest) {
  1102. static const struct {
  1103. const wchar_t* input;
  1104. bool portable;
  1105. } cases[] = {
  1106. { L"%ls", true },
  1107. { L"%s", false },
  1108. { L"%S", false },
  1109. { L"%lS", false },
  1110. { L"Hello, %s", false },
  1111. { L"%lc", true },
  1112. { L"%c", false },
  1113. { L"%C", false },
  1114. { L"%lC", false },
  1115. { L"%ls %s", false },
  1116. { L"%s %ls", false },
  1117. { L"%s %ls %s", false },
  1118. { L"%f", true },
  1119. { L"%f %F", false },
  1120. { L"%d %D", false },
  1121. { L"%o %O", false },
  1122. { L"%u %U", false },
  1123. { L"%f %d %o %u", true },
  1124. { L"%-8d (%02.1f%)", true },
  1125. { L"% 10s", false },
  1126. { L"% 10ls", true }
  1127. };
  1128. for (const auto& i : cases)
  1129. EXPECT_EQ(i.portable, IsWprintfFormatPortable(i.input));
  1130. }
  1131. TEST(StringUtilTest, MakeBasicStringPieceTest) {
  1132. constexpr char kFoo[] = "Foo";
  1133. static_assert(MakeStringPiece(kFoo, kFoo + 3) == kFoo, "");
  1134. static_assert(MakeStringPiece(kFoo, kFoo + 3).data() == kFoo, "");
  1135. static_assert(MakeStringPiece(kFoo, kFoo + 3).size() == 3, "");
  1136. static_assert(MakeStringPiece(kFoo + 3, kFoo + 3).empty(), "");
  1137. static_assert(MakeStringPiece(kFoo + 4, kFoo + 4).empty(), "");
  1138. std::string foo = kFoo;
  1139. EXPECT_EQ(MakeStringPiece(foo.begin(), foo.end()), foo);
  1140. EXPECT_EQ(MakeStringPiece(foo.begin(), foo.end()).data(), foo.data());
  1141. EXPECT_EQ(MakeStringPiece(foo.begin(), foo.end()).size(), foo.size());
  1142. EXPECT_TRUE(MakeStringPiece(foo.end(), foo.end()).empty());
  1143. constexpr char16_t kBar[] = u"Bar";
  1144. static_assert(MakeStringPiece16(kBar, kBar + 3) == kBar, "");
  1145. static_assert(MakeStringPiece16(kBar, kBar + 3).data() == kBar, "");
  1146. static_assert(MakeStringPiece16(kBar, kBar + 3).size() == 3, "");
  1147. static_assert(MakeStringPiece16(kBar + 3, kBar + 3).empty(), "");
  1148. static_assert(MakeStringPiece16(kBar + 4, kBar + 4).empty(), "");
  1149. std::u16string bar = kBar;
  1150. EXPECT_EQ(MakeStringPiece16(bar.begin(), bar.end()), bar);
  1151. EXPECT_EQ(MakeStringPiece16(bar.begin(), bar.end()).data(), bar.data());
  1152. EXPECT_EQ(MakeStringPiece16(bar.begin(), bar.end()).size(), bar.size());
  1153. EXPECT_TRUE(MakeStringPiece16(bar.end(), bar.end()).empty());
  1154. constexpr wchar_t kBaz[] = L"Baz";
  1155. static_assert(MakeWStringPiece(kBaz, kBaz + 3) == kBaz, "");
  1156. static_assert(MakeWStringPiece(kBaz, kBaz + 3).data() == kBaz, "");
  1157. static_assert(MakeWStringPiece(kBaz, kBaz + 3).size() == 3, "");
  1158. static_assert(MakeWStringPiece(kBaz + 3, kBaz + 3).empty(), "");
  1159. static_assert(MakeWStringPiece(kBaz + 4, kBaz + 4).empty(), "");
  1160. std::wstring baz = kBaz;
  1161. EXPECT_EQ(MakeWStringPiece(baz.begin(), baz.end()), baz);
  1162. EXPECT_EQ(MakeWStringPiece(baz.begin(), baz.end()).data(), baz.data());
  1163. EXPECT_EQ(MakeWStringPiece(baz.begin(), baz.end()).size(), baz.size());
  1164. EXPECT_TRUE(MakeWStringPiece(baz.end(), baz.end()).empty());
  1165. }
  1166. TEST(StringUtilTest, RemoveChars) {
  1167. const char kRemoveChars[] = "-/+*";
  1168. std::string input = "A-+bc/d!*";
  1169. EXPECT_TRUE(RemoveChars(input, kRemoveChars, &input));
  1170. EXPECT_EQ("Abcd!", input);
  1171. // No characters match kRemoveChars.
  1172. EXPECT_FALSE(RemoveChars(input, kRemoveChars, &input));
  1173. EXPECT_EQ("Abcd!", input);
  1174. // Empty string.
  1175. input.clear();
  1176. EXPECT_FALSE(RemoveChars(input, kRemoveChars, &input));
  1177. EXPECT_EQ(std::string(), input);
  1178. }
  1179. TEST(StringUtilTest, ReplaceChars) {
  1180. struct TestData {
  1181. const char* input;
  1182. const char* replace_chars;
  1183. const char* replace_with;
  1184. const char* output;
  1185. bool result;
  1186. } cases[] = {
  1187. {"", "", "", "", false},
  1188. {"t", "t", "t", "t", true},
  1189. {"a", "b", "c", "a", false},
  1190. {"b", "b", "c", "c", true},
  1191. {"bob", "b", "p", "pop", true},
  1192. {"bob", "o", "i", "bib", true},
  1193. {"test", "", "", "test", false},
  1194. {"test", "", "!", "test", false},
  1195. {"test", "z", "!", "test", false},
  1196. {"test", "e", "!", "t!st", true},
  1197. {"test", "e", "!?", "t!?st", true},
  1198. {"test", "ez", "!", "t!st", true},
  1199. {"test", "zed", "!?", "t!?st", true},
  1200. {"test", "t", "!?", "!?es!?", true},
  1201. {"test", "et", "!>", "!>!>s!>", true},
  1202. {"test", "zest", "!", "!!!!", true},
  1203. {"test", "szt", "!", "!e!!", true},
  1204. {"test", "t", "test", "testestest", true},
  1205. {"tetst", "t", "test", "testeteststest", true},
  1206. {"ttttttt", "t", "-", "-------", true},
  1207. {"aAaAaAAaAAa", "A", "", "aaaaa", true},
  1208. {"xxxxxxxxxx", "x", "", "", true},
  1209. {"xxxxxxxxxx", "x", "x", "xxxxxxxxxx", true},
  1210. {"xxxxxxxxxx", "x", "y-", "y-y-y-y-y-y-y-y-y-y-", true},
  1211. {"xxxxxxxxxx", "x", "xy", "xyxyxyxyxyxyxyxyxyxy", true},
  1212. {"xxxxxxxxxx", "x", "zyx", "zyxzyxzyxzyxzyxzyxzyxzyxzyxzyx", true},
  1213. {"xaxxaxxxaxxxax", "x", "xy", "xyaxyxyaxyxyxyaxyxyxyaxy", true},
  1214. {"-xaxxaxxxaxxxax-", "x", "xy", "-xyaxyxyaxyxyxyaxyxyxyaxy-", true},
  1215. };
  1216. for (const TestData& scenario : cases) {
  1217. // Test with separate output and input vars.
  1218. std::string output;
  1219. bool result = ReplaceChars(scenario.input, scenario.replace_chars,
  1220. scenario.replace_with, &output);
  1221. EXPECT_EQ(scenario.result, result) << scenario.input;
  1222. EXPECT_EQ(scenario.output, output);
  1223. }
  1224. for (const TestData& scenario : cases) {
  1225. // Test with an input/output var of limited capacity.
  1226. std::string input_output = scenario.input;
  1227. input_output.shrink_to_fit();
  1228. bool result = ReplaceChars(input_output, scenario.replace_chars,
  1229. scenario.replace_with, &input_output);
  1230. EXPECT_EQ(scenario.result, result) << scenario.input;
  1231. EXPECT_EQ(scenario.output, input_output);
  1232. }
  1233. for (const TestData& scenario : cases) {
  1234. // Test with an input/output var of ample capacity; should
  1235. // not realloc.
  1236. std::string input_output = scenario.input;
  1237. input_output.reserve(strlen(scenario.output) * 2);
  1238. const void* original_buffer = input_output.data();
  1239. bool result = ReplaceChars(input_output, scenario.replace_chars,
  1240. scenario.replace_with, &input_output);
  1241. EXPECT_EQ(scenario.result, result) << scenario.input;
  1242. EXPECT_EQ(scenario.output, input_output);
  1243. EXPECT_EQ(original_buffer, input_output.data());
  1244. }
  1245. }
  1246. TEST(StringUtilTest, ContainsOnlyChars) {
  1247. // Providing an empty list of characters should return false but for the empty
  1248. // string.
  1249. EXPECT_TRUE(ContainsOnlyChars(std::string(), std::string()));
  1250. EXPECT_FALSE(ContainsOnlyChars("Hello", std::string()));
  1251. EXPECT_TRUE(ContainsOnlyChars(std::string(), "1234"));
  1252. EXPECT_TRUE(ContainsOnlyChars("1", "1234"));
  1253. EXPECT_TRUE(ContainsOnlyChars("1", "4321"));
  1254. EXPECT_TRUE(ContainsOnlyChars("123", "4321"));
  1255. EXPECT_FALSE(ContainsOnlyChars("123a", "4321"));
  1256. EXPECT_TRUE(ContainsOnlyChars(std::string(), kWhitespaceASCII));
  1257. EXPECT_TRUE(ContainsOnlyChars(" ", kWhitespaceASCII));
  1258. EXPECT_TRUE(ContainsOnlyChars("\t", kWhitespaceASCII));
  1259. EXPECT_TRUE(ContainsOnlyChars("\t \r \n ", kWhitespaceASCII));
  1260. EXPECT_FALSE(ContainsOnlyChars("a", kWhitespaceASCII));
  1261. EXPECT_FALSE(ContainsOnlyChars("\thello\r \n ", kWhitespaceASCII));
  1262. EXPECT_TRUE(ContainsOnlyChars(std::u16string(), kWhitespaceUTF16));
  1263. EXPECT_TRUE(ContainsOnlyChars(u" ", kWhitespaceUTF16));
  1264. EXPECT_TRUE(ContainsOnlyChars(u"\t", kWhitespaceUTF16));
  1265. EXPECT_TRUE(ContainsOnlyChars(u"\t \r \n ", kWhitespaceUTF16));
  1266. EXPECT_FALSE(ContainsOnlyChars(u"a", kWhitespaceUTF16));
  1267. EXPECT_FALSE(ContainsOnlyChars(u"\thello\r \n ", kWhitespaceUTF16));
  1268. }
  1269. TEST(StringUtilTest, CompareCaseInsensitiveASCII) {
  1270. EXPECT_EQ(0, CompareCaseInsensitiveASCII("", ""));
  1271. EXPECT_EQ(0, CompareCaseInsensitiveASCII("Asdf", "aSDf"));
  1272. // Differing lengths.
  1273. EXPECT_EQ(-1, CompareCaseInsensitiveASCII("Asdf", "aSDfA"));
  1274. EXPECT_EQ(1, CompareCaseInsensitiveASCII("AsdfA", "aSDf"));
  1275. // Differing values.
  1276. EXPECT_EQ(-1, CompareCaseInsensitiveASCII("AsdfA", "aSDfb"));
  1277. EXPECT_EQ(1, CompareCaseInsensitiveASCII("Asdfb", "aSDfA"));
  1278. }
  1279. TEST(StringUtilTest, EqualsCaseInsensitiveASCII) {
  1280. EXPECT_TRUE(EqualsCaseInsensitiveASCII("", ""));
  1281. EXPECT_TRUE(EqualsCaseInsensitiveASCII("Asdf", "aSDF"));
  1282. EXPECT_FALSE(EqualsCaseInsensitiveASCII("bsdf", "aSDF"));
  1283. EXPECT_FALSE(EqualsCaseInsensitiveASCII("Asdf", "aSDFz"));
  1284. EXPECT_TRUE(EqualsCaseInsensitiveASCII(u"", u""));
  1285. EXPECT_TRUE(EqualsCaseInsensitiveASCII(u"Asdf", u"aSDF"));
  1286. EXPECT_FALSE(EqualsCaseInsensitiveASCII(u"bsdf", u"aSDF"));
  1287. EXPECT_FALSE(EqualsCaseInsensitiveASCII(u"Asdf", u"aSDFz"));
  1288. EXPECT_TRUE(EqualsCaseInsensitiveASCII(u"", ""));
  1289. EXPECT_TRUE(EqualsCaseInsensitiveASCII(u"Asdf", "aSDF"));
  1290. EXPECT_FALSE(EqualsCaseInsensitiveASCII(u"bsdf", "aSDF"));
  1291. EXPECT_FALSE(EqualsCaseInsensitiveASCII(u"Asdf", "aSDFz"));
  1292. EXPECT_TRUE(EqualsCaseInsensitiveASCII("", u""));
  1293. EXPECT_TRUE(EqualsCaseInsensitiveASCII("Asdf", u"aSDF"));
  1294. EXPECT_FALSE(EqualsCaseInsensitiveASCII("bsdf", u"aSDF"));
  1295. EXPECT_FALSE(EqualsCaseInsensitiveASCII("Asdf", u"aSDFz"));
  1296. // The `WStringPiece` overloads are only defined on Windows.
  1297. #if BUILDFLAG(IS_WIN)
  1298. EXPECT_TRUE(EqualsCaseInsensitiveASCII(L"", L""));
  1299. EXPECT_TRUE(EqualsCaseInsensitiveASCII(L"Asdf", L"aSDF"));
  1300. EXPECT_FALSE(EqualsCaseInsensitiveASCII(L"bsdf", L"aSDF"));
  1301. EXPECT_FALSE(EqualsCaseInsensitiveASCII(L"Asdf", L"aSDFz"));
  1302. EXPECT_TRUE(EqualsCaseInsensitiveASCII(L"", ""));
  1303. EXPECT_TRUE(EqualsCaseInsensitiveASCII(L"Asdf", "aSDF"));
  1304. EXPECT_FALSE(EqualsCaseInsensitiveASCII(L"bsdf", "aSDF"));
  1305. EXPECT_FALSE(EqualsCaseInsensitiveASCII(L"Asdf", "aSDFz"));
  1306. EXPECT_TRUE(EqualsCaseInsensitiveASCII("", L""));
  1307. EXPECT_TRUE(EqualsCaseInsensitiveASCII("Asdf", L"aSDF"));
  1308. EXPECT_FALSE(EqualsCaseInsensitiveASCII("bsdf", L"aSDF"));
  1309. EXPECT_FALSE(EqualsCaseInsensitiveASCII("Asdf", L"aSDFz"));
  1310. #endif
  1311. }
  1312. TEST(StringUtilTest, IsUnicodeWhitespace) {
  1313. // NOT unicode white space.
  1314. EXPECT_FALSE(IsUnicodeWhitespace(L'\0'));
  1315. EXPECT_FALSE(IsUnicodeWhitespace(L'A'));
  1316. EXPECT_FALSE(IsUnicodeWhitespace(L'0'));
  1317. EXPECT_FALSE(IsUnicodeWhitespace(L'.'));
  1318. EXPECT_FALSE(IsUnicodeWhitespace(L';'));
  1319. EXPECT_FALSE(IsUnicodeWhitespace(L'\x4100'));
  1320. // Actual unicode whitespace.
  1321. EXPECT_TRUE(IsUnicodeWhitespace(L' '));
  1322. EXPECT_TRUE(IsUnicodeWhitespace(L'\xa0'));
  1323. EXPECT_TRUE(IsUnicodeWhitespace(L'\x3000'));
  1324. EXPECT_TRUE(IsUnicodeWhitespace(L'\t'));
  1325. EXPECT_TRUE(IsUnicodeWhitespace(L'\r'));
  1326. EXPECT_TRUE(IsUnicodeWhitespace(L'\v'));
  1327. EXPECT_TRUE(IsUnicodeWhitespace(L'\f'));
  1328. EXPECT_TRUE(IsUnicodeWhitespace(L'\n'));
  1329. }
  1330. class WriteIntoTest : public testing::Test {
  1331. protected:
  1332. static void WritesCorrectly(size_t num_chars) {
  1333. std::string buffer;
  1334. char kOriginal[] = "supercali";
  1335. strncpy(WriteInto(&buffer, num_chars + 1), kOriginal, num_chars);
  1336. // Using std::string(buffer.c_str()) instead of |buffer| truncates the
  1337. // string at the first \0.
  1338. EXPECT_EQ(
  1339. std::string(kOriginal, std::min(num_chars, std::size(kOriginal) - 1)),
  1340. std::string(buffer.c_str()));
  1341. EXPECT_EQ(num_chars, buffer.size());
  1342. }
  1343. };
  1344. TEST_F(WriteIntoTest, WriteInto) {
  1345. // Validate that WriteInto reserves enough space and
  1346. // sizes a string correctly.
  1347. WritesCorrectly(1);
  1348. WritesCorrectly(2);
  1349. WritesCorrectly(5000);
  1350. // Validate that WriteInto handles 0-length strings
  1351. std::string empty;
  1352. const char kOriginal[] = "original";
  1353. strncpy(WriteInto(&empty, 1), kOriginal, 0);
  1354. EXPECT_STREQ("", empty.c_str());
  1355. EXPECT_EQ(0u, empty.size());
  1356. // Validate that WriteInto doesn't modify other strings
  1357. // when using a Copy-on-Write implementation.
  1358. const char kLive[] = "live";
  1359. const char kDead[] = "dead";
  1360. const std::string live = kLive;
  1361. std::string dead = live;
  1362. strncpy(WriteInto(&dead, 5), kDead, 4);
  1363. EXPECT_EQ(kDead, dead);
  1364. EXPECT_EQ(4u, dead.size());
  1365. EXPECT_EQ(kLive, live);
  1366. EXPECT_EQ(4u, live.size());
  1367. }
  1368. } // namespace base